メインコンテンツまでスキップ

pulse > context — ZSC CLI commands

The Pulse terminal in the workbench exposes the ZSC vault as a flat set of subcommands under context. Every command hits an admin-gated /api/zsc/* route (using the same admin cookie the session uses for everything else), renders the result as a card, and writes a row to the entangled state so the operation appears in the explorer.

CLI source: shared/pulse/src/cli/commands.ts. API surface: /api/zsc/*.

Subcommand index

CommandAPI routeNotes
context listGET /api/zsc/listRender every secret as a card with name, owner, last-read, read-count.
context info <name>GET /api/zsc/info/:nameDrill into one secret.
context set <name> <value...>POST /api/zsc/setCreate or replace. Value captured from raw line — multi-word values supported.
context rotate <name>POST /api/zsc/rotate/:nameRe-encrypt with fresh IV.
context grant <name> <zid>POST /api/zsc/grant/:nameAdd ZID to permissions.
context revoke <name> <zid>POST /api/zsc/revoke/:nameRemove ZID from permissions.
context audit <name> [--limit N] [--verify]GET /api/zsc/audit/:nameRecent chain rows; --verify re-derives every proof.
context delete <name> (alias: context rm <name>)DELETE /api/zsc/:nameIrreversible. Prompts for confirmation.

Examples

Adding the Stripe live key

pulse> context set STRIPE_SECRET_KEY sk_live_51ABC...XYZ

✓ Set
name STRIPE_SECRET_KEY
encrypted_at 2026-05-17T13:42:11Z
audit_row 8a1f2c… (proof verified)

The CLI never echoes the plaintext back — only the metadata. The plaintext is captured from ctx.raw.indexOf(name) so spaces or quotes in the value pass through verbatim.

Listing the vault

pulse> context list

OPENAI_API_KEY owner=ZEQ-SYS reads=184 last=2289605442
STRIPE_SECRET_KEY owner=ZEQ-FOUNDATION reads=47 last=2289605501
SENDGRID_API_KEY owner=ZEQ-SYS reads=12 last=2289602100

3 secrets · all rotated within 18.6 h target

Granting a ZID

pulse> context grant STRIPE_SECRET_KEY ZEQ07111111111

✓ Granted
name STRIPE_SECRET_KEY
zid ZEQ07111111111
permissions [ZEQ07111111111]
audit_row 61b34d… (purpose=granted)

Inspecting the entangled state

pulse> context audit STRIPE_SECRET_KEY --limit 5

[2289605501] secret_rotated ZEQ-SYS cd91f4… auto_rotated
[2289605442] secret_read ZEQ-FOUNDATION f4ce81… read
[2289605300] secret_read ZEQ-FOUNDATION 9a2c11… read
[2289500001] secret_set ZEQ-FOUNDATION 8a1f2c… created
[2289499900] secret_set ZEQ-FOUNDATION c3df45… granted

5 rows · chain head = cd91f4… · prev_hash linkage OK

Add --verify to re-derive every proof_digest and confirm linkage byte-for-byte:

pulse> context audit STRIPE_SECRET_KEY --verify

✓ 5/5 proofs match
✓ 5/5 prev_hash links chain correctly
✓ Chain head verified

Probing permissions

pulse> context probe STRIPE_SECRET_KEY ZEQ07222222222

✗ Denied
reason denied
hint ZID not in bound_zid (ZEQ-FOUNDATION) or permissions []
Grant with: context grant STRIPE_SECRET_KEY ZEQ07222222222

Rotating manually

pulse> context rotate STRIPE_SECRET_KEY

✓ Rotated
name STRIPE_SECRET_KEY
iv_before 446bc1e2... (8 bytes shown)
iv_after 93491d79... (8 bytes shown)
audit_row cd91f4… (purpose=manual_rotated)

Deleting (irreversible)

pulse> context delete LEGACY_API_KEY

! Confirm: delete LEGACY_API_KEY? This is irreversible. [y/N]
> y

✓ Deleted
name LEGACY_API_KEY
audit_chain preserved (12 rows survive)
vault_row dropped

The audit entangled state survives — every prior secret_read, secret_set, secret_rotated, secret_denied row remains as the forensic record that the secret existed.

How context set captures multi-word values

A vault value like sk_live_xxx is one token, but configuration strings with spaces happen — connection URIs, JSON blobs, BASIC-auth headers. The CLI captures from ctx.raw.indexOf(name) so:

pulse> context set DATABASE_URL postgres://user:pass with space@host/db

stores the full string verbatim. The shell never sees this — Pulse's own CLI parser handles it before the value would leak to a process arg list.

Companion surfaces

  • Admin UI: /portal/secrets/ — same 8 operations as a clickable surface (4-stat dashboard, table, drawer, modal)
  • HTTP API: /api/zsc/* — same operations as raw HTTP for scripted ops

Auth

Same authentication path as the rest of the workbench Pulse: the admin cookie issued at /admin/ sign-in. There's no separate "context" auth — if you can open the Pulse panel in the workbench, you can run context commands.

For operators who want narrower scope, write a Pulse-side macro that calls context probe before context set — the probe is safe to expose to less-privileged scripts because it never returns plaintext.