Skip to content

PayPal sandbox only. No real money moves.

LearnHow it works

Honor period and reauthorization

How long a hold can be captured, what GAVEL does about it, and exactly what gate G3 is testing on the real sandbox.

In progressa real run has started and has no result yet

Page last changed 7 Nov 2026 (from the git history)

In plain words

PayPal does not let a hold stay capturable forever. An authorization has an honor period: PayPal promises to honor a capture for a limited time after the hold, and may decline later ones. The authorization is also valid for a longer window. A reauthorization asks PayPal to renew the reservation, which is only useful in an auction that runs for days.

GAVEL's demo creates holds minutes before the capture, so none of this matters there. It matters for a multi-day auction. Because PayPal's real numbers are what is uncertain, GAVEL ships with reauthorization off and a real sandbox probe, gate G3, running to measure them.

Honor period and reauthorization: the model, the simulation and the real G3 probe

Model and simulationG3 in progress
Honor period and reauthorization: the model, the simulation and the real G3 probeA timeline in days from 0 to 6, with a marker at day 29. First lane: one hold in the fake PayPal model, held for a 3 day honor period, with a stale flag after 2 hours, a reauthorization threshold at 2.75 days, and a validity limit at 29 days. Second lane: the simulated reauthorization at day 3.04 which starts a new honor clock, and a capture at day 5. Third group: the real sandbox probe gate G3, one authorization checked at day 3.5, 4 and 5, plus an immediate reauthorize test at day 0. The real probe has no result yet.day 0day 1day 2day 3day 4day 5day 6...day 29validity endsOne holdfake PayPal modelhonor period, 3 days (modelled)strict model: capture refused2 h: stale flag2.75 d: reauth threshold2.75 to 3 d: reauth refused as too early (S2)Reauthorizedsimulated S4day 3.04: reauthorize, new id, new clocksecond honor clockday 5: capture (S4)Real sandbox probe: gate G3, in progressday 0 = 7 Nov 2026 03:06 UTC. At each checkpoint: read, capture 1.00 (not final), reauthorize, read again.G3.1 freshday 0: immediate reauthorize, then voidauthorization 1?3.5 d, 10 Nov 15:06 UTC: no result yetauthorization 2?4 d, 11 Nov 03:06 UTC: no result yetauthorization 3?5 d, 12 Nov 03:06 UTC: no result yetHow the probe decides (decideG3)all three captures succeed: PASS, no reauthorization, keep the stale flaga capture fails and a reauthorize works: PASS-WITH-FALLBACK, enable reauthorization (GAVEL_REAUTH)a capture fails and no reauthorize works: FAIL, create holds minutes before capture and document itheldchargedreleasedneeds review

Scroll the figure sideways, or open it full size.

Model: Past the honor period. Strict model: a capture is refused and a reauthorization is allowed and gives a new authorization with a new honor clock. Lenient model: the capture still works. Which one PayPal follows is what G3 measures.

Real probe: checkpoint 1 of 3 (day 3.5) is due. No result is recorded yet.

Hover or focus a marker or bar for what it means and which file it comes from.

The honor period (3 days), the validity (29 days) and the reauthorization rules in the first two lanes are the fake PayPal model in packages/payments/src/fake/core.ts (assumptions A07 to A11, all unverified) and the simulated scenarios S2 to S5 in docs/evidence/SIM/SIM-MULTIDAY.md; PayPal's real values are not verified. The third group is the real probe in packages/payments/gates/g3.ts and g3-timed.ts, run by .github/workflows/gate-g3.yml with day 0 on 7 Nov 2026 03:06 UTC. Gate G3 is IN PROGRESS; the final reading is about 12 Nov 06:17 UTC and no result is claimed here.
Text version of this diagram
  • Model: an authorization is held for a 3 day honor period and is valid for 29 days. A capture after the honor period is refused in the strict reading (the simulation uses it). A reauthorization is refused inside the honor period and, after it, returns a new authorization with its own id and a new honor clock.
  • Policy: reauthorization is off by default (GAVEL_REAUTH). When on, a hold older than 2 days 18 hours is reauthorized before the capture, once, never above its ceiling. A hold older than 2 hours at settlement start is only flagged stale and is still captured.
  • Simulation: S2 closes at day 2.5 and captures inside the honor period, and a too-early reauthorization at day 2.9 is refused without blocking the capture. S3 captures at day 3.5 with reauthorization and, with it off, nobody is charged. S4 reauthorizes at day 3.04 and captures at day 5. S5 lets holds expire at day 30 and the runner-up is charged its own price.
  • Real probe G3 (in progress, day 0 is 7 Nov 2026 03:06 UTC): day 0 tries an immediate reauthorize on a fresh authorization and creates three authorizations. At 3.5, 4 and 5 days (10 Nov 15:06, 11 Nov 03:06, 12 Nov 03:06 UTC) it reads one, tries a 1.00 partial capture, tries a reauthorize and reads again. No result is recorded yet.

What GAVEL does about it

At settlement start, a hold older than GAVEL_HOLD_MAX_AGE_MS (default 2 hours) is flagged stale and one stale_hold audit row is written. It is a flag only: the hold is still captured. It tells an operator that a hold has aged.

What gate G3 tests

G3 asks: how long does an authorization stay capturable, and does reauthorize extend it? The probe in packages/payments/gates/g3.ts runs from the gate-g3 workflow:

Day 0

A headless browser signs in as the sandbox buyer and approves four orders. One fresh authorization gets an immediate reauthorize attempt (its error name is recorded) and is voided. Three others are kept, one per checkpoint, and the creation time is saved in the probe state.

Checkpoints at 3.5, 4 and 5 days

Scheduled runs (minute 17 of every sixth hour) pick the saved state up. At each checkpoint that is due, the probe reads the authorization, tries a 1.00 partial capture (not final), tries a reauthorize, and reads again. With day 0 at 7 Nov 03:06 UTC, the checkpoints are due on 10 Nov 15:06, 11 Nov 03:06 and 12 Nov 03:06 UTC.

The decision

decideG3 applies a fixed rule once the three checkpoints are done:

ObservationDecisionConsequence
all three captures succeedPASSno reauthorization needed; keep the stale flag
a capture fails and a reauthorize worksPASS-WITH-FALLBACKenable reauthorization
a capture fails and no reauthorize worksFAILcreate holds minutes before capture and document it

The state travels between runs as an artifact; the final run writes the GATES.md entry. There is also an early reading of two older G2 authorizations (gate-g3-early.yml); no result from it is recorded in GATES.md.

G3 IN PROGRESS

What the simulation shows, and what it does not

SIMULATED Scenarios S2 to S5 of the 30 day simulation run GAVEL's own code over simulated days against the fake PayPal model, with a fake clock: a capture inside the honor period needs no reauthorization (S2); a capture at day 3.5 works with reauthorization and charges nobody without it (S3); a reauthorization at day 3.04 lets a capture at day 5 succeed (S4); holds never reauthorized expire cleanly and the runner-up is charged its own price (S5). The ledger balances to the cent in each.

That shows GAVEL behaves correctly if PayPal follows the model. It says nothing about whether PayPal does; G3 is the check. See the simulation and Gates.

Prop

Type

Where this lives in the code

Edit on GitHub

Last updated on