You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
anonymous write doors: an authorization-adjacent gap when a guest-writable object declares a file field (detail withheld pending measurement) #25694
Filing gate ①, the "may leak data" exception, on the maintainer's direct word (reach is measured first, not before filing). Found by the os-dev of the folded #25622 + #25572 dispatch (PR #25682), from source reading only, not measured. Filed by domain:server seat 2 (seat post #20966) · sunhaolin · session session_01JVTd3PprStGa26aez5omLB. ⛔ Not a claim. Domain, grade and route are triage's.
The maintainer, in this seat's session, choosing among the seat's options for this finding: 「立卡,先实测再修(推荐)」 (file a card; measure first, then fix).
Disclosure: the mechanism and the path are withheld from every public surface under the security-family discipline. The seat holds them and has handed them to the maintainer in the seat's session; the dev who takes this card gets them from the seat.
What can be said: PR #25682 makes the anonymous public-form submit door (ADR-0138 D2 class 1) carry no file, under ruling C. This card is ruling C's rule at ADR-0138 D2's other anonymous write classes. Reach needs a deployment grant (the default empty state denies); the first step is a measurement.
Business reason: ruling C's rule, an anonymous submission carries no file, should hold at every anonymous write door, not only at the form door; a deployment that opens a guest write should not reopen what C closed.
Reader who acts: after triage, the domain:server lane (the anonymous door classes of ADR-0138 D2 and the file-reference lifecycle), measurement first.
Dedupe: the titles of every objectstack-ai/objectstack issue updated since 2026-10-10, open and closed (1,229 read), matched on claim|copy-on|file id|download|unowned|orphan|sys_file|file reference|guest.*file|anonymous.*file|storage.*(auth|scope)|file.*organi. 21 title hits, none of them this gap (the nearest are #25572 and #25650, ruling C’s two halves, and #23306, a closed storage verb). New.
⛔ Not a claim, ⛔ not a dispatch.
⛔ Nothing about the mechanism goes on this card (#9387).
p2: it is unmeasured, and reach needs a deployment grant (the default empty state denies). Measure first, as the maintainer chose (「立卡,先实测再修」). If the gap is confirmed, the fix extends ruling C's "an anonymous submission carries no file" to ADR-0138 D2's other anonymous write classes.
The detail comes from the filing seat's session (session_01JVTd3PprStGa26aez5omLB).
Claim: PM loop round 1 · card thread
Session: session_0186vfjHHMsRXC9EUT9hTFMo (the seat); the card thread is session_01VG2Ug3VQqDPcepHcmoD9m1
Account: os-project-manager (the seat's linked user; the card's assignee)
Branch: claude/project-thread-0k5uer (the card thread's harness-pinned branch; it names no issue, so this claim is the identity record)
Worktree: the card thread's own container checkout
Domain: domain:server
Seat: domain:server#2
Ruling-ref: the maintainer's 「立卡,先实测再修(推荐)」 (measure first, then fix) and 「所有的安全卡不要创建issue,直接派发处理修复」 (no new issue, no advisory); the fix extends ruling C (an anonymous submission carries no file) to ADR-0138 D2's other anonymous write classes; ⛔ no mechanism or reproduction on any public surface
File surface: the anonymous write doors of ADR-0138 D2 other than the public-form door, and the file-reference claim path they reach (packages/rest/**, packages/services/service-storage/src/file-reference-lifecycle.ts), their tests, one changeset. ⛔ No packages/spec/** (stop on breach; explain in the report)
Container & model: M, security, mode:thread, default model and effort (set at thread open)
Clause-②: no (expected no (narrowing); the dev measures)
Metadata-protocol: none
Responsibility: unmeasured; the first act is the measurement the maintainer chose, re-read against PR #25951 (37617109), which landed after filing. Reach needs a deployment grant (the default empty state denies)
Thread-read: 6387012040
Premise: holds as a measurement card (read 2026-10-26T08:33Z at origin/main05f7758f05: card open, unassigned, pm:queue, no claim on the thread). A fully-closed reading after #25951 is a legal premise_still_valid: false hand-back
Serial constraints cleared: no open PR names #25694; no in-flight lane claim declares file-reference-lifecycle.ts or the anonymous doors (read across seat 1's 12 pm:dispatched claims at this act); the dev re-measures open PRs on its surface before pr_create
{
"issue": 25694,
"status": "done",
"branch": "claude/project-thread-0k5uer",
"pr": "https://github.com/objectstack-ai/objectstack/pull/26036",
"session": "session_01VG2Ug3VQqDPcepHcmoD9m1",
"premise_still_valid": true,
"summary": "Measured on origin/main 05f7758f against each ADR-0138 D2 anonymous write class after #25951: one class was still open, the others closed (reads, the form door by #25682, and one class closed by construction). Per-class measurements and paths are with the server seat 2 thread only. The fix extends ruling C at the file-reference lifecycle's before-write hook: a write whose caller has no user and carries a value in a file field is refused with the form door's envelope (400 VALIDATION_FAILED, invalid_value per field, labelled), before the driver runs. Empty or absent file fields, signed-in callers, system and context-less writes are unchanged. Fixes #25694 (every class is closed with this PR). Departure from the order's route: the guard is at the lifecycle (inside the claim's file surface), not at a door in packages/rest or packages/runtime, so one guard closes the class; no runtime door is edited.",
"tests": "On head b2f90ab2b5: pnpm --filter @objectstack/service-storage test: Test Files 65 passed (65), Tests 1197 passed (1197); typecheck incl. check:test-typecheck exit 0. Red first: pins committed in cb5bb350/be589179 failed on the unchanged lifecycle before the fix 1171d6c2. New: 11 unit cases (6 refusal, 5 controls) in file-reference-lifecycle.test.ts and 7 integration cases (5 refusal, 2 controls) on real ObjectQL+SqlDriver with StorageServicePlugin. Three existing fixtures (sys-file-copy-backfill-organization-stamping x3, backfill-sys-file-public-scope x1) now give their caller a user; subjects unchanged. Ablation via scripts/ablation-replace.mjs (anchor 1->0, blob a20601e3c089->0fb3c1f30905, restored blob == HEAD, git diff HEAD empty): guard disabled => 12 red (6 unit refusal, 5 integration refusal, 1 integration signed-in control that depends on the refusal), 5 unit controls + guest no-file control green; subject resolves via relative src, no dist. Live door probe on a booted stack before and after the fix (local only, not committed): every anonymous file value refused 400 VALIDATION_FAILED after, controls unchanged. eslint --no-inline-config over packages/services/service-storage/src: exit 0.",
"gates": "Local: dispatch-gates --commands --repo objectstack-ai/objectstack on b2f90ab2b5 derived 71; 70 exit 0 first pass; pnpm check:dual-build-cjs-loads exit 3 (7 packages outside the dogfood closure lacked dist, nothing measured), rerun after building them exit 0. --ran: 71 derived, 71 run, 0 NOT-MEASURED, 0 UNRUN, exit 0. Repo-wide pnpm lint is CI's. CI check-runs on #26036: in_progress at report time (seat reads convergence).",
"dogfood_battery": "b2f90ab2b5 · os-verify-lock VERDICT command-exit 1 (held 20m14s) · Test Files 295 passed / 1 failed / 3 skipped (299) · Tests 2522 passed / 1 failed / 18 skipped (2541) · the one failure: authz-probe-blind-spot.test.ts, control handleI18nRequest in packages/runtime/src/domains/i18n.ts expected 3 found 4 — red on main independently: neither file differs between base 05f7758f and main 39a78b15, and this diff touches neither package",
"mcp_calls": "0 — no MCP GitHub calls (reads via gh api REST: card, triage, claim, PRs #25682/#25951, 33 open-PR file lists for surface overlap — none overlap)",
"api_writes": "2 — POST /repos/{board}/dispatches via scripts/pm/fleet-write/dispatch.mjs (pr_create #26036, draft, assignee os-project-manager, read-back identical 6566 bytes); this os-dev-report comment via scripts/pm/post-stamped.mjs. git push is not a REST write.",
"open_questions": [],
"out_of_scope_findings": [
"class: a · reach: the full dogfood battery is red on main at authz-probe-blind-spot.test.ts (handleI18nRequest control count 3 expected, 4 found in packages/runtime/src/domains/i18n.ts) · evidence: failed identically on this branch, neither file differs from main 39a78b15 · dedupe words: authz-probe-blind-spot, handleI18nRequest, i18n control count · carrier: the seat (already noted in seat memory as red since #25956)"
]
}
PR #26036 merged at 2026-10-26T11:34Z by the merge queue as b4199c9683 on main (Fixes #25694; ACCEPT 6413809958, contract review 6413304729 PASS). The merge closed this card as completed. · domain:server seat 2 · os-project-manager · session_0186vfjHHMsRXC9EUT9hTFMo · 2026-10-26T11:39Z
GET /repos/objectstack-ai/objectstack/issues/25694
closed, completed
Landed: ruling C's rule, "an anonymous submission carries no file", now holds for every ADR-0138 D2 anonymous write class, enforced once where every engine write path passes. The changeset is .changeset/25694-anonymous-write-carries-no-file.md.
Remains: none on this card.
State: closed by the merge. The card thread is done.
Activity
objectstack-fleet commentedon Oct 24, 2026
Triage: first grade —
bug·security·priority:p2·domain:server·area:files·pm:queue· triage seat ·session_01AavokzJ5DndAwitDXvKy4U· 2026-10-24T16:59Z⛔ Not a claim, ⛔ not a dispatch.
⛔ Nothing about the mechanism goes on this card (#9387).
session_01JVTd3PprStGa26aez5omLB).Generated by Claude Code
objectstack-fleet commentedon Oct 26, 2026
Claim: PM loop round 1 · card thread
Session:
session_0186vfjHHMsRXC9EUT9hTFMo(the seat); the card thread issession_01VG2Ug3VQqDPcepHcmoD9m1Account:
os-project-manager(the seat's linked user; the card's assignee)Branch:
claude/project-thread-0k5uer(the card thread's harness-pinned branch; it names no issue, so this claim is the identity record)Worktree: the card thread's own container checkout
Domain:
domain:serverSeat:
domain:server#2Ruling-ref: the maintainer's 「立卡,先实测再修(推荐)」 (measure first, then fix) and 「所有的安全卡不要创建issue,直接派发处理修复」 (no new issue, no advisory); the fix extends ruling C (an anonymous submission carries no file) to ADR-0138 D2's other anonymous write classes; ⛔ no mechanism or reproduction on any public surface
File surface: the anonymous write doors of ADR-0138 D2 other than the public-form door, and the file-reference claim path they reach (
packages/rest/**,packages/services/service-storage/src/file-reference-lifecycle.ts), their tests, one changeset. ⛔ Nopackages/spec/**(stop on breach; explain in the report)Container & model:
M,security,mode:thread, default model and effort (set at thread open)Clause-②: no (expected
no (narrowing); the dev measures)Metadata-protocol: none
Responsibility: unmeasured; the first act is the measurement the maintainer chose, re-read against PR #25951 (
37617109), which landed after filing. Reach needs a deployment grant (the default empty state denies)Thread-read: 6387012040
Premise: holds as a measurement card (read 2026-10-26T08:33Z at
origin/main05f7758f05: card open, unassigned,pm:queue, no claim on the thread). A fully-closed reading after #25951 is a legalpremise_still_valid: falsehand-backSerial constraints cleared: no open PR names #25694; no in-flight lane claim declares
file-reference-lifecycle.tsor the anonymous doors (read across seat 1's 12pm:dispatchedclaims at this act); the dev re-measures open PRs on its surface beforepr_createobjectstack-fleet commentedon Oct 26, 2026
os-dev-report
{ "issue": 25694, "status": "done", "branch": "claude/project-thread-0k5uer", "pr": "https://github.com/objectstack-ai/objectstack/pull/26036", "session": "session_01VG2Ug3VQqDPcepHcmoD9m1", "premise_still_valid": true, "summary": "Measured on origin/main 05f7758f against each ADR-0138 D2 anonymous write class after #25951: one class was still open, the others closed (reads, the form door by #25682, and one class closed by construction). Per-class measurements and paths are with the server seat 2 thread only. The fix extends ruling C at the file-reference lifecycle's before-write hook: a write whose caller has no user and carries a value in a file field is refused with the form door's envelope (400 VALIDATION_FAILED, invalid_value per field, labelled), before the driver runs. Empty or absent file fields, signed-in callers, system and context-less writes are unchanged. Fixes #25694 (every class is closed with this PR). Departure from the order's route: the guard is at the lifecycle (inside the claim's file surface), not at a door in packages/rest or packages/runtime, so one guard closes the class; no runtime door is edited.", "tests": "On head b2f90ab2b5: pnpm --filter @objectstack/service-storage test: Test Files 65 passed (65), Tests 1197 passed (1197); typecheck incl. check:test-typecheck exit 0. Red first: pins committed in cb5bb350/be589179 failed on the unchanged lifecycle before the fix 1171d6c2. New: 11 unit cases (6 refusal, 5 controls) in file-reference-lifecycle.test.ts and 7 integration cases (5 refusal, 2 controls) on real ObjectQL+SqlDriver with StorageServicePlugin. Three existing fixtures (sys-file-copy-backfill-organization-stamping x3, backfill-sys-file-public-scope x1) now give their caller a user; subjects unchanged. Ablation via scripts/ablation-replace.mjs (anchor 1->0, blob a20601e3c089->0fb3c1f30905, restored blob == HEAD, git diff HEAD empty): guard disabled => 12 red (6 unit refusal, 5 integration refusal, 1 integration signed-in control that depends on the refusal), 5 unit controls + guest no-file control green; subject resolves via relative src, no dist. Live door probe on a booted stack before and after the fix (local only, not committed): every anonymous file value refused 400 VALIDATION_FAILED after, controls unchanged. eslint --no-inline-config over packages/services/service-storage/src: exit 0.", "gates": "Local: dispatch-gates --commands --repo objectstack-ai/objectstack on b2f90ab2b5 derived 71; 70 exit 0 first pass; pnpm check:dual-build-cjs-loads exit 3 (7 packages outside the dogfood closure lacked dist, nothing measured), rerun after building them exit 0. --ran: 71 derived, 71 run, 0 NOT-MEASURED, 0 UNRUN, exit 0. Repo-wide pnpm lint is CI's. CI check-runs on #26036: in_progress at report time (seat reads convergence).", "dogfood_battery": "b2f90ab2b5 · os-verify-lock VERDICT command-exit 1 (held 20m14s) · Test Files 295 passed / 1 failed / 3 skipped (299) · Tests 2522 passed / 1 failed / 18 skipped (2541) · the one failure: authz-probe-blind-spot.test.ts, control handleI18nRequest in packages/runtime/src/domains/i18n.ts expected 3 found 4 — red on main independently: neither file differs between base 05f7758f and main 39a78b15, and this diff touches neither package", "mcp_calls": "0 — no MCP GitHub calls (reads via gh api REST: card, triage, claim, PRs #25682/#25951, 33 open-PR file lists for surface overlap — none overlap)", "api_writes": "2 — POST /repos/{board}/dispatches via scripts/pm/fleet-write/dispatch.mjs (pr_create #26036, draft, assignee os-project-manager, read-back identical 6566 bytes); this os-dev-report comment via scripts/pm/post-stamped.mjs. git push is not a REST write.", "open_questions": [], "out_of_scope_findings": [ "class: a · reach: the full dogfood battery is red on main at authz-probe-blind-spot.test.ts (handleI18nRequest control count 3 expected, 4 found in packages/runtime/src/domains/i18n.ts) · evidence: failed identically on this branch, neither file differs from main 39a78b15 · dedupe words: authz-probe-blind-spot, handleI18nRequest, i18n control count · carrier: the seat (already noted in seat memory as red since #25956)" ] }Generated by Claude Code
objectstack-fleet commentedon Oct 26, 2026
ACCEPT → PR #26036 comment 6413809958 (head
8102869e46, contract review 6413304729 PASS) ·domain:serverseat 2 ·session_0186vfjHHMsRXC9EUT9hTFMo· 2026-10-26T10:29Z. The head is green; landing through the queue now.Generated by Claude Code
objectstack-fleet commentedon Oct 26, 2026
Landed
PR #26036 merged at 2026-10-26T11:34Z by the merge queue as
b4199c9683onmain(Fixes #25694; ACCEPT6413809958, contract review6413304729PASS). The merge closed this card as completed. ·domain:serverseat 2 ·os-project-manager·session_0186vfjHHMsRXC9EUT9hTFMo· 2026-10-26T11:39Zgit ls-remote origin 'refs/heads/gh-readonly-queue/main/pr-26036-*'git merge-base --is-ancestor b4199c9683 origin/mainGET /repos/objectstack-ai/objectstack/issues/25694completed.changeset/25694-anonymous-write-carries-no-file.md.Generated by Claude Code