Docs: answer collector record and consent #6
Loading…
Reference in a new issue
No description provided.
Delete branch "heimdall/answer-collector-consent"
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?
Docs-only. Specifies the answer record, version-scoped tallies, scope semantics, Matrix sender to member id, Eureka's Matrix shape, Matrix limits and respondent-facing revoke. Not merged; awaiting review.
🤖 Generated with Claude Code
Answers to Libby's nine (CultLib #12,
packages/heimdall-consent/README.md). Doc line numbers aredocs/answer-collector-consent.mdatd836f29; rulings are committed in2364979(docs only). Thanks for the transcription; the typed shape is right.origin_server_ts. New "Representation" section.terms_versionis a string (L53),sample_idversion a positive integer (L64),notice_versionan integer (L42). Ruled: ids are non-empty opaque strings,event_idverbatim, versions unsigned 32-bit.text" (L136-139) and nothing more. Ruled, new "Tombstone" section: the tombstone is the exitedAnswerrecord,text_hashis a new table row (32 bytes). Function: HMAC-SHA-256, raw 32 bytes, untruncated. Message:heimdall.tombstone.v1U+001Fevent_idU+001Ftext(UTF-8, unnormalised); the event id makes equal texts hash differently. Salt: 32 CSPRNG bytes, one per member, generated and held by the member-side service (the one that maps Matrix sender tomember_id). It is never given to the collector, researchers, exports or logs, so the collector cannot compute or check a hash itself: on seeing a redaction it sendsevent_idandtextto that service, writes the returned hash, setsexited, erasestext. If the service is down, text stays and the run retries. Destroying a member's salt makes their tombstones unlinkable to any text. Your crate rightly never computes it.origin_server_ts; if that can't be established the reply has none. A changed version needs a fresh first reply under it (L32-34, L47 key includes version).MemberTerms. Doc puts the fields on the member (L51-56). Ruled: they belong to the Heimdall member record;MemberTermsis only the typed shape of that pair, not a second store, and the collector doesn't hold it.scopemust betrainand equal the answer'sscope, withaccepted_at <= received_at. Doc amended. Train stays declared per room by notice only (L28-30).Unasked but relevant: no reward sound or reinforcement on consent controls is already L162-164. Nothing merged.
Two rulings from Libby's CultLib #12 follow-up questions, committed in
4e99bfa(docs only,docs/answer-collector-consent.md):text, and the collector rejects an empty one. Empty text is valid only on a revoked answer, where redaction clears the text and leaves the hash-only tombstone.received_at.received_atis assigned by the collector. Two replies to one key that tie on it break byevent_idcompared bytewise; the greaterevent_idwins as the later reply.Note: ruling 2 changes the
received_atfield, which previously said it was the reply'sorigin_server_ts. I changed that row and the Matrix receipt bullet to match. The notice version is still pinned at the reply'sorigin_server_ts, unchanged.Rebased on main (already current), pushed without force, nothing merged.
Leading-zero versions are refused, not normalised; one version, one key. A room's notice is the org.gamecult.notice state event {version, scope} under the room's power levels; a pinned message is not accepted. Absent or malformed means no train line and the narrowest scope. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>Pushed
cafdc52(docs only, no force): leading-zero versions refused (one version, one key); a room notice is the org.gamecult.notice state event, empty state_key, content {version, scope}, set under the room power levels; a pinned message is not accepted; absent or malformed means no train line and narrowest scope.Version rule folded into docs/answer-collector-consent.md in
d6a8d42(one rule under Representation; replaces the leading-zero text fromcafdc52). Docs only.