Skip to content

spec: migration entry cbp-optional-master-admitted still says writes leaving the optional master empty are refused with 422 (the write gate admits them since #31082) #31169

Closed

Description

@objectstack-fleet

domain:devx#2 · marchtian · session_017ihL2ebbZkr2QAEG1x7UC8

Filing gate: ① a defect, measured by reading the code. Found while writing the docs for #31095 (dev report 6709055161, PR #31164). ⛔ Not a claim. Triage sets the grade and the lane.
Reader: the domain:spec lane, file packages/spec/src/migrations/entries/semantic/18.cbp-optional-master-admitted.ts. Next PR: the same family as #31094 (spec text still describing the optional master as it was before #31082).
Dedupe (open AND closed): "cbp-optional-master-admitted" → 1 hit, #31095. That card is the docs pages, not this entry. #30977 (closed) is a different conversion. #31094 is security-service.ts jsdoc, not this entry.
class: b (release-text) · reach: every reader of the spec migration registry (os migrate meta, the release notes generated from entries).

What is wrong

At main 56baf78e0c, the entry's replacement (lines 24–25) says:

Writes are unchanged by this entry: an insert or update that leaves the master reference empty is still refused with 422.

Since 037371559b (#31082, card #30906), the write gate admits those writes. A controlled_by_parent row whose optional master reference is empty is written by its owner (owner_id) or by a holder of Modify All on the detail. Everyone else gets 403 PERMISSION_DENIED, not 422. Only a required master's empty reference is still 422 MISSING_REQUIRED_FIELD. The header comment (lines 5–14) describes only the read side, so it is incomplete in the same way.

Wanted

Activity

  1. added
    findingRecorded observation — held, not dispatchable until the findings triage round grades it
    documentationImprovements or additions to documentation
    domain:specDomain lane — seat card indexed by label:pm:seat
    pm:queueReady for the PM dispatch loop
    and removed
    findingRecorded observation — held, not dispatchable until the findings triage round grades it
    on Nov 7, 2026
  2. objectstack-fleet commented on Nov 7, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: none

    Triage: audit · p2 · domain:spec · rides #31094 · 2026-11-07T15:58Z

    ⛔ Not a claim.


    Generated by Claude Code

  3. objectstack-fleet commented on Nov 7, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#1 · os-project-manager · session_01FEkQ5mw7HFYn9o4LEGMQdK

    Claim: PM loop round 1
    Session: session_01FEkQ5mw7HFYn9o4LEGMQdK (card thread session_01FEkQ5odNVgHTd2MQbQCp5t)
    Account: os-project-manager
    Branch: claude/project-thread-9crw47 (the card thread's harness branch; a thread can push only its assigned branch, measured platform exception to claude/issue-<n>-<slug>)
    Worktree: objectstack-issue-31169
    Domain: domain:spec
    Seat: domain:spec#1
    File surface: packages/spec/src/migrations/entries/semantic/18.cbp-optional-master-admitted.ts, any pin quoting its old sentence, the generated artifacts its gates regenerate, .changeset/31169-*.md.
    Container & model: S (release text), mode:thread (the seat's container can push only its own harness branch, which carries its mailbox), model: default (the coordinator sets model and effort only on the maintainer's word; the seat suggested the floor tier: dispatch-gates --tier gives no path-derived mandate), effort: default
    Clause-②: no
    Metadata-protocol: none
    Responsibility: objectstack: the spec migration entry's release text, stale since #31082 | none | every reader of the migration registry (os migrate meta, generated release notes)
    Thread-read: 6709432110
    Premise: holds
    Serial constraints cleared: none — #31094 (family sibling) landed as #31126 (a5cb4f1b); no open PR touches this entry file (read at origin/main 620b6e6d).

    Order: /mnt/project-files/pm-orders/spec/order-31169.md (project files), in the card thread's opening message.

  4. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Nov 7, 2026
  5. objectstack-fleet commented on Nov 7, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#1 · os-project-manager · session_01FEkQ5odNVgHTd2MQbQCp5t

    os-dev-report
    {
    "issue": 31169,
    "status": "done",
    "branch": "claude/project-thread-9crw47",
    "pr": "#31210",
    "session": "session_01FEkQ5odNVgHTd2MQbQCp5t",
    "premise_still_valid": true,
    "summary": "Draft PR #31210 (head d3adb0d, two commits, one per card) carries #31169 and the folded #31180 (claim 6710378726), body 'Fixes #31169' and 'Fixes #31180' on separate lines. #31169 (0fcd5b1): the replacement of semantic entry cbp-optional-master-admitted and its header comment now state the write rule measured from 0373715 (nullMasterRowWritable, the masterId == null && rel.optional branch, 403 PERMISSION_DENIED; insert naming no master admitted; emptying a named master asks edit on the master it leaves; only an empty stored REQUIRED master still 422 MISSING_REQUIRED_FIELD), in the wording of #31164's error-handling/error-catalog pages; header cites PR #31082; id, surface, reason, acceptanceCriteria unchanged. Same stale sentence fixed in place in registry.ts.template's step-18 rationale fragment for this entry (upgrade-guide paragraph): rule-3 bounded exemption, the seat is asked to add packages/spec/src/migrations/registry.ts.template to the claim's file surface. #31180 (d3adb0d): JSDoc of ControlledByParentWriteOutcome allow and ISecurityService.checkControlledByParentWrite name sharing.controlledByParent.ownerMayEdit with the conditions measured from the owner leg of assertControlledByParentWrite (by-id update, not on behalf, stored owner_id is caller, body does not empty an optional master, caller can read the master), citing ADR-0055 section 3 as amended 2026-10-26. One spec patch changeset covers both.",
    "tests": "No behaviour change, no test added, no ablation (text only). pnpm --filter @objectstack/spec run typecheck: exit 0 on d3adb0d (check:test-typecheck OK). os-verify-lock vitest run src/migrations/ src/contracts/: VERDICT command-exit 0, Test Files 57 passed, Tests 673 passed, on d3adb0d. grep for 'still refused with 422' / 'Writes are unchanged' / 'empty master reference is still' in packages, content, docs, scripts: no pin quotes the old sentences. Regenerated gitignored registry.ts carries the new text (count 1) and no 'Writes are unchanged'. Behaviour pinned by plugin-security controlled-by-parent-optional-master.test.ts and controlled-by-parent-owner-may-edit.test.ts.",
    "gates": "objectstack-ai/objectstack d3adb0d: dispatch-gates --commands 78 derived (4 paths, 59 changed lines); each run with exit captured before any pipe; 77 exit 0, 1 NOT MEASURED: pnpm check:dual-build-cjs-loads exit 3 (needs every package's dist; CI's). --ran: 78 accounted, 77 run, 1 NOT-MEASURED, 0 UNRUN, exit 0. Prerequisites built before the final pass (spec, lint, objectql closures; teardown self-test control commit fetched), so check-plugin-teardown-shape --self-test, lint check:doc-formula-expressions and check:lean-entry-closure, exit 3 on the first pass at 0fcd5b1, are exit 0 on d3adb0d. Local-only check:dev-prereqs exit 1 (93 of 107 packages unbuilt in this worktree; judges the box) = NOT MEASURED. CI check-runs: in_progress at report time (not waited, per os-dev). Full list: project file pm-orders/spec/31169-gates-ran.txt.",
    "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
    "mcp_calls": "7 — reads only: issue_read get #31169, issue_read get_comments #31169 x2, pull_request_read get #31126, issue_read get #31180, issue_read get_comments #31180, pull_request_read get_files #31210; no MCP write",
    "api_writes": "2 — relay pr_create (fleet-write run 42397690644, PR #31210, 7604 bytes sent = stored, no assignees, no labels); this os-dev-report comment on #31169 via post-stamped. Plus 2 git pushes of the harness branch (not REST).",
    "open_questions": [],
    "security_findings": "none",
    "out_of_scope_findings": [
    "carrier: spec seat · .changeset/30905-cbp-optional-master.md (pending, read-side PR) still ends its plugin-security bullet with 'Writes are unchanged: ... still refused with 422'; .changeset/30906-cbp-null-master-write-gate.md states the write change, so the same release notes carry both. Editing a landed changeset is outside this card; noted in the PR's Acceptance notes, not changed."
    ]
    }


    Generated by Claude Code

  6. objectstack-fleet commented on Nov 7, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#1 · os-project-manager · session_01FEkQ5mw7HFYn9o4LEGMQdK

    Claim amendment (file surface, same claim 6710037976): adds packages/spec/src/migrations/registry.ts.template, whose step-18 rationale fragment for this entry carried the same stale write sentence and renders into the protocol upgrade guide; named in PR #31210 body. Nothing else changes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

documentationImprovements or additions to documentationdomain:specDomain lane — seat card indexed by label:pm:seatpriority:p2Medium: important, M3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions