morgana: row 275 r2 (mos-1311): downgraded viewer keeps send and open refusals with nothing stored in the R3 test; BUILD.md lists each changed assertion, old and new, with design 4.3 lines

This commit is contained in:
jason.woltje committed 2026-10-22 11:45:25 -05:00
1 parent 5f77489550
commit 4d2888471b
2 files changed
+22 -7

No files matched your search

+15 -6
View File
@@ -33,15 +33,24 @@ Not in this row: the share verbs, `thread.list {shared: true}` and `#readable`'s
the revocation timer, `access.reload` and the level-loss test (FED R4, which mutant 5 moved to). FED R4 has
not landed; this row checks the level per request only, which is what R3 already reads per request.
## Existing test changes (flag for review)
## Existing test changes (mos-1311 ruling)
`packages/bus/tests/user-principal.test.mjs` (FED R3) asserted a viewer is refused. Design 4.3 reverses that:
Mos approved both changes in mos-1311 (16:44:56Z), under mos-1272. They follow row 193 DESIGN r5
(e2d161e2e, approved by Duckworth) section 4.3: the thread.list row at DESIGN.md:125 ("own threads still
covered (from an earlier collaborator grant)") and note 2 at :139 ("A viewer can still read its own
threads when a collaborator grant is lowered to viewer, but can't send or open them"). Condition 3: Duckworth
confirms in review that both match section 4.3.
- line 86 test: the `viewer level` case moves from the refused list to a bind that succeeds; title now
"refuses one with no live grant".
- line 310: a grant lowered to viewer now answers `thread.list` (was `access-revoked`).
- header comment updated to match.
All in `packages/bus/tests/user-principal.test.mjs` (FED R3, row 274):
| Test | Assertion | Old expectation | New expectation | Design line |
|---|---|---|---|---|
| "R3: bindUser binds a granted user and refuses one with no live grant" (title was "...no live collaborator grant") | `bindUser` with `grant({ level: 'viewer' })` | refused `access-revoked` (case `'viewer level'` in the refused list) | binds: `assert.ok(user('alice'), 'viewer level')`; the case leaves the refused list | :125 viewer column; 4.3 viewer verbs need a bound viewer |
| "R3: a removed or expired grant refuses the next request access-revoked..." | `thread.list` after `level: 'viewer'` ('downgraded') | `access-revoked` | `null` (answers) | :125 and :139 |
| same test, added (mos-1311 condition 1) | `thread.send` and `thread.open` on A after the downgrade | (not asserted) | each `access-refused`; `messages` and `thread_opens` counts unchanged | :139 "can't send or open them" |
The header comment of the file is updated to say a viewer grant binds. Every other R3 refusal (no grant,
another user, another business, expired, unreadable file, no file, removed, file refused) is unchanged.
No other test names a viewer grant on the bus (git grep for `level: 'viewer'` outside packages/business).
## Tests, packages/bus/tests/viewer.test.mjs (new)
+7 -1
View File
@@ -300,7 +300,7 @@ test('R3: a user thread run cannot message the owner, while its uncited gated ra
});
test('R3: a removed or expired grant refuses the next request access-revoked, and the file is read per request', (t) => {
const { call, code, access } = granted(t);
const { call, code, access, store, A } = granted(t);
const reads = access.reads;
call('alice', 'thread.list');
call('alice', 'project.list');
@@ -313,6 +313,12 @@ test('R3: a removed or expired grant refuses the next request access-revoked, an
// Row 275 (193b1b, design 4.3): a grant lowered to viewer still reads the user's own threads.
access.doc.grants = kept.map((g) => ({ ...g, level: 'viewer' }));
assert.equal(code('alice', 'thread.list'), null, 'downgraded');
// mos-1311 condition 1: the downgraded viewer still can't send or open, and nothing is stored.
const stored = () => ['messages', 'thread_opens'].map((x) => store.get(`SELECT count(*) n FROM ${x}`).n);
const before = stored();
assert.equal(code('alice', 'thread.send', { thread: A, body: 'still mine?' }), 'access-refused', 'downgraded send');
assert.equal(code('alice', 'thread.open', { thread: A }), 'access-refused', 'downgraded open');
assert.deepEqual(stored(), before, 'downgraded: nothing stored');
access.fail = true;
access.doc.grants = kept;
assert.equal(code('alice', 'thread.list'), 'access-revoked', 'file refused');