Skip to content

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

Open
jklein24 wants to merge 2 commits into
graphite-base/711from
07-19-grid-cli-cards-auth-plan
Open

feat(cli): add cards and auth domains + signed-request header support#711
jklein24 wants to merge 2 commits into
graphite-base/711from
07-19-grid-cli-cards-auth-plan

Conversation

@jklein24

Copy link
Copy Markdown
Contributor

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.

Original PR: #704

@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 20, 2026 10:16pm
grid-wallet-demo Ignored Ignored Preview Jul 20, 2026 10:16pm

Request Review

@ls-bolt

ls-bolt Bot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

@greptileai review

@greptile-apps

greptile-apps Bot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

⚡️ \\m/ SHRED THE AUTH DOMAIN! \\m/ ⚡️
    |||||||||||||||||||||||
    || G R I D  C L I   ||
    || CARDS & AUTH      ||
    || SIGNED & SEALED   ||
    |||||||||||||||||||||||
    |||  \\m/       \\m/  |||

"Sign the payload or face the 202 — there is no retry without the stamp."

Adds two new CLI domains (cards and auth) to the Grid CLI, plus signed-retry header plumbing in GridClient. The cards domain covers list/get/create/update/reveal; auth covers credentials, delegated-keys, and sessions — all wired to Grid's signed-retry challenge flow via a new signed.ts utility.

  • cli/src/signed.ts introduces addSignedOptions/signedHeaders/validateSignedOptions as a reusable both-or-neither guard for the Grid-Wallet-Signature + Request-Id pair; client.ts gains an optional headers parameter on all four HTTP methods so those values can be forwarded verbatim.
  • Previous review findings (empty funding-source guards, partial signed-header rejection, invalid --state values) are addressed; 19 new boundary tests cover the new commands.

Confidence Score: 5/5

Safe to merge — the new commands are well-guarded and the previous review findings have all been addressed.

The header-plumbing change in client.ts is minimal and correct. The signed-retry flow is properly gated by the both-or-neither validator. The cards and auth commands carry the same defensive guards (empty-input checks, confirmation prompts, state enum validation) seen across the rest of the CLI codebase. No logic errors or data-integrity issues were found.

No files require special attention. The one note on cli/src/commands/auth.ts is a minor consistency gap in client-side type validation.

Important Files Changed

Filename Overview
cli/src/client.ts Adds an optional headers map to request/get/post/patch/delete; implementation is correct — custom headers are merged after Content-Type is set, undefined values are filtered, and the shared headers reference keeps fetchOptions in sync.
cli/src/signed.ts New utility module; the both-or-neither validation via Boolean(x) !== Boolean(y) is correct for all non-empty-string inputs, and undefined values are safely skipped in the client.
cli/src/commands/cards.ts New cards domain; state enum validation, empty-funding-source guard, and CLOSED+funding-sources mutual exclusion are all present. No issues found.
cli/src/commands/auth.ts New auth domain; --type on credentials create/verify accepts any string without client-side validation, unlike the already-validated --state on cards update. Everything else looks correct.
cli/test/auth.test.ts Good boundary test coverage for all new auth subcommands; tests check method, path, query, body, and headers.
cli/test/cards.test.ts Solid tests for the happy path and all previous-review edge cases (invalid state, empty funding sources, partial signed headers, CLOSED+funding-sources).
cli/src/index.ts Registers the two new command modules; mechanical change, no issues.
cli/README.md Documentation for cards and auth domains is accurate; the two-leg delegated-keys warning is correctly noted.

Sequence Diagram

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

    Note over User,GridAPI: Unsigned first leg (e.g. cards update, sessions refresh)
    User->>CLI: grid cards update Card:1 --state FROZEN
    CLI->>CLI: validateSignedOptions() → ok (neither flag)
    CLI->>GridClient: patch("/cards/Card:1", body)
    GridClient->>GridAPI: PATCH /cards/Card:1
    GridAPI-->>GridClient: "202 { payloadToSign, requestId }"
    GridClient-->>CLI: "{ success: true, data: { payloadToSign, requestId } }"
    CLI-->>User: prints payloadToSign + requestId

    Note over User,GridAPI: User signs payload externally (Turnkey/HPKE)
    User->>User: embedded-wallet-sign.js → stamp

    Note over User,GridAPI: Signed retry leg
    User->>CLI: grid cards update Card:1 --state FROZEN --wallet-signature stamp --request-id rid
    CLI->>CLI: validateSignedOptions() → ok (both flags)
    CLI->>GridClient: patch("/cards/Card:1", body, headers)
    GridClient->>GridAPI: PATCH /cards/Card:1 + Grid-Wallet-Signature + Request-Id
    GridAPI-->>GridClient: "200 { updated card }"
    GridClient-->>CLI: "{ success: true, data: Card }"
    CLI-->>User: prints updated card
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: Unsigned first leg (e.g. cards update, sessions refresh)
    User->>CLI: grid cards update Card:1 --state FROZEN
    CLI->>CLI: validateSignedOptions() → ok (neither flag)
    CLI->>GridClient: patch("/cards/Card:1", body)
    GridClient->>GridAPI: PATCH /cards/Card:1
    GridAPI-->>GridClient: "202 { payloadToSign, requestId }"
    GridClient-->>CLI: "{ success: true, data: { payloadToSign, requestId } }"
    CLI-->>User: prints payloadToSign + requestId

    Note over User,GridAPI: User signs payload externally (Turnkey/HPKE)
    User->>User: embedded-wallet-sign.js → stamp

    Note over User,GridAPI: Signed retry leg
    User->>CLI: grid cards update Card:1 --state FROZEN --wallet-signature stamp --request-id rid
    CLI->>CLI: validateSignedOptions() → ok (both flags)
    CLI->>GridClient: patch("/cards/Card:1", body, headers)
    GridClient->>GridAPI: PATCH /cards/Card:1 + Grid-Wallet-Signature + Request-Id
    GridAPI-->>GridClient: "200 { updated card }"
    GridClient-->>CLI: "{ success: true, data: Card }"
    CLI-->>User: prints updated card
Loading

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

Comment thread cli/src/commands/cards.ts
Comment thread cli/src/signed.ts
Comment thread cli/src/commands/cards.ts
@ls-bolt
ls-bolt Bot force-pushed the 07-18-grid-cli-contact-verification branch from 876fe21 to daec001 Compare July 19, 2026 18:46
@ls-bolt
ls-bolt Bot force-pushed the 07-19-grid-cli-cards-auth-plan branch from b0aab72 to ff7cc64 Compare July 19, 2026 18:46
@ls-bolt

ls-bolt Bot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

@greptileai review

@jklein24
jklein24 force-pushed the 07-18-grid-cli-contact-verification branch from daec001 to 7deef2d Compare July 20, 2026 22:15
jklein24 added 2 commits July 20, 2026 22:16
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.
@jklein24
jklein24 force-pushed the 07-18-grid-cli-contact-verification branch from 7deef2d to 94287e3 Compare July 20, 2026 22:16
@jklein24
jklein24 force-pushed the 07-19-grid-cli-cards-auth-plan branch from ff7cc64 to 893e326 Compare July 20, 2026 22:16
@jklein24
jklein24 changed the base branch from 07-18-grid-cli-contact-verification to graphite-base/711 July 21, 2026 06:01
@ls-bolt

ls-bolt Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

📌 Bolt Status

2026-07-21 06:01:50 UTC — ⚡ Agent locked-bulwark-5(#5) started


Feedback

@jklein24
jklein24 marked this pull request as ready for review July 21, 2026 06:02
@jklein24
jklein24 requested a review from shreyav July 21, 2026 23:50
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