Release: develop -> main - #139
Merged
Merged
Conversation
* feat(features): consume username_claim runtime capability Pairs with zk-coins/node#143, which splits the username write path behind a `username-claim` Cargo feature and exposes `/api/info.capabilities.username_claim`. This PR teaches the app to read that bit and gate the Claim input on it, dropping the previous attempt at a build-time client flag (closed PR #136 — wrong layer: client flags can't react to a server policy change without a rebuild, exactly the drift the runtime-capability layer exists to remove). Wiring: - `CapabilitiesSchema` adds `username_claim: z.boolean().optional()` (optional for one release cycle so an app pointed at a pre-#143 node doesn't trip the schema; the store fails closed otherwise). - `useFeatures()` exposes `USERNAME_CLAIM`, computed as `caps.username_claim ?? false`. Same fail-closed shape as the other capability bools. - `WalletScreen` gates the claim form + inline error banner on `features.USERNAME_CLAIM && features.USERNAMES && !account.username`. The display branch (`features.USERNAMES && account.username`) is unchanged — previously claimed names continue to render. - `audit-button-coverage` rationale for the `username-claim-btn` exemption now correctly attributes it to the runtime capability (the earlier `FEATURES.USERNAMES` claim was already false — that flag is runtime, not build-time DCE). Test plan: - `features.test.ts` extended: USERNAME_CLAIM is in the key set, defaults `false` (fail-closed), flips with `/api/info`, and stays `false` when the server omits the field (old-node path). - All existing tests stay green; build + audit-coverage pass; no E2E coverage shift expected (claim was already hidden in DEV+PRD). * refactor(capabilities): drop FAUCET/USERNAMES MVP fields, USERNAME_CLAIM required Sync with the server-side change that drops `faucet` and `usernames` from `/api/info.capabilities`. The Capabilities bit-set now describes only *opt-in* features a self-hoster might switch off; MVP surface (mint/faucet endpoints, username resolve and display) is permanently part of every node build and is unconditional in the UI. Schema: - CapabilitiesSchema: remove `faucet` and `usernames`; promote `username_claim` from optional to required (sync deploy is the norm, no version-skew window to support). Store: - FAIL_CLOSED: matches the new shape (address_list, username_claim, lnurl), all false. useFeatures(): - drop `FAUCET` and `USERNAMES` from the merged object; keep `USERNAME_CLAIM` for the claim-form gate. Memo deps narrowed accordingly. WalletScreen: - showFaucet collapses to the mainnet-defence check (faucet button is testnet-only; the server always serves /api/mint). - Username display drops the `features.USERNAMES &&` guard. - Balance-polling effect drops the `USERNAMES` gate and the matching dep-array entry; the local username is pinned on the first tick that reports one. - Claim form + claim-error gates collapse to `USERNAME_CLAIM && !account.username`. SendPage: - Username resolve (`@zkcoins.app` suffix, `$` prefix, hex fast-path) is unconditional now that resolve is MVP — the `features.USERNAMES` gate and its dep-array entry are gone. Recipient input placeholder is the canonical `alice@zkcoins.app` example. Tests: - features/capabilities/AppShell/home/Onboarding-restore/send-pipeline /WalletScreen.polling/client all updated to the new shape. - WalletScreen polling tests reframe the username path as "first-only, always-on" instead of gated-by-FEATURES.USERNAMES. Audit: - coverage.mjs MVP_EXEMPT_TESTIDS header now documents both exemption grounds (build-time DCE + runtime capability always-false) so the `username-claim-btn` entry has a clear rationale. * chore(reviewer-round-2): address MINORs from cross-PR review Test-state resets: - home.test.tsx / AppShell.test.tsx / Onboarding-restore.test.tsx — the `Object.assign(FEATURES_STATE, …)` beforeEach blocks listed the retired USERNAMES/FAUCET keys and forgot USERNAME_CLAIM. Tests ran green only because the vi.hoisted() initial state was already correct; the reset itself drifted. Each block now mirrors the current six build-time flags plus USERNAME_CLAIM. src/app/page.tsx: - Stale comment "Server feature gates: faucet / usernames / address_list / lnurl" → "Opt-in server features (address_list, username_claim, lnurl)". src/app/send/page.tsx: - `useFeatures()` was kept only for `features.APPS_DIRECTORY`, a pure build-time flag. The capabilities-store subscription would re-render the page on every /api/info update for no reason. Switched to `import { FEATURES }` + `FEATURES.APPS_DIRECTORY`. E2E doc drift: - 07-send.spec.ts header: username resolve is MVP and unconditional now (was incorrectly "no FEATURES.USERNAMES"). - 06-balance.spec.ts header: faucet is no longer a build flag — mint is MVP, button gated purely on `networkName !== mainnet`; DEV runs Mutinynet so the button IS shown. - e2e/README.md: gating table + the §8.6 row line for `balance-zero-faucet-visible` updated to match the new logic.
…138) * ci: add staging → develop auto-release-pr workflow + doc the new flow Mirrors the existing develop → main auto-release-pr.yaml, one layer down. Triggers on push to staging, opens (or no-ops on existing) "Promote: staging -> develop" PR for the operator to merge once they want the accumulated feature work to land on DEV. CONTRIBUTING.md updated: - Branches table now lists staging as the integration buffer between feature/* and develop. - Workflow rule rewritten: open feature PRs against staging, not develop. develop is fed by the staging auto-PR; main by the develop auto-PR. Same pattern, one extra step. - CI/CD table extended with the new workflow row. Bootstrap note: this PR targets develop directly because the staging-side workflow doesn't exist yet — once merged + synced to staging, all subsequent feature work follows the staging → develop flow. * ci(staging): apply reviewer round-1 feedback CONTRIBUTING: - re-add the protection statement that round-1 dropped: develop + main are protected, direct pushes rejected. Was implicit before; reviewer flagged the absence as ambiguous re. hotfix flow. Workflow rename Release → Promote: - "Release" stays reserved for develop → main (production cut). - staging → develop is a "promote" (DEV deploy is the side-effect, not the purpose). Workflow name, job name, step name + PR body headline all aligned on "Promote". - body checklist item rewritten to "Merge to promote staging to develop (deploys to DEV)" — the merge target is develop; the deploy is a follow-on effect, not the action. * test(e2e): regenerate visual baselines * test(e2e): regenerate visual baselines --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
globalSetup deadlocks on CI at `page.reload({ waitUntil: 'networkidle' })`
since PR #102 — the boot path now fires a fire-and-forget `/api/info`
capabilities fetch on every page mount and the service worker
(public/sw.js) does stale-while-revalidate for every cached asset. On
the GitHub Azure runner those background requests can keep the
500 ms networkidle window from ever closing, hitting the 30 s timeout
in `_helpers/wallet.ts:47` before the page settles. All 9 open PRs
plus the develop→main release PR have been red on E2E since 2026-05-18
19:18 UTC because of this.
Switch the reload to `domcontentloaded`. The caller's next step is
always a testid-based locator assertion (with its own 15-30 s
auto-wait), which is the real readiness signal we want — the same
rationale already applied to `snap()` in `_helpers/screenshot.ts`.
Locally:
- 3× pass on the previously-failing 02-create-seed wallet-after-create
- 10/10 pass on 03-restore-seed.spec.ts
- 9/9 pass on 11-cross-spec-redirects + 12-a11y
…er (#118) Mirrors the matching section in zk-coins/server. The split is: - Wallet operations (seed, sign, BIP32 derive, balance, history) run entirely on-device — no backend involvement. - Send / Receive / Mint post the full private witness to the configured server for ZK proof generation, so that server sees every transaction in cleartext. On-chain privacy is unaffected — Plonky2 keeps the chain footprint opaque. The trust boundary is the server operator. Default backend is api.zkcoins.app (NEXT_PUBLIC_API_URL build-time env, see src/stores/network.ts). Privacy-conscious users can point the app at a self-hosted zk-coins/server instance via the same env var at build time. Three-row hosted-vs-self-hosted table mirrors the server-side README plus an explicit row that the wallet seed never leaves the device in either case.
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: 1 new commit(s)