The platform declares 147 economy actions. 27 have no legitimate UI path — a crafted cross-tenant API probe is not something a person does — which leaves 120 a persona could perform in a browser. 120 of those have a macro (100%), and this run captured 120 of them against the deployed proving tier through the real sign-in — no mocks, no minted tokens. Failed units keep their recording and their error; units that could not run say why. The 0 actions nothing drives are named under Gaps, each with the reason. A gallery of only the successes would not be evidence.
What driving the platform actually caught. Coverage says how much was exercised; this says what came back. Each entry opens to the whole account of the defect.
A full run deploys billing, admin, auth, account and notify. delivery, developer, foundry, sigil and store are reported by check_deployed_versions.py as having no deployed-version record -- as WARNINGS, so the run still succeeds. "Deployed proving" can mean half of it. AUDIT 2026-08-28: STILL -- check_deployed_versions.py:50-55 warns on a missing non-orchestrated record, :62-65 fails only with --strict, and production_deploy.py:610-620 runs it without --strict; ran today: 5 warnings (delivery, developer, foundry, sigil, store), exit 0. The --only attested path (deploy_attested_repo.py) records nothing. Fix: --strict from production_deploy.py:614 and a record step in --only.
scripts/check_deployed_versions.pyThe catalog, the console's hand-copied duplicate, account's own grant rule, LiveOps' raw-role check, billing's per-route role lists, and each repo's vendored mirror. Every authorization defect above is a drift between two of them; undef-developer's mirror was found silently stale. End state: the console computes no authority at all and the server returns effective capabilities. AUDIT 2026-08-28: CHANGED -- 2 of 6 copies retired: the console's duplicate went at undef-admin b85d03ee (gated by tests/test_console_computes_no_authority.py); the catalog (undef-authz roles.json, 12 roles) is the source. Still there: account's own is_account_admin rule (billing_roles.py:132), billing's LiveOps raw roles (liveops/routes.py:38-40; the permission fix 97420a29 was reverted by c861872b, so QUESTIONS.md:998 is stale) and 28 per-route _*_ROLES lists (billing does not depend on undef-authz), and the two vendored mirrors (admin, developer -- equal to roles.json today; admin has a parity test, developer has none). End state still owed: billing authorizes on permissions through the catalog; a developer parity test; is_account_admin derived from the catalog.
.provide/QUESTIONS.mdCORRECTED 2026-08-21. The first version of this finding blamed the page for not refreshing. That is real but secondary, and I had the evidence to know better one run earlier: three runs credited at 04:35:26, 04:45:28 and 04:55:27 -- every one on a five-minute boundary, every one AFTER the run that caused it had given up. That regularity is not settlement jitter. undef-billing's worker declares `crons = ["*/5 * * * *"]` (terraform/main.tf:197), and the wallet credit for a claimed guest top-up is written by that SCHEDULED handler rather than by the claim. So a buyer who claims a top-up waits up to a full cron period for their money, with nothing on the page saying so. The second defect compounds it: the account portal is a hash router, the Wallet page fetches its postings once at mount, and there is no polling and no refresh control -- so even after the cron fires the page keeps showing the old balance until the buyer reloads, which nothing suggests. Measured directly: credit in the ledger at 04:35:26 (source_ref wallet-topup:line:31aa882d..., amount_minor 1000, hash_valid true), the open page still empty at 04:38:37, and a fresh load straight after rendering it as the FIRST history row. The macro spans a whole cron period with six spaced reloads, which makes the unit honest but slow. The PRODUCT questions -- should a claim credit synchronously, and should the wallet poll or offer a refresh while one is pending -- are customer-surface decisions and are not taken here. AUDIT 2026-08-28: STILL -- orders/client.py:186-215 enqueues wallet.credit.requested to the outbox and worker_entry.py:618-631 relays the owner db_group's outbox after any POST (since 8931c739), yet the credit lands on the */5 cron boundary; why relay_outbox_now does not deliver it on claim is unexplained. Wallet.tsx has no refetch (last change 512577a).
caught byverified_buyer.claim_topupTwo observations I cannot yet explain, recorded with their evidence rather than a guess. (1) Deploy take 2 (f7b7f239) seeded v2 with its allocation term -- the emitted SQL is correct and correctly ordered (version draft at line 57, allocation at 104, publish at 127), the run wrote 16 rows and exited 0 -- yet hours later offer_allocation_terms held NO v2 row while v2 sat published in the feed. Every sale of v2 in that window snapshotted EMPTY allocation terms onto its order line and will never pay the creator (the earn-sale-1 order is such a sale). (2) Replaying the same idempotent seed file restored the row -- INSERTing an allocation on a version whose status read `published` twice, which the BEFORE INSERT freeze trigger (confirmed present in sqlite_master) should have refused with `published offer allocations are immutable`, exactly as it refused deploy take 1. Suspect D1 trigger/batch semantics (WHEN with a subquery across a batch) but NOT confirmed. Follow-ups owed: reproduce trigger behaviour on a throwaway D1; audit other frozen-child tables (offer_prices, offer_bundle_components) for the same silent-loss shape; a guard that diffs seeded allocation terms against the tier after every deploy. UPDATE 2026-08-21: reproduced on a throwaway D1 through the same wrangler path -- the D1-semantics suspicion is REFUTED. All five shapes abort correctly: plain INSERT, the seed's guarded INSERT...SELECT WHERE NOT EXISTS, the full replay file via --file (atomic rollback), DELETE on published, and the missing-version-row case (trigger WHEN goes NULL-silent but the FK backstop refuses; D1 enforces foreign_keys). Proving today is healthy: triggers present, v2 published, allocation row present (owner_haiku). Sibling audit: no published version lacks a price. The loss mechanism remains unattributed -- no audit trail survives from the window -- so the guard checks OUTCOME: ci/check_seed_children.py (undef-billing) replays the applied seed file locally and diffs all three frozen child tables against the tier after every seed, wired into deploy-billing.sh, red side proven against proving with a mutated row. Recurrence now fails the deploy instead of surfacing as a creator paid $0. AUDIT 2026-08-28: CHANGED -- proving offer_allocation_terms holds one row for haiku.summer-rain.purchase.v2 again (and one for v1); the vanish and the re-insert past the freeze remain unexplained, no commit touched them.
caught bypayout_recipient.view_earningsHearting an offer awaits its PUT and disables the button, but the wishlist link stays clickable, so a fast click issues the list read before the write commits. The captured network log shows PUT .../wishlist/undef/pool.484 -> 200 with both GETs answered ahead of it. WishlistPage's useAsync fetches once on mount and never refetches, so the page renders 'Nothing wishlisted yet' over a row that exists in the database, and stays wrong until the view is re-entered. Patched at the TEST layer on 2026-08-24 (the macro now waits for the button's disabled->enabled transition); the product still loses the race for a user who clicks that fast. AUDIT 2026-08-28: STILL -- WishlistButton.tsx:70 disables only the button; WishlistPage.tsx:23-26 fetches once on mount. A manual Refresh (wishlist-refresh, WishlistPage.tsx:113) has existed since 6d7b73c, so 'never asks again' means never automatically.
caught byverified_buyer.wishlist_offer · packages/undef-storefront-kit/src/storefront/WishlistPage.tsx:23#106 said the tax line renders only where tax is zero. The EU half was fixed -- an inclusive quote now renders the amount through `store-checkout-tax-included`, and `storefront-review-tax` asserts that figure is greater than zero. The EXCLUSIVE half is unchanged and reproduces. Measured on proving 2026-08-25 through the store's own `/public/v1/store/undef/tax-quote` with the store's own location keys (billing_country/billing_region): DE returns tax_minor 160, mode inclusive, show_tax_line false; US/CA returns tax_minor 0, mode exclusive, show_tax_line TRUE. So the only branch that renders `store-checkout-tax-line` is one where the figure is 0.00, and that holds for every product type on the tier -- digital 999, bundle 799, composite/physical 1499, subscription 299 all quote 0 into US/CA. It is not a catalogue accident: US-CA is a DECLARED registration and 129 are on file. Either Stripe Tax genuinely returns zero for these product tax codes into California, in which case the tier cannot demonstrate a non-zero exclusive line and needs a jurisdiction that can, or the registration is not being matched at quote time -- and the public quote payload carries no jurisdiction or source field to tell those apart from outside. NOT DIAGNOSED FURTHER rather than guessed at. `store-checkout-tax-line` stays undriven for the same reason: driving it today would assert a zero and call it proof of a tax line.
caught bystorefront_visitor.review_checkout_tax · packages/undef-billing/src/undef/billing/domains/tax/display.py:49proving's tax_registrations table carries an ACTIVE US-CA sales_tax registration (effective_from 2026-08-23, no end date) and 142 expired US rows beside it. Stripe, the primary adapter, carries exactly ONE registration: IE. Stripe Tax computes zero where the account is not registered, so US/CA quotes tax_minor 0 while the engine has already stamped decision='collected' with a registration_snapshot naming US-CA -- the zero is indistinguishable, in the quote body and in the persisted determination, from a genuine zero-rated supply. That is the shape of a filing error nobody would see: the platform believes it collects California sales tax, the provider never charges it, and the determination says collected. Diagnosed by reading both sides -- the BFF's /v1/admin/billing/tax/registrations and Stripe's own /v1/tax/registrations -- which is what F-144 left as an either/or. The engine has the material to catch this: it holds the registration_snapshot AND the adapter's answer, so a collected decision that returns zero tax from an adapter with no matching provider-side registration is assertable at quote time. Closing #106 on this tier also needs the provider-side registration to exist, which is a Stripe TEST-mode change and is being made under the tier-seeding authority.
caught bystorefront_visitor.review_checkout_tax · diagnosis while measuring N, 2026-08-25undef-admin Catalog.tsx:469 renders 'Tax code' as a plain text input defaulting to digital-goods, and undef-account StoreManage.tsx:66 sends whatever the creator typed (v.tax.trim()). Billing accepted any non-empty string (authoring_models.py: Field(min_length=1)), the Stripe adapter dropped a code it did not know without a word, and Stripe priced the line at the account default -- 'tangable-goods' authored cleanly and was taxed as a download. Billing now refuses a code outside the supply vocabulary (supply_codes.py: digital-goods, physical-goods, stored-value, or a raw txcd_* id) at authoring, so the typo is a 422 instead of a wrong tax. What is still open is the console half: a human is offered a text box where the platform has a four-entry vocabulary, and sees a refusal where they should see a choice. Fix: a select (or datalist, to keep txcd_ passthrough) over the vocabulary in both consoles, read from billing rather than retyped. No unit: the refusal is proven at the model, the picker does not exist yet. AUDIT 2026-08-28: STILL -- undef-admin Catalog.tsx:469 and undef-account StoreManage.tsx:83 are still free-text inputs sent trimmed; billing refuses a code outside the supply vocabulary, so a typo is a 422 now, not a mis-taxed supply. Fix: a select over the vocabulary billing serves.
packages/undef-admin/frontend/src/Catalog.tsx:469; packages/undef-account/frontend/src/pages/StoreManage.tsx:66HeldEntitlements.tsx renders the empty notice whenever `items.length === 0 && error === null`, and items start empty, so the notice paints on mount and stays until GET /v1/billing/entitlements lands -- there is no loading state. library-view's second replay of sweep 54 read that notice off library_account_holder-01, who holds 266 entitlements (read directly off proving), and called the account empty. The macro now settles on rows; the panel should carry a loading state like the Games panel does. AUDIT 2026-08-28: STILL -- HeldEntitlements.tsx:16-17 has no loading flag; :33-34 renders the empty notice whenever error is null and items is empty.
packages/undef-account/frontend/src/pages/HeldEntitlements.tsx:33CREATE TABLE IF NOT EXISTS never alters an existing table, and nothing in the billing, developer or foundry deploys migrates one. On 2026-08-26 the first production deploy shipped code against tables created weeks earlier: agent_order_proposals.status CHECK lacked 'declined' (decline -> D1_ERROR CHECK constraint failed -> account 500), billing_agreements.provider_name NOT NULL refused a card-less trial (start-trial -> 500), outbox_messages.delivery_state lacked 'dead_letter' in all seventeen billing D1s, developer apps lacked demo_trial_offer_version_id (register -> 500), foundry production_jobs lacked six NOT NULL columns. Fourteen missing columns were added by ALTER on Tim's word; the constraint drift needs table rebuilds (scratchpad d1_ddl_diff.py, row counts in .provide/QUESTIONS.md 2026-08-26). Caught by production sweeps 66 and 67. AUDIT 2026-08-28: STILL as a class -- no deploy (production_deploy.py, billing main.tf) migrates an existing table; the 2026-08-27 rebuild covered the drifted tables then, and the next DDL change ships against tables it cannot alter.
caught byagentic_shopper.decline_order · capture sweep 67 (production), macros agent-decline-order and library-start-trial; worker tails of undef-account (D1_ERROR CHECK constraint failed; NOT NULL constraint failed: billing_agreements.provider_name); scratchpad/d1-ddl-diff.jsonPOST /v1/creator/crowdfund/campaigns writes the campaign row and then inserts its pledge tiers; when a tier insert is refused -- two tiers naming the same offer version, which the editor's own dropdowns let a creator pick -- the exception is not caught and the route answers 500 (Cloudflare 1101, the worker threw). Billing's create maps ValidationError to 422, a permission error to 403 and ValueError to 400 (crowdfund/creator_routes.py:54-67), so this shape reaches none of them. The campaign is left in the tier's database as a draft with zero tiers while the console shows 'Something went wrong on our side', so the creator's next attempt adds a second orphan rather than finding their campaign. Fix: refuse a duplicated offer version in CreateCampaignRequest (422, naming the field), and make the create atomic so a refused tier leaves no campaign. Proving carries four such orphans today (eb8f7e2a from sweep 81, and 79a91dc0/383004b5/5a5ef4f8 from the reproduction).
caught bypayout_recipient.author_crowdfund_campaign · proving, 2026-08-28: sweep 81 lost payout_recipient.author_crowdfund_campaign at step 28 (the save never left #/creator/campaigns/new; the session network log shows POST /v1/creator/crowdfund/campaigns -> 500 and the alert 'Something went wrong on our side'). Reproduced with scratchpad/probe_crowdfund_create.py as tim+payout_recipient-01: no tiers -> 201, one tier -> 201, the same offer version twice -> 500, and scratchpad/probe_campaign_list.py then lists the campaign as a draft with 0 tiers.The Spend tab's storefront subscriptions table renders its At-period-end column from cancel_at_period_end, which undef-billing's storefront_subscription_view (domains/overview/clients.py) computes as `cancel_at is not None and status not in {cancelled, ended}`. The operator's own Cancel sends at_period_end: false (undef-account billing_client/subscriptions.py), so billing cancels immediately and never sets cancel_at: the row's status becomes `cancelled` while the same row's At-period-end cell still reads `Renews`. An operator reading across the row is told the subscription they just cancelled will renew. Fix: render that column from the status as well -- a cancelled or ended agreement renews nothing -- or have the column say what the status means rather than what one nullable column says. Same table, second defect: every row renders the same two testids (admin-action-sub-cancel, admin-action-sub-reactivate), so ten distinct controls share one address. The console-surface inventory counts them as one control, and any selector written against them acts on whichever row sorts first -- which on 2026-08-28 cancelled agreement fa8a15c8 and reactivated 38cc6e76, two different subscriptions, both answering 200. Fix: suffix each row's action testids with the subscription id, the way the campaign list already does (crowdfund-campaign-open-{id}).
caught bybilling_admin.open_back_office · proving, 2026-08-28: rehearsal of billing_admin.open_back_office after the confirm-dialog fix. POST /v1/admin/billing/subscriptions/38cc6e76-697d-4425-823e-28c15da92864/cancel answered 200 and the refetched table rendered `Rain Club | cancelled | 2026-09-11 | $2.99 | Renews | Cancel | Reactivate` (the fail page saved beside that unit's video).haiku_seed.py:82 sets SUMMER_RAIN_CREATOR_PAYEE_ID = "test-creator" with a 5000bps share, and the comment above it states the intent the constant defeats. No payee record matches that id, so a real checkout accrues earnings nothing can pay out. AUDIT 2026-08-28: FIXED -- haiku_seed.py:115 sets SUMMER_RAIN_CREATOR_PAYEE_ID = HAIKU_OWNER_USER_ID (owner_haiku) and v2 supersedes v1; proving offer_allocation_terms: v2 published payee=owner_haiku 5000bps; earning_entries owner_haiku n=4. Residual: 21 legacy test-creator entries (4233 minor) from v1 sales belong to nobody and need an adjustment, not a seed change.
fixed in undef-billing 3c6abac3 + f7b7f239 ·packages/undef-billing/src/undef/billing/domains/storefront/haiku_seed.py:82capabilities.ts checked every permission at Scope(service="admin"). undef-account confers a billing role only for service in {billing, *}, so the console was wrong BOTH ways: the grant that works on the wire got a dead console, and a grant carrying no billing authority got billing tabs drawn. Scope now comes from the permission's own namespace.
caught bybilling_admin.form_vendor_group · fixed in undef-admin d19180aPOST returned 201 and the row existed, but createGroup re-listed immediately into a D1 replica that trails the write -- measured at 1.90s on proving -- and rendered the pre-write page. A successful write was reported as nothing, with no error. State is now seeded from the 201.
caught bybilling_admin.form_vendor_group · fixed in undef-admin 360b144MEASURED live on proving: preflight from the console origin answers 204 for /v1/admin/billing/ and 404 for /v1/admin/foundry/, /v1/billing/authoring/ and /v1/billing/storefronts/. The finding as filed named foundry alone; extracting every path undef-admin sends to accountBaseUrl gives 24 paths in four families, THREE of them uncovered by CORS_PATH_PREFIXES. Fix is to derive the set from the client and gate the drift, not to hand-add a prefix. AUDIT 2026-08-28: FIXED -- CORS_PATH_PREFIXES is derived from the calls the console makes (cors.py:46-56 lists /v1/admin/billing/, /v1/admin/foundry/, /v1/billing/authoring/, /v1/billing/store/, /v1/billing/storefronts/); preflight from https://proving.admin.undef.games answers 204 for all four families (measured live).
fixed in undef-account 8ac1281 + 612d0c0 ·packages/undef-account/src/undef/account/cors.py:31Root-caused live from the deployed worker's own log: D1_ERROR: UNIQUE constraint failed: storefront_sections.section_id. StoreSlots.tsx numbered section ids from the OPEN document, so every owner's first section was literally "section-1", and products.sql keeps section_id as a GLOBAL primary key -- the second group on a tier ever to save one 500'd, permanently, and so did everyone after. The first fix targeted storefront_pages' ownership UNIQUE instead, on the strength of a bare 500 that carried no evidence, and the next sweep failed identically. Ids are now namespaced by page and the route answers 409 naming the column. CAPTURED on the 2026-08-20 proving sweep: 95/95.
caught bycreator_vendor.compose_storefront_home · fixed in undef-account 361c69f + undef-billing b5babaf9 · packages/undef-billing/src/undef/billing/domains/storefront/store.pyLiveOps was the only authority on the platform checked by raw role name at Scope.everywhere(), bypassing the permission catalog -- so the only way to hold it was to be a superuser. The AuthzError it raised already named billing.liveops.admin, a permission that existed in no catalog. It now resolves that permission through the catalog at billing scope, and the proxy forwards billing's own role vocabulary, which undef-auth's issuance matrix is what actually permits.
caught bybilling_admin.edit_liveops · fixed in undef-authz f7ddbd6, undef-admin cf4df57 + 1d8d848Skipped with "no creator_vendor on this tier has two distinct offers it can still put in a cart". The cast owns the catalogue after enough runs, so a unit that needs an unowned offer runs dry -- the same exhaustion #78 and #81 addressed elsewhere. It needs a per-run seeded offer from a second creator, not a wider assertion. AUDIT 2026-08-28: FIXED -- capture_preconditions._stock_the_general_pool seeds the drawable pool in the SETUP phase (546387a9, 2026-08-20); creator_vendor.buy_other_creators_offer captured in every sweep since (latest 20260828T151422Z).
caught bycreator_vendor.buy_other_creators_offer · fixed in 546387a9 · scripts/acceptance/capture_preconditions.pyworkspace_divergence ran `git rev-parse origin/main` with check=True while build_steps was assembling the plan, so a root with no repo or no origin/main raised CalledProcessError and took the whole deploy plan down for every repo over one repo nobody could inspect. Seven tests went red; the pre-push gate refused the push, which is the only reason it was caught. It now returns ("", []) -- the strict reading, since the caller relaxes only on a NON-empty diverging path list.
fixed in undef-workspace (this commit)Measured on proving 2026-08-20: 10 of 20 consecutive POST /v1/auth/refresh calls for this unit's driver returned an access token with grants=[] and gv=0, in 187-393ms -- fast, so not the 1s enrichment timeout. undef-admin verifies undef-auth's service token by fetching its JWKS over the PUBLIC hostname, and that worker-to-edge hairpin answered 522 eleven times in thirty minutes (undef-admin-proving's own logs); the same URL answered 10/10 in under 210ms from outside Cloudflare. Each 522 became a 503 from /v1/internal/grants/{principal}, which undef-auth's bare `catch {}` turned into empty grants and a 30s open circuit. The console computes its whole navigation from those grants, so the capture landed on a 4-tab console instead of 25 and every admin call answered 403. This is the goal's own WHY: dead in a browser on a deployed tier while every suite and curl stays green, because they mint tokens directly and never traverse the refresh path. Mitigated in undef-authz (retry + last-known key set, undef-authz b170fef) and made diagnosable in undef-auth (133d032); neither is live until proving is redeployed, and the real cure is a service binding so undef-admin never leaves the edge to read this document. FIXED, and measured live rather than assumed: after redeploying proving the same 20-refresh probe that returned 10/20 zero-grant returns 0/20, one call taking 1689ms where the retry absorbed a 522 instead of stripping an operator's grants. billing_auditor.read_reports has since captured on three consecutive full sweeps with the console rendering all 25 tabs.
caught bybilling_auditor.read_reports · fixed in undef-auth 133d032, undef-authz b170fef, undef-admin 555e5ec, undef-developer 46bbe77buyer-keepsake-fulfillment navigated to the orders list immediately after checkout returned, then waited its full 180s for a shipment card. That list fetches once and never polls, so it had rendered the order at `pending payment` -- settlement landed 20 seconds later, and the failure screenshot, taken three minutes after THAT, still showed PENDING PAYMENT while every older keepsake row read PAID and billing had the order as paid the whole time. Waiting longer could never have helped: nothing was going to re-fetch. The macro now reads the order to PAID first -- the state fulfillment depends on -- and reloads while it waits, so it asserts against the tier rather than a snapshot of it. Caught by the 2026-08-20 sweep; the unit had captured on earlier sweeps purely because settlement happened to beat the first render.
caught byverified_buyer.composite_purchase · fixed in undef-workspace (this commit)StoreSlots renders its editor from a single useAsync keyed on the selected group, with no retry. On the 2026-08-21 sweep that GET never answered after the read-back reload: no 404, no error in the console, no editor -- just the group picker, for the full 45s, on a document the save had already confirmed. The macro now reloads while it waits, bounded to one reload every 12s, and only when the panel is showing neither the editor nor the create affordance (the stalled shape). The assertion is untouched: it still reads the SAVED TITLE back, so a document that returns wrong still fails. Third sweep in a row where the failing unit was a read that trailed or stalled behind a write it had already made -- see F-132 and #124. The pattern, not this macro, is the thing worth fixing: these surfaces retry nothing, so one slow upstream answer is indistinguishable from a broken page.
caught bycreator_vendor.compose_storefront_home · fixed in undef-workspace (this commit)Measured 2026-08-21 while deleting admin.spec.ts. Ten presets in undef-economy's visible-proof runner grepped for test titles that exist in NO spec under tests/browser. Playwright reports no-tests-found as SUCCESS, so each one ran, selected zero tests and went green. Deleting admin.spec.ts did not break the five that named it -- it revealed them. This is the third and fourth time the same rot has been found in this one file: its own comments record promo-checkout and agent-limits, both caught the same way, both described as assertions that held the drift in place instead of catching it. FIXED: the five naming admin.spec.ts are retired, and a general gate now checks every grep-based preset against the titles its specs actually contain -- including describe titles, because reading only test() calls made the gate itself under-read and misjudge dunning-recovery on its first run. OPEN: five presets are still vacuous (dunning-recovery, dunning-decline, composite-bundle, delivery-recovery, physical_good), registered in VACUOUS_PRESETS as a ratchet rather than deleted, because each names a journey somebody meant to prove and the entry is now the last record of that claim. dunning-recovery is the sharpest: a comment two lines above its grep warns that a mis-escaped pattern would select zero tests, and the pattern is mis-escaped. AUDIT 2026-08-28: FIXED -- visible_proof.py:415 _PRESETS = {} and :439 VACUOUS_PRESETS = frozenset(); the five vacuous presets became macros (dunning-* -> subscriber-dunning-retry, composite-bundle/physical_good -> buyer-*-fulfillment, delivery-recovery -> shipped-notification); tests/test_cli_visible_proof_command.py rejects any --preset. Dangling reference in the :427 comment to a test file that does not exist.
fixed in undef-economy 71b4572Proven in a browser on proving 2026-08-21, twice, four minutes apart. Driving the admin console's Merchandising tab as billing_admin renders 'Failed to fetch' under STOREFRONT HOME, and the browser says why: Access to fetch at '.../v1/billing/store/undef/offers?limit=100' from origin 'https://proving.admin.undef.games' has been blocked by CORS policy -- then the same for /v1/admin/foundry/production/assignments. undef-account/cors.py:31 allows exactly one prefix, /v1/admin/billing/, and needs_cors() is a prefix match, so every other console call leaves without an Access-Control-Allow-Origin and the browser refuses it before it goes anywhere. The same storefront-home endpoint answers 200 in 955ms to a direct request carrying the same persona's bearer. Green by curl, dead in a browser -- the exact shape this whole acceptance effort exists to eliminate, and it took a macro driving a real browser to see it. Tracked as #125, which had inferred it from a probe; this is the first time it has been watched happen. It blocks the merch-cms migration: those three browser tests stay until the console works, because deleting them would retire the evidence of a live defect. FIXED 2026-08-21: CORS_PATH_PREFIXES now carries five prefixes and is DERIVED from undef-admin's api.ts rather than maintained by hand (tests/test_console_cors_covers_every_call.py), so a console call under a new prefix fails at commit time. Deployed to proving (undef-account version 37f774a0) and verified live from both sides: a preflight from origin https://proving.admin.undef.games returns Access-Control-Allow-Origin for /v1/billing/store/undef/offers, /v1/admin/foundry/production/assignments, /v1/admin/billing/adjustments, /v1/billing/authoring/products and /v1/billing/storefronts/undef/home, and still returns NONE for /v1/account/me -- the portal's own same-origin route, which proves the list did not simply widen to the service. Re-driven in a browser: the Merchandising panel loads, saves a draft and publishes.
fixed in undef-account 612d0c0MY BUG, not the platform's, and it cost three wrong theories before the right one. admin-storefront-publish published a merch section titled 'Capture Shelf 81666' to the platform home, then waited 90s on the public shop for sections.some((s) => s.innerText.includes('Capture Shelf 81666')). It timed out. The reported failure named the selector, so the first three hypotheses were all about the section not being there: the publish silently failing, the deployed store build stripping data-testid (VITE_STOREFRONT_SELECTORS), and the section kind falling outside the kit's MERCH_KINDS. All three were wrong, and two were disproven by reading artifacts I already had -- the cached page markdown from the failing run contains the title, which means the publish landed and the section rendered. Driving the live page settled it: the element is there, carries data-testid=store-merch-section, and .merch-section__title is text-transform: uppercase -- so innerText returns 'CAPTURE SHELF 81666' while textContent returns 'Capture Shelf 81666'. A case-sensitive includes() against innerText could never match. Fixed by comparing textContent case-folded. Gated by tests/test_macro_text_reads_survive_css.py, which freezes the two surviving case-sensitive reads and fails on a new one, on a fixed one left in the register, and on the scan itself going blind (all three mutation-tested). Two negative checks were case-folded in the same pass -- admin-vendor-group's empty-state probe and this macro's facade line -- because a negative check against text CSS uppercases does not fail loudly, it passes vacuously.
caught bybilling_admin.publish_storefront_home · fixed in a3546e6fFound live on proving with a real declining card (pm_card_chargeCustomerFail). A non-trial subscription schedules its first cycle at creation; the executor claimed it (billing_cycles.status=charging) and Stripe answered the off-session confirm with 402 -- which _post wraps in ProviderError and create_payment_intent let propagate, so run_one's blanket except RESCHEDULED the decline every 30s forever. No capture-failure row, no past_due, no dunning state; the agreement read `active` half an hour after the charge was refused, and the portal's payment-recovery surface was unreachable for the exact customer it exists for. The invoice-pay path five lines below had mapped the same 402 to `failed` all along, with a comment stating the rule. Fixed at the gateway (402 -> terminal declined; 5xx/network still raise and reschedule) plus the Stripe result mapper (requires_payment_method/canceled are failures, not SCA challenges -- the old catch-all sent the decline-without-exception shape into a confirm loop). Tests written failing first; the stuck proving cycle self-heals on the next cron after deploy.
caught bydunning_subscriber.retry_payment · fixed in undef-billing c01a9df8billing serves GET and POST for disputes and nothing that re-reads the provider, so when our row disagrees with Stripe there is no operator path back to the truth -- the remaining fix is editing D1 by hand, which is the same shape as the gap that made #134 worth filing. Found while repairing 25 rows still reading action_required after the stale-snapshot ordering fix (#140): the code was correct from then on, and nothing could repair what it had already written. AUDIT 2026-08-28: STILL -- disputes/routes.py:398-430 carries create, list, get, evidence, accept; no resync. The F-162/F-166 commits did not add one. Fix: POST /v1/admin/disputes/{id}/resync re-reading the provider through the same ordering guard as the webhook. FIXED 2026-08-28: POST /v1/admin/disputes/{id}/resync fetches the provider's dispute (Stripe GET /v1/disputes/{id} through the webhook parser) and applies it through the webhook's own ordering guard; the account BFF proxies it and the disputes pane offers it (dispute-resync); dispute-decide presses it before contesting.
caught bydispute_operator.review · fixed in undef-billing d5b2a791 + undef-account 730a8c9 + undef-admin 6117a18 · packages/undef-billing/src/undef/billing/domains/disputes/routes.py:396The dispute detail pane renders 'No linked order' for a dispute raised against a real purchase, and with it goes the order lines -- what was bought, by whom, for how much -- which is the evidence the operator is being asked to contest with. Measured on proving 2026-08-24: dispute 65bb9822fa3a4cf1bb121c40dbe8ae93 carries provider_charge_ref ch_3U7qfWCLIBcgZ82u0dsaPnc3 AND provider_payment_ref pi_3U7qfWCLIBcgZ82u0RAxG04M, with order_id null. So the provider refs are not missing; resolution failed and nothing re-ran it. Two candidate causes, neither confirmed: the dispute webhook can land before the checkout-completion webhook writes payment_intents (Stripe raises charge.dispute.created immediately for the test card), and _resolve_intent only matches payment_intents.provider_intent_ref -- it has no fallback through payment_captures.provider_capture_ref, which the sibling resolve_signal_intent on the same class does have for pre-dispute warnings. Known since the opened_at windowing work, recorded only in a docstring; this files it with the refs. dispute-decide deliberately does NOT assert the no-order branch: a macro that passes on the broken state writes the defect down as the expected behaviour. AUDIT 2026-08-28: FIXED -- disputes resolve their order at intake through payment_intents, hosted_checkout_sessions by payment ref, and the session the provider names (F-162, F-166); every dispute recorded on proving since 2026-08-27 18:54Z carries its order (6/6 in the latest read). The 150 rows recorded before that stay unlinked -- a backfill, not this fix.
caught bydispute_operator.decide · fixed in undef-billing b42c0ca4 + 071b031e · packages/undef-billing/src/undef/billing/domains/disputes/store.py:40GET /v1/privacy/requests answered `error code: 1101` -- an unhandled Worker exception -- on every deployed tier, while POST to the same path answered 201. undef-account keeps two repositories: SQLite for local dev and tests, D1 for every deployed tier. `list_privacy_requests` was added to the SQLite one together with the route that reads it and never to D1, so the deployed path raised AttributeError on every call and the whole suite stayed green because the tests import the SQLite class. The export and erase controls render per ROW, so with the list failing the page collapsed to an error and offered nothing -- the GDPR rights undef-account serves were unreachable through the UI, which is the condition #144 was filed for one layer up. Measured on proving 2026-08-24: LIST 500, CREATE 201, LIST 500. Fixed in undef-account dd6e32d and gated by a test comparing the two repository classes against each other rather than a hand-kept list.
caught byverified_buyer.raise_privacy_request · fixed in undef-account dd6e32d · packages/undef-account/src/undef/account/d1.py:340#62 asks whether a cart may hold two currencies at all. The answer is no, and the mechanism is the feed, not the checkout: billing's public offers route defaults `currency` to USD (storefront/routes.py) and undef-store never sends another, so an offer priced only in EUR is listed nowhere the store looks and its own page answers 'offer not found'. The checkout's mixed-currency branch (`store-checkout-total-mixed`, the disabled submit) guards a cart no shopper can build through this UI. This finding used to park the question as 'a catalogue decision rather than a test fixture' -- that was the wrong frame, and it was mine: proving is a dev-grade tier and the platform prices per currency, so a EUR fixture is what the seed-a-tier authority is for. Minted one (seed_second_currency_offer, acceptance.eur.*, per run) and measured: the EUR view of the feed lists it (`?currency=EUR` -> acceptance.eur.01.purchase.v1, EUR, '€9.99'); the USD view answers 404 for it; a first draft of the unit that tried to put a EUR line beside a USD one could not even find the offer, which is the finding. storefront-one-currency-per-view now reads the values: every grid price carries one symbol, one USD line yields one unlabelled subtotal equal to its price, and the page for the real EUR offer renders 'offer not found' with no Add to cart while the cart keeps its USD line. Backend: storefront_visitor.mix_currencies finds the EUR offer through the EUR view and asks billing to quote it in USD; the refusal is offer_not_priced_in_currency naming that offer. Two things remain true and unproven here on purpose: a persisted cart from before a currency change could still reach the mixed branch, and the store offers no currency change -- when it does, that branch gets a driver.
caught bystorefront_visitor.mix_currencies · fixed in undef-workspace 0afc298a, undef-economy 5285f35, undef-persona-bindings 84b4480 · packages/undef-billing/src/undef/billing/domains/storefront/routes.py:200 (feed currency default); packages/undef-store (never sends currency)CampaignEditor loads four things at mount, one of them `getBillingConnectKyc()`, and renders `loadError` INSTEAD of the form when any of them fails. An account that sells but has never been paid has no payee row, so billing answers that call 404 payee_not_found and the whole editor is replaced by the notice 'Payee not found.' -- no title field, no group picker, no explanation, and a phrase naming an internal record rather than telling the creator to set up payouts. Found by driving it: developer_app_owner holds the `developer` capability, sees the Creator nav, and gets that notice at /#/creator/campaigns/new. The KYC answer is only needed to decide whether Submit-for-Review is enabled -- the DRAFT half of the page needs none of it -- so the fix is to treat a missing payee as 'not ready to submit' rather than as a failure to load. The unit is driven by payout_recipient, which has a seeded Connect payee, so the macro proves the editor and this finding records the surface it cannot reach. AUDIT 2026-08-28: STILL -- CampaignEditor.tsx:178-183 loads getBillingConnectKyc, :241-242 folds its error into loadError, :506-508 renders the error instead of the form; billing payouts/routes.py:184 answers 404 payee_not_found for a seller never paid. Fix in flight (undef-account branch f147-crowdfund-contract). FIXED 2026-08-28: a KYC/payee failure no longer replaces the editor; the form opens, Save works, Submit-for-Review stays disabled and campaign-editor-payouts-notice links to /#/creator. Pinned by CampaignEditor.test.tsx; the notice is excused in config/console_surface_reasons.json with the reason no cast member can reach it.
caught bypayout_recipient.author_crowdfund_campaign · fixed in undef-account bb41895 · capture sweep 70, macro creator-author-campaignThe console posts {group_id, realm_id, goal_amount, funding_model, payout_timing, fulfillment_trigger, donation_tax_mode, cta_mode, tiers, milestone_sigils} to /v1/creator/crowdfund/campaigns. The account BFF proxies that body to billing UNCHANGED (billing_client/creator_storefront.create_creator_crowdfund_campaign passes `payload` straight through), and billing validates it against CreateCampaignRequest, which is extra='forbid' and wants seller_group_id, currency, goal_minor and capture_policy -- none of which the console sends -- and has no realm concept at all. Every save answers 422 with four 'Field required' and several 'Extra inputs are not permitted'. Two vocabularies that were never connected: the console's own client test asserts it 'posts snake_case body' in a shape billing has never accepted, and billing's tests use billing's shape, so both suites are green over a path that cannot work. Found by driving Save on proving. `capture_policy` has no control anywhere in the editor and no default in billing -- choosing one decides WHEN a backer's card is charged, which is a money decision, so the mapping is parked in .provide/QUESTIONS.md rather than invented here. The macro pins the refusal so the defect stays measured; when the contract is joined it must flip to asserting the draft. AUDIT 2026-08-28: STILL -- apiClient/crowdfund.ts:80-97 posts group_id/goal_amount/realm_id/tiers[offer_id,price,limit_qty]; crowdfund_routes.py:70-76 forwards it unchanged; billing CreateCampaignRequest (schemas.py:38-62, extra=forbid) wants seller_group_id/currency/capture_policy/goal_minor/tiers[offer_version_id,amount_minor,quantity_limit] and no realm; the reverse mapping drifts the same way, so CampaignList renders -- for group and goal. The macro creator-author-campaign asserts the REFUSAL and throws if the save succeeds. Fix in flight: the BFF translates (crowdfund_contract.py), capture_policy defaults to capture_at_success (QUESTIONS, the recommended answer), realm removed from the console; the macro must then assert the created campaign. FIXED 2026-08-28: the BFF joins the two vocabularies (crowdfund_contract.py: group_id->seller_group_id, goal_amount->goal_minor, tiers offer_id/price/limit_qty->offer_version_id/amount_minor/quantity_limit; currency USD and capture_policy capture_at_success as defaults, the parked question's recommended answer; realm refused and removed from the console); the contract test validates the console fixture against billing's real CreateCampaignRequest. creator-author-campaign now asserts the created campaign read back from the list.
caught bypayout_recipient.author_crowdfund_campaign · fixed in undef-account 70c3467 · capture sweep 70, macro creator-author-campaignundef-social has no deployment outside dev: the repo carries no terraform, and the account app's /config.js omits its base URL on every deployed tier. socialClient then throws SocialUnavailableError and the page renders one line -- 'Social features are not available in this environment.' The Friends nav item is NOT hidden, so a signed-in person on proving can click Friends and reach a dead surface, on a console that otherwise works. Ten controls (the add box and its submit, the friends list, the conversation panel and its message list, the DM input, send and close) are rendered by code that ships to every tier and are driveable on none of them. The `unit` is null on purpose -- there IS no unit, and that is the finding. Found by building the macro for them: the unit was written, registered, and pulled again, because a unit that can only ever skip is not evidence -- the harness would carry a permanent skip and call it coverage. Two honest fixes, in order of cost: hide the Friends nav and route when the social base URL is absent, so the console stops offering what the tier cannot do; or deploy undef-social to proving, at which point the macro is a day's work and ten controls come with it. AUDIT 2026-08-28: STILL -- lib/categories.ts:27 friends row carries no visible(); App.tsx:256-257 routes it unconditionally; runtimeConfig optionalBaseUrl is '' on every deployed tier (health/routes.py:33-35 omits socialBaseUrl on purpose); packages/undef-social has no terraform. The ten ids are excused in config/console_surface_reasons.json:46-55. Fix in flight: visible() and the route gated on socialBaseUrl. FIXED 2026-08-28: the Friends nav item renders only when /config.js carries a social base URL and #/friends routes home otherwise, so no tier offers the page. Friends.tsx still ships: its ten controls stay in the static surface inventory, excused in config/console_surface_reasons.json with that reason (the surface gate refused the push that dropped the excuses). Removing the page or wiring a social service is the remaining work.
fixed in undef-account 7c1ffcd ·capture probe, macro buyer-befriend-and-message (withdrawn)CORRECTED FROM MY FIRST FILING, which said the tax-code map defaults to {} and that the platform never sends a code. That was wrong: DEFAULT_STRIPE_TAX_CODE_MAP is non-empty and `digital-goods` has always translated. The real defect is narrower and worse-shaped -- the map keyed `tangible-goods`, a name NOTHING in the platform has ever written, while every seeder that sells a physical thing writes `physical-goods` (currents_seed.py, haiku_composite_seed.py, and the acceptance composite fixture all define _PHYSICAL_TAX_CODE = 'physical-goods'). An unmapped code is silent: _stripe_tax_code returns None, the adapter omits line_items[i][tax_code], and Stripe prices the line at the ACCOUNT default. Measured against Stripe with proving's own key, same address (US-CA 94103) and same amount (1499 minor): with txcd_99999999 the answer is 129 at 8.625%, with no code at all it is 0. So every physical supply was taxed as whatever the account default happened to be, and the zero was indistinguishable from a genuinely untaxed sale. FIXED: `physical-goods` and `stored-value-clearing` added, `tangible-goods` kept as an alias because a tier may already carry it. GATED: a new test reads the tax-code constants out of the seeders themselves and requires each to translate, so the next supply type fails at the moment it is seeded rather than at the moment somebody reads a tax return. Probed both ways -- it fails with the mapping removed, naming the two files that write the code.
caught bystorefront_visitor.review_checkout_tax · fixed in undef-billing e2dfa19d · diagnosis while measuring N, 2026-08-25GuestCheckout.tsx sent every quote and every checkout session with billingRegion hard-coded to null, and TaxSummary offered a country select only. United States sales tax is set by the state and the postal code, so the platform could not compute it for any storefront sale into its own default country -- while proving declared a US-CA registration and the engine stamped decision=collected on a zero. A test asserted the absence: 'a region input is still absent -- no jurisdiction the platform sells into needs one to quote', which was false of the default country. Measured on proving 2026-08-25 through the public quote route, after the F-150 map fix was live: the physical keepsake into US with region null quotes tax_minor 0, into US-CA with no postal code 0, into US-CA 94110 91. The store now asks for state/province and postal code for US and CA, re-quotes on each, clears them when the country changes, and sends the same location to the checkout session; the kit carries billing_postal_code, which the wire already accepted. storefront-review-tax drives the US leg and reads the tax line's value.
caught bystorefront_visitor.review_checkout_tax · fixed in undef-store a5de95c, undef-checkout-kit 9bbd334 · packages/undef-store/src/checkout/GuestCheckout.tsx:92 (before a5de95c)The account BFF's GET /v1/billing/entitlements proxies to billing's GET /v1/entitlements with no domain -- the portal is one person's view of everything they hold -- and billing answered 422 'domain_id query parameter required'. The Home page mounts HeldEntitlements, so every signed-in user on every deployed tier saw account-entitlements-error where their holdings should be; 'You hold no entitlements yet' and the table never rendered. Found reading the network log of a headed replay (library_account_holder.view_library), then confirmed with the route as two personas: both 422. Fixed in billing by making the domain a narrowing filter rather than a requirement: a principal with no domain scope lists across domains, a domain-scoped caller still sees only its own. The macro that reads the panel's value lands with the next sweep, which is when this finding gains its unit.
caught bylibrary_account_holder.view_library · fixed in undef-billing 7d5e241b · packages/undef-account/src/undef/account/billing_client/overview.py:131; packages/undef-billing/src/undef/billing/domains/entitlements/routes.py:151 (before the fix)StoreManage.tsx mounts OfferAllocations under every draft version on a seller's own /#/store/manage page, and the editor's client calls /v1/admin/billing/products/offer-versions/{id}/allocations (account admin_billing/catalog_routes.py) -- an operator-only proxy onto billing's /v1/admin/products/offer-versions/{id}/allocations (products/routes.py). Neither the BFF nor billing has a seller-scoped allocations route, so a seller's GET answers 403 the moment the section mounts and the PUT answers 403 on Save. Read off proving by creator-publish's first replay of sweep 54 (creator_vendor-01: GET 403, PUT 403 on capture.06680.v1) while the same arc succeeds for an operator (admin-mutate). A seller cannot set a revenue share through the UI that offers it; the operator-side round trip is what sweep 54 attests. AUDIT 2026-08-28: STILL -- allocations.ts:17 still calls /v1/admin/billing/products/offer-versions/{id}/allocations; the only routes are account admin_billing/catalog_routes.py:103,109 and billing products/routes.py:334,341, both operator-only. Fix: a seller-scoped, owner-checked allocations route in billing with a BFF proxy. FIXED 2026-08-28: GET/PUT /v1/store/offer-versions/{id}/allocations on billing, authorized for a caller whose groups include the version's seller group (403 otherwise, operators included), proxied for the seller by the account BFF; the seller's editor calls it. creator-publish files a share through it before publishing and waits for the saved notice.
fixed in undef-billing 3fbf1019 + undef-account 350d3c0 ·packages/undef-account/frontend/src/pages/StoreManage.tsx (mounts OfferAllocations for drafts); packages/undef-account/src/undef/account/domains/admin_billing/catalog_routes.py:103; packages/undef-billing/src/undef/billing/domains/products/routes.py:334PUT /v1/billing/notifications stores the preference in the account repository, then syncs channels to billing with PUT /v1/notifications/channels. That billing route is machine-only (required_roles=["billing_system"], no role a human could hold), and billing refuses a delegated actor on an m2m-only route outright (billing route_def.m2m_only) -- and the BFF delegated the user (actor_user_id) on that call. So every save answered {"detail": "forbidden"} while the next GET carried the new values: read off proving with subscriber-01's own token (PUT 403, GET email_enabled flipped) after subscriber-view-orders-invoices' first replay of sweep 54 hit it. The sync now goes as the service alone; the body already names the user.
caught bysubscriber.view_orders_and_invoices · fixed in undef-account f9ae4b4 · packages/undef-account/src/undef/account/billing_client/overview.py (sync_notification_channels); packages/undef-billing/src/undef/billing/domains/notifications/routes.py (required_roles); packages/undef-billing/src/undef/billing/route_def.py (m2m_only)undef-admin's Spend tab lists `overview.subscriptions` from billing's account overview, which is `list_agreements` over billing_agreements (payments/store.py) -- the support-plan agreements no console creates -- and labels the empty state 'No support subscriptions'. The storefront subscriptions the account console lists at /#/billing/subscriptions live elsewhere: subscriber-01 holds 141 there (read off proving) and the back office shows none for the same sub. An operator looking a subscriber up cannot see, cancel or reactivate what the subscriber actually pays for; the Cancel/Reactivate controls are excused in config/console_surface_reasons.json until the tab reads the right table. AUDIT 2026-08-28: STILL -- Spend.tsx:541-543 lists snapshot.overview.subscriptions ('No support subscriptions'); overview/routes.py:36 and service_clients.py:1110 still read billing_agreements. FIXED 2026-08-28: the account overview carries storefront_subscriptions (the agreements the subscriber pays for) and billing gained operator cancel/reactivate routes; the Spend tab lists them with Cancel/Reactivate (the excused ids, now driven by admin-back-office's second lookup of subscriber-01); the account BFF's operator proxies call the operator routes. Note from the fix: the account console's own /#/billing/subscriptions reads the same billing_agreements table, so the original 'shows none' was the operator's lookup subject, not a second table. Sweep 80 (proving, 2026-08-28) then showed the account BFF's _public_overview dropping the field billing sent -- 'No storefront subscriptions' against 164 agreements for subscriber-01; undef-account 9008e66 returns it.
fixed in undef-billing 8846ab10 + undef-admin 1d716a9 + undef-account 20c95f6 + 9008e66 ·packages/undef-admin/frontend/src/Spend.tsx:544; packages/undef-billing/src/undef/billing/domains/overview/routes.py:26; packages/undef-billing/src/undef/billing/service_clients.py:1110useAsync keeps `loading: false` on the render between a deps change and the effect that starts the new call, so HubsPage painted its empty notice the instant an app was selected -- 2 ms after the list mounted, before GET /v1/developer/v1/hubs had been sent (read off sweep 58's action stream and network log for developer_app_owner.author_hub). saveHub then chose create from the rendered (empty) list and POSTed a hub that existed: 409 'hub slug already exists: acceptance-cast-news', while the failure DOM showed the hub at v6. Two fixes: the hook reports loading until the call for the CURRENT deps has started (every useAsync caller stops painting an empty state for that frame), and saveHub decides create-vs-update from a fresh hubList, not the one on screen. Same class as F-158, which has no loading state at all.
caught bydeveloper_app_owner.author_hub · fixed in undef-account 7ae4b7a · packages/undef-account/frontend/src/lib/useAsync.ts; packages/undef-account/frontend/src/pages/HubsPage.tsx (saveHub)undef-auth enriches each OIDC mint with the principal's grants by calling undef-admin /v1/internal/grants/{id} under a 1 s timeout (src/grants.ts, ADMIN_GRANTS_FETCH_TIMEOUT_MS). On failure it falls back to a last-known cache if fresh, else mints `grants: [], gv: 0`; after circuitFailureThreshold failures a module-level circuit skips the fetch for circuitBreakMs on that isolate. Observed 2026-08-26 01:10 and 01:15 PDT: two independent logins as billing_admin-01 answered GET /v1/me/capabilities 200 with 21 keys all false and delegatable-roles [] (the handoff generator and a hand probe, minutes after sweep 60 and the economy suite loaded the tier), while the admin grant store held the persona's unexpired billing_admin@billing/*/* row (granted_by system:seed_acceptance_roster) and billing_admin-02/-03 read 14 true; at 01:25 three consecutive logins as -01 read 14 true with fresh computed_at and no CDN cache. admin's epoch check passes gv 0 for a principal whose epoch was never bumped, so nothing refuses the token: the operator sees a console with no tabs and no error. The code names the quiet degradation as deliberate (login must not hard-fail) and logs the reason; what remains is that the TOKEN cannot say it is degraded, so no console can tell 'no authority' from 'authority unavailable'. Timed after nine idle minutes from the edge, three consecutive unauthenticated GET /v1/roles answered 401 in 0.830993s, 0.074140s, 0.789677s -- two of three at ~80% of the 1 s enrichment budget before the JWKS verification and D1 read the enrichment path adds; suggestive of cold isolates, not proof. Decision parked in .provide/QUESTIONS.md. AUDIT 2026-08-28: STILL, and LIVE ON PRODUCTION -- groups.ts runs the same fail-open breaker as grants.ts; at the start of production sweeps 10 and 11 (16:09Z, 16:53Z) the offer seeds' fresh developer_app_owner login listed 0 apps (its DB-backed group missing from the token) while ten sequential logins minutes later carried the group every time (14 apps each). The concurrent burst of logins at sweep start is what trips it; the harness pays with skipped bundle/composite units. FIXED 2026-08-28 (the parked option 3): each enrichment retries once inside its budget; when it still fails with no fresh last-known answer the token carries NO grants/gv/groups and grants_degraded: true on a TTL capped at 120 s -- never grants: []/gv: 0; groups.ts reads the same 4 s budget as grants.ts. The harness re-mints a login whose token says so (scripts/proving_smoke_login.mint_access_token). Consoles were not yet taught the marker.
fixed in undef-auth 286aca2 ·packages/undef-auth/src/grants.ts (enrichGrants catch -> lastKnownGrantsOrEmpty, emptyGrantJwtClaims); packages/undef-admin/src/undef/admin/auth.py (check_epoch)Every dispute either tier opens is delivered to both tiers' webhook endpoints (one Stripe test account, two endpoints, each with a valid secret), and billing's charge.dispute.created handler inserts a payment_disputes row for a charge it never took: open, provider-backed, order_id NULL, intent_id NULL. undef-billing-prod-payments held ~140 such rows dated 2026-08-18..26, one per proving sweep. The production console listed them as decidable; Stripe refused the console's evidence on every one with 'maximum number of evidence submissions for this dispute' (400) because proving had already argued them, and 'Disputes can't be updated once evidence has been submitted' on accept. Caught by production sweeps 66 and 67 (dispute_operator.decide failed both). The harness now skips a dispute with no order of this tier's own (undef-workspace 1cea52fa); the platform still ingests foreign events. Fix candidates: drop events whose charge/intent is unknown locally, or key the endpoint by a tier tag in payment metadata, or one Stripe account per tier. FIXED 2026-08-27 in two steps: c30a98a made DisputeService ask the store for the payment behind the event and drop a dispute on one this tier never made (logged as dispute.event_for_payment_this_tier_never_made); proving sweep 72 then skipped dispute_operator.decide because that lookup consulted only payment_intents, which a hosted checkout never opens, so the tier's OWN disputing-card purchase (ch_3U95x0..., du_1U95x2..., Stripe delivered charge.dispute.created, no payment_disputes row) was dropped too. b42c0ca resolves the payment through hosted_checkout_sessions as well, which also gives the tier's own disputes their order_id at intake (150 of proving's 152 had none).
caught bydispute_operator.decide · fixed in undef-billing b42c0ca · capture sweep 67 (production), macro dispute-decide; undef-billing-prod-payments payment_disputes (order_id IS NULL); packages/undef-billing/src/undef/billing/domains/disputes/routes.py:218GET /v1/billing/store/undef/offers answers in 7.0-7.4 s on production as the acceptance buyer with the tier otherwise idle (sort=newest: 21 of 42 with a cursor; limit=100: 38), a cost that scales with the catalogue rather than the page. Production sweep 69 (2026-08-27) ran the merchandising unit beside three other billing_admin units; its offers?limit=100 read had no response when the browser closed at 67 s and the panel never rendered its sections, so the unit failed with no 4xx or 5xx anywhere in its network log. The same unit captured on production in sweep 68 and captures on proving every sweep. Not a harness clock problem: the unit's 60 s is a generous budget for a list of forty cards, and the same read also gates every Store-tab unit. FIXED 2026-08-27: the feed hydrates a page in one chunked query per table plus one per currency for promotions, instead of five queries per offer; a 50-offer page costs the queries one offer costs (test_offer_page_hydrates_in_constant_queries).
caught bybilling_admin.publish_storefront_home · fixed in undef-billing 908feb9 · capture sweep 69 (production), billing_admin.publish_storefront_home network log (last request GET /v1/billing/store/undef/offers?limit=100 with no response); scratchpad/probe_prod_store_feed.py timings 2026-08-27tests/test_production_status.py builds a deploy tree per test through cached_deploy_tree; the template copies packages/undef-foundry/terraform verbatim, including .terraform/providers with three ~330 MB Cloudflare provider binaries, and each of 24 tests then gets a 1 GB copy across 8 xdist workers. A basetemp measured 24 GB; pytest keeps three, and every push runs the suite in the pre-push hook. On 2026-08-27 five pushes in one evening reached 79 GB under pytest-of-tim, the disk hit 0 bytes free at ~06:47Z, production sweep 5c died at its first batch with a traceback while recording, and the harness could not open an output file until space was freed by hand. The 2026-08-10/15 orphan-template leak was fixed by moving the template under pytest's basetemp; the size itself was not. AUDIT 2026-08-28: FIXED -- tests/test_production_status.py:1101-1118 ignores .terraform in the deploy-tree copy; newest basetemp 63M (was ~24 GB).
caught bystorefront_visitor.review_checkout_tax · fixed in 4df5af9b · du of $TMPDIR/pytest-of-tim/pytest-45/popen-gw2/test_build_status_adds_env_fil0 (1.0G workspace/packages, provider binaries under undef-foundry/terraform/.terraform/providers); scratchpad/sweep-prod-5c-enospc.log; tests/_deploy_fixtures.py cached_deploy_tree docstringStripe mints checkout.session.completed and charge.dispute.created in the same second for a disputing card. F-162's resolver (b42c0ca4) asked whether this tier knows the payment by looking for the payment ref on payment_intents and hosted_checkout_sessions; when the dispute handler ran before the completion handler had stored that ref, the tier's own dispute resolved to nothing and was dropped as foreign. Production sweep 8 (2026-08-27): Stripe raised du_1U998T... at 19:38:54Z and delivered it; billing wrote the session's completion at 19:38:55.979Z; payment_disputes holds no row; dispute_operator.decide skipped ('no open dispute appeared within 90s'). Sweep 7 had won the same race by 3 ms (completion 18:27:17.505, dispute 18:27:17.508). FIXED 071b031: when local rows miss, the service asks the provider which checkout session produced the payment (Stripe GET /v1/checkout/sessions?payment_intent=...) and resolves through the session row, which exists from checkout creation; a session this tier never created still answers 'not ours' (test_foreign_tier_dispute_is_not_recorded, test_stripe_adapter).
caught bydispute_operator.decide · fixed in undef-billing 071b031 · capture sweep 8 (production), precondition dispute-decide; Stripe events evt_1U998U... (19:38:54Z); undef-billing-prod-payments hosted_checkout_sessions.completed_at 2026-08-27T19:38:55.979Z, payment_disputes (no row)admin-tax-register-jurisdiction filed jurisdiction us-ca with a per-run reference (CA-nnnnn) and a per-run past date on whatever tier it ran, production included. A registration is a period: billing closes the previously open row at the new row's effective_from, so each production sweep made the harness's reference the open US-CA registration the engine priced sales under -- ten rows on undef-billing-prod-tax on 2026-08-27, one with effective_to NULL -- while config/tax_registrations.json declared production empty by decision (286cd50a) and tests/test_tax_units_skip_where_the_tier_declares_no_registration.py asserted it. Proving carried ~180 of them. FIXED c156f3cf: the macro files jurisdiction zz (ISO 3166 user-assigned, never a buyer's country) with no region, and the reference generator says ZZ-; the claim (an operator files a registration and reads back its row and posture) is unchanged. The ten production rows and proving's are left in place: deleting rows from a live registry is the operator's call (.provide/QUESTIONS.md).
caught bybilling_admin.register_tax_jurisdiction · fixed in c156f3cf · wrangler d1 execute undef-billing-prod-tax --remote: 10 US-CA sales_tax rows, registration_ref CA-55288 .. CA-14012, created 2026-08-26/27, CA-14012 effective_to NULL; config/tax_registrations.json [prod] registrations []; macro admin-tax-register-jurisdiction actions 3-5 (us-ca/us/ca)DisputeService._handle_dispute (disputes/service.py:102-109 at 43de70f0) opens storage.transaction(), calls upsert_from_event, then get_dispute(dispute_id) and asserts the row is there. On D1 a transaction is a batch: the read runs before the write lands, the assertion fails, worker_entry answers 500, Stripe retries, and on the retry the row exists so the second delivery succeeds -- which is why every dispute still ends up recorded and why F-162/F-166's tests (SQLite, where the read sees the write) never saw it. Cost: every new dispute's first event is a 500 the provider has to retry, its outbox effects run on the retry, and the worker logs an exception per dispute. The repo's ci/check_d1_transaction_reads.py gate ('no read-after-write inside transaction()') did not catch a read routed through the store. Fix: have upsert_from_event return the row it wrote (or the fields the rest of the handler needs) and drop the read-back; then the gate should learn the store-method shape. FIXED 2026-08-28: the finding's mechanism was only half right -- three production paths (hosted-checkout completion, the rate limiter) already read a row they wrote in the same D1 batch and work, so a batched read does see the batched write; what the tail recorded is a race: Stripe mints created + funds_withdrawn for one dispute in the same second, both invocations read no row, both mint a uuid4, the loser's INSERT keeps the winner's id under ON CONFLICT and its get_dispute(loser id) is None -> assert -> 500 -> the retry finds the row. The fix covers both: upsert_from_event is split into prepare_upsert (reads, returns the post-write linkage computed the way the statement's COALESCE/terminal WHERE leaves it) and apply_upsert (the one write) with no read-back, the upsert and its outbox row are one batch (the same split in _handle_signal is fixed), and dispute ids are derived (uuid5 of provider:ref) so two events racing to create one dispute publish the row's single id. ci/check_d1_transaction_reads.py now resolves reads routed through store methods and ratchets 77 pre-existing findings in ci/d1_transaction_reads.baseline.json (hosted-checkout completion and refund recording among them -- open work, not this finding). Tests: 3 behaviour tests that failed on the unfixed code at service.py:109, a race test, a SQLite proof that the Python linkage equals what the statement left.
fixed in undef-billing cc1f4aa7 ·wrangler tail undef-billing (production) during sweep 12, 2026-08-28T17:28:12Z: outcome exception, POST https://billing.undef.games/v1/webhooks/stripe -> 500, traceback provider_routes.py:97 -> disputes/service.py:47 -> :109 `assert dispute is not None` AssertionError; scratchpad/tail-billing-prod.jsonlauthFlow.refreshAccessToken (frontend/src/authFlow.ts:158) issued a bodyless credentialed POST to {authBaseUrl}/v1/auth/refresh during boot and awaited it; the request never settled, reported as net::ERR_TIMED_OUT, so the portal rendered LOADING ACCOUNT PORTAL forever, never redirected to /authorize, and the sign-in form the macros wait for (#auth-login-email) never appeared. Every unit therefore failed at step 0 with executed=0. Reproduced with plain headless Playwright, no octowright in the path, on BOTH production and proving. NOT cross-origin: the same fetch hung from a page on auth.undef.games itself. The endpoint was healthy -- ~35 curl probes of the exact bodyless credentialed shape all answered 401 in 70-423ms, with cookie headers up to 8KB, and direct browser navigation to the auth login page rendered the form in 0.5s. Ruled out: CPU load, octowright saturation, CORS config, IPv6, DNS, system/managed proxy and request size. The browser/edge mechanism remains unidentified; the Undef Platform fix does not depend on it. FIXED 2026-08-31 in undef-account ed6f2ab7: silent refresh is an optional cold-boot optimization, so the Account frontend now races the fetch against a three-second deadline, aborts it, returns the existing unauthenticated result, and proceeds to the sign-in flow instead of pinning the entire portal to the dependency. A never-settling-fetch regression test proves that boundary. The change was deployed to proving and production; a one-unit production rehearsal passed, proving's full sweep captured 120/120, and production sweep 17 captured 119/120 with zero failures and only the declared live-VIES skip.
fixed in undef-account ed6f2ab7 ·scratchpad/plain-probe2.log (goto 2.7s, selector timeout 30s, final url still account root); plain-probe3.log (cold direct navigation renders the auth login form in 0.5s, then the refresh POST from the account origin never returns); plain-probe4.log (same-origin fetch from the auth page itself also never returns); undef-account frontend/src/authFlow.test.ts never-settling-fetch regression; artifacts/persona-capture/proving/index.json digest 429906a18561 (120 captured, 0 failed); artifacts/persona-capture/production/index.json digest 8c260099ef4c (119 captured, 0 failed, one declared skip)UI-reachable actions no macro drives, grouped by why. This list existing at all is the difference between a proof and a highlight reel.
Every one of the 120 UI-reachable actions has a macro. There is nothing in this list, which is the point of it.
This page is one run. Sweep digest 429906a18561, built
2026-08-31 17:16 UTC. A gallery with no run identity cannot be told from a stale one: the
published copy read 38 of 78 for months while the tier proved 90 of 90,
and nothing on the page said which sweep it came from.
Run from artifacts/persona-capture/proving/index.json; denominator from
config/economy_gui_coverage.json, gated by
tests/test_action_coverage_gate.py.
account https://proving.account.undef.games · admin https://proving.admin.undef.games · auth https://proving.auth.undef.games · store https://proving.store.undef.games