@certrev/cert-block 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/builder/index.d.ts +73 -0
- package/dist/builder/index.d.ts.map +1 -0
- package/dist/builder/index.js +63 -0
- package/dist/builder/index.js.map +1 -0
- package/dist/contract/fixtures.d.ts +1 -1
- package/dist/contract/fixtures.d.ts.map +1 -1
- package/dist/contract/fixtures.js +8 -4
- package/dist/contract/fixtures.js.map +1 -1
- package/dist/contract/kernel.d.ts +2 -2
- package/dist/contract/kernel.js +2 -2
- package/dist/index.d.ts +9 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -6
- package/dist/index.js.map +1 -1
- package/dist/verify/get-verified-envelope.d.ts.map +1 -1
- package/dist/verify/get-verified-envelope.js +28 -4
- package/dist/verify/get-verified-envelope.js.map +1 -1
- package/dist/verify/resolve-kid.d.ts.map +1 -1
- package/dist/verify/resolve-kid.js +3 -1
- package/dist/verify/resolve-kid.js.map +1 -1
- package/package.json +77 -69
- package/src/__tests__/verify.test.ts +36 -0
- package/src/builder/__tests__/builder.test.tsx +81 -0
- package/src/builder/index.tsx +100 -0
- package/src/contract/fixtures.ts +13 -9
- package/src/contract/kernel.ts +2 -2
- package/src/index.ts +11 -6
- package/src/verify/get-verified-envelope.ts +29 -4
- package/src/verify/resolve-kid.ts +3 -1
- package/dist/contract/kernel-contract.d.ts +0 -154
- package/dist/contract/kernel-contract.d.ts.map +0 -1
- package/dist/contract/kernel-contract.js +0 -35
- package/dist/contract/kernel-contract.js.map +0 -1
- package/dist/contract/kernel-stub.d.ts +0 -44
- package/dist/contract/kernel-stub.d.ts.map +0 -1
- package/dist/contract/kernel-stub.js +0 -163
- package/dist/contract/kernel-stub.js.map +0 -1
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @certrev/cert-block/builder — the Builder.io adapter for the cert-block render edge.
|
|
3
|
+
*
|
|
4
|
+
* Lets a Builder.io content editor place a "CertREV Review" block into a page; the
|
|
5
|
+
* headless app's loader (Hydrogen/Next/Remix) crypto-verifies that placement's signed
|
|
6
|
+
* envelope and supplies the verdict via React context; this block renders cert-block's
|
|
7
|
+
* <CertReview> from the VERIFIED verdict — and renders NOTHING (fail-closed) on any
|
|
8
|
+
* suppress or unknown placement.
|
|
9
|
+
*
|
|
10
|
+
* THE TRUST BOUNDARY: the credential is never trusted from CMS content. A Builder block
|
|
11
|
+
* only carries an opaque `placementId` pointer; the authority comes solely from the
|
|
12
|
+
* loader-side WebCrypto verdict supplied through <CertVerifyProvider>. So a revoked /
|
|
13
|
+
* tampered / expired / wrong-subject placement that an editor drops into Builder renders
|
|
14
|
+
* nothing, even though the block is present in the published content.
|
|
15
|
+
*
|
|
16
|
+
* cert-block carries NO dependency on `@builder.io/sdk-react` — the registration's shape is
|
|
17
|
+
* declared structurally below, so the emitted JS pulls no Builder code and the type resolves
|
|
18
|
+
* without Builder installed. The consumer (who already has Builder) passes
|
|
19
|
+
* `certReviewBuilderComponent` to Builder's `<Content customComponents={[...]}>`; it is
|
|
20
|
+
* assignable to Builder's `RegisteredComponent` there.
|
|
21
|
+
*/
|
|
22
|
+
import { type ReactNode } from 'react';
|
|
23
|
+
import type { CertVerdict } from '../contract/kernel.js';
|
|
24
|
+
/** A loader-verified placement: the verdict cert-block renders from, plus the canonical
|
|
25
|
+
* page URL for JSON-LD @id alignment. */
|
|
26
|
+
export interface VerifiedPlacement {
|
|
27
|
+
readonly verdict: CertVerdict;
|
|
28
|
+
readonly pageUrl?: string;
|
|
29
|
+
}
|
|
30
|
+
/** Map of `placementId` → the loader's verified result. Built server-side in the loader
|
|
31
|
+
* (it crypto-verifies each placement) and handed to <CertVerifyProvider>. */
|
|
32
|
+
export type VerifiedPlacements = Record<string, VerifiedPlacement>;
|
|
33
|
+
/** Wraps Builder's <Content>; carries the loader's verified verdicts down to every
|
|
34
|
+
* CertReview block, keyed by `placementId`. */
|
|
35
|
+
export declare function CertVerifyProvider({ value, children, }: {
|
|
36
|
+
readonly value: VerifiedPlacements;
|
|
37
|
+
readonly children: ReactNode;
|
|
38
|
+
}): import("react").JSX.Element;
|
|
39
|
+
export interface CertReviewBlockProps {
|
|
40
|
+
/** The CertREV placement id the editor set on this Builder block. */
|
|
41
|
+
readonly placementId?: string;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* The component Builder renders for a "CertREV Review" block. It pulls the loader-verified
|
|
45
|
+
* verdict for its `placementId` from context and renders <CertReview>. Unknown placement
|
|
46
|
+
* OR a non-`render` verdict → renders nothing. cert-block's <CertReview> ALSO suppresses on
|
|
47
|
+
* a non-render verdict, so the boundary fails closed twice over (defense in depth).
|
|
48
|
+
*/
|
|
49
|
+
export declare function CertReviewBlock({ placementId }: CertReviewBlockProps): import("react").JSX.Element | null;
|
|
50
|
+
/**
|
|
51
|
+
* Structural shape of `@builder.io/sdk-react`'s `RegisteredComponent` — exactly the subset
|
|
52
|
+
* cert-block populates. Declared locally (not imported) so cert-block needs no Builder
|
|
53
|
+
* build- or runtime-dependency; the object below is assignable to Builder's
|
|
54
|
+
* `RegisteredComponent` at the consumer's `<Content customComponents={[...]}>` call site.
|
|
55
|
+
*/
|
|
56
|
+
export interface CertReviewBuilderRegistration {
|
|
57
|
+
component: typeof CertReviewBlock;
|
|
58
|
+
name: string;
|
|
59
|
+
inputs: Array<{
|
|
60
|
+
name: string;
|
|
61
|
+
type: 'string';
|
|
62
|
+
required?: boolean;
|
|
63
|
+
helperText?: string;
|
|
64
|
+
}>;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* The registration object to pass to Builder's `<Content customComponents={[...]}>`.
|
|
68
|
+
* Editors see a "CertREV Review" component with one input — the placement id. Because the
|
|
69
|
+
* block is matched by NAME at render time, this also works for content created via the
|
|
70
|
+
* Builder Write API (no visual-editor registration required for rendering).
|
|
71
|
+
*/
|
|
72
|
+
export declare const certReviewBuilderComponent: CertReviewBuilderRegistration;
|
|
73
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/builder/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,EAAiB,KAAK,SAAS,EAAc,MAAM,OAAO,CAAA;AAEjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAExD;0CAC0C;AAC1C,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAA;IAC7B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CACzB;AAED;8EAC8E;AAC9E,MAAM,MAAM,kBAAkB,GAAG,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAA;AAIlE;gDACgD;AAChD,wBAAgB,kBAAkB,CAAC,EAClC,KAAK,EACL,QAAQ,GACR,EAAE;IACF,QAAQ,CAAC,KAAK,EAAE,kBAAkB,CAAA;IAClC,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAA;CAC5B,+BAEA;AAED,MAAM,WAAW,oBAAoB;IACpC,qEAAqE;IACrE,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAC7B;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,EAAE,WAAW,EAAE,EAAE,oBAAoB,sCAKpE;AAED;;;;;GAKG;AACH,MAAM,WAAW,6BAA6B;IAC7C,SAAS,EAAE,OAAO,eAAe,CAAA;IACjC,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,QAAQ,CAAC;QAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CACxF;AAED;;;;;GAKG;AACH,eAAO,MAAM,0BAA0B,EAAE,6BAaxC,CAAA"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* @certrev/cert-block/builder — the Builder.io adapter for the cert-block render edge.
|
|
4
|
+
*
|
|
5
|
+
* Lets a Builder.io content editor place a "CertREV Review" block into a page; the
|
|
6
|
+
* headless app's loader (Hydrogen/Next/Remix) crypto-verifies that placement's signed
|
|
7
|
+
* envelope and supplies the verdict via React context; this block renders cert-block's
|
|
8
|
+
* <CertReview> from the VERIFIED verdict — and renders NOTHING (fail-closed) on any
|
|
9
|
+
* suppress or unknown placement.
|
|
10
|
+
*
|
|
11
|
+
* THE TRUST BOUNDARY: the credential is never trusted from CMS content. A Builder block
|
|
12
|
+
* only carries an opaque `placementId` pointer; the authority comes solely from the
|
|
13
|
+
* loader-side WebCrypto verdict supplied through <CertVerifyProvider>. So a revoked /
|
|
14
|
+
* tampered / expired / wrong-subject placement that an editor drops into Builder renders
|
|
15
|
+
* nothing, even though the block is present in the published content.
|
|
16
|
+
*
|
|
17
|
+
* cert-block carries NO dependency on `@builder.io/sdk-react` — the registration's shape is
|
|
18
|
+
* declared structurally below, so the emitted JS pulls no Builder code and the type resolves
|
|
19
|
+
* without Builder installed. The consumer (who already has Builder) passes
|
|
20
|
+
* `certReviewBuilderComponent` to Builder's `<Content customComponents={[...]}>`; it is
|
|
21
|
+
* assignable to Builder's `RegisteredComponent` there.
|
|
22
|
+
*/
|
|
23
|
+
import { createContext, useContext } from 'react';
|
|
24
|
+
import { CertReview } from '../components/CertReview.js';
|
|
25
|
+
const CertVerifyContext = createContext({});
|
|
26
|
+
/** Wraps Builder's <Content>; carries the loader's verified verdicts down to every
|
|
27
|
+
* CertReview block, keyed by `placementId`. */
|
|
28
|
+
export function CertVerifyProvider({ value, children, }) {
|
|
29
|
+
return _jsx(CertVerifyContext.Provider, { value: value, children: children });
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* The component Builder renders for a "CertREV Review" block. It pulls the loader-verified
|
|
33
|
+
* verdict for its `placementId` from context and renders <CertReview>. Unknown placement
|
|
34
|
+
* OR a non-`render` verdict → renders nothing. cert-block's <CertReview> ALSO suppresses on
|
|
35
|
+
* a non-render verdict, so the boundary fails closed twice over (defense in depth).
|
|
36
|
+
*/
|
|
37
|
+
export function CertReviewBlock({ placementId }) {
|
|
38
|
+
const placements = useContext(CertVerifyContext);
|
|
39
|
+
const placement = placementId ? placements[placementId] : undefined;
|
|
40
|
+
if (!placement)
|
|
41
|
+
return null;
|
|
42
|
+
return _jsx(CertReview, { verdict: placement.verdict, pageUrl: placement.pageUrl });
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* The registration object to pass to Builder's `<Content customComponents={[...]}>`.
|
|
46
|
+
* Editors see a "CertREV Review" component with one input — the placement id. Because the
|
|
47
|
+
* block is matched by NAME at render time, this also works for content created via the
|
|
48
|
+
* Builder Write API (no visual-editor registration required for rendering).
|
|
49
|
+
*/
|
|
50
|
+
export const certReviewBuilderComponent = {
|
|
51
|
+
component: CertReviewBlock,
|
|
52
|
+
name: 'CertREV Review',
|
|
53
|
+
inputs: [
|
|
54
|
+
{
|
|
55
|
+
name: 'placementId',
|
|
56
|
+
type: 'string',
|
|
57
|
+
required: true,
|
|
58
|
+
helperText: 'CertREV placement id (which certified article this badge attests). The headless ' +
|
|
59
|
+
'loader verifies that placement’s signed envelope; only a render-verdict shows a badge.',
|
|
60
|
+
},
|
|
61
|
+
],
|
|
62
|
+
};
|
|
63
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/builder/index.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,EAAE,aAAa,EAAkB,UAAU,EAAE,MAAM,OAAO,CAAA;AACjE,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAA;AAcxD,MAAM,iBAAiB,GAAG,aAAa,CAAqB,EAAE,CAAC,CAAA;AAE/D;gDACgD;AAChD,MAAM,UAAU,kBAAkB,CAAC,EAClC,KAAK,EACL,QAAQ,GAIR;IACA,OAAO,KAAC,iBAAiB,CAAC,QAAQ,IAAC,KAAK,EAAE,KAAK,YAAG,QAAQ,GAA8B,CAAA;AACzF,CAAC;AAOD;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,EAAE,WAAW,EAAwB;IACpE,MAAM,UAAU,GAAG,UAAU,CAAC,iBAAiB,CAAC,CAAA;IAChD,MAAM,SAAS,GAAG,WAAW,CAAC,CAAC,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;IACnE,IAAI,CAAC,SAAS;QAAE,OAAO,IAAI,CAAA;IAC3B,OAAO,KAAC,UAAU,IAAC,OAAO,EAAE,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,SAAS,CAAC,OAAO,GAAI,CAAA;AAC9E,CAAC;AAcD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAkC;IACxE,SAAS,EAAE,eAAe;IAC1B,IAAI,EAAE,gBAAgB;IACtB,MAAM,EAAE;QACP;YACC,IAAI,EAAE,aAAa;YACnB,IAAI,EAAE,QAAQ;YACd,QAAQ,EAAE,IAAI;YACd,UAAU,EACT,kFAAkF;gBAClF,wFAAwF;SACzF;KACD;CACD,CAAA"}
|
|
@@ -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 {
|
|
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,
|
|
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
|
|
19
|
-
|
|
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
|
-
|
|
76
|
-
|
|
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":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,mBAAmB,EAAkB,
|
|
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
|
|
11
|
-
* `renderVerdict`, `verifySignatureOnly`, `
|
|
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/contract/kernel.js
CHANGED
|
@@ -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
|
|
11
|
-
* `renderVerdict`, `verifySignatureOnly`, `
|
|
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` (
|
|
12
|
-
*
|
|
11
|
+
* • Contract types — re-exported from `@certrev/cert-contract` (the binding point in
|
|
12
|
+
* ./contract/kernel).
|
|
13
13
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
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';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
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` (
|
|
12
|
-
*
|
|
11
|
+
* • Contract types — re-exported from `@certrev/cert-contract` (the binding point in
|
|
12
|
+
* ./contract/kernel).
|
|
13
13
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
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
|
|
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;
|
|
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
|
-
/**
|
|
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
|
|
49
|
-
//
|
|
50
|
-
|
|
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":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAkCrC,iFAAiF;AACjF,MAAM,kBAAkB,GAAG,IAAI,QAAQ,CAAc,EAAE,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC,CAAA;AAE7F,SAAS,QAAQ,CAChB,MAE2D;IAE3D,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,CAAA;AACxC,CAAC;AAED,SAAS,aAAa,CAAC,KAAuD;IAC7E,IAAI,KAAK,IAAI,IAAI;QAAE,OAAO,IAAI,CAAA;IAC9B,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAA;IAC3C,IAAI,CAAC;QACJ,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAyB,CAAA;IACjD,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,IAAI,CAAA;IACZ,CAAC;AACF,CAAC;AAED,SAAS,cAAc,CAAC,CAAoD;IAC3E,MAAM,IAAI,GAAG,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;IAC1C,OAAO,GAAG,IAAI,yBAAyB,kBAAkB,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,kBAAkB,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE,CAAA;AAC5G,CAAC;AAED,kEAAkE;
|
|
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;
|
|
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
|
|
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;
|
|
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,78 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
2
|
+
"name": "@certrev/cert-block",
|
|
3
|
+
"version": "0.1.2",
|
|
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
|
+
"./builder": {
|
|
14
|
+
"types": "./dist/builder/index.d.ts",
|
|
15
|
+
"default": "./dist/builder/index.js"
|
|
16
|
+
},
|
|
17
|
+
"./webcomponent": {
|
|
18
|
+
"types": "./dist/webcomponent/certrev-badge.d.ts",
|
|
19
|
+
"default": "./dist/webcomponent/certrev-badge.js"
|
|
20
|
+
},
|
|
21
|
+
"./fixtures": {
|
|
22
|
+
"types": "./dist/contract/fixtures.d.ts",
|
|
23
|
+
"default": "./dist/contract/fixtures.js"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"files": [
|
|
27
|
+
"dist",
|
|
28
|
+
"src",
|
|
29
|
+
"README.md"
|
|
30
|
+
],
|
|
31
|
+
"publishConfig": {
|
|
32
|
+
"registry": "https://registry.npmjs.org",
|
|
33
|
+
"access": "public"
|
|
34
|
+
},
|
|
35
|
+
"publishTargets": [
|
|
36
|
+
"npmjs"
|
|
37
|
+
],
|
|
38
|
+
"scripts": {
|
|
39
|
+
"build": "tsc",
|
|
40
|
+
"typecheck": "tsc --noEmit",
|
|
41
|
+
"test": "vitest run"
|
|
42
|
+
},
|
|
43
|
+
"peerDependencies": {
|
|
44
|
+
"@certrev/cert-contract": ">=0.1.2",
|
|
45
|
+
"react": ">=18.0.0"
|
|
46
|
+
},
|
|
47
|
+
"peerDependenciesMeta": {
|
|
48
|
+
"react": {
|
|
49
|
+
"optional": false
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
"devDependencies": {
|
|
53
|
+
"@certrev/cert-contract": "workspace:*",
|
|
54
|
+
"@testing-library/react": "^16.1.0",
|
|
55
|
+
"@types/node": "^20.0.0",
|
|
56
|
+
"@types/react": "^18.3.0",
|
|
57
|
+
"@types/react-dom": "^18.3.0",
|
|
58
|
+
"jsdom": "^25.0.0",
|
|
59
|
+
"react": "^18.3.1",
|
|
60
|
+
"react-dom": "^18.3.1",
|
|
61
|
+
"typescript": "^6.0.3",
|
|
62
|
+
"vitest": "^4.1.5"
|
|
63
|
+
},
|
|
64
|
+
"keywords": [
|
|
65
|
+
"certrev",
|
|
66
|
+
"certification",
|
|
67
|
+
"react",
|
|
68
|
+
"server-components",
|
|
69
|
+
"hydrogen",
|
|
70
|
+
"shopify",
|
|
71
|
+
"json-ld",
|
|
72
|
+
"schema-org",
|
|
73
|
+
"web-component",
|
|
74
|
+
"ed25519",
|
|
75
|
+
"ssr"
|
|
76
|
+
],
|
|
77
|
+
"license": "MIT"
|
|
78
|
+
}
|