You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
runtime: an exact /webhooks/redeliver dispatcher domain that forwards to the declared redeliver member, with a typed refusal for an absent slot (webhooks segment 2 of #22564's stage 2) #22755
Filing gate ③: a segment the maintainer's ruling directs. Filed by the triage seat (seat post #6015, session_01AavokzJ5DndAwitDXvKy4U), splitting stage 2 of #22564 (ruling 「A + 扫类」 on #22438, 6079645593 item 2) as #22438 was split (#22575–#22578). ⛔ Not a claim.
Pointer from segment 1 (#22754): forward to slot webhooks, member handleRedeliver
domain:spec seat 2 (#18549) · session_016njDy8ozy9B9Ns5Y8kAWEK · 2026-10-11T05:10Z. ⛔ Not a claim, ⛔ not a dispatch, ⛔ no label change.
What segment 1 declared (PR #22767 at 06119a91ff, accepted 6105695211, in the merge queue):
A NEW contract, IWebhookService (packages/spec/src/contracts/webhook-service.ts), with the optional member handleRedeliver?(request: Request): Promise<Response>.
Its docblock names the slot key webhooks. ⛔ It is not on the messaging service.
What that means for this segment:
The dispatcher domain forwards to kernel.getService('webhooks')?.handleRedeliver.
The typed refusal fires when the slot or the member is absent.
The member this segment forwards to is now on main:IWebhookService.handleRedeliver? in packages/spec/src/contracts/webhook-service.ts, slot key webhooks. Segment 1's pointer (6105718935) names it.
The scope and done-when above are unchanged. Forward to kernel.getService('webhooks')?.handleRedeliver. When the slot or the member is absent, answer the typed refusal, ⛔ never ROUTE_NOT_FOUND. Make ⛔ no allow-list change.
Cross-lane relay from domain:services seat 1 (seat post #6021) · os-project-manager · session_01CBAfsWMSfM3EToQGVStEcp · 2026-10-11T07:58Z. ⛔ Not a claim, ⛔ not a dispatch. These are for whoever claims this card.
The pairing segment, #22756, is queued to land first: PR #22797 at c66f740762, ACCEPT 6106645610, at-tier contract review PASS 6106891207. The plugin-webhooks plugin now registers the webhooks slot holding IWebhookService.handleRedeliver(request). That member serves the redeliver door from a web-standard Request, with the self-hosted route's exact answers.
Two items the contract review routed to this card (6106891207, §③):
Also from the review: the member does not match the method. The contract's status table has no 405, and this domain is exact-POST, so method matching is pinned here. A non-POST that reaches the member would be told 401 or 400, never 405.
Claim: PM loop round 1
Session: session_01B5CHJNXuuqzChM4w6hkTN4
Account: marchtian
Branch: claude/issue-22755-webhooks-redeliver-domain
Worktree: objectstack-issue-22755
Domain: domain:cli
Seat: domain:cli#1
File surface: packages/runtime/src/domains/ (a new webhooks domain module and its tests), packages/runtime/src/http-dispatcher.ts (registration), packages/runtime/src/route-ledger.ts (the redeliver row), the dogfood authz census pair packages/qa/dogfood/test/authz-conformance.matrix.ts / authz-probe-blind-spot.census.ts (and their tests) and route-ledger-live-mount-parity.dogfood.test.ts if the new route moves them, scripts/check-route-envelope.mjs only if the new domain file must be declared there, a conformance pin under packages/qa/http-conformance/ if the end-to-end pin lands there, and one .changeset/22755-*.md. Widened by edit before the ACCEPT:packages/qa/http-conformance/package.json, packages/qa/http-conformance/vitest.config.ts and pnpm-lock.yaml (the devDependency and source alias the conformance pin needs, as in the precedent), scripts/engine-double-contract.pinned.json (written by the gate's own --write for the new pinned fake), and packages/qa/dogfood/test/authz-conformance.test.ts / authz-probe-blind-spot.test.ts (their counts) (PR #22842). ⛔ No packages/core auth-gate change and no packages/spec change. Read on origin/mainb7cd1af9df at 2026-10-11T11:13Z. Stop on a breach and explain it in the report.
Container & model: M, mode:subagent, model: default tier (dispatch-gates --tier --repo objectstack-ai/objectstack: "no path-derived mandate", floor · default · ceiling). Not mechanical: a new dispatcher domain with a per-request slot resolution and an end-to-end pin.
Clause-②: no
Responsibility: the runtime HttpDispatcher (this lane) has no /webhooks/redeliver domain, so a dispatcher-only kernel answers ROUTE_NOT_FOUND | plugin-webhooks' raw-app mount covers only a kernel with an http.server, never a hosted tenant kernel | an operator pressing redeliver on a hosted environment; the class was measured by the director record on #22438 (6079645593)
Thread-read: 6106905545
Serial constraints cleared: no open PR touches http-dispatcher.ts, route-ledger.ts or packages/runtime/src/domains/ (7 open PRs' file lists read). PR #22793 (epic:#15194 stage 6a, draft) also edits authz-conformance.matrix.ts; that is ordinary concurrency, and whichever lands second merges main. None of the 8 open pm:dispatched claims declares a runtime dispatcher file. Same-area sibling #22773 (this lane, area:workflow) edits the same registration and census files, so it is held hard-serial behind this card until this card's PR merges.
os-dev-report
{
"issue": 22755,
"status": "done",
"branch": "claude/issue-22755-webhooks-redeliver-domain",
"pr": "#22842",
"session": "session_01B5CHJNXuuqzChM4w6hkTN4",
"premise_still_valid": true,
"summary": "packages/runtime: HttpDispatcher now serves exactly POST /webhooks/redeliver through a new domains/webhooks.ts, registered beside /approvals/act. It resolves the request kernel's webhooks slot PER REQUEST (plugin-webhooks registers it at kernel:ready, only once its veto installs), forwards context.request unread to IWebhookService.handleRedeliver and returns that Response untouched. An absent slot or member answers 501 NOT_IMPLEMENTED (never ROUTE_NOT_FOUND); a member throw or an already-consumed body answers a sanitised 500, logged. No preamble-gate change: unlike /approvals/act the credential is the session, so the ADR-0069 gate and the membership gate both apply (pinned), making the hosted door stricter than the self-hosted mount, never looser; packages/core and packages/spec untouched. All four PM mechanism assumptions measured: (1) premise TRUE on main b7cd1af (slot holds handleRedeliver, the hosted door answered 404 ROUTE_NOT_FOUND for authenticated and anonymous POST); (2) per-request resolution held and pinned; (3) anonymous: both doors answer the identical 401 UNAUTHENTICATED bytes, no gate/allow-list change needed or made; (4) non-POST: self-hosted 404 ENDPOINT_NOT_FOUND, hosted 404 ROUTE_NOT_FOUND (pinned), member never runs. The end-to-end pin is this card's: http-conformance drives the real plugin-webhooks member on a dispatcher-only kernel through createHonoApp (a replay lands in the real outbox) and holds every refusal byte-equal to the self-hosted mount. Census bookkeeping as the precedent: route-ledger row (server-only, 85 to 86), route-envelope declaration, dogfood authz row webhook-redeliver-session plus census/test counts, showcase parity pin. Worktree removed after the PR opened.",
"tests": "All on final head be4051a (branch + main efcbac7 merged; pnpm install --frozen-lockfile, full turbo build 73/73, rm -rf packages/runtime/.objectstack). runtime local project in 3 chunks: 104 + 123 + 123 files, 1985 + 1520 + 1546 passed (19 skipped); runtime repo project 3 files, 751 passed; runtime typecheck (src + test layer) 0, new test counted in the test-layer program via --listFiles. http-conformance 11 files, 117 passed; typecheck 0. dogfood authz-conformance + authz-probe-blind-spot + route-ledger-live-mount-parity: 3 files, 100 passed; typecheck 0. New pins: runtime domains/webhooks-redeliver.test.ts 13/13; http-conformance hono-webhooks-redeliver.conformance.test.ts 7/7. Ablations (committed state, via scripts/ablation-replace.mjs WRAP mode plus a shell trap; restore proven by blob == HEAD, empty git diff HEAD, clean porcelain): A) registration replaced by void createWebhooksRedeliverDomain;, runtime dist rebuilt, ablation-dist-preflight --absent green (marker absent from all 6 built files, mutate leg confirmed): unit 10/13 red on ROUTE_NOT_FOUND (the 3 green are the gate pins, which refuse before route resolution), wire 5/7 red (404 for 200/501 and the anonymous parity row; the 2 green are the non-POST pin and the self-hosted control); restore: rebuilt, marker present in 2 dist files, tree clean, 13/13 + 7/7. C) slot guard disabled: exactly the 2 slot-absence pins red (TypeError reading handleRedeliver of undefined); member guard disabled: exactly the member-absence pin red (500 INTERNAL_ERROR for 501); restored 13/13. B) showcase parity pin renamed: 2/8 red, POST /webhooks/redeliver — LEDGERED BUT NOT MOUNTED plus the stale pin, boot log shows plugin-webhooks' raw mount; restored 8/8. Lint: proven narrowing, see gates.",
"mcp_calls": "0 — no MCP GitHub tool was called (reads went through gh api REST reads: card, comments, PR read-back, check-runs, precedent card's comments)",
"api_writes": "2 relay strokes (POST /repos/objectstack-ai/objectstack/dispatches, each executed by fleet-write as objectstack-fleet[bot]) = 3 endpoints: POST /repos/objectstack-ai/objectstack/pulls (draft, #22842), POST /repos//issues/22842/assignees (marchtian), POST /repos//issues/22755/comments (this report). 0 label writes. git push x8 (not REST): the empty-branch probe, 6 commits, 1 merge commit.",
"open_questions": [],
"out_of_scope_findings": [
"carrier: the #22564 sweep owner (services seat) · noted, not filed — read while working: other raw-app mounts that a dispatcher-only kernel would not serve (metadata HMR registerMetadataHmrRoutes, cloud-connection marketplace proxy / local install / runtime config, the CLI console, trigger-api's inbound hooks which #22773 carries). The ruling's sweep names further class members; nothing here was measured on a hosted kernel. Dedupe words: getRawApp, raw-app mount, dispatcher-only kernel, hosted door"
],
"gates": "Derived from the actual diff (dispatch-gates --commands, no paths, --repo objectstack-ai/objectstack) at be4051a: 100 families = the dispatch list's 53 (all inside) + 47 the diff adds. All 100 exit 0 at be4051a; dispatch-gates --ran over the recorded exits: 100 derived, 100 run, 0 NOT-MEASURED, 0 UNRUN. Red on the way and fixed in-diff: check:route-ledger-census (85 to 86, --fix) and check:engine-double-contract (fake findOne now opens with assertEngineFindOnePredicate; pinned ledger --write +1 row). check:dual-build-cjs-loads first refused PREREQUISITE NOT MET (8 packages without dist), measured after the full build (107 entries / 66 packages). pnpm lint (lane blind spot): proven narrowing, not the full run — population = eslint.config.mjs files globs minus NEVER_LINTED = 12 of 16 diff files; eslint --no-inline-config --format json: 12 files, 0 errors, 0 warnings, 0 fatal, none ignored; invariance: no type-aware linting (no parserOptions.project, stated in the config) and the diff touches no config input. CI at report time: 12 checks completed (0 failed), 21 in_progress — in_progress.",
"line_budget": {
".changeset/22755-webhooks-redeliver-domain.md": "+18 -0",
"packages/qa/dogfood/test/authz-conformance.matrix.ts": "+27 -7",
"packages/qa/dogfood/test/authz-conformance.test.ts": "+2 -0",
"packages/qa/dogfood/test/authz-probe-blind-spot.census.ts": "+26 -11",
"packages/qa/dogfood/test/authz-probe-blind-spot.test.ts": "+7 -5",
"packages/qa/dogfood/test/route-ledger-live-mount-parity.dogfood.test.ts": "+7 -0",
"packages/qa/http-conformance/package.json": "+2 -0",
"packages/qa/http-conformance/src/hono-webhooks-redeliver.conformance.test.ts": "+359 -0",
"packages/qa/http-conformance/vitest.config.ts": "+14 -0",
"packages/runtime/src/domains/webhooks-redeliver.test.ts": "+322 -0",
"packages/runtime/src/domains/webhooks.ts": "+169 -0",
"packages/runtime/src/http-dispatcher.ts": "+6 -0",
"packages/runtime/src/route-ledger.ts": "+5 -1",
"pnpm-lock.yaml": "+6 -0",
"scripts/check-route-envelope.mjs": "+5 -0",
"scripts/engine-double-contract.pinned.json": "+5 -0"
},
"deviations": [
"Draft PR opened after verification finished rather than at the first showable commit: the role file also says the PR body is written once and never PATCHed, so I held the open until the numbers were final (the branch was pushed after every compilable step throughout).",
"Merged main (efcbac7, 3 commits, zero overlap) into the branch before opening the PR, per AGENTS.md section 10, and re-ran the full verification on the merge head be4051a.",
"One file outside the claim's named surface: scripts/engine-double-contract.pinned.json (+5), written by node scripts/check-engine-double-contract.mjs --write as that gate prescribes for new pinned coverage (not the shrink-only baseline). packages/qa/http-conformance/package.json, vitest.config.ts and pnpm-lock.yaml are the devDependency + source-alias the conformance pin needs, as in the precedent.",
"Commit trailers and the PR footer follow AGENTS.md and this order (model-free Co-authored-by: Claude pair; session-URL footer), not the harness attribution reminder, which named a model and a different footer form.",
"First runtime test chunk returned exit 99 (queue-timeout, never acquired, a sibling's 9-minute run held the lock): read as NOT MEASURED and re-queued under the same slot name; not counted anywhere."
],
"files_changed": [
".changeset/22755-webhooks-redeliver-domain.md",
"packages/qa/dogfood/test/authz-conformance.matrix.ts",
"packages/qa/dogfood/test/authz-conformance.test.ts",
"packages/qa/dogfood/test/authz-probe-blind-spot.census.ts",
"packages/qa/dogfood/test/authz-probe-blind-spot.test.ts",
"packages/qa/dogfood/test/route-ledger-live-mount-parity.dogfood.test.ts",
"packages/qa/http-conformance/package.json",
"packages/qa/http-conformance/src/hono-webhooks-redeliver.conformance.test.ts",
"packages/qa/http-conformance/vitest.config.ts",
"packages/runtime/src/domains/webhooks-redeliver.test.ts",
"packages/runtime/src/domains/webhooks.ts",
"packages/runtime/src/http-dispatcher.ts",
"packages/runtime/src/route-ledger.ts",
"pnpm-lock.yaml",
"scripts/check-route-envelope.mjs",
"scripts/engine-double-contract.pinned.json"
]
}
PR shape: draft, base main, assignee marchtian. The first line is Fixes #22755, and no other closing keyword appears in the body. Clause-②: no is line-initial in the body and in the changeset.
The claim was widened in place before this ACCEPT to cover the http-conformance package.json / vitest.config.ts, pnpm-lock.yaml, scripts/engine-double-contract.pinned.json (written by the gate's own --write) and the two dogfood count tests.
No packages/core or packages/spec file is touched, and the allow-list is unchanged, as the card fenced.
Diff, read:
domains/webhooks.ts mirrors the /approvals/act precedent: exact POST /webhooks/redeliver, registered in http-dispatcher.ts.
The webhooks slot is resolved per request through deps.resolveService on every call, never at registration.
An absent slot or member answers 501 through deps.error. NOT_IMPLEMENTED is an existing ledger code, so no new code.
A member throw or a consumed body answers the sanitised INTERNAL_ERROR_MESSAGE500, with the original logged.
Contract faces: none hit. There is no Clause-②: yes, no packages/spec/src path and no governed text, so no contract-tier review is owed (contract-review.md). This seat read the diff.
CI on be4051ae27, latest run per name: 34 success, 2 skipped by design. Lint & Repo Gates and TypeScript Type Check are both completed: success. mergeable_state: clean.
Changeset, sentence by sentence against the diff: all true.
The door that changes (exact POST, request forwarded unread, the service read on every request, its Response returned as is).
The 501 for an absent service or member, "naming which" (two distinct messages).
The sanitised logged 500.
The non-POST404 ROUTE_NOT_FOUND.
"Stricter than the self-hosted mount, never looser" (no gate change in the diff).
"Nothing changes on a self-hosted server" (no plugin file touched).
PM mechanism assumptions, as the dev measured them:
The premise held: the hosted door answered 404 ROUTE_NOT_FOUND before the change.
The slot is resolved per request, and pinned.
An anonymous call gets identical 401 UNAUTHENTICATED bytes on both doors.
A non-POST gets 404 on both doors (different codes, pre-existing), and the member never runs.
The end-to-end pin through the real plugin-webhooks member is in hono-webhooks-redeliver.conformance.test.ts, as the review on PR #22797 routed here. The dev's ablations (registration removed, slot guard and member guard disabled) each turned exactly the expected pins red.
Findings: the further raw-app mounts a dispatcher-only kernel would not serve go to the #22564 sweep owner (domain:services), not filed here. Disposition: Acceptance notes, carrier: the sweep.
Landing next: ready, then auto-merge through the queue. #22773 is held hard-serial behind this PR (6108474120).
Merged by the queue at 2026-10-11T14:09Z as 8558668a68106b94917023256b31828f93de2230. It is a single-parent squash and an ancestor of origin/main. Its file list is the 16 accepted files (+980 / −24).
Card: closed completed by the PR's Fixes line. pm:dispatched is stripped in this act; domain:cli, area:workflow, priority:p2 and bug stay.
Activity
objectstack-fleet commentedon Oct 11, 2026
Pointer from segment 1 (#22754): forward to slot
webhooks, memberhandleRedeliverdomain:specseat 2 (#18549) ·session_016njDy8ozy9B9Ns5Y8kAWEK· 2026-10-11T05:10Z. ⛔ Not a claim, ⛔ not a dispatch, ⛔ no label change.What segment 1 declared (PR #22767 at
06119a91ff, accepted6105695211, in the merge queue):IWebhookService(packages/spec/src/contracts/webhook-service.ts), with the optional memberhandleRedeliver?(request: Request): Promise<Response>.webhooks. ⛔ It is not on the messaging service.What that means for this segment:
kernel.getService('webhooks')?.handleRedeliver.handleActionPageprecedent from spec(approvals): declare the approvals service's optional, transport-neutral action-page member (segment 1 of ruling A on #22438) #22575 / runtime + hono: an exact /approvals/act dispatcher domain that forwards to the approvals service member, and a catch-all that stops consuming non-JSON bodies (segment 2 of ruling A on #22438) #22576.Generated by Claude Code
objectstack-fleet commentedon Oct 11, 2026
Unlock:
pm:blocked→pm:queueTriage seat (seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-11T05:54Z. ⛔ Not a claim, ⛔ not a dispatch.Blocked-by:on this card is spec: declare the forward target forPOST /api/v1/webhooks/redeliver— an optional, transport-neutral service member a dispatcher domain can reach (webhooks segment 1 of #22564's stage 2) #22754. It closedcompletedwhen PR feat(spec): declare IWebhookService.handleRedeliver, the optional transport-neutral webhook redeliver member #22767 merged (e84aeb36ce).main:IWebhookService.handleRedeliver?inpackages/spec/src/contracts/webhook-service.ts, slot keywebhooks. Segment 1's pointer (6105718935) names it.kernel.getService('webhooks')?.handleRedeliver. When the slot or the member is absent, answer the typed refusal, ⛔ neverROUTE_NOT_FOUND. Make ⛔ no allow-list change.http.serverbefore thehttp-serveralias, and keep the self-hosted raw-app mount byte-unchanged (webhooks segment 3 of #22564's stage 2) #22756 and [Decision] 托管环境上 trigger-api 的入站 webhook(HMAC 签名)要不要在/automation匿名门槛上开一个精确到路由的口子,与自托管一致? #22757 are still open.objectstack-fleet commentedon Oct 11, 2026
Cross-lane relay from
domain:servicesseat 1 (seat post #6021) ·os-project-manager·session_01CBAfsWMSfM3EToQGVStEcp· 2026-10-11T07:58Z. ⛔ Not a claim, ⛔ not a dispatch. These are for whoever claims this card.The pairing segment, #22756, is queued to land first: PR #22797 at
c66f740762, ACCEPT6106645610, at-tier contract review PASS6106891207. Theplugin-webhooksplugin now registers thewebhooksslot holdingIWebhookService.handleRedeliver(request). That member serves the redeliver door from a web-standardRequest, with the self-hosted route's exact answers.Two items the contract review routed to this card (
6106891207, §③):webhooksatkernel:ready, after the [security] a dropped webhook subscription leaves no durable record — and the naive fix hands an operator aredeliverbutton that sends UNSIGNED #8069 veto installs, and only if it installs. The dispatcher domain must therefore resolve the slot and probehandleRedeliverat request time, ⛔ never at domain registration, or it records an absence the boot then contradicts. An absent slot or member answers the contract's typed absence.POST /webhooks/redeliver. With feat(plugin-webhooks): the webhooks service serves the redeliver door from a Request, and the veto no longer waits for realtime (webhooks segment 3 of #22564) #22797 landing first, that is this card. Its acceptance carries that pin and a typed-absence ablation (the slot or member removed on purpose).Also from the review: the member does not match the method. The contract's status table has no
405, and this domain is exact-POST, so method matching is pinned here. A non-POSTthat reaches the member would be told401or400, never405.Generated by Claude Code
objectstack-fleet commentedon Oct 11, 2026
Claim: PM loop round 1
Session:
session_01B5CHJNXuuqzChM4w6hkTN4Account:
marchtianBranch:
claude/issue-22755-webhooks-redeliver-domainWorktree:
objectstack-issue-22755Domain:
domain:cliSeat:
domain:cli#1File surface:
packages/runtime/src/domains/(a newwebhooksdomain module and its tests),packages/runtime/src/http-dispatcher.ts(registration),packages/runtime/src/route-ledger.ts(the redeliver row), the dogfood authz census pairpackages/qa/dogfood/test/authz-conformance.matrix.ts/authz-probe-blind-spot.census.ts(and their tests) androute-ledger-live-mount-parity.dogfood.test.tsif the new route moves them,scripts/check-route-envelope.mjsonly if the new domain file must be declared there, a conformance pin underpackages/qa/http-conformance/if the end-to-end pin lands there, and one.changeset/22755-*.md. Widened by edit before the ACCEPT:packages/qa/http-conformance/package.json,packages/qa/http-conformance/vitest.config.tsandpnpm-lock.yaml(the devDependency and source alias the conformance pin needs, as in the precedent),scripts/engine-double-contract.pinned.json(written by the gate's own--writefor the new pinned fake), andpackages/qa/dogfood/test/authz-conformance.test.ts/authz-probe-blind-spot.test.ts(their counts) (PR #22842). ⛔ Nopackages/coreauth-gate change and nopackages/specchange. Read onorigin/mainb7cd1af9dfat 2026-10-11T11:13Z. Stop on a breach and explain it in the report.Container & model:
M,mode:subagent,model: default tier(dispatch-gates --tier --repo objectstack-ai/objectstack: "no path-derived mandate", floor · default · ceiling). Not mechanical: a new dispatcher domain with a per-request slot resolution and an end-to-end pin.Clause-②: no
Responsibility:
the runtime HttpDispatcher (this lane) has no /webhooks/redeliver domain, so a dispatcher-only kernel answers ROUTE_NOT_FOUND | plugin-webhooks' raw-app mount covers only a kernel with an http.server, never a hosted tenant kernel | an operator pressing redeliver on a hosted environment; the class was measured by the director record on #22438 (6079645593)Thread-read: 6106905545
Serial constraints cleared: no open PR touches
http-dispatcher.ts,route-ledger.tsorpackages/runtime/src/domains/(7 open PRs' file lists read). PR #22793 (epic:#15194stage 6a, draft) also editsauthz-conformance.matrix.ts; that is ordinary concurrency, and whichever lands second mergesmain. None of the 8 openpm:dispatchedclaims declares a runtime dispatcher file. Same-area sibling #22773 (this lane,area:workflow) edits the same registration and census files, so it is held hard-serial behind this card until this card's PR merges.Generated by Claude Code
objectstack-fleet commentedon Oct 11, 2026
os-dev-report
{
"issue": 22755,
"status": "done",
"branch": "claude/issue-22755-webhooks-redeliver-domain",
"pr": "#22842",
"session": "session_01B5CHJNXuuqzChM4w6hkTN4",
"premise_still_valid": true,
"summary": "packages/runtime: HttpDispatcher now serves exactly POST /webhooks/redeliver through a new domains/webhooks.ts, registered beside /approvals/act. It resolves the request kernel's webhooks slot PER REQUEST (plugin-webhooks registers it at kernel:ready, only once its veto installs), forwards context.request unread to IWebhookService.handleRedeliver and returns that Response untouched. An absent slot or member answers 501 NOT_IMPLEMENTED (never ROUTE_NOT_FOUND); a member throw or an already-consumed body answers a sanitised 500, logged. No preamble-gate change: unlike /approvals/act the credential is the session, so the ADR-0069 gate and the membership gate both apply (pinned), making the hosted door stricter than the self-hosted mount, never looser; packages/core and packages/spec untouched. All four PM mechanism assumptions measured: (1) premise TRUE on main b7cd1af (slot holds handleRedeliver, the hosted door answered 404 ROUTE_NOT_FOUND for authenticated and anonymous POST); (2) per-request resolution held and pinned; (3) anonymous: both doors answer the identical 401 UNAUTHENTICATED bytes, no gate/allow-list change needed or made; (4) non-POST: self-hosted 404 ENDPOINT_NOT_FOUND, hosted 404 ROUTE_NOT_FOUND (pinned), member never runs. The end-to-end pin is this card's: http-conformance drives the real plugin-webhooks member on a dispatcher-only kernel through createHonoApp (a replay lands in the real outbox) and holds every refusal byte-equal to the self-hosted mount. Census bookkeeping as the precedent: route-ledger row (server-only, 85 to 86), route-envelope declaration, dogfood authz row webhook-redeliver-session plus census/test counts, showcase parity pin. Worktree removed after the PR opened.",
"tests": "All on final head be4051a (branch + main efcbac7 merged; pnpm install --frozen-lockfile, full turbo build 73/73, rm -rf packages/runtime/.objectstack). runtime local project in 3 chunks: 104 + 123 + 123 files, 1985 + 1520 + 1546 passed (19 skipped); runtime repo project 3 files, 751 passed; runtime typecheck (src + test layer) 0, new test counted in the test-layer program via --listFiles. http-conformance 11 files, 117 passed; typecheck 0. dogfood authz-conformance + authz-probe-blind-spot + route-ledger-live-mount-parity: 3 files, 100 passed; typecheck 0. New pins: runtime domains/webhooks-redeliver.test.ts 13/13; http-conformance hono-webhooks-redeliver.conformance.test.ts 7/7. Ablations (committed state, via scripts/ablation-replace.mjs WRAP mode plus a shell trap; restore proven by blob == HEAD, empty git diff HEAD, clean porcelain): A) registration replaced by
void createWebhooksRedeliverDomain;, runtime dist rebuilt, ablation-dist-preflight --absent green (marker absent from all 6 built files, mutate leg confirmed): unit 10/13 red on ROUTE_NOT_FOUND (the 3 green are the gate pins, which refuse before route resolution), wire 5/7 red (404 for 200/501 and the anonymous parity row; the 2 green are the non-POST pin and the self-hosted control); restore: rebuilt, marker present in 2 dist files, tree clean, 13/13 + 7/7. C) slot guard disabled: exactly the 2 slot-absence pins red (TypeError reading handleRedeliver of undefined); member guard disabled: exactly the member-absence pin red (500 INTERNAL_ERROR for 501); restored 13/13. B) showcase parity pin renamed: 2/8 red,POST /webhooks/redeliver — LEDGERED BUT NOT MOUNTEDplus the stale pin, boot log shows plugin-webhooks' raw mount; restored 8/8. Lint: proven narrowing, see gates.","mcp_calls": "0 — no MCP GitHub tool was called (reads went through gh api REST reads: card, comments, PR read-back, check-runs, precedent card's comments)",
"api_writes": "2 relay strokes (POST /repos/objectstack-ai/objectstack/dispatches, each executed by fleet-write as objectstack-fleet[bot]) = 3 endpoints: POST /repos/objectstack-ai/objectstack/pulls (draft, #22842), POST /repos//issues/22842/assignees (marchtian), POST /repos//issues/22755/comments (this report). 0 label writes. git push x8 (not REST): the empty-branch probe, 6 commits, 1 merge commit.",
"open_questions": [],
"out_of_scope_findings": [
"carrier: the #22564 sweep owner (services seat) · noted, not filed — read while working: other raw-app mounts that a dispatcher-only kernel would not serve (metadata HMR registerMetadataHmrRoutes, cloud-connection marketplace proxy / local install / runtime config, the CLI console, trigger-api's inbound hooks which #22773 carries). The ruling's sweep names further class members; nothing here was measured on a hosted kernel. Dedupe words: getRawApp, raw-app mount, dispatcher-only kernel, hosted door"
],
"gates": "Derived from the actual diff (dispatch-gates --commands, no paths, --repo objectstack-ai/objectstack) at be4051a: 100 families = the dispatch list's 53 (all inside) + 47 the diff adds. All 100 exit 0 at be4051a; dispatch-gates --ran over the recorded exits: 100 derived, 100 run, 0 NOT-MEASURED, 0 UNRUN. Red on the way and fixed in-diff: check:route-ledger-census (85 to 86, --fix) and check:engine-double-contract (fake findOne now opens with assertEngineFindOnePredicate; pinned ledger --write +1 row). check:dual-build-cjs-loads first refused PREREQUISITE NOT MET (8 packages without dist), measured after the full build (107 entries / 66 packages). pnpm lint (lane blind spot): proven narrowing, not the full run — population = eslint.config.mjs files globs minus NEVER_LINTED = 12 of 16 diff files; eslint --no-inline-config --format json: 12 files, 0 errors, 0 warnings, 0 fatal, none ignored; invariance: no type-aware linting (no parserOptions.project, stated in the config) and the diff touches no config input. CI at report time: 12 checks completed (0 failed), 21 in_progress — in_progress.",
"line_budget": {
".changeset/22755-webhooks-redeliver-domain.md": "+18 -0",
"packages/qa/dogfood/test/authz-conformance.matrix.ts": "+27 -7",
"packages/qa/dogfood/test/authz-conformance.test.ts": "+2 -0",
"packages/qa/dogfood/test/authz-probe-blind-spot.census.ts": "+26 -11",
"packages/qa/dogfood/test/authz-probe-blind-spot.test.ts": "+7 -5",
"packages/qa/dogfood/test/route-ledger-live-mount-parity.dogfood.test.ts": "+7 -0",
"packages/qa/http-conformance/package.json": "+2 -0",
"packages/qa/http-conformance/src/hono-webhooks-redeliver.conformance.test.ts": "+359 -0",
"packages/qa/http-conformance/vitest.config.ts": "+14 -0",
"packages/runtime/src/domains/webhooks-redeliver.test.ts": "+322 -0",
"packages/runtime/src/domains/webhooks.ts": "+169 -0",
"packages/runtime/src/http-dispatcher.ts": "+6 -0",
"packages/runtime/src/route-ledger.ts": "+5 -1",
"pnpm-lock.yaml": "+6 -0",
"scripts/check-route-envelope.mjs": "+5 -0",
"scripts/engine-double-contract.pinned.json": "+5 -0"
},
"deviations": [
"Draft PR opened after verification finished rather than at the first showable commit: the role file also says the PR body is written once and never PATCHed, so I held the open until the numbers were final (the branch was pushed after every compilable step throughout).",
"Merged main (efcbac7, 3 commits, zero overlap) into the branch before opening the PR, per AGENTS.md section 10, and re-ran the full verification on the merge head be4051a.",
"One file outside the claim's named surface: scripts/engine-double-contract.pinned.json (+5), written by
node scripts/check-engine-double-contract.mjs --writeas that gate prescribes for new pinned coverage (not the shrink-only baseline). packages/qa/http-conformance/package.json, vitest.config.ts and pnpm-lock.yaml are the devDependency + source-alias the conformance pin needs, as in the precedent.","Commit trailers and the PR footer follow AGENTS.md and this order (model-free
Co-authored-by: Claudepair; session-URL footer), not the harness attribution reminder, which named a model and a different footer form.","First runtime test chunk returned exit 99 (queue-timeout, never acquired, a sibling's 9-minute run held the lock): read as NOT MEASURED and re-queued under the same slot name; not counted anywhere."
],
"files_changed": [
".changeset/22755-webhooks-redeliver-domain.md",
"packages/qa/dogfood/test/authz-conformance.matrix.ts",
"packages/qa/dogfood/test/authz-conformance.test.ts",
"packages/qa/dogfood/test/authz-probe-blind-spot.census.ts",
"packages/qa/dogfood/test/authz-probe-blind-spot.test.ts",
"packages/qa/dogfood/test/route-ledger-live-mount-parity.dogfood.test.ts",
"packages/qa/http-conformance/package.json",
"packages/qa/http-conformance/src/hono-webhooks-redeliver.conformance.test.ts",
"packages/qa/http-conformance/vitest.config.ts",
"packages/runtime/src/domains/webhooks-redeliver.test.ts",
"packages/runtime/src/domains/webhooks.ts",
"packages/runtime/src/http-dispatcher.ts",
"packages/runtime/src/route-ledger.ts",
"pnpm-lock.yaml",
"scripts/check-route-envelope.mjs",
"scripts/engine-double-contract.pinned.json"
]
}
Generated by Claude Code
objectstack-fleet commentedon Oct 11, 2026
✅ ACCEPT: PR #22842 at
be4051ae27domain:cliseat 1 (#6024) ·marchtian·session_01B5CHJNXuuqzChM4w6hkTN4· 2026-10-11T13:38Z · holder of claim6108426635. Report6109304930.Checked on GitHub, not taken from the report:
main, assigneemarchtian. The first line isFixes #22755, and no other closing keyword appears in the body.Clause-②: nois line-initial in the body and in the changeset.check-governed-merges --pr 22842: NOT governed.package.json/vitest.config.ts,pnpm-lock.yaml,scripts/engine-double-contract.pinned.json(written by the gate's own--write) and the two dogfood count tests.packages/coreorpackages/specfile is touched, and the allow-list is unchanged, as the card fenced.domains/webhooks.tsmirrors the/approvals/actprecedent: exactPOST /webhooks/redeliver, registered inhttp-dispatcher.ts.webhooksslot is resolved per request throughdeps.resolveServiceon every call, never at registration.501throughdeps.error.NOT_IMPLEMENTEDis an existing ledger code, so no new code.INTERNAL_ERROR_MESSAGE500, with the original logged.Clause-②: yes, nopackages/spec/srcpath and no governed text, so no contract-tier review is owed (contract-review.md). This seat read the diff.be4051ae27, latest run per name: 34success, 2skippedby design.Lint & Repo GatesandTypeScript Type Checkare bothcompleted: success.mergeable_state: clean.POST, request forwarded unread, the service read on every request, itsResponsereturned as is).501for an absent service or member, "naming which" (two distinct messages).500.POST404 ROUTE_NOT_FOUND.PM mechanism assumptions, as the dev measured them:
404 ROUTE_NOT_FOUNDbefore the change.401 UNAUTHENTICATEDbytes on both doors.POSTgets404on both doors (different codes, pre-existing), and the member never runs.The end-to-end pin through the real plugin-webhooks member is in
hono-webhooks-redeliver.conformance.test.ts, as the review on PR #22797 routed here. The dev's ablations (registration removed, slot guard and member guard disabled) each turned exactly the expected pins red.Findings: the further raw-app mounts a dispatcher-only kernel would not serve go to the #22564 sweep owner (
domain:services), not filed here. Disposition: Acceptance notes,carrier:the sweep.Landing next: ready, then auto-merge through the queue. #22773 is held hard-serial behind this PR (
6108474120).Generated by Claude Code
objectstack-fleet commentedon Oct 11, 2026
Landed: PR #22842 →
8558668a68domain:cliseat 1 (#6024) ·marchtian·session_01B5CHJNXuuqzChM4w6hkTN4· 2026-10-11T14:10Z8558668a68106b94917023256b31828f93de2230. It is a single-parent squash and an ancestor oforigin/main. Its file list is the 16 accepted files (+980 / −24).completedby the PR'sFixesline.pm:dispatchedis stripped in this act;domain:cli,area:workflow,priority:p2andbugstay.domain:cliset lost runtime: an exact/webhooks/redeliverdispatcher domain that forwards to the declared redeliver member, with a typed refusal for an absent slot (webhooks segment 2 of #22564's stage 2) #22755 only, as expected.POST /automation/hooks/:flowName/:hookIddispatcher domain and its parameterised ADR-0069 allow-list row, anonymous through to the trigger's HMAC verifier only (trigger-api segment 2 of ruling A on #22757) #22773 (the/automation/hooks/:flowName/:hookIddomain), held hard-serial behind this card on the same registration, ledger and census files (6108474120). It is dispatchable from thismain.Generated by Claude Code