Skip to content

plugin-security: the permission-set projection and the position write-through delete metadata by name with no package — after #23165 a name two packages hold answers 409, and storedRowPackageArg (#21861) is redundant #23292

Closed

Description

@objectstack-fleet

Filing gate: (a) a reachable defect a sibling change exposes. reach: plugin-security's in-process callers of the metadata delete door, read from source at PR #23290's head (#23165's fix). Dev report 6148282605 on #23165, out-of-scope finding 2, which names the carrier as "the plugin-security lane". Reader who acts: triage, to grade and route (packages/plugins/plugin-security is domain:services); then the owning seat.

Filed by domain:spec seat 2 (#18549) · os-justin · session session_01BRQ9Mp1yH7R1az6MaUM18H, at #23165's ACCEPT. ⛔ Not a claim.

What changes when PR #23290 lands

Wanted

  • The two in-process deletes name the package of the row they mean, as deletePackage and the draft discards do on that head. A two-package name is then never ambiguous for them.
  • storedRowPackageArg is kept, if it still names something the door cannot resolve, or retired, if it is redundant, with the measurement either way.
  • Pins: a permission set and a position whose name two packages hold are each deleted from the intended package's row only.

Order: after PR #23290 lands.

Also: the runtime's flow registration door

Added at PR #23290's contract review (6148691041, items ①.11 and OOS2), which found a third in-process writer the dev report did not name.

  • registerAndSaveFlow in packages/runtime/src/domains/automation.ts saves a flow with no package and no source. For a one-package flow it now writes that package's row. For a name two packages hold it gets the 409, relays it, and rolls the engine registration back. The review calls that refusal correct: it is loud where the old write was silently misaddressed.
  • Wanted, for this door: it names the package of the flow it registers whenever its caller has one, and a pin holds the two-package case either way (refused loudly, or written to the named package's row only).
  • packages/runtime is domain:cli, not domain:services. Triage may split this door off into its own card; the seat lists it here so the family is complete in one place.

Dedupe

MCP search_issues on this repo, closed included: permission-set-projection position-write-through delete metadata by name no package storedRowPackageArg → 10 hits. #21861 and #21860 (closed) are the write-through's earlier package-axis defects; none is this.

Dedupe words: permission-set-projection delete by name no package; registerAndSaveFlow flow save no package 409; position-write-through delete 409 two packages; storedRowPackageArg redundant.


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Oct 13, 2026

    @objectstack-fleet
    ContributorAuthor

    Pointer · domain:spec seat 2 · session session_01BRQ9Mp1yH7R1az6MaUM18H · 2026-10-13T15:37Z. ⛔ Not a claim.

    #22975 (domain:engine, in flight; its re-cut dispatch is 6148409420) deletes permission-set-projection.ts and position-write-through.ts in plugin-security, with their siblings, because stage 8 removed their only callers. If it lands before this card is picked, both in-process deletes this card names go with those files, and so does storedRowPackageArg, which lives in the write-through. What would then remain is the runtime's flow registration door (the section added from 6148691041). Triage can re-grade this card once #22975 lands.


    Generated by Claude Code

  2. objectstack-fleet commented on Oct 13, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: first grade, bug · priority:p2 · domain:cli, pm:blocked on PR #23290. The runtime's flow registration door names the package it registers; the plugin-security half rides #22975's deletion

    Triage seat (objectstack-wide, seat post #6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-13T15:58Z. ⛔ Not a claim, ⛔ not a dispatch.

    Blocked-by: #23290
    Restart-when: PR #23290 has merged. Re-read #22975's state at claim.

    • Pins: a flow registered for package P is saved to P's row only; the two-package case without a package is refused loudly; a one-package flow is unchanged.
  3. objectstack-fleet commented on Oct 13, 2026

    @objectstack-fleet
    ContributorAuthor

    Unlock scan: pm:blocked → pm:queue. Blocked-by: #23290 is satisfied: PR #23290 (#23165's fix) merged as 543b33dee6

    Triage seat (objectstack-wide, seat post #6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-13T16:05Z. ⛔ Not a claim, ⛔ not a dispatch.

  4. objectstack-fleet commented on Oct 14, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 4 (#23292, the runtime half: registerAndSaveFlow names the package of the flow it registers whenever its caller has one; the two-package case without a package stays a loud refusal) · 2026-10-14T12:13Z
    Session: session_01Q9PZ5Pzqcus4woVvTZwWNU
    Account: sunhaolin (the seat's linked user as GET /user answers it; the card's assignee from this act)
    Branch: claude/issue-23292-flow-door-package
    Worktree: objectstack-issue-23292
    Domain: domain:cli
    Seat: domain:cli#2 (seat post #22648)
    Scope: the maintainer's 「继续派 p2 卡片」 (this seat's session chat, about 12:06Z).
    Re-read at claim, as the unlock scan 6149796842 asks:

    Container & model: S, judged (one helper and its three call sites; the package source is a measurement), mode:subagent, model: default tier (dispatch-gates --tier --repo objectstack-ai/objectstack: "no path-derived mandate"). Ceiling TIER_DEFAULT: naming a package the protocol already accepts touches none of the three contract faces, so CI plus this seat's own read. A new door input would change that grade, and the dev stops.
    Clause-②: no
    Responsibility: registerAndSaveFlow in packages/runtime (this lane) | the metadata protocol's package-less save, which resolves the one bound package or refuses 409 since #23165; read, not changed | a flow written through the automation door under a name two packages hold
    Thread-read: 6149796842
    Serial constraints cleared:


    Generated by Claude Code

  5. objectstack-fleet commented on Oct 14, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
    "issue": 23292,
    "status": "done",
    "branch": "claude/issue-23292-flow-door-package",
    "pr": "#23499",
    "session": "session_01Q9PZ5Pzqcus4woVvTZwWNU",
    "premise_still_valid": true,
    "summary": "Mechanism (b) holds, so registerAndSaveFlow keeps saving with no package. On main, measured over a real store through dispatch(): no caller of the door holds a package. POST / and PUT /:name reach only a _packageId stamp. On the caller's body, that stamp is the caller's bytes, and honouring it would be a new body input (a widening). On the engine-held definition, it is the contender the boot bind armed by arrival order: the execution view lists the two rows in opposite orders under opposite seed orders, so for a two-package name the stamp is a driver-order pick. The clone writes a new name and drops the envelope (FLOW_CLONE_DROPPED_KEYS), and the request context carries no package. PR #23499 ships the card's pins in a new real-store file (12 tests, both seed orders, all three call sites). A one-package flow saves to that package's row only; a flow no package holds saves the package-unbound row. A two-package name answers 409 RESOURCE_CONFLICT at PUT, POST overwrite, POST create and clone; both rows are unchanged, no third row is minted, and the engine is put back. The PR also adds one doc-comment bullet on registerAndSaveFlow recording why no package is named. No runtime behaviour changes. The plugin-security half was already gone from main (dac99c2, 5c9bfb0), as the claim records.",
    "tests": "Final head 6c0c016 (main 8731510 merged in). New pin file: 'pnpm --filter @objectstack/runtime exec vitest run --maxWorkers=2 --reporter=verbose src/domains/automation-flow-door-package-address.test.ts' -> Tests 12 passed (12). Full runtime local project: 'pnpm --filter @objectstack/runtime exec vitest run --project local --maxWorkers=2' -> Test Files 379 passed (379), Tests 5553 passed | 19 skipped (5572), lock VERDICT command-exit 0. Before the merge, at 1b04501: 377 files, 5499 passed, 19 skipped. 'pnpm --filter @objectstack/runtime typecheck' -> exit 0, check:test-typecheck OK (190 errors / 68 signatures held, unchanged). 'tsc -p tsconfig.test.json --listFiles' lists the new file, with 0 errors in it. Sibling suites automation-authoring-doors-durable and automation-flow-clone: 41 passed with the new file. Mutation proofs, one-shot, through 'node scripts/ablation-replace.mjs' in wrap mode, on committed HEAD 1b04501 (the subject resolves via src, by relative import, so no dist leg). Mutation 1 threads the engine-held _packageId into saveMetaItem: 4 failed / 8 passed, namely PUT and POST-overwrite in both orders, each answering 200 where 409 was pinned; restored with blob == HEAD 0684fb34d327 and git diff HEAD empty. Mutation 2 deletes restoreFlowRegistration from the refused-save branch: 8 failed / 4 passed, every two-package refusal pin; restored the same way. Mutation 2's first attempt was refused by the tool before any test ran (the replacement was a substring of the anchor) and was re-run with --delete.",
    "gates": "Derivation: 'node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack' at 6c0c016 gives 53 commands (unchanged from the pre-merge derivation). All 53 were run on 6c0c016, each exit captured before any pipe: 52 exit 0. 'pnpm check:type-check-debt' exited 3 (PREREQUISITE NOT MET: its closure build was OOM-killed, exit 137 in plugin-sharing#build, on the shared box); re-run alone it exited 0 ('check-type-check-coverage --re-measure: OK ... none above its recorded number'). On the pre-merge run, 'pnpm check:query-options-erasure' was red (test surface 236 -> 237, from an options cast in the new file); cdbed1b removes the cast, and on 6c0c016 it holds ('none new'). Reconciliation: 'dispatch-gates.mjs --ran' -> 53 derived, 53 run, 0 NOT-MEASURED, 0 UNRUN. Lint, narrowed: 'pnpm exec eslint --no-inline-config' over the 2 changed files -> exit 0, 2 files linted, 0 errors, 0 warnings. PR check-runs on head 6c0c016 at report time: Lint & Repo Gates success, TypeScript Type Check success, Build Core success, Governed Surface Queue Guard success, Check Changeset success, Test Core (1/6..6/6) in_progress. Of 43 runs: 27 success, 10 skipped, 6 in_progress. NOT MEASURED locally, declared to CI: the path-scheduled CI jobs the derivation names (Test Core shards, Temporal Conformance, Dogfood, Build Core steps) and the workspace type-check lanes.",
    "mcp_calls": "0",
    "api_writes": "3 relay dispatches, each 'POST /repos/objectstack-ai/objectstack/dispatches' from this session, executed by fleet-write.yml as objectstack-fleet[bot]. (1) pr_create, run 38576369061: POST /repos/objectstack-ai/objectstack/pulls (draft) and POST /repos//issues/23499/assignees [sunhaolin]; the body read back identical, 8139 bytes. (2) label-write labels_add, run 38576478225: POST /repos//issues/23499/labels [skip-changeset]; read back size/m, tests, skip-changeset. (3) This os-dev-report comment, posted through post-stamped: POST /repos//issues/23292/comments. Plus git push (not REST) of the branch: empty probe, 1b04501, cdbed1b, merge 6c0c016.",
    "open_questions": [],
    "out_of_scope_findings": [
    "class: a (user-visible misleading text) · reach: public door, measured on a real store through HttpDispatcher.dispatch(). For a flow name two packages hold, PUT /api/v1/automation/NAME answers 409 RESOURCE_CONFLICT, and the relayed message prescribes 'on the REST door add ?package= with the package id'. The automation door reads no query on PUT /:name, so re-sending PUT /automation/shared_flow?package=com.qa.alpha answers the identical 409: a caller following the remedy at this door loops. The save that works is PUT /meta/flow/NAME?package=P. The same relayed text reaches POST / and POST /:name/clone, and DELETE /:name with its 'delete' wording. · Seam: runtime:registerAndSaveFlow / unregisterAndDeleteFlow relay metadata-protocol packagelessAddressAmbiguityRefusal (sys-metadata-repository.ts) verbatim. · Fix shape not pinned; candidates are a door-specific remedy at the automation door, a protocol sentence naming the door that takes ?package=, or accepting ?package= on /automation (a widening that needs a ruling). · dedupe words: automation door 409 remedy ?package= loop; packagelessAddressAmbiguityRefusal REST door wording; PUT /automation two packages RESOURCE_CONFLICT remedy; flow door ignores package query",
    "carrier: none (承接者:无) · noted, not filed. The removal half, reading as dispatched in (d), unchanged. DELETE /automation/shared_flow on a two-package name answers 409 RESOURCE_CONFLICT, both rows remain, and the engine re-registers the definition it held, in both seed orders. Same loud-and-restored shape as the save half; no defect beyond the remedy text in finding 1."
    ],
    "deviations": [
    "Route: no packageId threaded. Mechanism (a) measured that no caller holds one, so the card reduced to mechanism (b), as the dispatch foresaw. The suggested ablation 'drop the forward' has no forward to drop, so two mutation proofs stand in its place (see tests).",
    "Changeset: the dispatch named an @objectstack/runtime patch changeset, premised on a fix. The role file's criterion is whether the publish surface moved, and here it did not. The src change is a comment and the new file is a test. Measured on a built runtime: a phrase of the new bullet appears 0 times in every dist file in files[] (index.js, index.cjs, both maps, both d.ts), against a positive control ('Flow definition body required') at 2 in each of index.js and index.cjs. So no changeset was added, and the skip-changeset label was written through label-write.mjs, where the dispatch expected no label write. Conflict named here, not silently resolved.",
    "pnpm lint: the dispatch says this lane always adds it, while the role file assigns the repo-wide scan to CI. Ran the narrowing, with three pieces of evidence: the flags of the lint script (--no-inline-config); 2 of 2 changed files linted with no ignore warning; exit 0 captured before any pipe. CI's Lint & Repo Gates is success on 6c0c016.",
    "Merged origin/main (8731510) into the branch before opening the PR, per AGENTS.md section 10, so the PR head is the merge commit 6c0c016. Build state was refreshed (install, runtime closure rebuild, rm -rf packages/runtime/.objectstack) and the tests, typecheck and gate union were re-run there. Before the merge I killed my own gate runner (recorded PID 23964).",
    "First full-suite command used a bare '--' ('pnpm --filter @objectstack/runtime test -- --maxWorkers=2'), so vitest dropped --maxWorkers. It still ran the whole local project, as intended. The merged-head run used the exec spelling with --project local.",
    "Attribution: the harness reminder asked for a model-named Co-Authored-By trailer and a two-line PR footer. Per AGENTS.md and the role file, the commits carry the model-free pair and the PR body ends with the single session-URL footer block."
    ],
    "files_changed": [
    "packages/runtime/src/domains/automation.ts (doc comment of registerAndSaveFlow only, +11 lines)",
    "packages/runtime/src/domains/automation-flow-door-package-address.test.ts (new, 248 lines)"
    ]
    }

  6. objectstack-fleet commented on Oct 14, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT → PR #23499 comment 6170440751 · 2026-10-14T14:15Z


    Generated by Claude Code

  7. objectstack-fleet commented on Oct 14, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed: PR #23499 → 111b5821ce · 2026-10-14T14:50Z

    domain:cli seat 2 (#22648) · sunhaolin · session session_01Q9PZ5Pzqcus4woVvTZwWNU · holder of claim 6168069112, released by this landing. Review: seat record 6170440751 on the PR (pointer on this card). No contract review was owed: the diff touches none of the three faces.

    Reading Value
    PR merged: true, merged_at 2026-10-14T14:49Z, through the merge queue (added_to_merge_queue 2026-10-14T14:29Z)
    Queue branch gh-readonly-queue/main/pr-23499-* absent (git ls-remote, 0 refs)
    origin/main 111b5821ce is an ancestor; one parent (ad5a7d7c39); 2 files, +259 / −0, as reviewed
    Closing keywords in the landed commit Fixes #23292 only
    Lane reconciliation 19 open domain:cli cards. Against the 13:48Z set: minus #23292 (this landing); plus #23491 and #23492 (triage-graded into the lane) and #23497 (filed 2026-10-14T13:49Z)

    State change: #23292 closed completed by the merge; pm:dispatched removed in this act. What closed it: the plugin-security half went with dac99c2277 and 5c9bfb0d3f. The runtime half was measured to hold no package at any call site, so registerAndSaveFlow keeps naming none, and the card's three pins now hold that on main. The relayed 409 remedy's loop at the automation door is #23501.


    Generated by Claude Code

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

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions