Skip to content

Make Action.expires_at optional, so an action without a deadline need not invent one - #25

Merged
yahalomran merged 1 commit into
masterfrom
maoryeh/action-expires-at-optional
Sep 21, 2026
Merged

yahalomran merged 1 commit into
masterfrom
maoryeh/action-expires-at-optional

Conversation

@maoryeh

@maoryeh maoryeh commented Sep 13, 2026

Copy link
Copy Markdown
Collaborator

Action required type, status, continue_url and expires_at. The last of
those is the only one a conformant business can be unable to state truthfully:
an action that simply has no deadline has no value to put there, and the schema
left inventing one as the only way to validate.

The specification already settled this question the other way one level up.
Booking.expires_at is optional, and its description says why — "a business
that does not hold slot capacity for a pending or requires_action booking MAY
omit this field" — because an advertised expiry is a claim the business must
then honour, and a business that enforces no deadline should not be made to
publish one. An action is in exactly that position. §8.5.4 even acknowledges the
asymmetry in passing: the payment-action clock is "independent of whether the
booking advertises expires_at", and the action's expiry "SHOULD be no later
than the booking's expires_at when the booking advertises that field" —
prose that already contemplates the booking having none, while the schema
refused the action the same freedom.

What an absent value means is now stated rather than left to the reader: the
business sets no deadline, and a platform MUST NOT infer one. The obligation
runs the other way for a business that will expire the action — it MUST
publish expires_at, because a deadline the platform cannot see is one it
cannot act on, and the buyer finds out about it only when the booking is
already canceled. Omitting the field is a statement about this business, not a
way out of §8.5.4.

Also reworded the two places in §5 that enumerated an action's fields as
"type, status, continue_url, expires_at". Those read as a list of what
is always present, and they are the sentences an implementer checks before
opening the schema.

continue_url is deliberately left REQUIRED. It is tempting to read §8.5.5's
"not applicable to the acp or embedded checkout paths" as making it
conditional too, but §8.5.4 says the opposite in terms: "Every action includes a
continue_url", and an embedded platform SHOULD send the buyer there for
buyer-side steps such as 3-D Secure "regardless of the declared
checkout_systems value". It is the universal escalation hatch, not a
redirect-mode field, and §8.5.5 scopes only the post-payment return mechanics.

schemas, refs and vectors pass.


Found while auditing a Standalone embedded implementation against the schema: it emits payment actions that genuinely have no deadline, and there was no conformant way to express that.

🤖 Generated with Claude Code

…ed not invent one

Rebuilt onto current master (branch had diverged at the root). Still needed: master's
`schemas/booking.json` keeps `expires_at` in `Action.required`, so the gap this closes
is open. CHANGE_LOG.md was the only conflict; both entries kept, newest-first.
Also drops the accidentally committed .pyc and adds a .gitignore.

schemas / refs / vectors / coherence all pass.
@maoryeh
maoryeh force-pushed the maoryeh/action-expires-at-optional branch from bfaa439 to 43211b7 Compare September 21, 2026 11:59
@yahalomran
yahalomran merged commit 996f5e4 into master Sep 21, 2026
1 check passed
@yahalomran
yahalomran deleted the maoryeh/action-expires-at-optional branch September 21, 2026 12:41
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.

2 participants