@interop/did-cli 0.13.0 → 0.15.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 +166 -6
- package/README.md +172 -26
- package/dist/commands/did/create.d.ts +22 -0
- package/dist/commands/did/create.d.ts.map +1 -1
- package/dist/commands/did/create.js +6 -27
- package/dist/commands/did/create.js.map +1 -1
- package/dist/commands/did/service.d.ts +19 -4
- package/dist/commands/did/service.d.ts.map +1 -1
- package/dist/commands/did/service.js +46 -45
- package/dist/commands/did/service.js.map +1 -1
- package/dist/commands/did/webvh-update.d.ts +72 -9
- package/dist/commands/did/webvh-update.d.ts.map +1 -1
- package/dist/commands/did/webvh-update.js +177 -61
- package/dist/commands/did/webvh-update.js.map +1 -1
- package/dist/commands/did.d.ts.map +1 -1
- package/dist/commands/did.js +10 -1
- package/dist/commands/did.js.map +1 -1
- package/dist/commands/key.d.ts.map +1 -1
- package/dist/commands/key.js +5 -8
- package/dist/commands/key.js.map +1 -1
- package/dist/commands/was/request-grant.d.ts +39 -0
- package/dist/commands/was/request-grant.d.ts.map +1 -0
- package/dist/commands/was/request-grant.js +250 -0
- package/dist/commands/was/request-grant.js.map +1 -0
- package/dist/commands/was/resource.d.ts +21 -7
- package/dist/commands/was/resource.d.ts.map +1 -1
- package/dist/commands/was/resource.js +40 -15
- package/dist/commands/was/resource.js.map +1 -1
- package/dist/commands/was/shared.d.ts +43 -3
- package/dist/commands/was/shared.d.ts.map +1 -1
- package/dist/commands/was/shared.js +82 -4
- package/dist/commands/was/shared.js.map +1 -1
- package/dist/commands/was/shell/completer.d.ts +24 -0
- package/dist/commands/was/shell/completer.d.ts.map +1 -0
- package/dist/commands/was/shell/completer.js +99 -0
- package/dist/commands/was/shell/completer.js.map +1 -0
- package/dist/commands/was/shell/dispatcher.d.ts +27 -0
- package/dist/commands/was/shell/dispatcher.d.ts.map +1 -0
- package/dist/commands/was/shell/dispatcher.js +227 -0
- package/dist/commands/was/shell/dispatcher.js.map +1 -0
- package/dist/commands/was/shell/session.d.ts +37 -0
- package/dist/commands/was/shell/session.d.ts.map +1 -0
- package/dist/commands/was/shell/session.js +67 -0
- package/dist/commands/was/shell/session.js.map +1 -0
- package/dist/commands/was/shell/tokenize.d.ts +19 -0
- package/dist/commands/was/shell/tokenize.d.ts.map +1 -0
- package/dist/commands/was/shell/tokenize.js +77 -0
- package/dist/commands/was/shell/tokenize.js.map +1 -0
- package/dist/commands/was/shell.d.ts +30 -0
- package/dist/commands/was/shell.d.ts.map +1 -0
- package/dist/commands/was/shell.js +170 -0
- package/dist/commands/was/shell.js.map +1 -0
- package/dist/commands/was/tree.d.ts +6 -1
- package/dist/commands/was/tree.d.ts.map +1 -1
- package/dist/commands/was/tree.js +12 -5
- package/dist/commands/was/tree.js.map +1 -1
- package/dist/commands/was.d.ts.map +1 -1
- package/dist/commands/was.js +34 -1
- package/dist/commands/was.js.map +1 -1
- package/dist/commands/zcap.d.ts +22 -2
- package/dist/commands/zcap.d.ts.map +1 -1
- package/dist/commands/zcap.js +75 -4
- package/dist/commands/zcap.js.map +1 -1
- package/dist/keys/seed.d.ts +21 -0
- package/dist/keys/seed.d.ts.map +1 -0
- package/dist/keys/seed.js +41 -0
- package/dist/keys/seed.js.map +1 -0
- package/dist/keys/webvh-signer.d.ts +18 -13
- package/dist/keys/webvh-signer.d.ts.map +1 -1
- package/dist/keys/webvh-signer.js +5 -20
- package/dist/keys/webvh-signer.js.map +1 -1
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +57 -10
- package/dist/storage.js.map +1 -1
- package/dist/was/address.d.ts +24 -0
- package/dist/was/address.d.ts.map +1 -1
- package/dist/was/address.js +49 -3
- package/dist/was/address.js.map +1 -1
- package/dist/was/capability.d.ts.map +1 -1
- package/dist/was/capability.js +4 -1
- package/dist/was/capability.js.map +1 -1
- package/dist/was/client.d.ts +10 -3
- package/dist/was/client.d.ts.map +1 -1
- package/dist/was/client.js +27 -6
- package/dist/was/client.js.map +1 -1
- package/dist/was/request-grant.d.ts +147 -0
- package/dist/was/request-grant.d.ts.map +1 -0
- package/dist/was/request-grant.js +256 -0
- package/dist/was/request-grant.js.map +1 -0
- package/dist/zcap/create.d.ts +1 -1
- package/dist/zcap/create.js +1 -1
- package/dist/zcap/delegate.d.ts +1 -1
- package/dist/zcap/delegate.js +1 -1
- package/dist/zcap/encoding.d.ts +17 -5
- package/dist/zcap/encoding.d.ts.map +1 -1
- package/dist/zcap/encoding.js +31 -17
- package/dist/zcap/encoding.js.map +1 -1
- package/dist/zcap/resolve.d.ts +17 -4
- package/dist/zcap/resolve.d.ts.map +1 -1
- package/dist/zcap/resolve.js +25 -8
- package/dist/zcap/resolve.js.map +1 -1
- package/package.json +22 -20
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,165 @@
|
|
|
1
1
|
# History
|
|
2
2
|
|
|
3
|
+
## 0.15.0 - 2026-09-14
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- `was request-grant` accepts an explicit `--save` (the default), so the
|
|
8
|
+
documented `--save --handle agent` invocation no longer fails with
|
|
9
|
+
"unknown option".
|
|
10
|
+
- An integration test for `was request-grant` against the WAS server's
|
|
11
|
+
ephemeral-exchange facet, with a scripted wallet that opens the interaction
|
|
12
|
+
URL, delegates the public collection from the space controller's key, and
|
|
13
|
+
posts the response presentation back. It then publishes `index.html`
|
|
14
|
+
through the stored handle and fetches it anonymously as `text/html`.
|
|
15
|
+
- `zcap import <capability>` validates a capability received outside the CLI
|
|
16
|
+
(a multibase `u...` string or a JSON file) and stores it, with optional
|
|
17
|
+
`--handle` / `--description`, so `--capability <handle>` can name it. It
|
|
18
|
+
refuses a capability whose id is already stored or a handle already in use.
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
|
|
22
|
+
- The `--wallet` deep link now carries the route and the `url` parameter in
|
|
23
|
+
the URL fragment (`<wallet>/#/external/request?url=<interaction url>`).
|
|
24
|
+
Freewallet routes on the fragment, so the earlier path form opened the
|
|
25
|
+
landing page instead of the approval page.
|
|
26
|
+
|
|
27
|
+
### Changed
|
|
28
|
+
|
|
29
|
+
- `@interop/zcap` is at `^11.3.0`, which exports the `checkCapability`
|
|
30
|
+
validator used by `zcap import`.
|
|
31
|
+
- BREAKING: `was request-grant` takes the exchange host as `--exchange <url>`
|
|
32
|
+
instead of `--server <url>`. The flag only names the WAS server that hosts
|
|
33
|
+
the ephemeral exchange; the granted capability targets whichever space the
|
|
34
|
+
wallet picks. `WAS_SERVER_URL` remains the fallback.
|
|
35
|
+
- BREAKING: the `encoded` form of a capability (printed by `zcap create`,
|
|
36
|
+
`zcap delegate`, `was grant`, and `was request-grant`) is now multibase
|
|
37
|
+
base64url (`u...`) instead of base58btc (`z...`); the `z` form is no longer
|
|
38
|
+
accepted by `--capability`. base58 is quadratic in the input size and
|
|
39
|
+
`@scure/base` refuses it past 2048 bytes, which a wallet-delegated
|
|
40
|
+
capability exceeds once it embeds its chain; `was request-grant` failed
|
|
41
|
+
after saving such a grant.
|
|
42
|
+
- The `was` commands run was-client's service discovery against a space-owned
|
|
43
|
+
URL (the capability's invocation target, or the addressed space) instead of
|
|
44
|
+
the server origin, so a deployment whose origin serves a static page with
|
|
45
|
+
no service link (such as freewallet.cloud) still resolves.
|
|
46
|
+
- Bumped `@interop/was-client` to `^0.64.0`. The Space root capability id is
|
|
47
|
+
now the canonical trailing-slash container URL and signed requests run
|
|
48
|
+
service discovery first, which was-teaching-server 0.33 and later require;
|
|
49
|
+
against those servers the previous client's delegated invocations were
|
|
50
|
+
refused as 404.
|
|
51
|
+
|
|
52
|
+
## 0.14.0 - 2026-09-14
|
|
53
|
+
|
|
54
|
+
### Added
|
|
55
|
+
|
|
56
|
+
- `was request-grant` -- the requesting side of capability delegation, the
|
|
57
|
+
inverse of `was grant`. It mints an Ed25519 `did:key` for itself, asks a
|
|
58
|
+
user's wallet for a capability on one of its public collections, prints an
|
|
59
|
+
approval link for the user to open, waits for their answer, and files the
|
|
60
|
+
received capability in the zcap store. The grantee key is minted by the
|
|
61
|
+
command rather than passed in, so a caller driving the CLI never handles key
|
|
62
|
+
material: stdout carries the capability (or, with `--json`, one object holding
|
|
63
|
+
the DID, the handle, the link, and the capability), and the approval link and
|
|
64
|
+
progress notes go to stderr. The key is written only once the grant arrives,
|
|
65
|
+
and a handle already taken by a stored DID or capability is refused up front,
|
|
66
|
+
so handle lookups stay unambiguous across runs. Options are
|
|
67
|
+
`--collection` (default `web`), `--action` (default `GET HEAD PUT POST`),
|
|
68
|
+
`--reason`, `--timeout` (default 600 seconds, the server's exchange
|
|
69
|
+
lifetime), `--handle` (default `agent`), `--description`, `--no-save`,
|
|
70
|
+
`--json`, and `--server`. Persistence is on by default because
|
|
71
|
+
`--capability` resolves its signer out of the local DID store, so a key held
|
|
72
|
+
only for the run cannot sign the write that follows; `--no-save` prints the
|
|
73
|
+
capability without keeping either half. The request carries a single
|
|
74
|
+
`AuthorizationCapabilityQuery` naming a public-collection descriptor, with no
|
|
75
|
+
`DIDAuthentication` query and no `domain`.
|
|
76
|
+
|
|
77
|
+
- `was request-grant --name <name>` sends the agent's self-declared display
|
|
78
|
+
name (the VPR's root `agent: { name }` member, wallet-core 0.53.0), shown on
|
|
79
|
+
the wallet consent screen as what the agent calls itself; at most 64
|
|
80
|
+
characters, no control characters.
|
|
81
|
+
|
|
82
|
+
- `was request-grant --wallet <url>` also prints a link that opens the given
|
|
83
|
+
wallet straight onto its approval page for the exchange
|
|
84
|
+
(`<wallet>/external/request?url=<interaction url>`). The interaction URL is
|
|
85
|
+
still printed, for a wallet on another device. The wallet URL must be
|
|
86
|
+
absolute http(s), and a bad one is refused before any exchange is opened.
|
|
87
|
+
|
|
88
|
+
- `--resource <id>` on `was get`, `was put`, `was meta get`, `was meta put`,
|
|
89
|
+
and `was rm`: names one resource beneath a collection-scoped
|
|
90
|
+
`--capability`, so a grant issued on a whole collection can read, write,
|
|
91
|
+
and delete at a caller-chosen id. `resource add` also takes a collection
|
|
92
|
+
capability, but the server picks the id there. The resource handle inherits
|
|
93
|
+
the collection's bound capability, so the request stays an invocation of
|
|
94
|
+
the received grant. `--resource` without a capability, or alongside a
|
|
95
|
+
capability that already targets a resource, is an input error.
|
|
96
|
+
- A `publish-page` Claude Code skill (`.claude/skills/publish-page/`) and the
|
|
97
|
+
agent storage demo it scripts (`demo/agent-storage/README.md`): an LLM agent
|
|
98
|
+
drafts an `index.html`, asks the user's wallet for a grant on a public
|
|
99
|
+
collection with `was request-grant`, and publishes the page through the
|
|
100
|
+
delegated capability. The skill is model-invoked, states that `--save` is
|
|
101
|
+
required (a key held only for the run cannot sign the write that follows),
|
|
102
|
+
keeps the agent away from key material, and sends a user with no wallet
|
|
103
|
+
account to `<wallet>/signup` before resuming.
|
|
104
|
+
|
|
105
|
+
- `was shell` -- an interactive REPL over the `was` command tree. Start it with
|
|
106
|
+
`di was shell [path]` (`--server`/`--did` seed the session defaults), then run
|
|
107
|
+
any `was` subcommand without re-typing space handles or re-paying the
|
|
108
|
+
cold-start cost. A "current directory" (`cd`/`use`, with `..`, `/`, relative
|
|
109
|
+
paths, and full space URLs) makes every command's path relative to it, and
|
|
110
|
+
`pwd`, `connect <url>`, `did <ref>`, `help`, and `exit`/`quit` round out the
|
|
111
|
+
builtins. Tab completion covers builtins, subcommands, and registered space
|
|
112
|
+
handles. The prompt and diagnostics go to stderr while command data stays on
|
|
113
|
+
stdout, so `di was shell < script` keeps a pipe-clean stdout.
|
|
114
|
+
|
|
115
|
+
### Changed
|
|
116
|
+
|
|
117
|
+
- Update to latest d-i-core, verifier-core, was-client and didwebvh deps.
|
|
118
|
+
- Added `@interop/wallet-request` as a dependency, for the ephemeral-exchange
|
|
119
|
+
create and poll helpers `was request-grant` transports over, and for the
|
|
120
|
+
zcap-only presentation-request composer it sends (moved there from
|
|
121
|
+
wallet-core's `request` subpath).
|
|
122
|
+
- `did webvh rotate-keys` and `did service add|remove` now pass the
|
|
123
|
+
already-resolved log state to `updateDID` as `priorMeta`, so each update
|
|
124
|
+
verifies the history log once instead of twice. The pairing between the log
|
|
125
|
+
and its resolved metadata is now asserted (O(1)) before signing.
|
|
126
|
+
- `did webvh rotate-keys` edits the authorized `updateKeys` set instead of
|
|
127
|
+
rebuilding it from the single local key: a stage-only `--enable-prerotation`
|
|
128
|
+
leaves the set unchanged, and an ordinary rotation replaces only the retired
|
|
129
|
+
key, so co-authorized update keys are no longer silently revoked.
|
|
130
|
+
- `rotate-keys --update-key` now authorizes every supplied key instead of
|
|
131
|
+
silently dropping all but the first.
|
|
132
|
+
- did:webvh updates persist crash-safely: the update-keys sidecar (including
|
|
133
|
+
the superseded secret) is written before the log that authorizes the new
|
|
134
|
+
key, and the signer loaders can recover from a rotation interrupted between
|
|
135
|
+
the two writes.
|
|
136
|
+
- Stored artifacts (DID documents, history logs, sidecars, wallet items) are
|
|
137
|
+
written atomically (temp file + rename), so an interrupted write can no
|
|
138
|
+
longer leave a truncated file.
|
|
139
|
+
- Stored artifacts are now written with mode `0600` (owner read/write only)
|
|
140
|
+
instead of the ambient umask default, since keys are held as plaintext
|
|
141
|
+
Multikey documents. Wallet and DID directories are created with mode `0700`,
|
|
142
|
+
since a DID document is named after its DID. Existing files are not
|
|
143
|
+
migrated.
|
|
144
|
+
- The atomic-write temp file is unlinked and reopened with `wx` rather than
|
|
145
|
+
chmod-ed after the write, so a temp file left behind by an interrupted run
|
|
146
|
+
cannot receive a secret at its own wider mode.
|
|
147
|
+
- Confirmation prompts no longer auto-confirm when stdin is not interactive;
|
|
148
|
+
non-interactive runs must pass `--yes`, and a declined confirmation now
|
|
149
|
+
exits 1.
|
|
150
|
+
- An empty `SECRET_KEY_SEED` env var is treated as unset, and an invalid one
|
|
151
|
+
is reported as a one-line error; seed derivation is shared across
|
|
152
|
+
`key create`, `did create`, and `rotate-keys`.
|
|
153
|
+
- Command errors that escape a runner are reported as one-line messages with
|
|
154
|
+
exit 1 instead of surfacing as unhandled rejections; a corrupt update-keys
|
|
155
|
+
sidecar reports its file path.
|
|
156
|
+
- `did add-service` validates `--endpoint`/`--endpoint-json` arguments before
|
|
157
|
+
resolving (and re-verifying) a did:webvh history log; `rotate-keys` likewise
|
|
158
|
+
checks flag conflicts before resolution.
|
|
159
|
+
- Bumped `@interop/ed25519-verification-key` to `^8.2.0` and switched the
|
|
160
|
+
did:webvh entry signer to its new `didKeySigner()` method, so the caller no
|
|
161
|
+
longer mutates `keyPair.id` before signing.
|
|
162
|
+
|
|
3
163
|
## 0.13.0 - 2026-07-12
|
|
4
164
|
|
|
5
165
|
### Added
|
|
@@ -82,7 +242,7 @@
|
|
|
82
242
|
- `vc issue --did` now accepts a metadata handle (not just a full DID id),
|
|
83
243
|
resolving it via the same lookup used by the other DID-referencing commands.
|
|
84
244
|
Previously passing a handle failed with a confusing `The "path" argument must
|
|
85
|
-
|
|
245
|
+
be of type string. Received undefined` error.
|
|
86
246
|
|
|
87
247
|
### Changed
|
|
88
248
|
|
|
@@ -121,7 +281,7 @@
|
|
|
121
281
|
field); `loadFromCollection` / `saveToCollection` take an options object like
|
|
122
282
|
the rest of the storage helpers; `vc/issue` and `vc/verify` replace their
|
|
123
283
|
`as never` casts with typed ones; `edv/recipients` replaces `Record<string,
|
|
124
|
-
|
|
284
|
+
any>` with a named `VerificationMethodNode` type; `edv`'s encrypt functions
|
|
125
285
|
share an `EnvelopeOptions` type and a `resolveEncryptContextOrReport` wrapper;
|
|
126
286
|
and the `z6Mk` / `z6LS` multibase prefixes are named constants. Added the
|
|
127
287
|
file-level JSDoc header to `key.ts` and moved the `zcap revoke` stub message to
|
|
@@ -457,7 +617,7 @@
|
|
|
457
617
|
`--handle` / `--description` tag it (exit `1` without `--save`).
|
|
458
618
|
- Add `vc list` (`--json` / `--plain`) to render a metadata table of the
|
|
459
619
|
stored credentials (`HANDLE | TYPE | ISSUER | CREATED | ID |
|
|
460
|
-
|
|
620
|
+
DESCRIPTION`), `vc show <id>` (aliases: `view`, `cat`; `--meta` for the
|
|
461
621
|
metadata, `--meta --json` for it as JSON), `vc meta <id>` to edit the
|
|
462
622
|
metadata sidecar, and `vc remove <id>` (aliases: `delete`, `rm`). All
|
|
463
623
|
accept a credential id, a storage id (for id-less credentials), or a
|
|
@@ -494,7 +654,7 @@
|
|
|
494
654
|
`did create --save` and `did add-key`).
|
|
495
655
|
- Add metadata support for locally stored keys and DIDs, persisted as
|
|
496
656
|
`.meta.json` sidecar files next to the stored item (`~/.wallet/keys/
|
|
497
|
-
|
|
657
|
+
<storageId>.meta.json` and `~/.dids/<method>/<did>.meta.json`, following the
|
|
498
658
|
existing `.keys.json` sidecar pattern). Metadata fields: `created` (ISO 8601
|
|
499
659
|
timestamp written at `--save` time), `handle` (a short user-defined tag),
|
|
500
660
|
`description` (longer free text), and -- for keys -- `dids`, a cache of the
|
|
@@ -534,8 +694,8 @@
|
|
|
534
694
|
the new `--plain` flag for the previous one-item-per-line output.
|
|
535
695
|
- **BREAKING**: `key list --json` and `did list --json` now output an array of
|
|
536
696
|
objects with metadata (`{fingerprint, storageId, type, curve?, created?,
|
|
537
|
-
|
|
538
|
-
|
|
697
|
+
handle?, description?, dids}` for keys; `{did, method, created?, handle?,
|
|
698
|
+
description?}` for DIDs) instead of an array of plain strings.
|
|
539
699
|
|
|
540
700
|
## 0.4.0 - 2026-06-09
|
|
541
701
|
|
package/README.md
CHANGED
|
@@ -25,7 +25,7 @@ cryptographic key pairs that underpin them.
|
|
|
25
25
|
It lets you generate and manage these objects locally -- minting DIDs, issuing
|
|
26
26
|
and verifying credentials, delegating capabilities, and encrypting data -- and
|
|
27
27
|
interact with remote
|
|
28
|
-
[Wallet Attached Storage](https://
|
|
28
|
+
[Wallet Attached Storage](https://w3c-ccg.github.io/wallet-attached-storage-spec/)
|
|
29
29
|
servers, all from the terminal and backed by a local file-based wallet.
|
|
30
30
|
|
|
31
31
|
### Features
|
|
@@ -91,6 +91,7 @@ di vc remove|delete|rm <id> remove a stored credential
|
|
|
91
91
|
|
|
92
92
|
di zcap create create a root capability
|
|
93
93
|
di zcap delegate delegate (attenuate) a capability
|
|
94
|
+
di zcap import <capability> validate and store a received capability
|
|
94
95
|
di zcap list list stored capabilities
|
|
95
96
|
di zcap show|view|cat <id> show a stored capability
|
|
96
97
|
di zcap meta <id> show/edit a capability's local metadata
|
|
@@ -109,6 +110,7 @@ di was ls|get|put|rm [path] depth-dispatching shorthands
|
|
|
109
110
|
di was policy <show|set|clear> manage access-control policies
|
|
110
111
|
di was publish|unpublish <path> toggle world-readable access
|
|
111
112
|
di was grant <path> delegate access via a signed capability
|
|
113
|
+
di was request-grant ask a wallet for a capability on a collection
|
|
112
114
|
```
|
|
113
115
|
|
|
114
116
|
### Environment Variables
|
|
@@ -118,14 +120,33 @@ or secret-key seeds for individual commands. Each is also documented inline in
|
|
|
118
120
|
the relevant command section below.
|
|
119
121
|
|
|
120
122
|
| Variable | Used by | Purpose |
|
|
121
|
-
|
|
123
|
+
| -------------------------- | -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
122
124
|
| `WALLET_DIR` | all | Wallet collections directory (`keys/`, `zcaps/`, `credentials/`, `was-spaces/`). Defaults to `~/.config/did-cli-wallet/` (honors `XDG_CONFIG_HOME`). |
|
|
123
125
|
| `DIDS_DIR` | `did` | DID-documents directory. Defaults to `<WALLET_DIR>/dids/`. |
|
|
124
126
|
| `SECRET_KEY_SEED` | `key create`, `did create` | Multibase-encoded seed for deterministic key/DID generation. Not supported with `--type ecdsa` or `--type x25519`. |
|
|
125
127
|
| `WAS_DID` | `was` | Default signing DID (or stored-DID handle) when `--did` is omitted. |
|
|
126
|
-
| `WAS_SERVER_URL` | `was` | Default WAS server base URL when `--server` is omitted.
|
|
128
|
+
| `WAS_SERVER_URL` | `was` | Default WAS server base URL when `--server` (or `--exchange` for `request-grant`) is omitted. |
|
|
127
129
|
| `ZCAP_CONTROLLER_KEY_SEED` | `zcap` | Controller signing-key seed for delegating capabilities. |
|
|
128
130
|
|
|
131
|
+
### File Permissions
|
|
132
|
+
|
|
133
|
+
Everything written under `WALLET_DIR` and `DIDS_DIR` -- keys, zcaps,
|
|
134
|
+
credentials, space records, DID documents, sidecars, and history logs -- is
|
|
135
|
+
created with mode `0600`, owner read/write only. Directories are created with
|
|
136
|
+
mode `0700`, since a DID document is named after its DID and the file names
|
|
137
|
+
alone reveal what you hold. Secret key material is stored as plaintext Multikey
|
|
138
|
+
documents, so the file mode is what keeps it off other local accounts.
|
|
139
|
+
|
|
140
|
+
Files written before this became the default are not migrated. To tighten an
|
|
141
|
+
existing wallet directory:
|
|
142
|
+
|
|
143
|
+
```
|
|
144
|
+
chmod -R u=rwX,go= ~/.config/did-cli-wallet
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
The capital `X` matters -- a plain `chmod -R 600` would clear the traverse bit
|
|
148
|
+
on the directories and leave the wallet unreadable to you as well.
|
|
149
|
+
|
|
129
150
|
### Key Management
|
|
130
151
|
|
|
131
152
|
#### Create a key pair
|
|
@@ -594,7 +615,7 @@ distinct keys, so the update key can be rotated without ever disturbing the
|
|
|
594
615
|
document.
|
|
595
616
|
|
|
596
617
|
By default `did:webvh` arms **key pre-rotation**: the DID commits, in advance,
|
|
597
|
-
to the
|
|
618
|
+
to the _hash_ of the key allowed to perform the next update. A compromise of the
|
|
598
619
|
currently active update key cannot be used to seize the DID, because the
|
|
599
620
|
attacker still does not hold the pre-committed next key. So `create` generates
|
|
600
621
|
three keys: the active update key, a staged next update key (whose hash is
|
|
@@ -633,8 +654,8 @@ A few more create-time options are recorded in the signed history-log
|
|
|
633
654
|
be moved to a different domain; `--no-portable` pins it to its origin.
|
|
634
655
|
- `--witness <did...>` -- declare one or more **witness** `did:key` DIDs
|
|
635
656
|
authorized to co-sign the DID's log entries (repeatable). `--witness-threshold
|
|
636
|
-
|
|
637
|
-
witnesses; it requires `--witness`). This only
|
|
657
|
+
<n>` sets how many witness approvals are required (defaults to the number of
|
|
658
|
+
witnesses; it requires `--witness`). This only _declares_ the witnesses;
|
|
638
659
|
actually generating witness proofs is not yet supported.
|
|
639
660
|
- `--watcher <url...>` -- declare one or more **watcher** URLs that monitor the
|
|
640
661
|
DID's log (repeatable; `https://`, or `http://localhost` for local testing).
|
|
@@ -654,7 +675,7 @@ Rotate the update (authorization) key of a locally stored `did:webvh` DID with
|
|
|
654
675
|
With no flags it advances the pre-rotation ratchet in one step: it reveals and
|
|
655
676
|
activates the previously staged next key (signing the new entry with it), and
|
|
656
677
|
stages a fresh next key for the following rotation. The retired update key's
|
|
657
|
-
secret is deleted by default -- a retired key is only ever needed to
|
|
678
|
+
secret is deleted by default -- a retired key is only ever needed to _verify_
|
|
658
679
|
historic log entries, which uses the public key from the log, not the secret:
|
|
659
680
|
|
|
660
681
|
```
|
|
@@ -693,6 +714,8 @@ Flags:
|
|
|
693
714
|
new key (a bare `--stop-prerotation` reveal, or rotating to an external
|
|
694
715
|
`--update-key`).
|
|
695
716
|
- `-y`, `--yes` -- skip the confirmation prompt (rotation is hard to undo).
|
|
717
|
+
Required when stdin is not interactive (scripts, cron), where the prompt
|
|
718
|
+
cannot be asked.
|
|
696
719
|
|
|
697
720
|
#### Add or remove a service entry
|
|
698
721
|
|
|
@@ -1046,7 +1069,7 @@ Store an existing Verifiable Credential in local wallet storage with
|
|
|
1046
1069
|
`vc import`. The credential is read from a file argument, an http(s) URL, or,
|
|
1047
1070
|
if neither is given, from stdin. The input must structurally look like a
|
|
1048
1071
|
credential (its `type` must include `VerifiableCredential`); it is stored
|
|
1049
|
-
as-is and is
|
|
1072
|
+
as-is and is _not_ verified on import (run `vc verify` for that). `--handle` /
|
|
1050
1073
|
`--description` tag the saved credential:
|
|
1051
1074
|
|
|
1052
1075
|
```
|
|
@@ -1178,7 +1201,7 @@ handed down a chain of signed _delegated_ capabilities, each one optionally
|
|
|
1178
1201
|
narrowing the allowed actions or the target.
|
|
1179
1202
|
|
|
1180
1203
|
Both commands print the capability as JSON together with an `encoded` field --
|
|
1181
|
-
the capability serialized and
|
|
1204
|
+
the capability serialized and base64url-encoded with a multibase `u` prefix --
|
|
1182
1205
|
which is the compact form you pass to `zcap delegate --capability` to delegate
|
|
1183
1206
|
it
|
|
1184
1207
|
further. Pass `--save` to also write the capability to local wallet storage
|
|
@@ -1207,7 +1230,7 @@ Root capabilities are unsigned, so no key is needed:
|
|
|
1207
1230
|
"controller": "did:key:z6Mkfeco2NSEPeFV3DkjNSabaCza1EoS3CmqLb1eJ5BriiaR",
|
|
1208
1231
|
"invocationTarget": "https://example.com/api"
|
|
1209
1232
|
},
|
|
1210
|
-
"encoded": "
|
|
1233
|
+
"encoded": "ueyJAY29udGV4dCI6Imh0dHBzOi8vdzNpZC5vcmcvemNhcC92MSIsImlkIjoi..."
|
|
1211
1234
|
}
|
|
1212
1235
|
```
|
|
1213
1236
|
|
|
@@ -1217,7 +1240,7 @@ and a root capability grants all actions (it has no `allowedAction`).
|
|
|
1217
1240
|
|
|
1218
1241
|
#### Note about the `encoded` field
|
|
1219
1242
|
|
|
1220
|
-
The multibase- (that's the `
|
|
1243
|
+
The multibase- (that's the `u` prefix) and base64url-encoded JSON of the zcap
|
|
1221
1244
|
is returned, for convenience, in the `encoded` field.
|
|
1222
1245
|
|
|
1223
1246
|
This is done for easier "double-click to copy" and pasting into other tools,
|
|
@@ -1265,7 +1288,7 @@ To delegate from the root capability for a target, pass `--url` (the same
|
|
|
1265
1288
|
"proofValue": "z5tuwwdJE6VXLhf1v8SNAquBmMcJCD7zJ4bXDi6rh1Fk..."
|
|
1266
1289
|
}
|
|
1267
1290
|
},
|
|
1268
|
-
"encoded": "
|
|
1291
|
+
"encoded": "ueyJAY29udGV4dCI6WyJodHRwczovL3czaWQub3JnL3pjYXAvdjEi..."
|
|
1269
1292
|
}
|
|
1270
1293
|
```
|
|
1271
1294
|
|
|
@@ -1290,7 +1313,7 @@ metadata handle of a zcap saved in local wallet storage. Use
|
|
|
1290
1313
|
./di zcap delegate \
|
|
1291
1314
|
--did did:key:z6MknBxr... \
|
|
1292
1315
|
--delegatee did:key:z6Mks... \
|
|
1293
|
-
--capability
|
|
1316
|
+
--capability ueyJAY29udGV4dCI6WyJodHRwczovL3czaWQub3JnL3pjYXAvdjEi... \
|
|
1294
1317
|
--invocation-target https://example.com/documents/reports \
|
|
1295
1318
|
--allow read
|
|
1296
1319
|
```
|
|
@@ -1419,7 +1442,7 @@ valid until it expires (see `--ttl` / `--expires`).
|
|
|
1419
1442
|
### Wallet Attached Storage (WAS)
|
|
1420
1443
|
|
|
1421
1444
|
The `was` command group is a client for
|
|
1422
|
-
[Wallet Attached Storage](https://
|
|
1445
|
+
[Wallet Attached Storage](https://w3c-ccg.github.io/wallet-attached-storage-spec/)
|
|
1423
1446
|
servers, which organize content as `Space > Collection > Resource` behind
|
|
1424
1447
|
zcap-authorized HTTP. Every request is signed with a `did:key` DID stored in
|
|
1425
1448
|
the local wallet (saved with `did create --save`; Ed25519 keys only for now).
|
|
@@ -1498,7 +1521,7 @@ the server, or the local registry record with `--meta`:
|
|
|
1498
1521
|
|
|
1499
1522
|
`was space update` (alias: `configure`) upserts description fields
|
|
1500
1523
|
(`--name`), also refreshing the registry entry. `was space add` registers an
|
|
1501
|
-
|
|
1524
|
+
_existing_ remote space (a full space URL, or a bare id plus `--server`) in
|
|
1502
1525
|
the local registry, verifying it with a describe first. `was space meta
|
|
1503
1526
|
<space>` updates only a registered space's local metadata (`--handle` and/or
|
|
1504
1527
|
`--description`); the server-side space is untouched, and passing an empty
|
|
@@ -1689,12 +1712,114 @@ the zcap store (`~/.config/did-cli-wallet/zcaps/`):
|
|
|
1689
1712
|
"expires": "2027-06-11T17:30:00Z",
|
|
1690
1713
|
"proof": { ... }
|
|
1691
1714
|
},
|
|
1692
|
-
"encoded": "
|
|
1715
|
+
"encoded": "ueyJAY29udGV4dCI6..."
|
|
1693
1716
|
}
|
|
1694
1717
|
```
|
|
1695
1718
|
|
|
1696
1719
|
Hand the `encoded` string (or the JSON) to the delegatee out-of-band.
|
|
1697
1720
|
|
|
1721
|
+
#### Request a grant
|
|
1722
|
+
|
|
1723
|
+
`was request-grant` is the inverse of `was grant`, for the case where you are
|
|
1724
|
+
the one who needs access. It asks a user's wallet to delegate a capability on
|
|
1725
|
+
one of its public collections, and is what lets a program publish into someone
|
|
1726
|
+
else's storage without ever logging into their wallet.
|
|
1727
|
+
|
|
1728
|
+
The grantee key is minted by the command rather than passed in, so a script (or
|
|
1729
|
+
an LLM agent) driving the CLI never handles key material: the secret goes
|
|
1730
|
+
straight into local DID storage, and stdout carries only the capability. The
|
|
1731
|
+
approval link and the progress notes go to stderr; `--json` puts the DID, the
|
|
1732
|
+
handle, the link, and the capability into one object on stdout instead.
|
|
1733
|
+
|
|
1734
|
+
```
|
|
1735
|
+
./di was request-grant --exchange https://freewallet.cloud/spaces/ \
|
|
1736
|
+
--reason "Publish a demo page" --name "demo-publisher"
|
|
1737
|
+
Requesting "web" access for did:key:z6MkAgent...
|
|
1738
|
+
|
|
1739
|
+
Open this in your wallet to approve:
|
|
1740
|
+
|
|
1741
|
+
https://freewallet.cloud/workflows/ephemeral/exchanges/abc-123/protocols?iuv=1
|
|
1742
|
+
|
|
1743
|
+
Waiting for approval...
|
|
1744
|
+
```
|
|
1745
|
+
|
|
1746
|
+
If you know which wallet the user runs, `--wallet <url>` also prints a link
|
|
1747
|
+
that opens it straight onto the approval page for this request:
|
|
1748
|
+
|
|
1749
|
+
```
|
|
1750
|
+
./di was request-grant --exchange https://freewallet.cloud/spaces/ --wallet https://freewallet.me
|
|
1751
|
+
...
|
|
1752
|
+
Or open your wallet directly:
|
|
1753
|
+
|
|
1754
|
+
https://freewallet.me/#/external/request?url=https%3A%2F%2Ffreewallet.cloud%2F...
|
|
1755
|
+
```
|
|
1756
|
+
|
|
1757
|
+
The interaction URL is still printed beside it, since that is what a wallet on
|
|
1758
|
+
another device can be pointed at.
|
|
1759
|
+
|
|
1760
|
+
The user opens that link in their wallet and approves. The command then prints
|
|
1761
|
+
the capability it received (the same `u...` form `--capability` accepts) and
|
|
1762
|
+
files it in the zcap store under `--handle` (default `agent`), together with the
|
|
1763
|
+
minted key:
|
|
1764
|
+
|
|
1765
|
+
```
|
|
1766
|
+
Capability saved to ~/.config/did-cli-wallet/zcaps/urn_uuid_....json
|
|
1767
|
+
Granted. Use it with --capability agent, for example:
|
|
1768
|
+
di was put ./index.html --capability agent --did agent --resource index.html --content-type text/html
|
|
1769
|
+
ueyJAY29udGV4dCI6...
|
|
1770
|
+
```
|
|
1771
|
+
|
|
1772
|
+
Saving is what makes the grant usable: `--capability` resolves its signing key
|
|
1773
|
+
out of the local DID store, so a key held only for the run cannot sign the write
|
|
1774
|
+
that follows. `--no-save` prints the capability without keeping either half, for
|
|
1775
|
+
inspecting a grant you do not intend to use.
|
|
1776
|
+
|
|
1777
|
+
The signing DID is taken from `--did` first, then `WAS_DID`, and only then the
|
|
1778
|
+
capability's own `controller`. Naming the minted key explicitly
|
|
1779
|
+
(`--did agent`, matching the handle the grant was filed under) is therefore
|
|
1780
|
+
worth doing whenever `WAS_DID` is set in the environment, or the write is signed
|
|
1781
|
+
by your own DID and the server rejects it.
|
|
1782
|
+
|
|
1783
|
+
A run files the minted key and the received capability under the same handle, so
|
|
1784
|
+
a handle already taken by a stored DID or capability is refused before anything
|
|
1785
|
+
is minted; pass a different `--handle` for a second grant. Nothing is written
|
|
1786
|
+
until the grant arrives -- a request that is declined, expires, or times out
|
|
1787
|
+
leaves no key behind.
|
|
1788
|
+
|
|
1789
|
+
Options are `--collection <name>` (default `web`), `--action <verb...>` (default
|
|
1790
|
+
`GET HEAD PUT POST`), `--reason <text>` (shown to the user at the consent step),
|
|
1791
|
+
`--name <name>` (what the agent calls itself, shown to the user beside its
|
|
1792
|
+
key), `--wallet <url>` (a wallet base URL to print an approval deep link for),
|
|
1793
|
+
`--timeout <seconds>` (default 600, matching the server's exchange
|
|
1794
|
+
lifetime), `--handle` / `--description`, `--no-save`, `--json`, and
|
|
1795
|
+
`--exchange <url>` (or `WAS_SERVER_URL`).
|
|
1796
|
+
|
|
1797
|
+
`--exchange` names the WAS server that hosts the ephemeral exchange carrying
|
|
1798
|
+
the request. It is only the meeting point between this command and the wallet.
|
|
1799
|
+
The grant itself names its own target, whichever space the user's wallet picks,
|
|
1800
|
+
so the two servers need not be the same.
|
|
1801
|
+
|
|
1802
|
+
The end-to-end flow this command exists for -- an LLM agent drafting a page and
|
|
1803
|
+
publishing it to the user's own storage -- is scripted in
|
|
1804
|
+
[demo/agent-storage](demo/agent-storage/README.md), with the agent-facing
|
|
1805
|
+
version in the `publish-page` skill under `.claude/skills/`.
|
|
1806
|
+
|
|
1807
|
+
`--name` is self-declared, not verified: the wallet shows it as what the agent
|
|
1808
|
+
calls itself, next to the grantee key, so the user should still compare the
|
|
1809
|
+
key rather than trust the name alone. It is at most 64 characters and cannot
|
|
1810
|
+
contain control characters.
|
|
1811
|
+
|
|
1812
|
+
Two things the wallet decides, not this command:
|
|
1813
|
+
|
|
1814
|
+
- A public collection is only ever created public. If the named collection
|
|
1815
|
+
already exists and is not world-readable, the wallet cannot satisfy the
|
|
1816
|
+
request, and the approval comes back granting nothing.
|
|
1817
|
+
- The actions you ask for are a request, not an instruction. The wallet caps
|
|
1818
|
+
them by what the collection allows, and may grant fewer than you asked for.
|
|
1819
|
+
|
|
1820
|
+
The exchange lives on the server for ten minutes. After that the link is dead
|
|
1821
|
+
and the command reports it; run it again for a fresh one.
|
|
1822
|
+
|
|
1698
1823
|
#### Use a received capability
|
|
1699
1824
|
|
|
1700
1825
|
On the receiving side, `ls` / `get` / `put` / `rm` (and `resource
|
|
@@ -1706,21 +1831,32 @@ of:
|
|
|
1706
1831
|
- the capability id or metadata **handle of a zcap** stored in
|
|
1707
1832
|
`~/.config/did-cli-wallet/zcaps/`.
|
|
1708
1833
|
|
|
1709
|
-
Note that a `--capability` reference is
|
|
1834
|
+
Note that a `--capability` reference is _not_ a WAS path -- no space,
|
|
1710
1835
|
collection, or resource address is given (or needed). The capability itself
|
|
1711
1836
|
records what it grants access to in its `invocationTarget`, and that is what
|
|
1712
1837
|
the command operates on:
|
|
1713
1838
|
|
|
1714
|
-
- a capability granted on a **resource** drives `get` / `put` / `rm
|
|
1839
|
+
- a capability granted on a **resource** drives `get` / `put` / `rm` and
|
|
1840
|
+
`meta get` / `meta put`;
|
|
1715
1841
|
- one granted on a **collection** drives `ls`, `resource add`, and `rm`;
|
|
1716
1842
|
- one granted on a whole **space** drives `ls` and `rm`.
|
|
1717
1843
|
|
|
1718
|
-
A
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1844
|
+
A collection-scoped capability also reaches one resource inside it, named
|
|
1845
|
+
with `--resource <id>`: `get`, `put`, `meta get`, `meta put`, and `rm` then
|
|
1846
|
+
act on that id beneath the capability's collection (without the flag, `rm`
|
|
1847
|
+
deletes the collection itself). This is how a grant issued on a whole
|
|
1848
|
+
collection writes at an id you choose (`resource add` also takes a collection
|
|
1849
|
+
capability, but the server picks the id, so it cannot produce `index.html`).
|
|
1850
|
+
The resource handle inherits the collection's capability, so the request is
|
|
1851
|
+
still an invocation of the grant you received.
|
|
1852
|
+
|
|
1853
|
+
Any other depth mismatch (e.g. `get` with a space-scoped capability) is an
|
|
1854
|
+
input error, as is `--resource` without a capability to anchor it. The
|
|
1855
|
+
server URL is taken from the invocation target's origin, and the signing DID
|
|
1856
|
+
defaults to the capability's controller (the delegatee) when that DID is
|
|
1857
|
+
stored locally -- so usually no flags are needed at all.
|
|
1858
|
+
|
|
1859
|
+
In the examples below, `bob-share` is the metadata handle of a _stored zcap_
|
|
1724
1860
|
(not a space or collection handle): say Alice granted Bob `GET`/`PUT` on the
|
|
1725
1861
|
single resource `home/credentials/vc-1`, and the capability was saved with
|
|
1726
1862
|
`--save --handle bob-share` (on Alice's machine via `was grant --save`; on
|
|
@@ -1733,7 +1869,7 @@ Bob's machine he can pass the encoded string or a JSON file directly):
|
|
|
1733
1869
|
|
|
1734
1870
|
# Bob, with the encoded string he received out-of-band -- this reads the
|
|
1735
1871
|
# resource the capability targets (home/credentials/vc-1):
|
|
1736
|
-
./di was get --capability
|
|
1872
|
+
./di was get --capability ueyJAY29udGV4dCI6...
|
|
1737
1873
|
{
|
|
1738
1874
|
"name": "Alice"
|
|
1739
1875
|
}
|
|
@@ -1747,7 +1883,17 @@ Bob's machine he can pass the encoded string or a JSON file directly):
|
|
|
1747
1883
|
|
|
1748
1884
|
# Had the grant been on the whole collection (home/credentials), ls would
|
|
1749
1885
|
# list it and `resource add` could post new resources into it:
|
|
1750
|
-
./di was ls --capability
|
|
1886
|
+
./di was ls --capability ueyJAY29udGV4dCI6...
|
|
1887
|
+
|
|
1888
|
+
# ...and --resource picks one id inside that collection, so the write lands
|
|
1889
|
+
# at a name you choose rather than a server-generated one:
|
|
1890
|
+
./di was put ./index.html --capability ueyJAY29udGV4dCI6... \
|
|
1891
|
+
--resource index.html --content-type text/html
|
|
1892
|
+
./di was get --capability ueyJAY29udGV4dCI6... --resource index.html
|
|
1893
|
+
|
|
1894
|
+
# ...and the same flag deletes that one resource, rather than the whole
|
|
1895
|
+
# collection the capability targets:
|
|
1896
|
+
./di was rm --capability ueyJAY29udGV4dCI6... --resource index.html
|
|
1751
1897
|
```
|
|
1752
1898
|
|
|
1753
1899
|
#### Policies and public sharing
|
|
@@ -4,6 +4,28 @@
|
|
|
4
4
|
* `add-key` default purpose set (described in its help text).
|
|
5
5
|
*/
|
|
6
6
|
export declare const DEFAULT_VERIFICATION_PURPOSES: readonly ["authentication", "assertionMethod", "capabilityDelegation", "capabilityInvocation"];
|
|
7
|
+
/**
|
|
8
|
+
* Save the artifacts of a newly created DID: the DID document, its keys file,
|
|
9
|
+
* a metadata sidecar (creation timestamp plus the handle and description when
|
|
10
|
+
* given), and the key-to-DID association cache of any matching wallet keys.
|
|
11
|
+
*
|
|
12
|
+
* @param options {object}
|
|
13
|
+
* @param options.method {string}
|
|
14
|
+
* @param options.didDocument {object}
|
|
15
|
+
* @param options.exportedKeys {object}
|
|
16
|
+
* @param options.fingerprints {(string | undefined)[]}
|
|
17
|
+
* @param [options.handle] {string}
|
|
18
|
+
* @param [options.description] {string}
|
|
19
|
+
* @returns {Promise<void>}
|
|
20
|
+
*/
|
|
21
|
+
export declare function saveDidArtifacts({ method, didDocument, exportedKeys, fingerprints, handle, description }: {
|
|
22
|
+
method: string;
|
|
23
|
+
didDocument: object;
|
|
24
|
+
exportedKeys: object;
|
|
25
|
+
fingerprints: (string | undefined)[];
|
|
26
|
+
handle?: string;
|
|
27
|
+
description?: string;
|
|
28
|
+
}): Promise<void>;
|
|
7
29
|
/**
|
|
8
30
|
* Create a new DID of the given method (key, web, or webvh), optionally saving
|
|
9
31
|
* its document, keys, and metadata to local storage, and print it to stdout.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../../src/commands/did/create.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../../src/commands/did/create.ts"],"names":[],"mappings":"AAmCA;;;;GAIG;AACH,eAAO,MAAM,6BAA6B,gGAKhC,CAAA;AAEV;;;;;;;;;;;;;GAaG;AACH,wBAAsB,gBAAgB,CAAC,EACrC,MAAM,EACN,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,MAAM,EACN,WAAW,EACZ,EAAE;IACD,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,EAAE,MAAM,CAAA;IACnB,YAAY,EAAE,MAAM,CAAA;IACpB,YAAY,EAAE,CAAC,MAAM,GAAG,SAAS,CAAC,EAAE,CAAA;IACpC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,GAAG,OAAO,CAAC,IAAI,CAAC,CAkBhB;AA8ED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,SAAS,CAAC,OAAO,EAAE;IACvC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,GAAG,OAAO,CAAC,MAAM,CAAC,CA2XlB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,SAAS,CAAC,OAAO,EAAE;IACvC,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,GAAG,OAAO,CAAC,MAAM,CAAC,CAsIlB"}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* DID creation and key addition: `runCreate` (key, web, webvh) and `runAddKey`
|
|
3
|
-
* (add a verification key to a stored did:web). Both share the
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* `./webvh-update.js`.
|
|
3
|
+
* (add a verification key to a stored did:web). Both share the ECDSA-curve,
|
|
4
|
+
* non-deterministic-seed-guard, and output helpers at the top of this module;
|
|
5
|
+
* seed derivation comes from `../../keys/seed.js` and the webvh signer/sidecar
|
|
6
|
+
* plumbing is reused from `./webvh-update.js`.
|
|
7
7
|
*/
|
|
8
|
-
import { decodeSecretKeySeed, generateSecretKeySeed } from '@digitalcredentials/bnid';
|
|
9
8
|
import { driver } from '@interop/did-method-key';
|
|
10
9
|
import * as didWeb from '@interop/did-web-resolver';
|
|
11
10
|
import { createDID } from '@interop/did-method-webvh';
|
|
@@ -15,6 +14,7 @@ import { X25519KeyAgreementKey2020 } from '@interop/x25519-key-agreement-key';
|
|
|
15
14
|
import { loadDidDocument, loadDidKeys, saveDidLog, saveDidMeta, saveToDids } from '../../storage.js';
|
|
16
15
|
import { recordKeyDidAssociation } from '../../meta.js';
|
|
17
16
|
import { normalizeEcdsaCurve, SUPPORTED_ECDSA_CURVES, warnIfNotVcIssuanceCapable } from '../../keys/ecdsa.js';
|
|
17
|
+
import { deriveSeed } from '../../keys/seed.js';
|
|
18
18
|
import { exportUpdateKey, generateStagedKey } from '../../keys/webvh-update.js';
|
|
19
19
|
import { requireSaveForMetaFlags } from '../collection-command.js';
|
|
20
20
|
import { makeWebvhEntrySigner, persistUpdateKeysSidecar } from './webvh-update.js';
|
|
@@ -43,7 +43,7 @@ export const DEFAULT_VERIFICATION_PURPOSES = [
|
|
|
43
43
|
* @param [options.description] {string}
|
|
44
44
|
* @returns {Promise<void>}
|
|
45
45
|
*/
|
|
46
|
-
async function saveDidArtifacts({ method, didDocument, exportedKeys, fingerprints, handle, description }) {
|
|
46
|
+
export async function saveDidArtifacts({ method, didDocument, exportedKeys, fingerprints, handle, description }) {
|
|
47
47
|
const did = didDocument.id;
|
|
48
48
|
const docPath = await saveToDids({ method, did, data: didDocument });
|
|
49
49
|
await saveToDids({ method, did, suffix: 'keys', data: exportedKeys });
|
|
@@ -62,27 +62,6 @@ async function saveDidArtifacts({ method, didDocument, exportedKeys, fingerprint
|
|
|
62
62
|
}
|
|
63
63
|
console.error(`DID saved to ${docPath}`);
|
|
64
64
|
}
|
|
65
|
-
/**
|
|
66
|
-
* Resolve the secret key seed for a deterministic (Ed25519) key. With
|
|
67
|
-
* `--with-seed`, an existing `SECRET_KEY_SEED` env var is honored or a fresh
|
|
68
|
-
* seed generated; without it, only an explicitly set env seed is used. Returns
|
|
69
|
-
* the encoded seed (echoed back to the user) and its decoded bytes (for key
|
|
70
|
-
* generation).
|
|
71
|
-
*
|
|
72
|
-
* @param options {object}
|
|
73
|
-
* @param [options.withSeed] {boolean}
|
|
74
|
-
* @returns {Promise<{ secretKeySeed?: string, seedBytes?: Uint8Array }>}
|
|
75
|
-
*/
|
|
76
|
-
async function deriveSeed({ withSeed }) {
|
|
77
|
-
const envSeed = process.env.SECRET_KEY_SEED;
|
|
78
|
-
const secretKeySeed = withSeed
|
|
79
|
-
? (envSeed ?? (await generateSecretKeySeed()))
|
|
80
|
-
: envSeed;
|
|
81
|
-
const seedBytes = secretKeySeed
|
|
82
|
-
? decodeSecretKeySeed({ secretKeySeed })
|
|
83
|
-
: undefined;
|
|
84
|
-
return { secretKeySeed, seedBytes };
|
|
85
|
-
}
|
|
86
65
|
/**
|
|
87
66
|
* Guard a non-deterministic key type against `--with-seed`: ECDSA and X25519
|
|
88
67
|
* keys are generated non-deterministically and cannot be derived from a seed.
|