@interop/did-cli 0.7.1 → 0.9.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 +130 -0
- package/README.md +335 -6
- package/dist/commands/did.d.ts.map +1 -1
- package/dist/commands/did.js +66 -18
- package/dist/commands/did.js.map +1 -1
- package/dist/commands/edv.d.ts +63 -0
- package/dist/commands/edv.d.ts.map +1 -0
- package/dist/commands/edv.js +627 -0
- package/dist/commands/edv.js.map +1 -0
- package/dist/commands/key.d.ts.map +1 -1
- package/dist/commands/key.js +87 -13
- package/dist/commands/key.js.map +1 -1
- package/dist/commands/was/collection.d.ts +121 -0
- package/dist/commands/was/collection.d.ts.map +1 -0
- package/dist/commands/was/collection.js +316 -0
- package/dist/commands/was/collection.js.map +1 -0
- package/dist/commands/was/policy.d.ts +50 -0
- package/dist/commands/was/policy.d.ts.map +1 -0
- package/dist/commands/was/policy.js +133 -0
- package/dist/commands/was/policy.js.map +1 -0
- package/dist/commands/was/publish.d.ts +67 -0
- package/dist/commands/was/publish.d.ts.map +1 -0
- package/dist/commands/was/publish.js +151 -0
- package/dist/commands/was/publish.js.map +1 -0
- package/dist/commands/was/resource.d.ts +148 -0
- package/dist/commands/was/resource.d.ts.map +1 -0
- package/dist/commands/was/resource.js +402 -0
- package/dist/commands/was/resource.js.map +1 -0
- package/dist/commands/was/shared.d.ts +156 -0
- package/dist/commands/was/shared.d.ts.map +1 -0
- package/dist/commands/was/shared.js +237 -0
- package/dist/commands/was/shared.js.map +1 -0
- package/dist/commands/was/space.d.ts +196 -0
- package/dist/commands/was/space.d.ts.map +1 -0
- package/dist/commands/was/space.js +516 -0
- package/dist/commands/was/space.js.map +1 -0
- package/dist/commands/was/tree.d.ts +44 -0
- package/dist/commands/was/tree.d.ts.map +1 -0
- package/dist/commands/was/tree.js +135 -0
- package/dist/commands/was/tree.js.map +1 -0
- package/dist/commands/was.d.ts +29 -496
- package/dist/commands/was.d.ts.map +1 -1
- package/dist/commands/was.js +84 -1473
- 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 +6 -20
- package/dist/commands/zcap.js.map +1 -1
- package/dist/edv/core.d.ts +60 -0
- package/dist/edv/core.d.ts.map +1 -0
- package/dist/edv/core.js +75 -0
- package/dist/edv/core.js.map +1 -0
- package/dist/edv/document.d.ts +25 -0
- package/dist/edv/document.d.ts.map +1 -0
- package/dist/edv/document.js +19 -0
- package/dist/edv/document.js.map +1 -0
- package/dist/edv/hmac.d.ts +26 -0
- package/dist/edv/hmac.d.ts.map +1 -0
- package/dist/edv/hmac.js +67 -0
- package/dist/edv/hmac.js.map +1 -0
- package/dist/edv/recipients.d.ts +65 -0
- package/dist/edv/recipients.d.ts.map +1 -0
- package/dist/edv/recipients.js +253 -0
- package/dist/edv/recipients.js.map +1 -0
- package/dist/edv/stream.d.ts +69 -0
- package/dist/edv/stream.d.ts.map +1 -0
- package/dist/edv/stream.js +169 -0
- package/dist/edv/stream.js.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/meta.d.ts +1 -0
- package/dist/meta.d.ts.map +1 -1
- package/dist/meta.js +1 -1
- package/dist/meta.js.map +1 -1
- package/dist/storage.d.ts +6 -4
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +6 -5
- package/dist/storage.js.map +1 -1
- package/dist/was/capability.d.ts +10 -13
- package/dist/was/capability.d.ts.map +1 -1
- package/dist/was/capability.js +1 -59
- package/dist/was/capability.js.map +1 -1
- package/dist/was/io.d.ts +14 -0
- package/dist/was/io.d.ts.map +1 -1
- package/dist/was/io.js +20 -7
- package/dist/was/io.js.map +1 -1
- package/dist/zcap/delegate.d.ts +2 -2
- package/dist/zcap/delegate.js +2 -2
- package/dist/zcap/resolve.d.ts +15 -0
- package/dist/zcap/resolve.d.ts.map +1 -0
- package/dist/zcap/resolve.js +55 -0
- package/dist/zcap/resolve.js.map +1 -0
- package/package.json +17 -14
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,135 @@
|
|
|
1
1
|
# History
|
|
2
2
|
|
|
3
|
+
## 0.9.0 - 2026-06-14
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- Implement `did get <did>` (alias: `resolve`), which resolves a DID to its DID
|
|
8
|
+
document through `@interop/security-document-loader`'s document loader
|
|
9
|
+
(did:key offline, did:web fetched). A DID URL (a `did#fragment` key id)
|
|
10
|
+
dereferences straight to its verification method. Unlike `did show`, which
|
|
11
|
+
reads local storage, `did get` resolves live.
|
|
12
|
+
- Add an `edv` command group with `encrypt` and `decrypt` subcommands
|
|
13
|
+
(Layer 1: raw JWE). `edv encrypt [file]` encrypts stdin or a file to one or
|
|
14
|
+
more X25519 recipients and emits a single flattened JWE (the `jwe` field of
|
|
15
|
+
an EDV Document) to stdout or an `-o` file (convention `*.jwe.json`);
|
|
16
|
+
`edv decrypt [file]` reverses it. Encryption is public-key (key-agreement)
|
|
17
|
+
only, via `@interop/minimal-cipher` with its default algorithm
|
|
18
|
+
(`ECDH-ES+A256KW` key wrap, `XC20P` content encryption). A recipient
|
|
19
|
+
(`-r/--recipient`, repeatable) is a raw X25519 `publicKeyMultibase`, a wallet
|
|
20
|
+
key fingerprint/handle, or a DID / DID URL (its `keyAgreement` key, typed
|
|
21
|
+
either `X25519KeyAgreementKey2020` or `Multikey`); `--recipient-file` reads a
|
|
22
|
+
key-document JSON. `--json` switches both commands
|
|
23
|
+
to object semantics. On decrypt, the secret key is given with `-k/--key` or
|
|
24
|
+
auto-selected from the wallet by matching a recipient `kid`; a non-recipient
|
|
25
|
+
key exits non-zero with a clear error. The full EDV Document envelope,
|
|
26
|
+
chunked streams, and HMAC-blinded indexing are deferred to Layer 2.
|
|
27
|
+
- Add EDV Document support to `edv` (Layer 2, Phase 1). `edv encrypt --document`
|
|
28
|
+
wraps the JWE in a full EDV Document envelope `{ id, sequence, indexed, jwe }`
|
|
29
|
+
(convention `*.edvdoc.json`), encrypting the input as the document `content`
|
|
30
|
+
with an optional `--meta <json>` object alongside it (both encrypted inside the
|
|
31
|
+
`jwe`); `id` is a fresh identity-multihash multibase value and `sequence`
|
|
32
|
+
starts at `0`, byte-faithful to `@interop/edv-client`'s `EdvClientCore` without
|
|
33
|
+
taking that dependency. `--update <file>` versions an existing document
|
|
34
|
+
(reusing its `id`, incrementing `sequence`, and merging its recipients).
|
|
35
|
+
`edv decrypt` detects an envelope automatically and emits its decrypted
|
|
36
|
+
`content` (reporting `meta`/`stream` on stderr); `--document` requires one.
|
|
37
|
+
Chunked streams and HMAC-blinded indexing remain deferred to later phases.
|
|
38
|
+
- Add chunked-stream support to `edv` (Layer 2, Phase 2). `edv encrypt --stream`
|
|
39
|
+
encrypts the input as a sequence of fixed-size chunks (`--chunk-size <bytes>`,
|
|
40
|
+
default 1 MiB) and writes a bundle directory (convention `*.edvdoc/`, so `-o`
|
|
41
|
+
is required): a `document.json` EDV Document carrying a cleartext
|
|
42
|
+
`stream: { sequence, chunks }` descriptor, plus one `chunks/<index>.jwe.json`
|
|
43
|
+
per chunk (`{ sequence, index, offset, jwe }`), mirroring how an EDV / WAS
|
|
44
|
+
server stores stream bytes separately from the document. `--meta` and
|
|
45
|
+
`--update` (a file or bundle) work as for `--document`. `edv decrypt`
|
|
46
|
+
recognizes a bundle directory, reassembles the chunks in order, and writes the
|
|
47
|
+
original bytes to `-o`/stdout (reporting `content`/`meta`/`stream` on stderr).
|
|
48
|
+
HMAC-blinded indexing remains deferred to Layer 2, Phase 3.
|
|
49
|
+
- Add HMAC-blinded indexing to `edv` (Layer 2, Phase 3). In
|
|
50
|
+
`--document`/`--stream` mode, `--index <attribute>` (repeatable; a dotted path
|
|
51
|
+
into `content`/`meta`) populates the envelope's `indexed` array with entries
|
|
52
|
+
whose attribute names and values are HMAC-blinded, so a document is searchable
|
|
53
|
+
the way an EDV / WAS server indexes it without the server learning the
|
|
54
|
+
cleartext. `--unique` marks every `--index` attribute unique; `--hmac <ref>`
|
|
55
|
+
selects the blinding key (auto-selected when the wallet holds exactly one). The
|
|
56
|
+
same key over the same value yields a stable blinded entry, matchable across
|
|
57
|
+
documents. The EDV Document envelope and its blinded `indexed` array are now
|
|
58
|
+
assembled and unwrapped by `@interop/edv-client`'s `EdvClientCore` (a new
|
|
59
|
+
dependency), converging on the reference implementation rather than the
|
|
60
|
+
hand-rolled envelope used in Phases 1-2.
|
|
61
|
+
- Add `key create --type hmac`, generating a `Sha256HmacKey2019` HMAC key (a
|
|
62
|
+
32-byte symmetric secret used to blind EDV index attributes) via
|
|
63
|
+
`@interop/data-integrity-core`'s `SHA256HMACKey`. The key has no public half;
|
|
64
|
+
it is serialized with its secret as an `oct` JWK and identified by a random
|
|
65
|
+
`urn:uuid:` id. HMAC keys list with an `hmac` type label, and `key show`
|
|
66
|
+
prints only their `id`/`type` (never the secret). Like ecdsa/x25519, HMAC
|
|
67
|
+
generation is non-deterministic, so `--with-seed` / `SECRET_KEY_SEED` are not
|
|
68
|
+
supported.
|
|
69
|
+
|
|
70
|
+
## 0.8.0 - 2026-06-13
|
|
71
|
+
|
|
72
|
+
### Added
|
|
73
|
+
|
|
74
|
+
- Add `key create --type x25519` support, generating an
|
|
75
|
+
`X25519KeyAgreementKey2020` (Curve25519 Diffie-Hellman) key pair via
|
|
76
|
+
`@interop/x25519-key-agreement-key`. Saved x25519 keys list with an `x25519`
|
|
77
|
+
type label and `key show` re-exports the public key only. Like ecdsa, x25519
|
|
78
|
+
generation is non-deterministic, so `--with-seed` / `SECRET_KEY_SEED` are not
|
|
79
|
+
supported.
|
|
80
|
+
- Add `did add-key --type x25519` support for `did:web`, adding an
|
|
81
|
+
`X25519KeyAgreementKey2020` to the DID document. Because x25519 keys are key
|
|
82
|
+
agreement (encryption) keys, they are wired into the `keyAgreement`
|
|
83
|
+
verification relationship only; a `--purpose` other than `keyAgreement` is
|
|
84
|
+
rejected, and (as with ecdsa) `--with-seed` is not supported.
|
|
85
|
+
- Add `was resource-meta get` and `was resource-meta put` (group alias
|
|
86
|
+
`meta`), surfacing the Resource Metadata endpoint (`GET`/`PUT .../meta`).
|
|
87
|
+
`get` prints the whole metadata object (server-managed `contentType`,
|
|
88
|
+
`size`, and timestamps plus the user-writable `custom` name/tags); a
|
|
89
|
+
missing/not-visible resource is reported as not-found. `put` updates
|
|
90
|
+
`custom`: `--name` and `--tag key=value` (repeatable) are non-destructive on
|
|
91
|
+
their own (they preserve the other field via the client's `setName` /
|
|
92
|
+
`setTags`), while passing both, or the `--json` escape hatch (inline JSON or
|
|
93
|
+
a file path), is a full `custom` replacement. Both verbs also accept
|
|
94
|
+
`--capability` targeting the resource.
|
|
95
|
+
- Add `was collection backend` and `was collection quota`, surfacing the
|
|
96
|
+
`GET /space/:spaceId/:collectionId/backend` and
|
|
97
|
+
`GET /space/:spaceId/:collectionId/quota` endpoints (the storage backend a
|
|
98
|
+
collection is stored on, and the collection's storage usage scoped to that
|
|
99
|
+
backend). Both render a table by default and take `--json` for the raw
|
|
100
|
+
response; a missing/not-visible collection is reported as not-found, and a
|
|
101
|
+
server (or backend) that does not implement the endpoint (a 501) as an error.
|
|
102
|
+
- Add `was space backends` and `was space quotas`, surfacing the
|
|
103
|
+
`GET /space/:spaceId/backends` and `GET /space/:spaceId/quotas` endpoints
|
|
104
|
+
(the storage backends available within a space, and the space's storage
|
|
105
|
+
report grouped by backend). Both render a table by default and take `--json`
|
|
106
|
+
for the raw response; a server that does not implement the endpoint (a 501)
|
|
107
|
+
is reported as an error.
|
|
108
|
+
- Add `ARCHITECTURE.md`, a codebase map (entry point, command-factory pattern,
|
|
109
|
+
module layout, and the command surface) for contributors, linked from
|
|
110
|
+
`CLAUDE.md` and the README.
|
|
111
|
+
- Add `CONTRIBUTING.md` as the canonical home for code-style and contribution
|
|
112
|
+
conventions (moved out of `CLAUDE.md`, which now imports it).
|
|
113
|
+
- Add `AGENTS.md` (an inline copy of `CONTRIBUTING.md`) so non-Claude coding
|
|
114
|
+
agents pick up the same project guidance.
|
|
115
|
+
- Add an Environment Variables table to the README consolidating `WALLET_DIR`,
|
|
116
|
+
`DIDS_DIR`, `SECRET_KEY_SEED`, `WAS_DID`, `WAS_SERVER_URL`, and
|
|
117
|
+
`ZCAP_CONTROLLER_KEY_SEED`.
|
|
118
|
+
|
|
119
|
+
### Changed
|
|
120
|
+
|
|
121
|
+
- `zcap delegate --capability` now also accepts the id or metadata handle of
|
|
122
|
+
a zcap saved in local wallet storage, in addition to a multibase string or
|
|
123
|
+
a JSON file path (the same resolution the `was` commands' `--capability`
|
|
124
|
+
flag uses; the shared resolver lives in `src/zcap/resolve.ts`).
|
|
125
|
+
- Split the `was` command module into `src/commands/was/` submodules (by noun:
|
|
126
|
+
`space`, `collection`, `resource`, `tree`, `policy`, `publish`, plus shared
|
|
127
|
+
helpers); `src/commands/was.ts` now holds only `makeWasCommand()`. Internal
|
|
128
|
+
refactor with no behavior change.
|
|
129
|
+
- Rename the `was resource list` positional from `<path>` to `<collection>`,
|
|
130
|
+
matching the sibling `was collection list <space>` and clarifying that the
|
|
131
|
+
argument is the parent collection being enumerated.
|
|
132
|
+
|
|
3
133
|
## 0.7.0-0.7.1 - 2026-06-11
|
|
4
134
|
|
|
5
135
|
### Changed
|
package/README.md
CHANGED
|
@@ -26,6 +26,21 @@ Help is available with the `--help/-h` command line option:
|
|
|
26
26
|
./di COMMAND -h
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
+
### Environment Variables
|
|
30
|
+
|
|
31
|
+
These environment variables configure storage locations and provide defaults
|
|
32
|
+
or secret-key seeds for individual commands. Each is also documented inline in
|
|
33
|
+
the relevant command section below.
|
|
34
|
+
|
|
35
|
+
| Variable | Used by | Purpose |
|
|
36
|
+
| --- | --- | --- |
|
|
37
|
+
| `WALLET_DIR` | all | Wallet collections directory (`keys/`, `zcaps/`, `credentials/`, `was-spaces/`). Defaults to `~/.config/did-cli-wallet/` (honors `XDG_CONFIG_HOME`). |
|
|
38
|
+
| `DIDS_DIR` | `did` | DID-documents directory. Defaults to `<WALLET_DIR>/dids/`. |
|
|
39
|
+
| `SECRET_KEY_SEED` | `key create`, `did create` | Multibase-encoded seed for deterministic key/DID generation. Not supported with `--type ecdsa` or `--type x25519`. |
|
|
40
|
+
| `WAS_DID` | `was` | Default signing DID (or stored-DID handle) when `--did` is omitted. |
|
|
41
|
+
| `WAS_SERVER_URL` | `was` | Default WAS server base URL when `--server` is omitted. |
|
|
42
|
+
| `ZCAP_CONTROLLER_KEY_SEED` | `zcap` | Controller signing-key seed for delegating capabilities. |
|
|
43
|
+
|
|
29
44
|
### Key Management
|
|
30
45
|
|
|
31
46
|
#### Create a key pair
|
|
@@ -66,7 +81,7 @@ SECRET_KEY_SEED=z1AXVyT6G1Qk3E9cMPkDYY6wVRpZjVGWAZ3TfrAgFZkX6bv ./di key create
|
|
|
66
81
|
```
|
|
67
82
|
|
|
68
83
|
Specify an explicit key type with `--type` (defaults to `ed25519`; supported:
|
|
69
|
-
`ed25519`, `ecdsa`):
|
|
84
|
+
`ed25519`, `ecdsa`, `x25519`, `hmac`):
|
|
70
85
|
|
|
71
86
|
```
|
|
72
87
|
SECRET_KEY_SEED=z1Aaj5A4UCsd... ./di key create --type ed25519
|
|
@@ -96,6 +111,49 @@ ECDSA keys are serialized as Multikey, the same as Ed25519. Note that ECDSA key
|
|
|
96
111
|
generation is non-deterministic (it cannot be derived from a seed), so
|
|
97
112
|
`--with-seed` and `SECRET_KEY_SEED` are not supported with `--type ecdsa`.
|
|
98
113
|
|
|
114
|
+
Generate an X25519 (Curve25519) key agreement key -- for Diffie-Hellman key
|
|
115
|
+
exchange / encryption, not signing -- with `--type x25519`:
|
|
116
|
+
|
|
117
|
+
```
|
|
118
|
+
./di key create --type x25519
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
It is serialized as an `X25519KeyAgreementKey2020` document with the public and
|
|
122
|
+
private key in multibase encoding:
|
|
123
|
+
|
|
124
|
+
```json
|
|
125
|
+
{
|
|
126
|
+
"type": "X25519KeyAgreementKey2020",
|
|
127
|
+
"publicKeyMultibase": "z6LS...",
|
|
128
|
+
"privateKeyMultibase": "z3we..."
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Like ECDSA, X25519 key generation is non-deterministic, so `--with-seed` and
|
|
133
|
+
`SECRET_KEY_SEED` are not supported with `--type x25519`.
|
|
134
|
+
|
|
135
|
+
Generate a `Sha256HmacKey2019` HMAC key -- a 32-byte symmetric secret used to
|
|
136
|
+
HMAC-blind EDV index attributes (see [Blinded indexing](#blinded-indexing---index))
|
|
137
|
+
-- with `--type hmac`:
|
|
138
|
+
|
|
139
|
+
```
|
|
140
|
+
./di key create --type hmac
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
It is serialized with the secret carried as an `oct` JWK (it has no public
|
|
144
|
+
half), identified by a random `urn:uuid:` id:
|
|
145
|
+
|
|
146
|
+
```json
|
|
147
|
+
{
|
|
148
|
+
"id": "urn:uuid:...",
|
|
149
|
+
"type": "Sha256HmacKey2019",
|
|
150
|
+
"secretKeyJwk": { "kty": "oct", "alg": "HS256", "k": "..." }
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
HMAC key generation is non-deterministic, so `--with-seed` and `SECRET_KEY_SEED`
|
|
155
|
+
are not supported with `--type hmac`.
|
|
156
|
+
|
|
99
157
|
Save the key to local wallet storage (`~/.config/did-cli-wallet/keys/` by default, or
|
|
100
158
|
`$WALLET_DIR/keys/` if set) with `--save`. A `.meta.json` metadata sidecar is
|
|
101
159
|
written next to the key, recording the creation timestamp; `--handle` (a short
|
|
@@ -376,10 +434,20 @@ By default the new key is Ed25519; pass `--type ecdsa` (with an optional
|
|
|
376
434
|
./di did add-key did:web:example.com --type ecdsa --curve p384
|
|
377
435
|
```
|
|
378
436
|
|
|
437
|
+
Pass `--type x25519` to add an X25519 (Curve25519) key agreement key. X25519
|
|
438
|
+
keys are encryption/key-exchange keys, not signing keys, so they are wired into
|
|
439
|
+
the `keyAgreement` relationship only -- a `--purpose` other than `keyAgreement`
|
|
440
|
+
is rejected:
|
|
441
|
+
|
|
442
|
+
```
|
|
443
|
+
./di did add-key did:web:example.com --type x25519
|
|
444
|
+
```
|
|
445
|
+
|
|
379
446
|
For Ed25519 keys, the new key is derived from a seed (as with `did create`):
|
|
380
447
|
pass `--with-seed` to generate (and print) a fresh seed, or set `SECRET_KEY_SEED`
|
|
381
|
-
to derive the key deterministically. ECDSA keys are not
|
|
382
|
-
`--with-seed` is not supported with `--type ecdsa
|
|
448
|
+
to derive the key deterministically. ECDSA and X25519 keys are not
|
|
449
|
+
seed-derivable, so `--with-seed` is not supported with `--type ecdsa` or
|
|
450
|
+
`--type x25519`:
|
|
383
451
|
|
|
384
452
|
```
|
|
385
453
|
./di did add-key did:web:example.com --with-seed
|
|
@@ -420,6 +488,33 @@ did:key:z6Mkr...
|
|
|
420
488
|
did:key:z6Mks...
|
|
421
489
|
```
|
|
422
490
|
|
|
491
|
+
#### Resolve a DID
|
|
492
|
+
|
|
493
|
+
Resolve a DID to its DID document through the security document loader. Unlike
|
|
494
|
+
`did show` (which reads local storage), `did get` resolves live: did:key is
|
|
495
|
+
resolved offline, did:web is fetched over HTTPS. Pass a DID URL (a
|
|
496
|
+
`did#fragment` key id) to dereference straight to its verification method:
|
|
497
|
+
|
|
498
|
+
```
|
|
499
|
+
./di did get did:key:z6Mkr...
|
|
500
|
+
{
|
|
501
|
+
"@context": [ ... ],
|
|
502
|
+
"id": "did:key:z6Mkr...",
|
|
503
|
+
"verificationMethod": [ ... ],
|
|
504
|
+
...
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
./di did get did:key:z6Mkr...#z6Mkr...
|
|
508
|
+
{
|
|
509
|
+
"id": "did:key:z6Mkr...#z6Mkr...",
|
|
510
|
+
"type": "Ed25519VerificationKey2020",
|
|
511
|
+
"controller": "did:key:z6Mkr...",
|
|
512
|
+
"publicKeyMultibase": "z6Mkr..."
|
|
513
|
+
}
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
Alias: `resolve`.
|
|
517
|
+
|
|
423
518
|
#### Show a DID
|
|
424
519
|
|
|
425
520
|
Display the DID document saved in local storage (via `did create --save`),
|
|
@@ -834,8 +929,9 @@ ZCAP_CONTROLLER_KEY_SEED=z1AZK4h5w5YZkKYEgqtcFfvSbWQ3tZ3ZFgmLsXMZsTVoeK7 \
|
|
|
834
929
|
```
|
|
835
930
|
|
|
836
931
|
To delegate an _existing_ capability further down the chain, pass it as
|
|
837
|
-
`--capability` instead of `--url` --
|
|
838
|
-
delegation
|
|
932
|
+
`--capability` instead of `--url` -- the `encoded` string from a previous
|
|
933
|
+
delegation, a path to a JSON file containing the capability, or the id or
|
|
934
|
+
metadata handle of a zcap saved in local wallet storage. Use
|
|
839
935
|
`--invocation-target` to attenuate (narrow) the parent's target to a sub-path:
|
|
840
936
|
|
|
841
937
|
```
|
|
@@ -1057,6 +1153,24 @@ delete pair:
|
|
|
1057
1153
|
server** (idempotent) and removes the registry entry;
|
|
1058
1154
|
- `was space forget <space>` removes only the local registry entry.
|
|
1059
1155
|
|
|
1156
|
+
`was space backends` lists the storage backends available within a space, and
|
|
1157
|
+
`was space quotas` shows the space's storage report grouped by backend (usage,
|
|
1158
|
+
limit, and any restricted actions). Both render a table by default and take
|
|
1159
|
+
`--json` for the raw response:
|
|
1160
|
+
|
|
1161
|
+
```
|
|
1162
|
+
./di was space backends home
|
|
1163
|
+
ID NAME MANAGED BY STORAGE MODE PERSISTENCE
|
|
1164
|
+
default Filesystem server document, blob durable
|
|
1165
|
+
|
|
1166
|
+
./di was space quotas home
|
|
1167
|
+
BACKEND STATE USAGE (B) LIMIT (B) RESTRICTED
|
|
1168
|
+
default (Filesystem) ok 2048 1048576
|
|
1169
|
+
```
|
|
1170
|
+
|
|
1171
|
+
A server that does not implement these endpoints (a 501) is reported as an
|
|
1172
|
+
error.
|
|
1173
|
+
|
|
1060
1174
|
#### Manage collections
|
|
1061
1175
|
|
|
1062
1176
|
The `collection` group (alias: `coll`) manages collections within a space.
|
|
@@ -1081,6 +1195,37 @@ credentials Credentials http://localhost:3002/space/8124...cf2e/credentials
|
|
|
1081
1195
|
Deleted http://localhost:3002/space/8124...cf2e/credentials on the server.
|
|
1082
1196
|
```
|
|
1083
1197
|
|
|
1198
|
+
`was collection backend` shows the storage backend a collection is stored on,
|
|
1199
|
+
and `was collection quota` shows the collection's storage usage scoped to that
|
|
1200
|
+
backend (state, usage, limit, and any restricted actions). Both render a table
|
|
1201
|
+
by default and take `--json` for the raw response:
|
|
1202
|
+
|
|
1203
|
+
```
|
|
1204
|
+
./di was collection backend home/credentials
|
|
1205
|
+
FIELD VALUE
|
|
1206
|
+
------------ --------------
|
|
1207
|
+
ID default
|
|
1208
|
+
Name Filesystem
|
|
1209
|
+
Managed By server
|
|
1210
|
+
Storage Mode document, blob
|
|
1211
|
+
Persistence durable
|
|
1212
|
+
|
|
1213
|
+
./di was collection quota home/credentials
|
|
1214
|
+
FIELD VALUE
|
|
1215
|
+
----------- --------------------
|
|
1216
|
+
Backend default (Filesystem)
|
|
1217
|
+
Managed By server
|
|
1218
|
+
State ok
|
|
1219
|
+
Usage (B) 2048
|
|
1220
|
+
Limit (B) 1048576
|
|
1221
|
+
Restricted
|
|
1222
|
+
Measured At 2026-06-13T00:00:00Z
|
|
1223
|
+
```
|
|
1224
|
+
|
|
1225
|
+
A missing or not-visible collection is reported as not-found; a server (or
|
|
1226
|
+
backend) that does not implement these endpoints (a 501) is reported as an
|
|
1227
|
+
error.
|
|
1228
|
+
|
|
1084
1229
|
#### Add and read resources
|
|
1085
1230
|
|
|
1086
1231
|
The `resource` group (alias: `res`) manages the content itself. Payloads come
|
|
@@ -1121,6 +1266,40 @@ files); a missing or not-visible resource prints
|
|
|
1121
1266
|
`list` renders the resources of a collection (`ID | CONTENT TYPE | URL`), and
|
|
1122
1267
|
`delete` (alias: `rm`) removes one (idempotent).
|
|
1123
1268
|
|
|
1269
|
+
#### Resource metadata (name and tags)
|
|
1270
|
+
|
|
1271
|
+
The `resource-meta` group (alias: `meta`) reads and updates a resource's
|
|
1272
|
+
metadata. `get` prints the whole metadata object -- the server-managed
|
|
1273
|
+
`contentType`, `size`, and timestamps plus the user-writable `custom` (its
|
|
1274
|
+
`name` and `tags`):
|
|
1275
|
+
|
|
1276
|
+
```
|
|
1277
|
+
./di was resource-meta get home/credentials/vc-1
|
|
1278
|
+
```
|
|
1279
|
+
|
|
1280
|
+
`put` updates the user-writable `custom`. `--name` sets the display name shown
|
|
1281
|
+
in collection listings and `--tag key=value` (repeatable) sets annotations;
|
|
1282
|
+
used on their own each is non-destructive -- `--name` preserves existing tags
|
|
1283
|
+
and `--tag` preserves the existing name:
|
|
1284
|
+
|
|
1285
|
+
```
|
|
1286
|
+
./di was resource-meta put home/credentials/vc-1 --name 'Diploma'
|
|
1287
|
+
./di was resource-meta put home/credentials/vc-1 --tag year=2026 --tag status=verified
|
|
1288
|
+
```
|
|
1289
|
+
|
|
1290
|
+
Giving both `--name` and `--tag` together replaces `custom` wholesale (any
|
|
1291
|
+
field you do not pass is cleared). The `--json` escape hatch takes the full
|
|
1292
|
+
`custom` object as inline JSON or a JSON file path, for the same full
|
|
1293
|
+
replacement (pass `--json '{}'` to clear everything):
|
|
1294
|
+
|
|
1295
|
+
```
|
|
1296
|
+
./di was resource-meta put home/credentials/vc-1 \
|
|
1297
|
+
--json '{"name":"Diploma","tags":{"year":"2026"}}'
|
|
1298
|
+
./di was resource-meta put home/credentials/vc-1 --json custom.json
|
|
1299
|
+
```
|
|
1300
|
+
|
|
1301
|
+
After a successful update the command prints the resulting metadata.
|
|
1302
|
+
|
|
1124
1303
|
#### Shorthand verbs
|
|
1125
1304
|
|
|
1126
1305
|
For day-to-day use, the top-level verbs dispatch on the path depth:
|
|
@@ -1298,9 +1477,159 @@ unless `WAS_TEST_SERVER_URL` points at a running server:
|
|
|
1298
1477
|
WAS_TEST_SERVER_URL=http://localhost:3002 npm run test:node
|
|
1299
1478
|
```
|
|
1300
1479
|
|
|
1480
|
+
### Encrypted Data (EDV)
|
|
1481
|
+
|
|
1482
|
+
The `edv` commands encrypt an object or file to one or more X25519 recipients
|
|
1483
|
+
and decrypt the result, using the EDV / [minimal-cipher](https://www.npmjs.com/package/@interop/minimal-cipher)
|
|
1484
|
+
serialization. The output is a single raw **JWE** (the `jwe` field of an EDV
|
|
1485
|
+
Document), written to stdout or an `-o` file -- by convention `*.jwe.json`.
|
|
1486
|
+
Encryption is public-key (key-agreement) only: there is no password mode. The
|
|
1487
|
+
algorithm is the library default, `ECDH-ES+A256KW` key wrap with `XC20P`
|
|
1488
|
+
(XChaCha20Poly1305) content encryption.
|
|
1489
|
+
|
|
1490
|
+
#### Encrypt
|
|
1491
|
+
|
|
1492
|
+
A recipient (`-r/--recipient`, repeatable, at least one required) is an X25519
|
|
1493
|
+
public key given as a raw `publicKeyMultibase` (starts `z6LS`), a wallet key
|
|
1494
|
+
fingerprint or handle, or a DID / DID URL (the DID's `keyAgreement` key; a DID
|
|
1495
|
+
with several keyAgreement keys needs the `did#fragment` form). A
|
|
1496
|
+
`--recipient-file <path>` is a key-document JSON file holding an X25519 public
|
|
1497
|
+
key.
|
|
1498
|
+
|
|
1499
|
+
Encrypt a JSON object (with `--json`, the input is parsed and encrypted as an
|
|
1500
|
+
object) to a stored x25519 key:
|
|
1501
|
+
|
|
1502
|
+
```
|
|
1503
|
+
./di key create --type x25519 --save --handle alice-kak
|
|
1504
|
+
echo '{"hello": "world"}' | ./di edv encrypt --json -r alice-kak -o secret.jwe.json
|
|
1505
|
+
```
|
|
1506
|
+
|
|
1507
|
+
Without `--json` the raw input bytes are encrypted. Encrypt to several
|
|
1508
|
+
recipients by repeating `-r`:
|
|
1509
|
+
|
|
1510
|
+
```
|
|
1511
|
+
./di edv encrypt photo.png -r alice-kak -r z6LSr... -o photo.jwe.json
|
|
1512
|
+
```
|
|
1513
|
+
|
|
1514
|
+
#### Decrypt
|
|
1515
|
+
|
|
1516
|
+
`-k/--key` is the X25519 secret key (fingerprint or handle) to decrypt with;
|
|
1517
|
+
when omitted, the matching stored key is auto-selected from the wallet. Use
|
|
1518
|
+
`--json` to pretty-print the decrypted object, and `-o` to write to a file.
|
|
1519
|
+
Only plaintext is ever written; secret key material stays in the key store.
|
|
1520
|
+
|
|
1521
|
+
```
|
|
1522
|
+
./di edv decrypt secret.jwe.json --json
|
|
1523
|
+
{
|
|
1524
|
+
"hello": "world"
|
|
1525
|
+
}
|
|
1526
|
+
|
|
1527
|
+
./di edv decrypt photo.jwe.json -k alice-kak -o photo.png
|
|
1528
|
+
```
|
|
1529
|
+
|
|
1530
|
+
Decryption with a key that is not a recipient exits non-zero with a clear
|
|
1531
|
+
error rather than emitting garbage.
|
|
1532
|
+
|
|
1533
|
+
#### EDV Documents (`--document`)
|
|
1534
|
+
|
|
1535
|
+
By default `edv encrypt` emits a bare JWE. With `-d/--document` it wraps that JWE
|
|
1536
|
+
in a full **EDV Document** envelope -- `{ id, sequence, indexed, jwe }`, the
|
|
1537
|
+
shape an EDV / WAS server stores -- written by convention to `*.edvdoc.json`. The
|
|
1538
|
+
input is encrypted as the document's `content`; an optional `--meta <json>`
|
|
1539
|
+
object is encrypted alongside it (both live inside the `jwe`, so only `id`,
|
|
1540
|
+
`sequence`, and `indexed` stay in cleartext). The `id` is a fresh
|
|
1541
|
+
identity-multihash multibase value and `sequence` starts at `0`. Index entries
|
|
1542
|
+
(`indexed`) are always `[]` for now; HMAC-blinded indexing and chunked streams
|
|
1543
|
+
are later phases.
|
|
1544
|
+
|
|
1545
|
+
```
|
|
1546
|
+
echo '{"name": "alice"}' | \
|
|
1547
|
+
./di edv encrypt --document -r alice-kak --meta '{"tag":"demo"}' -o doc.edvdoc.json
|
|
1548
|
+
```
|
|
1549
|
+
|
|
1550
|
+
`--update <file>` versions an existing document: it reuses that document's `id`,
|
|
1551
|
+
increments its `sequence`, and merges its recipients (so you can add a recipient
|
|
1552
|
+
without re-listing the existing ones) before re-encrypting the new content.
|
|
1553
|
+
|
|
1554
|
+
```
|
|
1555
|
+
echo '{"name": "alice", "v": 2}' | \
|
|
1556
|
+
./di edv encrypt --document -r bob-kak --update doc.edvdoc.json -o doc.v2.edvdoc.json
|
|
1557
|
+
```
|
|
1558
|
+
|
|
1559
|
+
`edv decrypt` detects an EDV Document automatically and prints its decrypted
|
|
1560
|
+
`content` (any `meta`/`stream` is reported on stderr); pass `-d/--document` to
|
|
1561
|
+
require an envelope and reject a bare JWE.
|
|
1562
|
+
|
|
1563
|
+
```
|
|
1564
|
+
./di edv decrypt doc.edvdoc.json
|
|
1565
|
+
{
|
|
1566
|
+
"name": "alice"
|
|
1567
|
+
}
|
|
1568
|
+
```
|
|
1569
|
+
|
|
1570
|
+
#### Chunked streams (`--stream`)
|
|
1571
|
+
|
|
1572
|
+
For large inputs, `-s/--stream` encrypts the bytes as a sequence of fixed-size
|
|
1573
|
+
chunks rather than one JWE. The output is a **bundle directory** (convention
|
|
1574
|
+
`*.edvdoc/`, so `-o` is required) holding `document.json` -- an EDV Document whose
|
|
1575
|
+
cleartext `stream: { sequence, chunks }` descriptor records the chunk count -- and
|
|
1576
|
+
one `chunks/<index>.jwe.json` per chunk. This mirrors how an EDV / WAS server
|
|
1577
|
+
stores stream bytes as resources separate from the document. `--chunk-size
|
|
1578
|
+
<bytes>` sets the chunk size (default 1 MiB); `--meta` and `--update` work as for
|
|
1579
|
+
`--document`.
|
|
1580
|
+
|
|
1581
|
+
```
|
|
1582
|
+
./di edv encrypt photo.png --stream -r alice-kak --chunk-size 1048576 -o photo.edvdoc/
|
|
1583
|
+
```
|
|
1584
|
+
|
|
1585
|
+
`edv decrypt` recognizes a bundle directory, reassembles the chunks in order, and
|
|
1586
|
+
writes the original bytes to `-o`/stdout (the document's `content`/`meta`/`stream`
|
|
1587
|
+
are reported on stderr).
|
|
1588
|
+
|
|
1589
|
+
```
|
|
1590
|
+
./di edv decrypt photo.edvdoc/ -o photo.png
|
|
1591
|
+
```
|
|
1592
|
+
|
|
1593
|
+
#### Blinded indexing (`--index`)
|
|
1594
|
+
|
|
1595
|
+
In `--document`/`--stream` mode, `--index <attribute>` populates the envelope's
|
|
1596
|
+
`indexed` array so a document is searchable the way an EDV / WAS server indexes
|
|
1597
|
+
it -- without the server learning the cleartext. The attribute name and value
|
|
1598
|
+
are **HMAC-blinded**: a `Sha256HmacKey2019` key signs them, so the same key over
|
|
1599
|
+
the same value always yields the same opaque entry (matchable across documents),
|
|
1600
|
+
but the cleartext never leaves the client.
|
|
1601
|
+
|
|
1602
|
+
First create an HMAC key in the wallet (a 32-byte secret, no public half):
|
|
1603
|
+
|
|
1604
|
+
```
|
|
1605
|
+
./di key create --type hmac --save --handle vault-index
|
|
1606
|
+
```
|
|
1607
|
+
|
|
1608
|
+
Then declare one or more indexable attribute paths (dotted paths into `content`
|
|
1609
|
+
or `meta`). The HMAC key is auto-selected when the wallet holds exactly one;
|
|
1610
|
+
otherwise pass `--hmac <id|handle>`. `--unique` marks every `--index` attribute
|
|
1611
|
+
as unique.
|
|
1612
|
+
|
|
1613
|
+
```
|
|
1614
|
+
echo '{"type":"Person","name":"alice"}' | \
|
|
1615
|
+
./di edv encrypt --document --json -r alice-kak \
|
|
1616
|
+
--index content.type --index content.name --hmac vault-index -o doc.edvdoc.json
|
|
1617
|
+
```
|
|
1618
|
+
|
|
1619
|
+
The resulting envelope carries `indexed: [{ hmac: { id, type }, sequence,
|
|
1620
|
+
attributes: [{ name, value, unique? }] }]`, where each `name`/`value` is the
|
|
1621
|
+
blinded (opaque) form. The envelope and its blinded entries are assembled by
|
|
1622
|
+
[`@interop/edv-client`](https://www.npmjs.com/package/@interop/edv-client)'s
|
|
1623
|
+
`EdvClientCore`, so they match what an EDV server expects byte-for-byte.
|
|
1624
|
+
|
|
1301
1625
|
## Contribute
|
|
1302
1626
|
|
|
1303
|
-
PRs accepted.
|
|
1627
|
+
PRs accepted. Please follow the code-style and contribution conventions in
|
|
1628
|
+
[CONTRIBUTING.md](CONTRIBUTING.md).
|
|
1629
|
+
|
|
1630
|
+
For a map of the codebase -- the module layout, the command-factory pattern,
|
|
1631
|
+
and the build/test commands -- see [ARCHITECTURE.md](ARCHITECTURE.md). Storage
|
|
1632
|
+
layout is documented in [STORAGE.md](STORAGE.md).
|
|
1304
1633
|
|
|
1305
1634
|
If editing the Readme, please conform to the
|
|
1306
1635
|
[standard-readme](https://github.com/RichardLitt/standard-readme) specification.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"did.d.ts","sourceRoot":"","sources":["../../src/commands/did.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"did.d.ts","sourceRoot":"","sources":["../../src/commands/did.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AA0FnC,wBAAgB,cAAc,IAAI,OAAO,CA0uBxC"}
|