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
Package duplicate and unmanaged import refuse a copied permission set that grants on an optional plugin's object not installed here (same 422 the clone door had, #30255) #30319
Filing gate: ② a sibling of #30255 (p0), found by the contract review of PR #30310 (record 6650931967, should-fix S2), outside that PR's door. Read, not measured — the first act is to measure it. ⛔ Not a claim. Triage sets the grade.
Reader: domain:server, metadata-protocol (protocol-package-commits.ts) and the save door's unknown-object grant refusal (protocol-save-door-refusals.ts).
Dedupe: package duplicate permission set unknown object → none open. New.
The doors
PR #30310 lets the permission-set clone door save a copy whose grants name objects the SOURCE set already held (inheritedGrantObjects, server-derived), so a copy of member_default on a boot without plugin-audit (no sys_comment / sys_activity) is no longer refused 422. Two other doors copy a stored permission set verbatim under a new name with mode: 'publish' and pass no inherited set:
The package-duplicate door (protocol-package-commits.ts ~:768).
The unmanaged import (~:934).
A stored set granting on an uninstalled optional plugin's object should hit the same 422 there.
Wanted
Measure both doors on a boot without plugin-audit, duplicating / importing a package that carries a set granting sys_comment.
Claim: PM loop round 5
Session: session_01Utp6Cbvcmv8YWFhFJwzjKL (seat) · dev thread session_01Utp6CYSw4nSVJDr6XpcWLJ
Account: os-bill
Branch: claude/project-thread-9dm0ks (harness-pinned thread branch; platform exception to claude/issue-<n>-<slug>)
Worktree: objectstack-issue-30319
Domain: domain:server
Seat: domain:server#2
File surface: packages/metadata-protocol/src/protocol-package-commits.ts (the package-duplicate and unmanaged-import doors only), protocol-save.ts / protocol-door-requests.ts only if the inherited-grant plumbing needs a touch, tests beside them, one changeset .changeset/30319-copy-doors-inherited-grants.md. ⛔ packages/spec/**, ui/**, apps/**, skills/**, docs/adr/**, content/docs/**, .claude/**; protocol.ts itself only after telling the seat (stop on breach; explain in the report)
Container & model: M, mode:thread, model: default tier (opus) — dispatch-gates --tier: no path-derived mandate, effort: high
Clause-②: no expected — a copy the clone door already accepts stops being refused at two sibling doors; the dev re-declares yes (widening) for a new export
Metadata-protocol: none
Responsibility: the package-duplicate and unmanaged-import doors save a copied permission set with mode: 'publish' and no inherited grant objects, so a set granting on an uninstalled optional plugin's object is refused 422 | the save door's unknown-object refusal itself (#30255, unchanged) | every deployment without an optional plugin whose package carries such a set
Thread-read: 6651966154
Premise: read, to be measured first (the card's own first box) — at 870ebce3: both doors pass mode: 'publish' (protocol-package-commits.ts ~:772, ~:938) with no inheritedGrantObjects; the clone door's plumbing is protocol-door-requests.ts ~:30 → protocol-save.ts ~:1584
Serial constraints cleared: #30255 / #30108 landed (PR #30310, a545a041); sibling seat 3's #30053 moves docblocks in engine.ts / protocol.ts (no overlap with these two doors); pull main before PR and before landing.
Order: project file server-seat2/dispatch-30319.md, delivered as the card thread's opening message.
{
"issue": 30319,
"status": "done",
"branch": "claude/project-thread-9dm0ks",
"pr": "https://github.com/objectstack-ai/objectstack/pull/30414",
"session": "session_01Utp6CYSw4nSVJDr6XpcWLJ",
"premise_still_valid": true,
"summary": "Measured at 870ebce3 on a boot without plugin-audit: duplicatePackage answered 200 success:false with the set granting sys_comment in failed[] (the unknown-object 422 text); importUnmanagedPackage answered 422 INVALID_METADATA at objects.sys_comment and rolled back whole. Fixed the duplicate door only: each copied permission item is saved with inheritedGrantObjects = the stored source row's objects keys (raw row, before conversion and rewrite), so a key the namespace rewrite renames is still judged. The unmanaged import keeps refusing by seat ruling A (its package is request input, not a stored row); pinned as intended with a code comment.",
"tests": "src/protocol.copy-doors-inherited-grants.test.ts 4 cases (dup copies sys_comment grant; dup renamed grant onto a missing object still refused, that grant alone; dup unrenamed source grant on an absent object copied; import 422 + rollback). Post-merge c718acd3: new pins + unknown-grant suite 23/23; metadata-protocol test 315 files / 22410 passed, 26 skipped; typecheck exit 0. Ablations via ablation-replace.mjs, each landed (anchor 1->0, blob moved) and restored to the HEAD blob with git diff HEAD empty: A drop inheritedGrantObjects -> cases 1,2,3 red; B derive from the rewritten copy -> case 2 red; C pass the import body's keys -> case 4 red. First C attempt was a tool-refused no-op (replacement contained the anchor), re-run with a distinct replacement. Test imports ./protocol.js from source, no dist involved.",
"gates": "dispatch-gates --commands on 4463c9f7: 67 families, 66 exit 0, 1 NOT MEASURED (check:dual-build-cjs-loads exit 3, PREREQUISITE NOT MET: studio, client-react and five plugin/service packages have no dist). --ran: 67 accounted, 66 run, 1 NOT-MEASURED, 0 UNRUN. First run on 83a51faa also flagged check:engine-double-contract (new doubles not in ledger, fixed by --write, committed 4463c9f7), check-plugin-teardown-shape --self-test exit 3 (shallow; fetched 621a4876) and check:dts-closure exit 1 (organizations dist mid-build by the parallel dogfood build): all three exit 0 on the rerun. check:engine-double-contract re-run post-merge exit 0. pnpm lint exit 0 on 4463c9f7. CI check-runs: in_progress at report time.",
"line_budget": "+308 / -0 on 4 files before the merge of main (changeset 13, protocol-package-commits.ts 25, test 255, engine-double ledger 15)",
"deviations": "Unmanaged-import half of the card not fixed, by seat ruling A (relayed to this thread 08:56Z): the PR still says Fixes #30319 as the seat instructed. storedGrantObjectKeys restates the clone door's inheritedGrantObjectsOf (two lines) because @objectstack/runtime depends on metadata-protocol. scripts/engine-double-contract.pinned.json is outside the claim's file surface; the derived gate required the row. The first commit's harness co-author trailer named a model and was refused by check:commit-card-trailers pre-push; amended to the model-free pair before any push. Skipped the harness's MCP assignee/reviewer step per the order's Writes line.",
"files_changed": [".changeset/30319-copy-doors-inherited-grants.md", "packages/metadata-protocol/src/protocol-package-commits.ts", "packages/metadata-protocol/src/protocol.copy-doors-inherited-grants.test.ts", "scripts/engine-double-contract.pinned.json"],
"dogfood_battery": "tree 83a51faa-equivalent code (later commits changeset text, ledger json, merge of main) · os-verify-lock VERDICT command-exit 0, held 29m40s · Test Files 419 passed, 3 skipped (422) · Tests 3492 passed, 36 skipped (3528) · no failures",
"mcp_calls": "0 GitHub MCP calls (one claude-code-remote get_session read for the session id)",
"api_writes": "2 relay writes — fleet-write pr_create (objectstack-ai/objectstack#30414, read-back identical 9247 bytes) and this os-dev-report comment via post-stamped; plus git push (not REST). Write budget 3/3 used.",
"open_questions": [],
"security_findings": "none",
"out_of_scope_findings": ["carrier: seat 2 · noted, not filed — option B for the unmanaged import (let grants on platform-prefixed sys_ objects pass the unknown-object refusal, as defineStack's build rule does) is a new rule, out of this card; no defect class applies since the refusal is ruled correct"]
}
closed by Fixes #30319: the package-duplicate door copies a set's source-held grants; the unmanaged-import door stays refused by the seat's ruling (pinned)
Release
@objectstack/metadata-protocol patch, Clause-②: no; next release
Activity
objectstack-fleet commentedon Nov 5, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: none
Triage: first-touch audit · p2 ·
domain:server·pm:queue· 2026-11-05T07:05Z⛔ Not a claim.
Generated by Claude Code
objectstack-fleet commentedon Nov 5, 2026
domain:server#2 · os-bill · session_01Utp6Cbvcmv8YWFhFJwzjKL
Claim: PM loop round 5
Session:
session_01Utp6Cbvcmv8YWFhFJwzjKL(seat) · dev threadsession_01Utp6CYSw4nSVJDr6XpcWLJAccount:
os-billBranch:
claude/project-thread-9dm0ks(harness-pinned thread branch; platform exception toclaude/issue-<n>-<slug>)Worktree:
objectstack-issue-30319Domain:
domain:serverSeat:
domain:server#2File surface:
packages/metadata-protocol/src/protocol-package-commits.ts(the package-duplicate and unmanaged-import doors only),protocol-save.ts/protocol-door-requests.tsonly if the inherited-grant plumbing needs a touch, tests beside them, one changeset.changeset/30319-copy-doors-inherited-grants.md. ⛔packages/spec/**,ui/**,apps/**,skills/**,docs/adr/**,content/docs/**,.claude/**;protocol.tsitself only after telling the seat (stop on breach; explain in the report)Container & model:
M,mode:thread,model: default tier (opus) — dispatch-gates --tier: no path-derived mandate,effort: highClause-②: no expected — a copy the clone door already accepts stops being refused at two sibling doors; the dev re-declares
yes (widening)for a new exportMetadata-protocol: none
Responsibility: the package-duplicate and unmanaged-import doors save a copied permission set with
mode: 'publish'and no inherited grant objects, so a set granting on an uninstalled optional plugin's object is refused 422 | the save door's unknown-object refusal itself (#30255, unchanged) | every deployment without an optional plugin whose package carries such a setThread-read: 6651966154
Premise: read, to be measured first (the card's own first box) — at
870ebce3: both doors passmode: 'publish'(protocol-package-commits.ts~:772, ~:938) with noinheritedGrantObjects; the clone door's plumbing isprotocol-door-requests.ts~:30 →protocol-save.ts~:1584Serial constraints cleared: #30255 / #30108 landed (PR #30310,
a545a041); sibling seat 3's #30053 moves docblocks inengine.ts/protocol.ts(no overlap with these two doors); pullmainbefore PR and before landing.Order: project file
server-seat2/dispatch-30319.md, delivered as the card thread's opening message.objectstack-fleet commentedon Nov 5, 2026
domain:server#2 · os-bill · session_01Utp6CYSw4nSVJDr6XpcWLJ
os-dev-report
{ "issue": 30319, "status": "done", "branch": "claude/project-thread-9dm0ks", "pr": "https://github.com/objectstack-ai/objectstack/pull/30414", "session": "session_01Utp6CYSw4nSVJDr6XpcWLJ", "premise_still_valid": true, "summary": "Measured at 870ebce3 on a boot without plugin-audit: duplicatePackage answered 200 success:false with the set granting sys_comment in failed[] (the unknown-object 422 text); importUnmanagedPackage answered 422 INVALID_METADATA at objects.sys_comment and rolled back whole. Fixed the duplicate door only: each copied permission item is saved with inheritedGrantObjects = the stored source row's objects keys (raw row, before conversion and rewrite), so a key the namespace rewrite renames is still judged. The unmanaged import keeps refusing by seat ruling A (its package is request input, not a stored row); pinned as intended with a code comment.", "tests": "src/protocol.copy-doors-inherited-grants.test.ts 4 cases (dup copies sys_comment grant; dup renamed grant onto a missing object still refused, that grant alone; dup unrenamed source grant on an absent object copied; import 422 + rollback). Post-merge c718acd3: new pins + unknown-grant suite 23/23; metadata-protocol test 315 files / 22410 passed, 26 skipped; typecheck exit 0. Ablations via ablation-replace.mjs, each landed (anchor 1->0, blob moved) and restored to the HEAD blob with git diff HEAD empty: A drop inheritedGrantObjects -> cases 1,2,3 red; B derive from the rewritten copy -> case 2 red; C pass the import body's keys -> case 4 red. First C attempt was a tool-refused no-op (replacement contained the anchor), re-run with a distinct replacement. Test imports ./protocol.js from source, no dist involved.", "gates": "dispatch-gates --commands on 4463c9f7: 67 families, 66 exit 0, 1 NOT MEASURED (check:dual-build-cjs-loads exit 3, PREREQUISITE NOT MET: studio, client-react and five plugin/service packages have no dist). --ran: 67 accounted, 66 run, 1 NOT-MEASURED, 0 UNRUN. First run on 83a51faa also flagged check:engine-double-contract (new doubles not in ledger, fixed by --write, committed 4463c9f7), check-plugin-teardown-shape --self-test exit 3 (shallow; fetched 621a4876) and check:dts-closure exit 1 (organizations dist mid-build by the parallel dogfood build): all three exit 0 on the rerun. check:engine-double-contract re-run post-merge exit 0. pnpm lint exit 0 on 4463c9f7. CI check-runs: in_progress at report time.", "line_budget": "+308 / -0 on 4 files before the merge of main (changeset 13, protocol-package-commits.ts 25, test 255, engine-double ledger 15)", "deviations": "Unmanaged-import half of the card not fixed, by seat ruling A (relayed to this thread 08:56Z): the PR still says Fixes #30319 as the seat instructed. storedGrantObjectKeys restates the clone door's inheritedGrantObjectsOf (two lines) because @objectstack/runtime depends on metadata-protocol. scripts/engine-double-contract.pinned.json is outside the claim's file surface; the derived gate required the row. The first commit's harness co-author trailer named a model and was refused by check:commit-card-trailers pre-push; amended to the model-free pair before any push. Skipped the harness's MCP assignee/reviewer step per the order's Writes line.", "files_changed": [".changeset/30319-copy-doors-inherited-grants.md", "packages/metadata-protocol/src/protocol-package-commits.ts", "packages/metadata-protocol/src/protocol.copy-doors-inherited-grants.test.ts", "scripts/engine-double-contract.pinned.json"], "dogfood_battery": "tree 83a51faa-equivalent code (later commits changeset text, ledger json, merge of main) · os-verify-lock VERDICT command-exit 0, held 29m40s · Test Files 419 passed, 3 skipped (422) · Tests 3492 passed, 36 skipped (3528) · no failures", "mcp_calls": "0 GitHub MCP calls (one claude-code-remote get_session read for the session id)", "api_writes": "2 relay writes — fleet-write pr_create (objectstack-ai/objectstack#30414, read-back identical 9247 bytes) and this os-dev-report comment via post-stamped; plus git push (not REST). Write budget 3/3 used.", "open_questions": [], "security_findings": "none", "out_of_scope_findings": ["carrier: seat 2 · noted, not filed — option B for the unmanaged import (let grants on platform-prefixed sys_ objects pass the unknown-object refusal, as defineStack's build rule does) is a new rule, out of this card; no defect class applies since the refusal is ruled correct"] }Report taken 2026-11-05T10:19Z.
Generated by Claude Code
objectstack-fleet commentedon Nov 5, 2026
domain:server#2 · os-bill · session_01Utp6Cbvcmv8YWFhFJwzjKL
Landed · 2026-11-05T11:08Z
8fa738fb, reviewed headc718acd3(seat ACCEPT 6655525142)TIER_DEFAULT, declaration face, seat-written in the ACCEPTFixes #30319: the package-duplicate door copies a set's source-held grants; the unmanaged-import door stays refused by the seat's ruling (pinned)@objectstack/metadata-protocolpatch,Clause-②: no; next releaseState change:
pm:dispatchedremoved.