@tokamak-private-dapps/private-state-cli 1.2.1 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,58 @@
1
1
  # Changelog
2
2
 
3
+ ## Unreleased
4
+
5
+ ## 2.1.0 - 2026-05-14
6
+
7
+ - Required current epoch-aware wallet workspaces for wallet commands and backup imports. Local
8
+ wallet metadata must include the wallet index and epoch metadata; users with older local
9
+ workspaces should rebuild them with `wallet recover-workspace`.
10
+ - Required current epoch-aware evidence bundle note paths in the investigator and removed the
11
+ special-case legacy evidence layout branch.
12
+ - Consolidated the static evidence investigator into the CLI package under `cli/investigator/`
13
+ and removed the duplicate top-level investigator copy.
14
+ - Simplified wallet command argument validation by removing unused schema fallback wrappers.
15
+
16
+ ## 2.0.0 - 2026-05-13
17
+
18
+ - Split wallet export/import into `wallet export backup`, `wallet export viewing-key`,
19
+ `wallet export spending-key`, `wallet import backup`, `wallet import viewing-key`, and
20
+ `wallet import spending-key`.
21
+ - Changed wallet backups so they exclude spending keys, viewing keys, key derivation material,
22
+ and plaintext note `owner`, `value`, and `salt` fields. Backups retain commitments,
23
+ nullifiers, encrypted note payloads, and channel workspace cache files.
24
+ - Replaced the previous full-control wallet workspace format with separate note-tracking,
25
+ spending-key metadata, and viewing-key metadata files. The CLI now loads only the current
26
+ wallet metadata format.
27
+ - Added action-impact acknowledgements for bridge-facing, channel, and note-mutating commands.
28
+ The warning output covers public event exposure, private note-state impact, note provenance
29
+ boundaries, illegal-use prohibition, CEX deposit-address warnings, secret-recovery limits, and
30
+ channel policy acceptance.
31
+ - Added full-note raw evidence export through `wallet get-notes --export-evidence` with an explicit
32
+ plaintext-export acknowledgement. Evidence bundles include note plaintext facts, derived
33
+ commitments and nullifiers, creation/spend transaction references, receipts, events, calldata, and
34
+ filtering indexes, while excluding viewing keys, spending keys, wallet secrets, account private
35
+ keys, and `.key` files.
36
+ - Made local wallet workspaces epoch-aware. `channel exit` now marks the active wallet epoch as
37
+ exited and retains its local note metadata instead of deleting the wallet workspace, while
38
+ `wallet recover-workspace` and `wallet get-notes --export-evidence` can still use retained exited
39
+ epochs for historical disclosure.
40
+ - Added a local static evidence investigator GUI and bundled it with the NPM package. The new
41
+ top-level `private-state-cli investigator` command prints the bundled HTML path, prints the file
42
+ URL, and opens the GUI in the default browser.
43
+ - Clarified wallet authority recovery in the NPM README: viewing-key rederivation needs the original
44
+ L1 private key and channel context, while spending-key rederivation additionally needs the same
45
+ wallet secret source used at `channel join`.
46
+ - Added a `channel join` success warning that losing both the spending-key file and wallet secret
47
+ source prevents spending-key rederivation.
48
+ - Aligned README terminology around `private-state DApp`, `private-state CLI`, `viewing key`,
49
+ `spending key`, `wallet secret source`, `user-controlled selective disclosure`, and
50
+ `privacy-preserving note semantics`.
51
+ - Added LLM-assistant guidance requiring strong user warnings and explicit confirmation before an
52
+ assistant runs commands that require `--acknowledge-*` options on a user's behalf.
53
+ - Simplified internal CLI code paths by removing a dead `loadWallet` parameter and redundant
54
+ `channel join` result aliases.
55
+
3
56
  ## 1.2.1 - 2026-05-11
4
57
 
5
58
  - Changed pre-command automatic recovery from an RPC log request time estimate to a fixed
package/README.md CHANGED
@@ -6,6 +6,35 @@ The full private-state DApp documentation is published with the repository:
6
6
 
7
7
  - https://github.com/tokamak-network/Tokamak-zk-EVM-contracts/tree/main/packages/apps/private-state/docs
8
8
 
9
+ ## Terminology And CEX Boundary
10
+
11
+ This npm README uses the same terminology as the repository README:
12
+
13
+ - `Tokamak Private App Channels`: Ethereum-settled, validity-proven execution domains for bridge-coupled DApps.
14
+ - `private-state DApp`: the current reference DApp that programs confidential application state inside a channel.
15
+ - `canonical Tokamak Network Token`: the L1 asset whose custody remains anchored on Ethereum.
16
+ - `self-custody L1 wallet`: a user-controlled L1 account, not a centralized-exchange deposit address.
17
+ - `L1-transparent bridge edge`: public bridge deposit and withdrawal transactions involving the canonical token.
18
+ - `channel-local accounting balance`: liquid application balance inside a channel before or after note use.
19
+ - `private-state note`: a channel-local application note, not an exchange-supported token or deposit asset.
20
+ - `proof-backed confidential application state`: DApp state advanced by accepted proof-backed channel transitions.
21
+ - `user-controlled selective disclosure`: optional user disclosure from local wallet state; Tokamak does not hold a master viewing key.
22
+ - `viewing key`: the note-receive private key used to decrypt note-delivery events for the registered note-receive public key.
23
+ - `spending key`: the channel-bound L2 private key used to authorize proof-backed note use.
24
+
25
+ Tokamak Private App Channels are not a centralized-exchange deposit network. CEX-facing token transfers and bridge
26
+ entry or exit remain public L1 activity. Internal private-state note counterparty relationships and note provenance are
27
+ not public by default and are not reconstructed by Tokamak on a user's behalf.
28
+
29
+ ## Tokamak-Operated Mainnet Channels
30
+
31
+ The table below lists private-state mainnet channels directly opened by Tokamak Network. Dates are
32
+ UTC.
33
+
34
+ | Channel name | Channel creator / leader | Created at | Genesis block | Channel manager |
35
+ | --- | --- | --- | ---: | --- |
36
+ | `the-great-first-channel` | [`0x32e6EE3d9820F0843E3e596132368747d36425F0`](https://etherscan.io/address/0x32e6EE3d9820F0843E3e596132368747d36425F0) | 2026-05-04 01:30:59 UTC | `25018368` | [`0x3108d92A38bFb4B3396DE7ad4D92318a8fbE61D7`](https://etherscan.io/address/0x3108d92A38bFb4B3396DE7ad4D92318a8fbE61D7) |
37
+
9
38
  ## Install
10
39
 
11
40
  ```bash
@@ -75,8 +104,8 @@ private-state-cli uninstall
75
104
 
76
105
  `uninstall` is intentionally interactive. It requires typing
77
106
  `I understand that the wallet secrets deleted due to this decision cannot be recovered` before deleting
78
- `~/tokamak-private-channels/`, the Tokamak zk-EVM runtime cache, and the global CLI npm package when npm reports that it
79
- is globally installed.
107
+ `~/tokamak-private-channels/`, including local account secrets and wallet key files, the Tokamak zk-EVM runtime cache,
108
+ and the global CLI npm package when npm reports that it is globally installed.
80
109
 
81
110
  ## Commands
82
111
 
@@ -97,6 +126,31 @@ A common private-state flow is:
97
126
  Use `private-state-cli help commands` for the full command list and required options. `private-state-cli --help`
98
127
  continues to print the same command list for shell compatibility.
99
128
 
129
+ ### Action-impact acknowledgement
130
+
131
+ Transaction-sending bridge, channel, and note commands require `--acknowledge-action-impact`. Before submitting any
132
+ transaction, the CLI prints a static action-impact summary covering whether the command emits public L1 events, whether
133
+ it changes private-state note state, which addresses or amounts become public, which note facts are not public by default,
134
+ illegal-use prohibition, secret-recovery limits, and channel policy acceptance. In non-interactive contexts, such as
135
+ scripts and LLM-assisted execution, the command fails unless the flag is present.
136
+
137
+ Static warning scope:
138
+
139
+ | Command | Public surface | Private-state note state | Not public by default |
140
+ |---|---|---|---|
141
+ | `account deposit-bridge` | L1 account, bridge vault, amount, approval/funding txs | No note change | No note plaintext or provenance is created |
142
+ | `account withdraw-bridge` | L1 recipient/account, bridge vault, amount, withdrawal tx | No note change | Prior private-state note path is not reconstructed |
143
+ | `channel join` | L1 account, L2 address, note-receive public key, join toll, channel id | No note change | Wallet secret, spending key, viewing key, and note plaintext |
144
+ | `wallet deposit-channel` | L1 submitter, registered L2 address, amount, channel id, accounting update | No note change | No note provenance is created |
145
+ | `wallet mint-notes` | L1 submitter, registered L2 address, commitments, encrypted note events, root update | Creates notes | Note owner, value, salt, and later provenance |
146
+ | `wallet transfer-notes` | L1 submitter, input nullifiers, output commitments, encrypted note events, root update | Spends and creates notes | Sender-recipient relationship, note plaintext, and provenance |
147
+ | `wallet redeem-notes` | L1 submitter, input nullifier, accounting update, root update | Consumes notes | Prior path by which the note was received |
148
+ | `wallet withdraw-channel` | L1 submitter, registered L2 address, amount, channel id, accounting update | No direct note spend | Prior private-state note path behind the liquid balance |
149
+
150
+ `account deposit-bridge` and `account withdraw-bridge` also print a centralized-exchange address warning. Do not use a
151
+ centralized-exchange controlled address as a self-custody bridge source or as the direct bridge withdrawal target
152
+ unless the user explicitly understands the compliance implications. Prefer a self-custody L1 wallet.
153
+
100
154
  Workspace recovery commands use the saved recovery index by default. If the local workspace is missing, corrupted, or
101
155
  does not contain a usable index, `channel recover-workspace` and `wallet recover-workspace` stop with an explicit error instead of
102
156
  silently replaying logs from channel genesis. Use `--source rpc --from-genesis` only when you intentionally want to
@@ -122,6 +176,16 @@ channel genesis and only runs when the recovery delta fits within the 7,200-bloc
122
176
  is missing, unusable, or too far behind, the command stops and asks the user to run the appropriate recovery command
123
177
  with `--from-genesis` explicitly when needed.
124
178
 
179
+ Local wallet workspaces are epoch-aware. Each successful channel registration creates a wallet epoch under the
180
+ canonical wallet directory. `channel exit` does not delete the local wallet workspace; it marks the active epoch as
181
+ exited with the exit transaction, block, and timestamp, then keeps that epoch read-only for historical note inspection
182
+ and evidence export. If the same account later joins the same channel again, the new registration is a separate active
183
+ epoch under the same canonical wallet name.
184
+
185
+ The current CLI only supports this epoch-aware wallet workspace layout. If a local wallet directory was created by an
186
+ older CLI and does not contain `wallet-index.metadata.json` plus `epochs/<epoch-id>/` metadata files, rebuild it with
187
+ `wallet recover-workspace` before using wallet commands.
188
+
125
189
  Channel leaders can optionally register a workspace mirror server so users can bootstrap recovery
126
190
  from a signed checkpoint and download only the local-to-checkpoint delta when a local recovery index
127
191
  already exists. The channel leader can build the static mirror files with
@@ -134,33 +198,63 @@ https://github.com/tokamak-network/Tokamak-zk-EVM-contracts/blob/main/packages/a
134
198
  Back up a local wallet with:
135
199
 
136
200
  ```bash
137
- private-state-cli wallet export --network mainnet --wallet <WALLET> --output ./wallet-backup.zip
201
+ private-state-cli wallet export backup --network mainnet --wallet <WALLET> --output ./wallet-backup.zip
138
202
  ```
139
203
 
140
- The default export stores the encrypted wallet, wallet metadata, and wallet-local secret. The encrypted `wallet.json`
141
- contains the wallet's current key material and tracked note state. The export intentionally excludes account secrets
142
- because wallet commands restore the L1 signer from the encrypted `wallet.json`; account secrets are only needed for
143
- account-level bridge-vault commands and optional `--tx-submitter` use. After importing a default export on a new machine,
144
- run `channel recover-workspace` before using wallet commands that need channel state:
204
+ The backup export stores note-tracking metadata and the channel workspace cache, but it does not include spending keys,
205
+ viewing keys, key derivation material, or plaintext note secrets. Note records in the backup keep commitments,
206
+ nullifiers, and encrypted note payloads only; `owner`, `value`, and `salt` are excluded.
207
+ Importing this backup restores encrypted tracking state and channel cache files, not wallet authority.
145
208
 
146
209
  ```bash
147
- private-state-cli wallet import --input ./wallet-backup.zip
148
- private-state-cli channel recover-workspace --channel-name <CHANNEL> --network mainnet --source rpc --from-genesis
210
+ private-state-cli wallet import backup --input ./wallet-backup.zip
211
+ ```
212
+
213
+ Export viewing and spending authority separately:
214
+
215
+ ```bash
216
+ private-state-cli wallet export viewing-key --network mainnet --wallet <WALLET> --output ./wallet-viewing.key
217
+ private-state-cli wallet export spending-key --network mainnet --wallet <WALLET> --output ./wallet-spending.key
149
218
  ```
150
219
 
151
- For a wider backup that can run wallet commands immediately when the imported channel workspace cache is still
152
- chain-aligned, add `--include-notes`:
220
+ Import those capabilities only when the target machine should receive them:
153
221
 
154
222
  ```bash
155
- private-state-cli wallet export --network mainnet --wallet <WALLET> --output ./wallet-backup.zip --include-notes
223
+ private-state-cli wallet import viewing-key --input ./wallet-viewing.key
224
+ private-state-cli wallet import spending-key --input ./wallet-spending.key
156
225
  ```
157
226
 
158
- Use `--all` to export every local mainnet wallet into one ZIP:
227
+ A backup plus a viewing key can reconstruct the wallet's readable note view from encrypted events, but it still cannot
228
+ spend notes. A backup plus a spending key is still missing event-log decryption authority. A normal operational restore
229
+ imports the backup, the viewing key, and the spending key, and still needs the relevant local L1 account secret for
230
+ commands that submit bridge or channel-registration transactions.
231
+
232
+ Export a local full-note evidence bundle with:
159
233
 
160
234
  ```bash
161
- private-state-cli wallet export --all --output ./mainnet-wallets.zip
235
+ private-state-cli wallet get-notes --network mainnet --wallet <WALLET> --export-evidence ./wallet-evidence.zip --acknowledge-full-note-plaintext-export
162
236
  ```
163
237
 
238
+ This ZIP is an input for `private-state-cli investigator`. It contains plaintext for all locally known
239
+ notes, derived commitments and nullifiers, creation and spend transaction references, transaction calldata, receipts,
240
+ events, and indexes for filtering by note, nullifier, transaction, block range, or available counterparty metadata. It
241
+ includes all local epochs for the selected wallet, including exited epochs retained after `channel exit`. It does not
242
+ include viewing keys, spending keys, wallet secret material, account private keys, or `.key` files. Do not submit the
243
+ raw ZIP as an exchange or auditor package unless full wallet-history disclosure is intended.
244
+
245
+ Open the local evidence investigator with:
246
+
247
+ ```bash
248
+ private-state-cli investigator
249
+ ```
250
+
251
+ The command prints the bundled investigator HTML path and file URL, then opens the static browser GUI. Load the raw
252
+ evidence ZIP in that GUI, apply the requested filters, and export a narrower user-consent disclosure ZIP. The GUI runs
253
+ locally in the browser and does not send files over the network.
254
+
255
+ The investigator accepts current epoch-aware evidence bundles only. If a bundle was generated by an older CLI, rebuild
256
+ the wallet workspace with `wallet recover-workspace` and export a new bundle with `wallet get-notes --export-evidence`.
257
+
164
258
  Estimate live transaction costs before sending commands with:
165
259
 
166
260
  ```bash
@@ -175,13 +269,13 @@ data.
175
269
  Proof-backed note commands can use a separate L1 transaction submitter:
176
270
 
177
271
  ```bash
178
- private-state-cli wallet mint-notes --wallet <WALLET> --network mainnet --amounts '[1]' --tx-submitter <ACCOUNT>
272
+ private-state-cli wallet mint-notes --wallet <WALLET> --network mainnet --amounts '[1]' --acknowledge-action-impact --tx-submitter <ACCOUNT>
179
273
  ```
180
274
 
181
275
  `--tx-submitter <ACCOUNT>` is available on `wallet mint-notes`, `wallet transfer-notes`, and `wallet redeem-notes`. The wallet still proves
182
276
  note ownership and builds the ZK proof, but the selected local account submits `executeChannelTransaction` and pays gas.
183
- Use this option when you want stronger privacy by avoiding a direct on-chain link between the note owner's wallet L1
184
- account and the proof-submission transaction.
277
+ Use this option when a separate imported local account should submit the L1 transaction and pay gas for a proof-backed
278
+ note command.
185
279
 
186
280
  Channel policy warning:
187
281
 
@@ -208,34 +302,67 @@ private-state-cli account import --account <ACCOUNT_NAME> --network sepolia --pr
208
302
  private-state-cli account get-l1-address --account <ACCOUNT_NAME> --network sepolia
209
303
  private-state-cli wallet list --network sepolia --channel-name cuda
210
304
  private-state-cli wallet get-meta --wallet <WALLET_NAME> --network sepolia
211
- private-state-cli wallet export --network sepolia --wallet <WALLET_NAME> --output ./wallet-backup.zip
212
- private-state-cli wallet import --input ./wallet-backup.zip
305
+ private-state-cli wallet export backup --network sepolia --wallet <WALLET_NAME> --output ./wallet-backup.zip
306
+ private-state-cli wallet import backup --input ./wallet-backup.zip
213
307
  ```
214
308
 
215
309
  `account import` is the only supported way to bring an L1 signing key into the CLI: it reads `--private-key-file` once
216
310
  and stores a protected local account secret for later `--account` use. The source file does not need `0600` permissions.
217
- `channel join` imports `--wallet-secret-path <PATH>` into the protected wallet-local default secret while creating the
218
- encrypted local wallet. `wallet list` reads only the local workspace and prints saved wallet names that can be reused with
311
+ `channel join` reads `--wallet-secret-path <PATH>` once while creating the channel-bound spending key and then stores
312
+ wallet backup metadata, viewing-key metadata, and spending-key metadata as separate files. `wallet list` reads only the local workspace and prints saved wallet names that can be reused with
219
313
  `--wallet`.
220
- `wallet get-meta` opens an encrypted local wallet and reports the stored L1/L2 identity metadata plus the current
221
- on-chain channel registration match state. `account get-l1-address` is a simple offline helper that derives the L1
222
- address for a local account.
314
+ `wallet get-meta` opens the wallet metadata and reports the stored L1/L2 identity metadata plus the current
315
+ on-chain channel registration match state, including the registered note-receive public key when present. On
316
+ epoch-aware wallet workspaces it also reports the selected wallet epoch and whether that epoch is active or exited.
317
+ `account get-l1-address` is a simple offline helper that derives the L1 address for a local account.
223
318
 
224
319
  ### Wallet Secret Source File
225
320
 
226
321
  `channel join` needs a wallet secret source file because the CLI no longer accepts raw wallet secrets on the command
227
- line. The source file is arbitrary high-entropy secret text that the CLI reads once and imports into the protected
228
- wallet-local canonical secret.
322
+ line. The source file is arbitrary high-entropy secret text that the CLI reads once for channel-bound spending-key
323
+ derivation. It is not persisted in the wallet workspace.
229
324
 
230
325
  Create one before joining a channel:
231
326
 
232
327
  ```bash
233
328
  openssl rand -hex 32 > ./wallet-secret.txt
234
- private-state-cli channel join --channel-name <CHANNEL> --network sepolia --account <ACCOUNT> --wallet-secret-path ./wallet-secret.txt
329
+ private-state-cli channel join --channel-name <CHANNEL> --network sepolia --account <ACCOUNT> --wallet-secret-path ./wallet-secret.txt --acknowledge-action-impact
235
330
  ```
236
331
 
237
- The import source file does not need `0600` permissions. The canonical wallet-local secret written by the CLI remains
238
- protected: macOS/Linux uses `0600`, while Windows uses ACL repair and inspection when possible.
332
+ The import source file does not need `0600` permissions. The CLI does not persist a wallet-local secret:
333
+ it reads the source once for channel-bound L2 spending-key derivation. The join flow stores the viewing key and
334
+ spending key as separate protected key files under the CLI secret root; macOS/Linux uses `0600`, while Windows uses ACL
335
+ repair and inspection when possible.
336
+
337
+ Keep the wallet secret source separately backed up if you expect to rederive the spending key later. The viewing key can
338
+ be rederived from the same L1 private key and channel context because it comes from the note-receive typed-data signing
339
+ flow. The spending key needs the same L1 private key, the same channel context, and the same wallet secret source. If the
340
+ spending-key file is lost and the wallet secret source is also lost, the CLI cannot reconstruct the spending key and the
341
+ notes for that wallet cannot be spent, transferred, or redeemed through the normal note flow.
342
+
343
+ ### Wallet Backup, Viewing, And Spending Authority
344
+
345
+ The wallet workspace is split so that a backup is not a full-control wallet export. Backup metadata stores the
346
+ recoverable local view of the channel: commitments, nullifiers, encrypted note-delivery payloads, scan checkpoints,
347
+ operation history, and the channel workspace cache. It deliberately omits plaintext note fields and key material.
348
+
349
+ The viewing key is the note-receive private key. It lets `wallet get-notes` decrypt bridge-propagated encrypted
350
+ note-delivery events and rebuild the user's readable note view. Sharing it gives read access to notes addressed to the
351
+ registered note-receive public key, but not spending authority.
352
+
353
+ The spending key is the channel-bound L2 private key. It authorizes proof-backed use of the wallet identity. Commands
354
+ that consume existing notes, such as `wallet transfer-notes` and `wallet redeem-notes`, need both the viewing key and
355
+ the spending key because the CLI must first reconstruct the plaintext notes and then prove authorized use of them.
356
+
357
+ Key recovery is intentionally split. Recreating the viewing key requires the original L1 private key and the same channel
358
+ context. Recreating the spending key requires the original L1 private key, the same channel context, and the same wallet
359
+ secret source used at `channel join`. Importing `wallet-viewing.key` or `wallet-spending.key` restores the corresponding
360
+ capability without rerunning derivation, but a backup ZIP alone never restores either capability.
361
+
362
+ `wallet get-notes --export-evidence <PATH> --acknowledge-full-note-plaintext-export` writes a local raw evidence ZIP.
363
+ The bundle is not a key export. It includes plaintext note facts for locally known notes so that
364
+ `private-state-cli investigator` can create narrower consent-disclosure packages without requiring viewing-key or
365
+ spending-key sharing.
239
366
 
240
367
  ## Workspace
241
368
 
@@ -245,8 +372,8 @@ The CLI stores user workspaces under:
245
372
  ~/tokamak-private-channels/workspace/<network>/<channel>/
246
373
  ```
247
374
 
248
- Wallet data is encrypted with the wallet-local default secret file under
249
- `~/tokamak-private-channels/secrets/<network>/wallets/<wallet>/secret`.
375
+ Wallet backup metadata lives under the channel workspace. Viewing and spending private keys live as separate protected
376
+ key files under `~/tokamak-private-channels/secrets/<network>/wallets/<wallet>/`.
250
377
 
251
378
  Bridge-facing commands accept optional `--rpc-url <URL>`. When `--rpc-url` is provided, the CLI stores it in
252
379
  `~/tokamak-private-channels/secrets/<network>/.env` as `RPC_URL=<URL>` with protected canonical secret permissions.
@@ -257,16 +384,19 @@ When `--rpc-url` is omitted, the CLI reads `RPC_URL` from that file. The `anvil`
257
384
  ## LLM Agent Guidance
258
385
 
259
386
  You may act as an interactive guide for users who do not understand this CLI or the private-state DApp. Assume the
260
- user only knows that the DApp is a way to send funds privately. Translate the user's intent into safe, step-by-step CLI
261
- actions.
387
+ user wants to use confidential channel-local notes while keeping L1 bridge deposits and withdrawals transparent.
388
+ Translate the user's intent into safe, step-by-step CLI actions.
262
389
 
263
- Primary goal: help the user privately send funds by guiding them through the required private-state CLI commands,
264
- explaining each step only as much as needed to proceed safely.
390
+ Primary goal: help the user safely use private-state note workflows: self-custody L1 funding, channel-local note
391
+ creation, note transfer, note recovery, and user-controlled disclosure where supported. Present this
392
+ as privacy-preserving note semantics for the current `private-state` DApp, not as invisible
393
+ activity or as a bridge-wide disclosure rule for every DApp.
265
394
 
266
395
  Operating rules:
267
396
 
268
397
  - Do not ask the user to reveal raw private keys or wallet secrets in chat. Use `account import --private-key-file`
269
- once, then use `--account` for L1 signing commands. Wallet commands use wallet-local default secret files.
398
+ once, then use `--account` for L1 signing commands. Wallet viewing and spending authority is imported separately
399
+ with `wallet import viewing-key` and `wallet import spending-key`.
270
400
  - Treat `private key file`, `account`, `wallet secret`, `wallet`, `network RPC URL`, and `channel policy` as
271
401
  new concepts unless the user has already demonstrated that they understand them. Define each term before using it
272
402
  in an instruction.
@@ -276,10 +406,14 @@ Operating rules:
276
406
  - An account is the local nickname created by `account import`. After import, signing commands should use
277
407
  `--account <NAME>` instead of asking for the raw key again.
278
408
  - A wallet secret source file is a separate high-entropy local secret chosen by the user for this private-state
279
- wallet. It is not the L1 private key. `channel join` imports it once and uses it to protect and recover the
280
- channel-local wallet.
281
- - A wallet is the encrypted local private-state wallet created during `channel join`. Its deterministic name is
282
- `<channelName>-<l1Address>`.
409
+ wallet. It is not the L1 private key. `channel join` reads it once for channel-bound spending-key derivation and
410
+ does not persist it in the wallet workspace.
411
+ - A wallet is the local private-state metadata set created during `channel join`. Its deterministic name is
412
+ `<channelName>-<l1Address>`. The wallet backup tracks encrypted note state, while viewing and spending authority
413
+ are stored in separate protected key files.
414
+ - A viewing key decrypts encrypted note-delivery events for the registered note-receive public key. A spending key is
415
+ the channel-bound L2 private key used to authorize note use. Do not describe either key as interchangeable with the
416
+ other.
283
417
  - The network RPC URL is the endpoint used to read and write chain state. It can be supplied once with `--rpc-url`
284
418
  on a bridge-facing command, after which the CLI saves it under the selected network.
285
419
  - A workspace recovery index is the saved block pointer and state-root hash that lets the CLI resume log scanning
@@ -301,7 +435,13 @@ Operating rules:
301
435
  8. inspect the channel with `channel get-meta` if it already exists, or create it with `channel create` if the user is
302
436
  the channel creator
303
437
  9. explain the immutable policy warning printed by the CLI
304
- 10. run `channel join --channel-name <CHANNEL> --network <NETWORK> --account <ACCOUNT> --wallet-secret-path <PATH>`
438
+ 10. run `channel join --channel-name <CHANNEL> --network <NETWORK> --account <ACCOUNT> --wallet-secret-path <PATH> --acknowledge-action-impact`
439
+ - Before executing any command for a user that requires an `--acknowledge-*` option, strongly warn the user in plain
440
+ language about what that acknowledgement means and ask for explicit confirmation. Do not add
441
+ `--acknowledge-action-impact` or `--acknowledge-full-note-plaintext-export` on the user's behalf until they confirm.
442
+ For `--acknowledge-action-impact`, explain the command's public/private action-impact summary. For
443
+ `--acknowledge-full-note-plaintext-export`, explain that all locally known note plaintext will be written into the
444
+ exported ZIP.
305
445
  - Before asking the user to create a file, explain what will be inside that file, who should be able to read it, and
306
446
  whether losing it prevents wallet recovery.
307
447
  - Prefer testnet examples unless the user explicitly asks for mainnet.
@@ -315,11 +455,11 @@ Operating rules:
315
455
  local wallet metadata and on-chain channel registration state.
316
456
  - Use `private-state-cli account get-bridge-fund` and `private-state-cli wallet get-channel-fund` to check balances before
317
457
  telling the user to move funds.
318
- - Explain that wallet names are local CLI identifiers, while private transfers use notes owned by L2 addresses
458
+ - Explain that wallet names are local CLI identifiers, while confidential note transfers use notes owned by L2 addresses
319
459
  registered in the channel.
320
- - Explain `--tx-submitter <ACCOUNT>` when the user wants stronger privacy for `wallet mint-notes`, `wallet transfer-notes`, or
321
- `wallet redeem-notes`: the wallet owner still proves note ownership, but another imported local L1 account can submit the
322
- on-chain `executeChannelTransaction` and pay gas.
460
+ - Explain `--tx-submitter <ACCOUNT>` when the user wants a separate L1 transaction submitter for `wallet mint-notes`,
461
+ `wallet transfer-notes`, or `wallet redeem-notes`: the wallet owner still proves note ownership, but another imported
462
+ local L1 account can submit the on-chain `executeChannelTransaction` and pay gas.
323
463
  - Before guiding a user through `channel create` or `channel join`, explain that channel policy is immutable after
324
464
  creation and that joining a channel means accepting its current verifier, DApp metadata, function layout, managed
325
465
  storage vector, and refund policy.
@@ -339,7 +479,7 @@ Suggested interaction flow:
339
479
  5. Run `wallet list` and relevant metadata or balance checks.
340
480
  6. If needed, guide the user through `channel create`, `account deposit-bridge`, `channel join`, `wallet deposit-channel`, and
341
481
  `wallet mint-notes`.
342
- 7. For a private transfer, select available note IDs from `wallet get-notes`, find the recipient L2 address from
482
+ 7. For a confidential note transfer, select available note IDs from `wallet get-notes`, find the recipient L2 address from
343
483
  `wallet get-meta`, then build `wallet transfer-notes`.
344
484
  8. After transfer, guide the recipient to run `wallet get-notes`; it refreshes received notes from the saved recovery index when the delta fits the 7,200-block pre-command budget. If the index is missing or too far behind, explain `wallet recover-workspace --from-genesis`.
345
485
 
@@ -347,9 +487,10 @@ Example onboarding explanation for `channel join`:
347
487
 
348
488
  > First we need two different local secrets. Your L1 private key proves which Ethereum account pays gas and signs
349
489
  > bridge transactions. We import it once into a local account nickname, so later commands can say `--account alice`
350
- > instead of handling the raw key again. Separately, the wallet secret protects the encrypted private-state wallet for
351
- > this channel. It is not sent on-chain and it is not the same as your L1 private key. If you lose the wallet secret,
352
- > recovering this channel wallet can become impossible.
490
+ > instead of handling the raw key again. Separately, the wallet secret source derives the channel-bound spending key
491
+ > during `channel join`. It is not sent on-chain, it is not the same as your L1 private key, and the CLI does not store
492
+ > it in the wallet workspace. A wallet backup restores encrypted tracking state; the viewing key restores note
493
+ > readability; the spending key restores note spendability.
353
494
 
354
495
  Example style: if the user says, "ADDR6 sends 10 tokens privately to ADDR8", do not assume the required note exists.
355
496
  First ask or check which channel and network to use, whether ADDR6 and ADDR8 are already joined, what the local wallet
@@ -386,3 +527,6 @@ Run it once on a new machine, or after public bridge, DApp, Groth16, or Tokamak
386
527
 
387
528
  No. User wallets and channel workspaces are created locally under `~/tokamak-private-channels/`.
388
529
  Bridge-facing commands still submit public transactions and proof-backed state transitions to the selected network.
530
+ For the current `private-state` DApp, commitments, nullifiers, and encrypted note-delivery events are
531
+ part of the DApp-programmed public disclosure surface, while note plaintext, note ownership, and note
532
+ provenance remain controlled by user-held secrets and implemented wallet tooling.
@@ -385,20 +385,20 @@
385
385
  <div class="box">
386
386
  <ul class="guide-list">
387
387
  <li>
388
- Your channel wallet is stored in your local workspace at
388
+ Your wallet backup metadata is stored in your local workspace at
389
389
  <code id="workspace-path-label"></code>.
390
390
  </li>
391
391
  <li>
392
- Even if you lose the channel wallet file, only your Ethereum private key, together with the correct
393
- channel context, can recover your channel wallet as long as you still know the wallet secret.
392
+ A wallet backup does not include viewing keys, spending keys, key derivation material, or plaintext
393
+ note owner, value, and salt fields.
394
394
  </li>
395
395
  <li>
396
- If your channel wallet file and wallet secret are both stolen, your channel funds can be stolen.
396
+ The viewing key decrypts encrypted note-delivery events. The spending key authorizes note use. Export
397
+ and import those keys only when that authority should move to the target machine.
397
398
  </li>
398
399
  <li>
399
- If you lose your wallet secret, you lose the ability to derive your channel L2 private key. In that
400
- case, you lose ownership of all notes because you can no longer use them, and that ownership cannot be
401
- recovered.
400
+ If you lose the spending key and cannot recreate it from the original account, channel context, and
401
+ wallet secret source, you lose the ability to spend, transfer, or redeem notes.
402
402
  </li>
403
403
  <li>
404
404
  Channel policy is immutable after creation. Joining a channel means accepting its verifier bindings,
@@ -485,6 +485,7 @@
485
485
  transferAmount1: "",
486
486
  transferRecipient2: "",
487
487
  transferAmount2: "",
488
+ acknowledgeActionImpact: false,
488
489
  docker: false,
489
490
  includeLocalArtifacts: false,
490
491
  groth16CliVersion: "",
@@ -826,7 +827,7 @@
826
827
  if (!commandNeedsWalletNotes()) {
827
828
  return;
828
829
  }
829
- clearWalletNoteState("Enter note IDs manually. The CLI uses the wallet-local default secret file and the assistant does not request wallet secrets.");
830
+ clearWalletNoteState("Enter note IDs manually. The CLI uses local wallet metadata plus protected viewing/spending key files when commands require them.");
830
831
  }
831
832
 
832
833
  function acceptsRpcUrl(command) {
@@ -843,9 +844,13 @@
843
844
  : null;
844
845
  const optionalFields = new Set(command.optionalFields ?? []);
845
846
  return command.fields.filter((fieldKey) => {
846
- if (fieldCatalog[fieldKey]?.optional || optionalFields.has(fieldKey)) {
847
+ const fieldConfig = fieldCatalog[fieldKey];
848
+ if (fieldConfig?.optional || optionalFields.has(fieldKey)) {
847
849
  return false;
848
850
  }
851
+ if (fieldConfig?.type === "checkbox") {
852
+ return state[fieldKey] !== true;
853
+ }
849
854
  if (fieldKey === "amounts" && command.id === "wallet-mint-notes") {
850
855
  return currentMintAmounts().length === 0;
851
856
  }
@@ -0,0 +1,41 @@
1
+ # Private-State Evidence Investigator
2
+
3
+ This directory contains a static browser tool for filtering a local raw evidence bundle produced by:
4
+
5
+ ```bash
6
+ private-state-cli wallet get-notes \
7
+ --network <NETWORK> \
8
+ --wallet <WALLET> \
9
+ --export-evidence ./wallet-evidence.zip \
10
+ --acknowledge-full-note-plaintext-export
11
+ ```
12
+
13
+ Open `index.html` in a modern browser, load the raw ZIP, select a filter scope, and build a narrower
14
+ user-consent disclosure ZIP. From an installed CLI package, `private-state-cli investigator` prints the bundled
15
+ HTML path and opens it in the default browser.
16
+
17
+ The tool does not run a server and does not send files over the network. It reads the selected ZIP in
18
+ the browser and writes a new ZIP with selected note records plus directly referenced transaction,
19
+ receipt, and event files.
20
+
21
+ The raw evidence bundle contains plaintext for all locally known notes. Do not submit the raw bundle
22
+ as an exchange or auditor package unless full wallet-history disclosure is intended. Use the
23
+ investigator output package for scoped disclosure.
24
+
25
+ The investigator accepts current epoch-aware evidence bundles only. Supported note records live under
26
+ `wallets/<wallet>/epochs/<epoch-id>/notes/` inside the ZIP. If a bundle uses an older layout, rebuild the local wallet
27
+ workspace with `wallet recover-workspace` and export a new evidence ZIP with `wallet get-notes --export-evidence`.
28
+
29
+ ## Supported Filtering
30
+
31
+ - note commitment or nullifier
32
+ - creation transaction or spend transaction
33
+ - creation or spend block range
34
+ - current note status
35
+ - relationship direction
36
+ - available counterparty L2 address metadata
37
+ - user-provided bridge deposit or withdraw transaction context
38
+
39
+ Counterparty filtering is only as complete as the relationship hints present in the raw evidence
40
+ bundle. The investigator does not create a keyless cryptographic decryption proof and does not
41
+ reconstruct private note provenance from public data alone.