@certrev/cert-block 0.5.5 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (190) hide show
  1. package/CHANGELOG.md +189 -25
  2. package/LICENSE +21 -0
  3. package/README.md +415 -54
  4. package/dist/builder/cert-chrome-data.d.ts +26 -8
  5. package/dist/builder/cert-chrome-data.d.ts.map +1 -1
  6. package/dist/builder/cert-chrome-data.js +5 -5
  7. package/dist/builder/cert-chrome-data.js.map +1 -1
  8. package/dist/builder/cert-review-card.d.ts +35 -5
  9. package/dist/builder/cert-review-card.d.ts.map +1 -1
  10. package/dist/builder/cert-review-card.js +117 -34
  11. package/dist/builder/cert-review-card.js.map +1 -1
  12. package/dist/builder/index.d.ts +33 -16
  13. package/dist/builder/index.d.ts.map +1 -1
  14. package/dist/builder/index.js +33 -16
  15. package/dist/builder/index.js.map +1 -1
  16. package/dist/components/CertBadge.d.ts +2 -2
  17. package/dist/components/CertBadge.d.ts.map +1 -1
  18. package/dist/components/CertBadge.js +11 -5
  19. package/dist/components/CertBadge.js.map +1 -1
  20. package/dist/components/CertJsonLd.d.ts.map +1 -1
  21. package/dist/components/CertJsonLd.js.map +1 -1
  22. package/dist/components/CertRevBacklink.d.ts.map +1 -1
  23. package/dist/components/CertRevBacklink.js +3 -2
  24. package/dist/components/CertRevBacklink.js.map +1 -1
  25. package/dist/components/CertReview.d.ts +1 -1
  26. package/dist/components/ExpertBio.d.ts.map +1 -1
  27. package/dist/components/ExpertBio.js +12 -4
  28. package/dist/components/ExpertBio.js.map +1 -1
  29. package/dist/components/escape.d.ts +28 -1
  30. package/dist/components/escape.d.ts.map +1 -1
  31. package/dist/components/escape.js +37 -8
  32. package/dist/components/escape.js.map +1 -1
  33. package/dist/components/format.d.ts +51 -2
  34. package/dist/components/format.d.ts.map +1 -1
  35. package/dist/components/format.js +103 -6
  36. package/dist/components/format.js.map +1 -1
  37. package/dist/components/preview-block.d.ts +1 -1
  38. package/dist/components/preview-block.js +3 -3
  39. package/dist/components/preview-block.js.map +1 -1
  40. package/dist/components/rel.d.ts +24 -0
  41. package/dist/components/rel.d.ts.map +1 -0
  42. package/dist/components/rel.js +24 -0
  43. package/dist/components/rel.js.map +1 -0
  44. package/dist/components/render-cert-block.d.ts +50 -22
  45. package/dist/components/render-cert-block.d.ts.map +1 -1
  46. package/dist/components/render-cert-block.js +146 -80
  47. package/dist/components/render-cert-block.js.map +1 -1
  48. package/dist/components/render-def.d.ts +13 -14
  49. package/dist/components/render-def.d.ts.map +1 -1
  50. package/dist/components/render-def.js +14 -15
  51. package/dist/components/render-def.js.map +1 -1
  52. package/dist/index.d.ts +1 -0
  53. package/dist/index.d.ts.map +1 -1
  54. package/dist/index.js +4 -2
  55. package/dist/index.js.map +1 -1
  56. package/dist/jsonld/project.d.ts +46 -13
  57. package/dist/jsonld/project.d.ts.map +1 -1
  58. package/dist/jsonld/project.js +139 -56
  59. package/dist/jsonld/project.js.map +1 -1
  60. package/dist/modal/avatar-resize.d.ts +10 -10
  61. package/dist/modal/avatar-resize.js +14 -14
  62. package/dist/modal/avatar-resize.js.map +1 -1
  63. package/dist/modal/cert-modal-view.d.ts +27 -7
  64. package/dist/modal/cert-modal-view.d.ts.map +1 -1
  65. package/dist/modal/cert-modal-view.js +49 -25
  66. package/dist/modal/cert-modal-view.js.map +1 -1
  67. package/dist/modal/certrev-cert-modal.d.ts +5 -5
  68. package/dist/modal/certrev-cert-modal.js +9 -9
  69. package/dist/modal/certrev-cert-modal.js.map +1 -1
  70. package/dist/modal/certrev-cert-modal.styles.d.ts +6 -6
  71. package/dist/modal/certrev-cert-modal.styles.d.ts.map +1 -1
  72. package/dist/modal/certrev-cert-modal.styles.js +8 -8
  73. package/dist/modal/certrev-cert-modal.styles.js.map +1 -1
  74. package/dist/modal/certrev-cert.entry.d.ts +8 -6
  75. package/dist/modal/certrev-cert.entry.d.ts.map +1 -1
  76. package/dist/modal/certrev-cert.entry.js +9 -7
  77. package/dist/modal/certrev-cert.entry.js.map +1 -1
  78. package/dist/modal/certrev-cert.js +6 -6
  79. package/dist/modal/display-strings.d.ts +25 -5
  80. package/dist/modal/display-strings.d.ts.map +1 -1
  81. package/dist/modal/display-strings.js +27 -5
  82. package/dist/modal/display-strings.js.map +1 -1
  83. package/dist/modal/escape.d.ts +26 -3
  84. package/dist/modal/escape.d.ts.map +1 -1
  85. package/dist/modal/escape.js +32 -3
  86. package/dist/modal/escape.js.map +1 -1
  87. package/dist/modal/font-face.d.ts.map +1 -1
  88. package/dist/modal/font-face.js +8 -11
  89. package/dist/modal/font-face.js.map +1 -1
  90. package/dist/modal/ftc-disclosure.d.ts +2 -2
  91. package/dist/modal/ftc-disclosure.js +2 -2
  92. package/dist/modal/ftc-guard.d.ts +44 -9
  93. package/dist/modal/ftc-guard.d.ts.map +1 -1
  94. package/dist/modal/ftc-guard.js +50 -17
  95. package/dist/modal/ftc-guard.js.map +1 -1
  96. package/dist/modal/index.d.ts +1 -1
  97. package/dist/modal/index.js +1 -1
  98. package/dist/modal/interactions.d.ts +2 -2
  99. package/dist/modal/interactions.js +2 -2
  100. package/dist/modal/logo-paths.js +2 -2
  101. package/dist/modal/logo-paths.js.map +1 -1
  102. package/dist/modal/placement.d.ts +4 -3
  103. package/dist/modal/placement.d.ts.map +1 -1
  104. package/dist/modal/placement.js +7 -6
  105. package/dist/modal/placement.js.map +1 -1
  106. package/dist/modal/revalidate.d.ts +2 -3
  107. package/dist/modal/revalidate.d.ts.map +1 -1
  108. package/dist/modal/revalidate.js +2 -3
  109. package/dist/modal/revalidate.js.map +1 -1
  110. package/dist/modal/verify-client.d.ts +2 -2
  111. package/dist/modal/verify-client.js +2 -2
  112. package/dist/verify/cache.d.ts +21 -6
  113. package/dist/verify/cache.d.ts.map +1 -1
  114. package/dist/verify/cache.js +29 -8
  115. package/dist/verify/cache.js.map +1 -1
  116. package/dist/verify/fetch-with-deadline.d.ts +35 -0
  117. package/dist/verify/fetch-with-deadline.d.ts.map +1 -0
  118. package/dist/verify/fetch-with-deadline.js +55 -0
  119. package/dist/verify/fetch-with-deadline.js.map +1 -0
  120. package/dist/verify/get-verified-envelope.d.ts +23 -9
  121. package/dist/verify/get-verified-envelope.d.ts.map +1 -1
  122. package/dist/verify/get-verified-envelope.js +89 -40
  123. package/dist/verify/get-verified-envelope.js.map +1 -1
  124. package/dist/verify/resolve-kid.d.ts +3 -0
  125. package/dist/verify/resolve-kid.d.ts.map +1 -1
  126. package/dist/verify/resolve-kid.js +17 -8
  127. package/dist/verify/resolve-kid.js.map +1 -1
  128. package/dist/webcomponent/certrev-badge.d.ts.map +1 -1
  129. package/dist/webcomponent/certrev-badge.js +24 -2
  130. package/dist/webcomponent/certrev-badge.js.map +1 -1
  131. package/dist/webcomponent/render-badge-html.d.ts +1 -1
  132. package/dist/webcomponent/render-badge-html.d.ts.map +1 -1
  133. package/dist/webcomponent/render-badge-html.js +36 -17
  134. package/dist/webcomponent/render-badge-html.js.map +1 -1
  135. package/package.json +5 -2
  136. package/src/builder/cert-chrome-data.ts +26 -8
  137. package/src/builder/cert-review-card.tsx +149 -38
  138. package/src/builder/index.tsx +34 -17
  139. package/src/components/CertBadge.tsx +14 -9
  140. package/src/components/CertJsonLd.tsx +1 -1
  141. package/src/components/CertRevBacklink.tsx +10 -3
  142. package/src/components/CertReview.tsx +1 -1
  143. package/src/components/ExpertBio.tsx +15 -8
  144. package/src/components/escape.ts +37 -7
  145. package/src/components/format.ts +102 -6
  146. package/src/components/preview-block.ts +3 -3
  147. package/src/components/rel.ts +23 -0
  148. package/src/components/render-cert-block.ts +192 -109
  149. package/src/components/render-def.ts +14 -15
  150. package/src/index.ts +4 -2
  151. package/src/jsonld/project.ts +155 -59
  152. package/src/modal/avatar-resize.ts +14 -14
  153. package/src/modal/cert-modal-view.ts +52 -27
  154. package/src/modal/certrev-cert-modal.styles.ts +8 -8
  155. package/src/modal/certrev-cert-modal.ts +9 -9
  156. package/src/modal/certrev-cert.entry.ts +9 -7
  157. package/src/modal/display-strings.ts +26 -5
  158. package/src/modal/escape.ts +32 -4
  159. package/src/modal/font-face.ts +8 -11
  160. package/src/modal/ftc-disclosure.ts +2 -2
  161. package/src/modal/ftc-guard.ts +73 -18
  162. package/src/modal/index.ts +1 -1
  163. package/src/modal/interactions.ts +2 -2
  164. package/src/modal/logo-paths.ts +2 -2
  165. package/src/modal/placement.ts +7 -6
  166. package/src/modal/revalidate.ts +2 -3
  167. package/src/modal/verify-client.ts +2 -2
  168. package/src/verify/cache.ts +34 -8
  169. package/src/verify/fetch-with-deadline.ts +60 -0
  170. package/src/verify/get-verified-envelope.ts +131 -48
  171. package/src/verify/resolve-kid.ts +22 -6
  172. package/src/webcomponent/certrev-badge.ts +24 -2
  173. package/src/webcomponent/render-badge-html.ts +66 -19
  174. package/src/__tests__/__snapshots__/render-cert-block.test.ts.snap +0 -17
  175. package/src/__tests__/components.test.tsx +0 -206
  176. package/src/__tests__/preview-block.test.ts +0 -84
  177. package/src/__tests__/project.test.ts +0 -128
  178. package/src/__tests__/readme-version.test.ts +0 -51
  179. package/src/__tests__/render-cert-block.test.ts +0 -657
  180. package/src/__tests__/render-def.test.tsx +0 -295
  181. package/src/__tests__/verify.test.ts +0 -239
  182. package/src/__tests__/webcomponent.test.tsx +0 -116
  183. package/src/builder/__tests__/builder.test.tsx +0 -158
  184. package/src/modal/cert-modal-view.test.ts +0 -175
  185. package/src/modal/certrev-cert-modal.test.ts +0 -125
  186. package/src/modal/ftc-guard.test.ts +0 -153
  187. package/src/modal/interactions.test.ts +0 -250
  188. package/src/modal/placement.test.ts +0 -398
  189. package/src/modal/revalidate.test.ts +0 -111
  190. package/src/modal/verify-client.test.ts +0 -164
@@ -4,19 +4,18 @@
4
4
  * layer) + the two always-on COMPLIANCE strings.
5
5
  * ─────────────────────────────────────────────────────────────────────────────
6
6
  *
7
- * WS6 of the unified cert-render / design-guide build
8
- * (~/.claude-account-m/plans/smooth-meandering-graham.md). This is the Builder /
9
- * headless projection twin's half of the "law-as-code" contract: cert-block is one
10
- * of the four render surfaces (Shopify Liquid, WordPress PHP, JS engine, and this)
11
- * that must paint the SAME compliant, optionally-themed badge from the SAME facts.
7
+ * This is the Builder / headless projection twin's half of the "law-as-code"
8
+ * contract: cert-block is one of the four render surfaces (Shopify Liquid,
9
+ * WordPress PHP, JS engine, and this) that must paint the SAME compliant,
10
+ * optionally-themed badge from the SAME facts.
12
11
  *
13
12
  * cert-block is a self-contained npm package — it does NOT import the portal's
14
- * `@/lib/design-guide` enforcement core. Instead it mirrors, at the RENDER edge,
15
- * the small subset that shape the projection carries:
13
+ * design-guide enforcement core. Instead it mirrors, at the RENDER edge, the
14
+ * small subset that shape the projection carries:
16
15
  *
17
16
  * 1. The four allowlisted THEMEABLE tokens `{accentColor, surface, cornerRadius,
18
17
  * fontSlot}`, emitted as the exact `--certrev-*` CSS custom properties the
19
- * Shopify/WordPress engines emit and the WS11 crawl monitor asserts
18
+ * Shopify/WordPress engines emit and the crawl monitor asserts
20
19
  * (`--certrev-accent` / `--certrev-surface` / `--certrev-radius` /
21
20
  * `--certrev-font`). Each is RE-VALIDATED here at render time (defense in
22
21
  * depth over the write-path fail-closed gate) against the SAME strict
@@ -41,16 +40,16 @@
41
40
  * entry targets (edge / Workers / server / client).
42
41
  */
43
42
  // ─────────────────────────────────────────────────────────────────────────────
44
- // Themeable token vocabulary (mirrors portal src/lib/design-guide/tokens.ts)
43
+ // Themeable token vocabulary (mirrors the portal's design-guide token module)
45
44
  // ─────────────────────────────────────────────────────────────────────────────
46
45
  /** The font ENUM. Resolves to a FIXED slot stack — never a free-form family. */
47
46
  export const FONT_SLOTS = ['sans', 'serif', 'system', 'grotesk', 'mono'];
48
47
  /**
49
48
  * The `fontSlot` → fixed font-stack literal — the render-def theme map the webcomponent MODAL
50
49
  * (`resolveRenderTheme` → `renderBadgeHtml`) and the legacy `<CertBadge>` resolve. The three original
51
- * slots (sans/serif/system) stay BYTE-IDENTICAL to the Shopify Liquid engine's stacks
52
- * (`shopify/extensions/certrev-schema/snippets/certrev-badge.liquid`), so a themed brand's popup modal
53
- * and its inline Liquid card paint the same typography — the load-bearing card==modal invariant.
50
+ * slots (sans/serif/system) stay BYTE-IDENTICAL to the Shopify Liquid engine's badge-snippet
51
+ * stacks, so a themed brand's popup modal and its inline Liquid card paint the same
52
+ * typography — the load-bearing card==modal invariant.
54
53
  * grotesk (Plus Jakarta Sans) + mono (JetBrains Mono) are ADDED at the shared guide values —
55
54
  * byte-identical to portal `FONT_SLOT_STACKS`, this package's `RENDER_BLOCK_FONT_STACKS`, and the
56
55
  * Liquid twin's added branches — so card == modal holds for them too. A raw family string in a
@@ -139,8 +138,8 @@ export function isFieldHidden(def, id) {
139
138
  // sans/serif/system to the legacy Liquid table (the card==modal invariant) while this
140
139
  // map pins them to the guide table; grotesk/mono are byte-identical across both.
141
140
  /**
142
- * The full portal font-slot enum (mirrors portal `src/lib/design-guide/tokens.ts`
143
- * `FONT_SLOTS`). `grotesk` ⇐ the guide's wordmark slot; `mono` ⇐ the label slot.
141
+ * The full portal font-slot enum (mirrors the portal design-guide's `FONT_SLOTS`).
142
+ * `grotesk` ⇐ the guide's wordmark slot; `mono` ⇐ the label slot.
144
143
  */
145
144
  export const RENDER_BLOCK_FONT_SLOTS = ['sans', 'serif', 'system', 'grotesk', 'mono'];
146
145
  /**
@@ -177,7 +176,7 @@ function parseHexColor(hex) {
177
176
  }
178
177
  /**
179
178
  * AUTO-CONTRAST PICKER — the ink painted over an opaque fill. BYTE-FAITHFUL to the portal's
180
- * `accentFg` (src/lib/design-guide/tokens.ts): Rec.601 perceptual luma with a strict `> 0.62`
179
+ * design-guide `accentFg`: Rec.601 perceptual luma with a strict `> 0.62`
181
180
  * cutoff, returning EXACTLY `#141414` (near-black) or `#ffffff`; an unparseable value falls back
182
181
  * to the dark ink (safe default). Used at the render edge to DERIVE `barInkFg` from a themed
183
182
  * `barInk` (v2 Phase 1), so the bar foreground always clears its own fill with no separate stored
@@ -1 +1 @@
1
- {"version":3,"file":"render-def.js","sourceRoot":"","sources":["../../src/components/render-def.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"render-def.js","sourceRoot":"","sources":["../../src/components/render-def.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -27,6 +27,7 @@ export { ExpertBio, type ExpertBioProps } from './components/ExpertBio.js';
27
27
  export { escapeAttribute, escapeHtml, safeCssColor, safeHttpUrl, tidyText } from './components/escape.js';
28
28
  export { credentialSuffix, DEFAULT_ACCENT, expertNameWithCredentials, formatDate, type ResolvedDisplay, resolveDisplay, } from './components/format.js';
29
29
  export { type PreviewBlockOptions, previewExpiry, renderPreviewBlock, } from './components/preview-block.js';
30
+ export { CERTREV_LINK_REL } from './components/rel.js';
30
31
  export { type CertBlockFace, type CertBlockFacts, type CertBlockLayout, type CertBlockMode, type RenderCertBlockInput, renderCertBlock, } from './components/render-cert-block.js';
31
32
  export { accentFg, type BadgeVisibilityFieldId, CERT_SCOPE_LINE, CERT_STRINGS_VERSION, type CertRenderDef, type CertThemeTokens, COMPENSATED_EXPERT_CUE, CREDENTIAL_VERIFIED_ATTRIBUTION, DEFAULT_BLOCK_THEME, FONT_SLOTS, FONT_STACKS, type FontSlot, HIDEABLE_FIELDS, isCornerRadius, isFieldHidden, isFontSlot, isOpaqueHexColor, isRenderBlockFontSlot, RENDER_BLOCK_FONT_SLOTS, RENDER_BLOCK_FONT_STACKS, type RenderBlockFontSlot, type ResolvedBlockTheme, type ResolvedRenderTheme, resolveBlockTheme, resolveRenderTheme, themeCssVarDeclarations, } from './components/render-def.js';
32
33
  export { CANONICALIZATION, type CertContent, type CertCredential, type CertDeliveryEnvelope, type CertDisplayConfig, type CertLifecycle, type CertPayload, type CertSignature, type CertSubject, type CertSuppressReason, type CertVerdict, CONTRACT_VERSION, type ContractVersion, type Ed25519PublicKeyInput, type RenderContext, type ResolvePublicKeyByKid, renderVerdict, SIGNATURE_ALG, type SignatureAlg, type VerdictKernel, verifyEnvelope, verifySignatureOnly, } from './contract/kernel.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAGH,OAAO,EAAE,SAAS,EAAE,KAAK,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAC1E,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,4BAA4B,CAAA;AAC7E,OAAO,EAAE,eAAe,EAAE,KAAK,oBAAoB,EAAE,MAAM,iCAAiC,CAAA;AAC5F,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,4BAA4B,CAAA;AAC7E,OAAO,EAAE,SAAS,EAAE,KAAK,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAC1E,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AAEzG,OAAO,EACN,gBAAgB,EAChB,cAAc,EACd,yBAAyB,EACzB,UAAU,EACV,KAAK,eAAe,EACpB,cAAc,GACd,MAAM,wBAAwB,CAAA;AAE/B,OAAO,EACN,KAAK,mBAAmB,EACxB,aAAa,EACb,kBAAkB,GAClB,MAAM,+BAA+B,CAAA;AAEtC,OAAO,EACN,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,oBAAoB,EACzB,eAAe,GACf,MAAM,mCAAmC,CAAA;AAE1C,OAAO,EACN,QAAQ,EACR,KAAK,sBAAsB,EAC3B,eAAe,EACf,oBAAoB,EACpB,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,sBAAsB,EACtB,+BAA+B,EAC/B,mBAAmB,EACnB,UAAU,EACV,WAAW,EACX,KAAK,QAAQ,EACb,eAAe,EACf,cAAc,EACd,aAAa,EACb,UAAU,EACV,gBAAgB,EAChB,qBAAqB,EACrB,uBAAuB,EACvB,wBAAwB,EACxB,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,iBAAiB,EACjB,kBAAkB,EAClB,uBAAuB,GACvB,MAAM,4BAA4B,CAAA;AAInC,OAAO,EACN,gBAAgB,EAChB,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,oBAAoB,EACzB,KAAK,iBAAiB,EACtB,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,kBAAkB,EACvB,KAAK,WAAW,EAChB,gBAAgB,EAChB,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,KAAK,aAAa,EAClB,KAAK,qBAAqB,EAC1B,aAAa,EACb,aAAa,EACb,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,cAAc,EACd,mBAAmB,GACnB,MAAM,sBAAsB,CAAA;AAE7B,OAAO,EACN,KAAK,WAAW,EAChB,KAAK,oBAAoB,EACzB,iBAAiB,EACjB,uBAAuB,EACvB,wBAAwB,GACxB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EAAE,QAAQ,EAAE,KAAK,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAElE,OAAO,EACN,KAAK,cAAc,EACnB,KAAK,0BAA0B,EAC/B,mBAAmB,EACnB,iBAAiB,EACjB,kBAAkB,GAClB,MAAM,mCAAmC,CAAA;AAC1C,OAAO,EACN,KAAK,0BAA0B,EAC/B,mBAAmB,EACnB,KAAK,YAAY,EACjB,iBAAiB,GACjB,MAAM,yBAAyB,CAAA;AAEhC,OAAO,EAAE,KAAK,kBAAkB,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAGH,OAAO,EAAE,SAAS,EAAE,KAAK,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAC1E,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,4BAA4B,CAAA;AAC7E,OAAO,EAAE,eAAe,EAAE,KAAK,oBAAoB,EAAE,MAAM,iCAAiC,CAAA;AAC5F,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,4BAA4B,CAAA;AAC7E,OAAO,EAAE,SAAS,EAAE,KAAK,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAC1E,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AAEzG,OAAO,EACN,gBAAgB,EAChB,cAAc,EACd,yBAAyB,EACzB,UAAU,EACV,KAAK,eAAe,EACpB,cAAc,GACd,MAAM,wBAAwB,CAAA;AAE/B,OAAO,EACN,KAAK,mBAAmB,EACxB,aAAa,EACb,kBAAkB,GAClB,MAAM,+BAA+B,CAAA;AAEtC,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AAEtD,OAAO,EACN,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,oBAAoB,EACzB,eAAe,GACf,MAAM,mCAAmC,CAAA;AAE1C,OAAO,EACN,QAAQ,EACR,KAAK,sBAAsB,EAC3B,eAAe,EACf,oBAAoB,EACpB,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,sBAAsB,EACtB,+BAA+B,EAC/B,mBAAmB,EACnB,UAAU,EACV,WAAW,EACX,KAAK,QAAQ,EACb,eAAe,EACf,cAAc,EACd,aAAa,EACb,UAAU,EACV,gBAAgB,EAChB,qBAAqB,EACrB,uBAAuB,EACvB,wBAAwB,EACxB,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,iBAAiB,EACjB,kBAAkB,EAClB,uBAAuB,GACvB,MAAM,4BAA4B,CAAA;AAInC,OAAO,EACN,gBAAgB,EAChB,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,oBAAoB,EACzB,KAAK,iBAAiB,EACtB,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,kBAAkB,EACvB,KAAK,WAAW,EAChB,gBAAgB,EAChB,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,KAAK,aAAa,EAClB,KAAK,qBAAqB,EAC1B,aAAa,EACb,aAAa,EACb,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,cAAc,EACd,mBAAmB,GACnB,MAAM,sBAAsB,CAAA;AAE7B,OAAO,EACN,KAAK,WAAW,EAChB,KAAK,oBAAoB,EACzB,iBAAiB,EACjB,uBAAuB,EACvB,wBAAwB,GACxB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EAAE,QAAQ,EAAE,KAAK,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAElE,OAAO,EACN,KAAK,cAAc,EACnB,KAAK,0BAA0B,EAC/B,mBAAmB,EACnB,iBAAiB,EACjB,kBAAkB,GAClB,MAAM,mCAAmC,CAAA;AAC1C,OAAO,EACN,KAAK,0BAA0B,EAC/B,mBAAmB,EACnB,KAAK,YAAY,EACjB,iBAAiB,GACjB,MAAM,yBAAyB,CAAA;AAEhC,OAAO,EAAE,KAAK,kBAAkB,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAA"}
package/dist/index.js CHANGED
@@ -28,11 +28,13 @@ export { ExpertBio } from './components/ExpertBio.js';
28
28
  export { escapeAttribute, escapeHtml, safeCssColor, safeHttpUrl, tidyText } from './components/escape.js';
29
29
  // ── Presentation helpers (shared with the Web Component) ────────────────────────────
30
30
  export { credentialSuffix, DEFAULT_ACCENT, expertNameWithCredentials, formatDate, resolveDisplay, } from './components/format.js';
31
- // ── Pre-sales PREVIEW block — static, non-delivery, hard-bounded (POR-10743) ──
31
+ // ── Pre-sales PREVIEW block — static, non-delivery, hard-bounded ──
32
32
  export { previewExpiry, renderPreviewBlock, } from './components/preview-block.js';
33
+ // ── Link qualification — the `rel` every anchor this package emits carries (read-only) ──
34
+ export { CERTREV_LINK_REL } from './components/rel.js';
33
35
  // ── Cert-render BLOCK — the LOCKED 3-mode cert design as an SSR-safe HTML string ──
34
36
  export { renderCertBlock, } from './components/render-cert-block.js';
35
- // ── Design-guide render-def support (WS6: themeable tokens + subtractive visibility) ──
37
+ // ── Design-guide render-def support (themeable tokens + subtractive visibility) ──
36
38
  export { accentFg, CERT_SCOPE_LINE, CERT_STRINGS_VERSION, COMPENSATED_EXPERT_CUE, CREDENTIAL_VERIFIED_ATTRIBUTION, DEFAULT_BLOCK_THEME, FONT_SLOTS, FONT_STACKS, HIDEABLE_FIELDS, isCornerRadius, isFieldHidden, isFontSlot, isOpaqueHexColor, isRenderBlockFontSlot, RENDER_BLOCK_FONT_SLOTS, RENDER_BLOCK_FONT_STACKS, resolveBlockTheme, resolveRenderTheme, themeCssVarDeclarations, } from './components/render-def.js';
37
39
  // ── Contract surface (types + kernel) — re-export the binding point ────────────────
38
40
  // NOTE: the test/dev fixtures (makeSignedEnvelope, makeMockPayload, FIXTURE_KID) are
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,qFAAqF;AACrF,OAAO,EAAE,SAAS,EAAuB,MAAM,2BAA2B,CAAA;AAC1E,OAAO,EAAE,UAAU,EAAwB,MAAM,4BAA4B,CAAA;AAC7E,OAAO,EAAE,eAAe,EAA6B,MAAM,iCAAiC,CAAA;AAC5F,OAAO,EAAE,UAAU,EAAwB,MAAM,4BAA4B,CAAA;AAC7E,OAAO,EAAE,SAAS,EAAuB,MAAM,2BAA2B,CAAA;AAC1E,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AACzG,uFAAuF;AACvF,OAAO,EACN,gBAAgB,EAChB,cAAc,EACd,yBAAyB,EACzB,UAAU,EAEV,cAAc,GACd,MAAM,wBAAwB,CAAA;AAC/B,iFAAiF;AACjF,OAAO,EAEN,aAAa,EACb,kBAAkB,GAClB,MAAM,+BAA+B,CAAA;AACtC,qFAAqF;AACrF,OAAO,EAMN,eAAe,GACf,MAAM,mCAAmC,CAAA;AAC1C,yFAAyF;AACzF,OAAO,EACN,QAAQ,EAER,eAAe,EACf,oBAAoB,EAGpB,sBAAsB,EACtB,+BAA+B,EAC/B,mBAAmB,EACnB,UAAU,EACV,WAAW,EAEX,eAAe,EACf,cAAc,EACd,aAAa,EACb,UAAU,EACV,gBAAgB,EAChB,qBAAqB,EACrB,uBAAuB,EACvB,wBAAwB,EAIxB,iBAAiB,EACjB,kBAAkB,EAClB,uBAAuB,GACvB,MAAM,4BAA4B,CAAA;AACnC,sFAAsF;AACtF,qFAAqF;AACrF,2FAA2F;AAC3F,OAAO,EACN,gBAAgB,EAWhB,gBAAgB,EAKhB,aAAa,EACb,aAAa,EAGb,cAAc,EACd,mBAAmB,GACnB,MAAM,sBAAsB,CAAA;AAC7B,uFAAuF;AACvF,OAAO,EAGN,iBAAiB,EACjB,uBAAuB,EACvB,wBAAwB,GACxB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EAAE,QAAQ,EAAwB,MAAM,mBAAmB,CAAA;AAClE,qFAAqF;AACrF,OAAO,EAGN,mBAAmB,EACnB,iBAAiB,EACjB,kBAAkB,GAClB,MAAM,mCAAmC,CAAA;AAC1C,OAAO,EAEN,mBAAmB,EAEnB,iBAAiB,GACjB,MAAM,yBAAyB,CAAA;AAChC,sFAAsF;AACtF,OAAO,EAA2B,eAAe,EAAE,MAAM,qCAAqC,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,qFAAqF;AACrF,OAAO,EAAE,SAAS,EAAuB,MAAM,2BAA2B,CAAA;AAC1E,OAAO,EAAE,UAAU,EAAwB,MAAM,4BAA4B,CAAA;AAC7E,OAAO,EAAE,eAAe,EAA6B,MAAM,iCAAiC,CAAA;AAC5F,OAAO,EAAE,UAAU,EAAwB,MAAM,4BAA4B,CAAA;AAC7E,OAAO,EAAE,SAAS,EAAuB,MAAM,2BAA2B,CAAA;AAC1E,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AACzG,uFAAuF;AACvF,OAAO,EACN,gBAAgB,EAChB,cAAc,EACd,yBAAyB,EACzB,UAAU,EAEV,cAAc,GACd,MAAM,wBAAwB,CAAA;AAC/B,qEAAqE;AACrE,OAAO,EAEN,aAAa,EACb,kBAAkB,GAClB,MAAM,+BAA+B,CAAA;AACtC,2FAA2F;AAC3F,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AACtD,qFAAqF;AACrF,OAAO,EAMN,eAAe,GACf,MAAM,mCAAmC,CAAA;AAC1C,oFAAoF;AACpF,OAAO,EACN,QAAQ,EAER,eAAe,EACf,oBAAoB,EAGpB,sBAAsB,EACtB,+BAA+B,EAC/B,mBAAmB,EACnB,UAAU,EACV,WAAW,EAEX,eAAe,EACf,cAAc,EACd,aAAa,EACb,UAAU,EACV,gBAAgB,EAChB,qBAAqB,EACrB,uBAAuB,EACvB,wBAAwB,EAIxB,iBAAiB,EACjB,kBAAkB,EAClB,uBAAuB,GACvB,MAAM,4BAA4B,CAAA;AACnC,sFAAsF;AACtF,qFAAqF;AACrF,2FAA2F;AAC3F,OAAO,EACN,gBAAgB,EAWhB,gBAAgB,EAKhB,aAAa,EACb,aAAa,EAGb,cAAc,EACd,mBAAmB,GACnB,MAAM,sBAAsB,CAAA;AAC7B,uFAAuF;AACvF,OAAO,EAGN,iBAAiB,EACjB,uBAAuB,EACvB,wBAAwB,GACxB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EAAE,QAAQ,EAAwB,MAAM,mBAAmB,CAAA;AAClE,qFAAqF;AACrF,OAAO,EAGN,mBAAmB,EACnB,iBAAiB,EACjB,kBAAkB,GAClB,MAAM,mCAAmC,CAAA;AAC1C,OAAO,EAEN,mBAAmB,EAEnB,iBAAiB,GACjB,MAAM,yBAAyB,CAAA;AAChC,sFAAsF;AACtF,OAAO,EAA2B,eAAe,EAAE,MAAM,qCAAqC,CAAA"}
@@ -9,31 +9,49 @@
9
9
  * server pre-render) produce the same structured data, and a snapshot diff is meaningful.
10
10
  *
11
11
  * DESIGN GOAL: MERGE, don't collide.
12
- * A brand page usually already emits an `Article` (or `BlogPosting`) graph — Yoast on
13
- * WordPress, the theme on Shopify, the framework on headless. If we emit a SECOND
14
- * top-level `Article`, crawlers see two competing primary entities. Instead we emit a
15
- * `@graph` whose Article node carries the SAME `@id` the page's primary article uses
16
- * (the page URL + `#article`, the Yoast convention) so a consumer MERGES our
17
- * `reviewedBy` / `dateModified` into the existing node by `@id` rather than duplicating
18
- * it. Our own nodes (the review, the expert Person, the CertREV org) use CertREV-scoped
19
- * `@id`s that cannot clash with the host page's nodes.
12
+ * A brand page usually already emits a `WebPage` + `Article` (or `BlogPosting`) graph —
13
+ * Yoast on WordPress, the theme on Shopify, the framework on headless. If we emit a
14
+ * SECOND top-level `Article`, crawlers see two competing primary entities. Instead we
15
+ * emit a `@graph` whose WebPage / Article nodes carry the SAME `@id`s the page's own
16
+ * nodes use (the unmodified canonical URL for the page, the page URL + `#article` for
17
+ * the article — the Yoast convention) so a consumer MERGES our `reviewedBy` /
18
+ * `lastReviewed` / `dateModified` into the existing nodes by `@id` rather than
19
+ * duplicating them. Our own nodes are keyed to the CERTIFICATION instead (the verify
20
+ * URL, the expert's profile, the fixed CertREV organization id) — never under the host
21
+ * page's `@id` namespace — so they cannot clash with the host page's nodes.
20
22
  *
21
23
  * The Person we attach is the reviewing EXPERT (schema.org `reviewedBy`), which is the
22
24
  * E-E-A-T signal CertREV exists to add — not the author. The author (content byline) is
23
25
  * attached as `author` only when present + distinct.
26
+ *
27
+ * VISIBILITY: "Don't mark up content that is not visible to readers" (Google's
28
+ * structured-data guidelines) is a HARD rule here, not a nicety. Every field on this
29
+ * graph that mirrors something the card paints behind a visibility flag — the memo, the
30
+ * author byline, the reviewer photo — is gated by the SAME `resolveDisplay` the card
31
+ * uses (which folds in the render-def's subtractive hide-set), so the graph can never
32
+ * assert to a crawler what the reader cannot see. Re-deriving those flags here instead
33
+ * of importing the card's resolver is exactly how the two would silently drift.
24
34
  */
35
+ import type { CertRenderDef } from '../components/render-def.js';
25
36
  import type { CertPayload } from '../contract/kernel.js';
26
37
  /** A JSON-LD node/graph value. Loose by design — this is wire JSON, not a TS model. */
27
38
  export type JsonLdValue = Record<string, unknown>;
28
39
  export interface ProjectJsonLdOptions {
29
40
  /**
30
41
  * The canonical page URL the article renders on. Used to derive the primary
31
- * Article node `@id` (`${pageUrl}#article`) so we merge into the host page's graph
32
- * instead of colliding. When omitted, the first `subject.canonicalUrls` entry is
33
- * used; when there is none either, a CertREV-scoped article `@id` is derived from
34
- * `verifyUrl` (still mergeable, just not aligned to a host node).
42
+ * WebPage / Article node `@id`s (`${pageUrl}` and `${pageUrl}#article`) so we merge
43
+ * into the host page's graph instead of colliding. When omitted, the first
44
+ * `subject.canonicalUrls` entry is used; when there is none either, the WebPage node
45
+ * is DROPPED and a CertREV-scoped article `@id` is derived from `verifyUrl` (still
46
+ * mergeable, just not aligned to a host node).
35
47
  */
36
48
  readonly pageUrl?: string;
49
+ /**
50
+ * The brand render-def in force for THIS face. Read for its SUBTRACTIVE hide-set only
51
+ * (its theming half means nothing to structured data): a brand that hides the memo or
52
+ * the reviewer photo on the card must not have it published in the graph either.
53
+ */
54
+ readonly renderDef?: CertRenderDef;
37
55
  /**
38
56
  * When true (default), emit the wrapping `{ "@context": "...", "@graph": [...] }`.
39
57
  * When false, return just the array of nodes — for a caller that merges them into an
@@ -41,11 +59,26 @@ export interface ProjectJsonLdOptions {
41
59
  */
42
60
  readonly wrapGraph?: boolean;
43
61
  }
62
+ /**
63
+ * THE CertREV organization node `@id` — a hard CONSTANT, not a per-payload derivation.
64
+ *
65
+ * It used to be `${new URL(verifyUrl).origin}/#certrev-organization` under a comment
66
+ * claiming "one stable CertREV organization node across all pages", which it was not: a
67
+ * cert served from a second verify origin (a staging/preview host, a vanity verify
68
+ * domain, a future regional origin) minted a SECOND CertREV org node that would never
69
+ * merge with the first. CertREV is ONE real-world organization; its node id must not
70
+ * move because of which host happened to serve a verify link. Portal must emit this
71
+ * exact literal for the two halves to merge — see the package README.
72
+ */
73
+ export declare const CERTREV_ORGANIZATION_ID = "https://certrev.com/#certrev-organization";
74
+ /** CertREV's canonical homepage — the `url` of the organization node above, same reasoning. */
75
+ export declare const CERTREV_ORGANIZATION_URL = "https://certrev.com";
44
76
  /**
45
77
  * Project the verified certification facts into a schema.org `@graph`.
46
78
  *
47
79
  * @param payload The cryptographically-verified payload (the same facts the badge renders).
48
- * @param opts Page URL for @id alignment + graph-wrapping control.
80
+ * @param opts Page URL for @id alignment, the render-def whose hide-set gates
81
+ * visibility-bound fields, + graph-wrapping control.
49
82
  * @returns A `{ "@context", "@graph" }` object (wrapGraph !== false) OR a bare
50
83
  * array of nodes (wrapGraph === false) for merge-into-existing-graph callers.
51
84
  */
@@ -1 +1 @@
1
- {"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../../src/jsonld/project.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAe,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAErE,uFAAuF;AACvF,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;AAEjD,MAAM,WAAW,oBAAoB;IACpC;;;;;;OAMG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;IACzB;;;;OAIG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAA;CAC5B;AAuHD;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,WAAW,EAAE,IAAI,GAAE,oBAAyB,GAAG,WAAW,GAAG,WAAW,EAAE,CASpH;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,WAAW,EAAE,IAAI,GAAE,oBAAyB,GAAG,MAAM,CAErG;AAED;;;;;;;;;GASG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAE/D"}
1
+ {"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../../src/jsonld/project.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAChE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAExD,uFAAuF;AACvF,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;AAEjD,MAAM,WAAW,oBAAoB;IACpC;;;;;;;OAOG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;IACzB;;;;OAIG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,aAAa,CAAA;IAClC;;;;OAIG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAA;CAC5B;AAID;;;;;;;;;;GAUG;AACH,eAAO,MAAM,uBAAuB,8CAA8C,CAAA;AAElF,+FAA+F;AAC/F,eAAO,MAAM,wBAAwB,wBAAwB,CAAA;AA2K7D;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,WAAW,EAAE,IAAI,GAAE,oBAAyB,GAAG,WAAW,GAAG,WAAW,EAAE,CAepH;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,WAAW,EAAE,IAAI,GAAE,oBAAyB,GAAG,MAAM,CAErG;AAED;;;;;;;;;GASG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAE/D"}
@@ -9,20 +9,45 @@
9
9
  * server pre-render) produce the same structured data, and a snapshot diff is meaningful.
10
10
  *
11
11
  * DESIGN GOAL: MERGE, don't collide.
12
- * A brand page usually already emits an `Article` (or `BlogPosting`) graph — Yoast on
13
- * WordPress, the theme on Shopify, the framework on headless. If we emit a SECOND
14
- * top-level `Article`, crawlers see two competing primary entities. Instead we emit a
15
- * `@graph` whose Article node carries the SAME `@id` the page's primary article uses
16
- * (the page URL + `#article`, the Yoast convention) so a consumer MERGES our
17
- * `reviewedBy` / `dateModified` into the existing node by `@id` rather than duplicating
18
- * it. Our own nodes (the review, the expert Person, the CertREV org) use CertREV-scoped
19
- * `@id`s that cannot clash with the host page's nodes.
12
+ * A brand page usually already emits a `WebPage` + `Article` (or `BlogPosting`) graph —
13
+ * Yoast on WordPress, the theme on Shopify, the framework on headless. If we emit a
14
+ * SECOND top-level `Article`, crawlers see two competing primary entities. Instead we
15
+ * emit a `@graph` whose WebPage / Article nodes carry the SAME `@id`s the page's own
16
+ * nodes use (the unmodified canonical URL for the page, the page URL + `#article` for
17
+ * the article — the Yoast convention) so a consumer MERGES our `reviewedBy` /
18
+ * `lastReviewed` / `dateModified` into the existing nodes by `@id` rather than
19
+ * duplicating them. Our own nodes are keyed to the CERTIFICATION instead (the verify
20
+ * URL, the expert's profile, the fixed CertREV organization id) — never under the host
21
+ * page's `@id` namespace — so they cannot clash with the host page's nodes.
20
22
  *
21
23
  * The Person we attach is the reviewing EXPERT (schema.org `reviewedBy`), which is the
22
24
  * E-E-A-T signal CertREV exists to add — not the author. The author (content byline) is
23
25
  * attached as `author` only when present + distinct.
26
+ *
27
+ * VISIBILITY: "Don't mark up content that is not visible to readers" (Google's
28
+ * structured-data guidelines) is a HARD rule here, not a nicety. Every field on this
29
+ * graph that mirrors something the card paints behind a visibility flag — the memo, the
30
+ * author byline, the reviewer photo — is gated by the SAME `resolveDisplay` the card
31
+ * uses (which folds in the render-def's subtractive hide-set), so the graph can never
32
+ * assert to a crawler what the reader cannot see. Re-deriving those flags here instead
33
+ * of importing the card's resolver is exactly how the two would silently drift.
24
34
  */
35
+ import { resolveDisplay } from '../components/format.js';
25
36
  const SCHEMA_CONTEXT = 'https://schema.org';
37
+ /**
38
+ * THE CertREV organization node `@id` — a hard CONSTANT, not a per-payload derivation.
39
+ *
40
+ * It used to be `${new URL(verifyUrl).origin}/#certrev-organization` under a comment
41
+ * claiming "one stable CertREV organization node across all pages", which it was not: a
42
+ * cert served from a second verify origin (a staging/preview host, a vanity verify
43
+ * domain, a future regional origin) minted a SECOND CertREV org node that would never
44
+ * merge with the first. CertREV is ONE real-world organization; its node id must not
45
+ * move because of which host happened to serve a verify link. Portal must emit this
46
+ * exact literal for the two halves to merge — see the package README.
47
+ */
48
+ export const CERTREV_ORGANIZATION_ID = 'https://certrev.com/#certrev-organization';
49
+ /** CertREV's canonical homepage — the `url` of the organization node above, same reasoning. */
50
+ export const CERTREV_ORGANIZATION_URL = 'https://certrev.com';
26
51
  /**
27
52
  * Strip the query AND fragment from a URL for a stable, mergeable @id. The Yoast / host
28
53
  * convention keys the primary Article node on `{path}#article` with no query — so a page
@@ -33,105 +58,156 @@ function baseUrl(url) {
33
58
  const cut = Math.min(...[url.indexOf('#'), url.indexOf('?')].filter((i) => i !== -1), url.length);
34
59
  return url.slice(0, cut);
35
60
  }
61
+ /**
62
+ * The page this face renders on — the caller's `pageUrl` first (it knows the actual
63
+ * request), else the payload's primary canonical. Null when neither is known, which is
64
+ * the ONLY honest answer: we then assert nothing about any page.
65
+ */
66
+ function pageBaseUrl(payload, opts) {
67
+ const page = opts.pageUrl ?? payload.subject.canonicalUrls[0];
68
+ return page ? baseUrl(page) : null;
69
+ }
36
70
  /** Derive the primary Article `@id`, aligned to the Yoast/host convention when we can. */
37
71
  function articleId(payload, opts) {
38
- const page = opts.pageUrl ?? payload.subject.canonicalUrls[0];
72
+ const page = pageBaseUrl(payload, opts);
39
73
  if (page)
40
- return `${baseUrl(page)}#article`;
74
+ return `${page}#article`;
41
75
  // No page URL known — derive a stable, mergeable id from the verify URL.
42
76
  return `${baseUrl(payload.content.verifyUrl)}#article`;
43
77
  }
44
- /** CertREV-scoped node ids — namespaced under the verify URL so they never clash. */
45
- function reviewId(content) {
46
- return `${content.verifyUrl}#certrev-review`;
78
+ /** CertREV-scoped node ids — namespaced under the certification, so they never clash. */
79
+ function reviewId(payload) {
80
+ return `${payload.content.verifyUrl}#certrev-review`;
47
81
  }
48
- function expertId(content) {
49
- return content.expert.profileUrl ? `${content.expert.profileUrl}#person` : `${content.verifyUrl}#expert`;
82
+ function expertId(payload) {
83
+ const { expert, verifyUrl } = payload.content;
84
+ return expert.profileUrl ? `${expert.profileUrl}#person` : `${verifyUrl}#expert`;
50
85
  }
51
- function orgId(content) {
52
- // One stable CertREV organization node across all pages: derive from the verify
53
- // URL origin so it dedupes cleanly when a page hosts multiple certified articles.
54
- try {
55
- return `${new URL(content.verifyUrl).origin}/#certrev-organization`;
56
- }
57
- catch {
58
- return 'https://certrev.com/#certrev-organization';
59
- }
86
+ /**
87
+ * The `YYYY-MM-DD` head of an ISO-8601 instant, or null. `lastReviewed`'s schema.org
88
+ * range is `Date` — not `DateTime` — so the certified instant is truncated to its
89
+ * calendar day. String-sliced rather than `Date`-parsed on purpose: parsing would
90
+ * re-render the day in the runtime's timezone and break the determinism invariant
91
+ * (server and edge could disagree by a day).
92
+ */
93
+ function isoDate(value) {
94
+ if (typeof value !== 'string')
95
+ return null;
96
+ const match = /^\d{4}-\d{2}-\d{2}/.exec(value);
97
+ return match ? match[0] : null;
60
98
  }
61
99
  /** Build the reviewing-expert Person node (the E-E-A-T signal). */
62
- function expertPersonNode(payload) {
100
+ function expertPersonNode(payload, display) {
63
101
  const { expert } = payload.content;
64
102
  const node = {
65
103
  '@type': 'Person',
66
- '@id': expertId(payload.content),
104
+ '@id': expertId(payload),
67
105
  name: expert.displayName,
68
106
  };
69
107
  if (expert.profileUrl)
70
108
  node.url = expert.profileUrl;
71
- if (expert.photoUrl)
109
+ // The photo is a brand-toggleable (`free`) field: a face that hides the reviewer photo
110
+ // must not publish one either. `showExpertPhoto` already folds in the render-def's
111
+ // `reviewerPhoto` hide-set. Deliberately NOT gated on `badgeStyle` — a compact card
112
+ // omits the photo as a LAYOUT choice, and the same payload may render full elsewhere on
113
+ // the page, so keying the graph to it would make the projection slot-dependent.
114
+ if (display.showExpertPhoto && expert.photoUrl)
72
115
  node.image = expert.photoUrl;
73
116
  if (expert.credentials.length > 0) {
74
117
  // hasCredential → EducationalOccupationalCredential per credential; also a flat
75
- // honorificSuffix list for consumers that don't read hasCredential.
118
+ // honorificSuffix list for consumers that don't read hasCredential. `recognizedBy`
119
+ // (a Credential property whose expected type is Organization) names CertREV as the
120
+ // body that verified it — the structured-data form of the face's locked
121
+ // "Credential verified by CertREV" attribution, and what the reviewedby-schema
122
+ // validator looks for.
76
123
  node.hasCredential = expert.credentials.map((c) => ({
77
124
  '@type': 'EducationalOccupationalCredential',
78
125
  name: c.fullName,
79
126
  alternateName: c.abbreviation,
127
+ recognizedBy: { '@id': CERTREV_ORGANIZATION_ID },
80
128
  }));
81
129
  node.honorificSuffix = expert.credentials.map((c) => c.abbreviation).join(', ');
82
130
  }
83
131
  return node;
84
132
  }
85
133
  /** Build the CertREV organization node (publisher of the review credential). */
86
- function certRevOrgNode(payload) {
87
- let url = 'https://certrev.com';
88
- try {
89
- url = new URL(payload.content.verifyUrl).origin;
90
- }
91
- catch {
92
- /* keep default */
93
- }
134
+ function certRevOrgNode() {
94
135
  return {
95
136
  '@type': 'Organization',
96
- '@id': orgId(payload.content),
137
+ '@id': CERTREV_ORGANIZATION_ID,
97
138
  name: 'CertREV',
98
- url,
139
+ url: CERTREV_ORGANIZATION_URL,
99
140
  };
100
141
  }
101
142
  /** Build the Review node binding the article to its expert review. */
102
- function reviewNode(payload) {
143
+ function reviewNode(payload, opts, display) {
103
144
  const node = {
104
145
  '@type': 'Review',
105
- '@id': reviewId(payload.content),
106
- itemReviewed: { '@id': articleId(payload, {}) },
107
- author: { '@id': expertId(payload.content) },
108
- publisher: { '@id': orgId(payload.content) },
146
+ '@id': reviewId(payload),
147
+ // The SAME opts the Article node is built from. Passing `{}` here (as this did)
148
+ // pointed `itemReviewed` at the payload's canonical while the Article node carried
149
+ // the caller's `pageUrl` — an orphaned reference on every page whose URL differs
150
+ // from `canonicalUrls[0]` (locale prefix, `www`, trailing slash, a syndicated copy).
151
+ itemReviewed: { '@id': articleId(payload, opts) },
152
+ author: { '@id': expertId(payload) },
153
+ publisher: { '@id': CERTREV_ORGANIZATION_ID },
109
154
  datePublished: payload.content.certifiedAt,
110
155
  url: payload.content.verifyUrl,
111
156
  };
112
- if (payload.content.memo)
157
+ // The memo is the one piece of REVIEW PROSE on the face, and it is brand-toggleable.
158
+ // Publishing `reviewBody` off a hidden memo marks up text no reader can see.
159
+ if (display.showMemo && payload.content.memo)
113
160
  node.reviewBody = payload.content.memo;
114
161
  return node;
115
162
  }
163
+ /**
164
+ * The host page node — where `lastReviewed` and `reviewedBy` actually belong: BOTH are
165
+ * schema.org `WebPage` properties (`lastReviewed`: "Date on which the content on this web
166
+ * page was last reviewed for accuracy and/or completeness", range `Date`; `reviewedBy`:
167
+ * "People or organizations that have reviewed the content on this web page", range
168
+ * `Organization`/`Person`). Keyed on the UNMODIFIED canonical URL, the Yoast WebPage
169
+ * convention, so this merges into the host's existing WebPage node instead of adding a
170
+ * competing one — and, like the Article node, it carries ONLY the certification-relevant
171
+ * properties so a merge never overwrites the host's richer page fields.
172
+ *
173
+ * Returns null when no page URL is known: `lastReviewed` on a page we cannot name would
174
+ * either be a dangling node or — worse — an assertion about the CertREV verify page,
175
+ * which is not the reviewed content.
176
+ */
177
+ function webPageNode(payload, opts) {
178
+ const id = pageBaseUrl(payload, opts);
179
+ if (!id)
180
+ return null;
181
+ const lastReviewed = isoDate(payload.content.certifiedAt);
182
+ return {
183
+ '@type': 'WebPage',
184
+ '@id': id,
185
+ url: id,
186
+ ...(lastReviewed ? { lastReviewed } : {}),
187
+ reviewedBy: { '@id': expertId(payload) },
188
+ };
189
+ }
116
190
  /**
117
191
  * The primary Article node — carries the SAME `@id` the host page's article uses so a
118
192
  * consumer merges our `reviewedBy` / `dateModified` into the existing node rather than
119
193
  * duplicating the primary entity. We deliberately emit ONLY the certification-relevant
120
- * properties (reviewedBy, dateModified, plus author when distinct) — not headline, body,
121
- * image, etc. — so we never overwrite the host's richer Article fields on merge.
194
+ * properties (reviewedBy, dateModified, plus author when distinct AND shown) — not
195
+ * headline, body, image, etc. — so we never overwrite the host's richer Article fields
196
+ * on merge.
122
197
  */
123
- function articleNode(payload, opts) {
198
+ function articleNode(payload, opts, display) {
124
199
  const { content } = payload;
125
200
  const node = {
126
201
  '@type': 'Article',
127
202
  '@id': articleId(payload, opts),
128
- reviewedBy: { '@id': expertId(content) },
129
- review: { '@id': reviewId(content) },
203
+ reviewedBy: { '@id': expertId(payload) },
204
+ review: { '@id': reviewId(payload) },
130
205
  };
131
206
  if (content.contentModifiedAt)
132
207
  node.dateModified = content.contentModifiedAt;
133
- // Author only when present + distinct from the expert (don't double-attribute).
134
- if (content.author.name && content.author.name !== content.expert.displayName) {
208
+ // Author only when the face SHOWS the byline (a `free`, brand-toggleable field) and it
209
+ // is present + distinct from the expert (don't double-attribute).
210
+ if (display.showAuthor && content.author.name && content.author.name !== content.expert.displayName) {
135
211
  const author = { '@type': 'Person', name: content.author.name };
136
212
  if (content.author.title)
137
213
  author.jobTitle = content.author.title;
@@ -143,16 +219,23 @@ function articleNode(payload, opts) {
143
219
  * Project the verified certification facts into a schema.org `@graph`.
144
220
  *
145
221
  * @param payload The cryptographically-verified payload (the same facts the badge renders).
146
- * @param opts Page URL for @id alignment + graph-wrapping control.
222
+ * @param opts Page URL for @id alignment, the render-def whose hide-set gates
223
+ * visibility-bound fields, + graph-wrapping control.
147
224
  * @returns A `{ "@context", "@graph" }` object (wrapGraph !== false) OR a bare
148
225
  * array of nodes (wrapGraph === false) for merge-into-existing-graph callers.
149
226
  */
150
227
  export function projectCertJsonLd(payload, opts = {}) {
228
+ // ONE resolution of the visibility flags, shared by every node — the same resolver
229
+ // (and therefore the same answer) the rendered card uses. No accent override: theming
230
+ // is meaningless to structured data.
231
+ const display = resolveDisplay(payload.content.display, undefined, opts.renderDef);
232
+ const page = webPageNode(payload, opts);
151
233
  const nodes = [
152
- articleNode(payload, opts),
153
- reviewNode(payload),
154
- expertPersonNode(payload),
155
- certRevOrgNode(payload),
234
+ ...(page ? [page] : []),
235
+ articleNode(payload, opts, display),
236
+ reviewNode(payload, opts, display),
237
+ expertPersonNode(payload, display),
238
+ certRevOrgNode(),
156
239
  ];
157
240
  if (opts.wrapGraph === false)
158
241
  return nodes;
@@ -1 +1 @@
1
- {"version":3,"file":"project.js","sourceRoot":"","sources":["../../src/jsonld/project.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"project.js","sourceRoot":"","sources":["../../src/jsonld/project.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,OAAO,EAAwB,cAAc,EAAE,MAAM,yBAAyB,CAAA;AA+B9E,MAAM,cAAc,GAAG,oBAAoB,CAAA;AAE3C;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,2CAA2C,CAAA;AAElF,+FAA+F;AAC/F,MAAM,CAAC,MAAM,wBAAwB,GAAG,qBAAqB,CAAA;AAE7D;;;;;GAKG;AACH,SAAS,OAAO,CAAC,GAAW;IAC3B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IACjG,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;AACzB,CAAC;AAED;;;;GAIG;AACH,SAAS,WAAW,CAAC,OAAoB,EAAE,IAA0B;IACpE,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAA;IAC7D,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;AACnC,CAAC;AAED,0FAA0F;AAC1F,SAAS,SAAS,CAAC,OAAoB,EAAE,IAA0B;IAClE,MAAM,IAAI,GAAG,WAAW,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;IACvC,IAAI,IAAI;QAAE,OAAO,GAAG,IAAI,UAAU,CAAA;IAClC,yEAAyE;IACzE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,UAAU,CAAA;AACvD,CAAC;AAED,yFAAyF;AACzF,SAAS,QAAQ,CAAC,OAAoB;IACrC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,SAAS,iBAAiB,CAAA;AACrD,CAAC;AACD,SAAS,QAAQ,CAAC,OAAoB;IACrC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC,OAAO,CAAA;IAC7C,OAAO,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,UAAU,SAAS,CAAC,CAAC,CAAC,GAAG,SAAS,SAAS,CAAA;AACjF,CAAC;AAED;;;;;;GAMG;AACH,SAAS,OAAO,CAAC,KAAc;IAC9B,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAA;IAC1C,MAAM,KAAK,GAAG,oBAAoB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAC9C,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;AAC/B,CAAC;AAED,mEAAmE;AACnE,SAAS,gBAAgB,CAAC,OAAoB,EAAE,OAAwB;IACvE,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAA;IAClC,MAAM,IAAI,GAAgB;QACzB,OAAO,EAAE,QAAQ;QACjB,KAAK,EAAE,QAAQ,CAAC,OAAO,CAAC;QACxB,IAAI,EAAE,MAAM,CAAC,WAAW;KACxB,CAAA;IACD,IAAI,MAAM,CAAC,UAAU;QAAE,IAAI,CAAC,GAAG,GAAG,MAAM,CAAC,UAAU,CAAA;IACnD,uFAAuF;IACvF,mFAAmF;IACnF,oFAAoF;IACpF,wFAAwF;IACxF,gFAAgF;IAChF,IAAI,OAAO,CAAC,eAAe,IAAI,MAAM,CAAC,QAAQ;QAAE,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAA;IAC5E,IAAI,MAAM,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACnC,gFAAgF;QAChF,mFAAmF;QACnF,mFAAmF;QACnF,wEAAwE;QACxE,+EAA+E;QAC/E,uBAAuB;QACvB,IAAI,CAAC,aAAa,GAAG,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACnD,OAAO,EAAE,mCAAmC;YAC5C,IAAI,EAAE,CAAC,CAAC,QAAQ;YAChB,aAAa,EAAE,CAAC,CAAC,YAAY;YAC7B,YAAY,EAAE,EAAE,KAAK,EAAE,uBAAuB,EAAE;SAChD,CAAC,CAAC,CAAA;QACH,IAAI,CAAC,eAAe,GAAG,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAChF,CAAC;IACD,OAAO,IAAI,CAAA;AACZ,CAAC;AAED,gFAAgF;AAChF,SAAS,cAAc;IACtB,OAAO;QACN,OAAO,EAAE,cAAc;QACvB,KAAK,EAAE,uBAAuB;QAC9B,IAAI,EAAE,SAAS;QACf,GAAG,EAAE,wBAAwB;KAC7B,CAAA;AACF,CAAC;AAED,sEAAsE;AACtE,SAAS,UAAU,CAAC,OAAoB,EAAE,IAA0B,EAAE,OAAwB;IAC7F,MAAM,IAAI,GAAgB;QACzB,OAAO,EAAE,QAAQ;QACjB,KAAK,EAAE,QAAQ,CAAC,OAAO,CAAC;QACxB,gFAAgF;QAChF,mFAAmF;QACnF,iFAAiF;QACjF,qFAAqF;QACrF,YAAY,EAAE,EAAE,KAAK,EAAE,SAAS,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE;QACjD,MAAM,EAAE,EAAE,KAAK,EAAE,QAAQ,CAAC,OAAO,CAAC,EAAE;QACpC,SAAS,EAAE,EAAE,KAAK,EAAE,uBAAuB,EAAE;QAC7C,aAAa,EAAE,OAAO,CAAC,OAAO,CAAC,WAAW;QAC1C,GAAG,EAAE,OAAO,CAAC,OAAO,CAAC,SAAS;KAC9B,CAAA;IACD,qFAAqF;IACrF,6EAA6E;IAC7E,IAAI,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,OAAO,CAAC,IAAI;QAAE,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,CAAA;IACpF,OAAO,IAAI,CAAA;AACZ,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,SAAS,WAAW,CAAC,OAAoB,EAAE,IAA0B;IACpE,MAAM,EAAE,GAAG,WAAW,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;IACrC,IAAI,CAAC,EAAE;QAAE,OAAO,IAAI,CAAA;IACpB,MAAM,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAAA;IACzD,OAAO;QACN,OAAO,EAAE,SAAS;QAClB,KAAK,EAAE,EAAE;QACT,GAAG,EAAE,EAAE;QACP,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACzC,UAAU,EAAE,EAAE,KAAK,EAAE,QAAQ,CAAC,OAAO,CAAC,EAAE;KACxC,CAAA;AACF,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,WAAW,CAAC,OAAoB,EAAE,IAA0B,EAAE,OAAwB;IAC9F,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAA;IAC3B,MAAM,IAAI,GAAgB;QACzB,OAAO,EAAE,SAAS;QAClB,KAAK,EAAE,SAAS,CAAC,OAAO,EAAE,IAAI,CAAC;QAC/B,UAAU,EAAE,EAAE,KAAK,EAAE,QAAQ,CAAC,OAAO,CAAC,EAAE;QACxC,MAAM,EAAE,EAAE,KAAK,EAAE,QAAQ,CAAC,OAAO,CAAC,EAAE;KACpC,CAAA;IACD,IAAI,OAAO,CAAC,iBAAiB;QAAE,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,iBAAiB,CAAA;IAC5E,uFAAuF;IACvF,kEAAkE;IAClE,IAAI,OAAO,CAAC,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;QACrG,MAAM,MAAM,GAAgB,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,CAAA;QAC5E,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK;YAAE,MAAM,CAAC,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAA;QAChE,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;IACrB,CAAC;IACD,OAAO,IAAI,CAAA;AACZ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAoB,EAAE,OAA6B,EAAE;IACtF,mFAAmF;IACnF,sFAAsF;IACtF,qCAAqC;IACrC,MAAM,OAAO,GAAG,cAAc,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,CAAA;IAClF,MAAM,IAAI,GAAG,WAAW,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;IACvC,MAAM,KAAK,GAAkB;QAC5B,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACvB,WAAW,CAAC,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC;QACnC,UAAU,CAAC,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC;QAClC,gBAAgB,CAAC,OAAO,EAAE,OAAO,CAAC;QAClC,cAAc,EAAE;KAChB,CAAA;IACD,IAAI,IAAI,CAAC,SAAS,KAAK,KAAK;QAAE,OAAO,KAAK,CAAA;IAC1C,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAA;AACvD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,uBAAuB,CAAC,OAAoB,EAAE,OAA6B,EAAE;IAC5F,OAAO,wBAAwB,CAAC,iBAAiB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAA;AAClE,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,wBAAwB,CAAC,KAAc;IACtD,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,SAAS,CAAC,CAAA;AAC/E,CAAC"}
@@ -1,11 +1,11 @@
1
1
  /**
2
- * Avatar right-sizing (POR-10470) — the SINGLE source of truth for how a cert contributor/expert
2
+ * Avatar right-sizing — the SINGLE source of truth for how a cert contributor/expert
3
3
  * headshot URL is rewritten to a display-sized derivative. Referenced by the cert MODAL (TS,
4
4
  * cert-modal-view.ts), mirrored by the Liquid snippet (certrev-avatar-url.liquid), and by the
5
- * Cloudflare size-allowlist WAF rule (infra/terraform/cloudflare). Keep the three in lockstep — the
5
+ * Cloudflare size-allowlist WAF rule. Keep the three in lockstep — the
6
6
  * `avatar-resize.test.ts` `SIZES`/param assertions are the tripwire.
7
7
  *
8
- * Architecture (Fable-reviewed): the signed cert envelope carries ONE canonical full-res photoUrl
8
+ * Architecture: the signed cert envelope carries ONE canonical full-res photoUrl
9
9
  * (also the JSON-LD Person.image — never shrunk). Display sizing is a PRESENTATION concern, applied
10
10
  * here via Cloudflare Image Resizing on the same zone as assets.certrev.com:
11
11
  * https://assets.certrev.com/cdn-cgi/image/width=W,height=W,fit=cover,format=auto/<path>
@@ -13,19 +13,19 @@
13
13
  * allowlist is needed; format=auto serves webp/avif; the transform is cached + billed per-unique.
14
14
  *
15
15
  * ENABLEMENT GATE (`AVATAR_RESIZE_ENABLED`): OFF until Cloudflare Image Resizing is enabled on the
16
- * certrev.com zone AND a real photo is verified to resize (POR-10470 gate). While OFF, avatars use
16
+ * certrev.com zone AND a real photo is verified to resize. While OFF, avatars use
17
17
  * the raw canonical URL — byte-identical to today's behavior — so the extension can deploy for the
18
18
  * font de-block with ZERO avatar regression (a cdn-cgi/image URL 404s → initials fallback if the
19
19
  * feature isn't live). Going live is a one-line flip here + in certrev-avatar-url.liquid, then the
20
- * raw branch is removed (flag-debt: tracked as the POR-10470 avatar go-live follow-up).
20
+ * raw branch is removed (flag-debt: the avatar go-live follow-up).
21
21
  */
22
22
  /**
23
- * Enablement gate — LIVE as of 2026-07-20 (POR-10656). Cloudflare Image Resizing (Transformations)
24
- * is enabled on the certrev.com zone (`image_resizing = on`), and the size-allowlist WAF rule
25
- * (ruleset 7c9df62e88cb4713b18f12853651af08) is verified enforcing on `/cdn-cgi/image/` paths — a real
26
- * photo resizes (`width=84` → 200 image/jpeg) while a disallowed size (`width=999`) is 403-blocked.
23
+ * Enablement gate — LIVE as of 2026-07-20. Cloudflare Image Resizing (Transformations)
24
+ * is enabled on the certrev.com zone (`image_resizing = on`), and the size-allowlist WAF rule is
25
+ * verified enforcing on `/cdn-cgi/image/` paths — a real photo resizes (`width=84` → 200
26
+ * image/jpeg) while a disallowed size (`width=999`) is 403-blocked.
27
27
  * Kept as a one-line kill-switch: flip back to `false` + redeploy to instantly revert to raw URLs if
28
- * resizing ever misbehaves (removing the raw branch entirely is the flag-debt follow-up, POR-10680).
28
+ * resizing ever misbehaves (removing the raw branch entirely is the flag-debt follow-up).
29
29
  */
30
30
  export declare const AVATAR_RESIZE_ENABLED = true;
31
31
  /**