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
spec: security-service contract jsdoc still describes a controlled_by_parent master as always required (optional master, cards #30905/#30906) #31094
Filing gate: carry-over item 2 on #30907 (comment 6702057019, from card 2's seat): the packages/spec jsdoc is spec-lane work and is not edited from the skills lane. Wording measured by the #30907 card thread (PR #31092 body) and confirmed by that PR's contract review (6703355433). ⛔ Not a claim. Triage sets the grade and the lane.
class: c · reach: every reader of the SecurityService contract's refusal reasons and write check.
What is owed
packages/spec/src/contracts/security-service.ts on main719a502b. Since #30905 / #30906 (maintainer ruling 「A」, PR #31082) a controlled_by_parent object may have one OPTIONAL master; a row naming none is read by its owner or View All, and written by its owner or Modify All on the detail.
L342–348, master_chain. Says the leg refuses when a master above is itself controlled_by_parent and has an empty master reference. Owed: the leg also refuses the record itself when its optional master reference is empty and the principal neither owns it (owner_id) nor holds Modify All on its object; a master above whose optional master is empty ends the chain under that row's owner rule. Only a required master's empty reference above the record is the chain-walk refusal the current text describes.
L377–378, master_reference_missing. Says "the record's stored master reference is empty (422 MISSING_REQUIRED_FIELD)". Owed: "the record's stored required master reference is empty"; an empty optional master reference is not this reason (the check answers allow, or deny on leg master_chain).
L1064–1065, checkControlledByParentWrite. Says "A by-id write to a controlled_by_parent record requires EDIT access to its master." Owed: "…, or, where its optional master reference is empty, ownership of the record or Modify All on its object (ADR-0055 §3 as amended 2026-11-07)".
Re-read the write gate (packages/plugins/plugin-security/src/security-plugin-cbp-write-gate.ts) before rewording; jsdoc only, no behaviour change.
Level:packages/spec jsdoc: an '@objectstack/spec': patch changeset (docs-only), Clause-②: no, Metadata-protocol: none (triage to confirm).
p2: the contract's refusal-reason text is what readers of the security write check rely on. Lane domain:spec, jsdoc only, no behaviour change. finding removed, pm:queue.
{
"issue": 31094,
"status": "done",
"branch": "claude/project-thread-67i8vs",
"pr": "https://github.com/objectstack-ai/objectstack/pull/31126",
"head": "6e4fd170a",
"session": "session_017ihL2etQ7BmrJuMddPx75W",
"premise_still_valid": true,
"summary": "JSDoc-only change in packages/spec/src/contracts/security-service.ts plus a spec patch changeset. Card items 1-3 applied as owed, each checked against security-plugin-cbp-write-gate.ts and controlled-by-parent-optional-master.test.ts: the code agrees with the card's owed text. Same-file sentences the ruling also made false were corrected in place (see deviations). The ⛔ lines at the end of the member docblock are untouched.",
"tests": "No behaviour change, no test added. Behaviour described is pinned by plugin-security controlled-by-parent-optional-master.test.ts (checkControlledByParentWrite describe blocks, required-master master_reference_missing control).",
"gates": "Local, on head 6e4fd170a after a packages/** build (verify lock VERDICT command-exit 0): all 74 commands from dispatch-gates --commands :: exit 0. --ran reconciliation: 74 derived, 74 run, 0 NOT-MEASURED, 0 UNRUN (exit 0). check:docs: 242 generated files in sync. eslint --no-inline-config on the touched file :: exit 0 (spec has no lint script). First pass (before the build) had 4 exit-3 prerequisite misses, cleared by fetching the teardown-shape fixture commit and building. CI on 6e4fd170a: 64 check-runs, 0 not success/skipped, including Lint & Repo Gates, TypeScript Type Check, Test Core, Build Core, Governed Surface Queue Guard, Lint UI (skipped), Type Check UI, Test UI, Build & E2E UI, Live E2E UI, Check Changeset.",
"line_budget": "+52 / -16 in security-service.ts, changeset +15; under the 3000-line threshold",
"dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
"deviations": [
"Bounded in-place fix (same defect class, same file, no other claim, same gate family): beyond items 1-3, also corrected ControlledByParentWriteDenialLeg's intro sentence, ControlledByParentWriteOutcome's allow bullet, the member's 'answers the master check alone' sentence and its empty-permission-set bullet (a principal with no sets answers on master_chain, not object_permission, for a record whose optional master is empty). Named in the PR body.",
"First commit was made with core.hooksPath overridden by mistake; the repo's pre-commit (regen-pending) and pre-push (commit-card-trailers) were then run by hand on it, both exit 0; later commits ran the hooks normally."
],
"files_changed": [
"packages/spec/src/contracts/security-service.ts",
".changeset/31094-security-service-optional-master-jsdoc.md"
],
"open_questions": [],
"out_of_scope_findings": [
"class: b · reach: contract text read by every consumer of ISecurityService.checkControlledByParentWrite · evidence: ControlledByParentWriteOutcome's allow bullet says every leg passes on every master, but the write gate's ownerMayEdit opt-in leg (ADR-0055 §3 amendment 2026-10-26; security-plugin-cbp-write-gate.ts, the by-id update owner branch) resolves allow for the row's owner with only READ on the master; the spec file never mentions the opt-in. Pre-existing, found by the Fable review. Seam: spec:ControlledByParentWriteOutcome.allow → runtime:assertControlledByParentWrite ownerMayEdit branch · dedupe words: ownerMayEdit, checkControlledByParentWrite, allow, jsdoc, security-service"
],
"mcp_calls": "0",
"api_writes": "3 — pr_create (relay fw-20261107T132650Z-007ccf, PR #31126, assignee marchtian); comment on PR #31126 (Fable verdict 6707550458, post-stamped); this report comment (post-stamped)",
"security_findings": "none",
"fable_review": "PR comment 6707550458: R1 on 45406927 PASS (1 should-fix + 2 nits applied, 1 nit out of scope); delta on e6e69d53 PASS (1 nit, rewrap, applied in 6e4fd170a). Verdict on 6e4fd170a: PASS."
}
merged 2026-11-07T16:36:05Z through the queue, merge commit a5cb4f1bf03293ebbe8033ba4d813bf940575d53, reviewed head 6e4fd170a (contract review PASS + ACCEPT on that head)
card
closed completed by Fixes
State: pm:dispatched removed. Should-fix follow-up filed: #31180 (ownerMayEdit opt-in missing from the contract).
Activity
objectstack-fleet commentedon Nov 7, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: none
Triage: audit · p2 ·
domain:spec· 2026-11-07T06:54Z⛔ Not a claim.
packages/spec/src/contracts/security-service.tsstill describes themaster_chainandmaster_reference_missingrefusal reasons for a required-only master (L342–348, L377–378), after PR feat(security, verify): a controlled_by_parent row with no master is written by its owner or by Modify All on the detail #31082 admitted an optional master (ruling A, controlled_by_parent admits an optional master (1/3): spec, lint and the read owner branch: a null-master detail row is readable by its owner only #30905 / controlled_by_parent admits an optional master (2/3): the write gate judges null-master rows (owner or modify-all), clearing a master needs edit on it, and the verify proof #30906). Wording measured by controlled_by_parent admits an optional master (3/3): docs and the authoring skills teach it instead of a copied owner field #30907's card thread and confirmed by PR docs(skills): teach controlled_by_parent with an optional master in the data skill, permission docs and ADR-0055 #31092's review.domain:spec, jsdoc only, no behaviour change.findingremoved,pm:queue.Generated by Claude Code
objectstack-fleet commentedon Nov 7, 2026
domain:spec#4 · marchtian · session_017ihL2eHDXrsKgGAUHq956U
Claim: PM loop round 1 · 2026-11-07T13:07Z
Session:
session_017ihL2etQ7BmrJuMddPx75W(card thread; dispatched by seat sessionsession_017ihL2eHDXrsKgGAUHq956U)Account:
marchtianBranch:
claude/project-thread-67i8vsWorktree: the card thread's own container checkout
Domain:
domain:specSeat:
domain:spec#4File surface:
packages/spec/src/contracts/security-service.ts(jsdoc only) + one.changeset/*.mdContainer & model:
XS docs card,mode:thread,model: default tier (dispatch-gates --tier: no path-derived mandate; floor sonnet · default opus · ceiling fable), reason: jsdoc-only, no behaviour change; full Fable review of the diff before ACCEPT per the maintainer's standing spec rule,effort: mediumClause-②: no
Metadata-protocol: none
Responsibility: n/a — not a defect card (contract prose lagging PR #31082)
Thread-read: 6703612303
Premise: holds
Serial constraints cleared: none (sibling #31099 is file-disjoint)
objectstack-fleet commentedon Nov 7, 2026
domain:spec#4 · marchtian · session_017ihL2etQ7BmrJuMddPx75W
os-dev-report
{ "issue": 31094, "status": "done", "branch": "claude/project-thread-67i8vs", "pr": "https://github.com/objectstack-ai/objectstack/pull/31126", "head": "6e4fd170a", "session": "session_017ihL2etQ7BmrJuMddPx75W", "premise_still_valid": true, "summary": "JSDoc-only change in packages/spec/src/contracts/security-service.ts plus a spec patch changeset. Card items 1-3 applied as owed, each checked against security-plugin-cbp-write-gate.ts and controlled-by-parent-optional-master.test.ts: the code agrees with the card's owed text. Same-file sentences the ruling also made false were corrected in place (see deviations). The ⛔ lines at the end of the member docblock are untouched.", "tests": "No behaviour change, no test added. Behaviour described is pinned by plugin-security controlled-by-parent-optional-master.test.ts (checkControlledByParentWrite describe blocks, required-master master_reference_missing control).", "gates": "Local, on head 6e4fd170a after a packages/** build (verify lock VERDICT command-exit 0): all 74 commands from dispatch-gates --commands :: exit 0. --ran reconciliation: 74 derived, 74 run, 0 NOT-MEASURED, 0 UNRUN (exit 0). check:docs: 242 generated files in sync. eslint --no-inline-config on the touched file :: exit 0 (spec has no lint script). First pass (before the build) had 4 exit-3 prerequisite misses, cleared by fetching the teardown-shape fixture commit and building. CI on 6e4fd170a: 64 check-runs, 0 not success/skipped, including Lint & Repo Gates, TypeScript Type Check, Test Core, Build Core, Governed Surface Queue Guard, Lint UI (skipped), Type Check UI, Test UI, Build & E2E UI, Live E2E UI, Check Changeset.", "line_budget": "+52 / -16 in security-service.ts, changeset +15; under the 3000-line threshold", "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm", "deviations": [ "Bounded in-place fix (same defect class, same file, no other claim, same gate family): beyond items 1-3, also corrected ControlledByParentWriteDenialLeg's intro sentence, ControlledByParentWriteOutcome's allow bullet, the member's 'answers the master check alone' sentence and its empty-permission-set bullet (a principal with no sets answers on master_chain, not object_permission, for a record whose optional master is empty). Named in the PR body.", "First commit was made with core.hooksPath overridden by mistake; the repo's pre-commit (regen-pending) and pre-push (commit-card-trailers) were then run by hand on it, both exit 0; later commits ran the hooks normally." ], "files_changed": [ "packages/spec/src/contracts/security-service.ts", ".changeset/31094-security-service-optional-master-jsdoc.md" ], "open_questions": [], "out_of_scope_findings": [ "class: b · reach: contract text read by every consumer of ISecurityService.checkControlledByParentWrite · evidence: ControlledByParentWriteOutcome's allow bullet says every leg passes on every master, but the write gate's ownerMayEdit opt-in leg (ADR-0055 §3 amendment 2026-10-26; security-plugin-cbp-write-gate.ts, the by-id update owner branch) resolves allow for the row's owner with only READ on the master; the spec file never mentions the opt-in. Pre-existing, found by the Fable review. Seam: spec:ControlledByParentWriteOutcome.allow → runtime:assertControlledByParentWrite ownerMayEdit branch · dedupe words: ownerMayEdit, checkControlledByParentWrite, allow, jsdoc, security-service" ], "mcp_calls": "0", "api_writes": "3 — pr_create (relay fw-20261107T132650Z-007ccf, PR #31126, assignee marchtian); comment on PR #31126 (Fable verdict 6707550458, post-stamped); this report comment (post-stamped)", "security_findings": "none", "fable_review": "PR comment 6707550458: R1 on 45406927 PASS (1 should-fix + 2 nits applied, 1 nit out of scope); delta on e6e69d53 PASS (1 nit, rewrap, applied in 6e4fd170a). Verdict on 6e4fd170a: PASS." }objectstack-fleet commentedon Nov 7, 2026
domain:spec#4 · marchtian · session_017ihL2eHDXrsKgGAUHq956U
Landed ·
domain:spec#4· 2026-11-07T16:36Za5cb4f1bf03293ebbe8033ba4d813bf940575d53, reviewed head6e4fd170a(contract review PASS + ACCEPT on that head)FixesState:
pm:dispatchedremoved. Should-fix follow-up filed: #31180 (ownerMayEditopt-in missing from the contract).