Loading…
Reference in a new issue
No description provided.
Delete branch "build/lane7-p3-safety"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
This is the server side of Table rules & safety: lines, veils, and anonymous suggestions and concerns. It builds the survey's recommended answers T3(a), T4(a) and T11(a) provisionally; the owner answers them in the morning. Each answer lives in one named place, listed below.
The model (migration
7e5afe7a1b2cond4e6f8a0b2c3)safety_entries: lines and veils, with sort order and soft delete for Undo.safety_submissions:id, campaign_id, kind (line|veil|unsure|concern), text, session_id, submitted_on DATE. No user column and no timestamp.ck_notifications_kindgainssafety_waiting, which is GM-only, sent once per unread, and marked read when the queue empties.The API (under
/api/campaigns/{cid}/safety)GETfor any member; the waiting queue is null for players.GET /safety/waitingreturns{waiting}, GM-only.POST /safety/submissions, any member. It returns only{"sent": true}. It's rate-limited, and asession_idis allowed only on a concern.acceptturns a submission into an entry and deletes it;DELETEdismisses it. There's no expiry timer (T11).Anonymity, proven by tests
notifynever gets anactor_id.user_idcontext, so no log record carries the sender. The survey missed this leak.access_log offanderror_log /dev/nullfor that path.docs/OPERATIONS.mdhas nginx and Caddy examples and says Traefik can't filter by path.nginx -t; nginx in front of a dummy backend (the POST wasn't logged, a GET was); and real uvicorn.Tests
test_safety.py(41),test_safety_anonymity.py(16) andtest_safety_migration.py(7).🤖 Generated with Claude Code
Lane 7, server PR 3. A campaign's lines and veils, read by everyone and written by its GMs (with Remove and its undo), and one anonymous queue any member can send a suggestion, a "not sure" or a flagged concern to. Anonymity is held by the shape, not by care: - safety_submissions has no user column and no timestamp: only the day (in the campaign's timezone, T3), ordered by random id within it; - the submitting request clears the log context's user_id, and the service that writes the row is never given the sender; - its path is dropped from uvicorn's access log and slowapi's rate-limit warning (logging_config.UNLOGGED_PATHS) and has access_log/error_log off in the frontend nginx; OPERATIONS.md tells operators to do the same; - safety_waiting goes to every GM with no actor, and says nothing of what was sent; the response is {"sent": true} and nothing else. test_safety_anonymity proves each (schema, a whole-database trace scan, notify's arguments, in-request log records with a control, uvicorn and slowapi filters with a control, nginx config). T4(a): the bell is told at once, and GET .../safety/waiting is the bare count for Table mode. T11(a): nothing expires a submission. Export (schema 12) carries table_rules and never the queue; import restores them. Migration 7e5afe7a1b2c on d4e6f8a0b2c3 (#828); the one-head pin moves with it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>