@certrev/cert-block 1.2.1-canary.0 → 1.3.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/CHANGELOG.md +72 -0
- package/README.md +12 -1
- package/dist/builder/cert-review-card.d.ts.map +1 -1
- package/dist/builder/cert-review-card.js +68 -3
- package/dist/builder/cert-review-card.js.map +1 -1
- package/dist/builder/delivered-face.d.ts +74 -0
- package/dist/builder/delivered-face.d.ts.map +1 -0
- package/dist/builder/delivered-face.js +122 -0
- package/dist/builder/delivered-face.js.map +1 -0
- package/dist/builder/delivery-runtime.d.ts +1 -1
- package/dist/builder/delivery-runtime.d.ts.map +1 -1
- package/dist/builder/delivery-runtime.js +3 -1
- package/dist/builder/delivery-runtime.js.map +1 -1
- package/dist/builder/index.d.ts +4 -1
- package/dist/builder/index.d.ts.map +1 -1
- package/dist/builder/index.js +4 -1
- package/dist/builder/index.js.map +1 -1
- package/dist/builder/ssr-seed.d.ts +13 -1
- package/dist/builder/ssr-seed.d.ts.map +1 -1
- package/dist/builder/ssr-seed.js +14 -2
- package/dist/builder/ssr-seed.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/verify/get-verified-delivery.d.ts +28 -0
- package/dist/verify/get-verified-delivery.d.ts.map +1 -1
- package/dist/verify/get-verified-delivery.js +29 -3
- package/dist/verify/get-verified-delivery.js.map +1 -1
- package/package.json +112 -112
- package/src/builder/cert-review-card.tsx +96 -4
- package/src/builder/delivered-face.ts +142 -0
- package/src/builder/delivery-runtime.ts +3 -1
- package/src/builder/index.tsx +4 -1
- package/src/builder/ssr-seed.ts +25 -2
- package/src/index.ts +3 -0
- package/src/verify/get-verified-delivery.ts +45 -3
package/src/index.ts
CHANGED
|
@@ -106,6 +106,7 @@ export {
|
|
|
106
106
|
type CertCredential,
|
|
107
107
|
type CertDeliveryEnvelope,
|
|
108
108
|
type CertDisplayConfig,
|
|
109
|
+
type CertFaceDigest,
|
|
109
110
|
type CertLifecycle,
|
|
110
111
|
type CertPayload,
|
|
111
112
|
type CertSignature,
|
|
@@ -135,6 +136,7 @@ export {
|
|
|
135
136
|
export { TtlCache, type TtlCacheOptions } from './verify/cache.js'
|
|
136
137
|
export {
|
|
137
138
|
type CachedDelivery,
|
|
139
|
+
type DeliveredFace,
|
|
138
140
|
type DesignPin,
|
|
139
141
|
deliveryCacheKey,
|
|
140
142
|
deliveryUrl,
|
|
@@ -142,6 +144,7 @@ export {
|
|
|
142
144
|
type GetVerifiedDeliveryOptions,
|
|
143
145
|
getVerifiedDelivery,
|
|
144
146
|
invalidateDelivery,
|
|
147
|
+
parseDeliveredFace,
|
|
145
148
|
parseDesignPin,
|
|
146
149
|
parseRenderDef,
|
|
147
150
|
peekVerifiedDelivery,
|
|
@@ -36,6 +36,12 @@
|
|
|
36
36
|
* card paints its options face instead of nothing. A definitive answer (404/410, a key or signature that does not
|
|
37
37
|
* verify, a revoked, expired or mismatched artifact) is never `unreachable`. `readVerifiedDelivery` is the
|
|
38
38
|
* synchronous read that also serves a stale entry while refreshing it.
|
|
39
|
+
*
|
|
40
|
+
* 1.3.0: the response may also carry a server-rendered face as a second UNSIGNED sibling, `face: { html, css }`. It is
|
|
41
|
+
* read the way `renderDef` is (shape-checked, malformed is dropped, never read unless the artifact verified) and cached
|
|
42
|
+
* beside it, and `settleDelivery` hands it out only on a `render` verdict. NOTHING HERE VOUCHES FOR IT: the signature
|
|
43
|
+
* does not cover it. What binds it is the signed `payload.content.faceDigest` (cert-contract 0.6.0), and a caller
|
|
44
|
+
* paints it only after hashing it against that digest, as the Builder card does (`src/builder/delivered-face.ts`).
|
|
39
45
|
*/
|
|
40
46
|
|
|
41
47
|
import type { CertChromeRenderDef } from '../builder/cert-chrome-data.js'
|
|
@@ -52,6 +58,16 @@ import { renderVerdict, verifyArtifact } from '../contract/kernel.js'
|
|
|
52
58
|
import { TtlCache } from './cache.js'
|
|
53
59
|
import { DEFAULT_FETCH_TIMEOUT_MS, fetchWithDeadline } from './fetch-with-deadline.js'
|
|
54
60
|
|
|
61
|
+
/**
|
|
62
|
+
* 1.3.0: the server-rendered face the Delivery API may serve beside the artifact. UNSIGNED and UNVERIFIED as carried
|
|
63
|
+
* here: paint it only when sha256 of each half's UTF-8 bytes equals the signed `payload.content.faceDigest`, and the
|
|
64
|
+
* digest's `defVersion` is the def served with it.
|
|
65
|
+
*/
|
|
66
|
+
export interface DeliveredFace {
|
|
67
|
+
readonly html: string
|
|
68
|
+
readonly css: string
|
|
69
|
+
}
|
|
70
|
+
|
|
55
71
|
/**
|
|
56
72
|
* What one Delivery read settles to, as cached: a verified payload + its def (and, from 1.2.0, the signature it
|
|
57
73
|
* verified with, so a server render can hand the signed envelope to the browser), or the reason not.
|
|
@@ -63,6 +79,8 @@ export type CachedDelivery =
|
|
|
63
79
|
readonly renderDef: CertChromeRenderDef | null
|
|
64
80
|
/** Absent only in a cache filled by hand (a test, a custom cache); a read always keeps it. */
|
|
65
81
|
readonly signature?: CertSignature
|
|
82
|
+
/** 1.3.0: the unsigned face sibling, when the response carried a well-formed one; else absent. */
|
|
83
|
+
readonly face?: DeliveredFace
|
|
66
84
|
}
|
|
67
85
|
| {
|
|
68
86
|
readonly kind: 'suppressed'
|
|
@@ -80,6 +98,11 @@ export interface VerifiedDelivery {
|
|
|
80
98
|
readonly signature?: CertSignature
|
|
81
99
|
/** 1.2.0: on a suppress verdict, true when CertREV was not reached; else undefined. */
|
|
82
100
|
readonly unreachable?: true
|
|
101
|
+
/**
|
|
102
|
+
* 1.3.0: on a `render` verdict, the server-rendered face served beside the artifact, when the response carried a
|
|
103
|
+
* well-formed one; else undefined (never on a suppress verdict). UNVERIFIED: see `DeliveredFace`.
|
|
104
|
+
*/
|
|
105
|
+
readonly face?: DeliveredFace
|
|
83
106
|
}
|
|
84
107
|
|
|
85
108
|
export interface GetVerifiedDeliveryOptions {
|
|
@@ -230,6 +253,18 @@ export function parseRenderDef(value: unknown): CertChromeRenderDef | null {
|
|
|
230
253
|
}
|
|
231
254
|
}
|
|
232
255
|
|
|
256
|
+
/**
|
|
257
|
+
* 1.3.0: the face sibling, shape-checked: an object whose `html` and `css` are both strings, copied to exactly those
|
|
258
|
+
* two keys. Anything else is null, and the card paints exactly what it paints with no face. The markup is NOT judged
|
|
259
|
+
* here; the signed digest judges it at paint time.
|
|
260
|
+
*/
|
|
261
|
+
export function parseDeliveredFace(value: unknown): DeliveredFace | null {
|
|
262
|
+
if (!isRecord(value)) return null
|
|
263
|
+
const { html, css } = value
|
|
264
|
+
if (!isString(html) || !isString(css)) return null
|
|
265
|
+
return { html, css }
|
|
266
|
+
}
|
|
267
|
+
|
|
233
268
|
/** Fetch, parse and cryptographically verify one Delivery response. Never throws. */
|
|
234
269
|
async function loadDelivery(opts: GetVerifiedDeliveryOptions): Promise<CachedDelivery> {
|
|
235
270
|
const fetchImpl = opts.fetchImpl ?? globalThis.fetch
|
|
@@ -259,8 +294,8 @@ async function loadDelivery(opts: GetVerifiedDeliveryOptions): Promise<CachedDel
|
|
|
259
294
|
let verdict: CertVerdict
|
|
260
295
|
try {
|
|
261
296
|
// `verifyArtifact`, so a tombstone verifies as itself and reports 'revoked'. The kernel reads
|
|
262
|
-
// `payload` + `signature` (or the tombstone's own fields); the `renderDef`
|
|
263
|
-
// part of what is verified, and
|
|
297
|
+
// `payload` + `signature` (or the tombstone's own fields); the `renderDef` and (1.3.0) `face`
|
|
298
|
+
// siblings are not part of what is verified, and are never read unless the artifact verified.
|
|
264
299
|
verdict = await verifyArtifact(body as unknown as CertDeliveryArtifact, opts.resolveKid, { ...opts.context })
|
|
265
300
|
} catch {
|
|
266
301
|
return suppressed('unknown_key')
|
|
@@ -268,11 +303,13 @@ async function loadDelivery(opts: GetVerifiedDeliveryOptions): Promise<CachedDel
|
|
|
268
303
|
if (verdict.decision !== 'render') return suppressed(verdict.reason)
|
|
269
304
|
// A `render` verdict came from an envelope (a tombstone never renders), so `signature` is the one just verified.
|
|
270
305
|
const signature = isRecord(body.signature) ? (body.signature as unknown as CertSignature) : undefined
|
|
306
|
+
const face = parseDeliveredFace(body.face)
|
|
271
307
|
return {
|
|
272
308
|
kind: 'verified',
|
|
273
309
|
payload: verdict.payload,
|
|
274
310
|
renderDef: parseRenderDef(body.renderDef),
|
|
275
311
|
...(signature ? { signature } : {}),
|
|
312
|
+
...(face ? { face } : {}),
|
|
276
313
|
}
|
|
277
314
|
}
|
|
278
315
|
|
|
@@ -287,7 +324,12 @@ export function settleDelivery(cached: CachedDelivery, context: RenderContext):
|
|
|
287
324
|
}
|
|
288
325
|
const verdict = renderVerdict(cached.payload, context)
|
|
289
326
|
if (verdict.decision !== 'render') return { verdict, renderDef: null }
|
|
290
|
-
return {
|
|
327
|
+
return {
|
|
328
|
+
verdict,
|
|
329
|
+
renderDef: cached.renderDef,
|
|
330
|
+
...(cached.signature ? { signature: cached.signature } : {}),
|
|
331
|
+
...(cached.face ? { face: cached.face } : {}),
|
|
332
|
+
}
|
|
291
333
|
}
|
|
292
334
|
|
|
293
335
|
/**
|