@certrev/cert-block 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +154 -0
- package/dist/components/CertBadge.d.ts +29 -0
- package/dist/components/CertBadge.d.ts.map +1 -0
- package/dist/components/CertBadge.js +36 -0
- package/dist/components/CertBadge.js.map +1 -0
- package/dist/components/CertJsonLd.d.ts +23 -0
- package/dist/components/CertJsonLd.d.ts.map +1 -0
- package/dist/components/CertJsonLd.js +10 -0
- package/dist/components/CertJsonLd.js.map +1 -0
- package/dist/components/CertRevBacklink.d.ts +18 -0
- package/dist/components/CertRevBacklink.d.ts.map +1 -0
- package/dist/components/CertRevBacklink.js +16 -0
- package/dist/components/CertRevBacklink.js.map +1 -0
- package/dist/components/CertReview.d.ts +23 -0
- package/dist/components/CertReview.d.ts.map +1 -0
- package/dist/components/CertReview.js +11 -0
- package/dist/components/CertReview.js.map +1 -0
- package/dist/components/ExpertBio.d.ts +17 -0
- package/dist/components/ExpertBio.d.ts.map +1 -0
- package/dist/components/ExpertBio.js +17 -0
- package/dist/components/ExpertBio.js.map +1 -0
- package/dist/components/escape.d.ts +36 -0
- package/dist/components/escape.d.ts.map +1 -0
- package/dist/components/escape.js +76 -0
- package/dist/components/escape.js.map +1 -0
- package/dist/components/format.d.ts +22 -0
- package/dist/components/format.d.ts.map +1 -0
- package/dist/components/format.js +42 -0
- package/dist/components/format.js.map +1 -0
- package/dist/contract/fixtures.d.ts +36 -0
- package/dist/contract/fixtures.d.ts.map +1 -0
- package/dist/contract/fixtures.js +87 -0
- package/dist/contract/fixtures.js.map +1 -0
- package/dist/contract/kernel-contract.d.ts +154 -0
- package/dist/contract/kernel-contract.d.ts.map +1 -0
- package/dist/contract/kernel-contract.js +35 -0
- package/dist/contract/kernel-contract.js.map +1 -0
- package/dist/contract/kernel-stub.d.ts +44 -0
- package/dist/contract/kernel-stub.d.ts.map +1 -0
- package/dist/contract/kernel-stub.js +163 -0
- package/dist/contract/kernel-stub.js.map +1 -0
- package/dist/contract/kernel.d.ts +20 -0
- package/dist/contract/kernel.d.ts.map +1 -0
- package/dist/contract/kernel.js +19 -0
- package/dist/contract/kernel.js.map +1 -0
- package/dist/contract/verdict-kernel.d.ts +34 -0
- package/dist/contract/verdict-kernel.d.ts.map +1 -0
- package/dist/contract/verdict-kernel.js +13 -0
- package/dist/contract/verdict-kernel.js.map +1 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +38 -0
- package/dist/index.js.map +1 -0
- package/dist/jsonld/project.d.ts +71 -0
- package/dist/jsonld/project.d.ts.map +1 -0
- package/dist/jsonld/project.js +183 -0
- package/dist/jsonld/project.js.map +1 -0
- package/dist/verify/cache.d.ts +56 -0
- package/dist/verify/cache.d.ts.map +1 -0
- package/dist/verify/cache.js +93 -0
- package/dist/verify/cache.js.map +1 -0
- package/dist/verify/get-verified-envelope.d.ts +65 -0
- package/dist/verify/get-verified-envelope.d.ts.map +1 -0
- package/dist/verify/get-verified-envelope.js +104 -0
- package/dist/verify/get-verified-envelope.js.map +1 -0
- package/dist/verify/resolve-kid.d.ts +38 -0
- package/dist/verify/resolve-kid.d.ts.map +1 -0
- package/dist/verify/resolve-kid.js +71 -0
- package/dist/verify/resolve-kid.js.map +1 -0
- package/dist/webcomponent/certrev-badge.d.ts +38 -0
- package/dist/webcomponent/certrev-badge.d.ts.map +1 -0
- package/dist/webcomponent/certrev-badge.js +98 -0
- package/dist/webcomponent/certrev-badge.js.map +1 -0
- package/dist/webcomponent/render-badge-html.d.ts +25 -0
- package/dist/webcomponent/render-badge-html.d.ts.map +1 -0
- package/dist/webcomponent/render-badge-html.js +81 -0
- package/dist/webcomponent/render-badge-html.js.map +1 -0
- package/package.json +70 -0
- package/src/__tests__/components.test.tsx +191 -0
- package/src/__tests__/project.test.ts +128 -0
- package/src/__tests__/verify.test.ts +203 -0
- package/src/__tests__/webcomponent.test.tsx +106 -0
- package/src/components/CertBadge.tsx +164 -0
- package/src/components/CertJsonLd.tsx +36 -0
- package/src/components/CertRevBacklink.tsx +63 -0
- package/src/components/CertReview.tsx +42 -0
- package/src/components/ExpertBio.tsx +77 -0
- package/src/components/escape.ts +72 -0
- package/src/components/format.ts +55 -0
- package/src/contract/fixtures.ts +107 -0
- package/src/contract/kernel.ts +20 -0
- package/src/contract/verdict-kernel.ts +47 -0
- package/src/index.ts +85 -0
- package/src/jsonld/project.ts +206 -0
- package/src/verify/cache.ts +116 -0
- package/src/verify/get-verified-envelope.ts +156 -0
- package/src/verify/resolve-kid.ts +103 -0
- package/src/webcomponent/certrev-badge.ts +100 -0
- package/src/webcomponent/render-badge-html.ts +106 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Presentation helpers shared by the React components + Web Component. Pure, no DOM,
|
|
3
|
+
* no React — so the same formatting drives JSX and the hand-built Web Component string.
|
|
4
|
+
*/
|
|
5
|
+
/** Default accent if the brand didn't pin one (CertREV teal). */
|
|
6
|
+
export const DEFAULT_ACCENT = '#0f766e';
|
|
7
|
+
/** Resolve the optional display config to concrete presentation flags + accent. */
|
|
8
|
+
export function resolveDisplay(display, accentOverride) {
|
|
9
|
+
return {
|
|
10
|
+
accentColor: accentOverride ?? display?.accentColor ?? DEFAULT_ACCENT,
|
|
11
|
+
showExpertPhoto: display?.showExpertPhoto ?? true,
|
|
12
|
+
showAuthor: display?.showAuthor ?? true,
|
|
13
|
+
showMemo: display?.showMemo ?? true,
|
|
14
|
+
badgeStyle: display?.badgeStyle ?? 'full',
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Format an ISO-8601 instant to a stable, locale-independent date label ("Jun 21, 2026").
|
|
19
|
+
* We deliberately DON'T use `toLocaleDateString` — its output varies by runtime ICU data,
|
|
20
|
+
* which would make SSR output non-deterministic + cause hydration mismatches. Fixed
|
|
21
|
+
* English month abbreviations keep server + client byte-identical.
|
|
22
|
+
*/
|
|
23
|
+
const MONTHS = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
|
|
24
|
+
export function formatDate(iso) {
|
|
25
|
+
if (!iso)
|
|
26
|
+
return null;
|
|
27
|
+
const ms = Date.parse(iso);
|
|
28
|
+
if (Number.isNaN(ms))
|
|
29
|
+
return null;
|
|
30
|
+
const d = new Date(ms);
|
|
31
|
+
return `${MONTHS[d.getUTCMonth()]} ${d.getUTCDate()}, ${d.getUTCFullYear()}`;
|
|
32
|
+
}
|
|
33
|
+
/** "PhD, RD" — the expert's credential abbreviations, comma-joined. */
|
|
34
|
+
export function credentialSuffix(content) {
|
|
35
|
+
return content.expert.credentials.map((c) => c.abbreviation).join(', ');
|
|
36
|
+
}
|
|
37
|
+
/** "Dr. Jane Doe, PhD, RD" — display name with credential suffix appended. */
|
|
38
|
+
export function expertNameWithCredentials(content) {
|
|
39
|
+
const suffix = credentialSuffix(content);
|
|
40
|
+
return suffix ? `${content.expert.displayName}, ${suffix}` : content.expert.displayName;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=format.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/components/format.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,iEAAiE;AACjE,MAAM,CAAC,MAAM,cAAc,GAAG,SAAS,CAAA;AAUvC,mFAAmF;AACnF,MAAM,UAAU,cAAc,CAAC,OAAsC,EAAE,cAAuB;IAC7F,OAAO;QACN,WAAW,EAAE,cAAc,IAAI,OAAO,EAAE,WAAW,IAAI,cAAc;QACrE,eAAe,EAAE,OAAO,EAAE,eAAe,IAAI,IAAI;QACjD,UAAU,EAAE,OAAO,EAAE,UAAU,IAAI,IAAI;QACvC,QAAQ,EAAE,OAAO,EAAE,QAAQ,IAAI,IAAI;QACnC,UAAU,EAAE,OAAO,EAAE,UAAU,IAAI,MAAM;KACzC,CAAA;AACF,CAAC;AAED;;;;;GAKG;AACH,MAAM,MAAM,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,CAAA;AAEnG,MAAM,UAAU,UAAU,CAAC,GAA8B;IACxD,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAA;IACrB,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAC1B,IAAI,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;QAAE,OAAO,IAAI,CAAA;IACjC,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,EAAE,CAAC,CAAA;IACtB,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC,cAAc,EAAE,EAAE,CAAA;AAC7E,CAAC;AAED,uEAAuE;AACvE,MAAM,UAAU,gBAAgB,CAAC,OAAoB;IACpD,OAAO,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACxE,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,yBAAyB,CAAC,OAAoB;IAC7D,MAAM,MAAM,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAA;IACxC,OAAO,MAAM,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,WAAW,KAAK,MAAM,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,WAAW,CAAA;AACxF,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mock facts + a SIGNED envelope fixture for unit tests + local dev.
|
|
3
|
+
*
|
|
4
|
+
* `makeMockPayload` returns a complete, well-formed `CertPayload` (override any field).
|
|
5
|
+
* `makeSignedEnvelope` generates an ephemeral Ed25519 keypair, signs the payload's RFC-
|
|
6
|
+
* 8785 canonical bytes, and returns `{ envelope, resolveKid, publicKey }` so a test can
|
|
7
|
+
* run the FULL kernel pipeline (real signature verification) against the fixture — no
|
|
8
|
+
* mocking of the crypto.
|
|
9
|
+
*
|
|
10
|
+
* These helpers depend on Node's `crypto` (for keygen + signing on the ISSUER side, which
|
|
11
|
+
* tests stand in for). The SDK's RUNTIME never signs — it only verifies — so this stays
|
|
12
|
+
* test/dev-only and is not part of the public render API.
|
|
13
|
+
*
|
|
14
|
+
* The fixture signs over `canonicalPayloadBytes` from `@certrev/cert-contract` (RFC 8785),
|
|
15
|
+
* the SAME bytes the real kernel recomputes on verify — so a fixture envelope verifies
|
|
16
|
+
* end-to-end under the production `verifyEnvelope`, not a stand-in canonicalizer.
|
|
17
|
+
*/
|
|
18
|
+
import { type KeyObject } from 'node:crypto';
|
|
19
|
+
import { type CertDeliveryEnvelope, type CertPayload, type ResolvePublicKeyByKid } from '@certrev/cert-contract';
|
|
20
|
+
declare const FIXTURE_KID = "certrev-fixture-key-1";
|
|
21
|
+
/** Build a complete mock payload. Pass overrides to exercise specific render branches. */
|
|
22
|
+
export declare function makeMockPayload(overrides?: Partial<CertPayload>): CertPayload;
|
|
23
|
+
export interface SignedEnvelopeFixture {
|
|
24
|
+
readonly envelope: CertDeliveryEnvelope;
|
|
25
|
+
readonly resolveKid: ResolvePublicKeyByKid;
|
|
26
|
+
readonly publicKey: KeyObject;
|
|
27
|
+
readonly kid: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Generate a fresh keypair, sign the payload, and return everything a test needs to run
|
|
31
|
+
* the kernel against a genuinely-valid envelope. The returned `resolveKid` resolves only
|
|
32
|
+
* the fixture kid (any other kid → null → 'unknown_key').
|
|
33
|
+
*/
|
|
34
|
+
export declare function makeSignedEnvelope(overrides?: Partial<CertPayload>, kid?: string): SignedEnvelopeFixture;
|
|
35
|
+
export { FIXTURE_KID };
|
|
36
|
+
//# sourceMappingURL=fixtures.d.ts.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mock facts + a SIGNED envelope fixture for unit tests + local dev.
|
|
3
|
+
*
|
|
4
|
+
* `makeMockPayload` returns a complete, well-formed `CertPayload` (override any field).
|
|
5
|
+
* `makeSignedEnvelope` generates an ephemeral Ed25519 keypair, signs the payload's RFC-
|
|
6
|
+
* 8785 canonical bytes, and returns `{ envelope, resolveKid, publicKey }` so a test can
|
|
7
|
+
* run the FULL kernel pipeline (real signature verification) against the fixture — no
|
|
8
|
+
* mocking of the crypto.
|
|
9
|
+
*
|
|
10
|
+
* These helpers depend on Node's `crypto` (for keygen + signing on the ISSUER side, which
|
|
11
|
+
* tests stand in for). The SDK's RUNTIME never signs — it only verifies — so this stays
|
|
12
|
+
* test/dev-only and is not part of the public render API.
|
|
13
|
+
*
|
|
14
|
+
* The fixture signs over `canonicalPayloadBytes` from `@certrev/cert-contract` (RFC 8785),
|
|
15
|
+
* the SAME bytes the real kernel recomputes on verify — so a fixture envelope verifies
|
|
16
|
+
* end-to-end under the production `verifyEnvelope`, not a stand-in canonicalizer.
|
|
17
|
+
*/
|
|
18
|
+
import { generateKeyPairSync, sign as nodeSign } from 'node:crypto';
|
|
19
|
+
import { canonicalPayloadBytes, } from '@certrev/cert-contract';
|
|
20
|
+
const FIXTURE_KID = 'certrev-fixture-key-1';
|
|
21
|
+
/** Build a complete mock payload. Pass overrides to exercise specific render branches. */
|
|
22
|
+
export function makeMockPayload(overrides = {}) {
|
|
23
|
+
const base = {
|
|
24
|
+
contractVersion: 1,
|
|
25
|
+
certId: 'cert_fixture_001',
|
|
26
|
+
subject: {
|
|
27
|
+
platform: 'shopify',
|
|
28
|
+
externalId: 'gid://shopify/Article/123456789',
|
|
29
|
+
logicalArticleId: 'art_logical_abc',
|
|
30
|
+
canonicalUrls: ['https://brand.example.com/blogs/skincare/retinol-guide'],
|
|
31
|
+
installationId: 'inst_shopify_42',
|
|
32
|
+
contentDigest: 'a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2',
|
|
33
|
+
},
|
|
34
|
+
content: {
|
|
35
|
+
expert: {
|
|
36
|
+
displayName: 'Dr. Jane Doe',
|
|
37
|
+
credentials: [
|
|
38
|
+
{ abbreviation: 'MD', fullName: 'Doctor of Medicine' },
|
|
39
|
+
{ abbreviation: 'FAAD', fullName: 'Fellow of the American Academy of Dermatology' },
|
|
40
|
+
],
|
|
41
|
+
profileUrl: 'https://certrev.com/experts/jane-doe',
|
|
42
|
+
photoUrl: 'https://cdn.certrev.com/experts/jane-doe.jpg',
|
|
43
|
+
},
|
|
44
|
+
author: { name: 'Sam Writer', title: 'Senior Content Editor' },
|
|
45
|
+
memo: 'I reviewed the retinol claims against current dermatology guidance; the concentrations and usage cadence cited are accurate and safely framed.',
|
|
46
|
+
certifiedAt: '2026-06-21T15:30:00.000Z',
|
|
47
|
+
contentModifiedAt: '2026-06-20T09:00:00.000Z',
|
|
48
|
+
verifyUrl: 'https://certrev.com/verify/cert_fixture_001',
|
|
49
|
+
display: {
|
|
50
|
+
accentColor: '#7c3aed',
|
|
51
|
+
showExpertPhoto: true,
|
|
52
|
+
showAuthor: true,
|
|
53
|
+
showMemo: true,
|
|
54
|
+
badgeStyle: 'full',
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
lifecycle: {
|
|
58
|
+
issuedAt: '2026-06-21T15:30:00.000Z',
|
|
59
|
+
expiresAt: '2099-01-01T00:00:00.000Z',
|
|
60
|
+
revokedAt: null,
|
|
61
|
+
revision: 1,
|
|
62
|
+
},
|
|
63
|
+
...overrides,
|
|
64
|
+
};
|
|
65
|
+
return base;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Generate a fresh keypair, sign the payload, and return everything a test needs to run
|
|
69
|
+
* the kernel against a genuinely-valid envelope. The returned `resolveKid` resolves only
|
|
70
|
+
* the fixture kid (any other kid → null → 'unknown_key').
|
|
71
|
+
*/
|
|
72
|
+
export function makeSignedEnvelope(overrides = {}, kid = FIXTURE_KID) {
|
|
73
|
+
const { publicKey, privateKey } = generateKeyPairSync('ed25519');
|
|
74
|
+
const payload = makeMockPayload(overrides);
|
|
75
|
+
const bytes = canonicalPayloadBytes(payload);
|
|
76
|
+
const sig = nodeSign(null, bytes, privateKey).toString('base64url');
|
|
77
|
+
const envelope = {
|
|
78
|
+
payload,
|
|
79
|
+
signature: { alg: 'ed25519', kid, sig, signedAt: payload.lifecycle.issuedAt },
|
|
80
|
+
};
|
|
81
|
+
const spkiBase64 = publicKey.export({ format: 'der', type: 'spki' }).toString('base64');
|
|
82
|
+
const keyInput = { format: 'spki-base64', base64: spkiBase64 };
|
|
83
|
+
const resolveKid = (k) => (k === kid ? keyInput : null);
|
|
84
|
+
return { envelope, resolveKid, publicKey, kid };
|
|
85
|
+
}
|
|
86
|
+
export { FIXTURE_KID };
|
|
87
|
+
//# sourceMappingURL=fixtures.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fixtures.js","sourceRoot":"","sources":["../../src/contract/fixtures.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,154 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kernel-contract.d.ts","sourceRoot":"","sources":["../../src/contract/kernel-contract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,yEAAyE;AACzE,eAAO,MAAM,gBAAgB,EAAG,CAAU,CAAA;AAC1C,MAAM,MAAM,eAAe,GAAG,OAAO,gBAAgB,CAAA;AAErD,gFAAgF;AAChF,eAAO,MAAM,gBAAgB,EAAG,aAAsB,CAAA;AAEtD,2BAA2B;AAC3B,eAAO,MAAM,aAAa,EAAG,SAAkB,CAAA;AAC/C,MAAM,MAAM,YAAY,GAAG,OAAO,aAAa,CAAA;AAG/C,MAAM,WAAW,WAAW;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAA;IACjC,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;IAC7C,QAAQ,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;IACtC,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;CACrC;AAGD,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACpC,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAA;IAClC,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAA;IAC7B,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAC3B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CACxC;AAGD,MAAM,WAAW,cAAc;IAC9B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CACzB;AAED,MAAM,WAAW,WAAW;IAC3B,QAAQ,CAAC,MAAM,EAAE;QAChB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;QAC5B,QAAQ,CAAC,WAAW,EAAE,aAAa,CAAC,cAAc,CAAC,CAAA;QACnD,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;QAClC,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;KAChC,CAAA;IACD,QAAQ,CAAC,MAAM,EAAE;QAChB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;QACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;KAC7B,CAAA;IACD,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAA;IACzC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,OAAO,EAAE,iBAAiB,CAAA;CACnC;AAGD,MAAM,WAAW,aAAa;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACjC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CACzB;AAGD,MAAM,WAAW,WAAW;IAC3B,QAAQ,CAAC,eAAe,EAAE,eAAe,CAAA;IACzC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAA;IAC7B,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAA;IAC7B,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAA;CACjC;AAGD,MAAM,WAAW,aAAa;IAC7B,QAAQ,CAAC,GAAG,EAAE,YAAY,CAAA;IAC1B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CACzB;AAGD,MAAM,WAAW,oBAAoB;IACpC,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAA;IAC7B,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAA;CACjC;AAGD,MAAM,MAAM,WAAW,GACpB;IAAE,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAA;CAAE,GAC9D;IAAE,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,kBAAkB,CAAA;CAAE,CAAA;AAEzE,MAAM,MAAM,kBAAkB,GAC3B,8BAA8B,GAC9B,iBAAiB,GACjB,aAAa,GACb,mBAAmB,GACnB,mBAAmB,GACnB,kBAAkB,GAClB,SAAS,GACT,SAAS,GACT,eAAe,CAAA;AAIlB,2EAA2E;AAC3E,MAAM,MAAM,qBAAqB,GAC9B;IAAE,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAA;CAAE,GAC3D;IAAE,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC3D;IAAE,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAChD;IAAE,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAA;CAAE,CAAA;AAEzD;;;;;GAKG;AACH,MAAM,MAAM,qBAAqB,GAAG,CACnC,GAAG,EAAE,MAAM,KACP,OAAO,CAAC,qBAAqB,GAAG,IAAI,GAAG,SAAS,CAAC,GAAG,qBAAqB,GAAG,IAAI,GAAG,SAAS,CAAA;AAEjG,kDAAkD;AAClD,MAAM,WAAW,aAAa;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxC,QAAQ,CAAC,GAAG,CAAC,EAAE,IAAI,CAAA;CACnB;AAED,gFAAgF;AAChF,MAAM,MAAM,cAAc,GAAG,CAC5B,QAAQ,EAAE,oBAAoB,EAC9B,UAAU,EAAE,qBAAqB,EACjC,GAAG,EAAE,aAAa,KACd,OAAO,CAAC,WAAW,CAAC,CAAA;AAEzB,4DAA4D;AAC5D,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,EAAE,aAAa,KAAK,WAAW,CAAA;AAErF,+CAA+C;AAC/C,MAAM,MAAM,mBAAmB,GAAG,CACjC,QAAQ,EAAE,oBAAoB,EAC9B,UAAU,EAAE,qBAAqB,KAC7B,OAAO,CAAC;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,kBAAkB,CAAA;CAAE,CAAC,CAAA;AAEtE;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC7B,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAA;IACvC,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAA;IACrC,QAAQ,CAAC,mBAAmB,EAAE,mBAAmB,CAAA;CACjD"}
|
|
@@ -0,0 +1,35 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
|
@@ -0,0 +1,163 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kernel-stub.js","sourceRoot":"","sources":["../../src/contract/kernel-stub.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
3
|
+
* Contract binding point — the SDK's single import of @certrev/cert-contract
|
|
4
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
5
|
+
*
|
|
6
|
+
* Every other SDK module imports the contract TYPES and the KERNEL functions from HERE,
|
|
7
|
+
* never directly from `@certrev/cert-contract`, so the whole SDK's dependency on the
|
|
8
|
+
* contract is funnelled through one module. The published package owns the envelope types
|
|
9
|
+
* (`CertDeliveryEnvelope`, `CertPayload`, `CertCredential`, …), the RFC-8785
|
|
10
|
+
* canonicalization (`canonicalPayloadBytes`), and the fail-closed kernel (`verifyEnvelope`,
|
|
11
|
+
* `renderVerdict`, `verifySignatureOnly`, `toEd25519PublicKey`).
|
|
12
|
+
*
|
|
13
|
+
* `VerdictKernel` is the ONE name NOT re-exported from the package: the contract exposes
|
|
14
|
+
* the kernel as free functions, and different edges bundle them with different key-resolver
|
|
15
|
+
* shapes (cert-block uses `Ed25519PublicKeyInput`; the portal Delivery API uses raw
|
|
16
|
+
* `Uint8Array`), so the bundled interface stays edge-local — see ./verdict-kernel.
|
|
17
|
+
*/
|
|
18
|
+
export * from '@certrev/cert-contract';
|
|
19
|
+
export type { VerdictKernel } from './verdict-kernel.js';
|
|
20
|
+
//# sourceMappingURL=kernel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kernel.d.ts","sourceRoot":"","sources":["../../src/contract/kernel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,cAAc,wBAAwB,CAAA;AACtC,YAAY,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA"}
|