Skip to content

fix: prepare for Bridge KYC Level 2 upgrades; proxy-addr 2.0.8 - #517

Merged
islandbitcoin merged 4 commits into
mainfrom
fix/upgrade-request-null-address
Oct 6, 2026
Merged

islandbitcoin merged 4 commits into
mainfrom
fix/upgrade-request-null-address

Conversation

@islandbitcoin

@islandbitcoin islandbitcoin commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Prepares flash for frappe-flash-admin's Bridge KYC → Level 2 auto-upgrade (lnflash/frappe-flash-admin#80). That job files Level 2 Account Upgrade Requests with no address and leaves the account with no bank account. It also fixes the Audit check that was failing on every PR.

1. Resolve an upgrade request that has no address. Address has non-null title/line1/city/state/country. The app's LatestAccountUpgradeRequest errored with Cannot return null for non-nullable field Address.city. Those fields now resolve to "". The nullable fields are untouched and a submitted address comes back unchanged. No schema change.

2. Require a complete address on customer-submitted requests. #80 drops reqd from the ERP request's address fields, because frappe enforces it on every save. ERPNext had been the only thing rejecting "" on a customer's request. The model now refuses a blank title, line1, city, state or country.

3. Level 2 no longer implies a bank account on file. deriveCapabilitiesForAccount ORed level >= 2 into bankPayout, so every L2 reported bank payout. That made the app hub show "Bank cash-out ✓ On" with no bank, and let a Business (L3) capability request skip its bank check.

  • Only L3 now implies bankPayout from the stored level. When ERPNext answers, its bank accounts decide.
  • The stored level still stands in when ERPNext can't answer (no erpParty, or a failed lookup), so legacy behaviour is unchanged.
  • A BANK_PAYOUT capability request from an L2 account now gets "add a bank account instead". The app routes those accounts to Bank accounts (fix(upgrade): handle Level 2 accounts upgraded on Bridge KYC flash-mobile#757).

4. proxy-addr 2.0.8, which fixes the Audit job. yarn audit --level critical was failing on every flash PR since 2026-10-05: GHSA-jqcg-44mw-7w3h / CVE-2026-90711, "IP spoofing via IPv4-mapped IPv6 trust subnet". All three paths go through express's proxy-addr@~2.0.7, so the lockfile entry moves to 2.0.8 within that range, with no package.json change.

  • Same dependencies as 2.0.7.
  • The tarball's sha1/sha512 match the registry, and it carries SLSA provenance.
  • Its changelog lists only this fix.
  • Flash trusts proxies by hop count ("trust proxy", 1), not by subnet, so no behaviour changes.
  • Locally: critical findings go from 3 to 0, the gate passes, and yarn install --frozen-lockfile accepts the lockfile.

Tests

  • account-upgrade-request-address.spec.ts runs the app's LatestAccountUpgradeRequest document verbatim against the real payload type. It fails without fix 1.
  • AccountUpgradeRequest.spec.ts covers the incomplete-address refusal.
  • Capability specs:
    • L2 without a bank account → no bankPayout, headline still VERIFIED;
    • no erpParty or a failed lookup → stored level stands in;
    • BANK_PAYOUT at L2 → clear error;
    • a Business request without a bank on file must include one.
  • Mutation-checked: reverting each change turns its spec red.
  • Full unit suite: 278 suites, 3,502 passed (3 skipped).
  • typos, prettier 3.6.2 (the CI pin) and eslint are clean.

Deploy order

Ship this before #80 is switched on. On its own, fixes 1–2 change nothing for existing requests. Fix 3 changes only what an L2 account with an ERP party but no bank account sees; Bridge upgrades are what create those.

🤖 Generated with Claude Code

The Bridge KYC auto-upgrade in frappe-flash-admin files Level 2 Account
Upgrade Requests with no address (Bridge verified the identity; no address
is collected). Address's title/line1/city/state/country are non-null, so a
null in any of them nulls the whole request and the app's
LatestAccountUpgradeRequest query comes back with "Cannot return null for
non-nullable field Address.city".

The address field now resolves those to "" and leaves the nullable fields
alone. A submitted address is returned unchanged. The spec runs the app's
query verbatim against the real payload type.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
frappe-flash-admin is dropping reqd from the Account Upgrade Request address
block (it stays required for Level 3 in the desk form only), because frappe
enforces reqd on every save and Bridge KYC auto-upgrades file Level 2
requests with no address. ERPNext was the only thing rejecting an empty
address on a customer's request: AddressInput's fields are non-null, but ""
passes. The model now refuses a request whose title, line1, city, state or
country is blank, so customer requests keep the guarantee they had.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@islandbitcoin islandbitcoin changed the title fix(graphql): resolve an upgrade request that has no address fix(accounts): handle upgrade requests with no address Oct 6, 2026
deriveCapabilitiesForAccount ORed `level >= 2` into bankPayout
unconditionally, so every Level 2 account reported bank payout. That held
while L2 was only reachable by submitting a bank account. Bridge KYC
upgrades (frappe-flash-admin#80) reach L2 with none, and the result was:
- the app hub showing "Bank cash-out ✓ On" with no bank account;
- a Business (L3) capability request skipping its bank-account check.

- bankPayout is implied by the stored level only at L3 (a bank account is
  part of the L3 requirements). When ERPNext answers, its bank accounts
  decide for L2.
- The stored level still stands in when ERPNext can't answer: no ERP party
  (pre-ERPNext legacy accounts) or a failed lookup. Legacy behaviour there
  is unchanged.
- A BANK_PAYOUT capability request from an account already at L2 gets a
  clear "add a bank account instead", not the validator's "already at
  requested level". bankAccountAdd is the path for those accounts; the app
  routes its hub row there (flash-mobile).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Audit job (yarn audit --level critical) fails on every PR since the
advisory was published 2026-10-05: proxy-addr >=1.1.0 <2.0.8, "IP spoofing
via IPv4-mapped IPv6 trust subnet" (CVE-2026-90711). There are three paths,
all through express's proxy-addr@~2.0.7, so the lockfile entry moves to
2.0.8 within the existing range. No package.json change.

- 2.0.8 has the same dependencies as 2.0.7 (forwarded 0.2.0, ipaddr.js
  1.9.1). The tarball's sha1/sha512 match the registry, it carries SLSA
  provenance, and its HISTORY lists only this fix.
- Flash's Express apps trust proxies by hop count ("trust proxy", 1), not
  by subnet, so this changes no behaviour here.
- yarn audit --level critical: 3 critical -> 0. The job's gate (exit >= 16)
  now passes. yarn install --frozen-lockfile accepts the lockfile.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@islandbitcoin islandbitcoin changed the title fix(accounts): handle upgrade requests with no address fix: prepare for Bridge KYC Level 2 upgrades; proxy-addr 2.0.8 Oct 6, 2026
@islandbitcoin
islandbitcoin merged commit 43f0c61 into main Oct 6, 2026
15 checks passed
islandbitcoin added a commit to lnflash/flash-mobile that referenced this pull request Oct 6, 2026
* fix(upgrade): handle Level 2 accounts upgraded on Bridge KYC

frappe-flash-admin#80 upgrades Bridge-KYC-approved accounts to Level 2 by
filing and approving an upgrade request the customer never filled in: no
address, no bank account. Three app fixes for those accounts:

- Bank cash-out row: for an account already at Level 2 it opens Bank
  accounts. With lnflash/flash#517 an L2 with no bank account reports
  bankPayout false, and the upgrade form would end in "already at requested
  level". The older-backend fallback stops implying bankPayout at L2 too.
- Loading the latest request into the form keeps only values the request
  has. The slice reducers spread their payload, so the request's empty
  country ("") wiped the form's "Jamaica" default, and Next on the Business
  form stayed disabled with no message.
- An APPROVED request only updates the status card. Loading it into the
  form overwrote a flow the customer was part-way through (request type,
  personal, business and bank details) whenever an automatic upgrade
  landed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test(upgrade): Level 2 fallback no longer implies bankPayout

useAccountStatus's older-backend fallback goes through capabilitiesFromLevel,
which stopped implying bankPayout at Level 2 in the previous commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Dread <dread@example.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants