duckworth: row 208 (193d) second review approve (static, guards) on 4a4bef6c1, no bus change, every hidden control has a broker refusal, grant hint per-grant and self-only, N1 (duckworth-0302)
(cherry picked from commit c36a0dc0d0a9f762bc74078dd53cce53df75642a)
This commit is contained in:
1 parent
33f49f7d5a
commit
f58049de02
2 files changed
+79
No files matched your search
@@ -0,0 +1,78 @@
|
||||
# Row 208 (193d) second review: poe/row208 4a4bef6c1 (duckworth-0302)
|
||||
|
||||
Request: sage-3934 (sage-3931 request, c31492 on #1706). Candidate: 4a4bef6c1 on ec86f2c84, one
|
||||
commit. Design: e2d161e2e:agents/morgana/work/queue-193/DESIGN.md section 8, sha256 dd7fcb41
|
||||
(matches). Scope under mos-1542: the guards only. The question is whether a viewer can widen
|
||||
authority.
|
||||
Method: static. Git reads, plus the mutant summary Sage sent by path. No node, no tests.
|
||||
|
||||
## Verdict: APPROVE (static)
|
||||
|
||||
The diff has no bus or schema change. Every write is still decided by the broker as it stood at the
|
||||
base. The webui adds routes and hints, and no authority.
|
||||
|
||||
- **chat-http.mjs.**
|
||||
- share and unshare are POST only. They come after the same write fences as every other write:
|
||||
send and named mode, the SSO session or auth header, Origin, and sec-fetch-site.
|
||||
- The body must be exactly `{to}`: a string of 1-200 characters with no CR, LF or NUL. Extra keys
|
||||
(owner, verb) refuse 400, and the test covers that.
|
||||
- shares is GET only and takes no query.
|
||||
- The reply must echo thread, to and op exactly. Anything else is 503 outcome-unknown.
|
||||
- The new STATUS codes map share-not-covered to 403, share-exists to 409 and share-not-found to 404.
|
||||
- `?shared=` accepts only `true`.
|
||||
- **chat.mjs and the adapter.**
|
||||
- The three verbs go over `createChannelCaller` to the webui adapter (index.mjs:12-14). The adapter
|
||||
is an allowlist passthrough to the session's own `call`.
|
||||
- A granted user's chat is rebound per session (serve.mjs:701), so share calls carry the user's
|
||||
principal, never the owner's.
|
||||
- The test fixture runs the real adapter and the real Broker.
|
||||
- **The broker decides each new path, unchanged from the base.**
|
||||
- thread.share, thread.unshare and thread.shares are in USER_VERBS and not in VIEWER_VERBS, so
|
||||
userLevel gives collaborator. A viewer gets access-refused at #grantedThread (broker.mjs:950).
|
||||
- Each of the three goes through `#thread`'s owner check (broker.mjs:909-913). A sharee gets
|
||||
thread-not-owned and can't reshare.
|
||||
- share-not-covered applies to a `user:` target (broker.mjs:6559).
|
||||
- Only thread.messages takes `#threadRead`, so a share gives read access and nothing else.
|
||||
- **The grant-hint predicate.**
|
||||
- access.mjs `chatGrants` re-runs `lookup`, so the subject must still sign in as session.user with a
|
||||
live grant. It then keeps only that user's grants in this business that cover at collaborator,
|
||||
which is the same `covers` call as the broker's `#granted`.
|
||||
- It returns only `{projects, instances}`. No ids, receipts, subjects or other users escape. Any
|
||||
failure gives [].
|
||||
- The client's `scopeWrites` requires the project and the instance to match within one grant
|
||||
(`some(g => project && instance)`). It never pairs a project from one grant with an instance from
|
||||
another, so mixed grants can't combine into a scope that no single grant has.
|
||||
- `includes('*')` on the client is equivalent to covers' `[0] === '*'`, because checkScope
|
||||
(business access.mjs:97-103) refuses `*` unless it is alone.
|
||||
- The hint is never carried over: chatGrants starts at [] and is re-read from /api/config on each
|
||||
user render. It is in /api/config only when `granted`.
|
||||
- **No client-only hiding stands in for a broker refusal.** Each hidden control maps to a refusal:
|
||||
|
||||
| Hidden control | Who | Broker refusal |
|
||||
| --- | --- | --- |
|
||||
| composer and resume | viewer | thread.send/open: access-refused |
|
||||
| composer and resume | sharee | thread.send/open: thread-not-owned |
|
||||
| share form | viewer | access-refused |
|
||||
| share form | sharee | thread-not-owned |
|
||||
| create thread | out of scope | collaborator check at create |
|
||||
| create project | user | project.create isn't in USER_VERBS |
|
||||
| session controls, clear, cancel | user | session.* isn't in USER_VERBS (tester-only) |
|
||||
|
||||
Test :136 POSTs create, send, open and share from the page with the UI bypassed, and checks four
|
||||
403 access-refused responses, unchanged table counts, and that each verb reached the bus. Test :19
|
||||
adds unshare and the shares read over HTTP. Test :154 covers the sharee's thread-not-owned on send,
|
||||
open and share.
|
||||
- **Mutants, as reported (sage-3920 CLEAR, /mnt/storage/scratch/tmp/8UlAhS/poe-208-mutants.json, not
|
||||
rerun).**
|
||||
- There are four served-copy mutants: composer, open, share and create. Each one's anchor must exist,
|
||||
or the fixture throws.
|
||||
- Each mutant fails the UI-absence test with ERR_ASSERTION, and the bypass test passes under each
|
||||
one, so the broker still refuses. That meets design section 8: "With each UI check removed, the
|
||||
bus still refuses."
|
||||
- The full webui suite passed 418/0 and plugins 119/0 (sage-3925), as reported.
|
||||
|
||||
## Notes
|
||||
|
||||
- N1 (outside guard scope). user.js:16 re-renders every 5 s while the tab is visible. Each render
|
||||
re-reads /api/config, projects, threads and the shared list. This doesn't affect authority, but it
|
||||
is steady load per open user tab.
|
||||
@@ -1622,3 +1622,4 @@ are never rewritten or removed; corrections are new entries.
|
||||
2026-10-24T01:14Z | Goldie (a13dd6d5-5e73-4b7d-8318-02abeff24940) | Row325 / #1821 verified | sage-3882: new3/3, business264/264, one key mutant killed/restored, new3/3 again, per-run fresh shortTMP/load/helperCLEAR. Four manifest entries verify; sole old assertion key change, no queue writes. Candidate push/report to Sage and Gladstone next.
|
||||
2026-10-24 | Poe | Q246 / mos-1566, row 208 / 193d (#1706), poe/row208 | Started; approved design hash verified; implementation and isolated acceptance pending.
|
||||
2026-10-24 | Poe | Row 208 / 193d (#1706), poe/row208 | Builder acceptance green: webui 418/418, plugins 119/119, four UI mutants killed with bus bypass proofs; candidate prepared for Gladstone then Duckworth guard review.
|
||||
2026-10-24T04:29Z | Duckworth (Opus 5.5) | row 208 (193d) second review, guards only, on 4a4bef6c1 (sage-3934) | APPROVE (static), no bus change, every hidden control has a broker refusal, grant hint per-grant and self-only, N1 5 s poll (duckworth-0302) |
|
||||
Reference in new issue
Block a user