@metalabel/dfos-web-relay 0.9.0 → 0.11.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/README.md +12 -13
- package/dist/index.d.ts +59 -23
- package/dist/index.js +322 -174
- package/dist/serve.js +28 -1
- package/openapi.yaml +84 -50
- package/package.json +8 -8
package/README.md
CHANGED
|
@@ -38,19 +38,18 @@ serve({ port: 4444 });
|
|
|
38
38
|
|
|
39
39
|
## Routes
|
|
40
40
|
|
|
41
|
-
| Method | Path | Description
|
|
42
|
-
| ------ | ---------------------------------------- |
|
|
43
|
-
| `GET` | `/.well-known/dfos-relay` | Relay metadata (DID, protocol version)
|
|
44
|
-
| `POST` | `/operations` | Submit signed operations (identity, content,
|
|
45
|
-
| `GET` | `/identities/:did` | Get identity chain state and operation log
|
|
46
|
-
| `GET` | `/content/:contentId` | Get content chain state and operation log
|
|
47
|
-
| `GET` | `/operations/:cid` | Get a single operation by CID
|
|
48
|
-
| `GET` | `/
|
|
49
|
-
| `GET` | `/
|
|
50
|
-
| `
|
|
51
|
-
| `
|
|
52
|
-
| `GET` | `/content/:contentId/blob`
|
|
53
|
-
| `GET` | `/content/:contentId/blob/:ref` | Download blob at specific operation ref |
|
|
41
|
+
| Method | Path | Description |
|
|
42
|
+
| ------ | ---------------------------------------- | ----------------------------------------------------------- |
|
|
43
|
+
| `GET` | `/.well-known/dfos-relay` | Relay metadata (DID, protocol version) |
|
|
44
|
+
| `POST` | `/operations` | Submit signed operations (identity, content, countersig) |
|
|
45
|
+
| `GET` | `/identities/:did` | Get identity chain state and operation log |
|
|
46
|
+
| `GET` | `/content/:contentId` | Get content chain state and operation log |
|
|
47
|
+
| `GET` | `/operations/:cid` | Get a single operation by CID |
|
|
48
|
+
| `GET` | `/countersignatures/:cid` | Get countersignatures for an operation |
|
|
49
|
+
| `GET` | `/operations/:cid/countersignatures` | Same as above (alias) |
|
|
50
|
+
| `PUT` | `/content/:contentId/blob/:operationCID` | Upload blob (auth required) |
|
|
51
|
+
| `GET` | `/content/:contentId/blob` | Download blob at head (standing auth, or auth + credential) |
|
|
52
|
+
| `GET` | `/content/:contentId/blob/:ref` | Download blob at specific operation ref |
|
|
54
53
|
|
|
55
54
|
## Blob Authorization
|
|
56
55
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { VerifiedIdentity, VerifiedContentChain
|
|
1
|
+
import { VerifiedIdentity, VerifiedContentChain } from '@metalabel/dfos-protocol/chain';
|
|
2
2
|
import { Attenuation } from '@metalabel/dfos-protocol/credentials';
|
|
3
3
|
import { Hono } from 'hono';
|
|
4
4
|
|
|
@@ -21,6 +21,12 @@ interface RelayOptions {
|
|
|
21
21
|
peers?: PeerConfig[];
|
|
22
22
|
/** Injected peer client — if omitted, a default HTTP implementation is used */
|
|
23
23
|
peerClient?: PeerClient;
|
|
24
|
+
/**
|
|
25
|
+
* Max lifetime (exp-iat, seconds) honored on a self-signed auth token.
|
|
26
|
+
* Default 86400 (24h); a value <= 0 disables the ceiling. Applies only to auth
|
|
27
|
+
* tokens, never to DFOS credentials.
|
|
28
|
+
*/
|
|
29
|
+
maxAuthTokenTTLSeconds?: number;
|
|
24
30
|
}
|
|
25
31
|
interface PeerConfig {
|
|
26
32
|
url: string;
|
|
@@ -84,18 +90,12 @@ interface StoredContentChain {
|
|
|
84
90
|
lastCreatedAt: string;
|
|
85
91
|
state: VerifiedContentChain;
|
|
86
92
|
}
|
|
87
|
-
interface StoredBeacon {
|
|
88
|
-
did: string;
|
|
89
|
-
jwsToken: string;
|
|
90
|
-
beaconCID: string;
|
|
91
|
-
state: VerifiedBeacon;
|
|
92
|
-
}
|
|
93
93
|
interface StoredOperation {
|
|
94
94
|
cid: string;
|
|
95
95
|
jwsToken: string;
|
|
96
96
|
/** Which chain type this operation belongs to */
|
|
97
|
-
chainType: 'identity' | 'content' | 'artifact' | '
|
|
98
|
-
/** The chain identifier — DID for identity/
|
|
97
|
+
chainType: 'identity' | 'content' | 'artifact' | 'countersign' | 'revocation' | 'credential';
|
|
98
|
+
/** The chain identifier — DID for identity/artifact, contentId for content, targetCID for countersign */
|
|
99
99
|
chainId: string;
|
|
100
100
|
}
|
|
101
101
|
/** Key for blob storage — deduplicates across chains sharing the same document */
|
|
@@ -111,7 +111,7 @@ interface LogEntry {
|
|
|
111
111
|
chainId: string;
|
|
112
112
|
}
|
|
113
113
|
/** All operation kinds in the protocol */
|
|
114
|
-
type OperationKind = 'identity-op' | 'content-op' | '
|
|
114
|
+
type OperationKind = 'identity-op' | 'content-op' | 'artifact' | 'countersign' | 'revocation' | 'credential';
|
|
115
115
|
interface StoredRevocation {
|
|
116
116
|
cid: string;
|
|
117
117
|
issuerDID: string;
|
|
@@ -150,8 +150,6 @@ interface RelayStore {
|
|
|
150
150
|
putIdentityChain(chain: StoredIdentityChain): Promise<void>;
|
|
151
151
|
getContentChain(contentId: string): Promise<StoredContentChain | undefined>;
|
|
152
152
|
putContentChain(chain: StoredContentChain): Promise<void>;
|
|
153
|
-
getBeacon(did: string): Promise<StoredBeacon | undefined>;
|
|
154
|
-
putBeacon(beacon: StoredBeacon): Promise<void>;
|
|
155
153
|
getBlob(key: BlobKey): Promise<Uint8Array | undefined>;
|
|
156
154
|
putBlob(key: BlobKey, data: Uint8Array): Promise<void>;
|
|
157
155
|
getCountersignatures(operationCID: string): Promise<string[]>;
|
|
@@ -236,6 +234,14 @@ interface IngestionResult {
|
|
|
236
234
|
kind?: OperationKind;
|
|
237
235
|
/** Chain identifier if applicable */
|
|
238
236
|
chainId?: string;
|
|
237
|
+
/**
|
|
238
|
+
* Structured dependency-failure signal. When true, the rejection is due to a
|
|
239
|
+
* missing dependency that may arrive later via sync or gossip, so the
|
|
240
|
+
* sequencer must keep the op pending (retryable) rather than durably reject
|
|
241
|
+
* it. This is the discriminator the sequencer branches on — NOT substring
|
|
242
|
+
* matching of the human-readable `error` string.
|
|
243
|
+
*/
|
|
244
|
+
dependencyMissing?: boolean;
|
|
239
245
|
}
|
|
240
246
|
|
|
241
247
|
/**
|
|
@@ -247,6 +253,20 @@ interface IngestionResult {
|
|
|
247
253
|
* they are available via the relay's proof plane routes.
|
|
248
254
|
*/
|
|
249
255
|
declare const bootstrapRelayIdentity: (store: RelayStore) => Promise<RelayIdentity>;
|
|
256
|
+
/**
|
|
257
|
+
* Bootstrap a relay identity from an EXISTING key + key ID, with optional pinned
|
|
258
|
+
* timestamps and profile name. Used for deterministic bootstrap — e.g. the
|
|
259
|
+
* dual-relay parity harness pins one key + one createdAt across both twins so
|
|
260
|
+
* the relay's own genesis + profile log entries are byte-identical, and durable
|
|
261
|
+
* relays that reload their key from storage. Mirrors the Go twin's
|
|
262
|
+
* BootstrapRelayIdentityFromKey.
|
|
263
|
+
*/
|
|
264
|
+
declare const bootstrapRelayIdentityFromKey: (store: RelayStore, params: {
|
|
265
|
+
privateKey: Uint8Array;
|
|
266
|
+
keyId: string;
|
|
267
|
+
name?: string;
|
|
268
|
+
createdAt?: string;
|
|
269
|
+
}) => Promise<RelayIdentity>;
|
|
250
270
|
|
|
251
271
|
/**
|
|
252
272
|
* Create an HTTP-based PeerClient.
|
|
@@ -265,6 +285,13 @@ interface CreatedRelay {
|
|
|
265
285
|
/** Sync operations from all configured sync peers (call on a schedule) */
|
|
266
286
|
syncFromPeers: () => Promise<void>;
|
|
267
287
|
}
|
|
288
|
+
/**
|
|
289
|
+
* Split items into batches of at most `size`, preserving order with no loss.
|
|
290
|
+
* gossip() uses this to stay within the receiver's per-batch cap; exported so
|
|
291
|
+
* the split behavior is directly testable (mirrors Go's maxGossipBatch chunking,
|
|
292
|
+
* whose TestGossipChunksLargeBatches drives the split directly).
|
|
293
|
+
*/
|
|
294
|
+
declare const chunkOps: <T>(items: T[], size: number) => T[][];
|
|
268
295
|
/**
|
|
269
296
|
* Create a DFOS web relay Hono application
|
|
270
297
|
*
|
|
@@ -285,7 +312,6 @@ declare class MemoryRelayStore implements RelayStore {
|
|
|
285
312
|
private operations;
|
|
286
313
|
private identityChains;
|
|
287
314
|
private contentChains;
|
|
288
|
-
private beacons;
|
|
289
315
|
private blobs;
|
|
290
316
|
private countersignatures;
|
|
291
317
|
private operationLog;
|
|
@@ -300,8 +326,6 @@ declare class MemoryRelayStore implements RelayStore {
|
|
|
300
326
|
putIdentityChain(chain: StoredIdentityChain): Promise<void>;
|
|
301
327
|
getContentChain(contentId: string): Promise<StoredContentChain | undefined>;
|
|
302
328
|
putContentChain(chain: StoredContentChain): Promise<void>;
|
|
303
|
-
getBeacon(did: string): Promise<StoredBeacon | undefined>;
|
|
304
|
-
putBeacon(beacon: StoredBeacon): Promise<void>;
|
|
305
329
|
getBlob(key: BlobKey): Promise<Uint8Array | undefined>;
|
|
306
330
|
putBlob(key: BlobKey, data: Uint8Array): Promise<void>;
|
|
307
331
|
getCountersignatures(operationCID: string): Promise<string[]>;
|
|
@@ -346,6 +370,13 @@ declare class MemoryRelayStore implements RelayStore {
|
|
|
346
370
|
resetSequencer(): Promise<void>;
|
|
347
371
|
}
|
|
348
372
|
|
|
373
|
+
/**
|
|
374
|
+
* Derive the operation CID from a JWS token by re-encoding the decoded payload.
|
|
375
|
+
* Returns the empty string for an undecodable token. Used at verify-failure
|
|
376
|
+
* sites so a rejection still carries a CID and can be durably rejected by the
|
|
377
|
+
* sequencer (instead of being skipped forever by `if (!res.cid) continue`).
|
|
378
|
+
*/
|
|
379
|
+
declare const computeOpCID: (jwsToken: string) => Promise<string>;
|
|
349
380
|
/**
|
|
350
381
|
* Create a key resolver that looks up Ed25519 public keys from identity chains
|
|
351
382
|
* in the store. Used for chain re-verification during ingestion.
|
|
@@ -390,6 +421,11 @@ declare const createHistoricalIdentityResolver: (store: RelayStore) => (did: str
|
|
|
390
421
|
}[];
|
|
391
422
|
did: string;
|
|
392
423
|
isDeleted: boolean;
|
|
424
|
+
services: {
|
|
425
|
+
[x: string]: unknown;
|
|
426
|
+
id: string;
|
|
427
|
+
type: string;
|
|
428
|
+
}[];
|
|
393
429
|
} | undefined>;
|
|
394
430
|
/**
|
|
395
431
|
* Create a key resolver that only resolves current-state keys.
|
|
@@ -403,7 +439,7 @@ declare const createCurrentKeyResolver: (store: RelayStore) => (kid: string) =>
|
|
|
403
439
|
* Ingest a batch of JWS operations
|
|
404
440
|
*
|
|
405
441
|
* Classifies, dependency-sorts, and processes each token. Identity operations
|
|
406
|
-
* are processed first so content chains
|
|
442
|
+
* are processed first so content chains can resolve their keys.
|
|
407
443
|
* Within each kind, genesis operations are processed before extensions.
|
|
408
444
|
*/
|
|
409
445
|
declare const ingestOperations: (tokens: string[], store: RelayStore, options?: {
|
|
@@ -411,13 +447,13 @@ declare const ingestOperations: (tokens: string[], store: RelayStore, options?:
|
|
|
411
447
|
}) => Promise<IngestionResult[]>;
|
|
412
448
|
|
|
413
449
|
/**
|
|
414
|
-
* Returns true if
|
|
415
|
-
* arrive later via sync or gossip.
|
|
416
|
-
*
|
|
450
|
+
* Returns true if a rejection is retryable (a missing dependency that may
|
|
451
|
+
* arrive later via sync or gossip). The sequencer branches on the STRUCTURED
|
|
452
|
+
* `dependencyMissing` flag set by the ingest producer — not on substring
|
|
453
|
+
* matching of the human-readable `error` string. Mirrors the Go twin's
|
|
454
|
+
* structured discriminator.
|
|
417
455
|
*/
|
|
418
|
-
declare const isDependencyFailure: (
|
|
419
|
-
/** Derive the operation CID from a JWS token */
|
|
420
|
-
declare const computeOpCID: (jwsToken: string) => Promise<string | undefined>;
|
|
456
|
+
declare const isDependencyFailure: (res: Pick<IngestionResult, "dependencyMissing">) => boolean;
|
|
421
457
|
/**
|
|
422
458
|
* Process unsequenced raw ops in a fixed-point loop until no more progress
|
|
423
459
|
* is made. Returns the JWS tokens of newly sequenced ops and aggregate stats.
|
|
@@ -427,4 +463,4 @@ declare const sequenceOps: (store: RelayStore) => Promise<{
|
|
|
427
463
|
result: SequenceResult;
|
|
428
464
|
}>;
|
|
429
465
|
|
|
430
|
-
export { type BlobKey, type CreatedRelay, type IngestionResult, type LogEntry, MemoryRelayStore, type OperationKind, type PeerClient, type PeerConfig, type PeerLogEntry, type RelayIdentity, type RelayOptions, type RelayStore, type SequenceResult, type
|
|
466
|
+
export { type BlobKey, type CreatedRelay, type IngestionResult, type LogEntry, MemoryRelayStore, type OperationKind, type PeerClient, type PeerConfig, type PeerLogEntry, type RelayIdentity, type RelayOptions, type RelayStore, type SequenceResult, type StoredContentChain, type StoredIdentityChain, type StoredOperation, bootstrapRelayIdentity, bootstrapRelayIdentityFromKey, chunkOps, computeOpCID, createCurrentKeyResolver, createHistoricalIdentityResolver, createHttpPeerClient, createKeyResolver, createRelay, ingestOperations, isDependencyFailure, sequenceOps };
|