Release: develop -> main - #186
Open
github-actions[bot] wants to merge 13 commits into
Open
Conversation
Rewrite the README into a project overview, a system-wide repo map, and an app-specific guide. Add the end-to-end layer/repo table, a "What zkCoins is" intro, and consolidate the app section (stack, trust model, thin-client architecture, develop/build, configuration, layout, branch flow). Replace the stale server-repo reference with zk-coins/node and neutralise the hosted-operator wording.
…182) * feat: multi-asset wallet UI — create-coin flow, per-asset portfolio, i18n Mirrors the neutral multi-asset contract (node#220 / sdk#29). No native asset; per-(owner, asset_id) accounts. - Create-coin flow (replaces the testnet faucet): name/decimals/amount form -> two-phase creator-signed mint (src/app/create). - Per-asset portfolio on home (GET /api/balance/:address) with empty state; usePortfolio hook; formatAssetAmount/shortAssetId. - Asset picker in Send; chosen asset_id flows into the send; amount scaled by the asset's decimals. - Per-asset detail screen (src/app/asset/[id]) with the owner-history note (history is per-wallet, not per-asset). - i18n de (default) + en via next-intl; all user-facing strings + error messages moved into messages/{de,en}.json. - API layer (src/lib/api/client.ts) implements the multi-asset wire bits locally (buildMintMessage byte-for-byte vs the SDK source, per-asset balance + ownerBalances, creator-signed createCoin, send with asset_id), reusing the existing @zkcoins/wasm crypto path; the installed @zkcoins/sdk predates multi-asset, so the wire bits live in the app until the SDK (sdk#29) is published. - e2e harness funds via the create-coin flow. Verified: next lint clean, prettier (CI scope src/**) clean, next build green, vitest 535 passed (stmts 90.5 / branches 84.5 / funcs 90.7 / lines 91.1; strict src/lib + src/hooks 100%), tsc clean, live-node smoke green (node accepted the app's mint-message signature). * fix(crypto+e2e): derive wallet address as node-compatible Poseidon; multi-asset goldens prep CRITICAL: the app's address derivation (app/rust/shared hash()) used SHA-256, but node#220 keys accounts by owner = Poseidon(creator_pubkey) (hash_bytes). So the app's address never matched the node owner — the live portfolio (GET /api/balance/:address) would never show minted assets. Aligned the app's shared crate to the node's Poseidon-Goldilocks hash + digest_to_bytes (byte-for-byte) and rebuilt @zkcoins/wasm. Verified: new address_hex == digest_to_bytes(Poseidon(pubkey0)) == node owner; a completed create-coin mint then shows under that address. - e2e/_helpers/wasm.ts loads the rebuilt wasm in Node; _helpers/api.ts + _global-setup.ts derive the polled address via the wasm Poseidon path (was the SDK's sha256), so fixture funding is detected (3 Dockerized globalSetup runs funded Alice). - New screenshot specs 18-create-coin, 19-portfolio, 20-send-asset, 21-asset-detail (desktop+mobile, applicable states); 06/17 repaired for the per-asset UI; registered in playwright.config. - e2e build locale override NEXT_PUBLIC_E2E_LOCALE (app default stays de; e2e bakes en for stable snapshots). - a11y: bump asset-id text contrast to WCAG-AA (text-ink3). - scripts/e2e-local.sh: publish --update-snapshots baselines back from the throwaway container to the worktree. Baselines themselves land in a follow-up commit once generated against the running node (lint/build/unit are green; tsc clean). * test(e2e): green multi-asset screenshot-golden suite + regenerated baselines Finish the e2e visual-regression suite for the multi-asset wallet so a no-update `scripts/e2e-local.sh` run passes end to end against a local node (leg 1: 106 passed; leg 2 real send: 1 passed). Spec fixes for the single-asset -> multi-asset migration: - 07-send: rewrite for the per-asset Send flow (asset picker + per-asset Available readout + amount in asset units), consistent with 20-send-asset. Keeps every branch (default/no-funds/recipient/amount/ set-max/invalid/insufficient/confirm/cancel/real send-success). The no-funds banner is driven via a route-mocked zero-balance asset (the live fixtures never produce a held-but-empty asset). Mask the volatile asset name on the success screen via a new `send-success-amount` testid. - 13-send-server-errors: assert the English `errors.*` catalog strings (the e2e build bakes NEXT_PUBLIC_E2E_LOCALE=en) instead of German; fix the flow to the per-asset form with a valid asset-unit amount. - 17-tx-detail: the local node lacks `GET /api/history/{id}` (404), so drive the detail-body goldens via a `page.route()` mock of that route returning a deterministic mint TxDetail; the live history list (and the clickable row) is untouched. The not-found case stays unmocked. Tooling + docs: - scripts/e2e-local.sh: strip a leading `--` arg separator on the host entrypoint so `e2e-local.sh -- --update-snapshots` forwards the flag to Playwright instead of passing a bare `--` (which made Playwright treat it as a test-file filter -> "No tests found"). - public/handbook: document the new screens (specs 18-21) and drop the removed balance-hidden entry, so the `prebuild` handbook<->baseline coverage gate passes. Regenerated all affected `*-chromium-linux.png` baselines and added the new spec 18-21 baselines (Docker Playwright, locale=en, against the live node). Removed the orphan 06-balance-hidden baseline. * ci: pin app/rust to nightly (plonky2 in shared needs it) + resync package-lock - rust/rust-toolchain.toml = nightly so the Rust Crypto Tests job (and the wasm build) compile the Poseidon-Goldilocks address path (plonky2 requires nightly), mirroring the node workspace. - Regenerate package-lock.json so npm ci is in sync (next-intl transitive deps incl. @swc/helpers). * build: pin @swc/helpers 0.5.23 via overrides so npm ci resolves consistently CI's npm resolves next@15.5's transitive @swc/helpers to 0.5.23 while a newer local npm pinned 0.5.15, leaving the lock file out of sync (npm ci EUSAGE 'Missing @swc/helpers@0.5.23'). An explicit override fixes the version across the tree; lock file regenerated, npm ci --dry-run clean. * test(e2e): cover create/asset-detail routes in audits, drop stale balance ghosts The multi-asset redesign added two route screens (`/create`, `/asset/[id]`) and replaced the single balance hero with a per-asset portfolio, leaving the two CI audits red: - golden-coverage: register the `/create` and `/asset/[id]` route screens in `e2e/_audit/screens.ts` with their `18-create-empty-*` / `21-asset-detail-*` baselines (already produced by specs 18 / 21). - button-inventory: - cover the two uncovered testids with real assertions — `getByTestId('create-phase')` in the create-success flow (the lifecycle phase label renders during the live mint) and `getByTestId('asset-row-decimals')` in the asset-detail happy path. - clear the three balance-hero ghost testids (`balance-amount-usd`, `balance-amount-btc`, `balance-value`) that no longer exist in `src/`: the default screenshot mask now targets the portfolio's volatile `asset-row-balance` cell, and the stale references in fixtures/README are updated to the per-asset model. The mask swap is pixel-neutral: `asset-row-balance` is already masked per-spec wherever it renders (06/19/21) and matches nothing elsewhere, while the removed `balance-amount-*` mask/CSS selectors matched nothing — so no baseline regeneration is required. * fix(build): pin @swc/helpers to 0.5.15 (next 15.5.18's exact dep) so standalone boots The 0.5.23 override satisfied @swc/core's optional >=0.5.17 peer but violated next@15.5.18's exact @swc/helpers 0.5.15 requirement. next's standalone require-hook is compiled against 0.5.15's file layout (esm/_interop_require_default.js), which 0.5.23 does not ship — so `node .next/standalone/server.js` crashed with MODULE_NOT_FOUND and the E2E job's app never came up. 0.5.15 satisfies next exactly; @swc/core's peer is optional and build-time only, unaffected at runtime. * feat(app): make the wallet a capability-adaptive multi-asset client The branch made the app multi-asset-only, which broke the E2E CI job: it serves the PR bundle against the single-asset DEV node (info-proxy forces capabilities.multi_asset=false), so the create-coin globalSetup, the portfolio-only WalletScreen, and the per-asset send all failed. Render the pre-branch single-asset surface when the node reports multi_asset:false, and the multi-asset surface only when true — mirroring how the repo already gates username_claim / address_list / lnurl. Gating: - src/lib/features.ts: add MULTI_ASSET as a build-time route gate (NEXT_PUBLIC_ENABLE_MULTI_ASSET, dead-strips /create + /asset) AND a runtime capability on useFeatures() (drives the shared screens). - WalletScreen: multi_asset=false → single-asset balance hero (balance-value + eye toggle + faucet via api.mint/api.walletBalance); true → per-asset portfolio + create-coin entry. - send/page.tsx: split into single-asset (api.walletSend, no asset_id) and multi-asset (asset picker, api.send) surfaces selected at runtime. - /create + /asset/[id]: build-time notFound() + runtime redirect home when multi_asset is off. - api client: add walletBalance (single-arg) + faucet mint + walletSend (no asset_id) alongside the multi-asset balance/ownerBalances/send. E2E: - _global-setup.ts: branch on the node's real /api/info — faucet-fund on false, create-coin on true. Keeps the WASM-Poseidon address derivation. - specs 18-21: skip when multi_asset:false via a shared capability probe (_helpers/capabilities.ts); their committed baselines are dropped (gated, no CI baseline) but the specs run + pass against a true node. - screens.ts: /create + /asset are MULTI_ASSET-gated (no baseline); gates.mjs adds MULTI_ASSET to ENV_GATED_FEATURES. - regenerate the false-surface 0x baselines (06/07/13/17 + the wallet shots in 02-05/08-10/15) to the single-asset rendering; restore the balance-amount-{usd,btc} masks + balance-value testid + handbook refs. Tests: features.test covers MULTI_ASSET; client.test covers walletBalance/mint/walletSend; new single-asset WalletScreen + Send specs; existing multi-asset unit tests pin the runtime capability ON. * fix(e2e+wallet): CI-rendered send baselines + gate portfolio poll, dedupe recipient resolve - Replace the 8 send-surface visual baselines (07-send + 15-scan-filled) with the ubuntu-latest Chromium renders the E2E job itself produces. The dual-mode rework's baselines were generated in the local Docker Playwright image, whose font metrics differ from the CI runner's npx-installed Chromium; text reflowed ~2% on the send chrome and tripped the threshold (text-light screens like 06 stayed just under). Harvesting the CI actuals makes the send baselines consistent with the rest of the repo's CI-rendered *-chromium-linux.png set. - WalletScreen: gate usePortfolio on MULTI_ASSET so a single-asset node is not polled on GET /api/balance/:address (404 there) every 5 s. - send/page.tsx: extract the byte-identical recipient-resolution block from both surfaces into a shared resolveRecipient() helper. * test(e2e): assert German send-error copy (de is the build/default locale) CI builds the app with the default `de` locale (the committed baselines render German — e.g. 'Bitcoin senden'), but the dual-mode rework's spec assertions were anglicised to 'Invalid amount' / 'Server error …'. Restore the German strings (matching messages/de.json + the pre-branch specs) so 07-send amount validation and 13 server-error toasts match the rendered text. The send-error tests fail on the toHaveText before their snap(), so this also lets those screenshots run. * test(e2e): CI-rendered baselines for the send error-state screens The amount-invalid/insufficient (07) and server-error toast (13) screens were unblocked once their assertions matched the de locale; their Docker-generated baselines then tripped the same font-metric drift vs the CI runner's Chromium. Replace them with the E2E job's own ubuntu-latest renders, consistent with the rest of the *-chromium-linux.png set.
…ract (#185) * fix(e2e): seed single-asset fixtures via the creator-signed mint contract The DEV node's neutral permissionless minting (zk-coins/node#220/#222) removed the server-mediated faucet: POST /api/jobs/mint now requires the creator-bound signed contract and 422s the old {account_address, amount} body, GET /api/balance?address= requires asset_id (no native asset), and sends without asset_id are rejected. The E2E globalSetup single-asset leg still posted the old mint body, failing every CI run at seeding. - e2e/_global-setup.ts: the single-asset leg now seeds Alice through the same creator-signed createCoin flow as the multi-asset leg, with a deterministic E2E-FIXTURE asset name, and asserts the wasm-derived mint owner matches the wallet UI address. - e2e/_helpers/api.ts: drop the dead old-contract mint helper; document that the parameterless walletBalance read only works through the proxy translation. - scripts/e2e-info-proxy.mjs: translate the single-asset surface against the multi-asset upstream — aggregate GET /api/balance?address= from the per-owner portfolio (num_sends summed wallet-globally) and inject the sender's sole asset_id into asset_id-less sends (the send signature does not cover asset_id). Capabilities normalisation is unchanged. - src/lib/api/client.ts + WalletScreen: rewrite the faucet as a creator-signed self-mint (delegates to createCoin with a unique FAUCET-<ts> asset name); no caller posts the old contract any more. - .gitattributes: mark packages/zkcoins-wasm/src/pkg/* linguist-generated so the generated wasm-bindgen glue stops attracting style findings. - unit tests updated/extended for the new faucet shape and both proxy translations (100% proxy coverage gate kept). * fix(e2e): make single-asset seeding retry idempotent The node rejects a re-mint into an existing (owner, asset_id) account, so with the deterministic E2E-FIXTURE name a createCoinWithRetry retry failed deterministically whenever an earlier attempt had landed server-side but the client's completed-poll blipped — even though Alice was actually funded. Treat the node's re-mint rejection on attempt >= 2 (deterministic names only) as already-seeded and defer to the independent balance poll for verification; the predicate lives in a dependency-free helper with unit tests. Also: widen the .gitattributes pkg glob to ** so future wasm-pack snippets/ subdirs stay linguist-generated, prettier-format e2e/README.md (pre-existing check failure), and document that E2E_FAUCET_CALLS > 1 produces a multi-asset portfolio in the proxied single-asset env after which send injection 422s.
Promote: staging -> develop
TaprootFreak
marked this pull request as ready for review
June 11, 2026 21:17
Contributor
Author
[OK] Button-Inventory-Audit — all clearChecked 137 testid(s) in |
Contributor
Author
[OK] Golden-Coverage-Audit — all clearEvery active, ungated screen has its golden: 12 active screen(s) across 10 route(s), 2 env-gated route(s) exempt.
|
6 tasks
…189) * test: close the src/app unit-coverage gap to 100% function coverage Cover the untested route-component handlers so src/app/** reaches 100% function coverage (was 75%): - send/page.tsx: single-asset scan/Set-max/cancel/Done/phase handlers and no-funds banner; multi-asset select onChange, ?asset= deep-link default, and success Done button - page.tsx: the unlock-screen handleReset escape hatch - create/page.tsx: the createCoin onPhase callback - receive/page.tsx: the clipboard-write rejection leg - settings/page.tsx: extract the disabled-only Toggle handler and c8-ignore it (all shipped settings toggles are "Planned"/disabled) Recalibrate the global functions threshold 86 -> 93 and add a per-glob src/app/** functions:100 gate so the route surface cannot silently regress again. Closes #188 * test: query home-reset stubs by role/label to satisfy the button-inventory audit The mocked Home child components used data-testids, which the button-inventory audit (scans src/ incl. __tests__) flagged as orphans; switch to role/aria-label queries like the QrScanModal stubs.
Coverage scope is now one deterministic criterion: code not behind a NEXT_PUBLIC_ENABLE_* build flag is default-active and must reach 100% (unit + e2e); env-gated code is exempt. No more triage / decorative / no-logic exemptions. - vitest.config: encode the rule; split excludes into permanent (env-gated) vs DEBT (not env-gated, must be covered — this list only shrinks); point at ENV_GATED_FEATURES as the single source of truth. - Remove the "MVP" term repo-wide (code comments, audit scripts, e2e/README.md) in favour of default-active / env-gated / always-on. - Rename MVP_EXEMPT_* -> EXEMPT_* in the button-coverage audit. - Fix mislabels: faucet (off-mainnet) and username resolve are always-on, not env-gated; the /network chart is in scope. No behaviour change: coverage thresholds, the test set, and both audits are unchanged.
Bring src/lib/simulate-network.ts and src/lib/api/explorer.ts to 100% coverage and drop them from the vitest DEBT exclude list, so the strict src/lib/** 100% gate again spans all of src/lib. Per the coverage-scope rule (#190): not env-gated -> coverage-required. - simulate-network: buildHistory (no-arg defaults + explicit args), nextSample (injected rng + Math.random default), plus deterministic-seed and timestamp-spacing assertions. - explorer: getNetworkActivity across every branch — no URL configured, ok + non-empty data, empty array, non-array samples, non-ok response, and fetch rejection.
Bring src/app/network/page.tsx and src/components/NetworkActivity.tsx to 100% coverage and drop them from the vitest DEBT exclude list. Per the coverage-scope rule (#190): not env-gated -> coverage-required. - network/page: drives the poll state machine — placeholder->loaded swap, the simulated local tick, the explorer re-fetch (samples present vs empty), and the failed-initial-fetch path that still marks loaded and starts no interval (fake timers). - NetworkActivity: data->geometry branches — populated vs empty window, live readouts, x-axis labels, path building. - Two genuinely-unreachable defensive guards (catmullRomToBezier length, interval cleanup ref) are c8-ignored with a justification, matching the existing convention.
…burn-down (#194) Cover the last non-env-gated files and remove them from the vitest exclude list, which now holds only env-gated files. Ratchet the global thresholds up to lock in the completed burn-down. - PixelIcon: render every icon in the map (sprite -> 1x1 rects) plus the size/color/className/rest-prop surface. - Logo / PixelLogo: default + explicit size, prop forwarding. - RootLayout: metadata/viewport exports and the html/body shell (next/font/google mocked). - vitest.config: exclude list is now env-gated-only; global floors raised to lines 92 / statements 92 / functions 94 / branches 85 (just under the live 92.9 / 92.3 / 94.3 / 85.8).
The hosted DEV (dev-api.zkcoins.app) + PRD (api.zkcoins.app) nodes were retired and now return 502, so the required 'E2E Tests' check had no reachable upstream and every PR was blocked. Repoint the node URL to ci.zkcoins.app — a dedicated Mutinynet node under the project's own domain — across: - ci.yaml E2E_NODE_URL (the required E2E gate) - api-contract.yml live contract probe default + dispatch default - regenerate-visual-baselines.yml E2E_API_URL Same upstream contract as before (real ZK proof gen + real Mutinynet broadcast); only the hostname changes. No DFX-internal infra names are referenced from this public repo.
Staging mirror of #196 (which landed on develop). In the feature -> staging -> develop -> main flow, staging is upstream of develop, so the E2E_NODE_URL repoint from #196 does not reach staging-based feature branches. Apply the identical change here so staging (and feature PRs based on it, e.g. #195) target the live ci.zkcoins.app node instead of the retired dev-api.zkcoins.app (502). Reconciles trivially on the next staging->develop promotion (develop already carries the identical value).
…I_ASSET gate) (#195) * feat: make multi-asset default-active (remove NEXT_PUBLIC_ENABLE_MULTI_ASSET gate) The multi-asset routes (/create, /asset/[id]) and the per-asset surface no longer sit behind the NEXT_PUBLIC_ENABLE_MULTI_ASSET build flag — they ship unconditionally. Whether the per-asset UI renders is driven purely by the runtime node capability (caps.multi_asset from /api/info), exactly like username_claim. - features.ts: drop the MULTI_ASSET build flag; the runtime useFeatures().MULTI_ASSET (= caps.multi_asset) stays. - create/page.tsx, asset/[id]/page.tsx: remove the `!FEATURES.MULTI_ASSET) notFound()` build guard (the runtime redirect-home guard stays). - gates.mjs: MULTI_ASSET is no longer an env gate. - screens.ts: /create + /asset/[id] are now default-active screens; register their page-level goldens. - features.test.ts + page tests: drop the build-flag assertions / stale guard comments. Golden baselines for the two routes must be generated against a multi_asset:true node via the regenerate-visual-baselines workflow before the Golden-Coverage-Audit goes green. * test(e2e): add the multi-asset leg + generate the /create + /asset goldens Adds the multi_asset:true leg the multi-asset-default surface needs, and the page-level baselines registered for /create + /asset[id] (so the Golden-Coverage-Audit passes). - e2e-info-proxy: `E2E_INFO_MULTI_ASSET=true` mode reports multi_asset:true and passes the per-asset balance/send through 1:1 (the multi-asset app issues native requests); proxy unit suite extended to keep its strict 100% gate. - e2e-local: thread `E2E_MULTI_ASSET` to the proxy; fix two latent regen bugs (the baseline sync-back missed `--update-snapshots=all` and was skipped by `set -e` when any spec failed). - e2e/18..21 baselines: captured on m5me (noble container) against the local multi_asset:true node — specs 18-21 ran green (19 passed). These are golden-audit existence targets; CI's single-asset leg skips them. * docs(handbook): document the multi-asset screens (create, portfolio, send-asset, asset-detail) Adds spec-18..21 sections (EN + DE) for the multi-asset surface, referencing all 19 new baselines so the handbook <-> baseline consistency gate (sync-handbook-baselines, run in prebuild) passes. Each section follows the existing per-spec layout with the mobile/desktop viewport toggle.
* test: close the src/app unit-coverage gap to 100% function coverage (#189) * test: close the src/app unit-coverage gap to 100% function coverage Cover the untested route-component handlers so src/app/** reaches 100% function coverage (was 75%): - send/page.tsx: single-asset scan/Set-max/cancel/Done/phase handlers and no-funds banner; multi-asset select onChange, ?asset= deep-link default, and success Done button - page.tsx: the unlock-screen handleReset escape hatch - create/page.tsx: the createCoin onPhase callback - receive/page.tsx: the clipboard-write rejection leg - settings/page.tsx: extract the disabled-only Toggle handler and c8-ignore it (all shipped settings toggles are "Planned"/disabled) Recalibrate the global functions threshold 86 -> 93 and add a per-glob src/app/** functions:100 gate so the route surface cannot silently regress again. Closes #188 * test: query home-reset stubs by role/label to satisfy the button-inventory audit The mocked Home child components used data-testids, which the button-inventory audit (scans src/ incl. __tests__) flagged as orphans; switch to role/aria-label queries like the QrScanModal stubs. * test: define coverage-scope rule and remove the "MVP" concept (#190) Coverage scope is now one deterministic criterion: code not behind a NEXT_PUBLIC_ENABLE_* build flag is default-active and must reach 100% (unit + e2e); env-gated code is exempt. No more triage / decorative / no-logic exemptions. - vitest.config: encode the rule; split excludes into permanent (env-gated) vs DEBT (not env-gated, must be covered — this list only shrinks); point at ENV_GATED_FEATURES as the single source of truth. - Remove the "MVP" term repo-wide (code comments, audit scripts, e2e/README.md) in favour of default-active / env-gated / always-on. - Rename MVP_EXEMPT_* -> EXEMPT_* in the button-coverage audit. - Fix mislabels: faucet (off-mainnet) and username resolve are always-on, not env-gated; the /network chart is in scope. No behaviour change: coverage thresholds, the test set, and both audits are unchanged. * test: cover the network-activity lib helpers to 100% (#192) Bring src/lib/simulate-network.ts and src/lib/api/explorer.ts to 100% coverage and drop them from the vitest DEBT exclude list, so the strict src/lib/** 100% gate again spans all of src/lib. Per the coverage-scope rule (#190): not env-gated -> coverage-required. - simulate-network: buildHistory (no-arg defaults + explicit args), nextSample (injected rng + Math.random default), plus deterministic-seed and timestamp-spacing assertions. - explorer: getNetworkActivity across every branch — no URL configured, ok + non-empty data, empty array, non-array samples, non-ok response, and fetch rejection. * test: cover the network-activity chart UI to 100% (#193) Bring src/app/network/page.tsx and src/components/NetworkActivity.tsx to 100% coverage and drop them from the vitest DEBT exclude list. Per the coverage-scope rule (#190): not env-gated -> coverage-required. - network/page: drives the poll state machine — placeholder->loaded swap, the simulated local tick, the explorer re-fetch (samples present vs empty), and the failed-initial-fetch path that still marks loaded and starts no interval (fake timers). - NetworkActivity: data->geometry branches — populated vs empty window, live readouts, x-axis labels, path building. - Two genuinely-unreachable defensive guards (catmullRomToBezier length, interval cleanup ref) are c8-ignored with a justification, matching the existing convention. * test: cover decorative icons + root layout, finish the coverage DEBT burn-down (#194) Cover the last non-env-gated files and remove them from the vitest exclude list, which now holds only env-gated files. Ratchet the global thresholds up to lock in the completed burn-down. - PixelIcon: render every icon in the map (sprite -> 1x1 rects) plus the size/color/className/rest-prop surface. - Logo / PixelLogo: default + explicit size, prop forwarding. - RootLayout: metadata/viewport exports and the html/body shell (next/font/google mocked). - vitest.config: exclude list is now env-gated-only; global floors raised to lines 92 / statements 92 / functions 94 / branches 85 (just under the live 92.9 / 92.3 / 94.3 / 85.8). * ci: point E2E upstream node at ci.zkcoins.app (staging) (#197) Staging mirror of #196 (which landed on develop). In the feature -> staging -> develop -> main flow, staging is upstream of develop, so the E2E_NODE_URL repoint from #196 does not reach staging-based feature branches. Apply the identical change here so staging (and feature PRs based on it, e.g. #195) target the live ci.zkcoins.app node instead of the retired dev-api.zkcoins.app (502). Reconciles trivially on the next staging->develop promotion (develop already carries the identical value). * feat: make multi-asset default-active (remove NEXT_PUBLIC_ENABLE_MULTI_ASSET gate) (#195) * feat: make multi-asset default-active (remove NEXT_PUBLIC_ENABLE_MULTI_ASSET gate) The multi-asset routes (/create, /asset/[id]) and the per-asset surface no longer sit behind the NEXT_PUBLIC_ENABLE_MULTI_ASSET build flag — they ship unconditionally. Whether the per-asset UI renders is driven purely by the runtime node capability (caps.multi_asset from /api/info), exactly like username_claim. - features.ts: drop the MULTI_ASSET build flag; the runtime useFeatures().MULTI_ASSET (= caps.multi_asset) stays. - create/page.tsx, asset/[id]/page.tsx: remove the `!FEATURES.MULTI_ASSET) notFound()` build guard (the runtime redirect-home guard stays). - gates.mjs: MULTI_ASSET is no longer an env gate. - screens.ts: /create + /asset/[id] are now default-active screens; register their page-level goldens. - features.test.ts + page tests: drop the build-flag assertions / stale guard comments. Golden baselines for the two routes must be generated against a multi_asset:true node via the regenerate-visual-baselines workflow before the Golden-Coverage-Audit goes green. * test(e2e): add the multi-asset leg + generate the /create + /asset goldens Adds the multi_asset:true leg the multi-asset-default surface needs, and the page-level baselines registered for /create + /asset[id] (so the Golden-Coverage-Audit passes). - e2e-info-proxy: `E2E_INFO_MULTI_ASSET=true` mode reports multi_asset:true and passes the per-asset balance/send through 1:1 (the multi-asset app issues native requests); proxy unit suite extended to keep its strict 100% gate. - e2e-local: thread `E2E_MULTI_ASSET` to the proxy; fix two latent regen bugs (the baseline sync-back missed `--update-snapshots=all` and was skipped by `set -e` when any spec failed). - e2e/18..21 baselines: captured on m5me (noble container) against the local multi_asset:true node — specs 18-21 ran green (19 passed). These are golden-audit existence targets; CI's single-asset leg skips them. * docs(handbook): document the multi-asset screens (create, portfolio, send-asset, asset-detail) Adds spec-18..21 sections (EN + DE) for the multi-asset surface, referencing all 19 new baselines so the handbook <-> baseline consistency gate (sync-handbook-baselines, run in prebuild) passes. Each section follows the existing per-spec layout with the mobile/desktop viewport toggle. --------- Co-authored-by: TaprootFreak <142087526+TaprootFreak@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Automatic Release PR
Commits: 4 new commit(s)