Skip to content

plugin-webhooks: follow-ups of PR #32577 — pin and door for two webhook holders that still meet in one namespace, the disabled co-holder pin, two checklist items, liveness and impact-report nits, GET /meta step 2 (ADR-0150 D4) #33016

Closed

Description

@objectstack-fleet

epic:#31527#1 · os-sales · session_01L6bhgXQnNkXTT1Wu7i7Y3i

Filing gate ①: product defects with named landing points, owed by PR #32577 under epic ruling 6842178655 on that PR ("Follow-up card (p2), not this PR").

Parent: #31699 (source card). Found by: contract review 6841104065 on PR #32577, items S1, S3, S5 and nits 1 to 3. Ruling: 6842178655. Open question 1 of dev report 6842933276 on #31699 adds GET /meta step 2.

What is owed

  1. S1 pin and door. Two holders that still meet under the narrowed rule (two co-owners of one namespace, two packages of a shareable namespace, or a package with no namespace beside another holder), each declaring one webhook name. Install refuses the state; the cold boot seals it with a warning (BARE_NAME_COLD_BOOT_MODE is 'warn').
    • Built and declared in PR feat(plugin-webhooks)!: declared webhooks are held per namespace, each holder dispatched and switched as its own (ADR-0150 child B, webhook family 2/3) #32577: slotsOf (packages/plugins/plugin-webhooks/src/declared-webhooks.ts) lists one slot per served holder, so both are dispatched (FROM neither). The namespace address answers 409 ambiguous-in-namespace and the bare address 409 naming both (resolveQualifiedWebhook, packages/runtime/src/domains/catalog-activation.ts), so neither can be switched through the door. Only a package disable or a ledger row written directly stops one.
    • Owed: a pin of that state (both dispatched, both doors 409 naming both), in both registration orders, and an exact-qualifier address on the activation door that switches one of the two holders. A new door is a protocol addition: declare it as a FROM → TO row.
  2. S3 co-holder pin. A namespace whose packages are all disabled, beside an enabled holder of another namespace, answers 409 not-held-by-qualifier naming the enabled holder (resolveQualifiedWebhook). Only the lone case ("B disabled and alone", 404) is pinned. Pin the co-holder case.
  3. S5, two platform-checklist items. docs/qa/platform-checklist/areas/integration-system.json (the item at line 618) and docs/qa/platform-checklist/areas/cli.json (the item at line 2148) expect a new delivery's ref_id to be declared:showcase_task_changed. The dogfood pins they point at expect declared:com.example.showcase/showcase_task_changed since PR feat(plugin-webhooks)!: declared webhooks are held per namespace, each holder dispatched and switched as its own (ADR-0150 child B, webhook family 2/3) #32577. Bring both items to the new reference.
  4. Nit 1. packages/spec/liveness/webhook.json, the name evidence, still reads "the first registration of a name holds it" and declaredWebhookRefId(wh.name). Bring it to per-holder slots and declaredWebhookRefId(name, packageId).
  5. Nit 2. SWITCH_DOORS and the withheld-webhook line in packages/plugins/plugin-security/src/upgrade-impact-report.ts name the namespace address for every finding. The environment's own webhook and a package with no namespace have only the bare address. Name the door each finding can use.
  6. Nit 3. webhookShippers (same file) counts a disabled holder only when the bare artifact lookup answers it, so a disabled second holder gets no withheld finding. main reported one holder, so nothing regresses; report each disabled holder.
  7. GET /meta step 2 (dev report open question 1, unmeasured). Shape: one holder, its package's stored row and a package-less stored row of one webhook name. The protocol's by-name read (packages/metadata-protocol/src/protocol-meta-item-reads.ts) calls the metadata service's getDiagnosed at its step 2, only when steps 1 and 1b answer nothing; step 1 declines package-less stored rows. PR feat(plugin-webhooks)!: declared webhooks are held per namespace, each holder dispatched and switched as its own (ADR-0150 child B, webhook family 2/3) #32577 moved that service read (its Clause-② (7)). Probe in a booted stack whether bare GET /meta/webhook/NAME reaches step 2 in this shape. If it does and its answer moved, declare it.
  8. Nit 4's pin, if absent. The activation door's one-holder widening (a row naming no package beside the holder's own row: FROM 409 TO the holder's own row written) is declared in the changeset. Pin it if no test does.

Acceptance

  • Each code item is pinned, red under ablation where it pins a moved answer, and in both registration orders where order applies.
  • Any answer this card moves is a declared FROM → TO row (Clause-② when it narrows).
  • The two checklist items pass against the showcase run that their dogfood pins describe.

Order

Activity

  1. added
    pm:queueReady for the PM dispatch loop
    domain:serverDomain lane — seat card indexed by label:pm:seat
    on Nov 13, 2026
  2. objectstack-fleet commented on Nov 13, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · hotlong · session_01Q4EjjMnyLqJdzuktEmRPXH

    Path: none

    Triage: first-touch audit (pre-labeled card) · p2 confirmed · 2026-11-13T07:53Z

    ⛔ Not a claim; the claim (if any) is unchanged.


    Generated by Claude Code

  3. objectstack-fleet commented on Nov 14, 2026

    @objectstack-fleet
    ContributorAuthor

    epic:#31527#3 · os-tesla · session_01L9qibzECS2npZFku4956Um

    Claim: PM loop round 1 · batch 3 of the maintainer's order 6866786021 (card 1 of 9, one session back to back) · 2026-11-14T00:48Z
    Session: session_01L9qibxGWY9FF7Lgr4CiTa3 (card thread; seat session_01L9qibzECS2npZFku4956Um)
    Account: os-tesla
    Branch: claude/project-thread-esw9si (the card thread's harness-pinned branch; the thread can push only this name)
    Worktree: objectstack-issue-33016
    Domain: domain:server
    Seat: epic:#31527#3
    File surface: packages/plugins/plugin-webhooks/src/**, packages/runtime/src/domains/catalog-activation.ts, packages/plugins/plugin-security/src/upgrade-impact-report.ts, packages/spec/liveness/webhook.json (evidence text only), docs/qa/platform-checklist/areas/integration-system.json and cli.json (the two named items), packages/metadata-protocol/src/protocol-meta-item-reads.ts (only if item 7's probe moves an answer), their tests, root .changeset/ (stop on breach; explain in the report)
    Container & model: M, mode:thread, model: default (no path-derived mandate), effort: xhigh (epic child)
    Clause-②: yes
    Metadata-protocol: added
    Responsibility: platform code in objectstack (plugin-webhooks slots, the runtime activation door, the upgrade-impact report); no other platform path covers it; reached by an operator with two webhook holders that still meet in one namespace — rare
    Thread-read: 6847357630
    Premise: holds as filed; the thread re-measures each item on current origin/main first (Clause-② / Metadata-protocol here are expected, for item 1's new exact-qualifier door; the dev derives the final lines from the diff)
    Serial constraints cleared: domain:server#7 #31699 PR 3 (connector narrowing, PR not yet open) may touch catalog-activation.ts and upgrade-impact-report.ts — write in parallel, land serially, merge main once if it lands first; #32692 PR #33166 (boot hydration) is on registry hydration, not these files

    Order: /mnt/project-files/epic-31527-3/r2026-11-13/dispatch-batch3.md under FRAME.md. Contract review: this seat, at CONTRACT_REVIEW_TIER.


    Generated by Claude Code

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

    @objectstack-fleet
    ContributorAuthor

    epic:#31527#3 · os-tesla · session_01L9qibxGWY9FF7Lgr4CiTa3
    os-dev-report

    {
     "issue": 33016,
     "status": "done",
     "branch": "claude/project-thread-esw9si",
     "pr": "https://github.com/objectstack-ai/objectstack/pull/33204",
     "session": "session_01L9qibxGWY9FF7Lgr4CiTa3",
     "premise_still_valid": true,
     "summary": "Items 1-6 and 8 of the card (PR: Refs #33016 (items 1, 2, 3, 4, 5, 6, 8)). Item 1: POST /security/_activation/webhook/NAME takes ?package=PKG (resolveExactWebhook, WEBHOOK_DOOR_QUERY_PARAMS) and switches exactly PKG's served declaration, writing its own row; two co-owners of one namespace and a package with no namespace are now switchable. Items 2 and 8 pinned (no code change). Item 3: two checklist items move to declared:com.example.showcase/showcase_task_changed (revision + history bumped). Item 4: liveness evidence text. Items 5-6: upgrade-impact report names ?package= in its switch lines and reports each holder, a disabled second holder included. Item 7: a security item is with the owner seat. Clause-② yes (widening), Metadata-protocol none (seat agreed), patch changeset. Head c68c098f0.",
     "tests": "At c68c098f0: runtime typecheck + test 597/597 files, 10617 passed / 19 skipped (VERDICT 0); before the merge (which touched neither): plugin-webhooks 267/267 files 6607 passed, plugin-security 25/25 files 294 passed; typecheck of runtime, plugin-security, plugin-webhooks exit 0. Ablations via scripts/ablation-replace.mjs (anchor 1->0, restored blob == HEAD; suites import src/): (1) webhook bare-address query set emptied -> catalog-activation-door.test.ts 5 failed/84 passed; (2) disabled-holder add removed from webhookShippers -> upgrade-impact-report.test.ts 2 failed/43 passed; (3) namespace address put back in WEBHOOK_SWITCH_DOOR -> 1 failed/44 passed.",
     "gates": "dispatch-gates --commands derived 105 at c68c098f0; all 105 run with </dev/null, every exit 0; --ran: 105 derived, 105 run, 0 NOT-MEASURED, 0 UNRUN. Also pnpm lint exit 0, spec check:generated exit 0. First run (pre-merge) found check:platform-checklist exit 1 (item revision not bumped; fixed in 95e17a456); exit-3 prerequisites (skill-examples, dual-build-cjs-loads, teardown self-test fixture) and dts-closure were local build state, cleared by full build + fixture fetch. CI check-runs: in_progress at report time.",
     "dogfood_battery": "n/a - no ! in the PR title and no (narrowing) arm",
     "mcp_calls": "4 - reads only: issue_read get + get_comments x2 on #33016 (and one ToolSearch); 0 writes",
     "api_writes": "2 relay writes - fleet-write pr_create (PR #33204 + assignee os-tesla leg); this os-dev-report comment via post-stamped. git push is not a REST write.",
     "open_questions": [],
     "security_findings": "withheld",
     "out_of_scope_findings": [
      "carrier: PR #33204 Acceptance notes - plugin-webhooks remedies (name guard, redelivery veto) still name the namespace address, which answers 409 for two co-owners of one namespace; a ruled text (#31699 round 2), not changed; the seat decides on a follow-up"
     ],
     "deviations": [
      "file surface extended by the seat (01:18Z thread message): packages/runtime/src/route-ledger.ts (webhook :ns row note) and content/docs/automation/webhooks.mdx, one sentence each",
      "Metadata-protocol derived none from the diff (claim expected added); seat agreed",
      "item 7 not in the PR, per the seat"
     ],
     "line_budget": "n/a - no skills/** path",
     "files_changed": [
      ".changeset/33016-webhook-exact-qualifier-door.md",
      "content/docs/automation/webhooks.mdx",
      "docs/qa/platform-checklist/areas/cli.json",
      "docs/qa/platform-checklist/areas/integration-system.json",
      "packages/plugins/plugin-security/src/upgrade-impact-report.test.ts",
      "packages/plugins/plugin-security/src/upgrade-impact-report.ts",
      "packages/plugins/plugin-webhooks/src/declared-webhooks.test.ts",
      "packages/runtime/src/domains/catalog-activation-door.test.ts",
      "packages/runtime/src/domains/catalog-activation.ts",
      "packages/runtime/src/route-ledger.ts",
      "packages/spec/liveness/webhook.json"
     ],
     "rulings_grep": "catalog-activation.ts 8 (ADR-0131 seeder ruling, #22621 -> A, ADR-0150 D2 ruling, epic ruling MF1 x3, ⛔ door limits), upgrade-impact-report.ts 1 (ruling on #24443), webhook.json 3 (#7131 previews ruling, spec-only override note); none touched"
    }
  6. objectstack-fleet commented on Nov 14, 2026

    @objectstack-fleet
    ContributorAuthor

    epic:#31527#3 · os-tesla · session_01L9qibxGWY9FF7Lgr4CiTa3
    os-dev-report (patch round after contract review 6870153173)

    {
     "issue": 33016,
     "status": "done",
     "branch": "claude/project-thread-esw9si",
     "pr": "https://github.com/objectstack-ai/objectstack/pull/33204",
     "head": "0afa1e462",
     "session": "session_01L9qibxGWY9FF7Lgr4CiTa3",
     "premise_still_valid": true,
     "summary": "One patch round on c68c098f0 -> 0afa1e462. S1: the second state of item 1 pinned, a package that declares no namespace beside another holder, both registration orders: at the door the bare address is 409 naming both and ?package= switches each holder's own row; in the dispatcher both are dispatched under their own ids and the bare read is refused naming both. S2: a disabled holder's withheld-webhook finding is marked packageDisabled: true (added optional field) and the line says such a package must be enabled first, then switched at ?package=PACKAGE; PR body item 5/6 wording corrected. N1: catalog-activation.ts module doc names package on the bare webhook address. N2: the bare-address arm dropped from WEBHOOK_SWITCH_DOOR (every webhook finding names a package: a re-enablement's row records one, a withheld holder is a package). N3: changeset first FROM/TO row names data.packageId. N4: changeset adds '@objectstack/spec': patch and a liveness-text line.",
     "measurement": "Environment's own declaration (no package) beside a packaged holder of the same name, no code change. Registry (booted shape): a package-less entry beside ONE packaged holder is that holder's customization (ADR-0150 D3), not a second holder: one slot, bare/?package=/namespace all switch it. Beside TWO packaged holders it binds to no package, sits in neither slot and is not dispatched; the two packages' own declarations are dispatched and switchable. Metadata-service path (no registry item): the name is refused whole, neither declaration dispatched (list() empty, warn 'not dispatched'), holdersOf [environment, PKG]; door: bare 409 naming the environment and PKG, ?package=PKG 404 ('no enabled package declares the name', which misreads: PKG does declare it), namespace address 404, nothing written. No holder has a working switch there, and nothing is delivered either. Not fixed here; for the seat.",
     "tests": "At 0afa1e462: runtime typecheck + test 597/597 files, 10619 passed / 19 skipped (lock VERDICT command-exit 0); plugin-security 267 files 6607 passed / 45 skipped; plugin-webhooks 25 files 296 passed; typecheck of plugin-security and plugin-webhooks exit 0. Ablations (scripts/ablation-replace.mjs, restored blob == HEAD): webhook bare-address query set removed -> door suite 7 failed/84 passed (incl. both new no-namespace pins); packageDisabled spread deleted -> report suite 2 failed/43; enable-first sentence replaced -> 2 failed/43; namespace address put back in WEBHOOK_SWITCH_DOOR -> 1 failed/44.",
     "gates": "dispatch-gates --commands derived 105 at 0afa1e462 (same set as c68c098f0); all 105 run with </dev/null, every exit 0; --ran: 105 derived, 105 run, 0 NOT-MEASURED. pnpm lint exit 0.",
     "dogfood_battery": "n/a - no ! in the PR title and no (narrowing) arm",
     "mcp_calls": "0 this round",
     "api_writes": "2 relay writes this round - issue_patch PR #33204 body (signature line first, read back identical); this comment via post-stamped. git push is not a REST write.",
     "open_questions": [],
     "security_findings": "withheld",
     "out_of_scope_findings": [
      "carrier: this report, measurement - environment declaration beside a packaged holder in the metadata-service path has no working switch, and ?package= answers a misleading 404; seat files if wanted",
      "carrier: PR #33204 Acceptance notes - plugin-webhooks remedies still name the namespace address; the seat files the follow-up"
     ],
     "deviations": [],
     "files_changed_this_round": [
      ".changeset/33016-webhook-exact-qualifier-door.md",
      "packages/plugins/plugin-security/src/upgrade-impact-report.ts",
      "packages/plugins/plugin-security/src/upgrade-impact-report.test.ts",
      "packages/plugins/plugin-webhooks/src/declared-webhooks.test.ts",
      "packages/runtime/src/domains/catalog-activation.ts",
      "packages/runtime/src/domains/catalog-activation-door.test.ts"
     ]
    }
  7. objectstack-fleet commented on Nov 14, 2026

    @objectstack-fleet
    ContributorAuthor

    epic:#31527#3 · os-tesla · session_01L9qibzECS2npZFku4956Um

    Release: session_01L9qibzECS2npZFku4956Um · seat epic:#31527#3 signs off on the maintainer's word 「所有座位当前任务处理完,合并后就下班」 (2026-11-14 04:35Z, project chat) · back to pm:queue for the next claimant · 2026-11-14T05:50Z
    Resume-from: none


    Generated by Claude Code

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

    @objectstack-fleet
    ContributorAuthor

    domain:server#5 · os-elon-musk · session_016WV4czXwx6JtQPvacrzzUw

    Closed in W0 of the area-lease pilot (#33059) · 2026-11-14T15:01Z

    Items 1–6 and 8 landed in PR #33204 (merged as 1f8ce6e; ACCEPT 6871180048). Item 7 (GET /meta step 2) was handed to the security seat, which is offline; it moves to its own card (linked below once filed). The loose ends #33204 owed (Release comment 6872656597) also get their own card. Read by area E2.

    The maintainer approved this W0 close list in the project thread: 「以上都同意」.


    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

No one assigned

    Labels

    domain:serverDomain 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