@metalabel/dfos-web-relay 0.3.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/LICENSE +21 -0
- package/README.md +29 -0
- package/RELAY.md +210 -0
- package/dist/index.d.ts +143 -0
- package/dist/index.js +708 -0
- package/openapi.yaml +561 -0
- package/package.json +59 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Metalabel
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# @metalabel/dfos-web-relay
|
|
2
|
+
|
|
3
|
+
Portable HTTP relay for the [DFOS protocol](https://protocol.dfos.com). Receives, verifies, stores, and serves identity chains, content chains, beacons, countersignatures, and content blobs.
|
|
4
|
+
|
|
5
|
+
See [RELAY.md](./RELAY.md) for the full protocol specification.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @metalabel/dfos-web-relay @metalabel/dfos-protocol
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { createRelay, MemoryRelayStore } from '@metalabel/dfos-web-relay';
|
|
17
|
+
|
|
18
|
+
const relay = createRelay({
|
|
19
|
+
relayDID: 'did:dfos:myrelay00000000000000',
|
|
20
|
+
store: new MemoryRelayStore(),
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
// Mount on any Hono-compatible runtime
|
|
24
|
+
export default relay;
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## License
|
|
28
|
+
|
|
29
|
+
MIT
|
package/RELAY.md
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
# DFOS Web Relay
|
|
2
|
+
|
|
3
|
+
An HTTP relay for the DFOS protocol — receives, verifies, stores, and serves identity chains, content chains, beacons, countersignatures, and content blobs.
|
|
4
|
+
|
|
5
|
+
This spec is under active review. Discuss it in the [clear.txt](https://clear.dfos.com) space on DFOS.
|
|
6
|
+
|
|
7
|
+
[Source](https://github.com/metalabel/dfos/tree/main/packages/dfos-web-relay) · [npm](https://www.npmjs.com/package/@metalabel/dfos-web-relay) · [Protocol](https://protocol.dfos.com)
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Philosophy
|
|
12
|
+
|
|
13
|
+
The DFOS protocol defines signed chain primitives — identity and content chains, beacons, credentials — but says nothing about transport. A web relay is the HTTP layer that carries these primitives between participants.
|
|
14
|
+
|
|
15
|
+
Relays are not authorities. They verify what they receive and serve what they've verified, but they don't issue identity, grant permissions, or define content semantics. Any relay implementing the same verification rules produces the same acceptance/rejection decisions for the same operations. Clients can replicate their data across multiple relays without coordination.
|
|
16
|
+
|
|
17
|
+
A relay is a library, not a service. `createRelay()` returns a portable Hono application that any runtime can host — Node.js, Cloudflare Workers, Deno, Bun, a Docker container, a Raspberry Pi. The consumer provides a storage backend and configuration. The relay handles verification and HTTP semantics.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Two Planes
|
|
22
|
+
|
|
23
|
+
The relay serves two distinct planes of data with different access models:
|
|
24
|
+
|
|
25
|
+
### Proof Plane (public)
|
|
26
|
+
|
|
27
|
+
Signed chain operations, beacons, and countersignatures. These are cryptographic proofs — anyone can verify them with a public key. The proof plane gossips freely: relays push operations to peers, peers verify and store independently.
|
|
28
|
+
|
|
29
|
+
All proof plane routes are unauthenticated. The operations themselves carry their own authentication (Ed25519 signatures).
|
|
30
|
+
|
|
31
|
+
### Content Plane (private)
|
|
32
|
+
|
|
33
|
+
Raw content blobs — the actual documents that content chains commit to via `documentCID`. The content plane never gossips. Blobs are stored by the relay that received them and served only to authorized readers.
|
|
34
|
+
|
|
35
|
+
Content plane access requires two credentials:
|
|
36
|
+
|
|
37
|
+
- **Auth token**: A DID-signed JWT proving the caller controls an identity (AuthN)
|
|
38
|
+
- **Read credential** (for non-creators): A `DFOSContentRead` VC-JWT issued by the content creator, granting the caller read access (AuthZ)
|
|
39
|
+
|
|
40
|
+
The content creator (the DID that signed the genesis content operation) can always read their own blobs with just an auth token.
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Operation Ingestion
|
|
45
|
+
|
|
46
|
+
All proof plane artifacts enter through a single endpoint: `POST /operations`. The request body is an array of JWS tokens — identity operations, content operations, beacons, and countersignatures can be mixed freely in the same batch.
|
|
47
|
+
|
|
48
|
+
### Classification
|
|
49
|
+
|
|
50
|
+
Each token is classified by its JWS `typ` header:
|
|
51
|
+
|
|
52
|
+
| `typ` header | kid DID == payload DID? | Classification |
|
|
53
|
+
| ---------------------- | ----------------------- | ------------------------ |
|
|
54
|
+
| `did:dfos:identity-op` | — | Identity chain operation |
|
|
55
|
+
| `did:dfos:content-op` | yes | Content chain operation |
|
|
56
|
+
| `did:dfos:content-op` | no | Countersignature |
|
|
57
|
+
| `did:dfos:beacon` | yes | Beacon announcement |
|
|
58
|
+
| `did:dfos:beacon` | no | Beacon countersignature |
|
|
59
|
+
|
|
60
|
+
When the signing key's DID differs from the payload DID, the operation is classified as a countersignature (witness attestation) rather than a primary operation.
|
|
61
|
+
|
|
62
|
+
### Dependency Sort
|
|
63
|
+
|
|
64
|
+
Within a batch, operations are sorted by dependency priority before processing:
|
|
65
|
+
|
|
66
|
+
1. **Identity operations** — must be processed first so their keys are available
|
|
67
|
+
2. **Beacons** — reference identity keys
|
|
68
|
+
3. **Content operations** — reference identity keys for signature verification
|
|
69
|
+
4. **Countersignatures** — reference both identity keys and existing operations
|
|
70
|
+
|
|
71
|
+
Within each priority level, genesis operations (no `previousOperationCID`) are processed before extensions. This ensures that a single batch can bootstrap an entire identity-and-content lifecycle — including chained create + update operations — without multiple round trips.
|
|
72
|
+
|
|
73
|
+
### Verification
|
|
74
|
+
|
|
75
|
+
Each operation is verified against the relay's stored state:
|
|
76
|
+
|
|
77
|
+
- **Identity operations**: The full chain (stored log + new operation) is re-verified from genesis. The relay uses `verifyIdentityChain()` from the protocol library
|
|
78
|
+
- **Content operations**: The full chain is re-verified with `enforceAuthorization: true`. Non-creator signers must include a `DFOSContentWrite` VC-JWT
|
|
79
|
+
- **Beacons**: Signature, CID integrity, and clock skew are verified. Replace-on-newer: only the most recent beacon per DID is retained
|
|
80
|
+
- **Countersignatures**: The referenced operation or beacon must already exist. Signature is verified against the witness DID's identity chain
|
|
81
|
+
- **Beacon countersignatures**: The referenced beacon must exist and the countersignature CID must match the current beacon CID
|
|
82
|
+
|
|
83
|
+
### Fork Policy
|
|
84
|
+
|
|
85
|
+
First-seen-wins. If a chain head has already advanced past the `previousOperationCID` referenced by an incoming operation, the new operation is rejected. The relay does not attempt to resolve forks — the first valid extension wins.
|
|
86
|
+
|
|
87
|
+
Duplicate submissions (same operation CID) are silently accepted (idempotent).
|
|
88
|
+
|
|
89
|
+
### Result Ordering
|
|
90
|
+
|
|
91
|
+
Ingestion results are returned in the same order as the input `operations` array, regardless of internal processing order. `results[i]` corresponds to `operations[i]`.
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## Relay Identity
|
|
96
|
+
|
|
97
|
+
Every relay has a DID, published at `GET /.well-known/dfos-relay`. The relay DID serves as:
|
|
98
|
+
|
|
99
|
+
- **Auth token audience**: Auth tokens are scoped to a specific relay via the JWT `aud` claim, preventing cross-relay token replay
|
|
100
|
+
- **Peer identity**: When relays gossip proof plane data to each other, the relay DID identifies the peer
|
|
101
|
+
|
|
102
|
+
The relay does not currently sign operations or participate in the protocol as an identity. It's a passive verifier and store.
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Content Plane Access
|
|
107
|
+
|
|
108
|
+
### Blob Upload (`PUT /content/:contentId/blob`)
|
|
109
|
+
|
|
110
|
+
Requirements:
|
|
111
|
+
|
|
112
|
+
- Valid auth token (Bearer header)
|
|
113
|
+
- The authenticated DID must be the content chain creator
|
|
114
|
+
- The `X-Document-CID` header must reference a `documentCID` that appears in the chain's operation log
|
|
115
|
+
- The uploaded bytes must hash to the claimed `documentCID` (dag-cbor + sha-256 verification)
|
|
116
|
+
|
|
117
|
+
Blobs are stored by `(creatorDID, documentCID)` — if multiple content chains by the same creator reference the same document, the blob is shared (deduplication).
|
|
118
|
+
|
|
119
|
+
### Blob Download (`GET /content/:contentId/blob[/:ref]`)
|
|
120
|
+
|
|
121
|
+
Requirements:
|
|
122
|
+
|
|
123
|
+
- Valid auth token (Bearer header)
|
|
124
|
+
- If the caller is the chain creator: no further credentials needed
|
|
125
|
+
- If the caller is not the creator: must present a `DFOSContentRead` VC-JWT in the `X-Credential` header, issued by the creator to the caller
|
|
126
|
+
|
|
127
|
+
The optional `:ref` parameter selects which operation's document to return:
|
|
128
|
+
|
|
129
|
+
- `head` (default): the current document at chain head
|
|
130
|
+
- An operation CID: the document committed by that specific operation
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## Key Resolution
|
|
135
|
+
|
|
136
|
+
The relay uses two key resolution strategies:
|
|
137
|
+
|
|
138
|
+
- **Historical resolver** (for chain re-verification): searches all keys that have ever appeared in an identity chain's log, including rotated-out keys. This is necessary because re-verifying a full content chain from genesis must resolve keys from operations signed before a key rotation.
|
|
139
|
+
- **Current-state resolver** (for live authentication): only resolves keys in the identity's current state. After a key rotation, the old key immediately stops working for auth tokens and credentials. This prevents a compromised rotated-out key from being used to authenticate new requests.
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## Storage Interface
|
|
144
|
+
|
|
145
|
+
The relay delegates persistence to a `RelayStore` interface. Implementations handle how data is stored — the relay handles what to store and when.
|
|
146
|
+
|
|
147
|
+
```typescript
|
|
148
|
+
interface RelayStore {
|
|
149
|
+
getOperation(cid: string): Promise<StoredOperation | undefined>;
|
|
150
|
+
putOperation(op: StoredOperation): Promise<void>;
|
|
151
|
+
|
|
152
|
+
getIdentityChain(did: string): Promise<StoredIdentityChain | undefined>;
|
|
153
|
+
putIdentityChain(chain: StoredIdentityChain): Promise<void>;
|
|
154
|
+
|
|
155
|
+
getContentChain(contentId: string): Promise<StoredContentChain | undefined>;
|
|
156
|
+
putContentChain(chain: StoredContentChain): Promise<void>;
|
|
157
|
+
|
|
158
|
+
getBeacon(did: string): Promise<StoredBeacon | undefined>;
|
|
159
|
+
putBeacon(beacon: StoredBeacon): Promise<void>;
|
|
160
|
+
|
|
161
|
+
getBlob(key: BlobKey): Promise<Uint8Array | undefined>;
|
|
162
|
+
putBlob(key: BlobKey, data: Uint8Array): Promise<void>;
|
|
163
|
+
|
|
164
|
+
getCountersignatures(operationCID: string): Promise<string[]>;
|
|
165
|
+
addCountersignature(operationCID: string, jwsToken: string): Promise<void>;
|
|
166
|
+
}
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
The package includes `MemoryRelayStore` for development and testing. Production deployments would implement the interface over Postgres, SQLite, S3, or any durable store.
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## Quick Start
|
|
174
|
+
|
|
175
|
+
```typescript
|
|
176
|
+
import { createRelay, MemoryRelayStore } from '@metalabel/dfos-web-relay';
|
|
177
|
+
|
|
178
|
+
const relay = createRelay({
|
|
179
|
+
relayDID: 'did:dfos:myrelay00000000000000',
|
|
180
|
+
store: new MemoryRelayStore(),
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
// Mount on any Hono-compatible runtime
|
|
184
|
+
export default relay;
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
The returned Hono app exposes:
|
|
188
|
+
|
|
189
|
+
| Method | Path | Plane | Auth |
|
|
190
|
+
| ------ | ------------------------------------ | ------- | ----------------------- |
|
|
191
|
+
| `GET` | `/.well-known/dfos-relay` | meta | none |
|
|
192
|
+
| `POST` | `/operations` | proof | none |
|
|
193
|
+
| `GET` | `/operations/:cid` | proof | none |
|
|
194
|
+
| `GET` | `/operations/:cid/countersignatures` | proof | none |
|
|
195
|
+
| `GET` | `/countersignatures/:cid` | proof | none |
|
|
196
|
+
| `GET` | `/identities/:did` | proof | none |
|
|
197
|
+
| `GET` | `/content/:contentId` | proof | none |
|
|
198
|
+
| `GET` | `/beacons/:did` | proof | none |
|
|
199
|
+
| `PUT` | `/content/:contentId/blob` | content | auth token |
|
|
200
|
+
| `GET` | `/content/:contentId/blob[/:ref]` | content | auth token + credential |
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
## What's Deferred
|
|
205
|
+
|
|
206
|
+
- **Peer gossip**: Proactive push of proof plane operations to other relays
|
|
207
|
+
- **Rate limiting / anti-spam**: Operational concern, not protocol concern
|
|
208
|
+
- **Docker/CF reference deployments**: Focus on the core library first
|
|
209
|
+
- **Pagination**: Chain logs are returned in full — fine for v1, needs pagination at scale
|
|
210
|
+
- **Blob size limits**: No enforcement yet — production deployments should add limits at the middleware layer
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { Hono } from 'hono';
|
|
2
|
+
import { VerifiedIdentity, VerifiedContentChain, VerifiedBeacon } from '@metalabel/dfos-protocol/chain';
|
|
3
|
+
|
|
4
|
+
interface RelayOptions {
|
|
5
|
+
/** The relay's DID — used as auth token audience and published in well-known */
|
|
6
|
+
relayDID: string;
|
|
7
|
+
/** Storage backend */
|
|
8
|
+
store: RelayStore;
|
|
9
|
+
}
|
|
10
|
+
interface StoredIdentityChain {
|
|
11
|
+
did: string;
|
|
12
|
+
/** Ordered JWS tokens from genesis to head */
|
|
13
|
+
log: string[];
|
|
14
|
+
state: VerifiedIdentity;
|
|
15
|
+
}
|
|
16
|
+
interface StoredContentChain {
|
|
17
|
+
contentId: string;
|
|
18
|
+
genesisCID: string;
|
|
19
|
+
/** Ordered JWS tokens from genesis to head */
|
|
20
|
+
log: string[];
|
|
21
|
+
state: VerifiedContentChain;
|
|
22
|
+
}
|
|
23
|
+
interface StoredBeacon {
|
|
24
|
+
did: string;
|
|
25
|
+
jwsToken: string;
|
|
26
|
+
beaconCID: string;
|
|
27
|
+
state: VerifiedBeacon;
|
|
28
|
+
}
|
|
29
|
+
interface StoredOperation {
|
|
30
|
+
cid: string;
|
|
31
|
+
jwsToken: string;
|
|
32
|
+
/** Which chain type this operation belongs to */
|
|
33
|
+
chainType: 'identity' | 'content';
|
|
34
|
+
/** The chain identifier — DID for identity, contentId for content */
|
|
35
|
+
chainId: string;
|
|
36
|
+
}
|
|
37
|
+
/** Key for blob storage — deduplicates across chains sharing the same document */
|
|
38
|
+
interface BlobKey {
|
|
39
|
+
creatorDID: string;
|
|
40
|
+
documentCID: string;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Storage backend for a DFOS web relay
|
|
44
|
+
*
|
|
45
|
+
* Implementations handle persistence (memory, SQLite, Postgres, S3, etc.).
|
|
46
|
+
* The relay core handles verification — the store just reads and writes.
|
|
47
|
+
*
|
|
48
|
+
* Concurrency contract: the in-memory store is safe under single-threaded JS.
|
|
49
|
+
* Durable implementations must enforce optimistic concurrency (compare-and-swap
|
|
50
|
+
* on chain head CID) or pessimistic locking to prevent concurrent extensions
|
|
51
|
+
* from silently overwriting each other.
|
|
52
|
+
*/
|
|
53
|
+
interface RelayStore {
|
|
54
|
+
getOperation(cid: string): Promise<StoredOperation | undefined>;
|
|
55
|
+
putOperation(op: StoredOperation): Promise<void>;
|
|
56
|
+
getIdentityChain(did: string): Promise<StoredIdentityChain | undefined>;
|
|
57
|
+
putIdentityChain(chain: StoredIdentityChain): Promise<void>;
|
|
58
|
+
getContentChain(contentId: string): Promise<StoredContentChain | undefined>;
|
|
59
|
+
putContentChain(chain: StoredContentChain): Promise<void>;
|
|
60
|
+
getBeacon(did: string): Promise<StoredBeacon | undefined>;
|
|
61
|
+
putBeacon(beacon: StoredBeacon): Promise<void>;
|
|
62
|
+
getBlob(key: BlobKey): Promise<Uint8Array | undefined>;
|
|
63
|
+
putBlob(key: BlobKey, data: Uint8Array): Promise<void>;
|
|
64
|
+
getCountersignatures(operationCID: string): Promise<string[]>;
|
|
65
|
+
addCountersignature(operationCID: string, jwsToken: string): Promise<void>;
|
|
66
|
+
}
|
|
67
|
+
interface IngestionResult {
|
|
68
|
+
cid: string;
|
|
69
|
+
status: 'accepted' | 'rejected';
|
|
70
|
+
error?: string;
|
|
71
|
+
/** What was ingested */
|
|
72
|
+
kind?: 'identity-op' | 'content-op' | 'beacon' | 'countersig' | 'beacon-countersig';
|
|
73
|
+
/** Chain identifier if applicable */
|
|
74
|
+
chainId?: string;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Create a DFOS web relay Hono application
|
|
79
|
+
*
|
|
80
|
+
* The returned app is portable — mount it on any Hono-compatible runtime
|
|
81
|
+
* (Node.js, Cloudflare Workers, Deno, Bun, etc.).
|
|
82
|
+
*/
|
|
83
|
+
declare const createRelay: (options: RelayOptions) => Hono;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* In-memory relay store — all data lives in Maps, lost on restart
|
|
87
|
+
*
|
|
88
|
+
* Suitable for development, testing, and short-lived relay instances.
|
|
89
|
+
*/
|
|
90
|
+
declare class MemoryRelayStore implements RelayStore {
|
|
91
|
+
private operations;
|
|
92
|
+
private identityChains;
|
|
93
|
+
private contentChains;
|
|
94
|
+
private beacons;
|
|
95
|
+
private blobs;
|
|
96
|
+
private countersignatures;
|
|
97
|
+
getOperation(cid: string): Promise<StoredOperation | undefined>;
|
|
98
|
+
putOperation(op: StoredOperation): Promise<void>;
|
|
99
|
+
getIdentityChain(did: string): Promise<StoredIdentityChain | undefined>;
|
|
100
|
+
putIdentityChain(chain: StoredIdentityChain): Promise<void>;
|
|
101
|
+
getContentChain(contentId: string): Promise<StoredContentChain | undefined>;
|
|
102
|
+
putContentChain(chain: StoredContentChain): Promise<void>;
|
|
103
|
+
getBeacon(did: string): Promise<StoredBeacon | undefined>;
|
|
104
|
+
putBeacon(beacon: StoredBeacon): Promise<void>;
|
|
105
|
+
getBlob(key: BlobKey): Promise<Uint8Array | undefined>;
|
|
106
|
+
putBlob(key: BlobKey, data: Uint8Array): Promise<void>;
|
|
107
|
+
getCountersignatures(operationCID: string): Promise<string[]>;
|
|
108
|
+
addCountersignature(operationCID: string, jwsToken: string): Promise<void>;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Create a key resolver that looks up Ed25519 public keys from identity chains
|
|
113
|
+
* in the store. Used for chain re-verification during ingestion.
|
|
114
|
+
*
|
|
115
|
+
* Searches all keys that have ever appeared in the identity chain log, not just
|
|
116
|
+
* current state. This is necessary because re-verifying a full content chain log
|
|
117
|
+
* needs to resolve keys from operations signed before a key rotation.
|
|
118
|
+
*
|
|
119
|
+
* CID fidelity invariant: countersignature ingestion derives the operation CID
|
|
120
|
+
* by re-encoding the decoded payload via dagCborCanonicalEncode. This relies on
|
|
121
|
+
* the JWS decode round-trip preserving payload fidelity through JSON→CBOR→JSON→CBOR.
|
|
122
|
+
* The protocol library's canonical encoding (dag-cbor + sha-256) guarantees
|
|
123
|
+
* deterministic CIDs for identical payloads.
|
|
124
|
+
*/
|
|
125
|
+
declare const createKeyResolver: (store: RelayStore) => (kid: string) => Promise<Uint8Array>;
|
|
126
|
+
/**
|
|
127
|
+
* Create a key resolver that only resolves current-state keys.
|
|
128
|
+
*
|
|
129
|
+
* Used for live authentication (auth tokens, credentials) where rotated-out
|
|
130
|
+
* keys must NOT be accepted. After a key rotation, the old key should no
|
|
131
|
+
* longer authenticate new requests.
|
|
132
|
+
*/
|
|
133
|
+
declare const createCurrentKeyResolver: (store: RelayStore) => (kid: string) => Promise<Uint8Array>;
|
|
134
|
+
/**
|
|
135
|
+
* Ingest a batch of JWS operations
|
|
136
|
+
*
|
|
137
|
+
* Classifies, dependency-sorts, and processes each token. Identity operations
|
|
138
|
+
* are processed first so content chains and beacons can resolve their keys.
|
|
139
|
+
* Within each kind, genesis operations are processed before extensions.
|
|
140
|
+
*/
|
|
141
|
+
declare const ingestOperations: (tokens: string[], store: RelayStore) => Promise<IngestionResult[]>;
|
|
142
|
+
|
|
143
|
+
export { type BlobKey, type IngestionResult, MemoryRelayStore, type RelayOptions, type RelayStore, type StoredBeacon, type StoredContentChain, type StoredIdentityChain, type StoredOperation, createCurrentKeyResolver, createKeyResolver, createRelay, ingestOperations };
|