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
metadata: a runtime permission-set save accepts a grant on an object that does not exist (200) — the build refuses the same grant (#18202), so a typo silently grants nothing #28990
立卡门: ① 产品缺陷,具名落点 + 复现(reach: 公开入口 HTTP PUT /api/v1/meta/permission/NAME 实测一次错误结果)
业务理由: 在 Studio 或用 API 运行时编辑权限集的管理员,把对象名写错(例如短名 lead 而不是 crm_lead)会得到 200,以为授权成功,实际什么都没授。#18202 正是为这个场景在构建期加了硬失败(「grant is simply lost … Fail loudly at build time」),但运行时保存门没有同样的检查,同一个错误在两条路上一条报错、一条静默。
动手的读者: domain:server 席,元数据保存门对 permission 的校验(packages/metadata-protocol):复用 packages/spec/src/stack.zod.ts 的 collectPermissionGrantObjectErrors 判据(平台对象照放行),对运行时已注册对象集合判 objects 的键,未知对象 422 点名。
查重: permission set grant unknown object runtime save 121 命中、permission set objects not defined meta PUT 51、collectPermissionGrantObjectErrors 1(均含已关);最近邻 #18202(构建期规则本身,已关),没有运行时门的卡。
QA-source: #28981 · access-security.permission-matrix-edit-loop · observed beside the clauses
What happens
PUT /api/v1/meta/permission/qa_r3_probe2 whose objects names qa_no_such_object answers 200 (active save), and the same body through ?mode=draft then publish answers 200 too.
Measured at framework 7fa9873f (main, 2026-11-02), stock showcase boot from a scratch copy, as the seeded admin.
Reproduction
As admin: PUT /api/v1/meta/permission/qa_r3_probe2 with an otherwise valid permission-set body whose objects map carries a grant keyed qa_no_such_object (an object no package registers).
Expected: 422 naming objects.qa_no_such_object as an unknown object, as the build-time rule does.
Actual: 200, stored and served; the same through draft → publish.
Claim: PM loop round 1 · card thread · 2026-11-02T06:25Z
Session: session_01R1q2xdtYgU6FKrZ7LgjPCC (the seat); the card thread is session_01FEkQ5oyJ4R1betVYFyp6SD (a new card thread, fresh from mainab085a04)
Account: os-project-manager (the seat's linked user; the card's assignee)
Branch: claude/project-thread-gk98zo (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#1
Ruling-ref: triage#1 graded the card p2 (06:01Z): wrong things refused loudly; not an authorization hole. Route (the dispatching seat's call): refuse at the metadata save door beside #26724's unknown-datasource refusal, with the save door's existing 422 envelope; "known" is the runtime's registered objects, stored rows and same-batch drafts. Dispatched in the seat-1 split of the server queue under 「队列进了很多任务,抓紧派发」 (Leehom, 2026-11-02T05:15Z) and 「定级你可以自己决定」 (Leehom, 2026-11-01T12:11Z).
File surface: the save-door refusals in packages/metadata-protocol/src/protocol-save-door-refusals.ts and their three call sites (save, publish promotion, restore); their tests and changesets. ⛔ No packages/spec/** (the build rule collectPermissionGrantObjectErrors is read, never exported or edited), no new error code, no new gate.
Container & model: S, mode:thread, model and effort as the thread was opened
Clause-②: no (narrowing) (expected: a permission-set save naming an unknown object, accepted 200 on main, is refused; the dev measures)
Metadata-protocol: per the #26724 precedent, expected narrowed with a minor changeset; measured by the dev
Responsibility: the code is the metadata save door of @objectstack/metadata-protocol · the platform path is a permission set whose grant names an object that does not exist, saved 200 and granting nothing · reached by every admin editing a permission set in Studio or through PUT /api/v1/meta/permission/:name
Thread-read: none
Premise: holds on main7fa9873f (the card's QA record #28981)
Serial constraints cleared: #18202 (the build rule) closed. No open server card edits protocol-save-door-refusals.ts; #28952 (seat 1, another thread) edits the seed save door in the same package, so merge origin/main once if it lands first.
Resume-from: none — fresh from origin/main
State: pm:queue → pm:dispatched, assigned to os-project-manager, recorded by this claim.
Release: server seat 1 shift close · 2026-11-02T07:42Z
Session: session_01R1q2xdtYgU6FKrZ7LgjPCC (the seat that claimed this card); card thread session_01FEkQ5oyJ4R1betVYFyp6SD (paused)
Who / what / where: Leehom (os-project-manager) in the server-lane project chat — 「进展中的开发先提交代码然后暂停,先确保已有的pr都合并」 (2026-11-02T07:11Z), 「自动合并中的也交给下一任跟进」 (2026-11-02T07:23Z), 「我说的是pm-dispatch 中车道下班的流程,都要走完」 (2026-11-02T07:33Z). Shift close returns every claim to the queue (seat-post-protocol.md 交接收尾清单 step 2); no stay-behind.
Resume-from: claude/project-thread-gk98zo@7d6842b30a5006dd6d1edbd2a6858af2104f6611 — PR #29093, ACCEPTed by the seat on this head. Contract review 6571510063, ACCEPT 6571515994; auto-merge armed, checks pending.
Successor: read the handoff 6571543819 on seat post #6367 first; land PR #29093 on green, write the landing record, close this card. ⛔ Do not re-dispatch the card from scratch.
State: pm:dispatched → pm:queue, assignee os-project-manager cleared, recorded by this release.
Claim: PM loop round 1 · takeover of a released card · 2026-11-02T08:17Z
Session: session_01ADHkmQjPiXgNoSaEpqeGvY
Account: os-steve (the card's assignee, set in the same round)
Branch: claude/project-thread-gk98zo
Worktree: the predecessor card thread's (paused); no new dev is dispatched
Domain: domain:server
Seat: domain:server#1
File surface: unchanged from the predecessor's claim 6570627828 (packages/metadata-protocol/src/protocol-save-door-refusals.ts and its call sites); the open PR #29093 is the surface.
Container & model: S, mode:thread, landing only (no new build)
Clause-②: no (narrowing)
Metadata-protocol: narrowed
Responsibility: as in the predecessor's claim (unchanged)
Thread-read: 6571796395
Premise: holds (PR #29093 ACCEPTed by the predecessor seat)
Serial constraints cleared: none new; the seven PRs this seat inherited are its only in-flight surface.
Resume-from: claude/project-thread-gk98zo@7d6842b30a5006dd6d1edbd2a6858af2104f6611
Takeover record: the predecessor (os-project-manager, session_01R1q2xdtYgU6FKrZ7LgjPCC) released this card in 6571796395 at its shift close (Leehom: 「自动合并中的也交给下一任跟进」). This seat takes it on the maintainer's summons in the Claude Code project "objectstack spec" (「server 1 号座位你也接手开席位」), seat 2 (#20966) having left it to seat 1. Last pushed head: 7d6842b30a (PR #29093). Auto-merge armed, checks pending; follow to MERGED.
Claim: PM loop round 1 · revised (a dev is dispatched onto the open PR) · 2026-11-02T08:39Z
Session: session_01ADHkmQjPiXgNoSaEpqeGvY (seat); dev = card thread session_01ADHkmSjtHK8jHQqWternFp
Account: os-steve
Branch: claude/project-thread-gk98zo (unchanged; the dev pushes to it, PR #29093)
Worktree: the card thread's own
Domain: domain:server
Seat: domain:server#1
File surface: the PR's surface (packages/metadata-protocol/src/protocol-save-door-refusals.ts and its call sites) plus the fixture of packages/objectql/src/protocol-duplicate-package-objects-key-collision.test.ts and any other consumer test the narrowing breaks. ⛔ No change that weakens the new refusal, no packages/spec/**, no new gate.
Container & model: S, mode:thread, model as the thread was opened, effort: medium
Clause-②: no (narrowing)
Metadata-protocol: narrowed
Responsibility: as in the predecessor's claim 6570627828 (unchanged)
Thread-read: 6572392758
Premise: corrected — PR #29093 head 7d6842b30a is red on Test Core (7/8): 2 objectql tests (ADR-0070 D4 duplicatePackage permission-set key collision) seed, through the save door, a grant on an unregistered object, which this PR now refuses. Auto-merge was disabled by this seat; the seat re-checks the new head before re-arming.
Serial constraints cleared: #28952 (PR #29066, this seat, seed save door in the same package) is in the merge queue; merge origin/main once if it lands first.
Resume-from: claude/project-thread-gk98zo@7d6842b30a5006dd6d1edbd2a6858af2104f6611
Orders: the seat's standard order plus server-seat1/28990-fix-delta.md in the project's shared folder.
{
"issue": 28990,
"status": "done",
"branch": "claude/project-thread-gk98zo",
"pr": "https://github.com/objectstack-ai/objectstack/pull/29093",
"session": "session_01ADHkmSjtHK8jHQqWternFp",
"premise_still_valid": true,
"summary": "Fix round on PR #29093 (red on Test Core 7/8 at 7d6842b3). Two consumer fixtures granted on an object that does not exist and are now refused by the PR's own save-door refusal; both fixed in the fixture, the refusal untouched: (1) objectql ADR-0070 D4 key-collision test now saves the set with its one known grant through the door and gives the stored sys_metadata row the two-key objects map (the at-rest shape); (2) dogfood wall-catalog-refusal granted CRUD on sys_permission_set / sys_position, the retired catalog row objects the same file pins unregistered; those two grants removed. Merged origin/main twice (second merge resolved conflicts with #28952's seed externalId refusal in protocol.ts, protocol-authoring-gate.ts and the restore-family test: both refusals kept, the test harness's objects stage unified on main's Map). Final head 8604d1dc.",
"tests": "At 7d6842b3: objectql key-collision file 2 failed / 3 passed (reproduced, the refusal thrown from seed()). After the fixture edit: 5/5. Full suites at 0993e876 (first merge, before the dogfood fixture edit): objectql 527 files / 10126 tests passed; metadata-protocol 299 passed 4 skipped / 22089 passed 26 skipped; plugin-security 238 / 5127 passed 45 skipped; runtime 514 / 8318 passed 19 skipped; rest 367 / 6963 passed 332 skipped; cloud-connection 67 / 813 passed. Full dogfood battery at 0993e876: 1 failed / 387 passed / 3 skipped files, 3195 passed tests; the failure was wall-catalog-refusal beforeAll (expected 422 to be 200) under both walled postures; fixed in 4b79bd63, that file 17/17. At final head 8604d1dc (after the conflict merge), every VERDICT command-exit 0: metadata-protocol 301 passed 4 skipped / 22120 passed 26 skipped; objectql 527 / 10140 passed; metadata-protocol typecheck 0; dogfood wall-catalog-refusal + permission-unknown-grant-object-refusal 2 files / 24 tests passed; eslint (objectql key-collision file, packages/metadata-protocol, both dogfood files, --no-inline-config) exit 0. No ablation: the diff changes fixtures, not a tested behaviour; the red side of each is the CI/dogfood failure above.",
"gates": "At 8604d1dc: dispatch-gates --commands derived 74 families; all 74 run, every one exit 0 (check-plugin-teardown-shape --self-test after fetching its fixture commit; check:dual-build-cjs-loads after building the 7 packages outside the closure; check:type-check-debt re-run without lock contention). --ran reconciliation: 74 derived, 74 run, 0 NOT-MEASURED, 0 UNRUN, exit 0. pnpm lint: neither touched package declares a lint script (pnpm lint answers Command not found, exit 254), so eslint was run directly as above, exit 0. CI on 8604d1dc: read by the seat (contract review PASS 6574758254, ACCEPT r2 6574786481); not re-read here.",
"dogfood_battery": "0993e876 · VERDICT command-exit 1 · Test Files 1 failed / 387 passed / 3 skipped (391) · Tests 3195 passed / 44 skipped · failure: wall-catalog-refusal.dogfood.test.ts (both postures), a stale fixture of this change, fixed in 4b79bd63 and re-run 17/17; the full battery was not re-run on 8604d1dc (the conflict merge touched metadata-protocol only; the two dogfood files that exercise this refusal re-ran green there)",
"mcp_calls": "3 — issue_read get_comments #28990, pull_request_read get_check_runs #29093, pull_request_read get #29093 (reads only); no MCP write",
"api_writes": "1 — this os-dev-report comment via post-stamped.mjs on #28990; plus 4 git pushes (00306c45, 0993e876, 4b79bd63, 8604d1dc), not REST writes",
"files_changed": [
"packages/objectql/src/protocol-duplicate-package-objects-key-collision.test.ts",
"packages/qa/dogfood/test/wall-catalog-refusal.dogfood.test.ts",
"merge resolutions: packages/metadata-protocol/src/protocol.ts, packages/metadata-protocol/src/protocol-authoring-gate.ts, packages/metadata-protocol/src/protocol.restore-doors-save-refusal-family.test.ts"
],
"line_budget": "this round, branch delta vs origin/main: 10 files, +727 / -7 (was 8 files +705 / -3); the two fixture edits are +27 / -6",
"deviations": [
"PR body NOT patched: os-dev.md (the dev writes the PR body once and never PATCHes it) binds over the fix-delta's step 5, and the relay refuses an issue_patch body whose first line is not a seat signature while the delta asks to keep the attribution lines first. The ready-to-write body is /mnt/project-files/server-seat1/29093-body-r2.md for the seat to write.",
"Merged origin/main a second time after the seat reported the PR dirty (conflicts with #28952); readings re-taken on 8604d1dc as listed; the full dogfood battery and the runtime/rest/plugin-security/cloud-connection suites were taken at 0993e876, not re-run after the conflict merge.",
"Throwaway probes (two, files deleted, never committed) answered the D4 reachability question and the seat's migrate-stored question."
],
"open_questions": [
{
"question": "Can a NEW save still reach ADR-0070 D4's permission-set branch after #28990?",
"options": [
"A: yes, it stays a live guard",
"B: no, only a stored-row guard"
],
"recommendation": "A, measured: with object dupdst_customer saved in the target package, a set granting on dupsrc_customer and dupdst_customer saves 200 and duplicatePackage into that target refuses it in failed[] with the D4 sentence; a held grant on an object deleted since reaches it too. No code change."
},
{
"question": "Seat's ask (review should-fix 1): does migrate-stored fail a draft-only permission set granting on an unknown object?",
"options": [
"A: file the follow-up card",
"B: leave it"
],
"recommendation": "A. Measured at 8604d1dc on the real kernel: a draft-only set (no active row) granting on an object draft that is then removed. Canonical body: scanned 1, canonical 1, no re-save, nothing reported. Body needing a conversion (legacy managedBy key): preview outcome pending, apply outcome failed with the 422 refusal text (failed 1). Control with the object draft still present: apply outcome rewritten. Cause: the held-grant read is readMetaItem of the active row, which a draft-only set does not have."
}
],
"out_of_scope_findings": [
"carrier: seat (follow-up card for the migrate-stored draft-only case, readings above) · noted, not filed"
]
}
Activity
objectstack-fleet commentedon Nov 2, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: none
Triage: p2 ·
domain:server·area:access·pm:queue· 2026-11-02T06:01Z⛔ Not a claim.
PUT /api/v1/meta/permission/NAME, active or draft then publish) accepts a grant keyed by an object that does not exist, so a typo silently grants nothing. The build already refuses the same grant (collectPermissionGrantObjectErrors, spec:defineStack's per-stack cross-reference validation refusespermissions[].objectsanddata[].objectthat name an object owned by ANOTHER PACKAGE OF THE SAME ARTIFACT — so ADR-0130's co-owned artifact and the "permission sets stay whole in the app package" addendum cannot both hold once the app package owns objects #18202). The save door inpackages/metadata-protocolmust judge the same set: wrong things refused loudly. Not an authorization hole: nothing is granted.domain:server, p2.Generated by Claude Code
objectstack-fleet commentedon Nov 2, 2026
domain:server#1 · os-project-manager · session_01R1q2xdtYgU6FKrZ7LgjPCC
Claim: PM loop round 1 · card thread · 2026-11-02T06:25Z
Session:
session_01R1q2xdtYgU6FKrZ7LgjPCC(the seat); the card thread issession_01FEkQ5oyJ4R1betVYFyp6SD(a new card thread, fresh frommainab085a04)Account:
os-project-manager(the seat's linked user; the card's assignee)Branch:
claude/project-thread-gk98zo(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#1Ruling-ref: triage#1 graded the card p2 (06:01Z): wrong things refused loudly; not an authorization hole. Route (the dispatching seat's call): refuse at the metadata save door beside #26724's unknown-datasource refusal, with the save door's existing 422 envelope; "known" is the runtime's registered objects, stored rows and same-batch drafts. Dispatched in the seat-1 split of the server queue under 「队列进了很多任务,抓紧派发」 (Leehom, 2026-11-02T05:15Z) and 「定级你可以自己决定」 (Leehom, 2026-11-01T12:11Z).
File surface: the save-door refusals in
packages/metadata-protocol/src/protocol-save-door-refusals.tsand their three call sites (save, publish promotion, restore); their tests and changesets. ⛔ Nopackages/spec/**(the build rulecollectPermissionGrantObjectErrorsis read, never exported or edited), no new error code, no new gate.Container & model:
S,mode:thread, model and effort as the thread was openedClause-②: no (narrowing) (expected: a permission-set save naming an unknown object, accepted 200 on
main, is refused; the dev measures)Metadata-protocol: per the #26724 precedent, expected
narrowedwith aminorchangeset; measured by the devResponsibility: the code is the metadata save door of
@objectstack/metadata-protocol· the platform path is a permission set whose grant names an object that does not exist, saved 200 and granting nothing · reached by every admin editing a permission set in Studio or throughPUT /api/v1/meta/permission/:nameThread-read: none
Premise: holds on
main7fa9873f(the card's QA record #28981)Serial constraints cleared: #18202 (the build rule) closed. No open server card edits
protocol-save-door-refusals.ts; #28952 (seat 1, another thread) edits the seed save door in the same package, so mergeorigin/mainonce if it lands first.Resume-from: none — fresh from
origin/mainState:
pm:queue→pm:dispatched, assigned toos-project-manager, recorded by this claim.Generated by Claude Code
objectstack-fleet commentedon Nov 2, 2026
domain:server#1 · os-project-manager · session_01R1q2xdtYgU6FKrZ7LgjPCC
Release: server seat 1 shift close · 2026-11-02T07:42Z
Session:
session_01R1q2xdtYgU6FKrZ7LgjPCC(the seat that claimed this card); card threadsession_01FEkQ5oyJ4R1betVYFyp6SD(paused)Who / what / where: Leehom (
os-project-manager) in the server-lane project chat — 「进展中的开发先提交代码然后暂停,先确保已有的pr都合并」 (2026-11-02T07:11Z), 「自动合并中的也交给下一任跟进」 (2026-11-02T07:23Z), 「我说的是pm-dispatch 中车道下班的流程,都要走完」 (2026-11-02T07:33Z). Shift close returns every claim to the queue (seat-post-protocol.md 交接收尾清单 step 2); no stay-behind.Resume-from:
claude/project-thread-gk98zo@7d6842b30a5006dd6d1edbd2a6858af2104f6611— PR #29093, ACCEPTed by the seat on this head. Contract review 6571510063, ACCEPT 6571515994; auto-merge armed, checks pending.Successor: read the handoff 6571543819 on seat post #6367 first; land PR #29093 on green, write the landing record, close this card. ⛔ Do not re-dispatch the card from scratch.
State:
pm:dispatched→pm:queue, assigneeos-project-managercleared, recorded by this release.Generated by Claude Code
objectstack-fleet commentedon Nov 2, 2026
domain:server#1 · os-steve · session_01ADHkmQjPiXgNoSaEpqeGvY
Claim: PM loop round 1 · takeover of a released card · 2026-11-02T08:17Z
Session:
session_01ADHkmQjPiXgNoSaEpqeGvYAccount:
os-steve(the card's assignee, set in the same round)Branch:
claude/project-thread-gk98zoWorktree: the predecessor card thread's (paused); no new dev is dispatched
Domain:
domain:serverSeat:
domain:server#1File surface: unchanged from the predecessor's claim 6570627828 (
packages/metadata-protocol/src/protocol-save-door-refusals.tsand its call sites); the open PR #29093 is the surface.Container & model:
S,mode:thread, landing only (no new build)Clause-②: no (narrowing)
Metadata-protocol: narrowed
Responsibility: as in the predecessor's claim (unchanged)
Thread-read: 6571796395
Premise: holds (PR #29093 ACCEPTed by the predecessor seat)
Serial constraints cleared: none new; the seven PRs this seat inherited are its only in-flight surface.
Resume-from:
claude/project-thread-gk98zo@7d6842b30a5006dd6d1edbd2a6858af2104f6611Takeover record: the predecessor (
os-project-manager,session_01R1q2xdtYgU6FKrZ7LgjPCC) released this card in 6571796395 at its shift close (Leehom: 「自动合并中的也交给下一任跟进」). This seat takes it on the maintainer's summons in the Claude Code project "objectstack spec" (「server 1 号座位你也接手开席位」), seat 2 (#20966) having left it to seat 1. Last pushed head:7d6842b30a(PR #29093). Auto-merge armed, checks pending; follow to MERGED.objectstack-fleet commentedon Nov 2, 2026
domain:server#1 · os-steve · session_01ADHkmQjPiXgNoSaEpqeGvY
Claim: PM loop round 1 · revised (a dev is dispatched onto the open PR) · 2026-11-02T08:39Z
Session:
session_01ADHkmQjPiXgNoSaEpqeGvY(seat); dev = card threadsession_01ADHkmSjtHK8jHQqWternFpAccount:
os-steveBranch:
claude/project-thread-gk98zo(unchanged; the dev pushes to it, PR #29093)Worktree: the card thread's own
Domain:
domain:serverSeat:
domain:server#1File surface: the PR's surface (
packages/metadata-protocol/src/protocol-save-door-refusals.tsand its call sites) plus the fixture ofpackages/objectql/src/protocol-duplicate-package-objects-key-collision.test.tsand any other consumer test the narrowing breaks. ⛔ No change that weakens the new refusal, nopackages/spec/**, no new gate.Container & model:
S,mode:thread, model as the thread was opened,effort: mediumClause-②: no (narrowing)
Metadata-protocol: narrowed
Responsibility: as in the predecessor's claim 6570627828 (unchanged)
Thread-read: 6572392758
Premise: corrected — PR #29093 head
7d6842b30ais red onTest Core (7/8): 2 objectql tests (ADR-0070 D4 duplicatePackage permission-set key collision) seed, through the save door, a grant on an unregistered object, which this PR now refuses. Auto-merge was disabled by this seat; the seat re-checks the new head before re-arming.Serial constraints cleared: #28952 (PR #29066, this seat, seed save door in the same package) is in the merge queue; merge
origin/mainonce if it lands first.Resume-from:
claude/project-thread-gk98zo@7d6842b30a5006dd6d1edbd2a6858af2104f6611Orders: the seat's standard order plus server-seat1/28990-fix-delta.md in the project's shared folder.
objectstack-fleet commentedon Nov 2, 2026
domain:server#1 · os-steve · session_01ADHkmSjtHK8jHQqWternFp
os-dev-report
{ "issue": 28990, "status": "done", "branch": "claude/project-thread-gk98zo", "pr": "https://github.com/objectstack-ai/objectstack/pull/29093", "session": "session_01ADHkmSjtHK8jHQqWternFp", "premise_still_valid": true, "summary": "Fix round on PR #29093 (red on Test Core 7/8 at 7d6842b3). Two consumer fixtures granted on an object that does not exist and are now refused by the PR's own save-door refusal; both fixed in the fixture, the refusal untouched: (1) objectql ADR-0070 D4 key-collision test now saves the set with its one known grant through the door and gives the stored sys_metadata row the two-key objects map (the at-rest shape); (2) dogfood wall-catalog-refusal granted CRUD on sys_permission_set / sys_position, the retired catalog row objects the same file pins unregistered; those two grants removed. Merged origin/main twice (second merge resolved conflicts with #28952's seed externalId refusal in protocol.ts, protocol-authoring-gate.ts and the restore-family test: both refusals kept, the test harness's objects stage unified on main's Map). Final head 8604d1dc.", "tests": "At 7d6842b3: objectql key-collision file 2 failed / 3 passed (reproduced, the refusal thrown from seed()). After the fixture edit: 5/5. Full suites at 0993e876 (first merge, before the dogfood fixture edit): objectql 527 files / 10126 tests passed; metadata-protocol 299 passed 4 skipped / 22089 passed 26 skipped; plugin-security 238 / 5127 passed 45 skipped; runtime 514 / 8318 passed 19 skipped; rest 367 / 6963 passed 332 skipped; cloud-connection 67 / 813 passed. Full dogfood battery at 0993e876: 1 failed / 387 passed / 3 skipped files, 3195 passed tests; the failure was wall-catalog-refusal beforeAll (expected 422 to be 200) under both walled postures; fixed in 4b79bd63, that file 17/17. At final head 8604d1dc (after the conflict merge), every VERDICT command-exit 0: metadata-protocol 301 passed 4 skipped / 22120 passed 26 skipped; objectql 527 / 10140 passed; metadata-protocol typecheck 0; dogfood wall-catalog-refusal + permission-unknown-grant-object-refusal 2 files / 24 tests passed; eslint (objectql key-collision file, packages/metadata-protocol, both dogfood files, --no-inline-config) exit 0. No ablation: the diff changes fixtures, not a tested behaviour; the red side of each is the CI/dogfood failure above.", "gates": "At 8604d1dc: dispatch-gates --commands derived 74 families; all 74 run, every one exit 0 (check-plugin-teardown-shape --self-test after fetching its fixture commit; check:dual-build-cjs-loads after building the 7 packages outside the closure; check:type-check-debt re-run without lock contention). --ran reconciliation: 74 derived, 74 run, 0 NOT-MEASURED, 0 UNRUN, exit 0. pnpm lint: neither touched package declares a lint script (pnpm lint answers Command not found, exit 254), so eslint was run directly as above, exit 0. CI on 8604d1dc: read by the seat (contract review PASS 6574758254, ACCEPT r2 6574786481); not re-read here.", "dogfood_battery": "0993e876 · VERDICT command-exit 1 · Test Files 1 failed / 387 passed / 3 skipped (391) · Tests 3195 passed / 44 skipped · failure: wall-catalog-refusal.dogfood.test.ts (both postures), a stale fixture of this change, fixed in 4b79bd63 and re-run 17/17; the full battery was not re-run on 8604d1dc (the conflict merge touched metadata-protocol only; the two dogfood files that exercise this refusal re-ran green there)", "mcp_calls": "3 — issue_read get_comments #28990, pull_request_read get_check_runs #29093, pull_request_read get #29093 (reads only); no MCP write", "api_writes": "1 — this os-dev-report comment via post-stamped.mjs on #28990; plus 4 git pushes (00306c45, 0993e876, 4b79bd63, 8604d1dc), not REST writes", "files_changed": [ "packages/objectql/src/protocol-duplicate-package-objects-key-collision.test.ts", "packages/qa/dogfood/test/wall-catalog-refusal.dogfood.test.ts", "merge resolutions: packages/metadata-protocol/src/protocol.ts, packages/metadata-protocol/src/protocol-authoring-gate.ts, packages/metadata-protocol/src/protocol.restore-doors-save-refusal-family.test.ts" ], "line_budget": "this round, branch delta vs origin/main: 10 files, +727 / -7 (was 8 files +705 / -3); the two fixture edits are +27 / -6", "deviations": [ "PR body NOT patched: os-dev.md (the dev writes the PR body once and never PATCHes it) binds over the fix-delta's step 5, and the relay refuses an issue_patch body whose first line is not a seat signature while the delta asks to keep the attribution lines first. The ready-to-write body is /mnt/project-files/server-seat1/29093-body-r2.md for the seat to write.", "Merged origin/main a second time after the seat reported the PR dirty (conflicts with #28952); readings re-taken on 8604d1dc as listed; the full dogfood battery and the runtime/rest/plugin-security/cloud-connection suites were taken at 0993e876, not re-run after the conflict merge.", "Throwaway probes (two, files deleted, never committed) answered the D4 reachability question and the seat's migrate-stored question." ], "open_questions": [ { "question": "Can a NEW save still reach ADR-0070 D4's permission-set branch after #28990?", "options": [ "A: yes, it stays a live guard", "B: no, only a stored-row guard" ], "recommendation": "A, measured: with object dupdst_customer saved in the target package, a set granting on dupsrc_customer and dupdst_customer saves 200 and duplicatePackage into that target refuses it in failed[] with the D4 sentence; a held grant on an object deleted since reaches it too. No code change." }, { "question": "Seat's ask (review should-fix 1): does migrate-stored fail a draft-only permission set granting on an unknown object?", "options": [ "A: file the follow-up card", "B: leave it" ], "recommendation": "A. Measured at 8604d1dc on the real kernel: a draft-only set (no active row) granting on an object draft that is then removed. Canonical body: scanned 1, canonical 1, no re-save, nothing reported. Body needing a conversion (legacy managedBy key): preview outcome pending, apply outcome failed with the 422 refusal text (failed 1). Control with the object draft still present: apply outcome rewritten. Cause: the held-grant read is readMetaItem of the active row, which a draft-only set does not have." } ], "out_of_scope_findings": [ "carrier: seat (follow-up card for the migrate-stored draft-only case, readings above) · noted, not filed" ] }Stamped 2026-11-02T10:52Z.
objectstack-fleet commentedon Nov 2, 2026
domain:server#1 · os-steve · session_01ADHkmQjPiXgNoSaEpqeGvY
Landed · 2026-11-02T11:25Z
78f78ac822, through the merge queuecompletedbyFixes #28990pm:dispatchedis removed. Seat record: revised claim 6572775812, contract review PASS 6574758254 (triage, head8604d1dc), seat ACCEPT r2 6574786481. Fix thread report 6575331948.migrate-storedfails to heal a draft-only permission set that needs a conversion when it grants on an object with no active row, because the unknown-grant refusal reads the active row #29279 (migrate-storedfails to heal a draft-only permission set that needs a conversion; publish-path wording; changeset line) awaits triage.