@certrev/cert-block 0.5.5 → 1.0.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 +164 -26
- package/LICENSE +21 -0
- package/README.md +415 -54
- package/dist/builder/cert-chrome-data.d.ts +26 -8
- package/dist/builder/cert-chrome-data.d.ts.map +1 -1
- package/dist/builder/cert-chrome-data.js +5 -5
- package/dist/builder/cert-chrome-data.js.map +1 -1
- package/dist/builder/cert-review-card.d.ts +35 -5
- package/dist/builder/cert-review-card.d.ts.map +1 -1
- package/dist/builder/cert-review-card.js +115 -34
- package/dist/builder/cert-review-card.js.map +1 -1
- package/dist/builder/index.d.ts +33 -16
- package/dist/builder/index.d.ts.map +1 -1
- package/dist/builder/index.js +33 -16
- package/dist/builder/index.js.map +1 -1
- package/dist/components/CertBadge.d.ts +2 -2
- package/dist/components/CertBadge.d.ts.map +1 -1
- package/dist/components/CertBadge.js +11 -5
- package/dist/components/CertBadge.js.map +1 -1
- package/dist/components/CertJsonLd.d.ts.map +1 -1
- package/dist/components/CertJsonLd.js.map +1 -1
- package/dist/components/CertRevBacklink.d.ts.map +1 -1
- package/dist/components/CertRevBacklink.js +3 -2
- package/dist/components/CertRevBacklink.js.map +1 -1
- package/dist/components/CertReview.d.ts +1 -1
- package/dist/components/ExpertBio.d.ts.map +1 -1
- package/dist/components/ExpertBio.js +12 -4
- package/dist/components/ExpertBio.js.map +1 -1
- package/dist/components/escape.d.ts +28 -1
- package/dist/components/escape.d.ts.map +1 -1
- package/dist/components/escape.js +37 -8
- package/dist/components/escape.js.map +1 -1
- package/dist/components/format.d.ts +51 -2
- package/dist/components/format.d.ts.map +1 -1
- package/dist/components/format.js +103 -6
- package/dist/components/format.js.map +1 -1
- package/dist/components/preview-block.d.ts +1 -1
- package/dist/components/preview-block.js +3 -3
- package/dist/components/preview-block.js.map +1 -1
- package/dist/components/rel.d.ts +24 -0
- package/dist/components/rel.d.ts.map +1 -0
- package/dist/components/rel.js +24 -0
- package/dist/components/rel.js.map +1 -0
- package/dist/components/render-cert-block.d.ts +50 -22
- package/dist/components/render-cert-block.d.ts.map +1 -1
- package/dist/components/render-cert-block.js +146 -80
- package/dist/components/render-cert-block.js.map +1 -1
- package/dist/components/render-def.d.ts +13 -14
- package/dist/components/render-def.d.ts.map +1 -1
- package/dist/components/render-def.js +14 -15
- package/dist/components/render-def.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/jsonld/project.d.ts +46 -13
- package/dist/jsonld/project.d.ts.map +1 -1
- package/dist/jsonld/project.js +139 -56
- package/dist/jsonld/project.js.map +1 -1
- package/dist/modal/avatar-resize.d.ts +10 -10
- package/dist/modal/avatar-resize.js +14 -14
- package/dist/modal/avatar-resize.js.map +1 -1
- package/dist/modal/cert-modal-view.d.ts +27 -7
- package/dist/modal/cert-modal-view.d.ts.map +1 -1
- package/dist/modal/cert-modal-view.js +49 -25
- package/dist/modal/cert-modal-view.js.map +1 -1
- package/dist/modal/certrev-cert-modal.d.ts +5 -5
- package/dist/modal/certrev-cert-modal.js +9 -9
- package/dist/modal/certrev-cert-modal.js.map +1 -1
- package/dist/modal/certrev-cert-modal.styles.d.ts +6 -6
- package/dist/modal/certrev-cert-modal.styles.d.ts.map +1 -1
- package/dist/modal/certrev-cert-modal.styles.js +8 -8
- package/dist/modal/certrev-cert-modal.styles.js.map +1 -1
- package/dist/modal/certrev-cert.entry.d.ts +8 -6
- package/dist/modal/certrev-cert.entry.d.ts.map +1 -1
- package/dist/modal/certrev-cert.entry.js +9 -7
- package/dist/modal/certrev-cert.entry.js.map +1 -1
- package/dist/modal/certrev-cert.js +6 -6
- package/dist/modal/display-strings.d.ts +25 -5
- package/dist/modal/display-strings.d.ts.map +1 -1
- package/dist/modal/display-strings.js +27 -5
- package/dist/modal/display-strings.js.map +1 -1
- package/dist/modal/escape.d.ts +26 -3
- package/dist/modal/escape.d.ts.map +1 -1
- package/dist/modal/escape.js +32 -3
- package/dist/modal/escape.js.map +1 -1
- package/dist/modal/font-face.d.ts.map +1 -1
- package/dist/modal/font-face.js +8 -11
- package/dist/modal/font-face.js.map +1 -1
- package/dist/modal/ftc-disclosure.d.ts +2 -2
- package/dist/modal/ftc-disclosure.js +2 -2
- package/dist/modal/ftc-guard.d.ts +44 -9
- package/dist/modal/ftc-guard.d.ts.map +1 -1
- package/dist/modal/ftc-guard.js +50 -17
- package/dist/modal/ftc-guard.js.map +1 -1
- package/dist/modal/index.d.ts +1 -1
- package/dist/modal/index.js +1 -1
- package/dist/modal/interactions.d.ts +2 -2
- package/dist/modal/interactions.js +2 -2
- package/dist/modal/logo-paths.js +2 -2
- package/dist/modal/logo-paths.js.map +1 -1
- package/dist/modal/placement.d.ts +4 -3
- package/dist/modal/placement.d.ts.map +1 -1
- package/dist/modal/placement.js +7 -6
- package/dist/modal/placement.js.map +1 -1
- package/dist/modal/revalidate.d.ts +2 -3
- package/dist/modal/revalidate.d.ts.map +1 -1
- package/dist/modal/revalidate.js +2 -3
- package/dist/modal/revalidate.js.map +1 -1
- package/dist/modal/verify-client.d.ts +2 -2
- package/dist/modal/verify-client.js +2 -2
- package/dist/verify/cache.d.ts +21 -6
- package/dist/verify/cache.d.ts.map +1 -1
- package/dist/verify/cache.js +29 -8
- package/dist/verify/cache.js.map +1 -1
- package/dist/verify/fetch-with-deadline.d.ts +35 -0
- package/dist/verify/fetch-with-deadline.d.ts.map +1 -0
- package/dist/verify/fetch-with-deadline.js +55 -0
- package/dist/verify/fetch-with-deadline.js.map +1 -0
- package/dist/verify/get-verified-envelope.d.ts +23 -9
- package/dist/verify/get-verified-envelope.d.ts.map +1 -1
- package/dist/verify/get-verified-envelope.js +89 -40
- package/dist/verify/get-verified-envelope.js.map +1 -1
- package/dist/verify/resolve-kid.d.ts +3 -0
- package/dist/verify/resolve-kid.d.ts.map +1 -1
- package/dist/verify/resolve-kid.js +17 -8
- package/dist/verify/resolve-kid.js.map +1 -1
- package/dist/webcomponent/certrev-badge.d.ts.map +1 -1
- package/dist/webcomponent/certrev-badge.js +24 -2
- package/dist/webcomponent/certrev-badge.js.map +1 -1
- package/dist/webcomponent/render-badge-html.d.ts +1 -1
- package/dist/webcomponent/render-badge-html.d.ts.map +1 -1
- package/dist/webcomponent/render-badge-html.js +36 -17
- package/dist/webcomponent/render-badge-html.js.map +1 -1
- package/package.json +5 -2
- package/src/builder/cert-chrome-data.ts +26 -8
- package/src/builder/cert-review-card.tsx +147 -38
- package/src/builder/index.tsx +34 -17
- package/src/components/CertBadge.tsx +14 -9
- package/src/components/CertJsonLd.tsx +1 -1
- package/src/components/CertRevBacklink.tsx +10 -3
- package/src/components/CertReview.tsx +1 -1
- package/src/components/ExpertBio.tsx +12 -7
- package/src/components/escape.ts +37 -7
- package/src/components/format.ts +102 -6
- package/src/components/preview-block.ts +3 -3
- package/src/components/rel.ts +23 -0
- package/src/components/render-cert-block.ts +192 -109
- package/src/components/render-def.ts +14 -15
- package/src/index.ts +4 -2
- package/src/jsonld/project.ts +155 -59
- package/src/modal/avatar-resize.ts +14 -14
- package/src/modal/cert-modal-view.ts +52 -27
- package/src/modal/certrev-cert-modal.styles.ts +8 -8
- package/src/modal/certrev-cert-modal.ts +9 -9
- package/src/modal/certrev-cert.entry.ts +9 -7
- package/src/modal/display-strings.ts +26 -5
- package/src/modal/escape.ts +32 -4
- package/src/modal/font-face.ts +8 -11
- package/src/modal/ftc-disclosure.ts +2 -2
- package/src/modal/ftc-guard.ts +73 -18
- package/src/modal/index.ts +1 -1
- package/src/modal/interactions.ts +2 -2
- package/src/modal/logo-paths.ts +2 -2
- package/src/modal/placement.ts +7 -6
- package/src/modal/revalidate.ts +2 -3
- package/src/modal/verify-client.ts +2 -2
- package/src/verify/cache.ts +34 -8
- package/src/verify/fetch-with-deadline.ts +60 -0
- package/src/verify/get-verified-envelope.ts +131 -48
- package/src/verify/resolve-kid.ts +22 -6
- package/src/webcomponent/certrev-badge.ts +24 -2
- package/src/webcomponent/render-badge-html.ts +66 -19
- package/src/__tests__/__snapshots__/render-cert-block.test.ts.snap +0 -17
- package/src/__tests__/components.test.tsx +0 -206
- package/src/__tests__/preview-block.test.ts +0 -84
- package/src/__tests__/project.test.ts +0 -128
- package/src/__tests__/readme-version.test.ts +0 -51
- package/src/__tests__/render-cert-block.test.ts +0 -657
- package/src/__tests__/render-def.test.tsx +0 -295
- package/src/__tests__/verify.test.ts +0 -239
- package/src/__tests__/webcomponent.test.tsx +0 -116
- package/src/builder/__tests__/builder.test.tsx +0 -158
- package/src/modal/cert-modal-view.test.ts +0 -175
- package/src/modal/certrev-cert-modal.test.ts +0 -125
- package/src/modal/ftc-guard.test.ts +0 -153
- package/src/modal/interactions.test.ts +0 -250
- package/src/modal/placement.test.ts +0 -398
- package/src/modal/revalidate.test.ts +0 -111
- package/src/modal/verify-client.test.ts +0 -164
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
// ⚠ VENDORED, BYTE-FAITHFUL relocation of portal `
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
1
|
+
// ⚠ VENDORED, BYTE-FAITHFUL relocation of the portal's `avatar-resize` module. The body is
|
|
2
|
+
// byte-identical to the source the deployed `certrev-cert.js` was bundled from — keep it that
|
|
3
|
+
// way. Configurable asset origins for other headless brands are a deliberate post-relocation
|
|
4
|
+
// follow-up (byte-parity takes precedence now).
|
|
5
5
|
/**
|
|
6
|
-
* Avatar right-sizing
|
|
6
|
+
* Avatar right-sizing — the SINGLE source of truth for how a cert contributor/expert
|
|
7
7
|
* headshot URL is rewritten to a display-sized derivative. Referenced by the cert MODAL (TS,
|
|
8
8
|
* cert-modal-view.ts), mirrored by the Liquid snippet (certrev-avatar-url.liquid), and by the
|
|
9
|
-
* Cloudflare size-allowlist WAF rule
|
|
9
|
+
* Cloudflare size-allowlist WAF rule. Keep the three in lockstep — the
|
|
10
10
|
* `avatar-resize.test.ts` `SIZES`/param assertions are the tripwire.
|
|
11
11
|
*
|
|
12
|
-
* Architecture
|
|
12
|
+
* Architecture: the signed cert envelope carries ONE canonical full-res photoUrl
|
|
13
13
|
* (also the JSON-LD Person.image — never shrunk). Display sizing is a PRESENTATION concern, applied
|
|
14
14
|
* here via Cloudflare Image Resizing on the same zone as assets.certrev.com:
|
|
15
15
|
* https://assets.certrev.com/cdn-cgi/image/width=W,height=W,fit=cover,format=auto/<path>
|
|
@@ -17,19 +17,19 @@
|
|
|
17
17
|
* allowlist is needed; format=auto serves webp/avif; the transform is cached + billed per-unique.
|
|
18
18
|
*
|
|
19
19
|
* ENABLEMENT GATE (`AVATAR_RESIZE_ENABLED`): OFF until Cloudflare Image Resizing is enabled on the
|
|
20
|
-
* certrev.com zone AND a real photo is verified to resize
|
|
20
|
+
* certrev.com zone AND a real photo is verified to resize. While OFF, avatars use
|
|
21
21
|
* the raw canonical URL — byte-identical to today's behavior — so the extension can deploy for the
|
|
22
22
|
* font de-block with ZERO avatar regression (a cdn-cgi/image URL 404s → initials fallback if the
|
|
23
23
|
* feature isn't live). Going live is a one-line flip here + in certrev-avatar-url.liquid, then the
|
|
24
|
-
* raw branch is removed (flag-debt:
|
|
24
|
+
* raw branch is removed (flag-debt: the avatar go-live follow-up).
|
|
25
25
|
*/
|
|
26
26
|
/**
|
|
27
|
-
* Enablement gate — LIVE as of 2026-07-20
|
|
28
|
-
* is enabled on the certrev.com zone (`image_resizing = on`), and the size-allowlist WAF rule
|
|
29
|
-
*
|
|
30
|
-
*
|
|
27
|
+
* Enablement gate — LIVE as of 2026-07-20. Cloudflare Image Resizing (Transformations)
|
|
28
|
+
* is enabled on the certrev.com zone (`image_resizing = on`), and the size-allowlist WAF rule is
|
|
29
|
+
* verified enforcing on `/cdn-cgi/image/` paths — a real photo resizes (`width=84` → 200
|
|
30
|
+
* image/jpeg) while a disallowed size (`width=999`) is 403-blocked.
|
|
31
31
|
* Kept as a one-line kill-switch: flip back to `false` + redeploy to instantly revert to raw URLs if
|
|
32
|
-
* resizing ever misbehaves (removing the raw branch entirely is the flag-debt follow-up
|
|
32
|
+
* resizing ever misbehaves (removing the raw branch entirely is the flag-debt follow-up).
|
|
33
33
|
*/
|
|
34
34
|
export const AVATAR_RESIZE_ENABLED = true;
|
|
35
35
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"avatar-resize.js","sourceRoot":"","sources":["../../src/modal/avatar-resize.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"avatar-resize.js","sourceRoot":"","sources":["../../src/modal/avatar-resize.ts"],"names":[],"mappings":"AAAA,2FAA2F;AAC3F,8FAA8F;AAC9F,6FAA6F;AAC7F,gDAAgD;AAChD;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,IAAI,CAAC;AAE1C;;;;GAIG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAU,CAAC;AAGzD,4FAA4F;AAC5F,MAAM,CAAC,MAAM,mBAAmB,GAAG;IAClC,oBAAoB;IACpB,4BAA4B;CACnB,CAAC;AAEX;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CAAC,IAAgB;IACtD,OAAO,SAAS,IAAI,WAAW,IAAI,yCAAyC,CAAC;AAC9E,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB,CACpC,GAA8B,EAC9B,IAAgB;IAEhB,MAAM,GAAG,GAAG,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC/B,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC;QAAE,OAAO,GAAG,CAAC;IAC1C,IAAI,MAAW,CAAC;IAChB,IAAI,CAAC;QACJ,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;IACvB,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,GAAG,CAAC;IACZ,CAAC;IACD,IAAI,CAAE,mBAAyC,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC;QACxE,OAAO,GAAG,CAAC;IACZ,IAAI,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,iBAAiB,CAAC;QAAE,OAAO,GAAG,CAAC,CAAC,oBAAoB;IACnF,gGAAgG;IAChG,oGAAoG;IACpG,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAChD,OAAO,GAAG,MAAM,CAAC,MAAM,kBAAkB,sBAAsB,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;AACjF,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAC9B,GAA8B,EAC9B,IAAgB;IAEhB,IAAI,CAAC,qBAAqB;QAAE,OAAO,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACtD,OAAO,qBAAqB,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;AACzC,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Pure envelope → modal-HTML mapping for `<certrev-cert-modal
|
|
2
|
+
* Pure envelope → modal-HTML mapping for `<certrev-cert-modal>`.
|
|
3
3
|
*
|
|
4
4
|
* DOM-free and side-effect-free so it unit-tests without a browser: given the
|
|
5
5
|
* signed envelope's `payload.content`, it returns the inner HTML of the certificate
|
|
@@ -11,16 +11,20 @@
|
|
|
11
11
|
* - Every dynamic value is `escapeHtml`'d (the envelope is signed, but a reviewer
|
|
12
12
|
* name / memo is still attacker-adjacent content).
|
|
13
13
|
* - Only `http(s)` hrefs render (mirrors the Liquid `certrev-safe-url` guard).
|
|
14
|
-
* - Verified-only fields
|
|
14
|
+
* - Verified-only fields: the bio binds the envelope's verified
|
|
15
15
|
* `background`/`bio`; this module never reaches for a raw column.
|
|
16
16
|
* - Graceful degradation: a missing article title drops the "Certifies the article"
|
|
17
17
|
* block; a missing display cert id drops that meta column; no credentials → no
|
|
18
18
|
* chips / no creds line; no bio → no bio paragraph. Nothing renders an empty gap.
|
|
19
|
-
* -
|
|
19
|
+
* - Display-eviction accept-on-read: an ABSENT `display` block resolves to the
|
|
20
20
|
* preset default (show-all) — every read below is `display?.x !== false` / `=== false`,
|
|
21
21
|
* so `undefined` never suppresses a field. The modal is the LOCKED navy trust chrome and
|
|
22
22
|
* is deliberately NOT themeable by a brand render-def; it reads visibility off the signed
|
|
23
23
|
* envelope only, so no render-def wiring belongs here.
|
|
24
|
+
* - Type tolerance, not just shape tolerance: `content` is a `JSON.parse(...) as` cast off an
|
|
25
|
+
* envelope whose SIGNATURE was checked and whose SHAPE never was, so every read below goes
|
|
26
|
+
* through `asText` before it touches a string method. `(x || '').trim()` looks defensive but
|
|
27
|
+
* throws on a number, and a throw here is the dialog the reader just clicked failing to open.
|
|
24
28
|
*/
|
|
25
29
|
export interface CertModalCredential {
|
|
26
30
|
abbreviation?: string | null;
|
|
@@ -34,7 +38,7 @@ export interface CertModalExpert {
|
|
|
34
38
|
photoUrl?: string | null;
|
|
35
39
|
bio?: string | null;
|
|
36
40
|
background?: string | null;
|
|
37
|
-
/**
|
|
41
|
+
/** The pre-composed material-connection label ('Compensated expert') or null/absent for
|
|
38
42
|
* a pro-bono reviewer. Present → the disclosure footer renders the label; null/absent → label omitted. */
|
|
39
43
|
compensationCue?: string | null;
|
|
40
44
|
}
|
|
@@ -50,6 +54,22 @@ export interface CertModalContent {
|
|
|
50
54
|
showBio?: boolean | null;
|
|
51
55
|
} | null;
|
|
52
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* The `rel` every CertREV anchor in this module carries.
|
|
59
|
+
*
|
|
60
|
+
* `../components/rel.ts` (`CERTREV_LINK_REL`) is the SOURCE OF TRUTH for the qualification
|
|
61
|
+
* tokens and the policy reasoning behind them — read it there. The value is duplicated rather
|
|
62
|
+
* than imported because `src/modal/` is bundled standalone into the dependency-free
|
|
63
|
+
* `certrev-cert.js` IIFE (`build:modal-bundle`) and imports NOTHING from `src/components/`;
|
|
64
|
+
* crossing that boundary for a string constant would pull the SSR module graph into a
|
|
65
|
+
* storefront asset. This copy adds `noreferrer` on top of the shared tokens: both anchors here
|
|
66
|
+
* are `target="_blank"`, where it still earns its place.
|
|
67
|
+
*
|
|
68
|
+
* Keep in lockstep with `CERTREV_LINK_REL` — `nofollow` + `sponsored` are the qualification the
|
|
69
|
+
* link-spam policy names, and dropping either from one copy silently un-qualifies half the
|
|
70
|
+
* package's links.
|
|
71
|
+
*/
|
|
72
|
+
export declare const CERTREV_MODAL_LINK_REL = "nofollow sponsored noopener noreferrer";
|
|
53
73
|
/** Two-letter initials — first + last of the core name (honorific + post-nominal stripped),
|
|
54
74
|
* so "Dr. Erik Schraga, MD" → "ES" (matches the Liquid derivation), not "EM". */
|
|
55
75
|
export declare function deriveInitials(name: string): string;
|
|
@@ -66,9 +86,9 @@ export declare function safeHref(url: string | null | undefined): string;
|
|
|
66
86
|
*/
|
|
67
87
|
export declare function renderCertDialogInner(content: CertModalContent): string | null;
|
|
68
88
|
/**
|
|
69
|
-
* The reviewer/profile modal
|
|
70
|
-
* reviewer name (fail-closed). The affiliation subtitle is intentionally omitted
|
|
71
|
-
*
|
|
89
|
+
* The reviewer/profile modal inner HTML. Returns `null` when there is no
|
|
90
|
+
* reviewer name (fail-closed). The affiliation subtitle is intentionally omitted:
|
|
91
|
+
* there is no verified data source for it.
|
|
72
92
|
*/
|
|
73
93
|
export declare function renderExpertDialogInner(content: CertModalContent): string | null;
|
|
74
94
|
//# sourceMappingURL=cert-modal-view.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cert-modal-view.d.ts","sourceRoot":"","sources":["../../src/modal/cert-modal-view.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"cert-modal-view.d.ts","sourceRoot":"","sources":["../../src/modal/cert-modal-view.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAOH,MAAM,WAAW,mBAAmB;IACnC,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACzB;AAED,MAAM,WAAW,eAAe;IAC/B,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,WAAW,CAAC,EAAE,SAAS,mBAAmB,EAAE,GAAG,IAAI,CAAA;IACnD,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B;+GAC2G;IAC3G,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC/B;AAED,+EAA+E;AAC/E,MAAM,WAAW,gBAAgB;IAChC,MAAM,CAAC,EAAE,eAAe,GAAG,IAAI,CAAA;IAC/B,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,OAAO,CAAC,EAAE;QAAE,eAAe,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI,CAAA;CAC/E;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,sBAAsB,2CAA2C,CAAA;AAY9E;kFACkF;AAClF,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAKnD;AAED,sDAAsD;AACtD,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED,iFAAiF;AACjF,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED,uFAAuF;AACvF,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAI/D;AAoED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,gBAAgB,GAAG,MAAM,GAAG,IAAI,CAwB9E;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,gBAAgB,GAAG,MAAM,GAAG,IAAI,CAiBhF"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Pure envelope → modal-HTML mapping for `<certrev-cert-modal
|
|
2
|
+
* Pure envelope → modal-HTML mapping for `<certrev-cert-modal>`.
|
|
3
3
|
*
|
|
4
4
|
* DOM-free and side-effect-free so it unit-tests without a browser: given the
|
|
5
5
|
* signed envelope's `payload.content`, it returns the inner HTML of the certificate
|
|
@@ -11,26 +11,46 @@
|
|
|
11
11
|
* - Every dynamic value is `escapeHtml`'d (the envelope is signed, but a reviewer
|
|
12
12
|
* name / memo is still attacker-adjacent content).
|
|
13
13
|
* - Only `http(s)` hrefs render (mirrors the Liquid `certrev-safe-url` guard).
|
|
14
|
-
* - Verified-only fields
|
|
14
|
+
* - Verified-only fields: the bio binds the envelope's verified
|
|
15
15
|
* `background`/`bio`; this module never reaches for a raw column.
|
|
16
16
|
* - Graceful degradation: a missing article title drops the "Certifies the article"
|
|
17
17
|
* block; a missing display cert id drops that meta column; no credentials → no
|
|
18
18
|
* chips / no creds line; no bio → no bio paragraph. Nothing renders an empty gap.
|
|
19
|
-
* -
|
|
19
|
+
* - Display-eviction accept-on-read: an ABSENT `display` block resolves to the
|
|
20
20
|
* preset default (show-all) — every read below is `display?.x !== false` / `=== false`,
|
|
21
21
|
* so `undefined` never suppresses a field. The modal is the LOCKED navy trust chrome and
|
|
22
22
|
* is deliberately NOT themeable by a brand render-def; it reads visibility off the signed
|
|
23
23
|
* envelope only, so no render-def wiring belongs here.
|
|
24
|
+
* - Type tolerance, not just shape tolerance: `content` is a `JSON.parse(...) as` cast off an
|
|
25
|
+
* envelope whose SIGNATURE was checked and whose SHAPE never was, so every read below goes
|
|
26
|
+
* through `asText` before it touches a string method. `(x || '').trim()` looks defensive but
|
|
27
|
+
* throws on a number, and a throw here is the dialog the reader just clicked failing to open.
|
|
24
28
|
*/
|
|
25
|
-
import { escapeHtml } from './escape.js';
|
|
29
|
+
import { asText, escapeHtml } from './escape.js';
|
|
26
30
|
import { resizeAvatarUrl } from './avatar-resize.js';
|
|
27
31
|
import { CERT_SCOPE_LINE, formatCertDisplayDate } from './display-strings.js';
|
|
28
32
|
import { checkIcon, chevronMark, verifiedStamp } from './certrev-cert-modal.styles.js';
|
|
33
|
+
/**
|
|
34
|
+
* The `rel` every CertREV anchor in this module carries.
|
|
35
|
+
*
|
|
36
|
+
* `../components/rel.ts` (`CERTREV_LINK_REL`) is the SOURCE OF TRUTH for the qualification
|
|
37
|
+
* tokens and the policy reasoning behind them — read it there. The value is duplicated rather
|
|
38
|
+
* than imported because `src/modal/` is bundled standalone into the dependency-free
|
|
39
|
+
* `certrev-cert.js` IIFE (`build:modal-bundle`) and imports NOTHING from `src/components/`;
|
|
40
|
+
* crossing that boundary for a string constant would pull the SSR module graph into a
|
|
41
|
+
* storefront asset. This copy adds `noreferrer` on top of the shared tokens: both anchors here
|
|
42
|
+
* are `target="_blank"`, where it still earns its place.
|
|
43
|
+
*
|
|
44
|
+
* Keep in lockstep with `CERTREV_LINK_REL` — `nofollow` + `sponsored` are the qualification the
|
|
45
|
+
* link-spam policy names, and dropping either from one copy silently un-qualifies half the
|
|
46
|
+
* package's links.
|
|
47
|
+
*/
|
|
48
|
+
export const CERTREV_MODAL_LINK_REL = 'nofollow sponsored noopener noreferrer';
|
|
29
49
|
const HONORIFIC_RE = /^(dr|prof|professor|mr|mrs|ms|mx|rev|sir|dame)\.?\s+/i;
|
|
30
50
|
/** The bare given+family name: strip the leading honorific AND the trailing post-nominal
|
|
31
51
|
* (`, MD`), so "Dr. Erik Schraga, MD" → "Erik Schraga". */
|
|
32
52
|
function coreName(displayName) {
|
|
33
|
-
const withoutHonorific = displayName.replace(HONORIFIC_RE, '').trim();
|
|
53
|
+
const withoutHonorific = asText(displayName).replace(HONORIFIC_RE, '').trim();
|
|
34
54
|
const comma = withoutHonorific.indexOf(',');
|
|
35
55
|
return (comma === -1 ? withoutHonorific : withoutHonorific.slice(0, comma)).trim();
|
|
36
56
|
}
|
|
@@ -50,22 +70,26 @@ export function signatureName(displayName) {
|
|
|
50
70
|
}
|
|
51
71
|
/** `https://certrev.com/verify/x` → `certrev.com/verify/x` (footer URL line). */
|
|
52
72
|
export function stripProtocol(url) {
|
|
53
|
-
return url.replace(/^https?:\/\//i, '').replace(/\/$/, '');
|
|
73
|
+
return asText(url).replace(/^https?:\/\//i, '').replace(/\/$/, '');
|
|
54
74
|
}
|
|
55
75
|
/** Return the url only if it is an absolute http(s) URL, else `#` (safe-url guard). */
|
|
56
76
|
export function safeHref(url) {
|
|
57
|
-
|
|
77
|
+
const href = asText(url).trim();
|
|
78
|
+
if (!href)
|
|
58
79
|
return '#';
|
|
59
|
-
return /^https?:\/\//i.test(
|
|
80
|
+
return /^https?:\/\//i.test(href) ? href : '#';
|
|
60
81
|
}
|
|
61
82
|
/** A single credential's display label (cardLabel ?? fullName ?? abbreviation). */
|
|
62
83
|
function credLabel(c) {
|
|
63
|
-
return (c
|
|
84
|
+
return (asText(c?.cardLabel) || asText(c?.fullName) || asText(c?.abbreviation)).trim();
|
|
64
85
|
}
|
|
65
86
|
/** The verified credential labels, in order, de-duped + non-empty. */
|
|
66
87
|
function credLabels(expert) {
|
|
67
88
|
const out = [];
|
|
68
|
-
|
|
89
|
+
// `Array.isArray`, not `?? []`: a `credentials` that parsed as an object is not iterable, and
|
|
90
|
+
// `for…of` over one throws before any of the per-entry guards below get a chance to run.
|
|
91
|
+
const credentials = Array.isArray(expert?.credentials) ? expert.credentials : [];
|
|
92
|
+
for (const c of credentials) {
|
|
69
93
|
const label = credLabel(c);
|
|
70
94
|
if (label && !out.includes(label))
|
|
71
95
|
out.push(label);
|
|
@@ -76,13 +100,13 @@ function credLabels(expert) {
|
|
|
76
100
|
function bioText(expert, display) {
|
|
77
101
|
if (display?.showBio === false)
|
|
78
102
|
return '';
|
|
79
|
-
return (expert?.background || expert?.bio
|
|
103
|
+
return (asText(expert?.background) || asText(expert?.bio)).trim();
|
|
80
104
|
}
|
|
81
105
|
/** An avatar cell — the cert-frozen photo (when shown) or the initials chip. */
|
|
82
106
|
function avatarHtml(expert, name, sizeClass, showPhoto) {
|
|
83
|
-
const photo = (expert?.photoUrl
|
|
107
|
+
const photo = asText(expert?.photoUrl).trim();
|
|
84
108
|
if (showPhoto && /^https?:\/\//i.test(photo)) {
|
|
85
|
-
// Display px from the size class; request the @2x derivative for retina crispness
|
|
109
|
+
// Display px from the size class; request the @2x derivative for retina crispness.
|
|
86
110
|
// resizeAvatarUrl is host-guarded + enablement-gated: until Cloudflare Image Resizing is live it
|
|
87
111
|
// returns the raw canonical URL, so the modal never 404s an unresized host.
|
|
88
112
|
const displayPx = sizeClass.includes('--64') ? 64 : 56;
|
|
@@ -99,14 +123,14 @@ function certifiedChip(cls) {
|
|
|
99
123
|
return `<span class="${cls}">${checkIcon(8)}Certified</span>`;
|
|
100
124
|
}
|
|
101
125
|
/**
|
|
102
|
-
* The FTC disclosure footer
|
|
126
|
+
* The FTC disclosure footer, rendered on both dialogs. The material-connection cue
|
|
103
127
|
* (`expert.compensationCue`, a FINISHED string off the signed envelope) leads ONLY when the reviewer
|
|
104
128
|
* was compensated; a pro-bono reviewer (null/absent cue) drops the label but keeps the scope line —
|
|
105
129
|
* which makes no compensation claim, so it is true for volunteers too and renders unconditionally.
|
|
106
130
|
* The scope line is the verbatim FTC copy (`CERT_SCOPE_LINE`), never re-assembled here.
|
|
107
131
|
*/
|
|
108
132
|
function disclosureFooter(expert) {
|
|
109
|
-
const cue = (expert?.compensationCue
|
|
133
|
+
const cue = asText(expert?.compensationCue).trim();
|
|
110
134
|
const cueHtml = cue ? `<span class="crm-disclosure__cue">${escapeHtml(cue)}</span> ` : '';
|
|
111
135
|
return `<div class="crm-disclosure">${cueHtml}${escapeHtml(CERT_SCOPE_LINE)}</div>`;
|
|
112
136
|
}
|
|
@@ -117,15 +141,15 @@ function disclosureFooter(expert) {
|
|
|
117
141
|
*/
|
|
118
142
|
export function renderCertDialogInner(content) {
|
|
119
143
|
const expert = content.expert ?? null;
|
|
120
|
-
const name = (expert?.displayName
|
|
144
|
+
const name = asText(expert?.displayName).trim();
|
|
121
145
|
if (!name)
|
|
122
146
|
return null;
|
|
123
147
|
const showPhoto = content.display?.showExpertPhoto !== false;
|
|
124
148
|
const creds = credLabels(expert).join(' · ');
|
|
125
149
|
const issued = formatCertDisplayDate(content.certifiedAt) ?? '';
|
|
126
|
-
const certId = (content.displayCertId
|
|
127
|
-
const title = (content.articleTitle
|
|
128
|
-
const verifyUrl = (content.verifyUrl
|
|
150
|
+
const certId = asText(content.displayCertId).trim();
|
|
151
|
+
const title = asText(content.articleTitle).trim();
|
|
152
|
+
const verifyUrl = asText(content.verifyUrl).trim();
|
|
129
153
|
const sig = signatureName(name);
|
|
130
154
|
const certifiesBlock = title
|
|
131
155
|
? `<div class="crm-certifies"><div class="crm-certifies__eyebrow">Certifies the article</div><div class="crm-certifies__title">${escapeHtml(title)}</div></div>`
|
|
@@ -134,16 +158,16 @@ export function renderCertDialogInner(content) {
|
|
|
134
158
|
? `<div class="crm-meta__col"><div class="crm-meta__label">Certificate ID</div><div class="crm-meta__value crm-meta__value--mono">${escapeHtml(certId)}</div></div>`
|
|
135
159
|
: '';
|
|
136
160
|
const urlLine = verifyUrl ? `<div class="crm-sig__url">${escapeHtml(stripProtocol(verifyUrl))}</div>` : '';
|
|
137
|
-
return `${CLOSE_BUTTON}${headHtml('Certificate of Expert Review')}<div class="crm-body--cert"><div class="crm-expert-row">${avatarHtml(expert, name, 'crm-avatar--56', showPhoto)}<div class="crm-expert-row__info"><div class="crm-expert-row__eyebrow">Reviewing Expert</div><div class="crm-expert-row__name">${escapeHtml(name)}</div>${creds ? `<div class="crm-expert-row__creds">${escapeHtml(creds)}</div>` : ''}</div></div>${certifiesBlock}<div class="crm-meta"><div class="crm-meta__col"><div class="crm-meta__label">Issued</div><div class="crm-meta__value">${escapeHtml(issued)}</div></div>${certIdCol}<div class="crm-meta__col"><div class="crm-meta__label">Status</div><div class="crm-meta__status">${certifiedChip('crm-chip')}</div></div></div><div class="crm-sig"><div><div class="crm-sig__name">${escapeHtml(sig)}</div><div class="crm-sig__rule"></div>${urlLine}</div>${verifiedStamp('cert')}</div>${disclosureFooter(expert)}<div class="crm-actions"><a class="crm-cta" href="${escapeHtml(safeHref(verifyUrl))}" target="_blank" rel="
|
|
161
|
+
return `${CLOSE_BUTTON}${headHtml('Certificate of Expert Review')}<div class="crm-body--cert"><div class="crm-expert-row">${avatarHtml(expert, name, 'crm-avatar--56', showPhoto)}<div class="crm-expert-row__info"><div class="crm-expert-row__eyebrow">Reviewing Expert</div><div class="crm-expert-row__name">${escapeHtml(name)}</div>${creds ? `<div class="crm-expert-row__creds">${escapeHtml(creds)}</div>` : ''}</div></div>${certifiesBlock}<div class="crm-meta"><div class="crm-meta__col"><div class="crm-meta__label">Issued</div><div class="crm-meta__value">${escapeHtml(issued)}</div></div>${certIdCol}<div class="crm-meta__col"><div class="crm-meta__label">Status</div><div class="crm-meta__status">${certifiedChip('crm-chip')}</div></div></div><div class="crm-sig"><div><div class="crm-sig__name">${escapeHtml(sig)}</div><div class="crm-sig__rule"></div>${urlLine}</div>${verifiedStamp('cert')}</div>${disclosureFooter(expert)}<div class="crm-actions"><a class="crm-cta" href="${escapeHtml(safeHref(verifyUrl))}" target="_blank" rel="${CERTREV_MODAL_LINK_REL}">View full certificate</a><button type="button" class="crm-ghost" data-certrev-modal-close>Close</button></div></div>`;
|
|
138
162
|
}
|
|
139
163
|
/**
|
|
140
|
-
* The reviewer/profile modal
|
|
141
|
-
* reviewer name (fail-closed). The affiliation subtitle is intentionally omitted
|
|
142
|
-
*
|
|
164
|
+
* The reviewer/profile modal inner HTML. Returns `null` when there is no
|
|
165
|
+
* reviewer name (fail-closed). The affiliation subtitle is intentionally omitted:
|
|
166
|
+
* there is no verified data source for it.
|
|
143
167
|
*/
|
|
144
168
|
export function renderExpertDialogInner(content) {
|
|
145
169
|
const expert = content.expert ?? null;
|
|
146
|
-
const name = (expert?.displayName
|
|
170
|
+
const name = asText(expert?.displayName).trim();
|
|
147
171
|
if (!name)
|
|
148
172
|
return null;
|
|
149
173
|
const showPhoto = content.display?.showExpertPhoto !== false;
|
|
@@ -155,6 +179,6 @@ export function renderExpertDialogInner(content) {
|
|
|
155
179
|
: '';
|
|
156
180
|
const bioHtml = bio ? `<p class="crm-bio">${escapeHtml(bio)}</p>` : '';
|
|
157
181
|
const trustText = date ? `Independently reviewed · Certified ${escapeHtml(date)}` : 'Independently reviewed';
|
|
158
|
-
return `${CLOSE_BUTTON}${headHtml('Verified reviewer')}<div class="crm-body--expert"><div class="crm-id">${avatarHtml(expert, name, 'crm-avatar--64', showPhoto)}<div class="crm-id__info"><div class="crm-id__name">${escapeHtml(name)}</div></div></div>${chipsHtml}${bioHtml}<div class="crm-trust">${certifiedChip('crm-trust__chip')}<span class="crm-trust__text">${trustText}</span></div>${disclosureFooter(expert)}<div class="crm-actions"><a class="crm-cta" href="${escapeHtml(safeHref(expert?.profileUrl))}" target="_blank" rel="
|
|
182
|
+
return `${CLOSE_BUTTON}${headHtml('Verified reviewer')}<div class="crm-body--expert"><div class="crm-id">${avatarHtml(expert, name, 'crm-avatar--64', showPhoto)}<div class="crm-id__info"><div class="crm-id__name">${escapeHtml(name)}</div></div></div>${chipsHtml}${bioHtml}<div class="crm-trust">${certifiedChip('crm-trust__chip')}<span class="crm-trust__text">${trustText}</span></div>${disclosureFooter(expert)}<div class="crm-actions"><a class="crm-cta" href="${escapeHtml(safeHref(expert?.profileUrl))}" target="_blank" rel="${CERTREV_MODAL_LINK_REL}">View full profile on CertREV</a><button type="button" class="crm-ghost" data-certrev-modal-close>Close</button></div></div>`;
|
|
159
183
|
}
|
|
160
184
|
//# sourceMappingURL=cert-modal-view.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cert-modal-view.js","sourceRoot":"","sources":["../../src/modal/cert-modal-view.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"cert-modal-view.js","sourceRoot":"","sources":["../../src/modal/cert-modal-view.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `<certrev-cert-modal>` — the ONE Shadow-DOM element that renders both in-page cert
|
|
3
|
-
* dialogs (certificate
|
|
4
|
-
*
|
|
3
|
+
* dialogs (certificate + reviewer) across Shopify / WordPress / Builder.
|
|
4
|
+
* Replaces the three drifting per-platform modal implementations.
|
|
5
5
|
*
|
|
6
6
|
* Design:
|
|
7
7
|
* - One element, one OPEN shadow root, two `<dialog>`s (`#cert`, `#expert`). Public
|
|
@@ -47,7 +47,7 @@ export declare class CertRevCertModal extends HTMLElement {
|
|
|
47
47
|
private renderDialogs;
|
|
48
48
|
private show;
|
|
49
49
|
/**
|
|
50
|
-
* The modal kill-switch
|
|
50
|
+
* The modal kill-switch: a fetched envelope is REVOKED/EXPIRED. Don't open;
|
|
51
51
|
* mark the host suppressed (mirrors the badge revalidation's `data-certrev-suppressed`) and
|
|
52
52
|
* hide the light-DOM triggers so a stale click can't re-open a pulled cert. Best-effort DOM.
|
|
53
53
|
*/
|
|
@@ -55,9 +55,9 @@ export declare class CertRevCertModal extends HTMLElement {
|
|
|
55
55
|
private onShadowClick;
|
|
56
56
|
}
|
|
57
57
|
/**
|
|
58
|
-
* The modal-side lifecycle gate
|
|
58
|
+
* The modal-side lifecycle gate: a fetched Delivery-API artifact that is
|
|
59
59
|
* REVOKED or EXPIRED must NOT render "verified" content. Two revocation shapes suppress:
|
|
60
|
-
* • the SLIM `CertTombstone` the control plane serves for a revoked placement
|
|
60
|
+
* • the SLIM `CertTombstone` the control plane serves for a revoked placement —
|
|
61
61
|
* detected by the `kind: 'tombstone'` discriminator via `isTombstone`. It carries NO payload,
|
|
62
62
|
* so a `payload.lifecycle` read alone would MISS it (and `markSuppressed()` would never fire);
|
|
63
63
|
* • a legacy envelope with `lifecycle.revokedAt` set, or any envelope whose `expiresAt` passed.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `<certrev-cert-modal>` — the ONE Shadow-DOM element that renders both in-page cert
|
|
3
|
-
* dialogs (certificate
|
|
4
|
-
*
|
|
3
|
+
* dialogs (certificate + reviewer) across Shopify / WordPress / Builder.
|
|
4
|
+
* Replaces the three drifting per-platform modal implementations.
|
|
5
5
|
*
|
|
6
6
|
* Design:
|
|
7
7
|
* - One element, one OPEN shadow root, two `<dialog>`s (`#cert`, `#expert`). Public
|
|
@@ -47,7 +47,7 @@ function getSharedSheet() {
|
|
|
47
47
|
}
|
|
48
48
|
/**
|
|
49
49
|
* Inject the modal font families once, at document level, on first open — SELF-HOSTED from R2
|
|
50
|
-
*
|
|
50
|
+
* Declares the shared CERT_FONT_FACE_CSS @font-face block inline instead of loading a
|
|
51
51
|
* render-blocking `fonts.googleapis.com` stylesheet (which also leaked the visitor's IP to Google).
|
|
52
52
|
* @font-face at document level resolves across the shadow boundary, so the shadow-DOM modal picks
|
|
53
53
|
* these up exactly as it did the old Google <link>. A crossorigin preconnect warms the R2 origin
|
|
@@ -155,16 +155,16 @@ export class CertRevCertModal extends HTMLElement {
|
|
|
155
155
|
return;
|
|
156
156
|
const artifact = (await res.json());
|
|
157
157
|
// A 200 may be a REVOCATION — either the SLIM `CertTombstone` the control plane now
|
|
158
|
-
// serves for a revoked placement (
|
|
158
|
+
// serves for a revoked placement (no payload) or a legacy envelope with
|
|
159
159
|
// `revokedAt` set — plus an EXPIRED envelope. The Delivery API serves those signed so
|
|
160
|
-
// the edge SUPPRESSES rather than fail-opening on a 404
|
|
160
|
+
// the edge SUPPRESSES rather than fail-opening on a 404. Never render
|
|
161
161
|
// "verified" content from a revoked/expired artifact.
|
|
162
162
|
if (isArtifactSuppressed(artifact)) {
|
|
163
163
|
this.markSuppressed();
|
|
164
164
|
return;
|
|
165
165
|
}
|
|
166
166
|
// Not suppressed → a live envelope (a tombstone always suppresses above); `isTombstone`
|
|
167
|
-
// narrows the union so the payload read is type-safe
|
|
167
|
+
// narrows the union so the payload read is type-safe.
|
|
168
168
|
const content = isTombstone(artifact)
|
|
169
169
|
? undefined
|
|
170
170
|
: artifact.payload?.content;
|
|
@@ -198,7 +198,7 @@ export class CertRevCertModal extends HTMLElement {
|
|
|
198
198
|
dlg.showModal();
|
|
199
199
|
}
|
|
200
200
|
/**
|
|
201
|
-
* The modal kill-switch
|
|
201
|
+
* The modal kill-switch: a fetched envelope is REVOKED/EXPIRED. Don't open;
|
|
202
202
|
* mark the host suppressed (mirrors the badge revalidation's `data-certrev-suppressed`) and
|
|
203
203
|
* hide the light-DOM triggers so a stale click can't re-open a pulled cert. Best-effort DOM.
|
|
204
204
|
*/
|
|
@@ -235,9 +235,9 @@ function safeParseContent(json) {
|
|
|
235
235
|
}
|
|
236
236
|
}
|
|
237
237
|
/**
|
|
238
|
-
* The modal-side lifecycle gate
|
|
238
|
+
* The modal-side lifecycle gate: a fetched Delivery-API artifact that is
|
|
239
239
|
* REVOKED or EXPIRED must NOT render "verified" content. Two revocation shapes suppress:
|
|
240
|
-
* • the SLIM `CertTombstone` the control plane serves for a revoked placement
|
|
240
|
+
* • the SLIM `CertTombstone` the control plane serves for a revoked placement —
|
|
241
241
|
* detected by the `kind: 'tombstone'` discriminator via `isTombstone`. It carries NO payload,
|
|
242
242
|
* so a `payload.lifecycle` read alone would MISS it (and `markSuppressed()` would never fire);
|
|
243
243
|
* • a legacy envelope with `lifecycle.revokedAt` set, or any envelope whose `expiresAt` passed.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"certrev-cert-modal.js","sourceRoot":"","sources":["../../src/modal/certrev-cert-modal.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"certrev-cert-modal.js","sourceRoot":"","sources":["../../src/modal/certrev-cert-modal.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Scoped styles + inline SVGs for the `<certrev-cert-modal>` Shadow-DOM element
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* (`docs/claude/design/certificate-modals/`, footer variant 3a + reviewer 4b).
|
|
2
|
+
* Scoped styles + inline SVGs for the `<certrev-cert-modal>` Shadow-DOM element.
|
|
3
|
+
* The single source of truth for the certificate + reviewer modal look, ported
|
|
4
|
+
* byte-faithfully from the approved design reference.
|
|
6
5
|
*
|
|
7
6
|
* Because the element renders inside a shadow root, this CSS is fully scoped: the
|
|
8
7
|
* brand storefront theme cannot bleed in, and these rules never leak out — so the
|
|
@@ -13,7 +12,8 @@
|
|
|
13
12
|
* root, so they must live at document level — see `certrev-cert-modal.ts`).
|
|
14
13
|
*/
|
|
15
14
|
/** The four-chevron CertREV mark (viewBox 0 0 375 375), tinted via the passed fill. Path data is
|
|
16
|
-
* single-sourced from
|
|
15
|
+
* single-sourced from the portal design-guide's logo module (the SOT the codegen mirrors into
|
|
16
|
+
* every twin). */
|
|
17
17
|
export declare function chevronMark(size: number, fill: string): string;
|
|
18
18
|
/** The 8px lime-chip check glyph (viewBox 0 0 24 24). */
|
|
19
19
|
export declare function checkIcon(size?: number): string;
|
|
@@ -31,5 +31,5 @@ export declare function verifiedStamp(idSuffix?: string): string;
|
|
|
31
31
|
*/
|
|
32
32
|
export declare const CERT_MODAL_FONT_FAMILIES: readonly ["DM Sans", "Playfair Display", "JetBrains Mono", "Plus Jakarta Sans", "Allura"];
|
|
33
33
|
/** The full scoped stylesheet, adopted via a constructable `CSSStyleSheet`. */
|
|
34
|
-
export declare const CERT_MODAL_CSS = "\n:host {\n\t--cr-navy: #0a1b3f;\n\t--cr-lime: #d4e157;\n\t--cr-white: #ffffff;\n\t--cr-navy-06: rgba(10, 27, 63, 0.06);\n\t--cr-navy-10: rgba(10, 27, 63, 0.1);\n\t--cr-navy-25: rgba(10, 27, 63, 0.25);\n\t--cr-navy-40: rgba(10, 27, 63, 0.4);\n\t--cr-navy-45: rgba(10, 27, 63, 0.45);\n\t--cr-navy-50: rgba(10, 27, 63, 0.5);\n\t--cr-navy-55: rgba(10, 27, 63, 0.55);\n\t--cr-navy-60: rgba(10, 27, 63, 0.6);\n\t--cr-navy-85: rgba(10, 27, 63, 0.85);\n\t--cr-white-60: rgba(255, 255, 255, 0.6);\n\t--cr-white-85: rgba(255, 255, 255, 0.85);\n\t--cr-cta-hover: #0c2149;\n\t--cr-ghost-hover: rgba(10, 27, 63, 0.12);\n\t--cr-shadow: 0 30px 60px -18px rgba(10, 27, 63, 0.5);\n\t--cr-backdrop: rgba(10, 27, 63, 0.45);\n\t--cr-sans: 'DM Sans', system-ui, -apple-system, sans-serif;\n\t--cr-serif: 'Playfair Display', Georgia, serif;\n\t--cr-mono: 'JetBrains Mono', ui-monospace, Menlo, monospace;\n\t--cr-wordmark: 'Plus Jakarta Sans', system-ui, sans-serif;\n\t--cr-script: 'Allura', cursive;\n}\n\n.crm-dialog {\n\tborder: none;\n\tborder-radius: 14px;\n\tpadding: 0;\n\twidth: 92%;\n\tmax-height: 92vh;\n\toverflow: auto;\n\tbox-shadow: var(--cr-shadow);\n\tbackground: var(--cr-white);\n\tcolor: var(--cr-navy);\n\tfont-family: var(--cr-sans);\n\t/* fixed, NOT relative
|
|
34
|
+
export declare const CERT_MODAL_CSS = "\n:host {\n\t--cr-navy: #0a1b3f;\n\t--cr-lime: #d4e157;\n\t--cr-white: #ffffff;\n\t--cr-navy-06: rgba(10, 27, 63, 0.06);\n\t--cr-navy-10: rgba(10, 27, 63, 0.1);\n\t--cr-navy-25: rgba(10, 27, 63, 0.25);\n\t--cr-navy-40: rgba(10, 27, 63, 0.4);\n\t--cr-navy-45: rgba(10, 27, 63, 0.45);\n\t--cr-navy-50: rgba(10, 27, 63, 0.5);\n\t--cr-navy-55: rgba(10, 27, 63, 0.55);\n\t--cr-navy-60: rgba(10, 27, 63, 0.6);\n\t--cr-navy-85: rgba(10, 27, 63, 0.85);\n\t--cr-white-60: rgba(255, 255, 255, 0.6);\n\t--cr-white-85: rgba(255, 255, 255, 0.85);\n\t--cr-cta-hover: #0c2149;\n\t--cr-ghost-hover: rgba(10, 27, 63, 0.12);\n\t--cr-shadow: 0 30px 60px -18px rgba(10, 27, 63, 0.5);\n\t--cr-backdrop: rgba(10, 27, 63, 0.45);\n\t--cr-sans: 'DM Sans', system-ui, -apple-system, sans-serif;\n\t--cr-serif: 'Playfair Display', Georgia, serif;\n\t--cr-mono: 'JetBrains Mono', ui-monospace, Menlo, monospace;\n\t--cr-wordmark: 'Plus Jakarta Sans', system-ui, sans-serif;\n\t--cr-script: 'Allura', cursive;\n}\n\n.crm-dialog {\n\tborder: none;\n\tborder-radius: 14px;\n\tpadding: 0;\n\twidth: 92%;\n\tmax-height: 92vh;\n\toverflow: auto;\n\tbox-shadow: var(--cr-shadow);\n\tbackground: var(--cr-white);\n\tcolor: var(--cr-navy);\n\tfont-family: var(--cr-sans);\n\t/* fixed, NOT relative: a :modal dialog (showModal) renders in the TOP LAYER; a\n\t * relative dialog anchors to its scrolled document position, so once the page is scrolled the\n\t * panel renders off-screen while the ::backdrop still covers the viewport (measured top -1972 at\n\t * scrollY 2537). fixed is viewport-anchored (the UA inset:0 + margin:auto centers it) and still\n\t * provides the containing block for the absolutely-positioned .crm-close (x stays in-corner). */\n\tposition: fixed;\n\t/* defensive resets against a hostile brand theme reaching the top-layer dialog */\n\tbox-sizing: border-box;\n\ttext-align: left;\n\tline-height: 1.4;\n}\n.crm-dialog *,\n.crm-dialog *::before,\n.crm-dialog *::after {\n\tbox-sizing: border-box;\n}\n.crm-dialog::backdrop {\n\tbackground: var(--cr-backdrop);\n}\n.crm-dialog--cert {\n\tmax-width: 484px;\n}\n.crm-dialog--expert {\n\tmax-width: 436px;\n}\n\n/* Close (\u00D7) */\n.crm-close {\n\tposition: absolute;\n\ttop: 12px;\n\tright: 15px;\n\tz-index: 2;\n\tbackground: none;\n\tborder: none;\n\tcursor: pointer;\n\tpadding: 2px;\n\tcolor: var(--cr-white-60);\n\tfont-size: 1.35rem;\n\tline-height: 1;\n\tfont-family: var(--cr-sans);\n\ttransition: color 0.15s;\n}\n.crm-close:hover {\n\tcolor: var(--cr-white);\n}\n\n/* Header bar */\n.crm-head {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 9px;\n\tpadding: 13px 22px;\n\tbackground: var(--cr-navy);\n\tcolor: var(--cr-white);\n}\n.crm-head__eyebrow {\n\tfont-family: var(--cr-mono);\n\tfont-size: 8.5px;\n\tfont-weight: 600;\n\tletter-spacing: 0.16em;\n\ttext-transform: uppercase;\n\tcolor: var(--cr-white-85);\n}\n.crm-head__wordmark {\n\tmargin-left: auto;\n\tmargin-right: 22px;\n\tfont-family: var(--cr-wordmark);\n\tfont-weight: 800;\n\tfont-size: 13px;\n\tletter-spacing: 0.03em;\n\tcolor: var(--cr-white);\n}\n\n/* Body */\n.crm-body--cert {\n\tpadding: 24px 28px 26px;\n}\n.crm-body--expert {\n\tpadding: 22px 26px 24px;\n}\n\n/* Avatar (shared, lime ring) */\n.crm-avatar {\n\tposition: relative;\n\tflex-shrink: 0;\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n\tborder-radius: 50%;\n\tbackground: var(--cr-navy);\n\tcolor: var(--cr-white);\n\tfont-weight: 700;\n\tobject-fit: cover;\n\tbox-shadow: 0 0 0 2px var(--cr-white), 0 0 0 3.5px var(--cr-lime);\n}\n.crm-avatar--56 {\n\twidth: 56px;\n\theight: 56px;\n\tfont-size: 17px;\n}\n.crm-avatar--64 {\n\twidth: 64px;\n\theight: 64px;\n\tfont-size: 1.35rem;\n\tletter-spacing: 0.02em;\n}\n\n/* Certificate \u2014 reviewing-expert row */\n.crm-expert-row {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 14px;\n}\n.crm-expert-row__info {\n\tflex: 1;\n\tmin-width: 0;\n}\n.crm-expert-row__eyebrow {\n\tfont-family: var(--cr-mono);\n\tfont-size: 8.5px;\n\tfont-weight: 600;\n\tletter-spacing: 0.14em;\n\ttext-transform: uppercase;\n\tcolor: var(--cr-navy-45);\n}\n.crm-expert-row__name {\n\tfont-size: 15px;\n\tfont-weight: 700;\n\tcolor: var(--cr-navy);\n\tmargin-top: 2px;\n}\n.crm-expert-row__creds {\n\tfont-size: 12px;\n\tcolor: var(--cr-navy-60);\n\tmargin-top: 1px;\n}\n\n/* Certificate \u2014 \"Certifies the article\" */\n.crm-certifies {\n\tmargin: 18px 0 0;\n\tpadding-top: 16px;\n\tborder-top: 1px solid var(--cr-navy-10);\n}\n.crm-certifies__eyebrow {\n\tfont-family: var(--cr-mono);\n\tfont-size: 9px;\n\tfont-weight: 600;\n\tletter-spacing: 0.16em;\n\ttext-transform: uppercase;\n\tcolor: var(--cr-navy-40);\n}\n.crm-certifies__title {\n\tfont-family: var(--cr-serif);\n\tfont-weight: 700;\n\tfont-size: 18px;\n\tline-height: 1.25;\n\tcolor: var(--cr-navy);\n\tmargin-top: 5px;\n\ttext-wrap: balance;\n}\n\n/* Certificate \u2014 meta row */\n.crm-meta {\n\tdisplay: flex;\n\tgap: 10px;\n\tmargin-top: 16px;\n}\n.crm-meta__col {\n\tflex: 1;\n}\n.crm-meta__label {\n\tfont-family: var(--cr-mono);\n\tfont-size: 8px;\n\tletter-spacing: 0.12em;\n\ttext-transform: uppercase;\n\tcolor: var(--cr-navy-40);\n}\n.crm-meta__value {\n\tfont-size: 12.5px;\n\tfont-weight: 600;\n\tcolor: var(--cr-navy);\n\tmargin-top: 3px;\n}\n.crm-meta__value--mono {\n\tfont-family: var(--cr-mono);\n\tfont-size: 12px;\n}\n.crm-meta__status {\n\tmargin-top: 3px;\n}\n\n/* Certified chip (meta status) */\n.crm-chip {\n\tdisplay: inline-flex;\n\talign-items: center;\n\tgap: 3px;\n\tpadding: 2px 7px;\n\tborder-radius: 4px;\n\tbackground: var(--cr-lime);\n\tcolor: var(--cr-navy);\n\tfont-family: var(--cr-mono);\n\tfont-size: 8.5px;\n\tfont-weight: 700;\n\tletter-spacing: 0.06em;\n\ttext-transform: uppercase;\n}\n\n/* Certificate \u2014 signature + stamp footer */\n.crm-sig {\n\tdisplay: flex;\n\talign-items: flex-end;\n\tjustify-content: space-between;\n\tmargin-top: 20px;\n\tpadding-top: 16px;\n\tborder-top: 1px solid var(--cr-navy-10);\n\tgap: 12px;\n}\n.crm-sig__name {\n\tfont-family: var(--cr-script);\n\tfont-size: 30px;\n\tline-height: 0.9;\n\tcolor: var(--cr-navy);\n}\n.crm-sig__rule {\n\twidth: 146px;\n\tmax-width: 100%;\n\theight: 1px;\n\tbackground: var(--cr-navy-25);\n\tmargin: 4px 0 6px;\n}\n.crm-sig__url {\n\tfont-family: var(--cr-mono);\n\tfont-size: 8px;\n\tfont-weight: 500;\n\tletter-spacing: 0.12em;\n\ttext-transform: uppercase;\n\tcolor: var(--cr-navy-50);\n}\n.crm-stamp {\n\ttransform: rotate(-8deg);\n\tflex-shrink: 0;\n}\n.crm-stamp svg {\n\tdisplay: block;\n}\n\n/* Actions (shared) */\n.crm-actions {\n\tdisplay: flex;\n\tgap: 10px;\n\tmargin-top: 20px;\n}\n.crm-cta {\n\tflex: 1;\n\tdisplay: inline-block;\n\ttext-align: center;\n\tpadding: 11px 16px;\n\tbackground: var(--cr-navy);\n\tcolor: var(--cr-white);\n\ttext-decoration: none;\n\tborder-radius: 8px;\n\tfont-size: 13px;\n\tfont-weight: 600;\n\tfont-family: var(--cr-sans);\n\tborder: none;\n\tcursor: pointer;\n\ttransition: background 0.15s;\n}\n.crm-cta:hover {\n\tbackground: var(--cr-cta-hover);\n}\n.crm-ghost {\n\tpadding: 11px 18px;\n\tbackground: var(--cr-navy-06);\n\tcolor: var(--cr-navy);\n\tborder: none;\n\tborder-radius: 8px;\n\tfont-size: 13px;\n\tfont-weight: 600;\n\tfont-family: var(--cr-sans);\n\tcursor: pointer;\n\ttransition: background 0.15s;\n}\n.crm-ghost:hover {\n\tbackground: var(--cr-ghost-hover);\n}\n\n/* Reviewer \u2014 identity row */\n.crm-id {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 14px;\n}\n.crm-id__info {\n\tmin-width: 0;\n}\n.crm-id__name {\n\tfont-size: 16px;\n\tfont-weight: 700;\n\tline-height: 1.25;\n\tcolor: var(--cr-navy);\n}\n.crm-id__subtitle {\n\tfont-size: 12.5px;\n\tline-height: 1.4;\n\tcolor: var(--cr-navy-60);\n\tmargin-top: 2px;\n}\n\n/* Reviewer \u2014 credential chips */\n.crm-chips {\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\tgap: 7px;\n\tmargin-top: 16px;\n}\n.crm-chips__chip {\n\tdisplay: inline-flex;\n\talign-items: center;\n\tpadding: 4px 10px;\n\tborder-radius: 999px;\n\tbackground: var(--cr-navy-06);\n\tcolor: var(--cr-navy);\n\tfont-size: 11px;\n\tfont-weight: 600;\n}\n\n/* Reviewer \u2014 bio */\n.crm-bio {\n\tmargin: 16px 0 0;\n\tfont-size: 0.9rem;\n\tline-height: 1.55;\n\tcolor: var(--cr-navy-85);\n}\n\n/* Reviewer \u2014 trust line (the disclosure footer below now owns the spacing to the actions) */\n.crm-trust {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 9px;\n\tflex-wrap: wrap;\n\tmargin: 16px 0 0;\n\tpadding-top: 16px;\n\tborder-top: 1px solid var(--cr-navy-10);\n}\n.crm-trust__chip {\n\tdisplay: inline-flex;\n\talign-items: center;\n\tgap: 4px;\n\tpadding: 3px 8px;\n\tborder-radius: 4px;\n\tbackground: var(--cr-lime);\n\tcolor: var(--cr-navy);\n\tfont-family: var(--cr-mono);\n\tfont-size: 8.5px;\n\tfont-weight: 700;\n\tletter-spacing: 0.08em;\n\ttext-transform: uppercase;\n}\n.crm-trust__text {\n\tfont-family: var(--cr-mono);\n\tfont-size: 9px;\n\tletter-spacing: 0.05em;\n\tcolor: var(--cr-navy-50);\n}\n\n/* FTC disclosure footer \u2014 material-connection cue (compensated only) + scope line\n * (always). Rendered on both the certificate + reviewer dialogs, immediately above the actions. */\n.crm-disclosure {\n\tmargin-top: 14px;\n\tpadding-top: 14px;\n\tborder-top: 1px solid var(--cr-navy-10);\n\tfont-family: var(--cr-sans);\n\tfont-size: 11.5px;\n\tline-height: 1.5;\n\tcolor: var(--cr-navy-50);\n}\n.crm-disclosure__cue {\n\tfont-family: var(--cr-mono);\n\tfont-size: 10px;\n\tfont-weight: 700;\n\tletter-spacing: 0.06em;\n\ttext-transform: uppercase;\n\tcolor: var(--cr-navy);\n}\n\n/* Narrow storefronts / phones */\n@media (max-width: 440px) {\n\t.crm-body--cert {\n\t\tpadding: 20px 18px 22px;\n\t}\n\t.crm-body--expert {\n\t\tpadding: 18px 18px 20px;\n\t}\n}\n";
|
|
35
35
|
//# sourceMappingURL=certrev-cert-modal.styles.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"certrev-cert-modal.styles.d.ts","sourceRoot":"","sources":["../../src/modal/certrev-cert-modal.styles.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"certrev-cert-modal.styles.d.ts","sourceRoot":"","sources":["../../src/modal/certrev-cert-modal.styles.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH;;kBAEkB;AAClB,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAG9D;AAED,yDAAyD;AACzD,wBAAgB,SAAS,CAAC,IAAI,SAAI,GAAG,MAAM,CAE1C;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,QAAQ,SAAQ,GAAG,MAAM,CAItD;AAED;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,2FAM3B,CAAA;AAOV,+EAA+E;AAC/E,eAAO,MAAM,cAAc,w/SAib1B,CAAA"}
|