@metalabel/dfos-protocol 0.10.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 CHANGED
@@ -21,11 +21,11 @@ import { createJws, dagCborCanonicalEncode, verifyJws } from '@metalabel/dfos-pr
21
21
 
22
22
  ## Subpath Exports
23
23
 
24
- | Export | Description |
25
- | -------------------------------------- | ----------------------------------------------------------------------- |
26
- | `@metalabel/dfos-protocol/chain` | Identity and content chain signing, verification, beacons, countersigns |
27
- | `@metalabel/dfos-protocol/credentials` | Auth tokens (DID-signed JWT) and DFOS credentials for authorization |
28
- | `@metalabel/dfos-protocol/crypto` | Ed25519, JWS, JWT, dag-cbor, base64url, ID generation |
24
+ | Export | Description |
25
+ | -------------------------------------- | ------------------------------------------------------------------------- |
26
+ | `@metalabel/dfos-protocol/chain` | Identity & content chains, services, artifacts, countersigns, revocations |
27
+ | `@metalabel/dfos-protocol/credentials` | Auth tokens (DID-signed JWT) and DFOS credentials for authorization |
28
+ | `@metalabel/dfos-protocol/crypto` | Ed25519, JWS, JWT, dag-cbor, base64url, ID generation |
29
29
 
30
30
  ## Specifications
31
31
 
@@ -33,7 +33,7 @@ import { createJws, dagCborCanonicalEncode, verifyJws } from '@metalabel/dfos-pr
33
33
  | ------------------------------------------------ | -------------------------------------------------------------- |
34
34
  | [PROTOCOL.md](../../specs/PROTOCOL.md) | Core protocol — chains, signatures, verification, test vectors |
35
35
  | [DID-METHOD.md](../../specs/DID-METHOD.md) | W3C DID method specification for `did:dfos` |
36
- | [CONTENT-MODEL.md](../../specs/CONTENT-MODEL.md) | Standard content schemas (post, profile, manifest) |
36
+ | [CONTENT-MODEL.md](../../specs/CONTENT-MODEL.md) | Standard content schemas (post, profile) |
37
37
 
38
38
  ## Examples
39
39
 
@@ -47,7 +47,7 @@ The `examples/` directory contains deterministic reference fixtures that can be
47
47
  - `content-delegated.json` — creator genesis + delegated update with DFOS write credential
48
48
  - `credential-write.json` — DFOS write credential (broad + content-narrowed)
49
49
  - `credential-read.json` — DFOS read credential
50
- - `beacon.json` — signed manifest pointer announcement with witness countersignature
50
+ - `identity-services.json` — genesis publishing a services set (relay locator + content/artifact anchors)
51
51
 
52
52
  ## License
53
53
 
@@ -1,5 +1,5 @@
1
- import { I as IdentityOperation, S as Signer, V as VerifiedIdentity, C as ContentOperation, B as BeaconPayload, a as CountersignPayload, A as ArtifactPayload } from '../schemas-BhikXSf_.js';
2
- export { M as MAX_ARTIFACT_PAYLOAD_SIZE, b as MultikeyPublicKey, R as RevocationPayload } from '../schemas-BhikXSf_.js';
1
+ import { I as IdentityOperation, h as Signer, V as VerifiedIdentity, S as ServiceEntry, b as ContentOperation, c as CountersignPayload, a as ArtifactPayload } from '../schemas-Myod8ES9.js';
2
+ export { A as ARTIFACT_CID_ANCHOR_RE, C as CONTENT_ID_ANCHOR_RE, M as MAX_ARTIFACT_PAYLOAD_SIZE, d as MAX_SERVICES_ENTRIES, e as MAX_SERVICES_PAYLOAD_SIZE, f as MultikeyPublicKey, R as RevocationPayload, g as ServicesArray } from '../schemas-Myod8ES9.js';
3
3
  import 'zod';
4
4
 
5
5
  /** Ed25519 public key multicodec value */
@@ -88,6 +88,29 @@ declare const verifyIdentityExtensionFromTrustedState: (input: {
88
88
  createdAt: string;
89
89
  }>;
90
90
 
91
+ type AnchorKind = 'chain' | 'artifact' | 'invalid';
92
+ /**
93
+ * Enforce the services byte cap on the CBOR-encoded array — same encoding the
94
+ * wire uses, so the bound is identical across implementations. Mirrors the
95
+ * artifact payload size check.
96
+ */
97
+ declare const assertServicesWithinCap: (services: ServiceEntry[]) => Promise<void>;
98
+ /**
99
+ * Classify a ContentAnchor target by structural form. Resolvers dispatch on the
100
+ * result: 'chain' → resolve a content chain by contentId; 'artifact' → fetch by
101
+ * CID and require type:"artifact"; 'invalid' → reject (e.g. a bare head CID is
102
+ * 'artifact'-shaped but fails the resolution-time type check).
103
+ */
104
+ declare const classifyAnchor: (anchor: string) => AnchorKind;
105
+ /** Recognized (core-blessed) service types. All other types are valid but opaque. */
106
+ declare const RECOGNIZED_SERVICE_TYPES: readonly ["DfosRelay", "ContentAnchor"];
107
+ /** Whether the core assigns structural semantics to this service type. */
108
+ declare const isRecognizedServiceType: (type: string) => boolean;
109
+ /** Select the DfosRelay transport endpoints from a services set, in entry order. */
110
+ declare const relayEndpoints: (services: ServiceEntry[]) => string[];
111
+ /** Select ContentAnchor entries matching a client label (e.g. "profile"). */
112
+ declare const anchorsByLabel: (services: ServiceEntry[], label: string) => ServiceEntry[];
113
+
91
114
  interface VerifiedContentChain {
92
115
  /** Content identifier — bare 31-char hash derived from genesis CID */
93
116
  contentId: string;
@@ -178,34 +201,6 @@ declare const verifyContentExtensionFromTrustedState: (input: {
178
201
  createdAt: string;
179
202
  }>;
180
203
 
181
- interface VerifiedBeacon {
182
- did: string;
183
- manifestContentId: string;
184
- createdAt: string;
185
- signerKeyId: string;
186
- beaconCID: string;
187
- }
188
- /**
189
- * Sign a beacon announcement as a JWS
190
- */
191
- declare const signBeacon: (input: {
192
- payload: BeaconPayload;
193
- signer: Signer;
194
- kid: string;
195
- }) => Promise<{
196
- jwsToken: string;
197
- beaconCID: string;
198
- }>;
199
- /**
200
- * Verify a beacon JWS — signature, CID, payload schema, clock skew
201
- */
202
- declare const verifyBeacon: (input: {
203
- jwsToken: string;
204
- resolveKey: (kid: string) => Promise<Uint8Array>;
205
- /** Current time for clock skew check (defaults to Date.now()) */
206
- now?: number;
207
- }) => Promise<VerifiedBeacon>;
208
-
209
204
  interface VerifiedCountersignature {
210
205
  /** CID of this countersign operation (distinct from the target) */
211
206
  countersignCID: string;
@@ -213,6 +208,8 @@ interface VerifiedCountersignature {
213
208
  witnessDID: string;
214
209
  /** The CID being attested to */
215
210
  targetCID: string;
211
+ /** Open-namespace relation tag, if present (e.g. "endorses", "coauthors") */
212
+ relation?: string;
216
213
  }
217
214
  /**
218
215
  * Sign a countersignature attesting to a target operation by CID
@@ -294,4 +291,4 @@ declare const verifyRevocation: (input: {
294
291
  resolveKey: (kid: string) => Promise<Uint8Array>;
295
292
  }) => Promise<VerifiedRevocation>;
296
293
 
297
- export { ArtifactPayload, BeaconPayload, ContentOperation, CountersignPayload, ED25519_PRIV_MULTICODEC, ED25519_PUB_MULTICODEC, IdentityOperation, Signer, type VerifiedArtifact, type VerifiedBeacon, type VerifiedContentChain, type VerifiedCountersignature, VerifiedIdentity, type VerifiedRevocation, decodeMultikey, deriveChainIdentifier, deriveContentId, encodeEd25519Multikey, signArtifact, signBeacon, signContentOperation, signCountersignature, signIdentityOperation, signRevocation, verifyArtifact, verifyBeacon, verifyContentChain, verifyContentExtensionFromTrustedState, verifyCountersignature, verifyIdentityChain, verifyIdentityExtensionFromTrustedState, verifyRevocation };
294
+ export { type AnchorKind, ArtifactPayload, ContentOperation, CountersignPayload, ED25519_PRIV_MULTICODEC, ED25519_PUB_MULTICODEC, IdentityOperation, RECOGNIZED_SERVICE_TYPES, ServiceEntry, Signer, type VerifiedArtifact, type VerifiedContentChain, type VerifiedCountersignature, VerifiedIdentity, type VerifiedRevocation, anchorsByLabel, assertServicesWithinCap, classifyAnchor, decodeMultikey, deriveChainIdentifier, deriveContentId, encodeEd25519Multikey, isRecognizedServiceType, relayEndpoints, signArtifact, signContentOperation, signCountersignature, signIdentityOperation, signRevocation, verifyArtifact, verifyContentChain, verifyContentExtensionFromTrustedState, verifyCountersignature, verifyIdentityChain, verifyIdentityExtensionFromTrustedState, verifyRevocation };
@@ -1,30 +1,39 @@
1
1
  import {
2
+ ARTIFACT_CID_ANCHOR_RE,
2
3
  ArtifactPayload,
3
- BeaconPayload,
4
+ CONTENT_ID_ANCHOR_RE,
4
5
  ContentOperation,
5
6
  CountersignPayload,
6
7
  IdentityOperation,
7
8
  MAX_ARTIFACT_PAYLOAD_SIZE,
9
+ MAX_SERVICES_ENTRIES,
10
+ MAX_SERVICES_PAYLOAD_SIZE,
8
11
  MultikeyPublicKey,
12
+ RECOGNIZED_SERVICE_TYPES,
9
13
  RevocationPayload,
14
+ ServiceEntry,
15
+ ServicesArray,
10
16
  VerifiedIdentity,
17
+ anchorsByLabel,
18
+ assertServicesWithinCap,
19
+ classifyAnchor,
11
20
  deriveChainIdentifier,
12
21
  deriveContentId,
22
+ isRecognizedServiceType,
23
+ relayEndpoints,
13
24
  signArtifact,
14
- signBeacon,
15
25
  signContentOperation,
16
26
  signCountersignature,
17
27
  signIdentityOperation,
18
28
  signRevocation,
19
29
  verifyArtifact,
20
- verifyBeacon,
21
30
  verifyContentChain,
22
31
  verifyContentExtensionFromTrustedState,
23
32
  verifyCountersignature,
24
33
  verifyIdentityChain,
25
34
  verifyIdentityExtensionFromTrustedState,
26
35
  verifyRevocation
27
- } from "../chunk-GZ7ZAIRD.js";
36
+ } from "../chunk-SDUOUFTF.js";
28
37
  import {
29
38
  ED25519_PRIV_MULTICODEC,
30
39
  ED25519_PUB_MULTICODEC,
@@ -33,29 +42,38 @@ import {
33
42
  } from "../chunk-LQFOBE6X.js";
34
43
  import "../chunk-GQOZJKKO.js";
35
44
  export {
45
+ ARTIFACT_CID_ANCHOR_RE,
36
46
  ArtifactPayload,
37
- BeaconPayload,
47
+ CONTENT_ID_ANCHOR_RE,
38
48
  ContentOperation,
39
49
  CountersignPayload,
40
50
  ED25519_PRIV_MULTICODEC,
41
51
  ED25519_PUB_MULTICODEC,
42
52
  IdentityOperation,
43
53
  MAX_ARTIFACT_PAYLOAD_SIZE,
54
+ MAX_SERVICES_ENTRIES,
55
+ MAX_SERVICES_PAYLOAD_SIZE,
44
56
  MultikeyPublicKey,
57
+ RECOGNIZED_SERVICE_TYPES,
45
58
  RevocationPayload,
59
+ ServiceEntry,
60
+ ServicesArray,
46
61
  VerifiedIdentity,
62
+ anchorsByLabel,
63
+ assertServicesWithinCap,
64
+ classifyAnchor,
47
65
  decodeMultikey,
48
66
  deriveChainIdentifier,
49
67
  deriveContentId,
50
68
  encodeEd25519Multikey,
69
+ isRecognizedServiceType,
70
+ relayEndpoints,
51
71
  signArtifact,
52
- signBeacon,
53
72
  signContentOperation,
54
73
  signCountersignature,
55
74
  signIdentityOperation,
56
75
  signRevocation,
57
76
  verifyArtifact,
58
- verifyBeacon,
59
77
  verifyContentChain,
60
78
  verifyContentExtensionFromTrustedState,
61
79
  verifyCountersignature,
@@ -21,11 +21,49 @@ var MAX_CID = 256;
21
21
  var MAX_NOTE = 256;
22
22
  var MAX_KEYS_PER_ROLE = 16;
23
23
  var MAX_DID = 256;
24
+ var MAX_SERVICE_ID = 64;
25
+ var MAX_SERVICE_TYPE = 64;
26
+ var MAX_SERVICE_STRING = 512;
27
+ var MAX_RELATION = 64;
28
+ var MAX_SERVICES_ENTRIES = 16;
29
+ var MAX_SERVICES_PAYLOAD_SIZE = 8192;
24
30
  var MultikeyPublicKey = z.strictObject({
25
31
  id: z.string().max(MAX_KEY_ID),
26
32
  type: z.literal("Multikey"),
27
33
  publicKeyMultibase: z.string().max(MAX_PUBLIC_KEY_MULTIBASE)
28
34
  });
35
+ var CONTENT_ID_ANCHOR_RE = /^[2346789acdefhknrtvz]{31}$/;
36
+ var ARTIFACT_CID_ANCHOR_RE = /^baf[a-z2-7]{20,}$/;
37
+ var ServiceEntry = z.object({
38
+ id: z.string().min(1).max(MAX_SERVICE_ID),
39
+ type: z.string().min(1).max(MAX_SERVICE_TYPE)
40
+ }).catchall(z.unknown()).superRefine((entry, ctx) => {
41
+ if (entry.type === "DfosRelay") {
42
+ const endpoint = entry["endpoint"];
43
+ if (typeof endpoint !== "string" || endpoint.length < 1 || endpoint.length > MAX_SERVICE_STRING) {
44
+ ctx.addIssue({ code: "custom", message: "DfosRelay requires a non-empty endpoint string" });
45
+ }
46
+ } else if (entry.type === "ContentAnchor") {
47
+ const label = entry["label"];
48
+ const anchor = entry["anchor"];
49
+ if (typeof label !== "string" || label.length < 1 || label.length > MAX_SERVICE_STRING) {
50
+ ctx.addIssue({
51
+ code: "custom",
52
+ message: "ContentAnchor requires a non-empty label string"
53
+ });
54
+ }
55
+ if (typeof anchor !== "string" || !(CONTENT_ID_ANCHOR_RE.test(anchor) || ARTIFACT_CID_ANCHOR_RE.test(anchor))) {
56
+ ctx.addIssue({
57
+ code: "custom",
58
+ message: "ContentAnchor anchor must be a 31-char contentId or a CIDv1 artifact CID"
59
+ });
60
+ }
61
+ }
62
+ });
63
+ var ServicesArray = z.array(ServiceEntry).max(MAX_SERVICES_ENTRIES).refine(
64
+ (arr) => new Set(arr.map((e) => e.id)).size === arr.length,
65
+ "service entry ids must be unique"
66
+ );
29
67
  var Iso8601 = z.iso.datetime({ offset: false, precision: 3 });
30
68
  var CIDString = z.string().max(MAX_CID);
31
69
  var IdentityCreate = z.strictObject({
@@ -34,6 +72,9 @@ var IdentityCreate = z.strictObject({
34
72
  authKeys: z.array(MultikeyPublicKey).max(MAX_KEYS_PER_ROLE),
35
73
  assertKeys: z.array(MultikeyPublicKey).max(MAX_KEYS_PER_ROLE),
36
74
  controllerKeys: z.array(MultikeyPublicKey).max(MAX_KEYS_PER_ROLE),
75
+ // Full-state discovery vocabulary. Optional so ops without services encode
76
+ // identically (undefined strips under canonical CBOR — CID-neutral).
77
+ services: ServicesArray.optional(),
37
78
  createdAt: Iso8601
38
79
  });
39
80
  var IdentityUpdate = z.strictObject({
@@ -43,6 +84,8 @@ var IdentityUpdate = z.strictObject({
43
84
  authKeys: z.array(MultikeyPublicKey).max(MAX_KEYS_PER_ROLE),
44
85
  assertKeys: z.array(MultikeyPublicKey).max(MAX_KEYS_PER_ROLE),
45
86
  controllerKeys: z.array(MultikeyPublicKey).min(1, "update must have at least one controller key").max(MAX_KEYS_PER_ROLE),
87
+ // Full-state: an update REPLACES the entire services set (omit to clear).
88
+ services: ServicesArray.optional(),
46
89
  createdAt: Iso8601
47
90
  });
48
91
  var IdentityDelete = z.strictObject({
@@ -61,7 +104,9 @@ var VerifiedIdentity = z.strictObject({
61
104
  isDeleted: z.boolean(),
62
105
  authKeys: z.array(MultikeyPublicKey).max(MAX_KEYS_PER_ROLE),
63
106
  assertKeys: z.array(MultikeyPublicKey).max(MAX_KEYS_PER_ROLE),
64
- controllerKeys: z.array(MultikeyPublicKey).max(MAX_KEYS_PER_ROLE)
107
+ controllerKeys: z.array(MultikeyPublicKey).max(MAX_KEYS_PER_ROLE),
108
+ /** Resolved discovery vocabulary — projection of the winning head's services */
109
+ services: ServicesArray
65
110
  });
66
111
  var ContentCreate = z.strictObject({
67
112
  version: z.literal(1),
@@ -99,13 +144,6 @@ var ContentOperation = z.discriminatedUnion("type", [
99
144
  ContentUpdate,
100
145
  ContentDelete
101
146
  ]);
102
- var BeaconPayload = z.strictObject({
103
- version: z.literal(1),
104
- type: z.literal("beacon"),
105
- did: z.string().max(MAX_DID),
106
- manifestContentId: z.string().max(MAX_CID),
107
- createdAt: Iso8601
108
- });
109
147
  var MAX_SCHEMA = 256;
110
148
  var MAX_ARTIFACT_PAYLOAD_SIZE = 16384;
111
149
  var ArtifactContent = z.object({ $schema: z.string().max(MAX_SCHEMA) }).catchall(z.unknown());
@@ -121,6 +159,7 @@ var CountersignPayload = z.strictObject({
121
159
  type: z.literal("countersign"),
122
160
  did: z.string().max(MAX_DID),
123
161
  targetCID: CIDString,
162
+ relation: z.string().min(1).max(MAX_RELATION).optional(),
124
163
  createdAt: Iso8601
125
164
  });
126
165
  var RevocationPayload = z.strictObject({
@@ -140,6 +179,27 @@ var deriveContentId = (cidBytes) => {
140
179
  return generateIdNoPrefix({ seed: cidBytes });
141
180
  };
142
181
 
182
+ // src/chain/services.ts
183
+ var assertServicesWithinCap = async (services) => {
184
+ const encoded = await dagCborCanonicalEncode(services);
185
+ if (encoded.bytes.length > MAX_SERVICES_PAYLOAD_SIZE) {
186
+ throw new Error(
187
+ `services payload exceeds max size: ${encoded.bytes.length} > ${MAX_SERVICES_PAYLOAD_SIZE}`
188
+ );
189
+ }
190
+ };
191
+ var classifyAnchor = (anchor) => {
192
+ if (CONTENT_ID_ANCHOR_RE.test(anchor)) return "chain";
193
+ if (ARTIFACT_CID_ANCHOR_RE.test(anchor)) return "artifact";
194
+ return "invalid";
195
+ };
196
+ var RECOGNIZED_SERVICE_TYPES = ["DfosRelay", "ContentAnchor"];
197
+ var isRecognizedServiceType = (type) => RECOGNIZED_SERVICE_TYPES.includes(type);
198
+ var relayEndpoints = (services) => services.filter((e) => e.type === "DfosRelay").map((e) => e["endpoint"]).filter((v) => typeof v === "string");
199
+ var anchorsByLabel = (services, label) => services.filter(
200
+ (e) => e.type === "ContentAnchor" && e["label"] === label
201
+ );
202
+
143
203
  // src/chain/identity-chain.ts
144
204
  var signIdentityOperation = async (input) => {
145
205
  const kid = input.identityDID ? `${input.identityDID}#${input.keyId}` : input.keyId;
@@ -162,6 +222,7 @@ var verifyIdentityChain = async (input) => {
162
222
  authKeys: [],
163
223
  assertKeys: [],
164
224
  controllerKeys: [],
225
+ services: [],
165
226
  seenKeys: /* @__PURE__ */ new Map()
166
227
  };
167
228
  for (const [idx, jwsToken] of input.log.entries()) {
@@ -190,6 +251,7 @@ var verifyIdentityChain = async (input) => {
190
251
  state.authKeys = op.authKeys;
191
252
  state.assertKeys = op.assertKeys;
192
253
  state.controllerKeys = op.controllerKeys;
254
+ state.services = op.services ?? [];
193
255
  }
194
256
  if (op.type === "update" || op.type === "delete") {
195
257
  if (op.previousOperationCID !== state.previousOperationCID) {
@@ -217,6 +279,13 @@ var verifyIdentityChain = async (input) => {
217
279
  throw new Error(`log[${idx}]: cannot repeat key ids in same usage`);
218
280
  }
219
281
  });
282
+ if (op.services) {
283
+ try {
284
+ await assertServicesWithinCap(op.services);
285
+ } catch (e) {
286
+ throw new Error(`log[${idx}]: ${e.message}`);
287
+ }
288
+ }
220
289
  }
221
290
  const encoded = await dagCborCanonicalEncode(op);
222
291
  const operationCID = encoded.cid.toString();
@@ -271,6 +340,7 @@ var verifyIdentityChain = async (input) => {
271
340
  state.authKeys = op.authKeys;
272
341
  state.assertKeys = op.assertKeys;
273
342
  state.controllerKeys = op.controllerKeys;
343
+ state.services = op.services ?? [];
274
344
  break;
275
345
  case "delete":
276
346
  state.isDeleted = true;
@@ -283,7 +353,8 @@ var verifyIdentityChain = async (input) => {
283
353
  isDeleted: state.isDeleted,
284
354
  authKeys: state.authKeys,
285
355
  assertKeys: state.assertKeys,
286
- controllerKeys: state.controllerKeys
356
+ controllerKeys: state.controllerKeys,
357
+ services: state.services
287
358
  };
288
359
  };
289
360
  var verifyIdentityExtensionFromTrustedState = async (input) => {
@@ -342,19 +413,22 @@ var verifyIdentityExtensionFromTrustedState = async (input) => {
342
413
  throw new Error("cannot repeat key ids in same usage");
343
414
  }
344
415
  });
416
+ if (op.services) await assertServicesWithinCap(op.services);
345
417
  }
346
418
  const newState = op.type === "update" ? {
347
419
  did: currentState.did,
348
420
  isDeleted: false,
349
421
  authKeys: op.authKeys,
350
422
  assertKeys: op.assertKeys,
351
- controllerKeys: op.controllerKeys
423
+ controllerKeys: op.controllerKeys,
424
+ services: op.services ?? []
352
425
  } : {
353
426
  did: currentState.did,
354
427
  isDeleted: true,
355
428
  authKeys: currentState.authKeys,
356
429
  assertKeys: currentState.assertKeys,
357
- controllerKeys: currentState.controllerKeys
430
+ controllerKeys: currentState.controllerKeys,
431
+ services: currentState.services
358
432
  };
359
433
  return { state: newState, operationCID, createdAt: op.createdAt };
360
434
  };
@@ -599,61 +673,6 @@ var verifyContentExtensionFromTrustedState = async (input) => {
599
673
  return { state: newState, operationCID, createdAt: op.createdAt };
600
674
  };
601
675
 
602
- // src/chain/beacon.ts
603
- var signBeacon = async (input) => {
604
- const encoded = await dagCborCanonicalEncode(input.payload);
605
- const beaconCID = encoded.cid.toString();
606
- const jwsToken = await createJws({
607
- header: { alg: "EdDSA", typ: "did:dfos:beacon", kid: input.kid, cid: beaconCID },
608
- payload: input.payload,
609
- sign: input.signer
610
- });
611
- return { jwsToken, beaconCID };
612
- };
613
- var MAX_FUTURE_MS = 5 * 60 * 1e3;
614
- var verifyBeacon = async (input) => {
615
- const decoded = decodeJwsUnsafe(input.jwsToken);
616
- if (!decoded) throw new Error("failed to decode beacon JWS");
617
- const result = BeaconPayload.safeParse(decoded.payload);
618
- if (!result.success) {
619
- const messages = result.error.issues.map((e) => e.message).join(", ");
620
- throw new Error(`invalid beacon payload: ${messages}`);
621
- }
622
- const payload = result.data;
623
- if (decoded.header.typ !== "did:dfos:beacon") {
624
- throw new Error(`invalid beacon typ: ${decoded.header.typ}`);
625
- }
626
- const kid = decoded.header.kid;
627
- const hashIdx = kid.indexOf("#");
628
- if (hashIdx < 0) throw new Error("beacon kid must be a DID URL");
629
- const kidDid = kid.substring(0, hashIdx);
630
- if (kidDid !== payload.did) {
631
- throw new Error("beacon kid DID does not match payload did");
632
- }
633
- const publicKey = await input.resolveKey(kid);
634
- try {
635
- verifyJws({ token: input.jwsToken, publicKey });
636
- } catch {
637
- throw new Error("invalid beacon signature");
638
- }
639
- const encoded = await dagCborCanonicalEncode(payload);
640
- const beaconCID = encoded.cid.toString();
641
- if (!decoded.header.cid) throw new Error("missing cid in beacon header");
642
- if (decoded.header.cid !== beaconCID) throw new Error("beacon cid mismatch");
643
- const now = input.now ?? Date.now();
644
- const beaconTime = new Date(payload.createdAt).getTime();
645
- if (beaconTime > now + MAX_FUTURE_MS) {
646
- throw new Error("beacon createdAt is too far in the future");
647
- }
648
- return {
649
- did: payload.did,
650
- manifestContentId: payload.manifestContentId,
651
- createdAt: payload.createdAt,
652
- signerKeyId: kid,
653
- beaconCID
654
- };
655
- };
656
-
657
676
  // src/chain/countersign.ts
658
677
  var signCountersignature = async (input) => {
659
678
  const encoded = await dagCborCanonicalEncode(input.payload);
@@ -697,7 +716,8 @@ var verifyCountersignature = async (input) => {
697
716
  return {
698
717
  countersignCID,
699
718
  witnessDID: payload.did,
700
- targetCID: payload.targetCID
719
+ targetCID: payload.targetCID,
720
+ ...payload.relation !== void 0 ? { relation: payload.relation } : {}
701
721
  };
702
722
  };
703
723
 
@@ -813,25 +833,34 @@ var verifyRevocation = async (input) => {
813
833
  };
814
834
 
815
835
  export {
836
+ MAX_SERVICES_ENTRIES,
837
+ MAX_SERVICES_PAYLOAD_SIZE,
816
838
  MultikeyPublicKey,
839
+ CONTENT_ID_ANCHOR_RE,
840
+ ARTIFACT_CID_ANCHOR_RE,
841
+ ServiceEntry,
842
+ ServicesArray,
817
843
  IdentityOperation,
818
844
  VerifiedIdentity,
819
845
  ContentOperation,
820
- BeaconPayload,
821
846
  MAX_ARTIFACT_PAYLOAD_SIZE,
822
847
  ArtifactPayload,
823
848
  CountersignPayload,
824
849
  RevocationPayload,
825
850
  deriveChainIdentifier,
826
851
  deriveContentId,
852
+ assertServicesWithinCap,
853
+ classifyAnchor,
854
+ RECOGNIZED_SERVICE_TYPES,
855
+ isRecognizedServiceType,
856
+ relayEndpoints,
857
+ anchorsByLabel,
827
858
  signIdentityOperation,
828
859
  verifyIdentityChain,
829
860
  verifyIdentityExtensionFromTrustedState,
830
861
  signContentOperation,
831
862
  verifyContentChain,
832
863
  verifyContentExtensionFromTrustedState,
833
- signBeacon,
834
- verifyBeacon,
835
864
  signCountersignature,
836
865
  verifyCountersignature,
837
866
  signArtifact,
@@ -1,5 +1,5 @@
1
1
  import { z } from 'zod';
2
- import { V as VerifiedIdentity } from '../schemas-BhikXSf_.js';
2
+ import { V as VerifiedIdentity } from '../schemas-Myod8ES9.js';
3
3
 
4
4
  /** Single attenuation entry — resource + action pair */
5
5
  declare const Attenuation: z.ZodObject<{
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export { JwsHeader, JwsVerificationError, JwtClaims, JwtCreateOptions, JwtHeader, JwtVerificationError, JwtVerifyOptions, PrefixedID, assertJwsProfile, base64urlDecode, base64urlEncode, createJws, createJwt, createNewEd25519Keypair, dagCborCanonicalEncode, decodeJwsUnsafe, decodeJwtUnsafe, generateId, generateIdNoPrefix, importEd25519Keypair, isCanonicallyEqual, isValidEd25519Signature, isValidId, normalizedId, parseDagCborCID, signPayloadEd25519, verifyJws, verifyJwt } from './crypto/index.js';
2
- export { A as ArtifactPayload, B as BeaconPayload, C as ContentOperation, a as CountersignPayload, I as IdentityOperation, M as MAX_ARTIFACT_PAYLOAD_SIZE, b as MultikeyPublicKey, R as RevocationPayload, S as Signer, V as VerifiedIdentity } from './schemas-BhikXSf_.js';
3
- export { ED25519_PRIV_MULTICODEC, ED25519_PUB_MULTICODEC, VerifiedArtifact, VerifiedBeacon, VerifiedContentChain, VerifiedCountersignature, VerifiedRevocation, decodeMultikey, deriveChainIdentifier, deriveContentId, encodeEd25519Multikey, signArtifact, signBeacon, signContentOperation, signCountersignature, signIdentityOperation, signRevocation, verifyArtifact, verifyBeacon, verifyContentChain, verifyContentExtensionFromTrustedState, verifyCountersignature, verifyIdentityChain, verifyIdentityExtensionFromTrustedState, verifyRevocation } from './chain/index.js';
2
+ export { A as ARTIFACT_CID_ANCHOR_RE, a as ArtifactPayload, C as CONTENT_ID_ANCHOR_RE, b as ContentOperation, c as CountersignPayload, I as IdentityOperation, M as MAX_ARTIFACT_PAYLOAD_SIZE, d as MAX_SERVICES_ENTRIES, e as MAX_SERVICES_PAYLOAD_SIZE, f as MultikeyPublicKey, R as RevocationPayload, S as ServiceEntry, g as ServicesArray, h as Signer, V as VerifiedIdentity } from './schemas-Myod8ES9.js';
3
+ export { AnchorKind, ED25519_PRIV_MULTICODEC, ED25519_PUB_MULTICODEC, RECOGNIZED_SERVICE_TYPES, VerifiedArtifact, VerifiedContentChain, VerifiedCountersignature, VerifiedRevocation, anchorsByLabel, assertServicesWithinCap, classifyAnchor, decodeMultikey, deriveChainIdentifier, deriveContentId, encodeEd25519Multikey, isRecognizedServiceType, relayEndpoints, signArtifact, signContentOperation, signCountersignature, signIdentityOperation, signRevocation, verifyArtifact, verifyContentChain, verifyContentExtensionFromTrustedState, verifyCountersignature, verifyIdentityChain, verifyIdentityExtensionFromTrustedState, verifyRevocation } from './chain/index.js';
4
4
  export { Attenuation, AuthTokenClaims, AuthTokenCreateOptions, AuthTokenVerificationError, AuthTokenVerifyOptions, CredentialVerificationError, DFOSCredentialPayload, VerifiedAuthToken, VerifiedDFOSCredential, VerifiedDelegationChain, createAuthToken, createDFOSCredential, decodeDFOSCredentialUnsafe, isAttenuated, matchesResource, verifyAuthToken, verifyDFOSCredential, verifyDelegationChain } from './credentials/index.js';
5
5
  import 'multiformats';
6
6
  import 'multiformats/cid';
package/dist/index.js CHANGED
@@ -1,30 +1,39 @@
1
1
  import {
2
+ ARTIFACT_CID_ANCHOR_RE,
2
3
  ArtifactPayload,
3
- BeaconPayload,
4
+ CONTENT_ID_ANCHOR_RE,
4
5
  ContentOperation,
5
6
  CountersignPayload,
6
7
  IdentityOperation,
7
8
  MAX_ARTIFACT_PAYLOAD_SIZE,
9
+ MAX_SERVICES_ENTRIES,
10
+ MAX_SERVICES_PAYLOAD_SIZE,
8
11
  MultikeyPublicKey,
12
+ RECOGNIZED_SERVICE_TYPES,
9
13
  RevocationPayload,
14
+ ServiceEntry,
15
+ ServicesArray,
10
16
  VerifiedIdentity,
17
+ anchorsByLabel,
18
+ assertServicesWithinCap,
19
+ classifyAnchor,
11
20
  deriveChainIdentifier,
12
21
  deriveContentId,
22
+ isRecognizedServiceType,
23
+ relayEndpoints,
13
24
  signArtifact,
14
- signBeacon,
15
25
  signContentOperation,
16
26
  signCountersignature,
17
27
  signIdentityOperation,
18
28
  signRevocation,
19
29
  verifyArtifact,
20
- verifyBeacon,
21
30
  verifyContentChain,
22
31
  verifyContentExtensionFromTrustedState,
23
32
  verifyCountersignature,
24
33
  verifyIdentityChain,
25
34
  verifyIdentityExtensionFromTrustedState,
26
35
  verifyRevocation
27
- } from "./chunk-GZ7ZAIRD.js";
36
+ } from "./chunk-SDUOUFTF.js";
28
37
  import {
29
38
  Attenuation,
30
39
  AuthTokenClaims,
@@ -69,11 +78,12 @@ import {
69
78
  verifyJwt
70
79
  } from "./chunk-GQOZJKKO.js";
71
80
  export {
81
+ ARTIFACT_CID_ANCHOR_RE,
72
82
  ArtifactPayload,
73
83
  Attenuation,
74
84
  AuthTokenClaims,
75
85
  AuthTokenVerificationError,
76
- BeaconPayload,
86
+ CONTENT_ID_ANCHOR_RE,
77
87
  ContentOperation,
78
88
  CountersignPayload,
79
89
  CredentialVerificationError,
@@ -84,12 +94,20 @@ export {
84
94
  JwsVerificationError,
85
95
  JwtVerificationError,
86
96
  MAX_ARTIFACT_PAYLOAD_SIZE,
97
+ MAX_SERVICES_ENTRIES,
98
+ MAX_SERVICES_PAYLOAD_SIZE,
87
99
  MultikeyPublicKey,
100
+ RECOGNIZED_SERVICE_TYPES,
88
101
  RevocationPayload,
102
+ ServiceEntry,
103
+ ServicesArray,
89
104
  VerifiedIdentity,
105
+ anchorsByLabel,
90
106
  assertJwsProfile,
107
+ assertServicesWithinCap,
91
108
  base64urlDecode,
92
109
  base64urlEncode,
110
+ classifyAnchor,
93
111
  createAuthToken,
94
112
  createDFOSCredential,
95
113
  createJws,
@@ -108,13 +126,14 @@ export {
108
126
  importEd25519Keypair,
109
127
  isAttenuated,
110
128
  isCanonicallyEqual,
129
+ isRecognizedServiceType,
111
130
  isValidEd25519Signature,
112
131
  isValidId,
113
132
  matchesResource,
114
133
  normalizedId,
115
134
  parseDagCborCID,
135
+ relayEndpoints,
116
136
  signArtifact,
117
- signBeacon,
118
137
  signContentOperation,
119
138
  signCountersignature,
120
139
  signIdentityOperation,
@@ -122,7 +141,6 @@ export {
122
141
  signRevocation,
123
142
  verifyArtifact,
124
143
  verifyAuthToken,
125
- verifyBeacon,
126
144
  verifyContentChain,
127
145
  verifyContentExtensionFromTrustedState,
128
146
  verifyCountersignature,
@@ -2,12 +2,46 @@ import { z } from 'zod';
2
2
 
3
3
  /** Function that signs a byte array and returns a signature */
4
4
  type Signer = (message: Uint8Array) => Promise<Uint8Array>;
5
+ /** Max number of service entries in an identity's services state */
6
+ declare const MAX_SERVICES_ENTRIES = 16;
7
+ /** Max CBOR-encoded size of the services array (bytes) — protocol constant */
8
+ declare const MAX_SERVICES_PAYLOAD_SIZE = 8192;
5
9
  declare const MultikeyPublicKey: z.ZodObject<{
6
10
  id: z.ZodString;
7
11
  type: z.ZodLiteral<"Multikey">;
8
12
  publicKeyMultibase: z.ZodString;
9
13
  }, z.core.$strict>;
10
14
  type MultikeyPublicKey = z.infer<typeof MultikeyPublicKey>;
15
+ /**
16
+ * Anchor target shapes — a ContentAnchor references a STABLE content
17
+ * identifier, dispatched by structural form:
18
+ * - 31-char contentId (content chain) → mutable, gateable
19
+ * - CIDv1 base32 (artifact) → immutable, public
20
+ * Both are stable; a chain HEAD CID (also base32 but resolves to a non-artifact
21
+ * op) is rejected by the shape-dispatch + resolution type check, never anchored.
22
+ */
23
+ declare const CONTENT_ID_ANCHOR_RE: RegExp;
24
+ declare const ARTIFACT_CID_ANCHOR_RE: RegExp;
25
+ /**
26
+ * Service entry — discovery vocabulary in identity-chain state.
27
+ *
28
+ * Open namespace: `type` is an arbitrary bounded string. Recognized types
29
+ * (`DfosRelay`, `ContentAnchor`) are structurally validated; UNRECOGNIZED types
30
+ * are preserved verbatim and ignored (MUST-ignore-unknown) — only the common
31
+ * envelope (id + type) and the byte cap apply. New service types therefore
32
+ * never require a protocol/cross-language change.
33
+ */
34
+ declare const ServiceEntry: z.ZodObject<{
35
+ id: z.ZodString;
36
+ type: z.ZodString;
37
+ }, z.core.$catchall<z.ZodUnknown>>;
38
+ type ServiceEntry = z.infer<typeof ServiceEntry>;
39
+ /** Identity services state — full-state, bounded, unique entry ids */
40
+ declare const ServicesArray: z.ZodArray<z.ZodObject<{
41
+ id: z.ZodString;
42
+ type: z.ZodString;
43
+ }, z.core.$catchall<z.ZodUnknown>>>;
44
+ type ServicesArray = z.infer<typeof ServicesArray>;
11
45
  declare const IdentityOperation: z.ZodDiscriminatedUnion<[z.ZodObject<{
12
46
  version: z.ZodLiteral<1>;
13
47
  type: z.ZodLiteral<"create">;
@@ -26,6 +60,10 @@ declare const IdentityOperation: z.ZodDiscriminatedUnion<[z.ZodObject<{
26
60
  type: z.ZodLiteral<"Multikey">;
27
61
  publicKeyMultibase: z.ZodString;
28
62
  }, z.core.$strict>>;
63
+ services: z.ZodOptional<z.ZodArray<z.ZodObject<{
64
+ id: z.ZodString;
65
+ type: z.ZodString;
66
+ }, z.core.$catchall<z.ZodUnknown>>>>;
29
67
  createdAt: z.ZodISODateTime;
30
68
  }, z.core.$strict>, z.ZodObject<{
31
69
  version: z.ZodLiteral<1>;
@@ -46,6 +84,10 @@ declare const IdentityOperation: z.ZodDiscriminatedUnion<[z.ZodObject<{
46
84
  type: z.ZodLiteral<"Multikey">;
47
85
  publicKeyMultibase: z.ZodString;
48
86
  }, z.core.$strict>>;
87
+ services: z.ZodOptional<z.ZodArray<z.ZodObject<{
88
+ id: z.ZodString;
89
+ type: z.ZodString;
90
+ }, z.core.$catchall<z.ZodUnknown>>>>;
49
91
  createdAt: z.ZodISODateTime;
50
92
  }, z.core.$strict>, z.ZodObject<{
51
93
  version: z.ZodLiteral<1>;
@@ -72,6 +114,10 @@ declare const VerifiedIdentity: z.ZodObject<{
72
114
  type: z.ZodLiteral<"Multikey">;
73
115
  publicKeyMultibase: z.ZodString;
74
116
  }, z.core.$strict>>;
117
+ services: z.ZodArray<z.ZodObject<{
118
+ id: z.ZodString;
119
+ type: z.ZodString;
120
+ }, z.core.$catchall<z.ZodUnknown>>>;
75
121
  }, z.core.$strict>;
76
122
  type VerifiedIdentity = z.infer<typeof VerifiedIdentity>;
77
123
  declare const ContentOperation: z.ZodDiscriminatedUnion<[z.ZodObject<{
@@ -102,15 +148,6 @@ declare const ContentOperation: z.ZodDiscriminatedUnion<[z.ZodObject<{
102
148
  authorization: z.ZodOptional<z.ZodString>;
103
149
  }, z.core.$strict>], "type">;
104
150
  type ContentOperation = z.infer<typeof ContentOperation>;
105
- /** Beacon: floating signed manifest pointer announcement */
106
- declare const BeaconPayload: z.ZodObject<{
107
- version: z.ZodLiteral<1>;
108
- type: z.ZodLiteral<"beacon">;
109
- did: z.ZodString;
110
- manifestContentId: z.ZodString;
111
- createdAt: z.ZodISODateTime;
112
- }, z.core.$strict>;
113
- type BeaconPayload = z.infer<typeof BeaconPayload>;
114
151
  /** Max CBOR-encoded payload size for artifacts (bytes) — protocol constant */
115
152
  declare const MAX_ARTIFACT_PAYLOAD_SIZE = 16384;
116
153
  /** Artifact: standalone signed inline document, immutable, CID-addressable */
@@ -124,16 +161,25 @@ declare const ArtifactPayload: z.ZodObject<{
124
161
  createdAt: z.ZodISODateTime;
125
162
  }, z.core.$strict>;
126
163
  type ArtifactPayload = z.infer<typeof ArtifactPayload>;
127
- /** Countersign: standalone witness attestation referencing a target operation by CID */
164
+ /**
165
+ * Countersign: standalone witness attestation referencing a target operation by CID.
166
+ *
167
+ * `relation` is an OPEN-namespace tag naming the nature of the attestation
168
+ * (e.g. `coauthors`, `endorses`, `witnessed`, `holds`, `received`). It is an
169
+ * arbitrary bounded string — recognized values carry social meaning to clients,
170
+ * unrecognized values MUST be preserved and ignored. Optional, so a bare witness
171
+ * attestation (no relation) encodes identically (CID-neutral).
172
+ */
128
173
  declare const CountersignPayload: z.ZodObject<{
129
174
  version: z.ZodLiteral<1>;
130
175
  type: z.ZodLiteral<"countersign">;
131
176
  did: z.ZodString;
132
177
  targetCID: z.ZodString;
178
+ relation: z.ZodOptional<z.ZodString>;
133
179
  createdAt: z.ZodISODateTime;
134
180
  }, z.core.$strict>;
135
181
  type CountersignPayload = z.infer<typeof CountersignPayload>;
136
- /** Revocation: signed credential revocation artifact, gossiped like beacons */
182
+ /** Revocation: signed credential revocation artifact, gossiped on the proof plane */
137
183
  declare const RevocationPayload: z.ZodObject<{
138
184
  version: z.ZodLiteral<1>;
139
185
  type: z.ZodLiteral<"revocation">;
@@ -143,4 +189,4 @@ declare const RevocationPayload: z.ZodObject<{
143
189
  }, z.core.$strict>;
144
190
  type RevocationPayload = z.infer<typeof RevocationPayload>;
145
191
 
146
- export { ArtifactPayload as A, BeaconPayload as B, ContentOperation as C, IdentityOperation as I, MAX_ARTIFACT_PAYLOAD_SIZE as M, RevocationPayload as R, type Signer as S, VerifiedIdentity as V, CountersignPayload as a, MultikeyPublicKey as b };
192
+ export { ARTIFACT_CID_ANCHOR_RE as A, CONTENT_ID_ANCHOR_RE as C, IdentityOperation as I, MAX_ARTIFACT_PAYLOAD_SIZE as M, RevocationPayload as R, ServiceEntry as S, VerifiedIdentity as V, ArtifactPayload as a, ContentOperation as b, CountersignPayload as c, MAX_SERVICES_ENTRIES as d, MAX_SERVICES_PAYLOAD_SIZE as e, MultikeyPublicKey as f, ServicesArray as g, type Signer as h };
@@ -0,0 +1,38 @@
1
+ {
2
+ "description": "Identity chain: genesis publishing a services set (relay locator + content/artifact anchors)",
3
+ "type": "identity",
4
+ "chain": [
5
+ "eyJhbGciOiJFZERTQSIsInR5cCI6ImRpZDpkZm9zOmlkZW50aXR5LW9wIiwia2lkIjoia2V5X3I5ZXYzNGZ2YzIzejk5OXZlYWFmdDgzbm4yOXp2aGUiLCJjaWQiOiJiYWZ5cmVpZGkzcXBzM3F0dHFwMjJtM3kzM2JkYmYyaXlrYnE1cjQ1ampod2EzN21nZXNvdjdzZGd6ZSJ9.eyJ2ZXJzaW9uIjoxLCJ0eXBlIjoiY3JlYXRlIiwiYXV0aEtleXMiOlt7ImlkIjoia2V5X3I5ZXYzNGZ2YzIzejk5OXZlYWFmdDgzbm4yOXp2aGUiLCJ0eXBlIjoiTXVsdGlrZXkiLCJwdWJsaWNLZXlNdWx0aWJhc2UiOiJ6Nk1rcnpMTU53b0pTVjRQM1ljY1djYnRrOHZkOUx0Z01LbkxlYURMVXFMdUFTamIifV0sImFzc2VydEtleXMiOlt7ImlkIjoia2V5X3I5ZXYzNGZ2YzIzejk5OXZlYWFmdDgzbm4yOXp2aGUiLCJ0eXBlIjoiTXVsdGlrZXkiLCJwdWJsaWNLZXlNdWx0aWJhc2UiOiJ6Nk1rcnpMTU53b0pTVjRQM1ljY1djYnRrOHZkOUx0Z01LbkxlYURMVXFMdUFTamIifV0sImNvbnRyb2xsZXJLZXlzIjpbeyJpZCI6ImtleV9yOWV2MzRmdmMyM3o5OTl2ZWFhZnQ4M25uMjl6dmhlIiwidHlwZSI6Ik11bHRpa2V5IiwicHVibGljS2V5TXVsdGliYXNlIjoiejZNa3J6TE1Od29KU1Y0UDNZY2NXY2J0azh2ZDlMdGdNS25MZWFETFVxTHVBU2piIn1dLCJzZXJ2aWNlcyI6W3siaWQiOiJyZWxheSIsInR5cGUiOiJEZm9zUmVsYXkiLCJlbmRwb2ludCI6Imh0dHBzOi8vcmVsYXkuZGZvcy5jb20ifSx7ImlkIjoicHJvZmlsZSIsInR5cGUiOiJDb250ZW50QW5jaG9yIiwibGFiZWwiOiJwcm9maWxlIiwiYW5jaG9yIjoiY3Y3bjh2a3ZyNjRjY3RmMzI5NGg5azRlYW5oZmY4eiJ9LHsiaWQiOiJhdmF0YXIiLCJ0eXBlIjoiQ29udGVudEFuY2hvciIsImxhYmVsIjoiYXZhdGFyIiwiYW5jaG9yIjoiYmFmeXJlaWV2Y3FybXZ0ejJwaXM1dGRpenQ3c2pvdG9xcW9nbDZ2cnJxZ2E2NHcydG53a3Eycm51ZHkifV0sImNyZWF0ZWRBdCI6IjIwMjYtMDMtMDdUMDA6MDU6MDAuMDAwWiJ9.HCzVJXcUzL62lxtC8omBlit1JNSWk4b4kQKjjjWT00honzZ9-k3dKusIRuhTV6gjT1M74bLVZYUxPb8kJvhHAw"
6
+ ],
7
+ "controllerPublicKey": "z6MkrzLMNwoJSV4P3YccWcbtk8vd9LtgMKnLeaDLUqLuASjb",
8
+ "expected": {
9
+ "did": "did:dfos:zhkrrzrd7z623ha8tt7dt699de8r3ar",
10
+ "isDeleted": false,
11
+ "controllerKeys": [
12
+ {
13
+ "id": "key_r9ev34fvc23z999veaaft83nn29zvhe",
14
+ "type": "Multikey",
15
+ "publicKeyMultibase": "z6MkrzLMNwoJSV4P3YccWcbtk8vd9LtgMKnLeaDLUqLuASjb"
16
+ }
17
+ ],
18
+ "services": [
19
+ {
20
+ "id": "relay",
21
+ "type": "DfosRelay",
22
+ "endpoint": "https://relay.dfos.com"
23
+ },
24
+ {
25
+ "id": "profile",
26
+ "type": "ContentAnchor",
27
+ "label": "profile",
28
+ "anchor": "cv7n8vkvr64cctf3294h9k4eanhff8z"
29
+ },
30
+ {
31
+ "id": "avatar",
32
+ "type": "ContentAnchor",
33
+ "label": "avatar",
34
+ "anchor": "bafyreievcqrmvtz2pis5tdizt7sjotoqqogl6vrrqga64w2tnwkq2rnudy"
35
+ }
36
+ ]
37
+ }
38
+ }
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@metalabel/dfos-protocol",
3
- "version": "0.10.0",
3
+ "version": "0.11.0",
4
4
  "type": "module",
5
- "description": "DFOS Protocol — Ed25519 signed chain primitives, beacons, credentials, and verification",
5
+ "description": "DFOS Protocol — Ed25519 signed chain primitives, services, credentials, and verification",
6
6
  "license": "MIT",
7
7
  "author": "Metalabel <hello@metalabel.com> (https://metalabel.com)",
8
8
  "repository": {
@@ -1,14 +0,0 @@
1
- {
2
- "description": "Beacon: signed manifest content ID announcement with witness countersignature",
3
- "type": "beacon",
4
- "controllerJws": "eyJhbGciOiJFZERTQSIsInR5cCI6ImRpZDpkZm9zOmJlYWNvbiIsImtpZCI6ImRpZDpkZm9zOmNubm5mdDlmOGEycm45MzhkNm5rejM4cjg0N3Yya3Ija2V5X3I5ZXYzNGZ2YzIzejk5OXZlYWFmdDgzbm4yOXp2aGUiLCJjaWQiOiJiYWZ5cmVpYjR3MnAydTZ0bHc3N3NidGtwdnc3ZnF2d3ZrNnJ3MzdweWFtM29zb2JvNXhwM29vZWt1cSJ9.eyJ2ZXJzaW9uIjoxLCJ0eXBlIjoiYmVhY29uIiwiZGlkIjoiZGlkOmRmb3M6Y25ubmZ0OWY4YTJybjkzOGQ2bmt6MzhyODQ3djJrciIsIm1hbmlmZXN0Q29udGVudElkIjoiY3Y3bjh2a3ZyNjRjY3RmMzI5NGg5azRlYW5oZmY4eiIsImNyZWF0ZWRBdCI6IjIwMjYtMDMtMDdUMDA6MDU6MDAuMDAwWiJ9.exr0Dfb_asVXeMpnUOaql9ppeO2pifzEdId8ocXHQ6-v_XUwccQdJaL4MhKzJGUbRAa0hfRVSFRndhjJ4NN1DA",
5
- "witnessJws": "eyJhbGciOiJFZERTQSIsInR5cCI6ImRpZDpkZm9zOmJlYWNvbiIsImtpZCI6ImRpZDpkZm9zOmNubm5mdDlmOGEycm45MzhkNm5rejM4cjg0N3Yya3Ija2V5X2V6OWE4NzR0Y2tyM2R2OTMzZDNja2RuN3o2enJjdDgiLCJjaWQiOiJiYWZ5cmVpYjR3MnAydTZ0bHc3N3NidGtwdnc3ZnF2d3ZrNnJ3MzdweWFtM29zb2JvNXhwM29vZWt1cSJ9.eyJ2ZXJzaW9uIjoxLCJ0eXBlIjoiYmVhY29uIiwiZGlkIjoiZGlkOmRmb3M6Y25ubmZ0OWY4YTJybjkzOGQ2bmt6MzhyODQ3djJrciIsIm1hbmlmZXN0Q29udGVudElkIjoiY3Y3bjh2a3ZyNjRjY3RmMzI5NGg5azRlYW5oZmY4eiIsImNyZWF0ZWRBdCI6IjIwMjYtMDMtMDdUMDA6MDU6MDAuMDAwWiJ9.-49R4npkmKMJtnK4sVS_x7MFOgB1RhjkZAzwycLp80g_o6y0gV0JjnUAj12as8NglccBXEk_5DdZTFs17ygKCA",
6
- "controllerPublicKey": "z6MkrzLMNwoJSV4P3YccWcbtk8vd9LtgMKnLeaDLUqLuASjb",
7
- "witnessPublicKey": "z6MkfUd65JrAhfdgFuMCccU9ThQvjB2fJAMUHkuuajF992gK",
8
- "expected": {
9
- "beaconCID": "bafyreib4w2p2u6tlw77sbtkpvw7fqvwvk6rw37pyam3osobo5xp3ooekuq",
10
- "did": "did:dfos:cnnnft9f8a2rn938d6nkz38r847v2kr",
11
- "manifestContentId": "cv7n8vkvr64cctf3294h9k4eanhff8z",
12
- "createdAt": "2026-03-07T00:05:00.000Z"
13
- }
14
- }
@@ -1,29 +0,0 @@
1
- {
2
- "$schema": "https://json-schema.org/draft/2020-12/schema",
3
- "$id": "https://schemas.dfos.com/manifest/v1",
4
- "title": "Manifest",
5
- "description": "A manifest — a named map of protocol object references for semantic navigation. Keys are path-like labels. Values are protocol references: content chain identifiers (31-char bare hash), DIDs (did:dfos:...), or CIDs (bafyrei...). The document layer of the dark forest. Discovery is social or out-of-band.",
6
- "type": "object",
7
- "required": ["$schema", "entries"],
8
- "properties": {
9
- "$schema": {
10
- "const": "https://schemas.dfos.com/manifest/v1"
11
- },
12
- "entries": {
13
- "type": "object",
14
- "propertyNames": {
15
- "pattern": "^[a-z0-9][a-z0-9._/-]*[a-z0-9]$",
16
- "minLength": 2,
17
- "maxLength": 128
18
- },
19
- "additionalProperties": {
20
- "type": "string",
21
- "pattern": "^[a-z0-9][a-z0-9:._/-]*$",
22
- "minLength": 1,
23
- "maxLength": 512
24
- },
25
- "description": "Named entries mapping path-like keys to protocol object references (contentId, DID, or CID)."
26
- }
27
- },
28
- "additionalProperties": false
29
- }