diff --git a/README.md b/README.md index 00837cf..60c382c 100644 --- a/README.md +++ b/README.md @@ -127,7 +127,7 @@ app/ (routes, pages) worker/ (two interval loops) ## Limitations, honestly -- **Web app deployed; the worker is not.** The Next.js app is live on Vercel (https://settle-wine-alpha.vercel.app) in **real mode** against a hosted Postgres — landing, NEAR-wallet sign-in, invoice create / list / dashboard / receipt — and `GET /api/health` returns `{"status":"ok","demo":false,"database":"ok"}` from the running deployment, not only from a local boot. It was **re-deployed on 2026-11-09** from the merged tip — the Vercel project is not connected to Git, so a merge does not deploy — and the staleness probe in `DEPLOY.md` §8 went from 404 to 200. Loading the live URL in a real browser then found a hydration mismatch on the landing page (React #418): the server's HTML said wallet sign-in was unavailable while the browser's first render offered it, so React threw the markup away. Fixed here and pinned by the fifth e2e test, then deployed: the live page re-checked in Chromium at 1440 px and 390 px reports the sign-in button enabled, no page or console error, no failed request and no horizontal overflow. A screenshot of that page then caught the one defect no probe could: the hero receipt's amounts inherited the brand field's white text and rendered white-on-white, so the same e2e test now reads the amount's computed colour and fails it, and the fix (a `text-ink` on the card root) was proven by re-injecting the bug and watching the test go red first. A green `/api/health` detects neither problem, which is why the deploy notes now say to probe a route only the new artifact has and then read the first screen's console. It was **re-deployed once more on 2026-11-10** with S1.7: the challenge probe answers 200, `/api/health` is green, the landing page opens in Chromium with no console message, and the live `/api/tokens` carries `refundChain` and lists BTC as refund-only (`settleChain: null`) with no BTC asset among the payouts. Two things that URL does not do yet, stated plainly: **no live payment quote**, because the vendor `ONECLICK_JWT` (S0.8) is not in hand, so the pay page fails closed before it prices anything; and **no background worker**, because a serverless host cannot keep the long-lived 5 s poll / 60 s expire process. That second limit is exactly why `DEPLOY.md` §6 concluded that a two-process host is a paid decision — Render's free-plan page says free plans do not support background workers, and usage-based hosts bill a worker that never idles. A full live payment therefore still needs a host that runs both processes plus the JWT. The offline evidence is unchanged: `pnpm demo`, the E2E browser journey — which drives a **production build** (`pnpm build` + `pnpm start`, the same two commands a host runs) rather than `next dev` — and 671 passing offline tests (672 total, one Postgres-only skip). `DEPLOY.md` also records two constraints that were measured, not assumed: PGlite is single-process — two processes on one directory lost half their writes and killed one outright — so a hosted Settle needs Postgres; and demo mode deliberately refuses an `https://` URL, so the hosted app runs **real mode** (decision `SD-8`) and the demo story lives in `pnpm demo` and the video. +- **Web app deployed; the worker is not.** The Next.js app is live on Vercel (https://settle-wine-alpha.vercel.app) in **real mode** against a hosted Postgres — landing, NEAR-wallet sign-in, invoice create / list / dashboard / receipt — and `GET /api/health` returns `{"status":"ok","demo":false,"database":"ok"}` from the running deployment, not only from a local boot. It was **re-deployed on 2026-11-09** from the merged tip — the Vercel project is not connected to Git, so a merge does not deploy — and the staleness probe in `DEPLOY.md` §8 went from 404 to 200. Loading the live URL in a real browser then found a hydration mismatch on the landing page (React #418): the server's HTML said wallet sign-in was unavailable while the browser's first render offered it, so React threw the markup away. Fixed here and pinned by the fifth e2e test, then deployed: the live page re-checked in Chromium at 1440 px and 390 px reports the sign-in button enabled, no page or console error, no failed request and no horizontal overflow. A screenshot of that page then caught the one defect no probe could: the hero receipt's amounts inherited the brand field's white text and rendered white-on-white, so the same e2e test now reads the amount's computed colour and fails it, and the fix (a `text-ink` on the card root) was proven by re-injecting the bug and watching the test go red first. A green `/api/health` detects neither problem, which is why the deploy notes now say to probe a route only the new artifact has and then read the first screen's console. It was **re-deployed once more on 2026-11-10** with S1.7: the challenge probe answers 200, `/api/health` is green, the landing page opens in Chromium with no console message, and the live `/api/tokens` carries `refundChain` and lists BTC as refund-only (`settleChain: null`) with no BTC asset among the payouts. The **same day** it was deployed again with S4.15, the dark landing redesign: the served HTML carries the new hero ("Invoice in dollars. Paid in any token."), the challenge probe answers 200, `/api/health` is green, the sign-in button is enabled after hydration, and Chromium at 1440 px and 390 px reports **no page or console error and no horizontal overflow**. Two things that URL does not do yet, stated plainly: **no live payment quote**, because the vendor `ONECLICK_JWT` (S0.8) is not in hand, so the pay page fails closed before it prices anything; and **no background worker**, because a serverless host cannot keep the long-lived 5 s poll / 60 s expire process. That second limit is exactly why `DEPLOY.md` §6 concluded that a two-process host is a paid decision — Render's free-plan page says free plans do not support background workers, and usage-based hosts bill a worker that never idles. A full live payment therefore still needs a host that runs both processes plus the JWT. The offline evidence is unchanged: `pnpm demo`, the E2E browser journey — which drives a **production build** (`pnpm build` + `pnpm start`, the same two commands a host runs) rather than `next dev` — and 671 passing offline tests (672 total, one Postgres-only skip). `DEPLOY.md` also records two constraints that were measured, not assumed: PGlite is single-process — two processes on one directory lost half their writes and killed one outright — so a hosted Settle needs Postgres; and demo mode deliberately refuses an `https://` URL, so the hosted app runs **real mode** (decision `SD-8`) and the demo story lives in `pnpm demo` and the video. - **A real quote has never been driven offline, and since 2026-11-10 no quote is served without the partner JWT.** The minimum refusal itself is not a guess — `try at least N` was provoked against the live API on 2026-11-09 with unauthenticated _dry_ quotes, which is what fixed the units it is rendered in (S0.13). Then, on **2026-11-10**, the same unauthenticated `POST /v0/quote` — dry or not, on three routes including the USDC→USDC call that had answered 200 the day before — returned `400 Internal server error`, while the same body with a bogus bearer returned `401 Invalid token`. The token list still answers without credentials. So a real payment now needs the partner JWT (S0.8, #11) even for a preview, plus a funded signer, a running worker and a two-process host. - **Refund addresses are checked on five payout chains, plus Bitcoin.** `lib/core/address.ts` validates NEAR, EVM (EIP-55), Solana and, since S1.7, **BTC** — base58-check P2PKH/P2SH and segwit bech32/bech32m, mainnet only. Bitcoin is a _refund-only_ chain: a client can pay from BTC and is refunded there, but Settle never pays out to it. Everything else a client might pay from is still refused with a reason rather than accepted unchecked; for TON and Tron that is a missing validator, and for chains that need a memo it is the missing memo field. The memo list itself is ours and flagged 🔍, because 1Click does not publish which origins require one. Refusing errs safe: an address Settle cannot check is not one it will send money back to. - **A region block is passed through, not recognised.** The vendor's own wording reaches the client; Settle does not match it against strings it guessed. diff --git a/ROADMAP.md b/ROADMAP.md index 6df44f7..b6a56bb 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -11,22 +11,22 @@ ## Readiness -| Phase | Target dates | Progress | Status | -| ----------------------------------- | ------------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| D. Design & docs | Nov 4 | 100% | ✅ done | -| 0. Setup & verification | Nov 4–5 | 88% | in progress (14 of 16; **S0.12 + S0.13 ✅ 2026-11-09** answered from the live API and the vendor docs, no JWT needed — and S0.13 found a units bug that is fixed. Only S0.8 and S0.10 remain, both 👤) | -| 1. Core logic (`lib/core`) | Nov 5–6 | 100% | ✅ done (S1.1–S1.7; S1.7 validates Bitcoin refund addresses, so a BTC payer is checked here rather than only by the vendor) | -| 2. Integrations (1Click, NEAR, DB) | Nov 5–7 | 90% | in progress (S2.1–S2.9 done; S2.10 spends payer funds, blocked) | -| 3. API routes | Nov 6–7 | 100% | ✅ done (S3.1–S3.8; `storage_deposit` spend stays blocked on S2.10) | -| 4. UI | Nov 7–9 | 100% | ✅ done (S4.1–S4.15; the E2E demo journey shipped with Phase 6, S4.9 is the app-wide identity, S4.10 designs the landing page, S4.11 keeps the wallet stack out of the first bundle, S4.12/13 are the Landbook-inspired redesign and the brand assets, S4.14 keeps a 24-decimal amount inside its quote column, S4.15 restyles the landing as a dark crypto-exchange hero, and one live wallet sign-in is still 👤) | -| 5. Worker | Nov 8 | 100% | ✅ done (S5.1–S5.3; both loops run on the app's own deps and were run as a real process) | -| 6. Demo mode & dry-run | Nov 9–10 | 100% | ✅ done (S6.1–S6.7; `pnpm demo` runs with no `.env`, and the Playwright journey runs in CI against a **production build** — `pnpm demo:prod`, S6.7 — so CI drives the artifact Phase 8 deploys) | -| 7. Hardening & edge cases | Nov 10–11 | 100% | ✅ done (S7.1–S7.13; four were already built and are now pinned by tests, #108 closed the bare-receipt-link dead-end, and S7.13/#140 — found on the hosted URL, not by CI — stopped the landing page's first render depending on `window`, with a fifth e2e test that opens `/` and refuses a hydration mismatch. 🔍 the memo-chain list and the region-block mapping are still ours — S0.12/S0.13 came back from the vendor in 2026-11-09 and published neither) | -| 8. Deploy & real run | Nov 11 | 67% | in progress (**S8.1/S8.2/S8.3 ✅ 2026-11-08 — the human chose Vercel and said deploy; the web app is live in real mode on https://settle-wine-alpha.vercel.app against a hosted Neon Postgres, `/api/health` green from the running deployment, no login wall. The serverless host cannot run the worker, so payments stay fail-closed on that URL and one real payment (S8.4 👤) still needs the partner JWT. **Re-deployed 2026-11-09** on the human's "follow your recommendation": the live build was ~5 merged PRs stale — `GET /api/auth/challenge?intent=session` answered 404 — and now answers 200 from `ab9d241`, with `/api/health`, `/` and `/demo` all 200 and no login wall. Verifying it in a real browser found S7.13/#140. **Re-deployed again 2026-11-10** with S1.7/#149: challenge probe 200, `/api/health` green, landing page clean in Chromium, and the live `/api/tokens` shows `refundChain` with BTC refund-only and absent from `payoutAssets`. S8.4 is blocked on a credential, not on code: measured 2026-11-10, **every unauthenticated `POST /v0/quote` now answers `400 Internal server error`** — dry or not, three routes, including the USDC→USDC dry call that returned 200 on 2026-11-09 — while a bogus bearer gets `401 Invalid token` and `/v0/tokens` still answers 200**) | -| 9. README & public repo | Nov 11–12 | 100% | ✅ done (S9.1–S9.7; the fresh clone was run against the public URL and passes. The hosted demo URL is Phase 8, not this one) | -| 10. Launch: video, post, submission | Nov 12–13 | 57% | in progress (S10.1, S10.3, S10.5, S10.6 ✅ as drafts in `LAUNCH.md`; S10.2, S10.4, S10.7 are 👤 — voice-over decision and upload, posting, submitting; two walkthrough cuts are recorded) | -| 11. After submission | Nov 14–25 | 0% | not started | -| **Overall (MVP)** | | **92%** | by the formula under this table: (1100) ÷ 12 = **91.7**. See the correction note below — the number printed here for the last two days, ~82%, was itself miscalculated. **The figure that describes the entry is the one under it: 5 of 9 submission gates (56%).** | +| Phase | Target dates | Progress | Status | +| ----------------------------------- | ------------ | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| D. Design & docs | Nov 4 | 100% | ✅ done | +| 0. Setup & verification | Nov 4–5 | 88% | in progress (14 of 16; **S0.12 + S0.13 ✅ 2026-11-09** answered from the live API and the vendor docs, no JWT needed — and S0.13 found a units bug that is fixed. Only S0.8 and S0.10 remain, both 👤) | +| 1. Core logic (`lib/core`) | Nov 5–6 | 100% | ✅ done (S1.1–S1.7; S1.7 validates Bitcoin refund addresses, so a BTC payer is checked here rather than only by the vendor) | +| 2. Integrations (1Click, NEAR, DB) | Nov 5–7 | 90% | in progress (S2.1–S2.9 done; S2.10 spends payer funds, blocked) | +| 3. API routes | Nov 6–7 | 100% | ✅ done (S3.1–S3.8; `storage_deposit` spend stays blocked on S2.10) | +| 4. UI | Nov 7–9 | 100% | ✅ done (S4.1–S4.15; the E2E demo journey shipped with Phase 6, S4.9 is the app-wide identity, S4.10 designs the landing page, S4.11 keeps the wallet stack out of the first bundle, S4.12/13 are the Landbook-inspired redesign and the brand assets, S4.14 keeps a 24-decimal amount inside its quote column, S4.15 restyles the landing as a dark crypto-exchange hero, and one live wallet sign-in is still 👤) | +| 5. Worker | Nov 8 | 100% | ✅ done (S5.1–S5.3; both loops run on the app's own deps and were run as a real process) | +| 6. Demo mode & dry-run | Nov 9–10 | 100% | ✅ done (S6.1–S6.7; `pnpm demo` runs with no `.env`, and the Playwright journey runs in CI against a **production build** — `pnpm demo:prod`, S6.7 — so CI drives the artifact Phase 8 deploys) | +| 7. Hardening & edge cases | Nov 10–11 | 100% | ✅ done (S7.1–S7.13; four were already built and are now pinned by tests, #108 closed the bare-receipt-link dead-end, and S7.13/#140 — found on the hosted URL, not by CI — stopped the landing page's first render depending on `window`, with a fifth e2e test that opens `/` and refuses a hydration mismatch. 🔍 the memo-chain list and the region-block mapping are still ours — S0.12/S0.13 came back from the vendor in 2026-11-09 and published neither) | +| 8. Deploy & real run | Nov 11 | 67% | in progress (**S8.1/S8.2/S8.3 ✅ 2026-11-08 — the human chose Vercel and said deploy; the web app is live in real mode on https://settle-wine-alpha.vercel.app against a hosted Neon Postgres, `/api/health` green from the running deployment, no login wall. The serverless host cannot run the worker, so payments stay fail-closed on that URL and one real payment (S8.4 👤) still needs the partner JWT. **Re-deployed 2026-11-09** on the human's "follow your recommendation": the live build was ~5 merged PRs stale — `GET /api/auth/challenge?intent=session` answered 404 — and now answers 200 from `ab9d241`, with `/api/health`, `/` and `/demo` all 200 and no login wall. Verifying it in a real browser found S7.13/#140. **Re-deployed again 2026-11-10** with S1.7/#149: challenge probe 200, `/api/health` green, landing page clean in Chromium, and the live `/api/tokens` shows `refundChain` with BTC refund-only and absent from `payoutAssets`. S8.4 is blocked on a credential, not on code: measured 2026-11-10, **every unauthenticated `POST /v0/quote` now answers `400 Internal server error`** — dry or not, three routes, including the USDC→USDC dry call that returned 200 on 2026-11-09 — while a bogus bearer gets `401 Invalid token` and `/v0/tokens` still answers 200**. **Re-deployed the same day with S4.15**: the live HTML serves the dark landing hero, the challenge probe is 200, `/api/health` is green, and Chromium at 1440 px and 390 px reports an enabled sign-in button, no page or console error and no horizontal overflow**) | +| 9. README & public repo | Nov 11–12 | 100% | ✅ done (S9.1–S9.7; the fresh clone was run against the public URL and passes. The hosted demo URL is Phase 8, not this one) | +| 10. Launch: video, post, submission | Nov 12–13 | 57% | in progress (S10.1, S10.3, S10.5, S10.6 ✅ as drafts in `LAUNCH.md`; S10.2, S10.4, S10.7 are 👤 — voice-over decision and upload, posting, submitting; two walkthrough cuts are recorded) | +| 11. After submission | Nov 14–25 | 0% | not started | +| **Overall (MVP)** | | **92%** | by the formula under this table: (1100) ÷ 12 = **91.7**. See the correction note below — the number printed here for the last two days, ~82%, was itself miscalculated. **The figure that describes the entry is the one under it: 5 of 9 submission gates (56%).** | Phase % = done tasks ÷ non-dropped tasks in that phase, and each of those is a count, not an impression: Phase 0 is 14 of 16, Phase 1 is 7 of 7, Phase 2 is 9 of 10, Phase 8 is 4 of 6, Phase 10 is 4 of 7, the rest are complete. Overall = D and phases 0–10, twelve equally weighted numbers: (100+100+86+90+100+100+100+100+100+67+100+57) = 1100, ÷ 12 = **91.7%**.