Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
197 commits
Select commit Hold shift + click to select a range
16ce231
DES-21: Pagination Base UI idiom upgrades + optional totalItems (#26918)
jaymantri Apr 30, 2026
aefb119
[grid] add typed wrapper for Origin Button (#26770)
jaymantri Apr 30, 2026
1e24a82
DES-23: Add LoadMore infinite-scroll primitive + useLoadMore hook (#2…
jaymantri Apr 30, 2026
497e6f9
fix(origin): unblock site builds — LoadMoreTriggerProps render overri…
jaymantri Apr 30, 2026
62d30b8
CI update lock file for PR
May 1, 2026
6f9cae0
[grid] Example app to test wallet module (#26717)
carsonp6 May 1, 2026
6f0e85a
CI update lock file for PR
May 1, 2026
4d67f34
[origin] add scoped globals for mixed app routes (#26900)
coreymartin May 1, 2026
de5ffdb
feat(origin/BarChart): anchor non-stacked bars at value 0 when 0 is i…
jamesxu-lightspark May 1, 2026
23405ed
[site] render auth buttons with Origin (#26933)
coreymartin May 1, 2026
4d66177
[js] Restore tests to CI checks (#26962)
coreymartin May 2, 2026
87a690d
[origin] Deploy Storybook to dev.dev.sparkinfra.net (#26994)
coreymartin May 4, 2026
885ae3a
CI update lock file for PR
May 4, 2026
60d92b5
[origin] Add Storybook PR previews (#27001)
coreymartin May 4, 2026
af6bb21
[origin] Lower scoped reset specificity (#27028)
jaymantri May 5, 2026
64a04d8
Simplify Combobox: align with Base UI multi-select pattern (DES-24) (…
jaymantri May 6, 2026
e80a390
[vite] Handle stale dev proxy ALB sessions (#27087)
coreymartin May 6, 2026
f61fff1
Migrate ops DLQ to DataManagerTable (#27080)
bsiaotickchong May 6, 2026
90146eb
[origin] Expose Field root render prop (#27097)
jaymantri May 6, 2026
7a2625d
[origin] Simplify Combobox chip composition (#27141)
jaymantri May 7, 2026
d6887ed
[origin] Add Field label suffix spacing (#27140)
jaymantri May 7, 2026
7046649
[origin] Bound Select popup height (#27142)
jaymantri May 7, 2026
8cf11b0
[origin] Add ButtonLink for link semantics (#27144)
jaymantri May 7, 2026
a3f6b53
[origin] Make Tabs panel unopinionated (#27143)
jaymantri May 7, 2026
27d4aac
DES-22: Add `Pager` direction-based pagination primitive (#26921)
jaymantri May 7, 2026
766561b
[js] Increase npm dependency age gate (#27190)
coreymartin May 8, 2026
e355ae1
[site] surface USDT-Tron in the Grid dashboard payout flow (#27211)
jklein24 May 14, 2026
ba1130e
[site] Speed up local Playwright UI tests (#25379)
coreymartin May 19, 2026
a5a2c99
[origin] Add form composition boundary tests (#27119)
jaymantri May 20, 2026
b2b4f09
fix(treasury): fix symbol case, restructure columns, fix stablecoin f…
k15z May 21, 2026
8cdb5ab
[uma-nage] Add segmented navigation wrapper (#27106)
jaymantri May 22, 2026
9cd70ea
[ui] Use built package imports in private apps (#27024)
coreymartin May 22, 2026
1128b0f
Fix fail-open async UMA validation checks (#524)
SOME-1HING May 25, 2026
32792ca
[js] Update form-data resolution (#27827)
coreymartin May 26, 2026
5bc0a0d
CI update lock file for PR
May 26, 2026
dfc6a8c
[js] Update vite dependency (#27876)
coreymartin May 27, 2026
9c2a3f1
[origin] Update fast-uri dependency (#27874)
coreymartin May 27, 2026
ae2b584
[js] Update axios dependency (#27873)
coreymartin May 27, 2026
1508dc1
CI update lock file for PR
May 27, 2026
b17529c
[js] Update react-router-dom dependency (#27861)
coreymartin May 27, 2026
37493d8
CI update lock file for PR
May 27, 2026
729ded5
DEMO(grid): add internal demo app for hosted KYC/KYB link API (#27615)
jklein24 May 28, 2026
3ae133b
Fix js build by running yarn (#27939)
jklein24 May 28, 2026
795107e
CI update lock file for PR
May 28, 2026
097aee9
DEMO(grid): add embedded Sumsub WebSDK option to demo (#27726)
jklein24 May 28, 2026
d908f6c
Update docs link domains (#27917)
bsiaotickchong May 28, 2026
c78e1b2
[js] Upgrade to React 19 and Next.js 15 (#27901)
coreymartin May 29, 2026
4c18497
CI update lock file for PR
May 29, 2026
2b81c87
[js] Update nodemon dependency (#27856)
coreymartin May 30, 2026
ad4d94f
CI update lock file for PR
May 30, 2026
f680742
[js] Update minimatch dependency (#27849)
coreymartin May 30, 2026
1e16384
CI update lock file for PR
May 30, 2026
6c742e4
[js][gga] Update example app (#28004)
carsonp6 Jun 1, 2026
e784c0a
[js] Update js-cookie dependency (#27866)
coreymartin Jun 1, 2026
fc30cb0
[js] Update Vitest to v4 (#28092)
coreymartin Jun 1, 2026
2c7d6ae
CI update lock file for PR
Jun 1, 2026
5f4cff3
[ui] Build icons from a single entrypoint (#28172)
coreymartin Jun 3, 2026
45b334c
[docs] Replace remark-prism with rehype-prism-plus (#28163)
coreymartin Jun 3, 2026
a2ccd0e
CI update lock file for PR
Jun 3, 2026
581a2f8
Gatekeeper: keyboard row navigation + highlight for the results table…
akanter Jun 4, 2026
821c5e3
[grid] Add read-only Home foundation (#27949)
jaymantri Jun 4, 2026
a327801
[grid] add CNY mobile-wallet payout corridor (AliPay / WeChatPay) (#2…
mohamedwane Jun 4, 2026
1eabc3a
[js] Upgrade libphonenumber-js (#28416)
coreymartin Jun 8, 2026
2b82edb
CI update lock file for PR
Jun 8, 2026
74d4fc8
fix(origin): thin x-axis labels by measured width (#28120)
jamesxu-lightspark Jun 9, 2026
f7e42c2
[origin] Fix long-list dropdown scrolling (#28492)
jaymantri Jun 9, 2026
7ad22a7
[origin] Default combobox clear to active (#28544)
jaymantri Jun 11, 2026
ddf20c0
chore(js): remove unused static logo asset (#28518)
kphurley7 Jun 11, 2026
779ce90
DES-51: add Nage phone input foundation (#28445)
jaymantri Jun 11, 2026
4bd38aa
[site] Fix preview login redirects (#28555)
coreymartin Jun 11, 2026
909a749
[grid] Add Receive/Add Funds money-flow primitives (#27951)
jaymantri Jun 11, 2026
a3b7643
[js] gga example app: V3 secure OTP e2e flow (test harness) (#28154)
carsonp6 Jun 12, 2026
d256b2d
CI update lock file for PR
Jun 12, 2026
004dae2
[js] gga example app: real WebAuthn ceremony + OTP-session caching; e…
carsonp6 Jun 12, 2026
d22cd61
[js] gga example app: split main.ts into config/turnkey/webauthn/api-…
carsonp6 Jun 12, 2026
42dc5e3
[js] gga example app: session.ts + status chip; disable-with-tooltip …
carsonp6 Jun 12, 2026
1ff29c6
[js] gga example app: prune dead flows + stale PR-number comments (#2…
carsonp6 Jun 12, 2026
9b760c4
[js] gga example app: sandbox/production mode split driven by SANDBOX…
carsonp6 Jun 12, 2026
3eb08af
[js] gga example app: guided login/manage flows + Advanced (manual) t…
carsonp6 Jun 12, 2026
88d6ef4
Add shellcheck linting across the repo (#28620)
markatto Jun 12, 2026
2c02a0d
feat(gga): redesign example app as React + Origin (Platform/Customer …
carsonp6 Jun 12, 2026
8fcbeab
CI update lock file for PR
Jun 12, 2026
0c0c505
[js] Upgrade Turbo for worktree cache sharing (#28807)
coreymartin Jun 13, 2026
657cc5f
Enable global Yarn cache (#28798)
coreymartin Jun 13, 2026
d297d00
CI update lock file for PR
Jun 13, 2026
dabbef1
[origin] Fix sidebar navigation roles (#28838)
jaymantri Jun 15, 2026
c7c3755
feat(gga): customer transactions tab (real Grid history) (#28761)
carsonp6 Jun 16, 2026
f16158d
[gga][example] Remove md files (#28995)
carsonp6 Jun 17, 2026
97933dc
[grid] Normalize crypto network and token icons (#29044)
jaymantri Jun 18, 2026
1010f42
Add sorting to treasury flows table (#29232)
k15z Jun 23, 2026
0ff7315
[ops] populate DLQ task args/kwargs via a live 'current' read (#29488)
bsiaotickchong Jun 29, 2026
58790e8
[origin] Retarget Base UI React to 1.6 (#29500)
coreymartin Jun 29, 2026
2455f87
CI update lock file for PR
Jun 29, 2026
f663a11
feat(ops): Grid Billing — Reconciliation page fixes (#29699)
bsiaotickchong Jul 2, 2026
8a5b6a4
[origin] ChipFilter interactive values, icon-token alignment, Field l…
jaymantri Jul 6, 2026
7a1e76d
[site] Wire Vitest tests (#29821)
coreymartin Jul 6, 2026
5b5a407
CI update lock file for PR
Jul 6, 2026
ae13e57
[origin] Give CountrySelect's hidden input its own form identity (#29…
jaymantri Jul 6, 2026
94cb8cd
[site] Remove legacy Cypress UI test setup (#29888)
coreymartin Jul 7, 2026
882e9f7
[origin] Add OTPField component (#29813)
jaymantri Jul 7, 2026
0bdb86a
[gha] Enable GitHub-backed Turbo remote cache (#27018)
coreymartin Jul 7, 2026
3f0b58c
CI update lock file for PR
Jul 7, 2026
40ab90f
origin: add ring variant to Loader (#29996)
jaymantri Jul 8, 2026
b75ac8b
[origin] Add PhoneInput.LockedCountry static leading cap (#30094)
jaymantri Jul 9, 2026
35f62ef
[gha] Speed up public JS Copybara sync (#30096)
coreymartin Jul 9, 2026
9eb63ea
[gql] Generate private typenames per app (#30082)
coreymartin Jul 9, 2026
76923f9
[origin] add label slot to Item title row (#30176)
jaymantri Jul 10, 2026
d6a4b57
[gha] Partially fetch the Copybara origin (#30198)
coreymartin Jul 10, 2026
0ebb882
[origin] pass single props object to useRender in Pagination (#30182)
jaymantri Jul 13, 2026
00f7294
[origin] support render prop on Breadcrumb.Link (#30178)
jaymantri Jul 13, 2026
7ac5d2c
[core] Preserve custom error serializer receivers (#30291)
coreymartin Jul 14, 2026
70e447a
[gha] Reuse shared builds across UI previews (#30263)
coreymartin Jul 14, 2026
b15e1c3
feat(striga): local e2e harness for the Grid switch (#30015)
jklein24 Jul 15, 2026
a7d6022
CI update lock file for PR
Jul 15, 2026
7c214c9
[vite] Support Bolt frontends behind Zeus (#30419)
coreymartin Jul 15, 2026
d7e240e
[js] Add docs and scripts covering private app backend modes (#29734)
coreymartin Jul 15, 2026
f8ce752
Match space-after-shebang scripts in shellcheck filter (#30401)
markatto Jul 15, 2026
543531e
Share Turbo cache through S3 (#30351)
coreymartin Jul 16, 2026
89fc07e
Add BGN, CZK, HUF, NOK, PLN, RON, SEK, CHF to CurrencyUnit enum (#30481)
akanter Jul 16, 2026
cffb9e3
[js] Bump tar to 7.5.20 (#30906)
mhrheaume Jul 22, 2026
92c83c1
CI update lock file for PR
Jul 22, 2026
49448c5
[origin] Add reusable table primitives and provider-free bindings (#3…
jaymantri Jul 22, 2026
2151c8f
feat(ops): link spark transfer id fields in inspector to spark transf…
zhenlu Jul 22, 2026
4b8f2b7
feat(harness): SCA panels for the Striga grid test harness (#30638)
jklein24 Jul 23, 2026
e6eeec7
CI update lock file for PR
Jul 23, 2026
8287bb8
feat(striga-harness): configure the target environment from the UI (#…
jklein24 Jul 29, 2026
a6ba11f
[origin] Improve DataTable sizing and loading behavior (#31303)
jaymantri Jul 29, 2026
97f1c41
Close Add Filter menu after enum selection (#31327)
jaymantri Jul 29, 2026
dd7b63a
[js] Publish titles only in public sync (#31495)
coreymartin Jul 30, 2026
3823b80
[js] Preserve sync review metadata (#31503)
coreymartin Jul 30, 2026
cfb052a
[ui] Clear the InputSubtext fade-out timer on unmount (#31553)
bsiaotickchong Jul 31, 2026
c6cf9e3
[origin] Extend Command palette capabilities (#31001)
jaymantri Jul 31, 2026
1eb5685
[origin] Add noninteractive DataTable cell truncation (#31614)
jaymantri Jul 31, 2026
cb7e860
feat(origin): preserve FilterBar application order (#31635)
jaymantri Aug 3, 2026
1304ff9
fix(ui): strip invisible characters in shared text inputs (#31965)
wuvictor-95 Aug 5, 2026
2e798e9
[origin] Add compact size variant to Item (#31984)
jaymantri Aug 6, 2026
b7f19aa
fix(origin): make Checkbox, Radio, and Switch clickable inside a Draw…
wuvictor-95 Aug 10, 2026
ce00c12
feat(grid): example app adapts passkey/oauth login to the client-held…
carsonp6 Aug 11, 2026
b43ed74
fix(grid): example app sends the compressed session key on passkey/oa…
carsonp6 Aug 11, 2026
a9bf8cd
feat(grid): example app toggle for legacy vs modern login key (#32007)
carsonp6 Aug 11, 2026
8ce1867
feat(grid): example app one-click Sign in with Google (OIDC) (#32071)
carsonp6 Aug 11, 2026
80d8439
[origin] Add flexible toast layouts and stacking (#32389)
jaymantri Aug 12, 2026
f0d59ff
[origin] Add fixed DatePicker presets to FilterBar (#31617)
jaymantri Aug 13, 2026
8fdfedf
[origin] Add FilterBar date preset shortcuts (#31652)
jaymantri Aug 13, 2026
6e14c31
[ops] Fix inspector collection filters (#32535)
coreymartin Aug 13, 2026
d93bec7
[gga-demo] Update @turnkey/crypto (#32591)
carsonp6 Aug 13, 2026
3bd7681
CI update lock file for PR
Aug 13, 2026
3ce518c
Persist Ops Inspector table preferences (#32581)
coreymartin Aug 18, 2026
6364881
[origin] Add icon-only InputGroup buttons (#32706)
jaymantri Aug 18, 2026
a916923
[origin] Add responsive Alert trailing content (#32764)
jaymantri Aug 18, 2026
f2ce0b2
[origin] Keep long menus within available space (#33021)
jaymantri Aug 19, 2026
c1a30fa
Fix same-day date filter ranges (#33022)
jaymantri Aug 20, 2026
2020128
Fix DatePicker range endpoint calendar edits (#33138)
jaymantri Aug 21, 2026
9b67738
[origin] Expose FilterBar range transition context (#33168)
jaymantri Aug 21, 2026
bb7f321
[ops] Infer core service on entity pages (#33199)
coreymartin Aug 21, 2026
42d8fd4
Add ILS (Israeli New Shekel) to the CurrencyUnit enum (#33291)
whoisglover Aug 21, 2026
92b419e
[origin] Keep multi-select Combobox on the 36px control height (#33241)
patcapulong Aug 25, 2026
becc454
[origin] Quiet placeholders to text-tertiary across all inputs (#33245)
patcapulong Aug 25, 2026
b68c0f4
[origin] Render Field.LabelSuffix as a body-sm secondary aside (#33247)
patcapulong Aug 25, 2026
f7171a3
[origin] Add opt-in md size to Field.Label (#33255)
patcapulong Aug 25, 2026
5dac772
[origin] Regular-weight choice labels and field-aligned group inset (…
patcapulong Aug 25, 2026
7c0ea71
[origin] Default to text-wrap: pretty globally (#33258)
patcapulong Aug 25, 2026
2529d3d
[origin] Add Stepper component (#33262)
patcapulong Aug 25, 2026
6d7a817
feat(striga-test-harness): cover the full Grid REST surface across ta…
jklein24 Aug 25, 2026
04d4c40
[grid] Move billing into Settings (#31328)
jaymantri Aug 25, 2026
a4aa1e3
[origin] Add toast placement and inline links (#33330)
coreymartin Aug 25, 2026
cbb9d26
[origin] Adopt Suisse Intl VF with baked metrics and single-story a (…
patcapulong Aug 25, 2026
ced640b
[origin] Rename font fallback family to Suisse Intl Extended (#33617)
patcapulong Aug 26, 2026
3d0cf29
[origin] Fix Dialog viewport layout and stacking (#33505)
jaymantri Aug 31, 2026
130463d
[origin] Fix date-rollover failure in FilterBar date-picker test (#34…
patcapulong Sep 1, 2026
6f97cfc
[site] Structured geography for the go-live questionnaire (#33280)
patcapulong Sep 1, 2026
f768254
[site] Grid go-live: review step, submit gate, and KYB card track (#3…
patcapulong Sep 2, 2026
b515e92
[origin] Refine the dark theme token set and make component surfaces …
jaymantri Sep 2, 2026
d0e7bff
[js] Upgrade Next.js to 15.5.25 (#34478)
coreymartin Sep 7, 2026
35d9aac
CI update lock file for PR
Sep 7, 2026
61310fd
fix(grid): unwrap Striga's passkey approval envelope (#33929)
jklein24 Sep 7, 2026
f600397
[grid] Split the dashboard hosted-KYC-link gate out of LSP_INDIVIDUAL…
ch-brian Sep 9, 2026
57a9124
feat(grid): require endUserIpAddress on record-event and 2FA reset (#…
jklein24 Sep 10, 2026
979102c
[site] Expand hermetic UI coverage for financial and account flows (#…
coreymartin Sep 10, 2026
f807560
[site] Fix autofill on email login (#34820)
mhrheaume Sep 11, 2026
a92b498
DEMO(grid): add programmatic KYC API mode to grid-kyc-demo (#34844)
jklein24 Sep 11, 2026
cfe0c24
[ops] Keep the document theme consistent from startup (#34599)
coreymartin Sep 11, 2026
23d221d
feat: add TRY Thunes fields and account schemas (#35339)
Awinfredwa Sep 15, 2026
d6fbf55
grid: remove the exchange-rates-v2 aliases and drop the v2 suffix (#3…
shreyav Sep 17, 2026
4ef91db
feat(site): support Arbitrum everywhere Ethereum is a valid Grid netw…
jklein24 Sep 18, 2026
8af1f7b
fix(ui): use official Arbitrum brand mark for network icons (#35766)
jaymantri Sep 18, 2026
0b6713f
Remove v1/v2 API version references from docs and tests (#35713)
shreyav Sep 18, 2026
9ac208e
[js] Move SDK publishing to private release candidates (#35793)
coreymartin Sep 21, 2026
5d5bac7
CI update lock file for PR
Sep 21, 2026
4e4f1e7
DEMO(grid): load existing customers into grid-kyc-demo, fix proxy 403…
akanter Sep 22, 2026
f8bd53d
feat(grid): make bankAccountType required for external US account and…
Ethan-Minghao Sep 23, 2026
e86c77e
[js] Remove dead eslintrc files and the esw lint:watch task (#36008)
mariano-macri Sep 23, 2026
7c5fa62
[js] Drop dead stores ahead of ESLint 10's new recommended rules (#36…
mariano-macri Sep 23, 2026
736e456
[js] Upgrade to ESLint 10 (#36010)
mariano-macri Sep 23, 2026
3d93f0b
[js] Restore ESLint watch mode (#36102)
coreymartin Sep 24, 2026
7ea0526
CI update lock file for PR
Sep 24, 2026
9d215b4
[gha] Simplify JS SDK major release approval (#36184)
coreymartin Sep 24, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ test-config.yml
dist/
build/
lib/
# The GGA example app keeps decoupled source modules under src/lib/ (not a
# compiled-output dir), so it must not be swept up by the `lib/` rule above.
!apps/examples/grid-global-accounts-example-app/src/lib/

# Vim swap files
*.swp
Expand Down Expand Up @@ -126,3 +129,6 @@ stats.html

# Dev proxy cookies (contains ALB session tokens)
.dev-proxy-cookies

# Playwright MCP logs
.playwright-mcp/
2 changes: 1 addition & 1 deletion .mise.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
MISE_NODE_COREPACK = true

[tools]
node = "20.19"
node = "20.19.6"

[tasks.deps]
description = "Install all JS dependencies"
Expand Down
4 changes: 2 additions & 2 deletions .yarnrc.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
compressionLevel: mixed

enableGlobalCache: false
enableGlobalCache: true

nodeLinker: node-modules

npmMinimalAgeGate: 1440
npmMinimalAgeGate: 4320 # 3 days

npmPreapprovedPackages:
- "@lightsparkdev/*"
Expand Down
1 change: 0 additions & 1 deletion AGENTS.md

This file was deleted.

72 changes: 0 additions & 72 deletions CLAUDE.md

This file was deleted.

8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,11 @@ yarn start remote-signing-server
```

Please see the README files in the [examples directory](./apps/examples) for instructions on running the examples. Please note that some packages such as @lightsparkdev/ui are for building the examples only and not necessary for your implementation of our [published SDK packages](https://www.npmjs.com/search?q=%40lightsparkdev).

## Contributions and releases

After the migration in [RELEASING.md](RELEASING.md) is activated, target
contribution PRs at `develop` and include a Changeset for public package changes.
Contributions are imported into Webdev for review and testing, then exported to
`main`. Versioning happens in Webdev; public `main` supplies immutable release
candidates.
283 changes: 283 additions & 0 deletions RELEASING.md

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions apps/examples/grid-global-accounts-example-app/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Verification screenshots — captured locally, not tracked.
.screenshots/
12 changes: 12 additions & 0 deletions apps/examples/grid-global-accounts-example-app/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Grid Global Accounts</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
30 changes: 30 additions & 0 deletions apps/examples/grid-global-accounts-example-app/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"name": "@lightsparkdev/grid-global-accounts-example-app",
"private": true,
"version": "0.0.1",
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"start": "vite",
"preview": "vite preview",
"test": "vitest run"
},
"devDependencies": {
"@types/react": "^19.2.15",
"@types/react-dom": "^19.2.3",
"@vitejs/plugin-react": "^5.2.0",
"typescript": "^5.6.2",
"vite": "^8.0.14",
"vitest": "^4.1.7"
},
"dependencies": {
"@emotion/react": "^11.14.0",
"@emotion/styled": "^11.14.1",
"@lightsparkdev/origin": "*",
"@turnkey/api-key-stamper": "^0.6.5",
"@turnkey/crypto": "^2.11.0",
"@turnkey/encoding": "^0.6.0",
"react": "^19.2.6",
"react-dom": "^19.2.6"
}
}
19 changes: 19 additions & 0 deletions apps/examples/grid-global-accounts-example-app/src/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Shell } from "./components/Shell";
import { AppStateProvider, useAppState } from "./state/store";
import { CustomerView } from "./views/customer/CustomerView";
import { PlatformView } from "./views/platform/PlatformView";

export function App() {
return (
<AppStateProvider>
<Shell>
<Router />
</Shell>
</AppStateProvider>
);
}

function Router() {
const { persona } = useAppState();
return persona === "platform" ? <PlatformView /> : <CustomerView />;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { createHash } from "node:crypto";
import { afterEach, describe, expect, it } from "vitest";

import { oidcNonceForPublicKey } from "../google-identity";
import { generateClientKeyPair } from "../turnkey";
import { setActiveSessionAccount } from "../session";

// The backend's sandbox_oidc_nonce_for_public_key / Turnkey enclave rule:
// sha256(public_key.encode("utf-8")).hexdigest()
function backendNonce(publicKeyHex: string): string {
return createHash("sha256").update(publicKeyHex, "utf8").digest("hex");
}

afterEach(() => {
setActiveSessionAccount(null);
});

describe("oidcNonceForPublicKey", () => {
it("matches sha256-hex of the public-key hex string (backend formula)", async () => {
const pub = "02a1b2c3";
expect(await oidcNonceForPublicKey(pub)).toBe(backendNonce(pub));
});

it("binds to the COMPRESSED session key the oauth flow generates", async () => {
setActiveSessionAccount("InternalAccount:google");
const kp = generateClientKeyPair();
// 33-byte compressed P-256 point → 66 hex chars; the nonce must hash this
// exact key, not the uncompressed encoding.
expect(kp.publicKey.length).toBe(66);
expect(await oidcNonceForPublicKey(kp.publicKey)).toBe(
backendNonce(kp.publicKey),
);
expect(await oidcNonceForPublicKey(kp.publicKey)).not.toBe(
backendNonce(kp.publicKeyUncompressed),
);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { afterEach, describe, expect, it, vi } from "vitest";

import type { ClientKeyPair } from "../session";
import {
loginClientPublicKey,
persistLoginKeyEncoding,
readLoginKeyEncoding,
} from "../login-key-encoding";

const kp: ClientKeyPair = {
privateKey: "priv",
publicKey: "02compressed",
publicKeyUncompressed: "04uncompressed",
};

function stubStoredEncoding(value: string | null): void {
vi.stubGlobal("localStorage", {
getItem: () => value,
setItem: () => {},
removeItem: () => {},
});
}

afterEach(() => {
vi.unstubAllGlobals();
});

describe("login key encoding toggle", () => {
it("sends the compressed (modern) key by default when the toggle is unset", () => {
stubStoredEncoding(null);
expect(readLoginKeyEncoding()).toBe("modern");
expect(loginClientPublicKey(kp)).toBe(kp.publicKey);
});

it("sends the uncompressed (legacy) key when the toggle is set to legacy", () => {
stubStoredEncoding("legacy");
expect(readLoginKeyEncoding()).toBe("legacy");
expect(loginClientPublicKey(kp)).toBe(kp.publicKeyUncompressed);
});

it("treats any non-legacy stored value as modern", () => {
stubStoredEncoding("something-else");
expect(readLoginKeyEncoding()).toBe("modern");
expect(loginClientPublicKey(kp)).toBe(kp.publicKey);
});

it("falls back to modern when localStorage is unavailable", () => {
vi.stubGlobal("localStorage", {
getItem: () => {
throw new Error("localStorage unavailable");
},
});
expect(readLoginKeyEncoding()).toBe("modern");
expect(loginClientPublicKey(kp)).toBe(kp.publicKey);
});

it("persists the toggle choice so the next login (and a reload) keeps it", () => {
const store: Record<string, string> = {};
vi.stubGlobal("localStorage", {
getItem: (k: string) => store[k] ?? null,
setItem: (k: string, v: string) => {
store[k] = v;
},
removeItem: (k: string) => {
delete store[k];
},
});
persistLoginKeyEncoding("legacy");
expect(readLoginKeyEncoding()).toBe("legacy");
expect(loginClientPublicKey(kp)).toBe(kp.publicKeyUncompressed);
persistLoginKeyEncoding("modern");
expect(readLoginKeyEncoding()).toBe("modern");
expect(loginClientPublicKey(kp)).toBe(kp.publicKey);
});

it("swallows write failures when localStorage is unavailable", () => {
vi.stubGlobal("localStorage", {
setItem: () => {
throw new Error("localStorage unavailable");
},
});
expect(() => persistLoginKeyEncoding("legacy")).not.toThrow();
});
});
Loading
Loading