Skip to content

spec: a restriction profile cannot list the ADR-0031 containers (parallel, try_catch), devPlugins counts as code under allowCode, and the allowedFlowNodeTypes docblock omits the reader rules #31239

Closed

Description

@objectstack-fleet

domain:server#4 · marchtian · session_017ihL2dLQEXWGsE2SZ3Qn5F

Filing gate: ② contract gap in RestrictionProfileSchema (packages/spec/src/system/restriction-profile.zod.ts), found by its first reader, os validate --target (#31156 item 2, PR #31237, dev report 6711857510, open questions 1 and 3, out-of-scope finding 1). ⛔ Not a claim. Triage sets the grade and the lane; item 1 is a vocabulary choice and may need a ruling.
Reader: the spec seat (packages/spec/src/system/restriction-profile.zod.ts, packages/spec/src/automation/flow.zod.ts, packages/spec/src/kernel/unmanaged-install.ts).
Dedupe (open AND closed): restriction profile, RestrictionProfile, allowedFlowNodeTypes → only #31155 / #31156 (the parent cards).
reach: every environment that publishes a profile with allowCode: false, and every author who runs os validate --target against one; read from the code, not run.
class: c · type: Bug

维护者速读

限制配置的流程节点白名单只能写 FlowNodeAction 里的类型,但平台自带的 parallel / try_catch 容器节点不在其中,所以禁止代码的环境会把它们当成插件节点拒掉,且无法放行。另外仅本地使用的 devPlugins 也被算作代码,以及白名单字段的说明还缺读者规则一句。

What is wrong

  1. ADR-0031 containers cannot be listed. allowedFlowNodeTypes is an array of FlowNodeAction. parallel and try_catch are engine built-ins (@objectstack/service-automation src/builtin/parallel-node.ts, try-catch-node.ts) but not FlowNodeAction ids. The reader rule ruled in review 6710350208 (a type outside FlowNodeAction is governed by allowCode) rests on the premise that such a type exists only because a code plugin registered it. That premise is false for these two. Today os validate --target refuses them under allowCode: false (fail-closed, message says "outside the registry"), and no profile can allow them.
  2. devPlugins is code. UNMANAGED_INSTALL_KEY_DISPOSITIONS classifies devPlugins as code, and the reader uses that one table, so a stack with dev-only plugins is refused under allowCode: false although devPlugins never reaches a target.
  3. Docblock. The allowedFlowNodeTypes docblock does not state the reader rules (start/end are structural and always allowed; a script node is also subject to allowCode). The cloud control plane will read the spec, not the CLI's module header.

Expected

  • Item 1, options from the dev report: (B, recommended) the profile's node vocabulary gains the ADR-0031 container ids — derived from the LOOP/PARALLEL/TRY_CATCH_NODE_TYPE constants, or FlowNodeAction gains them — so the reader judges them by allowedFlowNodeTypes; (C) the reader treats them as always allowed like start/end (a second list). Until then the shipped behaviour (refuse) stands.
  • Item 2: decide whether the restriction reader should read devPlugins as code (it is the one table's classification; a carve-out belongs in spec, not in the CLI).
  • Item 3: one docblock sentence on allowedFlowNodeTypes.
  • The CLI reader (packages/cli/src/utils/restriction-profile.ts) follows in the same PR or a paired card; pins move with it.

Activity

  1. added
    domain:specDomain lane — seat card indexed by label:pm:seat
    findingRecorded observation — held, not dispatchable until the findings triage round grades it
    bugSomething isn't working
    pm:queueReady for the PM dispatch loop
    priority:p1High: required for production / M2
    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 · p1 · domain:spec · 2026-11-07T19:55Z

    ⛔ 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 · lane refill (p1), follow-up to this seat's PR #31191 schema and server seat 4's reader PR #31237
    Session: session_01FEkQ5mw7HFYn9o4LEGMQdK (card thread session_01FEkQ5kxRsYPLNnBt5AWYj1)
    Account: os-project-manager
    Branch: claude/project-thread-0phzyp (the card thread's harness branch)
    Worktree: the card thread's own checkout of claude/project-thread-0phzyp
    Domain: domain:spec
    Seat: domain:spec#1
    File surface: packages/spec/src/system/restriction-profile.zod.ts (docblock reader rules; a vocabulary change only if the maintainer picks option B), its test, the spec artifacts the gates regenerate; packages/cli/src/utils/restriction-profile.ts and its tests/pins (the reader moves in the same PR, per triage); root .changeset/. ⛔ packages/spec/src/kernel/unmanaged-install.ts (UNMANAGED_INSTALL_KEY_DISPOSITIONS does not change), ⛔ ui/**.
    Container & model: M, mode:thread, model: default (dispatch-gates --tier: no path-derived mandate; Clause-② widening → CONTRACT_REVIEW_TIER review by this seat before enqueue), effort: default
    Clause-②: yes
    Metadata-protocol: none
    Responsibility: objectstack: os validate --target refuses the engine's own parallel / try_catch containers and dev-only plugins under allowCode: false | none | an author validating a stack against a no-code environment profile
    Thread-read: 6712277659
    Premise: holds — the card's cites verified by triage 6712277659 on main; PR #31237 (the reader) is merged; no open PR touches a restriction-profile file at origin/main bdefd49f (all open PRs' file lists read).
    Serial constraints cleared: none — no open PR touches the surface.

    Shape: item 1 builds option C (the reader treats the two ADR-0031 containers as structural, always allowed like start/end; nodes inside still judged) while the maintainer's decision between C and B (vocabulary growth) is open in the seat thread; the PR is not readied before that answer. Item 2: seat ruling, the restriction reader does not read devPlugins as code (it never reaches a target), stated as a reader rule in spec, dispositions table unchanged. Item 3: the allowedFlowNodeTypes docblock states the reader rules. Order: /mnt/project-files/pm-orders/spec/order-31239.md.

  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_01FEkQ5mw7HFYn9o4LEGMQdK

    Claim amendment · 2026-11-07T20:44Z · to claim 6712686821 (same session, branch claude/project-thread-0phzyp).

    Item 2 (devPlugins) leaves this card: the card thread measured that os compile writes devPlugins into dist/objectstack.json and os package publish snapshots it into sys_package_version.manifest_json, so the order's stop condition held and the seat's carve-out ruling is withdrawn. Moved to #31264 (domain:server, p2): strip the key from the artifact first, then the reader carve-out. On this card the reader keeps reading devPlugins as code, and the docblock says so.

    This card's PR carries items 1 (option C, pending the maintainer's pick between C and B) and 3, and closes #31239 (Fixes #31239).

  6. objectstack-fleet commented on Nov 7, 2026

    @objectstack-fleet
    ContributorAuthor

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

    os-dev-report
    {
    "issue": 31239,
    "status": "done",
    "branch": "claude/project-thread-0phzyp",
    "pr": "#31277",
    "session": "session_01FEkQ5kxRsYPLNnBt5AWYj1",
    "premise_still_valid": true,
    "summary": "Item 1 built as option C, pending the maintainer's pick between C and B: the CLI restriction reader treats the ADR-0031 containers parallel / try_catch (from PARALLEL_NODE_TYPE / TRY_CATCH_NODE_TYPE) as structural like start / end, while every node in their regions is still judged; loop is already a FlowNodeAction id and stays judged by allowedFlowNodeTypes. Item 3: the allowedFlowNodeTypes docblock states the reader rules (JSDoc only, no shape or describe text change). Item 2 hit the order's stop condition: os compile writes devPlugins into dist/objectstack.json (only demoStaff is deleted at the artifact write) and os package publish snapshots that file into sys_package_version.manifest_json; the seat withdrew the carve-out and moved it to #31264 (claim amendment 6712791333), so the reader still reads devPlugins as code and the allowCode docblock says so. PR stays draft; it changes shape if the maintainer picks B.",
    "tests": "pnpm --filter @objectstack/cli exec vitest run --project unit: 401 files / 5665 tests passed (2 new cases in src/utils/restriction-profile.test.ts: containers allowed under allowCode false while inner notify nodes are refused at config.branches[0] / config.catch paths; loop judged by the list). pnpm --filter @objectstack/spec test: 821 files / 25964 passed, 1 todo. Typecheck exit 0 for spec and cli; spec check:test-typecheck OK. Ablation via scripts/ablation-replace.mjs on the rule-1 line (anchor 1 to 0, blob dbc0daaabec5 to 2b0aa2d61236): container case red, Tests 1 failed / 22 passed; restored blob equals HEAD dbc0daaabec5, git diff HEAD empty. CLI unit suite runs src, no dist leg. All on head 405b3d4.",
    "gates": "dispatch-gates --commands on head 405b3d4: 83 derived, 81 exit 0, 2 NOT MEASURED (check:dual-build-cjs-loads, check:i18n-coverage: exit 3 PREREQUISITE NOT MET, need every package dist; CI's). check-plugin-teardown-shape --self-test exit 3 on the shallow clone, exit 0 after fetching 621a487. --ran: 83 accounted, 81 run, 2 NOT-MEASURED, 0 UNRUN. check:generated: test-typecheck-debt.json read stale only from tsc dying under the default heap; check:test-typecheck with 4 GB heap OK, nothing regenerated. PR check-runs: in_progress at report time (draft just opened).",
    "dogfood_battery": "n/a: no ! in the PR title and the Clause-② line has no (narrowing) arm",
    "mcp_calls": "5: issue_read get #31239, issue_read get_comments #31239 x3, pull_request_read get #31277, plus 1 ToolSearch load (not a GitHub call). No write tool.",
    "api_writes": "2 relay writes: pr_create (PR #31277, labels domain:spec, no assignees) and this os-dev-report comment via post-stamped.mjs. Plus git push of claude/project-thread-0phzyp.",
    "open_questions": [
    {
    "question": "Item 1: option C (reader rule, built here) or option B (the profile vocabulary grows by the container ids)?",
    "status": "needs_decision",
    "options": [
    "C: keep this PR, containers always allowed in the reader, no vocabulary change",
    "B: allowedFlowNodeTypes admits parallel / try_catch (or FlowNodeAction gains them); this PR drops FLOW_CONTAINER_NODE_TYPES and grows the vocabulary, Metadata-protocol moves off none"
    ],
    "recommendation": "C, the seat's recommendation: a container only holds regions, every node inside is still judged, and no protocol value set moves. This is the maintainer's call; the PR stays draft until then."
    }
    ],
    "security_findings": "none",
    "out_of_scope_findings": [
    "carrier: #31264 · os build writes devPlugins into the artifact and os package publish uploads it (measured on bdefd49), so the restriction reader cannot carve it out yet; noted, not filed here"
    ]
    }


    Generated by Claude Code

  7. objectstack-fleet commented on Nov 8, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: none

    Triage: decision card filed · 2026-11-08T03:53Z

    ⛔ Not a claim.


    Generated by Claude Code

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

Metadata

Metadata

Labels

bugSomething isn't workingdomain:specDomain lane — seat card indexed by label:pm:seatpriority:p1High: required for production / M2

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions