Skip to content

fix(async): complete beta.5 webhook convergence - #2660

Merged
bokelley merged 2 commits into
mainfrom
track-sdk-regeneration-fields
Aug 23, 2026
Merged

fix(async): complete beta.5 webhook convergence#2660
bokelley merged 2 commits into
mainfrom
track-sdk-regeneration-fields

Conversation

@bokelley

Copy link
Copy Markdown
Contributor

Summary

  • carry the buyer operation ID in beta.5 application-layer webhook registration across MCP, in-process MCP, and A2A while keeping native A2A push configuration distinct
  • reject missing or malformed beta.5 operation IDs before seller dispatch, preserving older wire behavior
  • converge terminal webhook re-emissions across delivery keys with seller, buyer-operation, and task scoping
  • return canonical completed, failed, and rejected task artifacts when polling with include_result
  • document the beta.5 migration and add a patch changeset

Validation

  • npm run typecheck
  • npm run ci:codegen-strict
  • npm run format:check
  • npm run test:protocols
  • 10 changed-area suites, 528 tests passed
  • protocol, code, and security expert reviews: SHIP
  • npm run review:codex -- --all --base main: no blocking findings

@bokelley
bokelley enabled auto-merge (squash) August 23, 2026 03:20
taskId: metadata.task_id,
taskType: metadata.task_type,
status: metadata.status,
notificationId: metadata.notification_id ?? null,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Medium: Adding notificationId: metadata.notification_id ?? null to the fingerprint changes the hash for every v2 entry, not just ones carrying a notification_id — the ?? null folds the field into the canonicalized object unconditionally. A handled-marker or in-flight claim written before this deploy (fingerprint computed without the field) will mismatch the same webhook's post-deploy at-least-once retry (fingerprint now includes notificationId: null), so webhookHandledFingerprint/webhookActiveClaimFingerprint at L883/L890 throw WebhookDedupConflictError → 5xx → publisher retries again → conflict storm on already-handled/in-flight events for the full dedup TTL (default 24h) after upgrade. This is the exact continuity break the v1→v2 key namespace split was created to avoid. Consider omitting the key when absent (...(metadata.notification_id !== undefined && { notificationId: metadata.notification_id })) so pre-existing fingerprints stay stable and only genuine beta.5 events differ.

if (record.statusMessage) payload.message = record.statusMessage;
if (record.status === 'completed' && record.result !== undefined) {
if (
args.include_result === true &&

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Medium: Behavior change on tasks_get, and it is not version-gated. Previously record.status === 'completed' && record.result !== undefined returned result unconditionally; now completed results require args.include_result === true. Any existing tasks_get consumer that read result on a completed task without passing include_result now gets undefined — on every served version, not only beta.5. This aligns tasks_get with get_task_status (which already gated on include_result) and the migration doc documents it as intended, so it is arguably a drift fix — but it is a default-response narrowing for a stable wire tool shipping under a patch changeset. Confirm patch is the right severity given a previously-returned field is now omitted by default.

aao-secretariat[bot]
aao-secretariat Bot previously approved these changes Aug 23, 2026

@aao-secretariat aao-secretariat Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ladon verdict: Approve

Approve — clean, heavily-tested beta.5 async adoption with no blocking findings.

What I checked

  • Wire-shape logic in prepareProtocolToolCall, governance fail-closed path, and postgres/in-memory terminal-status fencing — all correct and covered by tests.
  • Witness-not-translator posture preserved; no fabrication or re-shaping at seams.
  • Changeset present (.changeset/warm-webhooks-converge.md) for the src/lib/** changes.
  • high_risk is true only because src/lib/protocols/index.ts was (modified); no medium-or-higher finding on that file, so the modification is presumed safe. No deletions.

Medium findings (non-blocking; 2 total, falls through to row 9)

  • src/lib/core/AsyncHandler.ts:908 — Fingerprint schema change breaks webhook dedup continuity across upgrade.
  • src/lib/server/decisioning/runtime/from-platform.ts:3479tasks_get completed result now gated behind include_result, not version-gated.

Two medium findings (neither in data-loss/schema/infra category), no critical/high, no gated-paths gate (gated_paths: false), no no-auto-approve team match, and high_risk (modified) has no accompanying medium on the modified high-risk file. Rows 1–8 do not fire → row 9 approve. The low defensive-throw note is informational.

Medium findings

  • src/lib/core/AsyncHandler.ts:908 — Fingerprint schema change breaks webhook dedup continuity across upgrade
  • src/lib/server/decisioning/runtime/from-platform.ts:3479 — tasks_get completed result now gated behind include_result, not version-gated

@aao-secretariat aao-secretariat Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ladon verdict: Approve

Approve.

This subsequent-review delta is test-only: it adds the now-required push_notification_config.operation_id field to three test cases and one YAML fixture (create_media_buy_async_submitted.yaml) that previously omitted it. All added values conform to the ^[A-Za-z0-9_.:-]{1,255}$ pattern the PR enforces for beta.5. No library code changed in this delta.

The two prior medium findings (AsyncHandler.ts:908 fingerprint schema continuity, from-platform.ts:3479 tasks_get include_result gating) are absent from the current run and not re-raised — the prior decision was already approve.

Decision-table walk: no critical/high findings (row 1 no); gated_paths is false (row 2 no); high_risk is true but the only high-risk match is src/lib/protocols/index.ts (modified) with no medium finding attached to it (rows 3–5 no); prior decision was approve, so sticky escalation row 6 does not apply; no no-auto-approve team match (row 7 no); zero medium findings, well under the 3-medium threshold (row 8 no). Falls through to row 9 → approve.

@bokelley
bokelley merged commit 3618dac into main Aug 23, 2026
32 checks passed
@bokelley
bokelley deleted the track-sdk-regeneration-fields branch August 23, 2026 03:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant