Files

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_threads joined to threads) is owned by a user: 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 #owner still gives tester.
  • #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 hidden messages rows, deliveries rows of a hidden message, and events rows whose subject is a hidden message. Decisions, decision events, task snapshots, run events and claims stay.
  • replies: a hidden id fails message-not-found, as an unknown id does. Hidden replies are left out in SQL (NOT EXISTS a thread whose owner starts with user: and isn't the caller), so the REPLIES limit counts only visible rows.
    • The SQL clause doesn't call #readable. That is exact while #readable is false. 193b2 must add the share exception to the clause and to #readable together.

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.

  • trail on a hidden id equals trail on an unknown id, byte for byte, for the owner, a reader and the tester.
  • replies on a hidden id equals replies on an unknown id (code and message), for all three.
  • trail on 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.
  • replies with REPLIES hidden 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. trail and replies hide 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). #trail reaches events on a decision trail by subject = the decision or body.$.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.claim writes thread_claims only and returns (broker.mjs:2682). agents (:3309) reads role_claims only. No owner verb shows a thread claim. The gap predates 205. Ruling sage-2430, option (a): the pin checks through threadsState (the launcher view) that the claim is recorded with holder assistant-run and isn't filtered. agents is 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 [].