spec(idempotency): declare capabilities.idempotency.in_flight_max_seconds#4409
Merged
Merged
Conversation
…onds Closes #4406. Follow-up to #4402 (rules 9 + 10 + IDEMPOTENCY_IN_FLIGHT). Rule 9 bounds in-flight row lifetime to the seller's per-task handler timeout but the bound is not buyer-observable today — the existing capabilities surface declares replay_ttl_seconds only (1h–7d), much wider than a realistic handler timeout. Buyers retrying on IDEMPOTENCY_IN_FLIGHT have no way to compute a tight retry budget. This adds an optional in_flight_max_seconds field to the IdempotencySupported branch of adcp.idempotency: - Optional in 3.1 (additive; SDKs that don't see it fall back to rule 9's order-of-magnitude SHOULD heuristic). - Required when supported: true in 4.0 (same migration path replay_ttl_seconds followed across 2.x → 3.x). - Bounded integer >= 1, <= 604800 at the schema layer; cross-field bound (<= replay_ttl_seconds) enforced by composed-schema test suite since JSON Schema cannot express field-relative bounds. - Forbidden on IdempotencyUnsupported branch (mirrors the existing replay_ttl_seconds treatment — no replay window means no in-flight bound). Rule 9 in security.mdx updated to point at the new capability field as the primary retry-budget bound when declared (Option A per the triage design pass); the order-of-magnitude heuristic remains the fallback when the field is absent. Composed-schema validation suite gains 5 new tests: - IdempotencySupported with in_flight_max_seconds accepts - Rejects in_flight_max_seconds: 0 (below minimum 1) - Rejects in_flight_max_seconds on unsupported branch - Schema accepts in_flight_max_seconds > replay_ttl_seconds at the schema layer (programmatic cross-field assertion catches it separately) - Cross-field assertion: in_flight_max_seconds > replay_ttl_seconds is detected 40/40 tests pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #4406. Follow-up to #4402 (rules 9 + 10 + IDEMPOTENCY_IN_FLIGHT).
Rule 9 bounds in-flight row lifetime to the seller's per-task handler timeout — but that bound is not buyer-observable today. The existing capability surface declares
replay_ttl_secondsonly (1h–7d), much wider than a realistic handler timeout. Buyers retrying onIDEMPOTENCY_IN_FLIGHThave no way to compute a tight retry budget.This adds an optional
in_flight_max_secondsfield to theIdempotencySupportedbranch ofadcp.idempotency:supported: truein 4.0 — same migration pathreplay_ttl_secondsfollowed across 2.x → 3.x.integer ≥ 1, ≤ 604800at the schema layer; cross-field bound (≤ replay_ttl_seconds) enforced by the composed-schema test suite since JSON Schema cannot express field-relative bounds.IdempotencyUnsupportedbranch — no replay window means no in-flight bound (mirrors the existingreplay_ttl_secondstreatment).Spec text
Rule 9 in
security.mdxupdated to point at the new capability field as the primary retry-budget bound when declared (Option A per the triage design pass) — the order-of-magnitude heuristic remains the fallback when the field is absent.Schema changes
IdempotencySupported:in_flight_max_seconds: integer ≥ 1, ≤ 604800IdempotencyUnsupportedbranch'snotclause widened fromrequired: [replay_ttl_seconds]toanyOf: [{required: [replay_ttl_seconds]}, {required: [in_flight_max_seconds]}]— both fields forbidden on the unsupported branch.Tests added
Composed-schema validation suite gains 5 new tests:
IdempotencySupported with in_flight_max_seconds: {supported: true, replay_ttl_seconds: 86400, in_flight_max_seconds: 60}acceptsRejects in_flight_max_seconds: 0 (below minimum 1)Rejects in_flight_max_seconds on unsupported branchin_flight_max_seconds > replay_ttl_secondsat the schema layer (programmatic cross-field assertion catches it separately, mirroring how other field-relative bounds are tested in this suite)40/40 composed schema tests pass.
Design choices (from the issue triage)
replay_ttl_secondsfollowed. Optional now avoids breaking every existing seller's capability response on the 3.1 upgrade.Test plan
node tests/composed-schema-validation.test.cjs— 40/40 passnode scripts/build-schemas.cjs— cleannode scripts/lint-storyboard-check-enum.cjs— clean🤖 Generated with Claude Code