@certrev/cert-block 0.1.0 → 0.1.1

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.
@@ -16,7 +16,7 @@
16
16
  * end-to-end under the production `verifyEnvelope`, not a stand-in canonicalizer.
17
17
  */
18
18
  import { type KeyObject } from 'node:crypto';
19
- import { type CertDeliveryEnvelope, type CertPayload, type ResolvePublicKeyByKid } from '@certrev/cert-contract';
19
+ import type { CertDeliveryEnvelope, CertPayload, ResolvePublicKeyByKid } from '@certrev/cert-contract';
20
20
  declare const FIXTURE_KID = "certrev-fixture-key-1";
21
21
  /** Build a complete mock payload. Pass overrides to exercise specific render branches. */
22
22
  export declare function makeMockPayload(overrides?: Partial<CertPayload>): CertPayload;
@@ -1 +1 @@
1
- {"version":3,"file":"fixtures.d.ts","sourceRoot":"","sources":["../../src/contract/fixtures.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAuB,KAAK,SAAS,EAAoB,MAAM,aAAa,CAAA;AACnF,OAAO,EAEN,KAAK,oBAAoB,EACzB,KAAK,WAAW,EAEhB,KAAK,qBAAqB,EAC1B,MAAM,wBAAwB,CAAA;AAE/B,QAAA,MAAM,WAAW,0BAA0B,CAAA;AAE3C,0FAA0F;AAC1F,wBAAgB,eAAe,CAAC,SAAS,GAAE,OAAO,CAAC,WAAW,CAAM,GAAG,WAAW,CA4CjF;AAED,MAAM,WAAW,qBAAqB;IACrC,QAAQ,CAAC,QAAQ,EAAE,oBAAoB,CAAA;IACvC,QAAQ,CAAC,UAAU,EAAE,qBAAqB,CAAA;IAC1C,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAA;IAC7B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CACpB;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,GAAE,OAAO,CAAC,WAAW,CAAM,EAAE,GAAG,SAAc,GAAG,qBAAqB,CAgBjH;AAED,OAAO,EAAE,WAAW,EAAE,CAAA"}
1
+ {"version":3,"file":"fixtures.d.ts","sourceRoot":"","sources":["../../src/contract/fixtures.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAuB,KAAK,SAAS,EAAE,MAAM,aAAa,CAAA;AACjE,OAAO,KAAK,EACX,oBAAoB,EACpB,WAAW,EAEX,qBAAqB,EACrB,MAAM,wBAAwB,CAAA;AAM/B,QAAA,MAAM,WAAW,0BAA0B,CAAA;AAE3C,0FAA0F;AAC1F,wBAAgB,eAAe,CAAC,SAAS,GAAE,OAAO,CAAC,WAAW,CAAM,GAAG,WAAW,CA4CjF;AAED,MAAM,WAAW,qBAAqB;IACrC,QAAQ,CAAC,QAAQ,EAAE,oBAAoB,CAAA;IACvC,QAAQ,CAAC,UAAU,EAAE,qBAAqB,CAAA;IAC1C,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAA;IAC7B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CACpB;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,GAAE,OAAO,CAAC,WAAW,CAAM,EAAE,GAAG,SAAc,GAAG,qBAAqB,CAiBjH;AAED,OAAO,EAAE,WAAW,EAAE,CAAA"}
@@ -15,8 +15,11 @@
15
15
  * the SAME bytes the real kernel recomputes on verify — so a fixture envelope verifies
16
16
  * end-to-end under the production `verifyEnvelope`, not a stand-in canonicalizer.
17
17
  */
18
- import { generateKeyPairSync, sign as nodeSign } from 'node:crypto';
19
- import { canonicalPayloadBytes, } from '@certrev/cert-contract';
18
+ import { generateKeyPairSync } from 'node:crypto';
19
+ // SIGN is Node-only and lives on the contract's signer subpath. Fixtures are themselves
20
+ // Node-only (they stand in for the issuer) and ship from the './fixtures' subpath, so the
21
+ // SDK's edge-safe main entry never pulls a Node builtin.
22
+ import { signPayloadEd25519 } from '@certrev/cert-contract/signer';
20
23
  const FIXTURE_KID = 'certrev-fixture-key-1';
21
24
  /** Build a complete mock payload. Pass overrides to exercise specific render branches. */
22
25
  export function makeMockPayload(overrides = {}) {
@@ -72,8 +75,9 @@ export function makeMockPayload(overrides = {}) {
72
75
  export function makeSignedEnvelope(overrides = {}, kid = FIXTURE_KID) {
73
76
  const { publicKey, privateKey } = generateKeyPairSync('ed25519');
74
77
  const payload = makeMockPayload(overrides);
75
- const bytes = canonicalPayloadBytes(payload);
76
- const sig = nodeSign(null, bytes, privateKey).toString('base64url');
78
+ // Sign the RFC-8785 canonical bytes via the contract's signer — the SAME bytes the
79
+ // edge-safe kernel recomputes on verify, so the fixture verifies end-to-end.
80
+ const sig = signPayloadEd25519(payload, privateKey);
77
81
  const envelope = {
78
82
  payload,
79
83
  signature: { alg: 'ed25519', kid, sig, signedAt: payload.lifecycle.issuedAt },
@@ -1 +1 @@
1
- {"version":3,"file":"fixtures.js","sourceRoot":"","sources":["../../src/contract/fixtures.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"fixtures.js","sourceRoot":"","sources":["../../src/contract/fixtures.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,mBAAmB,EAAkB,MAAM,aAAa,CAAA;AAOjE,wFAAwF;AACxF,0FAA0F;AAC1F,yDAAyD;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAA;AAElE,MAAM,WAAW,GAAG,uBAAuB,CAAA;AAE3C,0FAA0F;AAC1F,MAAM,UAAU,eAAe,CAAC,YAAkC,EAAE;IACnE,MAAM,IAAI,GAAgB;QACzB,eAAe,EAAE,CAAC;QAClB,MAAM,EAAE,kBAAkB;QAC1B,OAAO,EAAE;YACR,QAAQ,EAAE,SAAS;YACnB,UAAU,EAAE,iCAAiC;YAC7C,gBAAgB,EAAE,iBAAiB;YACnC,aAAa,EAAE,CAAC,wDAAwD,CAAC;YACzE,cAAc,EAAE,iBAAiB;YACjC,aAAa,EAAE,kEAAkE;SACjF;QACD,OAAO,EAAE;YACR,MAAM,EAAE;gBACP,WAAW,EAAE,cAAc;gBAC3B,WAAW,EAAE;oBACZ,EAAE,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,oBAAoB,EAAE;oBACtD,EAAE,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,+CAA+C,EAAE;iBACnF;gBACD,UAAU,EAAE,sCAAsC;gBAClD,QAAQ,EAAE,8CAA8C;aACxD;YACD,MAAM,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,uBAAuB,EAAE;YAC9D,IAAI,EAAE,gJAAgJ;YACtJ,WAAW,EAAE,0BAA0B;YACvC,iBAAiB,EAAE,0BAA0B;YAC7C,SAAS,EAAE,6CAA6C;YACxD,OAAO,EAAE;gBACR,WAAW,EAAE,SAAS;gBACtB,eAAe,EAAE,IAAI;gBACrB,UAAU,EAAE,IAAI;gBAChB,QAAQ,EAAE,IAAI;gBACd,UAAU,EAAE,MAAM;aAClB;SACD;QACD,SAAS,EAAE;YACV,QAAQ,EAAE,0BAA0B;YACpC,SAAS,EAAE,0BAA0B;YACrC,SAAS,EAAE,IAAI;YACf,QAAQ,EAAE,CAAC;SACX;QACD,GAAG,SAAS;KACZ,CAAA;IACD,OAAO,IAAI,CAAA;AACZ,CAAC;AASD;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,YAAkC,EAAE,EAAE,GAAG,GAAG,WAAW;IACzF,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,GAAG,mBAAmB,CAAC,SAAS,CAAC,CAAA;IAChE,MAAM,OAAO,GAAG,eAAe,CAAC,SAAS,CAAC,CAAA;IAC1C,mFAAmF;IACnF,6EAA6E;IAC7E,MAAM,GAAG,GAAG,kBAAkB,CAAC,OAAO,EAAE,UAAU,CAAC,CAAA;IAEnD,MAAM,QAAQ,GAAyB;QACtC,OAAO;QACP,SAAS,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG,EAAE,GAAG,EAAE,QAAQ,EAAE,OAAO,CAAC,SAAS,CAAC,QAAQ,EAAE;KAC7E,CAAA;IAED,MAAM,UAAU,GAAG,SAAS,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;IACvF,MAAM,QAAQ,GAA0B,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,UAAU,EAAE,CAAA;IACrF,MAAM,UAAU,GAA0B,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAA;IAE9E,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,EAAE,CAAA;AAChD,CAAC;AAED,OAAO,EAAE,WAAW,EAAE,CAAA"}
@@ -7,8 +7,8 @@
7
7
  * never directly from `@certrev/cert-contract`, so the whole SDK's dependency on the
8
8
  * contract is funnelled through one module. The published package owns the envelope types
9
9
  * (`CertDeliveryEnvelope`, `CertPayload`, `CertCredential`, …), the RFC-8785
10
- * canonicalization (`canonicalPayloadBytes`), and the fail-closed kernel (`verifyEnvelope`,
11
- * `renderVerdict`, `verifySignatureOnly`, `toEd25519PublicKey`).
10
+ * canonicalization (`canonicalPayloadBytes`), and the fail-closed WebCrypto kernel
11
+ * (`verifyEnvelope`, `renderVerdict`, `verifySignatureOnly`, `importEd25519PublicKey`).
12
12
  *
13
13
  * `VerdictKernel` is the ONE name NOT re-exported from the package: the contract exposes
14
14
  * the kernel as free functions, and different edges bundle them with different key-resolver
@@ -7,8 +7,8 @@
7
7
  * never directly from `@certrev/cert-contract`, so the whole SDK's dependency on the
8
8
  * contract is funnelled through one module. The published package owns the envelope types
9
9
  * (`CertDeliveryEnvelope`, `CertPayload`, `CertCredential`, …), the RFC-8785
10
- * canonicalization (`canonicalPayloadBytes`), and the fail-closed kernel (`verifyEnvelope`,
11
- * `renderVerdict`, `verifySignatureOnly`, `toEd25519PublicKey`).
10
+ * canonicalization (`canonicalPayloadBytes`), and the fail-closed WebCrypto kernel
11
+ * (`verifyEnvelope`, `renderVerdict`, `verifySignatureOnly`, `importEd25519PublicKey`).
12
12
  *
13
13
  * `VerdictKernel` is the ONE name NOT re-exported from the package: the contract exposes
14
14
  * the kernel as free functions, and different edges bundle them with different key-resolver
package/dist/index.d.ts CHANGED
@@ -8,11 +8,16 @@
8
8
  * graph, mergeable by @id (won't collide with Yoast).
9
9
  * • Verify layer — `getVerifiedEnvelope` (fetch from metafield OR Delivery API + run
10
10
  * the fail-closed VerdictKernel + cache), kid resolvers, the TTL/single-flight cache.
11
- * • Contract types — re-exported from `@certrev/cert-contract` (stubbed locally until
12
- * that package publishes; see the contract binding point in ./contract/kernel).
11
+ * • Contract types — re-exported from `@certrev/cert-contract` (the binding point in
12
+ * ./contract/kernel).
13
13
  *
14
- * The Web Component (`<certrev-badge>`) ships from the './webcomponent' subpath export so
15
- * importing the main entry doesn't touch `customElements` (which is undefined server-side).
14
+ * EDGE-RUNTIME SAFE. This main entry imports NO `node:crypto` and uses NO `Buffer`, so it
15
+ * loads + runs on edge/Workers runtimes (Shopify Oxygen, Cloudflare Workers, Vercel Edge).
16
+ * Two things are deliberately kept OFF this entry:
17
+ * • the Web Component (`<certrev-badge>`) → './webcomponent' subpath (touches
18
+ * `customElements`, undefined server-side);
19
+ * • the Node-only test/dev fixtures (`makeSignedEnvelope`, which signs with `node:crypto`)
20
+ * → './fixtures' subpath. Importing the main entry must never pull a Node builtin.
16
21
  */
17
22
  export { CertBadge, type CertBadgeProps } from './components/CertBadge.js';
18
23
  export { CertJsonLd, type CertJsonLdProps } from './components/CertJsonLd.js';
@@ -21,7 +26,6 @@ export { CertReview, type CertReviewProps } from './components/CertReview.js';
21
26
  export { ExpertBio, type ExpertBioProps } from './components/ExpertBio.js';
22
27
  export { escapeAttribute, escapeHtml, safeCssColor, safeHttpUrl, tidyText } from './components/escape.js';
23
28
  export { credentialSuffix, DEFAULT_ACCENT, expertNameWithCredentials, formatDate, type ResolvedDisplay, resolveDisplay, } from './components/format.js';
24
- export { FIXTURE_KID, makeMockPayload, makeSignedEnvelope, type SignedEnvelopeFixture } from './contract/fixtures.js';
25
29
  export { CANONICALIZATION, type CertContent, type CertCredential, type CertDeliveryEnvelope, type CertDisplayConfig, type CertLifecycle, type CertPayload, type CertSignature, type CertSubject, type CertSuppressReason, type CertVerdict, CONTRACT_VERSION, type ContractVersion, type Ed25519PublicKeyInput, type RenderContext, type ResolvePublicKeyByKid, renderVerdict, SIGNATURE_ALG, type SignatureAlg, type VerdictKernel, verifyEnvelope, verifySignatureOnly, } from './contract/kernel.js';
26
30
  export { type JsonLdValue, type ProjectJsonLdOptions, projectCertJsonLd, projectCertJsonLdString, serializeJsonLdForScript, } from './jsonld/project.js';
27
31
  export { TtlCache, type TtlCacheOptions } from './verify/cache.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,EAAE,SAAS,EAAE,KAAK,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAC1E,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,4BAA4B,CAAA;AAC7E,OAAO,EAAE,eAAe,EAAE,KAAK,oBAAoB,EAAE,MAAM,iCAAiC,CAAA;AAC5F,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,4BAA4B,CAAA;AAC7E,OAAO,EAAE,SAAS,EAAE,KAAK,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAC1E,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AAEzG,OAAO,EACN,gBAAgB,EAChB,cAAc,EACd,yBAAyB,EACzB,UAAU,EACV,KAAK,eAAe,EACpB,cAAc,GACd,MAAM,wBAAwB,CAAA;AAE/B,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,kBAAkB,EAAE,KAAK,qBAAqB,EAAE,MAAM,wBAAwB,CAAA;AAErH,OAAO,EACN,gBAAgB,EAChB,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,oBAAoB,EACzB,KAAK,iBAAiB,EACtB,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,kBAAkB,EACvB,KAAK,WAAW,EAChB,gBAAgB,EAChB,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,KAAK,aAAa,EAClB,KAAK,qBAAqB,EAC1B,aAAa,EACb,aAAa,EACb,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,cAAc,EACd,mBAAmB,GACnB,MAAM,sBAAsB,CAAA;AAE7B,OAAO,EACN,KAAK,WAAW,EAChB,KAAK,oBAAoB,EACzB,iBAAiB,EACjB,uBAAuB,EACvB,wBAAwB,GACxB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EAAE,QAAQ,EAAE,KAAK,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAElE,OAAO,EACN,KAAK,cAAc,EACnB,KAAK,0BAA0B,EAC/B,mBAAmB,EACnB,iBAAiB,EACjB,kBAAkB,GAClB,MAAM,mCAAmC,CAAA;AAC1C,OAAO,EACN,KAAK,0BAA0B,EAC/B,mBAAmB,EACnB,KAAK,YAAY,EACjB,iBAAiB,GACjB,MAAM,yBAAyB,CAAA;AAEhC,OAAO,EAAE,KAAK,kBAAkB,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAGH,OAAO,EAAE,SAAS,EAAE,KAAK,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAC1E,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,4BAA4B,CAAA;AAC7E,OAAO,EAAE,eAAe,EAAE,KAAK,oBAAoB,EAAE,MAAM,iCAAiC,CAAA;AAC5F,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,4BAA4B,CAAA;AAC7E,OAAO,EAAE,SAAS,EAAE,KAAK,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAC1E,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AAEzG,OAAO,EACN,gBAAgB,EAChB,cAAc,EACd,yBAAyB,EACzB,UAAU,EACV,KAAK,eAAe,EACpB,cAAc,GACd,MAAM,wBAAwB,CAAA;AAI/B,OAAO,EACN,gBAAgB,EAChB,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,oBAAoB,EACzB,KAAK,iBAAiB,EACtB,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,kBAAkB,EACvB,KAAK,WAAW,EAChB,gBAAgB,EAChB,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,KAAK,aAAa,EAClB,KAAK,qBAAqB,EAC1B,aAAa,EACb,aAAa,EACb,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,cAAc,EACd,mBAAmB,GACnB,MAAM,sBAAsB,CAAA;AAE7B,OAAO,EACN,KAAK,WAAW,EAChB,KAAK,oBAAoB,EACzB,iBAAiB,EACjB,uBAAuB,EACvB,wBAAwB,GACxB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EAAE,QAAQ,EAAE,KAAK,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAElE,OAAO,EACN,KAAK,cAAc,EACnB,KAAK,0BAA0B,EAC/B,mBAAmB,EACnB,iBAAiB,EACjB,kBAAkB,GAClB,MAAM,mCAAmC,CAAA;AAC1C,OAAO,EACN,KAAK,0BAA0B,EAC/B,mBAAmB,EACnB,KAAK,YAAY,EACjB,iBAAiB,GACjB,MAAM,yBAAyB,CAAA;AAEhC,OAAO,EAAE,KAAK,kBAAkB,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAA"}
package/dist/index.js CHANGED
@@ -8,11 +8,16 @@
8
8
  * graph, mergeable by @id (won't collide with Yoast).
9
9
  * • Verify layer — `getVerifiedEnvelope` (fetch from metafield OR Delivery API + run
10
10
  * the fail-closed VerdictKernel + cache), kid resolvers, the TTL/single-flight cache.
11
- * • Contract types — re-exported from `@certrev/cert-contract` (stubbed locally until
12
- * that package publishes; see the contract binding point in ./contract/kernel).
11
+ * • Contract types — re-exported from `@certrev/cert-contract` (the binding point in
12
+ * ./contract/kernel).
13
13
  *
14
- * The Web Component (`<certrev-badge>`) ships from the './webcomponent' subpath export so
15
- * importing the main entry doesn't touch `customElements` (which is undefined server-side).
14
+ * EDGE-RUNTIME SAFE. This main entry imports NO `node:crypto` and uses NO `Buffer`, so it
15
+ * loads + runs on edge/Workers runtimes (Shopify Oxygen, Cloudflare Workers, Vercel Edge).
16
+ * Two things are deliberately kept OFF this entry:
17
+ * • the Web Component (`<certrev-badge>`) → './webcomponent' subpath (touches
18
+ * `customElements`, undefined server-side);
19
+ * • the Node-only test/dev fixtures (`makeSignedEnvelope`, which signs with `node:crypto`)
20
+ * → './fixtures' subpath. Importing the main entry must never pull a Node builtin.
16
21
  */
17
22
  // ── React components ──────────────────────────────────────────────────────────────
18
23
  export { CertBadge } from './components/CertBadge.js';
@@ -23,9 +28,9 @@ export { ExpertBio } from './components/ExpertBio.js';
23
28
  export { escapeAttribute, escapeHtml, safeCssColor, safeHttpUrl, tidyText } from './components/escape.js';
24
29
  // ── Presentation helpers (shared with the Web Component) ────────────────────────────
25
30
  export { credentialSuffix, DEFAULT_ACCENT, expertNameWithCredentials, formatDate, resolveDisplay, } from './components/format.js';
26
- // ── Test/dev fixtures (mock facts + signed-envelope generator) ─────────────────────
27
- export { FIXTURE_KID, makeMockPayload, makeSignedEnvelope } from './contract/fixtures.js';
28
31
  // ── Contract surface (types + kernel) — re-export the binding point ────────────────
32
+ // NOTE: the test/dev fixtures (makeSignedEnvelope, makeMockPayload, FIXTURE_KID) are
33
+ // Node-only (they sign with node:crypto) and ship from the './fixtures' subpath, NOT here.
29
34
  export { CANONICALIZATION, CONTRACT_VERSION, renderVerdict, SIGNATURE_ALG, verifyEnvelope, verifySignatureOnly, } from './contract/kernel.js';
30
35
  // ── JSON-LD projector ───────────────────────────────────────────────────────────────
31
36
  export { projectCertJsonLd, projectCertJsonLdString, serializeJsonLdForScript, } from './jsonld/project.js';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,qFAAqF;AACrF,OAAO,EAAE,SAAS,EAAuB,MAAM,2BAA2B,CAAA;AAC1E,OAAO,EAAE,UAAU,EAAwB,MAAM,4BAA4B,CAAA;AAC7E,OAAO,EAAE,eAAe,EAA6B,MAAM,iCAAiC,CAAA;AAC5F,OAAO,EAAE,UAAU,EAAwB,MAAM,4BAA4B,CAAA;AAC7E,OAAO,EAAE,SAAS,EAAuB,MAAM,2BAA2B,CAAA;AAC1E,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AACzG,uFAAuF;AACvF,OAAO,EACN,gBAAgB,EAChB,cAAc,EACd,yBAAyB,EACzB,UAAU,EAEV,cAAc,GACd,MAAM,wBAAwB,CAAA;AAC/B,sFAAsF;AACtF,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,kBAAkB,EAA8B,MAAM,wBAAwB,CAAA;AACrH,sFAAsF;AACtF,OAAO,EACN,gBAAgB,EAWhB,gBAAgB,EAKhB,aAAa,EACb,aAAa,EAGb,cAAc,EACd,mBAAmB,GACnB,MAAM,sBAAsB,CAAA;AAC7B,uFAAuF;AACvF,OAAO,EAGN,iBAAiB,EACjB,uBAAuB,EACvB,wBAAwB,GACxB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EAAE,QAAQ,EAAwB,MAAM,mBAAmB,CAAA;AAClE,qFAAqF;AACrF,OAAO,EAGN,mBAAmB,EACnB,iBAAiB,EACjB,kBAAkB,GAClB,MAAM,mCAAmC,CAAA;AAC1C,OAAO,EAEN,mBAAmB,EAEnB,iBAAiB,GACjB,MAAM,yBAAyB,CAAA;AAChC,sFAAsF;AACtF,OAAO,EAA2B,eAAe,EAAE,MAAM,qCAAqC,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,qFAAqF;AACrF,OAAO,EAAE,SAAS,EAAuB,MAAM,2BAA2B,CAAA;AAC1E,OAAO,EAAE,UAAU,EAAwB,MAAM,4BAA4B,CAAA;AAC7E,OAAO,EAAE,eAAe,EAA6B,MAAM,iCAAiC,CAAA;AAC5F,OAAO,EAAE,UAAU,EAAwB,MAAM,4BAA4B,CAAA;AAC7E,OAAO,EAAE,SAAS,EAAuB,MAAM,2BAA2B,CAAA;AAC1E,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AACzG,uFAAuF;AACvF,OAAO,EACN,gBAAgB,EAChB,cAAc,EACd,yBAAyB,EACzB,UAAU,EAEV,cAAc,GACd,MAAM,wBAAwB,CAAA;AAC/B,sFAAsF;AACtF,qFAAqF;AACrF,2FAA2F;AAC3F,OAAO,EACN,gBAAgB,EAWhB,gBAAgB,EAKhB,aAAa,EACb,aAAa,EAGb,cAAc,EACd,mBAAmB,GACnB,MAAM,sBAAsB,CAAA;AAC7B,uFAAuF;AACvF,OAAO,EAGN,iBAAiB,EACjB,uBAAuB,EACvB,wBAAwB,GACxB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EAAE,QAAQ,EAAwB,MAAM,mBAAmB,CAAA;AAClE,qFAAqF;AACrF,OAAO,EAGN,mBAAmB,EACnB,iBAAiB,EACjB,kBAAkB,GAClB,MAAM,mCAAmC,CAAA;AAC1C,OAAO,EAEN,mBAAmB,EAEnB,iBAAiB,GACjB,MAAM,yBAAyB,CAAA;AAChC,sFAAsF;AACtF,OAAO,EAA2B,eAAe,EAAE,MAAM,qCAAqC,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"get-verified-envelope.d.ts","sourceRoot":"","sources":["../../src/verify/get-verified-envelope.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,WAAW,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAA;AAEpH,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAErC,kFAAkF;AAClF,MAAM,MAAM,cAAc;AACzB,2EAA2E;AACzE;IACA,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAA;IAC7B,8EAA8E;IAC9E,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;CAC1B;AACH;;sFAEsF;GACpF;IACA,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAA;IAC1B,QAAQ,CAAC,KAAK,EAAE,oBAAoB,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,CAAA;CAC/D,CAAA;AAEJ,MAAM,WAAW,0BAA0B;IAC1C,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAA;IAC/B,uFAAuF;IACvF,QAAQ,CAAC,UAAU,EAAE,qBAAqB,CAAA;IAC1C,uFAAuF;IACvF,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,aAAa,EAAE,KAAK,CAAC,GAAG;QAAE,QAAQ,CAAC,GAAG,CAAC,EAAE,IAAI,CAAA;KAAE,CAAA;IACtE,8DAA8D;IAC9D,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,KAAK,CAAA;IACjC,gFAAgF;IAChF,QAAQ,CAAC,KAAK,CAAC,EAAE,QAAQ,CAAC,WAAW,CAAC,CAAA;IACtC,gDAAgD;IAChD,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,iFAAiF;AACjF,QAAA,MAAM,kBAAkB,uBAAqE,CAAA;AAgD7F;;;;GAIG;AACH,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,0BAA0B,GAAG,OAAO,CAAC,WAAW,CAAC,CAkChG;AAED,0FAA0F;AAC1F,wBAAgB,iBAAiB,CAChC,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE,aAAa,EACtB,KAAK,GAAE,QAAQ,CAAC,WAAW,CAAsB,GAC/C,IAAI,CAEN;AAED,OAAO,EAAE,kBAAkB,EAAE,CAAA"}
1
+ {"version":3,"file":"get-verified-envelope.d.ts","sourceRoot":"","sources":["../../src/verify/get-verified-envelope.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,WAAW,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAA;AAEpH,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAErC,kFAAkF;AAClF,MAAM,MAAM,cAAc;AACzB,2EAA2E;AACzE;IACA,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAA;IAC7B,8EAA8E;IAC9E,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;CAC1B;AACH;;sFAEsF;GACpF;IACA,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAA;IAC1B,QAAQ,CAAC,KAAK,EAAE,oBAAoB,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,CAAA;CAC/D,CAAA;AAEJ,MAAM,WAAW,0BAA0B;IAC1C,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAA;IAC/B,uFAAuF;IACvF,QAAQ,CAAC,UAAU,EAAE,qBAAqB,CAAA;IAC1C,uFAAuF;IACvF,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,aAAa,EAAE,KAAK,CAAC,GAAG;QAAE,QAAQ,CAAC,GAAG,CAAC,EAAE,IAAI,CAAA;KAAE,CAAA;IACtE,8DAA8D;IAC9D,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,KAAK,CAAA;IACjC,gFAAgF;IAChF,QAAQ,CAAC,KAAK,CAAC,EAAE,QAAQ,CAAC,WAAW,CAAC,CAAA;IACtC,gDAAgD;IAChD,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,iFAAiF;AACjF,QAAA,MAAM,kBAAkB,uBAAqE,CAAA;AAyE7F;;;;GAIG;AACH,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,0BAA0B,GAAG,OAAO,CAAC,WAAW,CAAC,CAkChG;AAED,0FAA0F;AAC1F,wBAAgB,iBAAiB,CAChC,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE,aAAa,EACtB,KAAK,GAAE,QAAQ,CAAC,WAAW,CAAsB,GAC/C,IAAI,CAEN;AAED,OAAO,EAAE,kBAAkB,EAAE,CAAA"}
@@ -40,14 +40,38 @@ function deliveryApiUrl(s) {
40
40
  const base = s.baseUrl.replace(/\/+$/, '');
41
41
  return `${base}/api/cert/v1/delivery/${encodeURIComponent(s.platform)}/${encodeURIComponent(s.externalId)}`;
42
42
  }
43
- /** Stable cache key per (source identity × render externalId). */
43
+ /**
44
+ * A short, fast, NON-cryptographic string hash (FNV-1a, 32-bit) — used ONLY to disambiguate
45
+ * cache keys, never for security. Edge-safe (no node:crypto). Distinct envelope values for
46
+ * the same placement must produce distinct keys so a push update (or, in tests/proofs,
47
+ * verifying several different envelopes against one render context) can't be served a stale
48
+ * verdict for a different envelope.
49
+ */
50
+ function fnv1a(s) {
51
+ let h = 0x811c9dc5;
52
+ for (let i = 0; i < s.length; i++) {
53
+ h ^= s.charCodeAt(i);
54
+ // 32-bit FNV prime multiply via shifts (stays in 32-bit unsigned)
55
+ h = (h + ((h << 1) + (h << 4) + (h << 7) + (h << 8) + (h << 24))) >>> 0;
56
+ }
57
+ return h.toString(16).padStart(8, '0');
58
+ }
59
+ /** A stable string form of the metafield value for hashing (parsed → canonical-ish JSON). */
60
+ function metafieldValueKey(value) {
61
+ if (value == null)
62
+ return 'null';
63
+ const s = typeof value === 'string' ? value : JSON.stringify(value);
64
+ return fnv1a(s);
65
+ }
66
+ /** Stable cache key per (source identity × render externalId × envelope value). */
44
67
  function cacheKey(source, ctx) {
45
68
  if (source.kind === 'delivery_api') {
46
69
  return `api:${source.platform}:${source.externalId}`;
47
70
  }
48
- // Metafield: key on the rendering identity (the value is already in hand; the verdict
49
- // still depends on context). Include a short hash of the value to bust on push update.
50
- return `mf:${ctx.platform}:${ctx.externalId}`;
71
+ // Metafield: key on the rendering identity AND a short hash of the envelope value, so a
72
+ // push update (new envelope at the same placement) busts the entry, and verifying
73
+ // different envelopes against one render context never collides on a stale verdict.
74
+ return `mf:${ctx.platform}:${ctx.externalId}:${metafieldValueKey(source.value)}`;
51
75
  }
52
76
  async function fetchFromDeliveryApi(s, fetchImpl) {
53
77
  const res = await fetchImpl(deliveryApiUrl(s), { headers: { accept: 'application/json' } });
@@ -1 +1 @@
1
- {"version":3,"file":"get-verified-envelope.js","sourceRoot":"","sources":["../../src/verify/get-verified-envelope.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"get-verified-envelope.js","sourceRoot":"","sources":["../../src/verify/get-verified-envelope.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"resolve-kid.d.ts","sourceRoot":"","sources":["../../src/verify/resolve-kid.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAA;AAGzF,0EAA0E;AAC1E,MAAM,MAAM,YAAY,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,qBAAqB,CAAC,CAAC,CAAA;AAOnF,gFAAgF;AAChF,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,YAAY,GAAG,qBAAqB,CAK3E;AA+BD,MAAM,WAAW,0BAA0B;IAC1C,sDAAsD;IACtD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,iEAAiE;IACjE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;IACvB,8DAA8D;IAC9D,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,KAAK,CAAA;CACjC;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,0BAA0B,GAAG,qBAAqB,CAqB3F"}
1
+ {"version":3,"file":"resolve-kid.d.ts","sourceRoot":"","sources":["../../src/verify/resolve-kid.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAGH,OAAO,KAAK,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAA;AAGzF,0EAA0E;AAC1E,MAAM,MAAM,YAAY,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,qBAAqB,CAAC,CAAC,CAAA;AAOnF,gFAAgF;AAChF,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,YAAY,GAAG,qBAAqB,CAK3E;AAgCD,MAAM,WAAW,0BAA0B;IAC1C,sDAAsD;IACtD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,iEAAiE;IACjE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;IACvB,8DAA8D;IAC9D,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,KAAK,CAAA;CACjC;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,0BAA0B,GAAG,qBAAqB,CAqB3F"}
@@ -16,6 +16,7 @@
16
16
  * understands the two encodings CertREV may publish: a PEM string, or a JWK with an
17
17
  * Ed25519 `x` (base64url raw key).
18
18
  */
19
+ import { base64urlDecode } from '@certrev/cert-contract';
19
20
  import { TtlCache } from './cache.js';
20
21
  function asInput(v) {
21
22
  // A bare string is treated as PEM (the common deploy-config form).
@@ -28,8 +29,9 @@ export function staticKidResolver(keys) {
28
29
  return k ? asInput(k) : null;
29
30
  };
30
31
  }
32
+ // Runtime-agnostic base64url decode from the contract (no `Buffer` — edge/Workers safe).
31
33
  function base64urlToBytes(b64url) {
32
- return new Uint8Array(Buffer.from(b64url, 'base64url'));
34
+ return base64urlDecode(b64url);
33
35
  }
34
36
  function jwkToInput(jwk) {
35
37
  if (jwk.pem)
@@ -1 +1 @@
1
- {"version":3,"file":"resolve-kid.js","sourceRoot":"","sources":["../../src/verify/resolve-kid.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAGH,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAKrC,SAAS,OAAO,CAAC,CAAiC;IACjD,mEAAmE;IACnE,OAAO,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAA;AAC7D,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,iBAAiB,CAAC,IAAkB;IACnD,OAAO,CAAC,GAAG,EAAE,EAAE;QACd,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAA;QACnB,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;IAC7B,CAAC,CAAA;AACF,CAAC;AAkBD,SAAS,gBAAgB,CAAC,MAAc;IACvC,OAAO,IAAI,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAA;AACxD,CAAC;AAED,SAAS,UAAU,CAAC,GAAiB;IACpC,IAAI,GAAG,CAAC,GAAG;QAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,CAAA;IACnD,IAAI,GAAG,CAAC,CAAC,EAAE,CAAC;QACX,MAAM,KAAK,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;QACrC,IAAI,KAAK,CAAC,MAAM,KAAK,EAAE;YAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,CAAA;IACzD,CAAC;IACD,OAAO,IAAI,CAAA;AACZ,CAAC;AAWD;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAgC;IACnE,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,UAAU,CAAC,KAAK,CAAA;IACpD,MAAM,KAAK,GAAG,IAAI,QAAQ,CAAqC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,SAAS,EAAE,CAAC,CAAA;IAClG,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAA;IAE9B,KAAK,UAAU,UAAU;QACxB,MAAM,GAAG,GAAG,IAAI,GAAG,EAAiC,CAAA;QACpD,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,kBAAkB,EAAE,EAAE,CAAC,CAAA;QACtF,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,OAAO,GAAG,CAAA,CAAC,gDAAgD;QACxE,MAAM,GAAG,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAuB,CAAA;QACpD,KAAK,MAAM,GAAG,IAAI,GAAG,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC;YAClC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,CAAC,CAAA;YAC7B,IAAI,KAAK,IAAI,GAAG,CAAC,GAAG;gBAAE,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;QAC9C,CAAC;QACD,OAAO,GAAG,CAAA;IACX,CAAC;IAED,OAAO,KAAK,EAAE,GAAG,EAAE,EAAE;QACpB,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,SAAS,CAAC,SAAS,EAAE,UAAU,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAA;QAChF,OAAO,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,CAAA;IAC/B,CAAC,CAAA;AACF,CAAC"}
1
+ {"version":3,"file":"resolve-kid.js","sourceRoot":"","sources":["../../src/verify/resolve-kid.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAExD,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAKrC,SAAS,OAAO,CAAC,CAAiC;IACjD,mEAAmE;IACnE,OAAO,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAA;AAC7D,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,iBAAiB,CAAC,IAAkB;IACnD,OAAO,CAAC,GAAG,EAAE,EAAE;QACd,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAA;QACnB,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;IAC7B,CAAC,CAAA;AACF,CAAC;AAkBD,yFAAyF;AACzF,SAAS,gBAAgB,CAAC,MAAc;IACvC,OAAO,eAAe,CAAC,MAAM,CAAC,CAAA;AAC/B,CAAC;AAED,SAAS,UAAU,CAAC,GAAiB;IACpC,IAAI,GAAG,CAAC,GAAG;QAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,CAAA;IACnD,IAAI,GAAG,CAAC,CAAC,EAAE,CAAC;QACX,MAAM,KAAK,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;QACrC,IAAI,KAAK,CAAC,MAAM,KAAK,EAAE;YAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,CAAA;IACzD,CAAC;IACD,OAAO,IAAI,CAAA;AACZ,CAAC;AAWD;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAgC;IACnE,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,UAAU,CAAC,KAAK,CAAA;IACpD,MAAM,KAAK,GAAG,IAAI,QAAQ,CAAqC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,SAAS,EAAE,CAAC,CAAA;IAClG,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAA;IAE9B,KAAK,UAAU,UAAU;QACxB,MAAM,GAAG,GAAG,IAAI,GAAG,EAAiC,CAAA;QACpD,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,kBAAkB,EAAE,EAAE,CAAC,CAAA;QACtF,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,OAAO,GAAG,CAAA,CAAC,gDAAgD;QACxE,MAAM,GAAG,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAuB,CAAA;QACpD,KAAK,MAAM,GAAG,IAAI,GAAG,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC;YAClC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,CAAC,CAAA;YAC7B,IAAI,KAAK,IAAI,GAAG,CAAC,GAAG;gBAAE,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;QAC9C,CAAC;QACD,OAAO,GAAG,CAAA;IACX,CAAC;IAED,OAAO,KAAK,EAAE,GAAG,EAAE,EAAE;QACpB,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,SAAS,CAAC,SAAS,EAAE,UAAU,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAA;QAChF,OAAO,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,CAAA;IAC/B,CAAC,CAAA;AACF,CAAC"}
package/package.json CHANGED
@@ -1,70 +1,74 @@
1
1
  {
2
- "name": "@certrev/cert-block",
3
- "version": "0.1.0",
4
- "description": "Headless / crypto_verify render edge for the CertREV CertDeliveryEnvelope. SSR-safe React components (<CertBadge>/<ExpertBio>/<CertRevBacklink>), a deterministic schema.org JSON-LD projector, a fail-closed verify layer over the shared VerdictKernel, and a framework-agnostic <certrev-badge> Web Component. Sign once (portal), render everywhere (Hydrogen / Next / Builder / universal embed).",
5
- "type": "module",
6
- "main": "./dist/index.js",
7
- "types": "./dist/index.d.ts",
8
- "exports": {
9
- ".": {
10
- "types": "./dist/index.d.ts",
11
- "default": "./dist/index.js"
12
- },
13
- "./webcomponent": {
14
- "types": "./dist/webcomponent/certrev-badge.d.ts",
15
- "default": "./dist/webcomponent/certrev-badge.js"
16
- }
17
- },
18
- "files": [
19
- "dist",
20
- "src",
21
- "README.md"
22
- ],
23
- "publishConfig": {
24
- "registry": "https://registry.npmjs.org",
25
- "access": "public"
26
- },
27
- "publishTargets": [
28
- "npmjs"
29
- ],
30
- "peerDependencies": {
31
- "@certrev/cert-contract": ">=0.1.1",
32
- "react": ">=18.0.0"
33
- },
34
- "peerDependenciesMeta": {
35
- "react": {
36
- "optional": false
37
- }
38
- },
39
- "devDependencies": {
40
- "@testing-library/react": "^16.1.0",
41
- "@types/node": "^20.0.0",
42
- "@types/react": "^18.3.0",
43
- "@types/react-dom": "^18.3.0",
44
- "jsdom": "^25.0.0",
45
- "react": "^18.3.1",
46
- "react-dom": "^18.3.1",
47
- "typescript": "^6.0.3",
48
- "vitest": "^4.1.5",
49
- "@certrev/cert-contract": "0.1.1"
50
- },
51
- "keywords": [
52
- "certrev",
53
- "certification",
54
- "react",
55
- "server-components",
56
- "hydrogen",
57
- "shopify",
58
- "json-ld",
59
- "schema-org",
60
- "web-component",
61
- "ed25519",
62
- "ssr"
63
- ],
64
- "license": "MIT",
65
- "scripts": {
66
- "build": "tsc",
67
- "typecheck": "tsc --noEmit",
68
- "test": "vitest run"
69
- }
70
- }
2
+ "name": "@certrev/cert-block",
3
+ "version": "0.1.1",
4
+ "description": "Headless / crypto_verify render edge for the CertREV CertDeliveryEnvelope. SSR-safe React components (<CertBadge>/<ExpertBio>/<CertRevBacklink>), a deterministic schema.org JSON-LD projector, a fail-closed verify layer over the shared VerdictKernel, and a framework-agnostic <certrev-badge> Web Component. Sign once (portal), render everywhere (Hydrogen / Next / Builder / universal embed).",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "default": "./dist/index.js"
12
+ },
13
+ "./webcomponent": {
14
+ "types": "./dist/webcomponent/certrev-badge.d.ts",
15
+ "default": "./dist/webcomponent/certrev-badge.js"
16
+ },
17
+ "./fixtures": {
18
+ "types": "./dist/contract/fixtures.d.ts",
19
+ "default": "./dist/contract/fixtures.js"
20
+ }
21
+ },
22
+ "files": [
23
+ "dist",
24
+ "src",
25
+ "README.md"
26
+ ],
27
+ "publishConfig": {
28
+ "registry": "https://registry.npmjs.org",
29
+ "access": "public"
30
+ },
31
+ "publishTargets": [
32
+ "npmjs"
33
+ ],
34
+ "scripts": {
35
+ "build": "tsc",
36
+ "typecheck": "tsc --noEmit",
37
+ "test": "vitest run"
38
+ },
39
+ "peerDependencies": {
40
+ "@certrev/cert-contract": ">=0.1.2",
41
+ "react": ">=18.0.0"
42
+ },
43
+ "peerDependenciesMeta": {
44
+ "react": {
45
+ "optional": false
46
+ }
47
+ },
48
+ "devDependencies": {
49
+ "@certrev/cert-contract": "workspace:*",
50
+ "@testing-library/react": "^16.1.0",
51
+ "@types/node": "^20.0.0",
52
+ "@types/react": "^18.3.0",
53
+ "@types/react-dom": "^18.3.0",
54
+ "jsdom": "^25.0.0",
55
+ "react": "^18.3.1",
56
+ "react-dom": "^18.3.1",
57
+ "typescript": "^6.0.3",
58
+ "vitest": "^4.1.5"
59
+ },
60
+ "keywords": [
61
+ "certrev",
62
+ "certification",
63
+ "react",
64
+ "server-components",
65
+ "hydrogen",
66
+ "shopify",
67
+ "json-ld",
68
+ "schema-org",
69
+ "web-component",
70
+ "ed25519",
71
+ "ssr"
72
+ ],
73
+ "license": "MIT"
74
+ }
@@ -119,6 +119,42 @@ describe('getVerifiedEnvelope — metafield source', () => {
119
119
  })
120
120
  expect(verdict.decision).toBe('suppress')
121
121
  })
122
+
123
+ it('DISTINCT metafield envelopes at one placement do NOT collide on a shared cache (value-keyed)', async () => {
124
+ // Regression: the metafield cache key must include a hash of the envelope value, else
125
+ // the first verdict (render) is served for a later, DIFFERENT envelope — a fail-closed
126
+ // violation (an unverified/tampered credential rendered). Here a valid + a tampered
127
+ // envelope share the SAME resolver, context, and cache; each must get its own verdict.
128
+ const { envelope, resolveKid } = makeSignedEnvelope()
129
+ const tampered: CertDeliveryEnvelope = {
130
+ ...envelope,
131
+ payload: {
132
+ ...envelope.payload,
133
+ content: {
134
+ ...envelope.payload.content,
135
+ expert: { ...envelope.payload.content.expert, displayName: 'Dr. Forged' },
136
+ },
137
+ },
138
+ }
139
+ const cache = new TtlCache<import('../contract/kernel.js').CertVerdict>()
140
+ const ctx = { ...RENDER_CTX, now: new Date('2026-06-22T00:00:00Z') }
141
+
142
+ const validVerdict = await getVerifiedEnvelope({
143
+ source: { kind: 'metafield', value: envelope },
144
+ resolveKid,
145
+ context: ctx,
146
+ cache,
147
+ })
148
+ const tamperedVerdict = await getVerifiedEnvelope({
149
+ source: { kind: 'metafield', value: tampered },
150
+ resolveKid,
151
+ context: ctx,
152
+ cache,
153
+ })
154
+
155
+ expect(validVerdict.decision).toBe('render')
156
+ expect(tamperedVerdict).toEqual({ decision: 'suppress', reason: 'invalid_signature' })
157
+ })
122
158
  })
123
159
 
124
160
  describe('getVerifiedEnvelope — Delivery API source', () => {
@@ -16,14 +16,17 @@
16
16
  * end-to-end under the production `verifyEnvelope`, not a stand-in canonicalizer.
17
17
  */
18
18
 
19
- import { generateKeyPairSync, type KeyObject, sign as nodeSign } from 'node:crypto'
20
- import {
21
- canonicalPayloadBytes,
22
- type CertDeliveryEnvelope,
23
- type CertPayload,
24
- type Ed25519PublicKeyInput,
25
- type ResolvePublicKeyByKid,
19
+ import { generateKeyPairSync, type KeyObject } from 'node:crypto'
20
+ import type {
21
+ CertDeliveryEnvelope,
22
+ CertPayload,
23
+ Ed25519PublicKeyInput,
24
+ ResolvePublicKeyByKid,
26
25
  } from '@certrev/cert-contract'
26
+ // SIGN is Node-only and lives on the contract's signer subpath. Fixtures are themselves
27
+ // Node-only (they stand in for the issuer) and ship from the './fixtures' subpath, so the
28
+ // SDK's edge-safe main entry never pulls a Node builtin.
29
+ import { signPayloadEd25519 } from '@certrev/cert-contract/signer'
27
30
 
28
31
  const FIXTURE_KID = 'certrev-fixture-key-1'
29
32
 
@@ -89,8 +92,9 @@ export interface SignedEnvelopeFixture {
89
92
  export function makeSignedEnvelope(overrides: Partial<CertPayload> = {}, kid = FIXTURE_KID): SignedEnvelopeFixture {
90
93
  const { publicKey, privateKey } = generateKeyPairSync('ed25519')
91
94
  const payload = makeMockPayload(overrides)
92
- const bytes = canonicalPayloadBytes(payload)
93
- const sig = nodeSign(null, bytes, privateKey).toString('base64url')
95
+ // Sign the RFC-8785 canonical bytes via the contract's signer — the SAME bytes the
96
+ // edge-safe kernel recomputes on verify, so the fixture verifies end-to-end.
97
+ const sig = signPayloadEd25519(payload, privateKey)
94
98
 
95
99
  const envelope: CertDeliveryEnvelope = {
96
100
  payload,
@@ -7,8 +7,8 @@
7
7
  * never directly from `@certrev/cert-contract`, so the whole SDK's dependency on the
8
8
  * contract is funnelled through one module. The published package owns the envelope types
9
9
  * (`CertDeliveryEnvelope`, `CertPayload`, `CertCredential`, …), the RFC-8785
10
- * canonicalization (`canonicalPayloadBytes`), and the fail-closed kernel (`verifyEnvelope`,
11
- * `renderVerdict`, `verifySignatureOnly`, `toEd25519PublicKey`).
10
+ * canonicalization (`canonicalPayloadBytes`), and the fail-closed WebCrypto kernel
11
+ * (`verifyEnvelope`, `renderVerdict`, `verifySignatureOnly`, `importEd25519PublicKey`).
12
12
  *
13
13
  * `VerdictKernel` is the ONE name NOT re-exported from the package: the contract exposes
14
14
  * the kernel as free functions, and different edges bundle them with different key-resolver
package/src/index.ts CHANGED
@@ -8,11 +8,16 @@
8
8
  * graph, mergeable by @id (won't collide with Yoast).
9
9
  * • Verify layer — `getVerifiedEnvelope` (fetch from metafield OR Delivery API + run
10
10
  * the fail-closed VerdictKernel + cache), kid resolvers, the TTL/single-flight cache.
11
- * • Contract types — re-exported from `@certrev/cert-contract` (stubbed locally until
12
- * that package publishes; see the contract binding point in ./contract/kernel).
11
+ * • Contract types — re-exported from `@certrev/cert-contract` (the binding point in
12
+ * ./contract/kernel).
13
13
  *
14
- * The Web Component (`<certrev-badge>`) ships from the './webcomponent' subpath export so
15
- * importing the main entry doesn't touch `customElements` (which is undefined server-side).
14
+ * EDGE-RUNTIME SAFE. This main entry imports NO `node:crypto` and uses NO `Buffer`, so it
15
+ * loads + runs on edge/Workers runtimes (Shopify Oxygen, Cloudflare Workers, Vercel Edge).
16
+ * Two things are deliberately kept OFF this entry:
17
+ * • the Web Component (`<certrev-badge>`) → './webcomponent' subpath (touches
18
+ * `customElements`, undefined server-side);
19
+ * • the Node-only test/dev fixtures (`makeSignedEnvelope`, which signs with `node:crypto`)
20
+ * → './fixtures' subpath. Importing the main entry must never pull a Node builtin.
16
21
  */
17
22
 
18
23
  // ── React components ──────────────────────────────────────────────────────────────
@@ -31,9 +36,9 @@ export {
31
36
  type ResolvedDisplay,
32
37
  resolveDisplay,
33
38
  } from './components/format.js'
34
- // ── Test/dev fixtures (mock facts + signed-envelope generator) ─────────────────────
35
- export { FIXTURE_KID, makeMockPayload, makeSignedEnvelope, type SignedEnvelopeFixture } from './contract/fixtures.js'
36
39
  // ── Contract surface (types + kernel) — re-export the binding point ────────────────
40
+ // NOTE: the test/dev fixtures (makeSignedEnvelope, makeMockPayload, FIXTURE_KID) are
41
+ // Node-only (they sign with node:crypto) and ship from the './fixtures' subpath, NOT here.
37
42
  export {
38
43
  CANONICALIZATION,
39
44
  type CertContent,
@@ -80,14 +80,39 @@ function deliveryApiUrl(s: Extract<EnvelopeSource, { kind: 'delivery_api' }>): s
80
80
  return `${base}/api/cert/v1/delivery/${encodeURIComponent(s.platform)}/${encodeURIComponent(s.externalId)}`
81
81
  }
82
82
 
83
- /** Stable cache key per (source identity × render externalId). */
83
+ /**
84
+ * A short, fast, NON-cryptographic string hash (FNV-1a, 32-bit) — used ONLY to disambiguate
85
+ * cache keys, never for security. Edge-safe (no node:crypto). Distinct envelope values for
86
+ * the same placement must produce distinct keys so a push update (or, in tests/proofs,
87
+ * verifying several different envelopes against one render context) can't be served a stale
88
+ * verdict for a different envelope.
89
+ */
90
+ function fnv1a(s: string): string {
91
+ let h = 0x811c9dc5
92
+ for (let i = 0; i < s.length; i++) {
93
+ h ^= s.charCodeAt(i)
94
+ // 32-bit FNV prime multiply via shifts (stays in 32-bit unsigned)
95
+ h = (h + ((h << 1) + (h << 4) + (h << 7) + (h << 8) + (h << 24))) >>> 0
96
+ }
97
+ return h.toString(16).padStart(8, '0')
98
+ }
99
+
100
+ /** A stable string form of the metafield value for hashing (parsed → canonical-ish JSON). */
101
+ function metafieldValueKey(value: CertDeliveryEnvelope | string | null | undefined): string {
102
+ if (value == null) return 'null'
103
+ const s = typeof value === 'string' ? value : JSON.stringify(value)
104
+ return fnv1a(s)
105
+ }
106
+
107
+ /** Stable cache key per (source identity × render externalId × envelope value). */
84
108
  function cacheKey(source: EnvelopeSource, ctx: RenderContext): string {
85
109
  if (source.kind === 'delivery_api') {
86
110
  return `api:${source.platform}:${source.externalId}`
87
111
  }
88
- // Metafield: key on the rendering identity (the value is already in hand; the verdict
89
- // still depends on context). Include a short hash of the value to bust on push update.
90
- return `mf:${ctx.platform}:${ctx.externalId}`
112
+ // Metafield: key on the rendering identity AND a short hash of the envelope value, so a
113
+ // push update (new envelope at the same placement) busts the entry, and verifying
114
+ // different envelopes against one render context never collides on a stale verdict.
115
+ return `mf:${ctx.platform}:${ctx.externalId}:${metafieldValueKey(source.value)}`
91
116
  }
92
117
 
93
118
  async function fetchFromDeliveryApi(
@@ -17,6 +17,7 @@
17
17
  * Ed25519 `x` (base64url raw key).
18
18
  */
19
19
 
20
+ import { base64urlDecode } from '@certrev/cert-contract'
20
21
  import type { Ed25519PublicKeyInput, ResolvePublicKeyByKid } from '../contract/kernel.js'
21
22
  import { TtlCache } from './cache.js'
22
23
 
@@ -52,8 +53,9 @@ interface PublishedKeySetDoc {
52
53
  readonly keys: ReadonlyArray<PublishedJwk>
53
54
  }
54
55
 
56
+ // Runtime-agnostic base64url decode from the contract (no `Buffer` — edge/Workers safe).
55
57
  function base64urlToBytes(b64url: string): Uint8Array {
56
- return new Uint8Array(Buffer.from(b64url, 'base64url'))
58
+ return base64urlDecode(b64url)
57
59
  }
58
60
 
59
61
  function jwkToInput(jwk: PublishedJwk): Ed25519PublicKeyInput | null {
@@ -1,154 +0,0 @@
1
- /**
2
- * ─────────────────────────────────────────────────────────────────────────────
3
- * @certrev/cert-contract — INTERFACE STUB (delete on publish; see INTEGRATION below)
4
- * ─────────────────────────────────────────────────────────────────────────────
5
- *
6
- * The shared `CertDeliveryEnvelope` types + the fail-closed `VerdictKernel` live in
7
- * the published `@certrev/cert-contract` package. That package is not yet on a registry
8
- * this workspace can `pnpm install` from (it ships `file:`/workspace-only today), so
9
- * `@certrev/cert-block` imports the contract surface from THIS local interface module
10
- * instead. The types here are a byte-for-byte mirror of `cert-contract`'s `types.ts`
11
- * (the settled, panel-revised shape: structured FACTS, no rendered JSON-LD in the
12
- * payload; `subject` carries `logicalArticleId`, `canonicalUrls[]`, `installationId`,
13
- * `contentDigest`).
14
- *
15
- * INTEGRATION (when @certrev/cert-contract publishes — see README "Integration TODOs"):
16
- * 1. Delete this file and `./kernel-stub.ts`.
17
- * 2. Replace every `from '../contract/kernel-contract.js'` with
18
- * `from '@certrev/cert-contract'`.
19
- * 3. The exported names here are deliberately identical to cert-contract's exports
20
- * (`CertDeliveryEnvelope`, `CertPayload`, `CertVerdict`, `verifyEnvelope`,
21
- * `renderVerdict`, `verifySignatureOnly`, `ResolvePublicKeyByKid`, `RenderContext`,
22
- * `Ed25519PublicKeyInput`), so the swap is a find-and-replace of the import
23
- * specifier — no call-site churn.
24
- *
25
- * Because this is type-only for everything the SDK consumes at COMPILE time, swapping
26
- * the import path is the only change; the runtime kernel comes from `./kernel-stub.ts`
27
- * today and from `@certrev/cert-contract` after publish.
28
- */
29
- /** Bump on ANY breaking change to the payload shape or signing rules. */
30
- export declare const CONTRACT_VERSION: 1;
31
- export type ContractVersion = typeof CONTRACT_VERSION;
32
- /** RFC 8785 JSON Canonicalization Scheme — the bytes that get signed/hashed. */
33
- export declare const CANONICALIZATION: "RFC8785-JCS";
34
- /** Ed25519 (PureEdDSA). */
35
- export declare const SIGNATURE_ALG: "ed25519";
36
- export type SignatureAlg = typeof SIGNATURE_ALG;
37
- export interface CertSubject {
38
- readonly platform: string;
39
- readonly externalId: string;
40
- readonly logicalArticleId: string;
41
- readonly canonicalUrls: ReadonlyArray<string>;
42
- readonly installationId: string | null;
43
- readonly contentDigest: string | null;
44
- }
45
- export interface CertDisplayConfig {
46
- readonly accentColor?: string | null;
47
- readonly showExpertPhoto?: boolean;
48
- readonly showAuthor?: boolean;
49
- readonly showMemo?: boolean;
50
- readonly badgeStyle?: 'full' | 'compact';
51
- }
52
- export interface CertCredential {
53
- readonly abbreviation: string;
54
- readonly fullName: string;
55
- }
56
- export interface CertContent {
57
- readonly expert: {
58
- readonly displayName: string;
59
- readonly credentials: ReadonlyArray<CertCredential>;
60
- readonly profileUrl: string | null;
61
- readonly photoUrl: string | null;
62
- };
63
- readonly author: {
64
- readonly name: string;
65
- readonly title: string | null;
66
- };
67
- readonly memo: string | null;
68
- readonly certifiedAt: string;
69
- readonly contentModifiedAt: string | null;
70
- readonly verifyUrl: string;
71
- readonly display: CertDisplayConfig;
72
- }
73
- export interface CertLifecycle {
74
- readonly issuedAt: string;
75
- readonly expiresAt: string;
76
- readonly revokedAt: string | null;
77
- readonly revision: number;
78
- }
79
- export interface CertPayload {
80
- readonly contractVersion: ContractVersion;
81
- readonly certId: string;
82
- readonly subject: CertSubject;
83
- readonly content: CertContent;
84
- readonly lifecycle: CertLifecycle;
85
- }
86
- export interface CertSignature {
87
- readonly alg: SignatureAlg;
88
- readonly kid: string;
89
- readonly sig: string;
90
- readonly signedAt: string;
91
- }
92
- export interface CertDeliveryEnvelope {
93
- readonly payload: CertPayload;
94
- readonly signature: CertSignature;
95
- }
96
- export type CertVerdict = {
97
- readonly decision: 'render';
98
- readonly payload: CertPayload;
99
- } | {
100
- readonly decision: 'suppress';
101
- readonly reason: CertSuppressReason;
102
- };
103
- export type CertSuppressReason = 'unsupported_contract_version' | 'unsupported_alg' | 'unknown_key' | 'invalid_signature' | 'platform_mismatch' | 'subject_mismatch' | 'revoked' | 'expired' | 'content_drift';
104
- /** The Ed25519 public-key encodings a kid resolver may hand the kernel. */
105
- export type Ed25519PublicKeyInput = {
106
- readonly format: 'spki-der';
107
- readonly bytes: Uint8Array;
108
- } | {
109
- readonly format: 'spki-base64';
110
- readonly base64: string;
111
- } | {
112
- readonly format: 'pem';
113
- readonly pem: string;
114
- } | {
115
- readonly format: 'raw';
116
- readonly bytes: Uint8Array;
117
- };
118
- /**
119
- * A kid → public-key resolver. Returns a usable Ed25519 key for the given kid, or
120
- * null/undefined when the kid is unknown (→ suppress 'unknown_key'). May be async so
121
- * an edge can fetch + cache a published key set. The real kernel also accepts a Node
122
- * KeyObject; we model only the SDK-relevant inputs here.
123
- */
124
- export type ResolvePublicKeyByKid = (kid: string) => Promise<Ed25519PublicKeyInput | null | undefined> | Ed25519PublicKeyInput | null | undefined;
125
- /** Edge-supplied context for the policy phase. */
126
- export interface RenderContext {
127
- readonly platform: string;
128
- readonly externalId: string;
129
- readonly liveContentHash?: string | null;
130
- readonly now?: Date;
131
- }
132
- /** Full kernel: verify signature, then apply subject/lifecycle/drift policy. */
133
- export type VerifyEnvelope = (envelope: CertDeliveryEnvelope, resolveKid: ResolvePublicKeyByKid, ctx: RenderContext) => Promise<CertVerdict>;
134
- /** Phase-2-only policy over an already-verified payload. */
135
- export type RenderVerdict = (payload: CertPayload, ctx: RenderContext) => CertVerdict;
136
- /** Phase-1-only cryptographic verification. */
137
- export type VerifySignatureOnly = (envelope: CertDeliveryEnvelope, resolveKid: ResolvePublicKeyByKid) => Promise<{
138
- ok: true;
139
- } | {
140
- ok: false;
141
- reason: CertSuppressReason;
142
- }>;
143
- /**
144
- * The kernel function set as a single named interface — what the SDK depends on at
145
- * the value level. `@certrev/cert-contract` exposes these as free functions; the SDK
146
- * binds them through `./kernel-stub` today and re-points to the real exports on
147
- * publish.
148
- */
149
- export interface VerdictKernel {
150
- readonly verifyEnvelope: VerifyEnvelope;
151
- readonly renderVerdict: RenderVerdict;
152
- readonly verifySignatureOnly: VerifySignatureOnly;
153
- }
154
- //# sourceMappingURL=kernel-contract.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"kernel-contract.d.ts","sourceRoot":"","sources":["../../src/contract/kernel-contract.ts"],"names":[],"mappings":"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"}
@@ -1,35 +0,0 @@
1
- /**
2
- * ─────────────────────────────────────────────────────────────────────────────
3
- * @certrev/cert-contract — INTERFACE STUB (delete on publish; see INTEGRATION below)
4
- * ─────────────────────────────────────────────────────────────────────────────
5
- *
6
- * The shared `CertDeliveryEnvelope` types + the fail-closed `VerdictKernel` live in
7
- * the published `@certrev/cert-contract` package. That package is not yet on a registry
8
- * this workspace can `pnpm install` from (it ships `file:`/workspace-only today), so
9
- * `@certrev/cert-block` imports the contract surface from THIS local interface module
10
- * instead. The types here are a byte-for-byte mirror of `cert-contract`'s `types.ts`
11
- * (the settled, panel-revised shape: structured FACTS, no rendered JSON-LD in the
12
- * payload; `subject` carries `logicalArticleId`, `canonicalUrls[]`, `installationId`,
13
- * `contentDigest`).
14
- *
15
- * INTEGRATION (when @certrev/cert-contract publishes — see README "Integration TODOs"):
16
- * 1. Delete this file and `./kernel-stub.ts`.
17
- * 2. Replace every `from '../contract/kernel-contract.js'` with
18
- * `from '@certrev/cert-contract'`.
19
- * 3. The exported names here are deliberately identical to cert-contract's exports
20
- * (`CertDeliveryEnvelope`, `CertPayload`, `CertVerdict`, `verifyEnvelope`,
21
- * `renderVerdict`, `verifySignatureOnly`, `ResolvePublicKeyByKid`, `RenderContext`,
22
- * `Ed25519PublicKeyInput`), so the swap is a find-and-replace of the import
23
- * specifier — no call-site churn.
24
- *
25
- * Because this is type-only for everything the SDK consumes at COMPILE time, swapping
26
- * the import path is the only change; the runtime kernel comes from `./kernel-stub.ts`
27
- * today and from `@certrev/cert-contract` after publish.
28
- */
29
- /** Bump on ANY breaking change to the payload shape or signing rules. */
30
- export const CONTRACT_VERSION = 1;
31
- /** RFC 8785 JSON Canonicalization Scheme — the bytes that get signed/hashed. */
32
- export const CANONICALIZATION = 'RFC8785-JCS';
33
- /** Ed25519 (PureEdDSA). */
34
- export const SIGNATURE_ALG = 'ed25519';
35
- //# sourceMappingURL=kernel-contract.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"kernel-contract.js","sourceRoot":"","sources":["../../src/contract/kernel-contract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,yEAAyE;AACzE,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAU,CAAA;AAG1C,gFAAgF;AAChF,MAAM,CAAC,MAAM,gBAAgB,GAAG,aAAsB,CAAA;AAEtD,2BAA2B;AAC3B,MAAM,CAAC,MAAM,aAAa,GAAG,SAAkB,CAAA"}
@@ -1,44 +0,0 @@
1
- /**
2
- * ─────────────────────────────────────────────────────────────────────────────
3
- * VerdictKernel — LOCAL STUB (delete on publish; mirrors @certrev/cert-contract)
4
- * ─────────────────────────────────────────────────────────────────────────────
5
- *
6
- * A faithful, self-contained implementation of the cert-contract VerdictKernel so the
7
- * SDK's verify layer + tests run NOW, before `@certrev/cert-contract` publishes to a
8
- * registry this workspace installs from. The behavior is identical to the real kernel:
9
- * • Ed25519 detached signature verified over the RFC-8785 (JCS) canonical bytes of
10
- * `payload` (lexicographic key order, minimal whitespace, UTF-8).
11
- * • Fail-closed pipeline: shape → alg → kid → signature → platform → subject →
12
- * revoked → expired → drift → render. Any failure short-circuits to `suppress`.
13
- * • Never throws on a bad envelope — a malformed input / throwing resolver fails
14
- * closed to `suppress`, not to an exception a caller might swallow into a render.
15
- *
16
- * The byte-identical canonicalization across PHP / Node is what makes the credential
17
- * portable; here we hand-roll a deterministic JCS serializer (sufficient for the
18
- * envelope's all-string/number/bool/array/object shape — no exotic numbers) so the SDK
19
- * carries no production crypto-canonicalization of its own that could DRIFT from the
20
- * contract. On publish, the real `canonicalize` (RFC 8785) from cert-contract is used.
21
- *
22
- * INTEGRATION: delete this file + `./kernel-contract.ts`; import `verifyEnvelope`,
23
- * `renderVerdict`, `verifySignatureOnly`, `toEd25519PublicKey` from
24
- * `@certrev/cert-contract`. See README "Integration TODOs".
25
- */
26
- import { type KeyObject } from 'node:crypto';
27
- import type { CertDeliveryEnvelope, CertPayload, CertSuppressReason, CertVerdict, Ed25519PublicKeyInput, RenderContext, ResolvePublicKeyByKid } from './kernel-contract.js';
28
- /** Mirror of cert-contract's `toEd25519PublicKey` for the input encodings the SDK uses. */
29
- declare function toEd25519PublicKey(input: Ed25519PublicKeyInput): KeyObject;
30
- type CryptoResult = {
31
- ok: true;
32
- } | {
33
- ok: false;
34
- reason: CertSuppressReason;
35
- };
36
- /** Phase-2-only policy verdict over an already-authentic payload. Pure + synchronous. */
37
- export declare function renderVerdict(payload: CertPayload, ctx: RenderContext): CertVerdict;
38
- /** Phase-1-only cryptographic verification. */
39
- export declare function verifySignatureOnly(envelope: CertDeliveryEnvelope, resolveKid: ResolvePublicKeyByKid): Promise<CryptoResult>;
40
- /** Full kernel: verify signature, then apply policy. Fail-closed, never throws. */
41
- export declare function verifyEnvelope(envelope: CertDeliveryEnvelope, resolveKid: ResolvePublicKeyByKid, ctx: RenderContext): Promise<CertVerdict>;
42
- /** Re-export for tests that need to build a public key from raw/spki bytes. */
43
- export { toEd25519PublicKey };
44
- //# sourceMappingURL=kernel-stub.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"kernel-stub.d.ts","sourceRoot":"","sources":["../../src/contract/kernel-stub.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EAAmB,KAAK,SAAS,EAAwB,MAAM,aAAa,CAAA;AACnF,OAAO,KAAK,EACX,oBAAoB,EACpB,WAAW,EACX,kBAAkB,EAClB,WAAW,EACX,qBAAqB,EACrB,aAAa,EACb,qBAAqB,EACrB,MAAM,sBAAsB,CAAA;AA4C7B,2FAA2F;AAC3F,iBAAS,kBAAkB,CAAC,KAAK,EAAE,qBAAqB,GAAG,SAAS,CAkBnE;AAUD,KAAK,YAAY,GAAG;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,kBAAkB,CAAA;CAAE,CAAA;AA6B5E,yFAAyF;AACzF,wBAAgB,aAAa,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,EAAE,aAAa,GAAG,WAAW,CAoBnF;AAED,+CAA+C;AAC/C,wBAAsB,mBAAmB,CACxC,QAAQ,EAAE,oBAAoB,EAC9B,UAAU,EAAE,qBAAqB,GAC/B,OAAO,CAAC,YAAY,CAAC,CAEvB;AAED,mFAAmF;AACnF,wBAAsB,cAAc,CACnC,QAAQ,EAAE,oBAAoB,EAC9B,UAAU,EAAE,qBAAqB,EACjC,GAAG,EAAE,aAAa,GAChB,OAAO,CAAC,WAAW,CAAC,CAWtB;AAED,+EAA+E;AAC/E,OAAO,EAAE,kBAAkB,EAAE,CAAA"}
@@ -1,163 +0,0 @@
1
- /**
2
- * ─────────────────────────────────────────────────────────────────────────────
3
- * VerdictKernel — LOCAL STUB (delete on publish; mirrors @certrev/cert-contract)
4
- * ─────────────────────────────────────────────────────────────────────────────
5
- *
6
- * A faithful, self-contained implementation of the cert-contract VerdictKernel so the
7
- * SDK's verify layer + tests run NOW, before `@certrev/cert-contract` publishes to a
8
- * registry this workspace installs from. The behavior is identical to the real kernel:
9
- * • Ed25519 detached signature verified over the RFC-8785 (JCS) canonical bytes of
10
- * `payload` (lexicographic key order, minimal whitespace, UTF-8).
11
- * • Fail-closed pipeline: shape → alg → kid → signature → platform → subject →
12
- * revoked → expired → drift → render. Any failure short-circuits to `suppress`.
13
- * • Never throws on a bad envelope — a malformed input / throwing resolver fails
14
- * closed to `suppress`, not to an exception a caller might swallow into a render.
15
- *
16
- * The byte-identical canonicalization across PHP / Node is what makes the credential
17
- * portable; here we hand-roll a deterministic JCS serializer (sufficient for the
18
- * envelope's all-string/number/bool/array/object shape — no exotic numbers) so the SDK
19
- * carries no production crypto-canonicalization of its own that could DRIFT from the
20
- * contract. On publish, the real `canonicalize` (RFC 8785) from cert-contract is used.
21
- *
22
- * INTEGRATION: delete this file + `./kernel-contract.ts`; import `verifyEnvelope`,
23
- * `renderVerdict`, `verifySignatureOnly`, `toEd25519PublicKey` from
24
- * `@certrev/cert-contract`. See README "Integration TODOs".
25
- */
26
- import { createPublicKey, verify as nodeVerify } from 'node:crypto';
27
- import { CONTRACT_VERSION, SIGNATURE_ALG } from './kernel-contract.js';
28
- // ── RFC-8785 (JCS) canonicalization — minimal, deterministic, envelope-shaped ─────
29
- /**
30
- * Serialize a JSON value to its RFC-8785 canonical string form: object keys sorted by
31
- * UTF-16 code unit, no insignificant whitespace, JSON string escaping. The payload is
32
- * all strings / finite numbers / booleans / null / arrays / objects, so we do NOT need
33
- * the full ECMAScript number-formatting machinery the production `canonicalize` package
34
- * implements — integers + ISO strings serialize identically either way. This stub
35
- * exists only so tests run; the published path uses cert-contract's vetted JCS.
36
- */
37
- function jcs(value) {
38
- if (value === null)
39
- return 'null';
40
- const t = typeof value;
41
- if (t === 'string')
42
- return JSON.stringify(value);
43
- if (t === 'number') {
44
- if (!Number.isFinite(value))
45
- throw new Error('jcs: non-finite number');
46
- return JSON.stringify(value);
47
- }
48
- if (t === 'boolean')
49
- return value ? 'true' : 'false';
50
- if (Array.isArray(value)) {
51
- return `[${value.map((v) => jcs(v)).join(',')}]`;
52
- }
53
- if (t === 'object') {
54
- const obj = value;
55
- const keys = Object.keys(obj)
56
- .filter((k) => obj[k] !== undefined)
57
- .sort();
58
- return `{${keys.map((k) => `${JSON.stringify(k)}:${jcs(obj[k])}`).join(',')}}`;
59
- }
60
- throw new Error(`jcs: unsupported value type ${t}`);
61
- }
62
- function canonicalPayloadBytes(payload) {
63
- return new TextEncoder().encode(jcs(payload));
64
- }
65
- function base64urlDecode(s) {
66
- return new Uint8Array(Buffer.from(s, 'base64url'));
67
- }
68
- const RAW_SPKI_PREFIX = Uint8Array.from([0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x70, 0x03, 0x21, 0x00]);
69
- /** Mirror of cert-contract's `toEd25519PublicKey` for the input encodings the SDK uses. */
70
- function toEd25519PublicKey(input) {
71
- switch (input.format) {
72
- case 'pem':
73
- return createPublicKey({ key: input.pem, format: 'pem' });
74
- case 'spki-base64':
75
- return createPublicKey({ key: Buffer.from(input.base64, 'base64'), format: 'der', type: 'spki' });
76
- case 'spki-der':
77
- return createPublicKey({ key: Buffer.from(input.bytes), format: 'der', type: 'spki' });
78
- case 'raw': {
79
- if (input.bytes.length !== 32) {
80
- throw new Error(`ed25519 raw public key must be 32 bytes, got ${input.bytes.length}`);
81
- }
82
- const spki = new Uint8Array(RAW_SPKI_PREFIX.length + 32);
83
- spki.set(RAW_SPKI_PREFIX, 0);
84
- spki.set(input.bytes, RAW_SPKI_PREFIX.length);
85
- return createPublicKey({ key: Buffer.from(spki), format: 'der', type: 'spki' });
86
- }
87
- }
88
- }
89
- function verifyDetached(payload, sigBase64url, publicKey) {
90
- try {
91
- return nodeVerify(null, canonicalPayloadBytes(payload), publicKey, base64urlDecode(sigBase64url));
92
- }
93
- catch {
94
- return false;
95
- }
96
- }
97
- async function verifyCryptographic(envelope, resolveKid) {
98
- const { payload, signature } = envelope ?? {};
99
- if (!payload || !signature || payload.contractVersion !== CONTRACT_VERSION) {
100
- return { ok: false, reason: 'unsupported_contract_version' };
101
- }
102
- if (signature.alg !== SIGNATURE_ALG) {
103
- return { ok: false, reason: 'unsupported_alg' };
104
- }
105
- const resolved = await resolveKid(signature.kid);
106
- if (!resolved) {
107
- return { ok: false, reason: 'unknown_key' };
108
- }
109
- let key;
110
- try {
111
- key = toEd25519PublicKey(resolved);
112
- }
113
- catch {
114
- return { ok: false, reason: 'unknown_key' };
115
- }
116
- if (!verifyDetached(payload, signature.sig, key)) {
117
- return { ok: false, reason: 'invalid_signature' };
118
- }
119
- return { ok: true };
120
- }
121
- /** Phase-2-only policy verdict over an already-authentic payload. Pure + synchronous. */
122
- export function renderVerdict(payload, ctx) {
123
- const now = ctx.now ?? new Date();
124
- if (payload.subject.platform !== ctx.platform) {
125
- return { decision: 'suppress', reason: 'platform_mismatch' };
126
- }
127
- if (payload.subject.externalId !== ctx.externalId) {
128
- return { decision: 'suppress', reason: 'subject_mismatch' };
129
- }
130
- if (payload.lifecycle.revokedAt !== null) {
131
- return { decision: 'suppress', reason: 'revoked' };
132
- }
133
- if (now.getTime() >= Date.parse(payload.lifecycle.expiresAt)) {
134
- return { decision: 'suppress', reason: 'expired' };
135
- }
136
- const bound = payload.subject.contentDigest;
137
- const live = ctx.liveContentHash;
138
- if (bound !== null && live != null && bound !== live) {
139
- return { decision: 'suppress', reason: 'content_drift' };
140
- }
141
- return { decision: 'render', payload };
142
- }
143
- /** Phase-1-only cryptographic verification. */
144
- export async function verifySignatureOnly(envelope, resolveKid) {
145
- return verifyCryptographic(envelope, resolveKid);
146
- }
147
- /** Full kernel: verify signature, then apply policy. Fail-closed, never throws. */
148
- export async function verifyEnvelope(envelope, resolveKid, ctx) {
149
- let crypto;
150
- try {
151
- crypto = await verifyCryptographic(envelope, resolveKid);
152
- }
153
- catch {
154
- return { decision: 'suppress', reason: 'unknown_key' };
155
- }
156
- if (!crypto.ok) {
157
- return { decision: 'suppress', reason: crypto.reason };
158
- }
159
- return renderVerdict(envelope.payload, ctx);
160
- }
161
- /** Re-export for tests that need to build a public key from raw/spki bytes. */
162
- export { toEd25519PublicKey };
163
- //# sourceMappingURL=kernel-stub.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"kernel-stub.js","sourceRoot":"","sources":["../../src/contract/kernel-stub.ts"],"names":[],"mappings":"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"}