Repository navigation
Freeze note on assertControlledByParentWrite — the guard is the sole enforcement for three authorable master-reference shapes until the #8772 ramp completes #9137
Description
Activity
os-project-manager commented
on Aug 16, 2026 CollaboratorMore actionsTriage:
domain:identityadded (lands inpackages/plugins/plugin-security, as the card states; single-producer rule),pm:queuekept, typeTask.Guard presence re-verified on
origin/mainthis round (assertControlledByParentWritelive insecurity-plugin.ts). S-grade mechanical: load-bearing comment + optional pin, no behaviour change. Ordering from the #8772 ruling: this slice lands first (before or with the builder-force sibling #9138) — identity seat can dispatch immediately.Size/model suggestion: S mechanical, sonnet.
Generated by Claude Code
os-project-manager commented
on Aug 17, 2026 CollaboratorMore actionsClaiming this card. Working branch
claude/issue-9137-guard-freeze-note, sessionsession_01Y26DJEHSBhhAQ6wwfsHNza.
Generated by Claude Code
Generated by Claude Code
- added a commit that references this issue
on Aug 17, 2026 os-project-manager commented
on Aug 17, 2026 CollaboratorMore actionsos-dev-report
{ "issue": 9137, "status": "done", "branch": "claude/issue-9137-guard-freeze-note", "pr": "https://github.com/objectstack-ai/objectstack/pull/9199", "premise_still_valid": true, "summary": "Added the #8772 Direction-4 freeze note at assertControlledByParentWrite's absent-master-FK branch (security-plugin.ts) stating the guard is the sole enforcement point for the three authorable controlled_by_parent master shapes (master_detail without required; required+readonly; required+system) until #9138 (builder-force) and #9139 (lint-at-v18) both land. Comment-only, no behaviour change. The card's own re-check anticipated a stale premise and it was: #8688 is NOT 'open and unruled' -- it was ruled and merged via PR #8879, which already landed a CONDITIONAL stand-down keyed on a new omissionRefusedByValidation predicate, so the guard is not flatly unconditional any more, though it remains unconditional for exactly the three target shapes. The note and PR body are written against that corrected framing: they protect against widening the already-landed stand-down, not against a still-hypothetical one. Also corrected an adjacent [#8959] comment in the same branch/paragraph that had itself gone stale, still claiming #8772 was 'open and unruled' (it was ruled and closed 2026-08-16) -- left as-is it would have directly contradicted the new freeze note one paragraph below it. Applied the bounded in-place exemption for that correction: same file, same defect class (stale #8772-ramp-status prose at this exact guard), mechanical fix pinned by the ruling comment itself (5306089973), no other claim on this file, no new verification surface -- named in the PR body. A pinned test asserting the guard refuses the absent-master insert for all three shapes already existed (PR #8879's it.each block in controlled-by-parent-sharing.test.ts), so per the card's 'check first' instruction no duplicate test was added.", "tests": "At final commit 1a67152fc (git rev-parse --short HEAD): pnpm --filter '@objectstack/plugin-security^...' build (dependency closure) -- green. pnpm --filter @objectstack/plugin-security typecheck (tsc --noEmit) -- exit 0. pnpm --filter @objectstack/plugin-security test -- 66 test files / 1279 tests, all passing (includes the pre-existing three-shape it.each pin). node scripts/check-cross-package-test-inputs.mjs, node scripts/check-test-source-alias.mjs, node scripts/check-type-source-resolution.mjs -- the three path-derived gates from node scripts/pm/dispatch-gates.mjs -- all green. node scripts/check-adr-anchors.mjs -- green (this file is ADR-0055 content-anchored; citation-based, unaffected by a comment-only edit). node scripts/check-nul-bytes.mjs -- clean. node scripts/check-i18n-bundles.mjs, after building @objectstack/cli (pnpm exec turbo run build --filter=@objectstack/cli) -- '9 package(s) -- all bundles in sync, no undeclared authoring keys', confirming the comment-only edit produced no i18n drift. skip-changeset label applied to the PR, read back afterward to confirm it settled: labels = [size/s, skip-changeset].", "open_questions": [], "out_of_scope_findings": [] }
Generated by Claude Code
os-project-manager commented
on Aug 17, 2026 CollaboratorMore actionsos-project-manager commented
on Aug 17, 2026 CollaboratorMore actions(Supersedes comment 5310802117, which opened with the plain-text fallback instead of this marker — the marker survives here, confirmed by the probe comment just above. Same JSON, unchanged.)
{ "issue": 9137, "status": "done", "branch": "claude/issue-9137-guard-freeze-note", "pr": "https://github.com/objectstack-ai/objectstack/pull/9199", "premise_still_valid": true, "summary": "Added the #8772 Direction-4 freeze note at assertControlledByParentWrite's absent-master-FK branch (security-plugin.ts) stating the guard is the sole enforcement point for the three authorable controlled_by_parent master shapes (master_detail without required; required+readonly; required+system) until #9138 (builder-force) and #9139 (lint-at-v18) both land. Comment-only, no behaviour change. The card's own re-check anticipated a stale premise and it was: #8688 is NOT 'open and unruled' -- it was ruled and merged via PR #8879, which already landed a CONDITIONAL stand-down keyed on a new omissionRefusedByValidation predicate, so the guard is not flatly unconditional any more, though it remains unconditional for exactly the three target shapes. The note and PR body are written against that corrected framing: they protect against widening the already-landed stand-down, not against a still-hypothetical one. Also corrected an adjacent [#8959] comment in the same branch/paragraph that had itself gone stale, still claiming #8772 was 'open and unruled' (it was ruled and closed 2026-08-16) -- left as-is it would have directly contradicted the new freeze note one paragraph below it. Applied the bounded in-place exemption for that correction: same file, same defect class (stale #8772-ramp-status prose at this exact guard), mechanical fix pinned by the ruling comment itself (5306089973), no other claim on this file, no new verification surface -- named in the PR body. A pinned test asserting the guard refuses the absent-master insert for all three shapes already existed (PR #8879's it.each block in controlled-by-parent-sharing.test.ts), so per the card's 'check first' instruction no duplicate test was added.", "tests": "At final commit 1a67152fc (git rev-parse --short HEAD): pnpm --filter '@objectstack/plugin-security^...' build (dependency closure) -- green. pnpm --filter @objectstack/plugin-security typecheck (tsc --noEmit) -- exit 0. pnpm --filter @objectstack/plugin-security test -- 66 test files / 1279 tests, all passing (includes the pre-existing three-shape it.each pin). node scripts/check-cross-package-test-inputs.mjs, node scripts/check-test-source-alias.mjs, node scripts/check-type-source-resolution.mjs -- the three path-derived gates from node scripts/pm/dispatch-gates.mjs -- all green. node scripts/check-adr-anchors.mjs -- green (this file is ADR-0055 content-anchored; citation-based, unaffected by a comment-only edit). node scripts/check-nul-bytes.mjs -- clean. node scripts/check-i18n-bundles.mjs, after building @objectstack/cli (pnpm exec turbo run build --filter=@objectstack/cli) -- '9 package(s) -- all bundles in sync, no undeclared authoring keys', confirming the comment-only edit produced no i18n drift. skip-changeset label applied to the PR, read back afterward to confirm it settled: labels = [size/s, skip-changeset].", "open_questions": [], "out_of_scope_findings": [] }
Generated by Claude Code
Generated by Claude Code
- added a commit that references this issue
on Aug 17, 2026 - added a commit that references this issue
on Sep 1, 2026
Provenance
Slice A (Direction 4) of the #8772 maintainer ruling (2026-08-16, comment 5306089973): Direction 2 now + Direction 1 at v18 + Direction 4's sentence immediately. Carved into its own card on the maintainer's instruction of 2026-08-16 (PM chat, verbatim: 「接受你的建议,开新卡,现有的可以关闭?」 confirming the three-way split), recorded by PM session
session_01NYgmGheCzM6NrHZN436Cxf. Intended lane:domain:identity(lands inplugin-security) —domain:*left for the triage seat per the single-producer rule.This is the first slice to land — the ruling says the note should land before or with the first code slice, because it is what protects #8688's proposed route during the ramp.
The work (S-grade, mechanical)
Add a load-bearing comment at
assertControlledByParentWrite(packages/plugins/plugin-security/src/security-plugin.ts) stating:controlled_by_parentmaster-reference shapes (master_detailwithoutrequired;required: true+readonly;required: true+system— the latter two skipped byrecord-validator.ts's provenance-flagcontinue).fields[]and a[Security]message — while the same field, present-but-unresolvable, answers 400 VALIDATION_FAILED withfields[](#7474 residual, 17.0.0 GA) #8688 proposes — until the Acontrolled_by_parentobject may declare its master reference withoutrequired, so the master-access guard is the only thing preventing an unreachable orphan detail row #8772 ramp completes: (a) the authoring builder forcesrequired: true(sibling card), and (b) lint refuses the shape at the v18 boundary (sibling card). Standing it down earlier mints a detail row with a null master FK that thecontrolled_by_parentread filter (fk IN (readable masters)) can never match — unreadable by anyone,422 MISSING_REQUIRED_FIELDon every later by-id write.controlled_by_parentobject may declare its master reference withoutrequired, so the master-access guard is the only thing preventing an unreachable orphan detail row #8772's five-shape measurement table.No behaviour change; comment + (optionally) one pinned test asserting the guard refuses the absent-master insert for the three shapes, if not already pinned.
Re-check before acting
git grep -n "assertControlledByParentWrite" origin/main -- packages/plugins/plugin-securityfields[]and a[Security]message — while the same field, present-but-unresolvable, answers 400 VALIDATION_FAILED withfields[](#7474 residual, 17.0.0 GA) #8688 still open/unruled.Refs: #8772 (ruling + measurement) · #8688 (the route this note protects) · sibling cards: builder-force (spec), lint-at-v18 (devx).