@metalabel/dfos-protocol 0.52.1 → 0.53.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.
@@ -86,6 +86,25 @@ declare const verifyIdentityChain: (input: {
86
86
  */
87
87
  asOf?: string;
88
88
  }) => Promise<VerifiedIdentity>;
89
+ /**
90
+ * The trusted state cannot be extended incrementally: it does not carry the
91
+ * chain-wide id-to-material binding. The caller replays the log.
92
+ *
93
+ * THERE IS NO RECONSTRUCTION, and that is the whole point. `seenKeys` is a
94
+ * monotonic index that never forgets a key id once the chain declared it — even
95
+ * after the id is dropped from the declared arrays — and nothing else in the
96
+ * state remembers it: an id introduced without a proof and then removed is in
97
+ * neither `declared` (removed) nor `provedKeys` (never proved). Reading the
98
+ * binding off those two arrays therefore treats a re-declaration of that id,
99
+ * bound to DIFFERENT material, as a fresh introduction and accepts it — while a
100
+ * full replay of the same operations rejects it. A fast path that accepts what
101
+ * its own re-verification refuses is worse than one that says it cannot answer.
102
+ *
103
+ * The Go twin is `ErrIdentityStateNoSeenKeys`, with this exact message.
104
+ */
105
+ declare class IdentityStateNoSeenKeysError extends Error {
106
+ constructor();
107
+ }
89
108
  /**
90
109
  * Verify a single new operation against already-verified identity state
91
110
  *
@@ -100,7 +119,8 @@ declare const verifyIdentityChain: (input: {
100
119
  * is REJECTED on this path exactly as a replay of the same two operations would
101
120
  * reject it. Without that the fast path would accept a chain its own
102
121
  * re-verification refuses, and a relay's linear path is the path almost every
103
- * operation takes.
122
+ * operation takes. A state that does not carry `seenKeys` is therefore not
123
+ * extensible at all — see `IdentityStateNoSeenKeysError`.
104
124
  *
105
125
  * THE POSSESSION FOLD RUNS HERE TOO, and it needs both halves of the trusted
106
126
  * state: the EFFECTIVE arrays (to know what an introduction is a transition out
@@ -130,8 +150,16 @@ type AnchorKind = 'chain' | 'artifact' | 'invalid';
130
150
  * Enforce the services byte cap on the CBOR-encoded array — same encoding the
131
151
  * wire uses, so the bound is identical across implementations. Mirrors the
132
152
  * artifact payload size check.
153
+ *
154
+ * MEASURE THE RAW DECODED PAYLOAD'S ARRAY, never zod's output. The parameter is
155
+ * `unknown` to make that hard to get wrong: the schema is a validator, not a
156
+ * canonicalizer, and its output object is freshly built — a `__proto__` data
157
+ * member (constructible only by `JSON.parse`) does not survive the copy. Handing
158
+ * this the parsed `op.services` measured 19 bytes for a 33,032-byte signed
159
+ * array, which Go's `parseServices` — reading the wire map directly — rejects.
160
+ * Same rule as the operation CID, and for the same reason.
133
161
  */
134
- declare const assertServicesWithinCap: (services: ServiceEntry[]) => Promise<void>;
162
+ declare const assertServicesWithinCap: (services: unknown) => Promise<void>;
135
163
  /**
136
164
  * Classify a ContentAnchor target by structural form. Resolvers dispatch on the
137
165
  * result: 'chain' → resolve a content chain by contentId; 'artifact' → fetch by
@@ -560,4 +588,4 @@ declare const assertCanonicalSignRequestPayload: (payloadTyp: string, payloadByt
560
588
  subject: string;
561
589
  }) => void;
562
590
 
563
- export { type AnchorKind, ArtifactPayload, ContentOperation, CountersignPayload, type CreditClaimFailureReason, CreditClaimVerifyError, type CreditEntry, type CreditEntryState, ED25519_PRIV_MULTICODEC, ED25519_PUB_MULTICODEC, IdentityOperation, RECOGNIZED_SERVICE_TYPES, ServiceEntry, type SignRequestFailureReason, SignRequestVerifyError, Signer, type VerifiedArtifact, type VerifiedContentChain, type VerifiedCountersignature, type VerifiedCreditClaim, type VerifiedCreditEntry, VerifiedIdentity, type VerifiedRevocation, type VerifiedSignRequest, anchorsByLabel, assertCanonicalSignRequestPayload, assertServicesWithinCap, buildSignRequest, classifyAnchor, decodeEd25519PublicMultikey, decodeMultikey, deriveChainIdentifier, deriveContentId, encodeEd25519Multikey, isRecognizedServiceType, relayEndpoints, signArtifact, signContentOperation, signCountersignature, signCreditClaim, signIdentityOperation, signRevocation, verifyArtifact, verifyContentChain, verifyContentExtensionFromTrustedState, verifyCountersignature, verifyCreditClaim, verifyCreditEntry, verifyIdentityChain, verifyIdentityExtensionFromTrustedState, verifyRevocation, verifySignRequest };
591
+ export { type AnchorKind, ArtifactPayload, ContentOperation, CountersignPayload, type CreditClaimFailureReason, CreditClaimVerifyError, type CreditEntry, type CreditEntryState, ED25519_PRIV_MULTICODEC, ED25519_PUB_MULTICODEC, IdentityOperation, IdentityStateNoSeenKeysError, RECOGNIZED_SERVICE_TYPES, ServiceEntry, type SignRequestFailureReason, SignRequestVerifyError, Signer, type VerifiedArtifact, type VerifiedContentChain, type VerifiedCountersignature, type VerifiedCreditClaim, type VerifiedCreditEntry, VerifiedIdentity, type VerifiedRevocation, type VerifiedSignRequest, anchorsByLabel, assertCanonicalSignRequestPayload, assertServicesWithinCap, buildSignRequest, classifyAnchor, decodeEd25519PublicMultikey, decodeMultikey, deriveChainIdentifier, deriveContentId, encodeEd25519Multikey, isRecognizedServiceType, relayEndpoints, signArtifact, signContentOperation, signCountersignature, signCreditClaim, signIdentityOperation, signRevocation, verifyArtifact, verifyContentChain, verifyContentExtensionFromTrustedState, verifyCountersignature, verifyCreditClaim, verifyCreditEntry, verifyIdentityChain, verifyIdentityExtensionFromTrustedState, verifyRevocation, verifySignRequest };
@@ -8,6 +8,7 @@ import {
8
8
  CreditClaimVerifyError,
9
9
  DeclaredKeyState,
10
10
  IdentityOperation,
11
+ IdentityStateNoSeenKeysError,
11
12
  Iso8601,
12
13
  MAX_ARTIFACT_PAYLOAD_SIZE,
13
14
  MAX_CREDIT_CLAIM_SIZE,
@@ -52,9 +53,9 @@ import {
52
53
  verifyIdentityExtensionFromTrustedState,
53
54
  verifyRevocation,
54
55
  verifySignRequest
55
- } from "../chunk-Q7FREWMY.js";
56
- import "../chunk-FZHHSC5N.js";
57
- import "../chunk-BMIOY5W5.js";
56
+ } from "../chunk-WBFWGQTS.js";
57
+ import "../chunk-VEKRLXZ5.js";
58
+ import "../chunk-ISHAX5WN.js";
58
59
  import {
59
60
  ED25519_PRIV_MULTICODEC,
60
61
  ED25519_PUB_MULTICODEC,
@@ -62,7 +63,7 @@ import {
62
63
  decodeMultikey,
63
64
  encodeEd25519Multikey
64
65
  } from "../chunk-F7RHI2CK.js";
65
- import "../chunk-KAW4MT4P.js";
66
+ import "../chunk-NUIIVAZ3.js";
66
67
  export {
67
68
  ARTIFACT_CID_ANCHOR_RE,
68
69
  ArtifactPayload,
@@ -75,6 +76,7 @@ export {
75
76
  ED25519_PRIV_MULTICODEC,
76
77
  ED25519_PUB_MULTICODEC,
77
78
  IdentityOperation,
79
+ IdentityStateNoSeenKeysError,
78
80
  Iso8601,
79
81
  MAX_ARTIFACT_PAYLOAD_SIZE,
80
82
  MAX_CREDIT_CLAIM_SIZE,
@@ -9,7 +9,7 @@ import {
9
9
  isValidEd25519Signature,
10
10
  sha256,
11
11
  signPayloadEd25519
12
- } from "./chunk-KAW4MT4P.js";
12
+ } from "./chunk-NUIIVAZ3.js";
13
13
 
14
14
  // src/key-proof/role-set.ts
15
15
  var KEY_ROLES = ["auth", "assert", "controller"];
@@ -161,10 +161,15 @@ var assertJwsProfile = (header, makeError) => {
161
161
  var decodeJwsSegment = (segmentB64) => {
162
162
  let text;
163
163
  try {
164
- text = new TextDecoder("utf-8", { fatal: true }).decode(base64urlDecode(segmentB64));
164
+ text = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(
165
+ base64urlDecode(segmentB64)
166
+ );
165
167
  } catch {
166
168
  return null;
167
169
  }
170
+ if (text.charCodeAt(0) === 65279) {
171
+ throw new Error("leading byte order mark is not canonicalizable");
172
+ }
168
173
  assertCanonicalJsonText(text);
169
174
  let value;
170
175
  try {
@@ -10,7 +10,7 @@ import {
10
10
  decodeJwsUnsafe,
11
11
  sha256,
12
12
  verifyJws
13
- } from "./chunk-KAW4MT4P.js";
13
+ } from "./chunk-NUIIVAZ3.js";
14
14
 
15
15
  // src/credentials/schemas.ts
16
16
  import { z } from "zod";
@@ -6,13 +6,13 @@ import {
6
6
  matchesResource,
7
7
  verifyDFOSCredential,
8
8
  verifyDelegationChain
9
- } from "./chunk-FZHHSC5N.js";
9
+ } from "./chunk-VEKRLXZ5.js";
10
10
  import {
11
11
  KEY_ADD_JWS_TYP,
12
12
  KEY_ROLES,
13
13
  unsafeKeyProofSubject,
14
14
  verifyChainKeyProof
15
- } from "./chunk-BMIOY5W5.js";
15
+ } from "./chunk-ISHAX5WN.js";
16
16
  import {
17
17
  decodeEd25519PublicMultikey
18
18
  } from "./chunk-F7RHI2CK.js";
@@ -25,7 +25,7 @@ import {
25
25
  decodeJwsUnsafe,
26
26
  generateIdNoPrefix,
27
27
  verifyJws
28
- } from "./chunk-KAW4MT4P.js";
28
+ } from "./chunk-NUIIVAZ3.js";
29
29
 
30
30
  // src/chain/schemas.ts
31
31
  import { z } from "zod";
@@ -540,7 +540,7 @@ var verifyIdentityChain = async (input) => {
540
540
  });
541
541
  if (op.services) {
542
542
  try {
543
- await assertServicesWithinCap(op.services);
543
+ await assertServicesWithinCap(decoded.payload["services"]);
544
544
  } catch (e) {
545
545
  throw new Error(`log[${idx}]: ${e.message}`);
546
546
  }
@@ -661,14 +661,19 @@ var verifyIdentityChain = async (input) => {
661
661
  seenKeys: [...state.seenKeys.values()]
662
662
  };
663
663
  };
664
+ var IdentityStateNoSeenKeysError = class extends Error {
665
+ constructor() {
666
+ super("identity state has no seenKeys; replay the chain");
667
+ this.name = "IdentityStateNoSeenKeysError";
668
+ }
669
+ };
664
670
  var verifyIdentityExtensionFromTrustedState = async (input) => {
665
671
  const { currentState, headCID, lastCreatedAt, newOp } = input;
666
672
  const priorEffective = keyStateOf(currentState);
667
673
  const priorDeclared = currentState.declared ?? priorEffective;
668
674
  const priorProved = currentState.provedKeys ?? priorEffective;
669
- const seenKeys = keyMaterialIndex(
670
- currentState.seenKeys ?? [...flatKeys(priorDeclared), ...flatKeys(priorProved)]
671
- );
675
+ if (!currentState.seenKeys?.length) throw new IdentityStateNoSeenKeysError();
676
+ const seenKeys = keyMaterialIndex(currentState.seenKeys);
672
677
  const priorSeenKeys = [...seenKeys.values()];
673
678
  const decoded = decodeJwsUnsafe(newOp);
674
679
  if (!decoded) throw new Error("failed to decode JWS");
@@ -733,7 +738,7 @@ var verifyIdentityExtensionFromTrustedState = async (input) => {
733
738
  throw new Error("cannot repeat key ids in same usage");
734
739
  }
735
740
  });
736
- if (op.services) await assertServicesWithinCap(op.services);
741
+ if (op.services) await assertServicesWithinCap(decoded.payload["services"]);
737
742
  }
738
743
  const newState = (() => {
739
744
  switch (op.type) {
@@ -1679,6 +1684,7 @@ export {
1679
1684
  anchorsByLabel,
1680
1685
  signIdentityOperation,
1681
1686
  verifyIdentityChain,
1687
+ IdentityStateNoSeenKeysError,
1682
1688
  verifyIdentityExtensionFromTrustedState,
1683
1689
  signContentOperation,
1684
1690
  verifyContentChain,
@@ -34,9 +34,9 @@ import {
34
34
  verifyDelegationChain,
35
35
  verifyIdentityProofEnvelope,
36
36
  verifyRequestProofEnvelope
37
- } from "../chunk-FZHHSC5N.js";
37
+ } from "../chunk-VEKRLXZ5.js";
38
38
  import "../chunk-F7RHI2CK.js";
39
- import "../chunk-KAW4MT4P.js";
39
+ import "../chunk-NUIIVAZ3.js";
40
40
  export {
41
41
  ApiRequestVerifyError,
42
42
  Attenuation,
@@ -23,7 +23,7 @@ import {
23
23
  signPayloadEd25519,
24
24
  verifyJws,
25
25
  verifyJwt
26
- } from "../chunk-KAW4MT4P.js";
26
+ } from "../chunk-NUIIVAZ3.js";
27
27
  export {
28
28
  JwsVerificationError,
29
29
  JwtVerificationError,
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export { JwsHeader, JwsVerificationError, JwtClaims, JwtCreateOptions, JwtHeader, JwtVerificationError, JwtVerifyOptions, PrefixedID, assertCanonicalJsonText, assertJwsProfile, base64urlDecode, base64urlEncode, createJws, createJwt, createNewEd25519Keypair, dagCborCanonicalEncode, decodeJwsUnsafe, decodeJwtUnsafe, generateId, generateIdNoPrefix, importEd25519Keypair, isCanonicallyEqual, isValidEd25519Signature, isValidId, normalizedId, parseDagCborCID, sha256, signPayloadEd25519, verifyJws, verifyJwt } from './crypto/index.js';
2
2
  export { A as ARTIFACT_CID_ANCHOR_RE, a as ArtifactPayload, b as Attenuation, C as CONTENT_ID_ANCHOR_RE, c as ContentOperation, d as CountersignPayload, e as CredentialVerificationError, f as CreditClaimPayload, D as DFOSCredentialPayload, g as DeclaredKeyState, I as IdentityOperation, h as Iso8601, M as MAX_ARTIFACT_PAYLOAD_SIZE, i as MAX_CREDENTIAL_SIZE, j as MAX_CREDIT_CLAIM_SIZE, k as MAX_KEY_PROOFS, l as MAX_OPERATION_SIZE, m as MAX_SERVICES_ENTRIES, n as MAX_SERVICES_PAYLOAD_SIZE, o as MAX_SIGN_REQUEST_PAYLOAD_SIZE, p as MAX_SIGN_REQUEST_SIZE, q as MultikeyPublicKey, R as ResolvedIdentity, r as RevocationChecker, s as RevocationPayload, S as ServiceEntry, t as ServicesArray, u as SignRequestPayload, v as Signer, V as VerifiedDFOSCredential, w as VerifiedDelegationChain, x as VerifiedIdentity, y as VoidKeyMembership, z as createDFOSCredential, B as decodeDFOSCredentialUnsafe, E as isAttenuated, F as matchesResource, G as parseProtocolTimestampUnix, H as verifyDFOSCredential, J as verifyDelegationChain } from './dfos-credential-j-kHtFvG.js';
3
- export { AnchorKind, CreditClaimFailureReason, CreditClaimVerifyError, CreditEntry, CreditEntryState, ED25519_PRIV_MULTICODEC, ED25519_PUB_MULTICODEC, RECOGNIZED_SERVICE_TYPES, SignRequestFailureReason, SignRequestVerifyError, VerifiedArtifact, VerifiedContentChain, VerifiedCountersignature, VerifiedCreditClaim, VerifiedCreditEntry, VerifiedRevocation, VerifiedSignRequest, anchorsByLabel, assertCanonicalSignRequestPayload, assertServicesWithinCap, buildSignRequest, classifyAnchor, decodeEd25519PublicMultikey, decodeMultikey, deriveChainIdentifier, deriveContentId, encodeEd25519Multikey, isRecognizedServiceType, relayEndpoints, signArtifact, signContentOperation, signCountersignature, signCreditClaim, signIdentityOperation, signRevocation, verifyArtifact, verifyContentChain, verifyContentExtensionFromTrustedState, verifyCountersignature, verifyCreditClaim, verifyCreditEntry, verifyIdentityChain, verifyIdentityExtensionFromTrustedState, verifyRevocation, verifySignRequest } from './chain/index.js';
3
+ export { AnchorKind, CreditClaimFailureReason, CreditClaimVerifyError, CreditEntry, CreditEntryState, ED25519_PRIV_MULTICODEC, ED25519_PUB_MULTICODEC, IdentityStateNoSeenKeysError, RECOGNIZED_SERVICE_TYPES, SignRequestFailureReason, SignRequestVerifyError, VerifiedArtifact, VerifiedContentChain, VerifiedCountersignature, VerifiedCreditClaim, VerifiedCreditEntry, VerifiedRevocation, VerifiedSignRequest, anchorsByLabel, assertCanonicalSignRequestPayload, assertServicesWithinCap, buildSignRequest, classifyAnchor, decodeEd25519PublicMultikey, decodeMultikey, deriveChainIdentifier, deriveContentId, encodeEd25519Multikey, isRecognizedServiceType, relayEndpoints, signArtifact, signContentOperation, signCountersignature, signCreditClaim, signIdentityOperation, signRevocation, verifyArtifact, verifyContentChain, verifyContentExtensionFromTrustedState, verifyCountersignature, verifyCreditClaim, verifyCreditEntry, verifyIdentityChain, verifyIdentityExtensionFromTrustedState, verifyRevocation, verifySignRequest } from './chain/index.js';
4
4
  export { ApiRequestVerifyError, DEFAULT_PROOF_SKEW_SECONDS, DEFAULT_PROOF_WINDOW_SECONDS, DFOS_AUTH_SCHEME, EMPTY_BODY_SHA256, IDENTITY_PROOF_JWS_TYP, IdentityProofPayload, MAX_BODY_BYTES, MAX_PROOF_FRESHNESS_SPAN_SECONDS, MAX_REQUEST_PROOF_SIZE, ParsedProofPayload, ProofEnvelopeInput, ProofExtraMembers, ProofPresenterState, REQUEST_PROOF_JWS_TYP, RequestProofFailurePhase, RequestProofFailureReason, RequestProofPayload, ResolveProofPresenter, SignApiIdentityRequestInput, SignApiRequestInput, VerifiedProofEnvelope, apiIdentitySigningInput, apiRequestSigningInput, assertProofVerifierConfig, buildApiAuthHeaders, buildApiIdentityHeaders, canonicalExtraMembers, invalidProof, misconfiguredProof, parseDfosAuthorization, sha256BodyHash, signApiIdentityRequest, signApiRequest, unverifiableProof, verifyIdentityProofEnvelope, verifyRequestProofEnvelope } from './credentials/index.js';
5
5
  export { DEFAULT_KEY_PROOF_SKEW_SECONDS, KEY_ADD_JWS_TYP, KEY_ROLES, KeyProofFailureReason, KeyProofPayload, KeyProofVerifyError, KeyRole, MAX_KEY_PROOF_SIZE, SignKeyProofInput, VerifiedKeyProof, VerifyChainKeyProofOptions, VerifyKeyProofOptions, isCanonicalRoleSet, keyProofSigningInput, keyWordFingerprint, parseRoleSet, roleSetCovers, serializeRoleSet, signKeyProof, unsafeKeyProofSubject, verifyChainKeyProof, verifyKeyProof } from './key-proof/index.js';
6
6
  export { FoldOperation, INDEX_V1_SCHEMA, IndexDelta, IndexDocument, IndexEntry, LwwDelta, OrderKey, byteCompare, compareHeadPreference, compareLinear, foldIndexV1, foldLwwMap, linearize } from './fold/index.js';
package/dist/index.js CHANGED
@@ -8,6 +8,7 @@ import {
8
8
  CreditClaimVerifyError,
9
9
  DeclaredKeyState,
10
10
  IdentityOperation,
11
+ IdentityStateNoSeenKeysError,
11
12
  Iso8601,
12
13
  MAX_ARTIFACT_PAYLOAD_SIZE,
13
14
  MAX_CREDIT_CLAIM_SIZE,
@@ -52,7 +53,7 @@ import {
52
53
  verifyIdentityExtensionFromTrustedState,
53
54
  verifyRevocation,
54
55
  verifySignRequest
55
- } from "./chunk-Q7FREWMY.js";
56
+ } from "./chunk-WBFWGQTS.js";
56
57
  import {
57
58
  ApiRequestVerifyError,
58
59
  Attenuation,
@@ -92,7 +93,7 @@ import {
92
93
  verifyDelegationChain,
93
94
  verifyIdentityProofEnvelope,
94
95
  verifyRequestProofEnvelope
95
- } from "./chunk-FZHHSC5N.js";
96
+ } from "./chunk-VEKRLXZ5.js";
96
97
  import {
97
98
  DEFAULT_KEY_PROOF_SKEW_SECONDS,
98
99
  KEY_ADD_JWS_TYP,
@@ -109,7 +110,7 @@ import {
109
110
  unsafeKeyProofSubject,
110
111
  verifyChainKeyProof,
111
112
  verifyKeyProof
112
- } from "./chunk-BMIOY5W5.js";
113
+ } from "./chunk-ISHAX5WN.js";
113
114
  import {
114
115
  ED25519_PRIV_MULTICODEC,
115
116
  ED25519_PUB_MULTICODEC,
@@ -142,7 +143,7 @@ import {
142
143
  signPayloadEd25519,
143
144
  verifyJws,
144
145
  verifyJwt
145
- } from "./chunk-KAW4MT4P.js";
146
+ } from "./chunk-NUIIVAZ3.js";
146
147
  import {
147
148
  INDEX_V1_SCHEMA,
148
149
  byteCompare,
@@ -175,6 +176,7 @@ export {
175
176
  IDENTITY_PROOF_JWS_TYP,
176
177
  INDEX_V1_SCHEMA,
177
178
  IdentityOperation,
179
+ IdentityStateNoSeenKeysError,
178
180
  Iso8601,
179
181
  JwsVerificationError,
180
182
  JwtVerificationError,
@@ -14,9 +14,9 @@ import {
14
14
  unsafeKeyProofSubject,
15
15
  verifyChainKeyProof,
16
16
  verifyKeyProof
17
- } from "../chunk-BMIOY5W5.js";
17
+ } from "../chunk-ISHAX5WN.js";
18
18
  import "../chunk-F7RHI2CK.js";
19
- import "../chunk-KAW4MT4P.js";
19
+ import "../chunk-NUIIVAZ3.js";
20
20
  export {
21
21
  DEFAULT_KEY_PROOF_SKEW_SECONDS,
22
22
  KEY_ADD_JWS_TYP,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metalabel/dfos-protocol",
3
- "version": "0.52.1",
3
+ "version": "0.53.0",
4
4
  "type": "module",
5
5
  "description": "DFOS Protocol — Ed25519 signed chain primitives, services, credentials, and verification",
6
6
  "license": "MIT",