Evidence

Running it

The checks that run every night from outside, the failure cases you can run now, every test suite, and how it holds under load.

Checked every night, from outside

Reading the latest run…

25 checks run every night on Render Workflows, and on demand.

Failure cases, run live

Each run creates small sandbox orders. No real money moves.

All eight, with what should happen
  • The donor's card is declined

    Nothing is charged, nothing is marked paid, and the donor sees a plain next step.

    Not run yet

  • The donor clicks Pay twice

    PayPal charges once. Both clicks get the same capture.

    Not run yet

  • Someone tries to complete a payment PayPal has not approved

    PayPal refuses, nothing is charged, and the message is plain.

    Not run yet

  • A browser tries to change the amount or the payee

    The server ignores both. Amount and payee come only from the need record.

    Not run yet

  • A gift would lower her check

    The rules engine skips that route and sends the money a benefit-safe way.

    Not run yet

  • An AI reviewer gets the rule wrong

    Its quote is not in its rulebook, so the referee sets it aside and her check stays whole.

    Not run yet

  • Someone edits a past ledger entry

    Recomputing the chain finds the exact entry that changed.

    Not run yet

  • Only the shop can send money back

    Giftwise cannot pull money from a shop. PayPal allows the refund only from the account that received it.

    Not run yet

Test results

What each checks, and its command

The PayPal suites, step by step

Real PayPal checkout, logged in as the sandbox buyer: 14 of 14, November 9, 2026, 18 steps in 41.2 s
StepPayPalAt
need button creates an order4.8 s
the need order, as createdorder 8XL1701886187253P; 1 payee; PAYER_ACTION_REQUIRED4.8 s
PayPal checkout opens for that order6.5 s
need checkout asks the donor for no shipping address10.8 s
card shows it paid, with the buyer's name13.7 s
PayPal says the need order is COMPLETED14.5 s
PayPal's record of the need orderorder 8XL1701886187253P; 1 payee; COMPLETED; captures 22K29357G9671360815.0 s
public receipt for the need order15.0 s
Give any amount creates one routed order17.6 s
the routed order, as createdorder 0HR89776MY849324R; 4 payees; PAYER_ACTION_REQUIRED17.6 s
PayPal checkout opens for the routed order20.9 s
routed checkout asks the donor for no shipping address31.0 s
thank-you shows every payee captured, each once38.1 s
thank-you lists the same lines, in the same order, as the preview38.1 s
needs the gift covered show as paid without a reload38.1 s
PayPal says the routed order is COMPLETED39.1 s
PayPal's record of the routed orderorder 0HR89776MY849324R; 4 payees; COMPLETED; captures 4VE01614J5227092P, 68552514CD769774K, 2PJ75858779200138, 0HD57516W7543664540.0 s
public receipt lists every capture, one line per purchase unit41.0 s
API end to end: 130 of 130, November 10, 2026, 133 steps in 43.2 s
StepPayPalAt
check-gift cash $1,000 -> $740.1 s
check-gift vendor $420 -> $9940.1 s
check-gift rent $800 monthly -> $662.670.1 s
check-gift ABLE rent -> $9940.1 s
check-gift a home given as itself counts at the presumed maximum value -> $662.67 (POMS SI 00835.400 F)0.2 s
check-gift a co-owner's $1,600 for eight months counts $200 in February -> $814 (POMS SI 00835.360 D.3)0.2 s
check-gift rent $130 below market from a child, $280 paid, counts $71.33 (POMS SI 00835.380 D)0.2 s
plan-month values a co-owner's payment in each of the eight months it covers0.2 s
check-gift covers that end before they start -> 4000.2 s
check-gift envelope has meta.request_id, rules_version, citations with urls0.2 s
check-gift default date (today) works0.2 s
check-gift bad JSON -> 400 invalid_request0.3 s
check-gift negative amount -> 4000.3 s
check-gift unknown delivery -> 4000.4 s
plan-month shares the $60 exclusion across the quarter (50 then 10)0.4 s
plan-month empty list -> 4000.4 s
preset wheelchair-repair download + expected result0.4 s
preset birthday-cash download + expected result0.4 s
preset electric-bill download + expected result0.4 s
preset rent-help download + expected result0.4 s
preset laptop-college download + expected result0.4 s
preset groceries download + expected result0.4 s
preset van-fundraiser download + expected result0.4 s
preset march-month download + expected result0.4 s
preset CSV download has header + 6 rows0.4 s
unknown preset -> 4040.4 s
read-bill with a broken image -> friendly 422 (or 503 without AI)0.4 s
read-bill replayed reads the electric bill as a $138 utility and routes to ABLE0.5 s
analyze-fundraiser replayed plans every use so her check stays $10290.5 s
analyze-fundraiser rejects non-http url0.5 s
review-bill without a description -> 4000.5 s
review-bill replayed: both reviewers quote their own rulebook, agree it is housing, and the engine routes to ABLE at $9940.5 s
openapi lists review-bill with its request schema0.5 s
openapi lists the letter reader and the manage link's profile0.5 s
gift-pages: the lift is paid straight to the shop, rent goes to the ABLE account, check stays $10290.6 s
the new page reads Help Jordan and uses their, never her or she0.6 s
gift-pages: a need toward a home goes to the ABLE account0.7 s
gift-pages with his own situation: his check is $106, not $1029, and both needs keep it0.7 s
his gift page shows his check, $106, from his own situation0.7 s
manage link reads his situation: own, from his answers, with the fields given0.8 s
manage link puts the page back on the sample situation: $10290.8 s
manage link sets his facts again, read from his letter0.8 s
manage link refuses a negative amount0.8 s
read-letter replayed: the sample letter's $106 for January 2027 matches the engine, every quote is in its text, and nothing private comes back0.8 s
read-letter with no file -> 400 (or 503 without AI)0.8 s
gift-pages rejects a name that is not letters0.8 s
paypal order for need 4 created (sandbox)1.9 s
the need order, as created (never approved: the API suite moves no money)order 26F53216UM334992W; 1 payee; PAYER_ACTION_REQUIRED1.9 s
paypal order for unknown need -> 4041.9 s
paypal order with bad id -> 400 (or 403 from the host firewall)1.9 s
capture unknown order -> 4041.9 s
capture path traversal -> not 2001.9 s
capture before buyer approval -> PayPal refuses, app returns plain error2.6 s
gift-orders $1,500 -> one order, every open need plus ABLE3.8 s
gift-orders plan keeps her full check, cash would not3.8 s
gift-orders lines add up to the gift3.8 s
live order check returns each payee unit from PayPal4.2 s
the routed $1,500 order, read back from PayPalorder 1J410122JJ374220G; 5 payees; PAYER_ACTION_REQUIRED4.2 s
receipt page renders for a started order4.2 s
gift-orders $0 -> 4004.2 s
gift-orders unknown page -> 4044.2 s
live order check with bad id -> 4004.2 s
live order check on the recorded multi-payee order -> 200 COMPLETED, every capture5.4 s
receipt for unknown order -> not-found page, noindex5.5 s
ledger verifies end to end5.5 s
key created, shown once, gw_test_ plus 43 base62 characters5.5 s
key without accepting terms -> 4005.5 s
keyed call works and returns rate-limit headers5.6 s
unknown key -> 401 unauthorized5.6 s
usage lists the key and its call5.6 s
revoke from another browser -> 4045.6 s
rotate: old key stops, new key works5.6 s
openapi.json is 3.1 and lists every endpoint5.6 s
unknown preset -> 404 in the standard envelope5.6 s
ssa-report October as given: 5 gifts, nothing counts, check stays $994, due November 105.8 s
ssa-report records every gift with a rule and a cited source5.8 s
ssa-report the same October as cash: 5 gifts to tell SSA, $538 counted, check $456, a call script5.9 s
ssa-report CSV download has a header and one row per gift6.2 s
ssa-report bad month -> 4006.2 s
ssa-report unknown page -> 4046.2 s
report page renders the verdict and the PayPal proof column6.5 s
checks: the workflow can list the eight failure cases6.5 s
checks: running a case without the secret -> 401 (or 503 if the server has none)6.5 s
checks: paying the card check without the secret -> 401 (or 503 if the server has none)6.6 s
checks: filing a run with the wrong secret -> 401 (or 503 if the server has none)6.6 s
checks: a malformed run with the right secret -> 400 with details6.6 s
workflow jobs: the active monthly gifts are listed by id and one month is planned ahead, with its split6.6 s
workflow jobs: listing monthly gifts without the secret -> 4016.6 s
workflow jobs: the rulebook index rebuilds on Elastic, or reports Elastic is not connected12.8 s
checks: the latest run is public, with a pass count12.8 s
checks: starting a run needs Render Workflows (503 here) or is rate limited (429)12.8 s
MCP initialize names the server and agrees a protocol version12.8 s
MCP notification -> 202 with no body12.8 s
MCP lists the nine tools with input schemas12.9 s
MCP start_monthly_gift returns the giver's page, nothing charged, check stays $102912.9 s
MCP plan_gift splits $500 so her check stays $1029 (cash would be $609)13.0 s
MCP check_gift counts a home given as itself at the presumed maximum value -> $662.67 (POMS SI 00815.550 C.2)13.0 s
MCP check_gift values rent below market from a child as $351.33 less the $280 paid -> $942.6713.0 s
MCP plan_gift puts $1,500 toward her home through the ABLE account, check stays $102913.1 s
MCP get_gift_page reads his own situation and his $106 check13.1 s
MCP plan_gift keeps his own check whole at $106; as cash it would be lower13.1 s
MCP get_ssa_report: October needs no income report, due November 1013.3 s
MCP bad arguments come back as a tool error the agent can read13.3 s
MCP unknown method -> JSON-RPC -3260113.3 s
check-gift a $25 weekly rent counts $108.33 a month -> $905.67 (POMS SI 00835.474 B.3)13.3 s
plan-month divides a $1,200 tax bill between two in the household: $351.33, then $50 and $50 (POMS SI 00835.474 B.2)13.4 s
check-gift with $101,000 in ABLE and $1,500 saved pays no SSI, ABLE the reason (POMS SI 01130.740 D.1.c)13.4 s
check-gift an ABLE gift past $100,000 says the check stops and routes it elsewhere13.4 s
MCP check_gift takes the ABLE balance: past $100,000 and over the limit, $0 and the item route instead13.4 s
check-gift paying $100 of a $150 share says the household already takes a third: $662.67 (POMS SI 00835.160 G)13.4 s
check-gift a utility bill paid as a loan she repays in full counts nothing (POMS SI 00835.482 G.4.c)13.4 s
MCP check_gift: paying $175 toward a $150 share is sharing, so the check is the full $99413.5 s
unsigned PayPal webhook is refused13.5 s
org payouts over the per-household sandbox limit -> 40013.5 s
org payouts to an unknown page -> 42213.5 s
org payouts preview routes a $10 grant and keeps the check at $102913.5 s
org payouts sends one PayPal Payouts batch14.5 s
the fund's $10 grant as one PayPal Payouts batchbatch QEEN7WYZXGGXJ; 1 payee; PENDING14.5 s
PayPal reports the batch sent, with a transaction id for every item40.4 s
each paid item is checked against PayPal's transaction report40.4 s
unknown payout batch -> 40440.4 s
rules-watch: the Federal Register answers live, every SSI income rule and amounts notice is reviewed, 2027 amounts in use40.4 s
report code: October's report names its check page, and the page says it matches40.7 s
report code: October is all sample year, and its check page says PayPal was not asked40.7 s
report code: the recorded order's month asks PayPal for every capture, and every one is completed42.1 s
report code: a code that does not match shows the current report's code42.4 s
ask-rules: the phone bill question finds SSA's own passage on bills paid by someone else, and every quote it shows is checked42.9 s
ask-rules: a question that is too short gets a plain 40043.0 s
discovery: the AI Catalog lists the MCP Server Card, and the card names /api/mcp with its protocol versions43.0 s
discovery: the Server Card answers 304 to a matching ETag43.0 s
llms.txt names the MCP server and every tool43.0 s
security headers: no framing by other sites, nosniff, a referrer policy, and HSTS43.0 s
the gift page has its own share image43.2 s

Under load

On the deployed site: 10 visitors at once, 3 rounds, 60 requests in 3.4 seconds, November 8, 2026

On a laptop: 100 visitors at once, 3 rounds, 600 requests in 18.9 seconds, November 7, 2026

The exact method and machines

Running it for real