@agentcontextdistributionprotocol/acdp 0.3.0 → 0.4.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/index.d.ts +204 -8
- package/package.json +5 -5
package/index.d.ts
CHANGED
|
@@ -80,6 +80,25 @@ export interface PublishOpts {
|
|
|
80
80
|
* only — rejected on first-version publishes.
|
|
81
81
|
*/
|
|
82
82
|
expectedLineageId?: string
|
|
83
|
+
/**
|
|
84
|
+
* Explicit `acdp_version` string for the emitted request.
|
|
85
|
+
*
|
|
86
|
+
* **SDK default (since 0.2): `acdp_version` is emitted explicitly,
|
|
87
|
+
* set to the library's current ACDP protocol version
|
|
88
|
+
* (`acdp::ACDP_VERSION` — `"0.2.0"` as of this release).** Per
|
|
89
|
+
* RFC-ACDP-0001 §6 consumers treat an absent field as `"0.1.0"`,
|
|
90
|
+
* but the omitted and explicit forms are *different JCS preimages*
|
|
91
|
+
* and therefore hash differently — pick one form per lineage and
|
|
92
|
+
* never switch mid-lineage.
|
|
93
|
+
*/
|
|
94
|
+
acdpVersion?: string
|
|
95
|
+
/**
|
|
96
|
+
* When `true`, omit `acdp_version` entirely (the 0.1.x SDK default
|
|
97
|
+
* form). Use this only to reproduce hashes signed under the
|
|
98
|
+
* omitted form (e.g. the sig-001 golden vector); takes precedence
|
|
99
|
+
* over `acdpVersion`.
|
|
100
|
+
*/
|
|
101
|
+
omitAcdpVersion?: boolean
|
|
83
102
|
}
|
|
84
103
|
/**
|
|
85
104
|
* Options for `buildSupersedeRequest`. Any field omitted is carried
|
|
@@ -103,6 +122,18 @@ export interface SupersedeOpts {
|
|
|
103
122
|
dataPeriod?: string
|
|
104
123
|
/** Self-verifying `lin:sha256:<hex>` lineage id (v2+). */
|
|
105
124
|
expectedLineageId?: string
|
|
125
|
+
/**
|
|
126
|
+
* Explicit `acdp_version` string. **By default (since 0.2) the
|
|
127
|
+
* library's current ACDP protocol version (`acdp::ACDP_VERSION` —
|
|
128
|
+
* `"0.2.0"` as of this release) is emitted explicitly** — see
|
|
129
|
+
* `PublishOpts.acdpVersion`. Do not switch the form mid-lineage.
|
|
130
|
+
*/
|
|
131
|
+
acdpVersion?: string
|
|
132
|
+
/**
|
|
133
|
+
* When `true`, omit `acdp_version` entirely (the 0.1.x form);
|
|
134
|
+
* takes precedence over `acdpVersion`.
|
|
135
|
+
*/
|
|
136
|
+
omitAcdpVersion?: boolean
|
|
106
137
|
}
|
|
107
138
|
/** Stateless did:web string helpers. All methods are static. */
|
|
108
139
|
export declare class AcdpDid {
|
|
@@ -189,7 +220,8 @@ export declare class AcdpCanonicalizer {
|
|
|
189
220
|
static contentHash(jsonStr: string): string
|
|
190
221
|
}
|
|
191
222
|
/**
|
|
192
|
-
* An ACDP producer: an Ed25519 signing key and its
|
|
223
|
+
* An ACDP producer: an Ed25519 signing key and its DID identity
|
|
224
|
+
* (`did:web`, or `did:key` via the `*DidKey` factories — ACDP 0.2).
|
|
193
225
|
*
|
|
194
226
|
* All methods return wire-ready JSON strings the caller sends via its
|
|
195
227
|
* own HTTP client. No HTTP calls are made inside this class.
|
|
@@ -197,11 +229,38 @@ export declare class AcdpCanonicalizer {
|
|
|
197
229
|
export declare class AcdpProducer {
|
|
198
230
|
/** Generate a producer with a fresh random Ed25519 key (OsRng). */
|
|
199
231
|
static generate(agentDid: string, keyId: string): AcdpProducer
|
|
232
|
+
/**
|
|
233
|
+
* Generate a producer whose identity **is** its fresh Ed25519 key
|
|
234
|
+
* (`did:key`, ACDP 0.2). The `agentDid` and `keyId` are derived
|
|
235
|
+
* from the public key — no domain, no DID-document hosting.
|
|
236
|
+
* Consumers verify did:key contexts offline
|
|
237
|
+
* (`AcdpVerifier.verifyBodyOffline`), with no dependency on the
|
|
238
|
+
* producer's infrastructure remaining online.
|
|
239
|
+
*
|
|
240
|
+
* Tradeoff: did:key cannot rotate — a new key is a new identity,
|
|
241
|
+
* and `supersedes` requires the same `agent_id`, so lineage
|
|
242
|
+
* continuity ends with the key. Use `did:web` for long-lived
|
|
243
|
+
* organizational anchors; use did:key for ephemeral or
|
|
244
|
+
* archival-critical producers.
|
|
245
|
+
*/
|
|
246
|
+
static generateDidKey(): AcdpProducer
|
|
247
|
+
/**
|
|
248
|
+
* Construct a `did:key` producer from a 32-byte Ed25519 seed.
|
|
249
|
+
*
|
|
250
|
+
* Deterministic — the same seed always derives the same
|
|
251
|
+
* `agentDid` / `keyId`. The seed is the private key — protect it
|
|
252
|
+
* as such. See [`AcdpProducer::generate_did_key`] for the did:key
|
|
253
|
+
* rotation tradeoff.
|
|
254
|
+
*/
|
|
255
|
+
static fromSeedDidKey(seed: Buffer): AcdpProducer
|
|
200
256
|
/** Construct from a 32-byte Ed25519 seed (deterministic). */
|
|
201
257
|
static fromSeed(seed: Buffer, agentDid: string, keyId: string): AcdpProducer
|
|
202
|
-
/** The producer's DID (`did:web:…`). */
|
|
258
|
+
/** The producer's DID (`did:web:…` or `did:key:…`). */
|
|
203
259
|
get agentDid(): string
|
|
204
|
-
/**
|
|
260
|
+
/**
|
|
261
|
+
* The producer's signing-key DID URL (`did:web:…#key-1`, or the
|
|
262
|
+
* `did:key:z…#z…` self-fragment form).
|
|
263
|
+
*/
|
|
205
264
|
get keyId(): string
|
|
206
265
|
/**
|
|
207
266
|
* Raw Ed25519 public key as standard base64 (44 chars with padding).
|
|
@@ -216,12 +275,25 @@ export declare class AcdpProducer {
|
|
|
216
275
|
/**
|
|
217
276
|
* Build and sign a first-version PublishRequest. Returns the
|
|
218
277
|
* wire JSON string.
|
|
278
|
+
*
|
|
279
|
+
* **By default (since 0.2) `acdp_version` is emitted explicitly,
|
|
280
|
+
* set to the library's current ACDP protocol version
|
|
281
|
+
* (`acdp::ACDP_VERSION` — `"0.2.0"` as of this release).** Pass
|
|
282
|
+
* `omitAcdpVersion: true` to reproduce the 0.1.x omitted form (a
|
|
283
|
+
* distinct JCS preimage, so a distinct `content_hash`), or
|
|
284
|
+
* `acdpVersion` to pin another string.
|
|
219
285
|
*/
|
|
220
286
|
buildPublishRequest(opts: PublishOpts): string
|
|
221
287
|
/**
|
|
222
288
|
* Build and sign a supersession PublishRequest from a previous
|
|
223
289
|
* version's `Body` JSON. Version is propagated automatically
|
|
224
290
|
* (`previous.version + 1`) and `lineage_id` is carried forward.
|
|
291
|
+
*
|
|
292
|
+
* **By default (since 0.2) `acdp_version` is emitted explicitly,
|
|
293
|
+
* set to the library's current ACDP protocol version
|
|
294
|
+
* (`acdp::ACDP_VERSION` — `"0.2.0"` as of this release)** — see
|
|
295
|
+
* `buildPublishRequest`. Do not switch between the omitted and
|
|
296
|
+
* explicit forms mid-lineage.
|
|
225
297
|
*/
|
|
226
298
|
buildSupersedeRequest(previousBodyJson: string, opts: SupersedeOpts): string
|
|
227
299
|
/**
|
|
@@ -247,14 +319,30 @@ export declare class AcdpProducer {
|
|
|
247
319
|
export declare class AcdpP256Producer {
|
|
248
320
|
/** Generate a producer with a fresh random P-256 key (OsRng). */
|
|
249
321
|
static generate(agentDid: string, keyId: string): AcdpP256Producer
|
|
322
|
+
/**
|
|
323
|
+
* Generate a producer whose identity **is** its fresh P-256 key
|
|
324
|
+
* (`did:key`, ACDP 0.2). See [`AcdpProducer::generate_did_key`]
|
|
325
|
+
* for the did:key rotation tradeoff.
|
|
326
|
+
*/
|
|
327
|
+
static generateDidKey(): AcdpP256Producer
|
|
328
|
+
/**
|
|
329
|
+
* Construct a `did:key` producer from a 32-byte P-256 private
|
|
330
|
+
* scalar (big-endian). Deterministic — the same seed always
|
|
331
|
+
* derives the same `agentDid` / `keyId`. Throws if the bytes are
|
|
332
|
+
* not exactly 32 or are not a valid scalar.
|
|
333
|
+
*/
|
|
334
|
+
static fromSeedDidKey(seed: Buffer): AcdpP256Producer
|
|
250
335
|
/**
|
|
251
336
|
* Construct from a 32-byte P-256 private scalar (deterministic).
|
|
252
337
|
* Throws if the bytes are not exactly 32 or are not a valid scalar.
|
|
253
338
|
*/
|
|
254
339
|
static fromSeed(seed: Buffer, agentDid: string, keyId: string): AcdpP256Producer
|
|
255
|
-
/** The producer's DID (`did:web:…`). */
|
|
340
|
+
/** The producer's DID (`did:web:…` or `did:key:…`). */
|
|
256
341
|
get agentDid(): string
|
|
257
|
-
/**
|
|
342
|
+
/**
|
|
343
|
+
* The producer's signing-key DID URL (`did:web:…#key-1`, or the
|
|
344
|
+
* `did:key:z…#z…` self-fragment form).
|
|
345
|
+
*/
|
|
258
346
|
get keyId(): string
|
|
259
347
|
/**
|
|
260
348
|
* SEC1-uncompressed public key (`0x04 || x || y`, 65 bytes) as
|
|
@@ -289,14 +377,19 @@ export declare class AcdpP256Producer {
|
|
|
289
377
|
seedBytes(): Buffer
|
|
290
378
|
/**
|
|
291
379
|
* Build and sign a first-version PublishRequest. Returns the wire
|
|
292
|
-
* JSON string. Same surface as [`AcdpProducer::build_publish_request`]
|
|
293
|
-
*
|
|
380
|
+
* JSON string. Same surface as [`AcdpProducer::build_publish_request`]
|
|
381
|
+
* — including the explicit `acdp_version` default (the library's
|
|
382
|
+
* current ACDP protocol version, `"0.2.0"` as of this release) and
|
|
383
|
+
* the `acdpVersion` / `omitAcdpVersion` controls; only the
|
|
384
|
+
* signature algorithm differs.
|
|
294
385
|
*/
|
|
295
386
|
buildPublishRequest(opts: PublishOpts): string
|
|
296
387
|
/**
|
|
297
388
|
* Build and sign a supersession PublishRequest from a previous
|
|
298
389
|
* version's `Body` JSON. Same semantics as
|
|
299
|
-
* [`AcdpProducer::build_supersede_request`]
|
|
390
|
+
* [`AcdpProducer::build_supersede_request`], including the
|
|
391
|
+
* explicit `acdp_version` default (the library's current ACDP
|
|
392
|
+
* protocol version, `"0.2.0"` as of this release).
|
|
300
393
|
*/
|
|
301
394
|
buildSupersedeRequest(previousBodyJson: string, opts: SupersedeOpts): string
|
|
302
395
|
/**
|
|
@@ -399,4 +492,107 @@ export declare class AcdpVerifier {
|
|
|
399
492
|
* Returns `true` on success; throws on failure.
|
|
400
493
|
*/
|
|
401
494
|
static verifySignatureP256(pubKeySec1B64: string, sigB64: string, contentHash: string): boolean
|
|
495
|
+
/**
|
|
496
|
+
* Full offline verification of a retrieved `Body` from a `did:key`
|
|
497
|
+
* producer (ACDP 0.2) — structural validation, `content_hash`
|
|
498
|
+
* recomputation, key_id/agent_id binding, and signature check, all
|
|
499
|
+
* with no network.
|
|
500
|
+
*
|
|
501
|
+
* * `bodyJson` — the `body` object from a `FullContext` retrieval
|
|
502
|
+
* (the registry-assigned fields must be present).
|
|
503
|
+
*
|
|
504
|
+
* Throws for `did:web` bodies — those need DID-document
|
|
505
|
+
* resolution, which stays in JS land (resolve via `AcdpDid.webToUrl`
|
|
506
|
+
* + `fetch`, then use `verifySignature`).
|
|
507
|
+
*
|
|
508
|
+
* Returns `true` on success; throws on any failure.
|
|
509
|
+
*/
|
|
510
|
+
static verifyBodyOffline(bodyJson: string): boolean
|
|
511
|
+
/**
|
|
512
|
+
* Offline verification of a `PublishRequest` from a `did:key`
|
|
513
|
+
* producer (ACDP 0.2): recomputes the `content_hash` over the
|
|
514
|
+
* request's producer-controlled fields, then verifies the
|
|
515
|
+
* signature against the key embedded in the `did:key` itself.
|
|
516
|
+
*
|
|
517
|
+
* * `requestJson` — the full PublishRequest wire JSON (e.g. the
|
|
518
|
+
* string `buildPublishRequest` returned).
|
|
519
|
+
*
|
|
520
|
+
* Throws for non-`did:key` requests — `did:web` verification needs
|
|
521
|
+
* DID resolution, which stays in JS land by design.
|
|
522
|
+
*
|
|
523
|
+
* Returns `true` on success; throws on any failure.
|
|
524
|
+
*/
|
|
525
|
+
static verifyPublishRequestOffline(requestJson: string): boolean
|
|
526
|
+
/**
|
|
527
|
+
* Diagnose a `content_hash` mismatch (ACDP 0.2 divergence
|
|
528
|
+
* tooling). Probes the known cross-implementation divergence
|
|
529
|
+
* patterns — `acdp_version` omitted vs explicit, null-vs-absent
|
|
530
|
+
* optionals, sub-millisecond timestamps — and returns a
|
|
531
|
+
* human-readable report naming the matching pattern (or the
|
|
532
|
+
* recomputed hash and preimage when none matches).
|
|
533
|
+
*
|
|
534
|
+
* Never use this to *accept* a body; it is producer/SDK-author
|
|
535
|
+
* tooling for chasing "the hash that won't reproduce".
|
|
536
|
+
*/
|
|
537
|
+
static explainHashMismatch(bodyJson: string, expectedHash: string): string
|
|
538
|
+
/**
|
|
539
|
+
* The exact JCS canonical preimage hashed for `content_hash`,
|
|
540
|
+
* returned as a UTF-8 string. When two SDKs disagree on a hash,
|
|
541
|
+
* diffing their canonical preimages localizes the divergence in a
|
|
542
|
+
* way two opaque digests never can.
|
|
543
|
+
*/
|
|
544
|
+
static canonicalPreimage(bodyJson: string): string
|
|
545
|
+
/**
|
|
546
|
+
* SHA-256 fingerprint (`"sha256:<64-hex>"`) of a raw Ed25519
|
|
547
|
+
* public key, as carried in a registry receipt's
|
|
548
|
+
* `key_fingerprint` (ACDP 0.2).
|
|
549
|
+
*
|
|
550
|
+
* * `publicKeyB64` — standard base64 of the 32-byte raw key (the
|
|
551
|
+
* same shape as `AcdpProducer.publicKeyB64` /
|
|
552
|
+
* `ResolvedDidKey.publicKeyB64`).
|
|
553
|
+
*/
|
|
554
|
+
static fingerprintEd25519B64(publicKeyB64: string): string
|
|
555
|
+
/**
|
|
556
|
+
* Verify a registry receipt (ACDP 0.2, RFC-ACDP-0010): the
|
|
557
|
+
* canonical `created_at` byte-form check, the offline cross-checks
|
|
558
|
+
* (`ctx_id`, recomputed body hash, producer key fingerprint,
|
|
559
|
+
* ms-truncated `created_at`, `registry_did`/`origin_registry`
|
|
560
|
+
* consistency), then the Ed25519 signature check against the
|
|
561
|
+
* registry's receipt key — with the signature preimage hashed over
|
|
562
|
+
* the **raw wire JSON** of the receipt as received (minus
|
|
563
|
+
* `signature`), never a re-serialization of the parsed struct.
|
|
564
|
+
*
|
|
565
|
+
* Resolving `registry_did` to that key is the caller's job — DID
|
|
566
|
+
* resolution stays in JS land by design (resolve the registry's
|
|
567
|
+
* DID document via `AcdpDid.webToUrl` + `fetch`, extract the key
|
|
568
|
+
* with `AcdpDidDocument.keyForAlgorithm`).
|
|
569
|
+
*
|
|
570
|
+
* **Two checks remain the HOST's obligation** — this binding makes
|
|
571
|
+
* no HTTP calls and never sees the accompanying body:
|
|
572
|
+
*
|
|
573
|
+
* 1. **Serving-authority binding** — `receipt.registry_did` MUST
|
|
574
|
+
* equal `"did:web:" + <authority>` where `<authority>` is the
|
|
575
|
+
* authority the response was *actually fetched from*, not
|
|
576
|
+
* whatever the receipt claims.
|
|
577
|
+
* 2. **Body bindings** — the receipt's `lineage_id`,
|
|
578
|
+
* `origin_registry`, and `created_at` MUST equal the
|
|
579
|
+
* accompanying body's fields, and the `recomputedBodyHash`
|
|
580
|
+
* argument MUST be independently recomputed from that body
|
|
581
|
+
* (run `AcdpVerifier.verifyContentHash` first) — never the
|
|
582
|
+
* body's echoed `content_hash` field.
|
|
583
|
+
*
|
|
584
|
+
* * `receiptJson` — the `registry_receipt` object from a
|
|
585
|
+
* `FullContext` retrieval.
|
|
586
|
+
* * `registryPublicKeyB64` — standard base64 of the registry's
|
|
587
|
+
* 32-byte raw Ed25519 receipt key.
|
|
588
|
+
* * `expectedCtxId` — the ctx_id the caller actually requested.
|
|
589
|
+
* * `recomputedBodyHash` — the *independently recomputed* body
|
|
590
|
+
* hash, never the body's echoed `content_hash` field.
|
|
591
|
+
* * `producerKeyFingerprint` — fingerprint of the resolved
|
|
592
|
+
* producer key (see `fingerprintEd25519B64`).
|
|
593
|
+
*
|
|
594
|
+
* Returns `true` on success; throws with the failing check's
|
|
595
|
+
* message otherwise.
|
|
596
|
+
*/
|
|
597
|
+
static verifyReceipt(receiptJson: string, registryPublicKeyB64: string, expectedCtxId: string, recomputedBodyHash: string, producerKeyFingerprint: string): boolean
|
|
402
598
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentcontextdistributionprotocol/acdp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Agent Context Distribution Protocol — Node.js SDK",
|
|
5
5
|
"license": "MIT OR Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -47,9 +47,9 @@
|
|
|
47
47
|
"registry": "https://registry.npmjs.org/"
|
|
48
48
|
},
|
|
49
49
|
"optionalDependencies": {
|
|
50
|
-
"@agentcontextdistributionprotocol/acdp-darwin-x64": "0.
|
|
51
|
-
"@agentcontextdistributionprotocol/acdp-darwin-arm64": "0.
|
|
52
|
-
"@agentcontextdistributionprotocol/acdp-linux-x64-gnu": "0.
|
|
53
|
-
"@agentcontextdistributionprotocol/acdp-linux-arm64-gnu": "0.
|
|
50
|
+
"@agentcontextdistributionprotocol/acdp-darwin-x64": "0.4.0",
|
|
51
|
+
"@agentcontextdistributionprotocol/acdp-darwin-arm64": "0.4.0",
|
|
52
|
+
"@agentcontextdistributionprotocol/acdp-linux-x64-gnu": "0.4.0",
|
|
53
|
+
"@agentcontextdistributionprotocol/acdp-linux-arm64-gnu": "0.4.0"
|
|
54
54
|
}
|
|
55
55
|
}
|