@dwk/vc 0.1.0-beta.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.
Files changed (58) hide show
  1. package/LICENSE +15 -0
  2. package/README.md +143 -0
  3. package/dist/config.d.ts +97 -0
  4. package/dist/config.d.ts.map +1 -0
  5. package/dist/config.js +62 -0
  6. package/dist/config.js.map +1 -0
  7. package/dist/credential.d.ts +70 -0
  8. package/dist/credential.d.ts.map +1 -0
  9. package/dist/credential.js +139 -0
  10. package/dist/credential.js.map +1 -0
  11. package/dist/data-integrity.d.ts +102 -0
  12. package/dist/data-integrity.d.ts.map +1 -0
  13. package/dist/data-integrity.js +253 -0
  14. package/dist/data-integrity.js.map +1 -0
  15. package/dist/datetime.d.ts +26 -0
  16. package/dist/datetime.d.ts.map +1 -0
  17. package/dist/datetime.js +54 -0
  18. package/dist/datetime.js.map +1 -0
  19. package/dist/did-web.d.ts +93 -0
  20. package/dist/did-web.d.ts.map +1 -0
  21. package/dist/did-web.js +206 -0
  22. package/dist/did-web.js.map +1 -0
  23. package/dist/handler.d.ts +37 -0
  24. package/dist/handler.d.ts.map +1 -0
  25. package/dist/handler.js +362 -0
  26. package/dist/handler.js.map +1 -0
  27. package/dist/index.d.ts +42 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +46 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/jcs.d.ts +31 -0
  32. package/dist/jcs.d.ts.map +1 -0
  33. package/dist/jcs.js +67 -0
  34. package/dist/jcs.js.map +1 -0
  35. package/dist/log.d.ts +34 -0
  36. package/dist/log.d.ts.map +1 -0
  37. package/dist/log.js +32 -0
  38. package/dist/log.js.map +1 -0
  39. package/dist/multibase.d.ts +57 -0
  40. package/dist/multibase.d.ts.map +1 -0
  41. package/dist/multibase.js +165 -0
  42. package/dist/multibase.js.map +1 -0
  43. package/dist/status-list.d.ts +116 -0
  44. package/dist/status-list.d.ts.map +1 -0
  45. package/dist/status-list.js +241 -0
  46. package/dist/status-list.js.map +1 -0
  47. package/package.json +48 -0
  48. package/src/config.ts +158 -0
  49. package/src/credential.ts +188 -0
  50. package/src/data-integrity.ts +425 -0
  51. package/src/datetime.ts +57 -0
  52. package/src/did-web.ts +273 -0
  53. package/src/handler.ts +477 -0
  54. package/src/index.ts +133 -0
  55. package/src/jcs.ts +83 -0
  56. package/src/log.ts +35 -0
  57. package/src/multibase.ts +189 -0
  58. package/src/status-list.ts +356 -0
@@ -0,0 +1,42 @@
1
+ /**
2
+ * `@dwk/vc` — `did:web` identity plus Verifiable Credential issuance and
3
+ * verification.
4
+ *
5
+ * Endpoint package (+ lib): exports a factory returning a `fetch`-compatible
6
+ * handler, mountable under any prefix so it composes with the other `@dwk`
7
+ * packages in one Worker. Decentralized identity is rooted at the user's own
8
+ * domain — the same WebID / IndieAuth identity root, expressed as a DID — and
9
+ * credential proofs reuse the project's asymmetric, alg-allow-listed crypto
10
+ * posture (`@dwk/dpop`, `@dwk/http-signatures`).
11
+ *
12
+ * The split: the **`did:web` DID document is a static file** ({@link buildDidDocument}
13
+ * produces `/.well-known/did.json` — no Worker needed to resolve it), while the
14
+ * Worker covers the dynamic parts — VC **issuance** (signing with the domain's
15
+ * key), VC **verification**, and **status / revocation** whose bit-flips need a
16
+ * strongly-consistent store. Proofs use the **JCS** Data Integrity cryptosuites
17
+ * (`eddsa-jcs-2022`, `ecdsa-jcs-2019`), so the package canonicalizes with
18
+ * {@link canonicalize} (RFC 8785) rather than shipping a JSON-LD/RDF
19
+ * canonicalizer — staying within the Worker script-size budget.
20
+ *
21
+ * Credential construction and proof logic take **plain-data inputs** and
22
+ * unit-test without a Workers runtime; only the issuance/status endpoints and
23
+ * their D1-backed status store touch the runtime. Signing keys and issuer
24
+ * identity arrive via config and a secret binding — never read from the global
25
+ * environment (composition contract).
26
+ *
27
+ * @see spec/packages/vc.md
28
+ * @packageDocumentation
29
+ */
30
+ export { createVc } from "./handler";
31
+ export type { VcEnv, VcHandler } from "./handler";
32
+ export { resolveConfig, type VcConfig, type ResolvedVcConfig, type StatusConfig, type VcOperation, type AuthorizeOperation, type DidResolver, } from "./config";
33
+ export { importSigner, addProof, verifyProof, isSupportedCryptosuite, type Cryptosuite, type Signer, type JsonObject, type SecuredDocument, type AddProofOptions, type VerifyProofOptions, type VerifyProofResult, type VerificationMethod, type VerificationMethodResolver, } from "./data-integrity";
34
+ export { buildCredential, validateCredential, checkValidityPeriod, issuerId, VC_CONTEXT_V2, VERIFIABLE_CREDENTIAL_TYPE, type UnsignedCredential, type BuildCredentialOptions, type Issuer, } from "./credential";
35
+ export { didWebToUrl, urlToDidWeb, buildDidDocument, findVerificationMethod, createDidWebResolver, DID_CONTEXT_V1, MULTIKEY_CONTEXT_V1, JWK_CONTEXT_V1, type BuildDidDocumentOptions, type VerificationMethodInput, type VerificationRelationships, type DidWebResolverOptions, type FetchLike, } from "./did-web";
36
+ export { buildStatusListCredential, buildStatusEntry, buildEncodedList, encodeBitstring, decodeBitstring, getBit, setBit, findStatusEntry, statusEntryIndex, createVcStatusStore, DEFAULT_STATUS_LIST_LENGTH, BITSTRING_STATUS_LIST_CREDENTIAL_TYPE, BITSTRING_STATUS_LIST_ENTRY_TYPE, BITSTRING_STATUS_LIST_SUBJECT_TYPE, type StatusPurpose, type StatusPurposeValue, type StatusListCredentialOptions, type VcStatusStore, type VcStatusStoreEnv, } from "./status-list";
37
+ export { isValidXsdDateTimeStamp, toXsdDateTime } from "./datetime";
38
+ export { canonicalize, canonicalizeToBytes, type JcsValue } from "./jcs";
39
+ export { base58btcEncode, base58btcDecode, base64urlEncode, base64urlDecode, encodeMultibaseBase58btc, encodeMultibaseBase64url, decodeMultibase, encodeEd25519Multikey, decodeMultikey, type DecodedMultikey, } from "./multibase";
40
+ export { VcLogEvent } from "./log";
41
+ export type { Logger, Metrics } from "@dwk/log";
42
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,YAAY,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAElD,OAAO,EACL,aAAa,EACb,KAAK,QAAQ,EACb,KAAK,gBAAgB,EACrB,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,kBAAkB,EACvB,KAAK,WAAW,GACjB,MAAM,UAAU,CAAC;AAGlB,OAAO,EACL,YAAY,EACZ,QAAQ,EACR,WAAW,EACX,sBAAsB,EACtB,KAAK,WAAW,EAChB,KAAK,MAAM,EACX,KAAK,UAAU,EACf,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,0BAA0B,GAChC,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,mBAAmB,EACnB,QAAQ,EACR,aAAa,EACb,0BAA0B,EAC1B,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,EAC3B,KAAK,MAAM,GACZ,MAAM,cAAc,CAAC;AAGtB,OAAO,EACL,WAAW,EACX,WAAW,EACX,gBAAgB,EAChB,sBAAsB,EACtB,oBAAoB,EACpB,cAAc,EACd,mBAAmB,EACnB,cAAc,EACd,KAAK,uBAAuB,EAC5B,KAAK,uBAAuB,EAC5B,KAAK,yBAAyB,EAC9B,KAAK,qBAAqB,EAC1B,KAAK,SAAS,GACf,MAAM,WAAW,CAAC;AAGnB,OAAO,EACL,yBAAyB,EACzB,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,eAAe,EACf,MAAM,EACN,MAAM,EACN,eAAe,EACf,gBAAgB,EAChB,mBAAmB,EACnB,0BAA0B,EAC1B,qCAAqC,EACrC,gCAAgC,EAChC,kCAAkC,EAClC,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACvB,KAAK,2BAA2B,EAChC,KAAK,aAAa,EAClB,KAAK,gBAAgB,GACtB,MAAM,eAAe,CAAC;AAGvB,OAAO,EAAE,uBAAuB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAGpE,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,KAAK,QAAQ,EAAE,MAAM,OAAO,CAAC;AACzE,OAAO,EACL,eAAe,EACf,eAAe,EACf,eAAe,EACf,eAAe,EACf,wBAAwB,EACxB,wBAAwB,EACxB,eAAe,EACf,qBAAqB,EACrB,cAAc,EACd,KAAK,eAAe,GACrB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AACnC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,46 @@
1
+ /**
2
+ * `@dwk/vc` — `did:web` identity plus Verifiable Credential issuance and
3
+ * verification.
4
+ *
5
+ * Endpoint package (+ lib): exports a factory returning a `fetch`-compatible
6
+ * handler, mountable under any prefix so it composes with the other `@dwk`
7
+ * packages in one Worker. Decentralized identity is rooted at the user's own
8
+ * domain — the same WebID / IndieAuth identity root, expressed as a DID — and
9
+ * credential proofs reuse the project's asymmetric, alg-allow-listed crypto
10
+ * posture (`@dwk/dpop`, `@dwk/http-signatures`).
11
+ *
12
+ * The split: the **`did:web` DID document is a static file** ({@link buildDidDocument}
13
+ * produces `/.well-known/did.json` — no Worker needed to resolve it), while the
14
+ * Worker covers the dynamic parts — VC **issuance** (signing with the domain's
15
+ * key), VC **verification**, and **status / revocation** whose bit-flips need a
16
+ * strongly-consistent store. Proofs use the **JCS** Data Integrity cryptosuites
17
+ * (`eddsa-jcs-2022`, `ecdsa-jcs-2019`), so the package canonicalizes with
18
+ * {@link canonicalize} (RFC 8785) rather than shipping a JSON-LD/RDF
19
+ * canonicalizer — staying within the Worker script-size budget.
20
+ *
21
+ * Credential construction and proof logic take **plain-data inputs** and
22
+ * unit-test without a Workers runtime; only the issuance/status endpoints and
23
+ * their D1-backed status store touch the runtime. Signing keys and issuer
24
+ * identity arrive via config and a secret binding — never read from the global
25
+ * environment (composition contract).
26
+ *
27
+ * @see spec/packages/vc.md
28
+ * @packageDocumentation
29
+ */
30
+ export { createVc } from "./handler";
31
+ export { resolveConfig, } from "./config";
32
+ // Data Integrity (cryptosuites + proof pipeline)
33
+ export { importSigner, addProof, verifyProof, isSupportedCryptosuite, } from "./data-integrity";
34
+ // Credential data model (VCDM 2.0)
35
+ export { buildCredential, validateCredential, checkValidityPeriod, issuerId, VC_CONTEXT_V2, VERIFIABLE_CREDENTIAL_TYPE, } from "./credential";
36
+ // did:web
37
+ export { didWebToUrl, urlToDidWeb, buildDidDocument, findVerificationMethod, createDidWebResolver, DID_CONTEXT_V1, MULTIKEY_CONTEXT_V1, JWK_CONTEXT_V1, } from "./did-web";
38
+ // Bitstring Status List
39
+ export { buildStatusListCredential, buildStatusEntry, buildEncodedList, encodeBitstring, decodeBitstring, getBit, setBit, findStatusEntry, statusEntryIndex, createVcStatusStore, DEFAULT_STATUS_LIST_LENGTH, BITSTRING_STATUS_LIST_CREDENTIAL_TYPE, BITSTRING_STATUS_LIST_ENTRY_TYPE, BITSTRING_STATUS_LIST_SUBJECT_TYPE, } from "./status-list";
40
+ // XSD dateTimeStamp validation for VC temporal fields
41
+ export { isValidXsdDateTimeStamp, toXsdDateTime } from "./datetime";
42
+ // JCS canonicalization and multibase/Multikey codecs
43
+ export { canonicalize, canonicalizeToBytes } from "./jcs";
44
+ export { base58btcEncode, base58btcDecode, base64urlEncode, base64urlDecode, encodeMultibaseBase58btc, encodeMultibaseBase64url, decodeMultibase, encodeEd25519Multikey, decodeMultikey, } from "./multibase";
45
+ export { VcLogEvent } from "./log";
46
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAGrC,OAAO,EACL,aAAa,GAOd,MAAM,UAAU,CAAC;AAElB,iDAAiD;AACjD,OAAO,EACL,YAAY,EACZ,QAAQ,EACR,WAAW,EACX,sBAAsB,GAUvB,MAAM,kBAAkB,CAAC;AAE1B,mCAAmC;AACnC,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,mBAAmB,EACnB,QAAQ,EACR,aAAa,EACb,0BAA0B,GAI3B,MAAM,cAAc,CAAC;AAEtB,UAAU;AACV,OAAO,EACL,WAAW,EACX,WAAW,EACX,gBAAgB,EAChB,sBAAsB,EACtB,oBAAoB,EACpB,cAAc,EACd,mBAAmB,EACnB,cAAc,GAMf,MAAM,WAAW,CAAC;AAEnB,wBAAwB;AACxB,OAAO,EACL,yBAAyB,EACzB,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,eAAe,EACf,MAAM,EACN,MAAM,EACN,eAAe,EACf,gBAAgB,EAChB,mBAAmB,EACnB,0BAA0B,EAC1B,qCAAqC,EACrC,gCAAgC,EAChC,kCAAkC,GAMnC,MAAM,eAAe,CAAC;AAEvB,sDAAsD;AACtD,OAAO,EAAE,uBAAuB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEpE,qDAAqD;AACrD,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAiB,MAAM,OAAO,CAAC;AACzE,OAAO,EACL,eAAe,EACf,eAAe,EACf,eAAe,EACf,eAAe,EACf,wBAAwB,EACxB,wBAAwB,EACxB,eAAe,EACf,qBAAqB,EACrB,cAAc,GAEf,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC"}
package/dist/jcs.d.ts ADDED
@@ -0,0 +1,31 @@
1
+ /**
2
+ * JSON Canonicalization Scheme (RFC 8785).
3
+ *
4
+ * The `*-jcs-*` Data Integrity cryptosuites canonicalize a credential and its
5
+ * proof configuration with JCS — not RDF Dataset Canonicalization — so the proof
6
+ * pipeline needs no JSON-LD expansion or URDNA2015 implementation. That keeps
7
+ * the package within the Worker script-size budget (no `jsonld.js`/Comunica) and
8
+ * makes proof construction a pure, plain-data transform that unit-tests without a
9
+ * Workers runtime.
10
+ *
11
+ * JCS ordering and escaping line up with the ECMAScript primitives this uses:
12
+ * object members are sorted by the UTF-16 code units of their keys (the default
13
+ * `Array.prototype.sort` order), and string escaping matches `JSON.stringify`.
14
+ * Number serialization uses the ECMAScript `Number`-to-string algorithm
15
+ * (`String(n)`); credentials carry small integers and simple decimals, well
16
+ * within where that agrees with RFC 8785.
17
+ *
18
+ * @see https://www.rfc-editor.org/rfc/rfc8785
19
+ */
20
+ /** A JSON value accepted by {@link canonicalize}. */
21
+ export type JcsValue = null | boolean | number | string | JcsValue[] | {
22
+ [key: string]: JcsValue | undefined;
23
+ };
24
+ /**
25
+ * Canonicalize a JSON value to its RFC 8785 string form. Throws on values JSON
26
+ * cannot represent (non-finite numbers, `undefined` at the top level, functions).
27
+ */
28
+ export declare function canonicalize(value: JcsValue): string;
29
+ /** Canonicalize a value and return its UTF-8 bytes (the hash input). */
30
+ export declare function canonicalizeToBytes(value: JcsValue): Uint8Array;
31
+ //# sourceMappingURL=jcs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jcs.d.ts","sourceRoot":"","sources":["../src/jcs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,qDAAqD;AACrD,MAAM,MAAM,QAAQ,GAChB,IAAI,GACJ,OAAO,GACP,MAAM,GACN,MAAM,GACN,QAAQ,EAAE,GACV;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,CAAA;CAAE,CAAC;AAyC5C;;;GAGG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,QAAQ,GAAG,MAAM,CAKpD;AAED,wEAAwE;AACxE,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,QAAQ,GAAG,UAAU,CAE/D"}
package/dist/jcs.js ADDED
@@ -0,0 +1,67 @@
1
+ /**
2
+ * JSON Canonicalization Scheme (RFC 8785).
3
+ *
4
+ * The `*-jcs-*` Data Integrity cryptosuites canonicalize a credential and its
5
+ * proof configuration with JCS — not RDF Dataset Canonicalization — so the proof
6
+ * pipeline needs no JSON-LD expansion or URDNA2015 implementation. That keeps
7
+ * the package within the Worker script-size budget (no `jsonld.js`/Comunica) and
8
+ * makes proof construction a pure, plain-data transform that unit-tests without a
9
+ * Workers runtime.
10
+ *
11
+ * JCS ordering and escaping line up with the ECMAScript primitives this uses:
12
+ * object members are sorted by the UTF-16 code units of their keys (the default
13
+ * `Array.prototype.sort` order), and string escaping matches `JSON.stringify`.
14
+ * Number serialization uses the ECMAScript `Number`-to-string algorithm
15
+ * (`String(n)`); credentials carry small integers and simple decimals, well
16
+ * within where that agrees with RFC 8785.
17
+ *
18
+ * @see https://www.rfc-editor.org/rfc/rfc8785
19
+ */
20
+ function serializeNumber(value) {
21
+ if (!Number.isFinite(value)) {
22
+ throw new Error("@dwk/vc: cannot canonicalize a non-finite number");
23
+ }
24
+ // String(-0) === "0", matching JCS's requirement that -0 serialize as "0".
25
+ return String(value);
26
+ }
27
+ function serialize(value) {
28
+ if (value === null)
29
+ return "null";
30
+ const type = typeof value;
31
+ if (type === "boolean")
32
+ return value ? "true" : "false";
33
+ if (type === "number")
34
+ return serializeNumber(value);
35
+ if (type === "string")
36
+ return JSON.stringify(value);
37
+ if (Array.isArray(value)) {
38
+ // Mirror JSON.stringify: an `undefined` element serializes as `null`.
39
+ const items = value.map((item) => item === undefined ? "null" : serialize(item));
40
+ return `[${items.join(",")}]`;
41
+ }
42
+ if (type === "object") {
43
+ const obj = value;
44
+ // Drop members whose value is `undefined`, then sort by UTF-16 code unit.
45
+ const keys = Object.keys(obj)
46
+ .filter((key) => obj[key] !== undefined)
47
+ .sort();
48
+ const members = keys.map((key) => `${JSON.stringify(key)}:${serialize(obj[key])}`);
49
+ return `{${members.join(",")}}`;
50
+ }
51
+ throw new Error(`@dwk/vc: cannot canonicalize value of type ${type}`);
52
+ }
53
+ /**
54
+ * Canonicalize a JSON value to its RFC 8785 string form. Throws on values JSON
55
+ * cannot represent (non-finite numbers, `undefined` at the top level, functions).
56
+ */
57
+ export function canonicalize(value) {
58
+ if (value === undefined) {
59
+ throw new Error("@dwk/vc: cannot canonicalize `undefined`");
60
+ }
61
+ return serialize(value);
62
+ }
63
+ /** Canonicalize a value and return its UTF-8 bytes (the hash input). */
64
+ export function canonicalizeToBytes(value) {
65
+ return new TextEncoder().encode(canonicalize(value));
66
+ }
67
+ //# sourceMappingURL=jcs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jcs.js","sourceRoot":"","sources":["../src/jcs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAWH,SAAS,eAAe,CAAC,KAAa;IACpC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;IACtE,CAAC;IACD,2EAA2E;IAC3E,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;AACvB,CAAC;AAED,SAAS,SAAS,CAAC,KAAe;IAChC,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,MAAM,CAAC;IAElC,MAAM,IAAI,GAAG,OAAO,KAAK,CAAC;IAC1B,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;IACxD,IAAI,IAAI,KAAK,QAAQ;QAAE,OAAO,eAAe,CAAC,KAAe,CAAC,CAAC;IAC/D,IAAI,IAAI,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAEpD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,sEAAsE;QACtE,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAC/B,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAC9C,CAAC;QACF,OAAO,IAAI,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;IAChC,CAAC;IAED,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;QACtB,MAAM,GAAG,GAAG,KAAgD,CAAC;QAC7D,0EAA0E;QAC1E,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC;aAC1B,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,SAAS,CAAC;aACvC,IAAI,EAAE,CAAC;QACV,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CACtB,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,SAAS,CAAC,GAAG,CAAC,GAAG,CAAE,CAAC,EAAE,CAC1D,CAAC;QACF,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;IAClC,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,8CAA8C,IAAI,EAAE,CAAC,CAAC;AACxE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,KAAe;IAC1C,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;IAC9D,CAAC;IACD,OAAO,SAAS,CAAC,KAAK,CAAC,CAAC;AAC1B,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,mBAAmB,CAAC,KAAe;IACjD,OAAO,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC;AACvD,CAAC"}
package/dist/log.d.ts ADDED
@@ -0,0 +1,34 @@
1
+ /**
2
+ * `@dwk/vc` — structured observability event taxonomy.
3
+ *
4
+ * Credential issuance and status changes are the security-relevant moments here:
5
+ * an unauthorized issue attempt, a verification that fails its proof, or a
6
+ * revocation are exactly what an operator wants a signal for. Logging and metrics
7
+ * are opt-in via an injected {@link Logger} and {@link Metrics} (see `@dwk/log`)
8
+ * and **share this one vocabulary**: the same dotted event name is passed to the
9
+ * logger and the metrics sink so a log line and its counter line up.
10
+ *
11
+ * Fields follow the redaction policy: never the credential subject, claims, the
12
+ * signing key, or a `proofValue` — only stable reason codes, a credential `type`
13
+ * count or list, the issuer host, and the status purpose/outcome.
14
+ *
15
+ * @packageDocumentation
16
+ */
17
+ /** Stable event names emitted by `@dwk/vc`. */
18
+ export declare const VcLogEvent: {
19
+ /** A credential was issued (signed). Fields: `cryptosuite`. */
20
+ readonly Issued: "vc.issued";
21
+ /** A credential was verified. Fields: `verified` (boolean). */
22
+ readonly Verified: "vc.verified";
23
+ /** A credential's status was changed. Fields: `statusPurpose`, `value`. */
24
+ readonly StatusChanged: "vc.status.changed";
25
+ /**
26
+ * A request was rejected before completing. Field: `reason`
27
+ * (`method_not_allowed`, `unauthorized`, `malformed_request`,
28
+ * `unsupported`, `status_disabled`, `not_found`).
29
+ */
30
+ readonly Rejected: "vc.rejected";
31
+ };
32
+ /** Union of the event-name string literals in {@link VcLogEvent}. */
33
+ export type VcLogEvent = (typeof VcLogEvent)[keyof typeof VcLogEvent];
34
+ //# sourceMappingURL=log.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log.d.ts","sourceRoot":"","sources":["../src/log.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,+CAA+C;AAC/C,eAAO,MAAM,UAAU;IACrB,+DAA+D;;IAE/D,+DAA+D;;IAE/D,2EAA2E;;IAE3E;;;;OAIG;;CAEK,CAAC;AAEX,qEAAqE;AACrE,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,OAAO,UAAU,CAAC,CAAC"}
package/dist/log.js ADDED
@@ -0,0 +1,32 @@
1
+ /**
2
+ * `@dwk/vc` — structured observability event taxonomy.
3
+ *
4
+ * Credential issuance and status changes are the security-relevant moments here:
5
+ * an unauthorized issue attempt, a verification that fails its proof, or a
6
+ * revocation are exactly what an operator wants a signal for. Logging and metrics
7
+ * are opt-in via an injected {@link Logger} and {@link Metrics} (see `@dwk/log`)
8
+ * and **share this one vocabulary**: the same dotted event name is passed to the
9
+ * logger and the metrics sink so a log line and its counter line up.
10
+ *
11
+ * Fields follow the redaction policy: never the credential subject, claims, the
12
+ * signing key, or a `proofValue` — only stable reason codes, a credential `type`
13
+ * count or list, the issuer host, and the status purpose/outcome.
14
+ *
15
+ * @packageDocumentation
16
+ */
17
+ /** Stable event names emitted by `@dwk/vc`. */
18
+ export const VcLogEvent = {
19
+ /** A credential was issued (signed). Fields: `cryptosuite`. */
20
+ Issued: "vc.issued",
21
+ /** A credential was verified. Fields: `verified` (boolean). */
22
+ Verified: "vc.verified",
23
+ /** A credential's status was changed. Fields: `statusPurpose`, `value`. */
24
+ StatusChanged: "vc.status.changed",
25
+ /**
26
+ * A request was rejected before completing. Field: `reason`
27
+ * (`method_not_allowed`, `unauthorized`, `malformed_request`,
28
+ * `unsupported`, `status_disabled`, `not_found`).
29
+ */
30
+ Rejected: "vc.rejected",
31
+ };
32
+ //# sourceMappingURL=log.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log.js","sourceRoot":"","sources":["../src/log.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,+CAA+C;AAC/C,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,+DAA+D;IAC/D,MAAM,EAAE,WAAW;IACnB,+DAA+D;IAC/D,QAAQ,EAAE,aAAa;IACvB,2EAA2E;IAC3E,aAAa,EAAE,mBAAmB;IAClC;;;;OAIG;IACH,QAAQ,EAAE,aAAa;CACf,CAAC"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Multibase / Multikey encoding primitives used by Verifiable Credential proofs
3
+ * and DID documents.
4
+ *
5
+ * Data Integrity proof values are **multibase base58-btc** strings (a leading
6
+ * `z`), and a `Multikey` verification method publishes its public key as a
7
+ * multibase base58-btc string over a **multicodec**-prefixed raw key. Status
8
+ * lists are **multibase base64url** (a leading `u`). These helpers are pure
9
+ * byte/string transforms with no Web Crypto or runtime dependency, so they
10
+ * unit-test in isolation.
11
+ *
12
+ * @see https://www.w3.org/TR/controller-document/#multikey
13
+ * @see https://github.com/multiformats/multibase
14
+ */
15
+ /** Multibase prefix characters this module understands. */
16
+ export declare const MULTIBASE_BASE58BTC = "z";
17
+ export declare const MULTIBASE_BASE64URL = "u";
18
+ /**
19
+ * Multicodec varint prefixes for the key types published as a `Multikey`.
20
+ * Encoded as unsigned LEB128 varints (the on-disk multicodec form).
21
+ */
22
+ export declare const MULTICODEC_ED25519_PUB: Uint8Array<ArrayBuffer>;
23
+ /** Encode raw bytes as base58-btc (no multibase prefix). */
24
+ export declare function base58btcEncode(bytes: Uint8Array): string;
25
+ /** Decode a base58-btc string (no multibase prefix) to raw bytes. */
26
+ export declare function base58btcDecode(input: string): Uint8Array;
27
+ /** Base64url-encode bytes without padding. */
28
+ export declare function base64urlEncode(bytes: Uint8Array): string;
29
+ /** Decode a base64url string (padded or not) to bytes. */
30
+ export declare function base64urlDecode(input: string): Uint8Array;
31
+ /** Encode bytes as a multibase base58-btc string (`z…`). */
32
+ export declare function encodeMultibaseBase58btc(bytes: Uint8Array): string;
33
+ /** Encode bytes as a multibase base64url string (`u…`). */
34
+ export declare function encodeMultibaseBase64url(bytes: Uint8Array): string;
35
+ /**
36
+ * Decode a multibase string, dispatching on its prefix. Supports base58-btc
37
+ * (`z`) and base64url (`u`) — the two encodings the VC suite emits.
38
+ */
39
+ export declare function decodeMultibase(input: string): Uint8Array;
40
+ /**
41
+ * Encode a raw Ed25519 public key (32 bytes) as a `Multikey`
42
+ * `publicKeyMultibase` value: multibase base58-btc over the
43
+ * multicodec-prefixed key.
44
+ */
45
+ export declare function encodeEd25519Multikey(rawPublicKey: Uint8Array): string;
46
+ /** The raw key bytes and key type recovered from a `publicKeyMultibase`. */
47
+ export interface DecodedMultikey {
48
+ readonly keyType: "Ed25519";
49
+ readonly rawPublicKey: Uint8Array;
50
+ }
51
+ /**
52
+ * Decode a `Multikey` `publicKeyMultibase` value into its raw key bytes,
53
+ * validating the multicodec prefix. Only Ed25519 is supported as a Multikey;
54
+ * other key types are published as `publicKeyJwk` instead.
55
+ */
56
+ export declare function decodeMultikey(publicKeyMultibase: string): DecodedMultikey;
57
+ //# sourceMappingURL=multibase.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"multibase.d.ts","sourceRoot":"","sources":["../src/multibase.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAcH,2DAA2D;AAC3D,eAAO,MAAM,mBAAmB,MAAM,CAAC;AACvC,eAAO,MAAM,mBAAmB,MAAM,CAAC;AAEvC;;;GAGG;AACH,eAAO,MAAM,sBAAsB,yBAA4B,CAAC;AAEhE,4DAA4D;AAC5D,wBAAgB,eAAe,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CA2BzD;AAED,qEAAqE;AACrE,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,CA6BzD;AAED,8CAA8C;AAC9C,wBAAgB,eAAe,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAOzD;AAED,0DAA0D;AAC1D,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,CAQzD;AAED,4DAA4D;AAC5D,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAElE;AAED,2DAA2D;AAC3D,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAElE;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,CASzD;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,YAAY,EAAE,UAAU,GAAG,MAAM,CAYtE;AAED,4EAA4E;AAC5E,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,UAAU,CAAC;CACnC;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,kBAAkB,EAAE,MAAM,GAAG,eAAe,CAa1E"}
@@ -0,0 +1,165 @@
1
+ /**
2
+ * Multibase / Multikey encoding primitives used by Verifiable Credential proofs
3
+ * and DID documents.
4
+ *
5
+ * Data Integrity proof values are **multibase base58-btc** strings (a leading
6
+ * `z`), and a `Multikey` verification method publishes its public key as a
7
+ * multibase base58-btc string over a **multicodec**-prefixed raw key. Status
8
+ * lists are **multibase base64url** (a leading `u`). These helpers are pure
9
+ * byte/string transforms with no Web Crypto or runtime dependency, so they
10
+ * unit-test in isolation.
11
+ *
12
+ * @see https://www.w3.org/TR/controller-document/#multikey
13
+ * @see https://github.com/multiformats/multibase
14
+ */
15
+ const BASE58_ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
16
+ // Reverse lookup: code point → value, built once.
17
+ const BASE58_LOOKUP = (() => {
18
+ const map = {};
19
+ for (let i = 0; i < BASE58_ALPHABET.length; i++) {
20
+ map[BASE58_ALPHABET[i]] = i;
21
+ }
22
+ return map;
23
+ })();
24
+ /** Multibase prefix characters this module understands. */
25
+ export const MULTIBASE_BASE58BTC = "z";
26
+ export const MULTIBASE_BASE64URL = "u";
27
+ /**
28
+ * Multicodec varint prefixes for the key types published as a `Multikey`.
29
+ * Encoded as unsigned LEB128 varints (the on-disk multicodec form).
30
+ */
31
+ export const MULTICODEC_ED25519_PUB = Uint8Array.of(0xed, 0x01);
32
+ /** Encode raw bytes as base58-btc (no multibase prefix). */
33
+ export function base58btcEncode(bytes) {
34
+ if (bytes.length === 0)
35
+ return "";
36
+ // Count and preserve leading zero bytes as leading '1's.
37
+ let zeros = 0;
38
+ while (zeros < bytes.length && bytes[zeros] === 0)
39
+ zeros++;
40
+ // Convert the base-256 big-endian integer to base-58 via repeated division.
41
+ const digits = [];
42
+ for (let i = zeros; i < bytes.length; i++) {
43
+ let carry = bytes[i];
44
+ for (let j = 0; j < digits.length; j++) {
45
+ carry += digits[j] << 8;
46
+ digits[j] = carry % 58;
47
+ carry = (carry / 58) | 0;
48
+ }
49
+ while (carry > 0) {
50
+ digits.push(carry % 58);
51
+ carry = (carry / 58) | 0;
52
+ }
53
+ }
54
+ let out = "1".repeat(zeros);
55
+ for (let i = digits.length - 1; i >= 0; i--) {
56
+ out += BASE58_ALPHABET[digits[i]];
57
+ }
58
+ return out;
59
+ }
60
+ /** Decode a base58-btc string (no multibase prefix) to raw bytes. */
61
+ export function base58btcDecode(input) {
62
+ if (input.length === 0)
63
+ return new Uint8Array(0);
64
+ let zeros = 0;
65
+ while (zeros < input.length && input[zeros] === "1")
66
+ zeros++;
67
+ const bytes = [];
68
+ for (let i = zeros; i < input.length; i++) {
69
+ const value = BASE58_LOOKUP[input[i]];
70
+ if (value === undefined) {
71
+ throw new Error(`@dwk/vc: invalid base58 character "${input[i]}"`);
72
+ }
73
+ let carry = value;
74
+ for (let j = 0; j < bytes.length; j++) {
75
+ carry += bytes[j] * 58;
76
+ bytes[j] = carry & 0xff;
77
+ carry >>= 8;
78
+ }
79
+ while (carry > 0) {
80
+ bytes.push(carry & 0xff);
81
+ carry >>= 8;
82
+ }
83
+ }
84
+ const out = new Uint8Array(zeros + bytes.length);
85
+ for (let i = 0; i < bytes.length; i++) {
86
+ out[zeros + bytes.length - 1 - i] = bytes[i];
87
+ }
88
+ return out;
89
+ }
90
+ /** Base64url-encode bytes without padding. */
91
+ export function base64urlEncode(bytes) {
92
+ let binary = "";
93
+ for (const byte of bytes)
94
+ binary += String.fromCharCode(byte);
95
+ return btoa(binary)
96
+ .replace(/\+/g, "-")
97
+ .replace(/\//g, "_")
98
+ .replace(/=+$/, "");
99
+ }
100
+ /** Decode a base64url string (padded or not) to bytes. */
101
+ export function base64urlDecode(input) {
102
+ const b64 = input.replace(/-/g, "+").replace(/_/g, "/");
103
+ const padded = b64.length % 4 === 0 ? b64 : b64 + "=".repeat(4 - (b64.length % 4));
104
+ const binary = atob(padded);
105
+ const bytes = new Uint8Array(binary.length);
106
+ for (let i = 0; i < binary.length; i++)
107
+ bytes[i] = binary.charCodeAt(i);
108
+ return bytes;
109
+ }
110
+ /** Encode bytes as a multibase base58-btc string (`z…`). */
111
+ export function encodeMultibaseBase58btc(bytes) {
112
+ return MULTIBASE_BASE58BTC + base58btcEncode(bytes);
113
+ }
114
+ /** Encode bytes as a multibase base64url string (`u…`). */
115
+ export function encodeMultibaseBase64url(bytes) {
116
+ return MULTIBASE_BASE64URL + base64urlEncode(bytes);
117
+ }
118
+ /**
119
+ * Decode a multibase string, dispatching on its prefix. Supports base58-btc
120
+ * (`z`) and base64url (`u`) — the two encodings the VC suite emits.
121
+ */
122
+ export function decodeMultibase(input) {
123
+ if (input.length === 0) {
124
+ throw new Error("@dwk/vc: empty multibase value");
125
+ }
126
+ const prefix = input[0];
127
+ const rest = input.slice(1);
128
+ if (prefix === MULTIBASE_BASE58BTC)
129
+ return base58btcDecode(rest);
130
+ if (prefix === MULTIBASE_BASE64URL)
131
+ return base64urlDecode(rest);
132
+ throw new Error(`@dwk/vc: unsupported multibase prefix "${prefix ?? ""}"`);
133
+ }
134
+ /**
135
+ * Encode a raw Ed25519 public key (32 bytes) as a `Multikey`
136
+ * `publicKeyMultibase` value: multibase base58-btc over the
137
+ * multicodec-prefixed key.
138
+ */
139
+ export function encodeEd25519Multikey(rawPublicKey) {
140
+ if (rawPublicKey.length !== 32) {
141
+ throw new Error(`@dwk/vc: Ed25519 public key must be 32 bytes, got ${rawPublicKey.length}`);
142
+ }
143
+ const prefixed = new Uint8Array(MULTICODEC_ED25519_PUB.length + rawPublicKey.length);
144
+ prefixed.set(MULTICODEC_ED25519_PUB, 0);
145
+ prefixed.set(rawPublicKey, MULTICODEC_ED25519_PUB.length);
146
+ return encodeMultibaseBase58btc(prefixed);
147
+ }
148
+ /**
149
+ * Decode a `Multikey` `publicKeyMultibase` value into its raw key bytes,
150
+ * validating the multicodec prefix. Only Ed25519 is supported as a Multikey;
151
+ * other key types are published as `publicKeyJwk` instead.
152
+ */
153
+ export function decodeMultikey(publicKeyMultibase) {
154
+ const bytes = decodeMultibase(publicKeyMultibase);
155
+ if (bytes.length === MULTICODEC_ED25519_PUB.length + 32 &&
156
+ bytes[0] === MULTICODEC_ED25519_PUB[0] &&
157
+ bytes[1] === MULTICODEC_ED25519_PUB[1]) {
158
+ return {
159
+ keyType: "Ed25519",
160
+ rawPublicKey: bytes.slice(MULTICODEC_ED25519_PUB.length),
161
+ };
162
+ }
163
+ throw new Error("@dwk/vc: unsupported or malformed Multikey prefix");
164
+ }
165
+ //# sourceMappingURL=multibase.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"multibase.js","sourceRoot":"","sources":["../src/multibase.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Bitstring Status List support: the encoded-list codec, credential/entry
3
+ * builders, and a D1-backed authority for flipping a credential's status.
4
+ *
5
+ * A status list is a GZIP-compressed bitstring, multibase base64url-encoded,
6
+ * published inside a `BitstringStatusListCredential`. A credential opts in by
7
+ * carrying a `BitstringStatusListEntry` that points at a list and an index;
8
+ * verifiers read the bit at that index. Flipping a bit (revoking, suspending) is
9
+ * stateful and security-sensitive, so the authoritative bits live in **D1** — a
10
+ * strongly-consistent store — never KV (see `spec/non-functional-requirements.md`).
11
+ *
12
+ * The codec and builders are pure (GZIP via `CompressionStream`, available under
13
+ * both Node and workerd); only {@link createVcStatusStore} touches a binding.
14
+ *
15
+ * @see https://www.w3.org/TR/vc-bitstring-status-list/
16
+ */
17
+ import type { JsonObject } from "./data-integrity";
18
+ /**
19
+ * The minimum bitstring length the spec mandates (131,072 bits / 16 KB), chosen
20
+ * so an individual entry's index does not leak which credential it refers to.
21
+ */
22
+ export declare const DEFAULT_STATUS_LIST_LENGTH = 131072;
23
+ export declare const BITSTRING_STATUS_LIST_CREDENTIAL_TYPE = "BitstringStatusListCredential";
24
+ export declare const BITSTRING_STATUS_LIST_ENTRY_TYPE = "BitstringStatusListEntry";
25
+ export declare const BITSTRING_STATUS_LIST_SUBJECT_TYPE = "BitstringStatusList";
26
+ /** A status purpose. `revocation` is permanent; `suspension` is reversible. */
27
+ export type StatusPurpose = "revocation" | "suspension" | (string & {});
28
+ /**
29
+ * A `statusPurpose` value as it appears on a credential or entry. The Bitstring
30
+ * Status List spec allows "one or more" purposes, so a single purpose or an
31
+ * array of them are both valid.
32
+ */
33
+ export type StatusPurposeValue = StatusPurpose | readonly StatusPurpose[];
34
+ /** Get the bit at `index` in a most-significant-bit-first bitstring. */
35
+ export declare function getBit(bits: Uint8Array, index: number): boolean;
36
+ /** Set the bit at `index` in a most-significant-bit-first bitstring. */
37
+ export declare function setBit(bits: Uint8Array, index: number, value: boolean): void;
38
+ /** GZIP-compress a bitstring and multibase base64url-encode it (`encodedList`). */
39
+ export declare function encodeBitstring(bits: Uint8Array): Promise<string>;
40
+ /** Decode an `encodedList` (multibase base64url + GZIP) back to its bitstring. */
41
+ export declare function decodeBitstring(encodedList: string): Promise<Uint8Array>;
42
+ /**
43
+ * Build an `encodedList` of `length` bits with the given indices set to 1.
44
+ * `length` is the bit count (rounded up to whole bytes).
45
+ */
46
+ export declare function buildEncodedList(setIndices: Iterable<number>, length?: number): Promise<string>;
47
+ /** Options for {@link buildStatusListCredential}. */
48
+ export interface StatusListCredentialOptions {
49
+ /** The status list credential's id (a URL). */
50
+ readonly id: string;
51
+ /** The status purpose(s) this list tracks (one or more). */
52
+ readonly statusPurpose: StatusPurposeValue;
53
+ /** The pre-built `encodedList` value. */
54
+ readonly encodedList: string;
55
+ /** The issuer (string or object with id). */
56
+ readonly issuer: string | (JsonObject & {
57
+ id: string;
58
+ });
59
+ /** `validFrom` (XSD dateTime). Defaults to now when omitted. */
60
+ readonly validFrom?: Date | string;
61
+ /**
62
+ * `validUntil` (XSD dateTime). Bounds how long a verifier may treat the
63
+ * cached status as authoritative.
64
+ */
65
+ readonly validUntil?: Date | string;
66
+ /**
67
+ * Cache time-to-live in milliseconds, advertised on both the credential and
68
+ * its status-list subject so verifiers can bound status caching.
69
+ */
70
+ readonly ttl?: number;
71
+ }
72
+ /**
73
+ * Assemble an **unsigned** `BitstringStatusListCredential`. The caller signs it
74
+ * with {@link ./data-integrity.addProof} before publishing.
75
+ *
76
+ * Per the Bitstring Status List spec, `validFrom`/`validUntil`/`ttl` bound how
77
+ * long the published status may be cached; `validUntil` and `ttl` are emitted on
78
+ * the credential (and `ttl` also on the subject) when supplied.
79
+ */
80
+ export declare function buildStatusListCredential(options: StatusListCredentialOptions): JsonObject;
81
+ /** Build a `credentialStatus` entry referencing a list index. */
82
+ export declare function buildStatusEntry(options: {
83
+ readonly statusListCredential: string;
84
+ readonly statusListIndex: number;
85
+ readonly statusPurpose: StatusPurposeValue;
86
+ readonly id?: string;
87
+ }): JsonObject;
88
+ /** Read a `statusListIndex` from a credential's `credentialStatus` entry. */
89
+ export declare function statusEntryIndex(entry: JsonObject): number | undefined;
90
+ /** Locate a `credentialStatus` entry for a purpose on a credential. */
91
+ export declare function findStatusEntry(credential: JsonObject, statusPurpose: StatusPurpose): JsonObject | undefined;
92
+ /** Cloudflare bindings required by the D1-backed status store. */
93
+ export interface VcStatusStoreEnv {
94
+ /** D1 database holding per-list status bits and index allocations. */
95
+ readonly VC_STATUS_DB: D1Database;
96
+ }
97
+ /** Authoritative store for credential status bits, backed by D1. */
98
+ export interface VcStatusStore {
99
+ /** Create the schema if absent. Idempotent. */
100
+ init(): Promise<void>;
101
+ /** Allocate and return the next unused index for a list + purpose. */
102
+ allocateIndex(listId: string, statusPurpose: StatusPurpose): Promise<number>;
103
+ /** Set the status bit at an index (e.g. revoke). */
104
+ setStatus(listId: string, statusPurpose: StatusPurpose, index: number, value: boolean): Promise<void>;
105
+ /** Read the status bit at an index (defaults to `false`/unset). */
106
+ getStatus(listId: string, statusPurpose: StatusPurpose, index: number): Promise<boolean>;
107
+ /** The set (value-1) indices for a list + purpose, ascending. */
108
+ setIndices(listId: string, statusPurpose: StatusPurpose): Promise<number[]>;
109
+ }
110
+ /**
111
+ * Create the D1-backed {@link VcStatusStore}. Fails loudly if the required
112
+ * `VC_STATUS_DB` binding is missing — no silent degradation (composition
113
+ * contract).
114
+ */
115
+ export declare function createVcStatusStore(env: VcStatusStoreEnv): VcStatusStore;
116
+ //# sourceMappingURL=status-list.d.ts.map