Skip to content

feat(cli): add cards and auth domains + signed-request header support#704

Closed
ls-bolt[bot] wants to merge 2 commits into
07-18-grid-cli-contact-verificationfrom
07-19-grid-cli-cards-auth-plan
Closed

feat(cli): add cards and auth domains + signed-request header support#704
ls-bolt[bot] wants to merge 2 commits into
07-18-grid-cli-contact-verificationfrom
07-19-grid-cli-cards-auth-plan

Conversation

@ls-bolt

@ls-bolt ls-bolt Bot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

This PR has been claimed. The active PR is now #711.

Summary

Adds the cards and auth domains to the Grid CLI, plus signed-request header support so the signed-retry flows are usable. Stacked on #702/#703.

cards (grid cards …)

list, get, create, update (freeze/unfreeze/replace-sources/close), reveal (prints the short-lived panEmbedUrl). No delete — closing is update --state CLOSED.

auth (grid auth …)

  • credentialslist, create, challenge (OTP resend / passkey re-challenge), verify, revoke
  • delegated-keyslist, get, create (with repeatable --spending-limit CUR:amount), revoke
  • sessionslist, refresh, revoke

Signed-request support

Many auth operations and cards update use Grid's signed-retry flow (first call returns 202 + payloadToSign; the retry carries a Grid-Wallet-Signature + Request-Id). This PR:

  • extends GridClient so get/post/patch/delete accept optional headers;
  • exposes --wallet-signature / --request-id on the signed operations.

The CLI forwards a caller-supplied stamp — it does not compute the Turnkey/HPKE signature itself (compute it with scripts/embedded-wallet-sign.js or your own tooling). Passkey create/verify likewise accept the WebAuthn --attestation / --assertion as JSON you produce client-side.

Note on structure

The plan proposed cards and auth as two separate stacked PRs. They share the new client.ts header plumbing (and auth depends on it) and both touch index.ts, so I've kept them in one PR to avoid a fragile cross-branch split. Say the word if you'd prefer them separated.

Test plan

  • cd cli && npm run build — clean strict compile.
  • npm test — 53 boundary tests (19 new for cards + auth), asserting each command's method/path/query/body/headers.

Known follow-up

  • Sensitive values (OIDC tokens, wallet signatures) are passed as flags today. Supporting file/stdin/env input for secrets is a sensible cross-cutting follow-up (also applies to the existing configure --client-secret) — not done here.

@vercel

vercel Bot commented Jul 19, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

2 Skipped Deployments
Project Deployment Actions Updated (UTC)
grid-flow-builder Ignored Ignored Preview Jul 19, 2026 1:36am
grid-wallet-demo Ignored Ignored Preview Jul 19, 2026 1:36am

Request Review

akanter commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

@ls-bolt ls-bolt Bot changed the title plan: add cards and auth domains to the Grid CLI feat(cli): add cards and auth domains + signed-request header support Jul 19, 2026
@ls-bolt

ls-bolt Bot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor Author

@greptileai review

@greptile-apps

greptile-apps Bot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds cards and auth CLI domains (credentials, delegated-keys, sessions sub-commands) plus signed-request header forwarding so the signed-retry flows are usable. The GridClient HTTP methods now accept an optional headers map, which is threaded through a new signed.ts helper and surfaced via --wallet-signature / --request-id flags.

  • cards: list, get, create, update (freeze/unfreeze/replace-sources/close), and reveal with proper NaN guard on --limit and conflict validation for CLOSED + --funding-sources.
  • auth: Full credentials, delegated-keys, and sessions hierarchies, with robust spending-limit parsing (regex-validated CURRENCY:amount format using InvalidArgumentError), JSON passkey payloads, and confirmation prompts on destructive operations.
  • Test helper cleanup: runCli now saves and restores GRID_API_TOKEN_ID, GRID_API_CLIENT_SECRET, and process.exitCode, preventing inter-test contamination.

Confidence Score: 5/5

Safe to merge — the new commands are well-isolated, all destructive operations have confirmation prompts, and the two previously flagged issues are both properly addressed in this revision.

The signed-retry header plumbing is clean, the spending-limit parser uses a strict regex with InvalidArgumentError, and the test helper isolation fix prevents exitCode bleed between tests. The one remaining wrinkle — cards update checking the raw string instead of the parsed result for its empty-guard — would only manifest with intentionally degenerate whitespace input and the API would reject the empty body anyway.

cli/src/commands/cards.ts — the update guard uses the raw flag string rather than the parseList result.

Important Files Changed

Filename Overview
cli/src/commands/cards.ts New cards command; --limit NaN guard is present; cards update guard uses raw options.fundingSources (undefined check) rather than the parsed result, allowing whitespace-only input to bypass validation and send an empty PATCH body.
cli/src/commands/auth.ts New auth command; spending-limit parsing uses regex + InvalidArgumentError (previous NaN→null issue addressed); JSON passkey fields parsed with error propagation; confirmation prompts on all destructive operations.
cli/src/client.ts Adds optional headers parameter to get/post/patch/delete; header merging correctly skips undefined values and happens after auth/content-type headers are set.
cli/src/signed.ts New helper adds --wallet-signature / --request-id options and builds the header map; undefined values are filtered by the client layer.
cli/test/helpers.ts Saves/restores env vars and process.exitCode in finally block, preventing test-to-test contamination.
cli/test/auth.test.ts New tests covering all auth sub-commands including spending-limit rejection, signed-retry header forwarding, and empty-filter guard for delegated-keys list.
cli/test/cards.test.ts Tests cover list, create, update (freeze, signed headers, no-arg rejection, CLOSED+funding-sources rejection), and reveal.
cli/src/index.ts Registers new cards and auth commands alongside existing ones; straightforward addition.
cli/README.md Documents cards and auth commands with examples; includes multi-leg signed-retry note and panEmbedUrl caution.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant User
    participant CLI
    participant GridClient
    participant GridAPI

    Note over User,GridAPI: First leg — unsigned call
    User->>CLI: grid cards update Card:1 --state CLOSED
    CLI->>GridClient: patch("/cards/Card:1", body)
    GridClient->>GridAPI: PATCH /cards/Card:1
    GridAPI-->>GridClient: "202 { payloadToSign, requestId }"
    GridClient-->>CLI: ApiResponse(202)
    CLI-->>User: prints challenge JSON

    Note over User,GridAPI: Out-of-band signing
    User->>User: sign payloadToSign via embedded-wallet-sign.js

    Note over User,GridAPI: Second leg — signed retry
    User->>CLI: grid cards update Card:1 --state CLOSED --wallet-signature stamp --request-id req-1
    CLI->>GridClient: patch("/cards/Card:1", body, headers)
    GridClient->>GridAPI: PATCH /cards/Card:1 + Grid-Wallet-Signature + Request-Id
    GridAPI-->>GridClient: "200 { card }"
    GridClient-->>CLI: ApiResponse(200)
    CLI-->>User: prints updated card JSON
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant User
    participant CLI
    participant GridClient
    participant GridAPI

    Note over User,GridAPI: First leg — unsigned call
    User->>CLI: grid cards update Card:1 --state CLOSED
    CLI->>GridClient: patch("/cards/Card:1", body)
    GridClient->>GridAPI: PATCH /cards/Card:1
    GridAPI-->>GridClient: "202 { payloadToSign, requestId }"
    GridClient-->>CLI: ApiResponse(202)
    CLI-->>User: prints challenge JSON

    Note over User,GridAPI: Out-of-band signing
    User->>User: sign payloadToSign via embedded-wallet-sign.js

    Note over User,GridAPI: Second leg — signed retry
    User->>CLI: grid cards update Card:1 --state CLOSED --wallet-signature stamp --request-id req-1
    CLI->>GridClient: patch("/cards/Card:1", body, headers)
    GridClient->>GridAPI: PATCH /cards/Card:1 + Grid-Wallet-Signature + Request-Id
    GridAPI-->>GridClient: "200 { card }"
    GridClient-->>CLI: ApiResponse(200)
    CLI-->>User: prints updated card JSON
Loading

Reviews (3): Last reviewed commit: "feat(cli): add cards and auth domains + ..." | Re-trigger Greptile

Comment thread cli/src/commands/auth.ts
Comment thread cli/src/commands/cards.ts Outdated
@ls-bolt
ls-bolt Bot force-pushed the 07-19-grid-cli-cards-auth-plan branch from 848b62b to fc569a6 Compare July 19, 2026 01:01
@ls-bolt
ls-bolt Bot force-pushed the 07-18-grid-cli-contact-verification branch from d8e8758 to 102281f Compare July 19, 2026 01:01
@ls-bolt

ls-bolt Bot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor Author

Revision — addressed Greptile + Faraday review

  • --spending-limit parsing (Greptile P1 + Faraday): collectSpendingLimit now validates the CUR:amount format (uppercase code + positive safe-integer amount) and throws InvalidArgumentError on malformed/decimal/oversized input instead of silently sending null.
  • cards list --limit (Greptile): added an isNaN guard.
  • cards update close guard (Faraday): now checks options.fundingSources !== undefined so --state CLOSED --funding-sources ',' is rejected rather than slipping through.
  • Test coverage (Faraday): added a test for auth sessions revoke (signed DELETE + Grid-Wallet-Signature/Request-Id headers) and a malformed-spending-limit rejection test.
  • Docs (Faraday): documented that auth delegated-keys create needs two successive signed retries (a single signed retry stops at the second 202 and leaves the key PENDING).

npm run build + npm test green (58 tests).

@ls-bolt

ls-bolt Bot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor Author

@greptileai review

@ls-bolt

ls-bolt Bot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor Author

@greptileai review

jklein24 added 2 commits July 19, 2026 01:36
New cards commands (list/get/create/update/reveal) and auth commands
(credentials, delegated-keys, sessions). Extend GridClient so get/post/patch/
delete accept optional headers, and expose --wallet-signature/--request-id on
the signed-retry operations (the CLI forwards a caller-supplied Turnkey stamp;
it does not compute one). vitest boundary tests cover both domains.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants