5.8 KiB
Row 205a (193b1a, #1703): the trail and replies message filter
Design: DESIGN.md d2 in this directory, with rulings in section 7 (sage-2288). Base: refactor 02da6a2ae. No schema
change. Nothing has run yet: every test run waits for Sage's CLEAR.
Changes
packages/bus/src/broker.mjs:
#hiddenMessage(s, id): the message's thread (message_threadsjoined tothreads) is owned by auser:other than#owner(s), and#readable(s, t)is false. A message with no thread, or in the business human's or the tester's thread, is never hidden. A reader session owns nothing, so every user thread is hidden from it. The tester reads through its reader view, and#ownerstill givestester.#readable(s, t)returns false. Rule 1 (a share in force) can't hold before 193b2's schema 3j, so nobody reads another's thread. 193b2 adds the share rule and rules 2-4 here.#trail: a hidden subject returns[]before anything is read, exactly as an unknown id does (ruling 3). After the rows are collected, it drops hiddenmessagesrows,deliveriesrows of a hidden message, andeventsrows whose subject is a hidden message. Decisions, decision events, task snapshots, run events and claims stay.replies: a hidden id failsmessage-not-found, as an unknown id does. Hidden replies are left out in SQL (NOT EXISTSa thread whose owner starts withuser:and isn't the caller), so theREPLIESlimit counts only visible rows.- The SQL clause doesn't call
#readable. That is exact while#readableis false. 193b2 must add the share exception to the clause and to#readabletogether.
- The SQL clause doesn't call
packages/bus/tests/message-filter.test.mjs (new). It writes a user:alice thread and its messages
straight to the store, as R3's thread.send and the run's to: 'user' reply will write them, because nothing
makes a user session before R3.
trailon a hidden id equalstrailon an unknown id, byte for byte, for the owner, a reader and the tester.replieson a hidden id equalsreplieson an unknown id (code and message), for all three.trailon a user-thread run's decision shows the decision and the owner's message, and drops the user thread message, its delivery and its event.replieswithREPLIEShidden replies ahead of a visible one returns the visible one.- Messages in the business human's and the tester's threads stay visible on both verbs (row 177 control).
- The governance pin, one assertion per item in the user sentence: inbox entry, claim, task, project file and
the closed decision in
decisions {list: 'recent'}show to the owner.trailandreplieshide the user message, and the decision's trail carries no user body.
Mutants (each must fail its named test in message-filter.test.mjs)
| Mutant | Edit | Named test |
|---|---|---|
| M1 | #readable returns true |
governance pin: the owner sees decisions, inbox entries, claims, tasks and project files, but not the user messages |
| M11 | the trail drop loop iterates nothing | trail on a decision keeps the decision and drops the user thread messages, their deliveries and their events |
| M12 | the replies NOT EXISTS clause removed |
replies leaves out other users thread messages and still fills a page |
| M13 | trail fails message-not-found for a hidden subject |
trail on a hidden message id answers exactly as on an unknown id, for the owner, a reader and the tester |
| M14 | replies returns [] for a hidden id |
replies on a hidden message id answers exactly as on an unknown id, for the owner, a reader and the tester |
Gate
The kit is /mnt/storage/scratch/morgana-r205 (slot205.sh, mutate.py, busy.sh), run as
bash busy.sh && CAND=<sha> bash slot205.sh on Sage's CLEAR. It runs these files whole:
- message-filter;
- the bus files that call trail or replies: replies, tester, tester-threads, tester-writes, broker, decisions, decision-close, end-launch and task-read.
Then it runs the bus suite, then M1 and M11-M14, each on its named test and restored after each. It uses umask
022 and TMPDIR from mktemp -d /mnt/storage/scratch/tmp/g205XXXX. It refuses unless HEAD is the candidate
and the tree is clean, and it stops at the first unexpected failure (sage-2371).
Sage's gate adds every scripts/test-*.sh. The webui tests that read trail or replies run there.
Static check: node --check on broker.mjs and the new test, run from /. Both parse. All five mutant anchors
match exactly once.
r2 (after the 742cba805 slot, failure 1 of the window, sage-2428)
slot205 on 742cba805 stopped red in message-filter, 4 pass and 2 fail. Both fixes are in the test only.
broker.mjs is unchanged (sage-2430).
- "trail on a decision ..." (:124, its event shows).
#trailreaches events on a decision trail bysubject= the decision orbody.$.decision= the decision.put()wrote every event body as{}, so the shown message's event was out of reach. That also made the "no hidden event" check (:127) vacuous: the hidden event was never collected, so dropping it proved nothing. Fix:put()writes{decision}as the event body when the message has a decision. Both events are now collected; the filter keeps one and drops the other. - Governance pin, claims item (:175). A thread run's
role.claimwritesthread_claimsonly and returns (broker.mjs:2682).agents(:3309) readsrole_claimsonly. No owner verb shows a thread claim. The gap predates 205. Ruling sage-2430, option (a): the pin checks throughthreadsState(the launcher view) that the claim is recorded with holderassistant-runand isn't filtered.agentsis unchanged in 205. Follow-up: Sage adds a row for an owner-visible thread-claim read. Like the filter, it lands before any user thread goes live, since PRD :1084 and the FED R6 sentence promise that the owner sees claims.
M1 still fails the pin: with #readable true, trail on the user message returns rows instead of [].