@warpgogol/werkstatt-shared 0.2.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.
Files changed (403) hide show
  1. package/package.json +352 -0
  2. package/src/checks/index.ts +24 -0
  3. package/src/checks/lib/astro-site-url.ts +30 -0
  4. package/src/checks/lib/i18n.ts +30 -0
  5. package/src/checks/result-helpers.ts +102 -0
  6. package/src/checks/suppressions-config.ts +195 -0
  7. package/src/index.ts +14 -0
  8. package/src/integration/README.md +38 -0
  9. package/src/integration/adapters.ts +143 -0
  10. package/src/integration/crm-buffer.ts +491 -0
  11. package/src/integration/dispatch.ts +106 -0
  12. package/src/integration/funnel.ts +379 -0
  13. package/src/integration/index.ts +56 -0
  14. package/src/integration/lifecycle.ts +155 -0
  15. package/src/integration/orchestration.ts +439 -0
  16. package/src/integration/port-barrel.ts +124 -0
  17. package/src/integration/port.ts +143 -0
  18. package/src/integration/qstash.ts +134 -0
  19. package/src/integration/sharding.ts +133 -0
  20. package/src/integration/tests/deliver-event.test.ts +52 -0
  21. package/src/integration/tests/dispatch.test.ts +88 -0
  22. package/src/integration/tests/funnel-bridge.test.ts +46 -0
  23. package/src/integration/tests/hub-runtime.test.ts +128 -0
  24. package/src/integration/tests/lifecycle.test.ts +69 -0
  25. package/src/integration/tests/qstash.test.ts +83 -0
  26. package/src/integration/tests/sharding.test.ts +64 -0
  27. package/src/integration/vitest.config.ts +8 -0
  28. package/src/integration-adapter-supabase-crm/adapter.ts +437 -0
  29. package/src/integration-adapter-supabase-crm/client.ts +605 -0
  30. package/src/integration-adapter-supabase-crm/index.ts +28 -0
  31. package/src/integration-adapter-supabase-crm/pipedrive-sync-target.ts +482 -0
  32. package/src/integration-adapter-supabase-crm/supabase-rest.ts +89 -0
  33. package/src/integration-adapter-supabase-crm/tenant-registry.ts +334 -0
  34. package/src/integration-adapter-supabase-crm/tests/change-balance.pbt.test.ts +83 -0
  35. package/src/integration-adapter-supabase-crm/tests/funnel-persistence.test.ts +409 -0
  36. package/src/integration-adapter-supabase-crm/tests/lifecycle-sync.test.ts +288 -0
  37. package/src/integration-adapter-supabase-crm/tests/stage-map.test.ts +80 -0
  38. package/src/integration-adapter-supabase-crm/vitest.config.ts +8 -0
  39. package/src/integration-adapter-supabase-crm/worker.ts +223 -0
  40. package/src/observability/conventions.ts +93 -0
  41. package/src/observability/env-resolver.ts +57 -0
  42. package/src/observability/index.ts +57 -0
  43. package/src/observability/metric-registry.ts +184 -0
  44. package/src/observability/otlp-converter.ts +125 -0
  45. package/src/observability/otlp-json.ts +135 -0
  46. package/src/observability/otlp-transport.ts +68 -0
  47. package/src/observability/pusher.ts +142 -0
  48. package/src/observability/redact.ts +27 -0
  49. package/src/observability/tests/conventions.test.ts +100 -0
  50. package/src/observability/tests/metric-registry.test.ts +117 -0
  51. package/src/observability/tests/otlp-converter.pbt.test.ts +77 -0
  52. package/src/observability/tests/otlp-converter.test.ts +157 -0
  53. package/src/observability/tests/otlp-json.test.ts +120 -0
  54. package/src/observability/tests/pusher.test.ts +75 -0
  55. package/src/observability/tests/redact.pbt.test.ts +71 -0
  56. package/src/observability/tests/redact.test.ts +37 -0
  57. package/src/observability/typed-refs.ts +137 -0
  58. package/src/observability/vitest.config.ts +8 -0
  59. package/src/ontology/analytics/matomo-binding.yaml +172 -0
  60. package/src/ontology/analytics/matomo-fleet.registry.yaml +26 -0
  61. package/src/ontology/analytics/messkanon.yaml +151 -0
  62. package/src/ontology/archetype-registry.ts +61 -0
  63. package/src/ontology/archetypes/components/brand-label.yaml +19 -0
  64. package/src/ontology/archetypes/components/copyright.yaml +19 -0
  65. package/src/ontology/archetypes/components/currency-aware-price-display.yaml +19 -0
  66. package/src/ontology/archetypes/components/currency-selector.yaml +19 -0
  67. package/src/ontology/archetypes/components/footer-promo.yaml +19 -0
  68. package/src/ontology/archetypes/components/lang-switcher.yaml +19 -0
  69. package/src/ontology/archetypes/components/layout.yaml +19 -0
  70. package/src/ontology/archetypes/components/live-photo.yaml +20 -0
  71. package/src/ontology/archetypes/components/material-credit.yaml +20 -0
  72. package/src/ontology/archetypes/components/media.yaml +21 -0
  73. package/src/ontology/archetypes/components/nachweis-card.yaml +34 -0
  74. package/src/ontology/archetypes/components/nachweis-detail.yaml +43 -0
  75. package/src/ontology/archetypes/components/nachweis-list.yaml +37 -0
  76. package/src/ontology/archetypes/components/nachweis-verify.yaml +31 -0
  77. package/src/ontology/archetypes/components/not-found.yaml +22 -0
  78. package/src/ontology/archetypes/components/offer-capacity.yaml +21 -0
  79. package/src/ontology/archetypes/components/passport-header.yaml +19 -0
  80. package/src/ontology/archetypes/components/passport-provenance.yaml +20 -0
  81. package/src/ontology/archetypes/components/passport-score-grid.yaml +20 -0
  82. package/src/ontology/archetypes/components/passport-star-map.yaml +20 -0
  83. package/src/ontology/archetypes/components/person-profile.yaml +20 -0
  84. package/src/ontology/archetypes/components/pulsar.yaml +20 -0
  85. package/src/ontology/archetypes/components/responsive-image.yaml +19 -0
  86. package/src/ontology/archetypes/components/scroll-to-top.yaml +22 -0
  87. package/src/ontology/archetypes/components/social-meta.yaml +20 -0
  88. package/src/ontology/archetypes/components/structured-data.yaml +19 -0
  89. package/src/ontology/archetypes/index.json +1003 -0
  90. package/src/ontology/archetypes/index.yaml +821 -0
  91. package/src/ontology/archetypes/sections/approach.yaml +23 -0
  92. package/src/ontology/archetypes/sections/article-list.yaml +30 -0
  93. package/src/ontology/archetypes/sections/audience-cards.yaml +30 -0
  94. package/src/ontology/archetypes/sections/breadcrumbs.yaml +21 -0
  95. package/src/ontology/archetypes/sections/chat-widget.yaml +37 -0
  96. package/src/ontology/archetypes/sections/comparison-cards.yaml +31 -0
  97. package/src/ontology/archetypes/sections/controlled-responsibility-block.yaml +34 -0
  98. package/src/ontology/archetypes/sections/credits.yaml +29 -0
  99. package/src/ontology/archetypes/sections/donation-card.yaml +53 -0
  100. package/src/ontology/archetypes/sections/donation-use.yaml +23 -0
  101. package/src/ontology/archetypes/sections/dynamic-status-block.yaml +35 -0
  102. package/src/ontology/archetypes/sections/faq-list.yaml +26 -0
  103. package/src/ontology/archetypes/sections/final-cta.yaml +53 -0
  104. package/src/ontology/archetypes/sections/hero-decision-card.yaml +65 -0
  105. package/src/ontology/archetypes/sections/hero.yaml +50 -0
  106. package/src/ontology/archetypes/sections/impact.yaml +23 -0
  107. package/src/ontology/archetypes/sections/markdown.yaml +43 -0
  108. package/src/ontology/archetypes/sections/mountain-journey.yaml +43 -0
  109. package/src/ontology/archetypes/sections/navigation.yaml +20 -0
  110. package/src/ontology/archetypes/sections/notausgang-block.yaml +41 -0
  111. package/src/ontology/archetypes/sections/open-source-registry.yaml +26 -0
  112. package/src/ontology/archetypes/sections/ownership-block.yaml +57 -0
  113. package/src/ontology/archetypes/sections/people.yaml +48 -0
  114. package/src/ontology/archetypes/sections/price-card.yaml +50 -0
  115. package/src/ontology/archetypes/sections/problem.yaml +23 -0
  116. package/src/ontology/archetypes/sections/send-message.yaml +63 -0
  117. package/src/ontology/archetypes/sections/service-metadata-block.yaml +40 -0
  118. package/src/ontology/archetypes/sections/social-proof.yaml +27 -0
  119. package/src/ontology/archetypes/sections/transparency.yaml +32 -0
  120. package/src/ontology/archetypes/sections/trust-strip.yaml +42 -0
  121. package/src/ontology/archetypes/sections/video-section.yaml +27 -0
  122. package/src/ontology/archetypes/sections/women.yaml +29 -0
  123. package/src/ontology/biome-token-projection.ts +229 -0
  124. package/src/ontology/biomes/check-concrete-blueprint.yaml +118 -0
  125. package/src/ontology/biomes/handwerk-material-warm.yaml +135 -0
  126. package/src/ontology/biomes/nonprofit-trust.yaml +123 -0
  127. package/src/ontology/blueprints/offer.yaml +39 -0
  128. package/src/ontology/blueprints/prompts/local-market-signal.md +13 -0
  129. package/src/ontology/blueprints/prompts/website-local-narrative.md +24 -0
  130. package/src/ontology/blueprints/ratgeber.yaml +62 -0
  131. package/src/ontology/blueprints/website-local.yaml +309 -0
  132. package/src/ontology/blueprints/website-service.yaml +84 -0
  133. package/src/ontology/capabilities/lead.submit.yaml +44 -0
  134. package/src/ontology/cosmic/index.ts +48 -0
  135. package/src/ontology/cosmic/moon-catalog.ts +173 -0
  136. package/src/ontology/cosmic/planet-catalog.ts +82 -0
  137. package/src/ontology/cosmic/star-catalog.ts +337 -0
  138. package/src/ontology/enums.ts +159 -0
  139. package/src/ontology/external-surfaces/index.ts +158 -0
  140. package/src/ontology/external-surfaces/jsonld-types.yaml +135 -0
  141. package/src/ontology/external-surfaces/sitemap-shape.yaml +6 -0
  142. package/src/ontology/external-surfaces/url-schema.yaml +95 -0
  143. package/src/ontology/growth/events/contact-email-click.yaml +21 -0
  144. package/src/ontology/growth/events/contact-form-submit.yaml +25 -0
  145. package/src/ontology/growth/events/contact-phone-click.yaml +21 -0
  146. package/src/ontology/growth/events/contact-route-click.yaml +21 -0
  147. package/src/ontology/growth/events/contact-submit.yaml +28 -0
  148. package/src/ontology/growth/events/contact-whatsapp-click.yaml +21 -0
  149. package/src/ontology/growth/events/cta-click.yaml +30 -0
  150. package/src/ontology/growth/events/donation-confirmed.yaml +32 -0
  151. package/src/ontology/growth/events/donation-form-start.yaml +21 -0
  152. package/src/ontology/growth/events/donation-form-submit.yaml +29 -0
  153. package/src/ontology/growth/events/donation-intent.yaml +29 -0
  154. package/src/ontology/growth/events/form-error.yaml +27 -0
  155. package/src/ontology/growth/events/form-start.yaml +21 -0
  156. package/src/ontology/growth/events/form-submit.yaml +21 -0
  157. package/src/ontology/growth/events/outbound-click.yaml +25 -0
  158. package/src/ontology/growth/events/page-view.yaml +24 -0
  159. package/src/ontology/growth/events/passport-view.yaml +28 -0
  160. package/src/ontology/growth/events/star-map-navigate.yaml +30 -0
  161. package/src/ontology/index.ts +165 -0
  162. package/src/ontology/manifest.ts +344 -0
  163. package/src/ontology/operations/index.ts +1 -0
  164. package/src/ontology/schemas/biome.ts +303 -0
  165. package/src/ontology/schemas/capability.ts +104 -0
  166. package/src/ontology/schemas/constellation.ts +114 -0
  167. package/src/ontology/schemas/dns-records.ts +53 -0
  168. package/src/ontology/schemas/index.ts +95 -0
  169. package/src/ontology/schemas/manifest-resolver.ts +123 -0
  170. package/src/ontology/schemas/page-entry.ts +213 -0
  171. package/src/ontology/schemas/section-archetype.ts +109 -0
  172. package/src/ontology/schemas/site-family.ts +98 -0
  173. package/src/ontology/schemas/system/growth.ts +80 -0
  174. package/src/ontology/schemas/system/integrations.ts +143 -0
  175. package/src/ontology/schemas/system/manifest.ts +492 -0
  176. package/src/ontology/schemas/system/page-output.ts +99 -0
  177. package/src/ontology/schemas/system/release.ts +58 -0
  178. package/src/ontology/schemas/system/text.ts +58 -0
  179. package/src/ontology/schemas/system.ts +53 -0
  180. package/src/ontology/shared-section-props/body-fragments.ts +182 -0
  181. package/src/ontology/shared-section-props/catalog.ts +195 -0
  182. package/src/ontology/shared-section-props/common.ts +178 -0
  183. package/src/ontology/shared-section-props/index.ts +34 -0
  184. package/src/ontology/shared-section-props/visual-header.ts +163 -0
  185. package/src/ontology/site-families/charity-donation-trust/cultural-rules.yaml +6 -0
  186. package/src/ontology/site-families/charity-donation-trust/family.yaml +44 -0
  187. package/src/ontology/site-families/charity-donation-trust/linguistic-rules.yaml +6 -0
  188. package/src/ontology/site-families/check-quality-operator/cultural-rules.yaml +6 -0
  189. package/src/ontology/site-families/check-quality-operator/family.yaml +40 -0
  190. package/src/ontology/site-families/check-quality-operator/linguistic-rules.yaml +6 -0
  191. package/src/ontology/site-families/handwerk-trust-engineering/cultural-rules.yaml +6 -0
  192. package/src/ontology/site-families/handwerk-trust-engineering/family.yaml +53 -0
  193. package/src/ontology/site-families/handwerk-trust-engineering/linguistic-rules.yaml +6 -0
  194. package/src/ontology/tests/catalogs.pbt.test.ts +89 -0
  195. package/src/ontology/tests/enums.test.ts +203 -0
  196. package/src/ontology/tests/sternsystem-owner.test.ts +63 -0
  197. package/src/ontology/vitest.config.ts +8 -0
  198. package/src/passport/dht-sign.test.ts +99 -0
  199. package/src/passport/dht-sign.ts +73 -0
  200. package/src/passport/identity-sign.test.ts +134 -0
  201. package/src/passport/identity-sign.ts +85 -0
  202. package/src/passport/index.ts +53 -0
  203. package/src/passport/key-rotate.ts +133 -0
  204. package/src/passport/schema.ts +198 -0
  205. package/src/passport/sign.ts +225 -0
  206. package/src/passport/tests/schema.pbt.test.ts +93 -0
  207. package/src/passport/tests/schema.test.ts +222 -0
  208. package/src/passport/vitest.config.ts +8 -0
  209. package/src/share/agent/api-catalog.ts +77 -0
  210. package/src/share/agent/capability.ts +68 -0
  211. package/src/share/agent/dns-aid.test.ts +74 -0
  212. package/src/share/agent/dns-aid.ts +53 -0
  213. package/src/share/agent/fleet-catalog.ts +149 -0
  214. package/src/share/agent/index.ts +29 -0
  215. package/src/share/agent/knowledge.ts +96 -0
  216. package/src/share/agent/manifest.ts +126 -0
  217. package/src/share/agent/mcp-card.ts +63 -0
  218. package/src/share/agent/omit-empty.ts +77 -0
  219. package/src/share/agent/openapi.ts +157 -0
  220. package/src/share/agent/proof.ts +61 -0
  221. package/src/share/attribution-display.ts +86 -0
  222. package/src/share/check-hints.ts +38 -0
  223. package/src/share/content/entity-id.ts +65 -0
  224. package/src/share/content/index.ts +16 -0
  225. package/src/share/content/merge.ts +86 -0
  226. package/src/share/content/resolve-field-path.ts +39 -0
  227. package/src/share/content/substitute-deep.ts +47 -0
  228. package/src/share/content-discipline/index.ts +14 -0
  229. package/src/share/content-discipline/parsers.ts +66 -0
  230. package/src/share/content-discipline/types.ts +118 -0
  231. package/src/share/content-reference.ts +333 -0
  232. package/src/share/counter-utils.ts +75 -0
  233. package/src/share/css-value-normalize.ts +48 -0
  234. package/src/share/dev-props-validator.ts +131 -0
  235. package/src/share/entitlement.ts +172 -0
  236. package/src/share/env.d.ts +73 -0
  237. package/src/share/feature-policy.ts +367 -0
  238. package/src/share/formula-eval.ts +364 -0
  239. package/src/share/fs/index.ts +96 -0
  240. package/src/share/i18n/localization.ts +57 -0
  241. package/src/share/image-provider.ts +314 -0
  242. package/src/share/index.ts +86 -0
  243. package/src/share/knowledge/claim.ts +129 -0
  244. package/src/share/knowledge/derivation.ts +55 -0
  245. package/src/share/knowledge/freshness.ts +127 -0
  246. package/src/share/knowledge/index.ts +23 -0
  247. package/src/share/knowledge/ledger.ts +222 -0
  248. package/src/share/knowledge/plan.ts +122 -0
  249. package/src/share/knowledge/source.ts +170 -0
  250. package/src/share/legal/translation-policy.ts +133 -0
  251. package/src/share/material-credits.ts +181 -0
  252. package/src/share/middleware/language-redirect.ts +49 -0
  253. package/src/share/offer-capacity.ts +149 -0
  254. package/src/share/onboarding-yaml/index.ts +162 -0
  255. package/src/share/page.ts +351 -0
  256. package/src/share/redirects.test.ts +62 -0
  257. package/src/share/redirects.ts +54 -0
  258. package/src/share/rfc0042-utils.ts +95 -0
  259. package/src/share/runtime-context.ts +70 -0
  260. package/src/share/schemas/claim-records.ts +69 -0
  261. package/src/share/schemas/claims.ts +150 -0
  262. package/src/share/schemas/effects.ts +212 -0
  263. package/src/share/schemas/features.ts +147 -0
  264. package/src/share/schemas/horizontal-align.ts +22 -0
  265. package/src/share/schemas/icon-color.ts +27 -0
  266. package/src/share/schemas/index.ts +43 -0
  267. package/src/share/schemas/live-photo.ts +53 -0
  268. package/src/share/schemas/material-credit.ts +292 -0
  269. package/src/share/schemas/media.ts +220 -0
  270. package/src/share/schemas/navigation.ts +74 -0
  271. package/src/share/schemas/page-base.ts +33 -0
  272. package/src/share/schemas/participant.ts +247 -0
  273. package/src/share/schemas/person.ts +24 -0
  274. package/src/share/schemas/print.ts +93 -0
  275. package/src/share/schemas/section-background.ts +106 -0
  276. package/src/share/schemas/section-body.ts +138 -0
  277. package/src/share/schemas/section-cards.ts +37 -0
  278. package/src/share/schemas/section-cta.ts +74 -0
  279. package/src/share/schemas/section-header.ts +77 -0
  280. package/src/share/schemas/section-image.ts +77 -0
  281. package/src/share/schemas/section-motion.ts +52 -0
  282. package/src/share/schemas/section-shell.ts +63 -0
  283. package/src/share/schemas/section-stats.ts +37 -0
  284. package/src/share/schemas/site-background.ts +78 -0
  285. package/src/share/schemas/standard-list-item.ts +38 -0
  286. package/src/share/scripts/external-links.ts +45 -0
  287. package/src/share/scripts/gsap-counter.ts +168 -0
  288. package/src/share/scripts/gsap-mountain-journey.ts +236 -0
  289. package/src/share/scripts/gsap-parallax.ts +50 -0
  290. package/src/share/scripts/gsap-reveal.ts +65 -0
  291. package/src/share/scripts/gsap-stagger.ts +54 -0
  292. package/src/share/scripts/index.ts +25 -0
  293. package/src/share/scripts/inline-number-animation.ts +120 -0
  294. package/src/share/scripts/lenis.ts +109 -0
  295. package/src/share/scripts/live-photos.ts +250 -0
  296. package/src/share/scripts/lordicon.ts +94 -0
  297. package/src/share/scripts/orchestrator.ts +138 -0
  298. package/src/share/scripts/scheduler.ts +53 -0
  299. package/src/share/scripts/video-player.ts +116 -0
  300. package/src/share/semantic/ai.ts +140 -0
  301. package/src/share/semantic/block-extraction.ts +52 -0
  302. package/src/share/semantic/block-extractors/index.ts +502 -0
  303. package/src/share/semantic/breadcrumbs.ts +120 -0
  304. package/src/share/semantic/build-page.ts +309 -0
  305. package/src/share/semantic/business-projection.ts +278 -0
  306. package/src/share/semantic/derived-prices-loader.ts +36 -0
  307. package/src/share/semantic/extract.ts +118 -0
  308. package/src/share/semantic/feed.ts +124 -0
  309. package/src/share/semantic/ids.ts +76 -0
  310. package/src/share/semantic/image-sitemap.ts +153 -0
  311. package/src/share/semantic/index.ts +36 -0
  312. package/src/share/semantic/jsonld/article.ts +47 -0
  313. package/src/share/semantic/jsonld/breadcrumb.ts +47 -0
  314. package/src/share/semantic/jsonld/collection-list.ts +30 -0
  315. package/src/share/semantic/jsonld/context.ts +46 -0
  316. package/src/share/semantic/jsonld/faq.ts +49 -0
  317. package/src/share/semantic/jsonld/initiative.ts +53 -0
  318. package/src/share/semantic/jsonld/organization.ts +101 -0
  319. package/src/share/semantic/jsonld/person.ts +71 -0
  320. package/src/share/semantic/jsonld/service.ts +80 -0
  321. package/src/share/semantic/jsonld/shared.ts +31 -0
  322. package/src/share/semantic/jsonld/types.ts +18 -0
  323. package/src/share/semantic/jsonld/webpage.ts +98 -0
  324. package/src/share/semantic/jsonld/website.ts +27 -0
  325. package/src/share/semantic/jsonld.ts +75 -0
  326. package/src/share/semantic/llms-policy.ts +74 -0
  327. package/src/share/semantic/llms.ts +394 -0
  328. package/src/share/semantic/markdown-hygiene.ts +68 -0
  329. package/src/share/semantic/markdown-twin-provenance.ts +242 -0
  330. package/src/share/semantic/models.ts +402 -0
  331. package/src/share/semantic/organization-profile.ts +160 -0
  332. package/src/share/semantic/output-projection.ts +131 -0
  333. package/src/share/semantic/page-builders/markdown-page.ts +84 -0
  334. package/src/share/semantic/page-markdown.ts +234 -0
  335. package/src/share/semantic/page-utils.ts +125 -0
  336. package/src/share/semantic/price-marker-resolver.ts +92 -0
  337. package/src/share/semantic/robots.ts +127 -0
  338. package/src/share/semantic/update-stamp.ts +136 -0
  339. package/src/share/shared-context.ts +177 -0
  340. package/src/share/string-utils.ts +19 -0
  341. package/src/share/tests/api-catalog.test.ts +97 -0
  342. package/src/share/tests/breadcrumbs.test.ts +126 -0
  343. package/src/share/tests/build-page-price-markers.test.ts +160 -0
  344. package/src/share/tests/capability.test.ts +107 -0
  345. package/src/share/tests/claim.test.ts +90 -0
  346. package/src/share/tests/content-ref-index.test.ts +328 -0
  347. package/src/share/tests/create-dev-props-validator.test.ts +38 -0
  348. package/src/share/tests/derivation.test.ts +39 -0
  349. package/src/share/tests/dev-props-validator.test.ts +88 -0
  350. package/src/share/tests/fleet-catalog.test.ts +134 -0
  351. package/src/share/tests/formula-eval.test.ts +619 -0
  352. package/src/share/tests/freshness.test.ts +60 -0
  353. package/src/share/tests/hero-section-numbering-parity.test.ts +51 -0
  354. package/src/share/tests/image-sitemap.test.ts +101 -0
  355. package/src/share/tests/jsonld-service.test.ts +282 -0
  356. package/src/share/tests/knowledge.test.ts +86 -0
  357. package/src/share/tests/ledger.test.ts +125 -0
  358. package/src/share/tests/llms-0789.test.ts +63 -0
  359. package/src/share/tests/manifest.test.ts +100 -0
  360. package/src/share/tests/markdown-twin-provenance.test.ts +108 -0
  361. package/src/share/tests/mcp-card.test.ts +57 -0
  362. package/src/share/tests/onboarding-yaml.test.ts +111 -0
  363. package/src/share/tests/ontology-role-by-cosmic-name.test.ts +28 -0
  364. package/src/share/tests/openapi.test.ts +116 -0
  365. package/src/share/tests/organization-jsonld.test.ts +74 -0
  366. package/src/share/tests/output-projection.test.ts +61 -0
  367. package/src/share/tests/plan.test.ts +97 -0
  368. package/src/share/tests/price-marker-resolver.test.ts +141 -0
  369. package/src/share/tests/proof.test.ts +72 -0
  370. package/src/share/tests/resolve-field-path.test.ts +52 -0
  371. package/src/share/tests/source.test.ts +81 -0
  372. package/src/share/tests/substitute-deep.test.ts +65 -0
  373. package/src/share/tests/text-normalize.pbt.test.ts +143 -0
  374. package/src/share/tests/text-normalize.test.ts +285 -0
  375. package/src/share/tests/twin-path.test.ts +43 -0
  376. package/src/share/text-normalize.ts +548 -0
  377. package/src/share/text-position.ts +19 -0
  378. package/src/share/types/hls-js-light.d.ts +16 -0
  379. package/src/share/visibility.ts +167 -0
  380. package/src/share/vitest.config.ts +8 -0
  381. package/src/share/wrap-inline-numbers.ts +139 -0
  382. package/src/surface/blueprint-schema.ts +314 -0
  383. package/src/surface/blueprint-types.ts +256 -0
  384. package/src/surface/blueprint.ts +300 -0
  385. package/src/surface/breaker.ts +57 -0
  386. package/src/surface/decision-composer.ts +156 -0
  387. package/src/surface/eligibility.ts +372 -0
  388. package/src/surface/evidence-records.ts +97 -0
  389. package/src/surface/fleet.ts +60 -0
  390. package/src/surface/geo.ts +170 -0
  391. package/src/surface/governance.ts +146 -0
  392. package/src/surface/index.ts +216 -0
  393. package/src/surface/io/index.ts +18 -0
  394. package/src/surface/io/surface-module-context-io.ts +60 -0
  395. package/src/surface/io/visibility-outcomes-io.ts +46 -0
  396. package/src/surface/module-context.ts +120 -0
  397. package/src/surface/substance.ts +161 -0
  398. package/src/surface/tests/eligibility.pbt.test.ts +137 -0
  399. package/src/surface/tests/eligibility.test.ts +302 -0
  400. package/src/surface/types.ts +289 -0
  401. package/src/surface/visibility.ts +57 -0
  402. package/src/surface/vitest.config.ts +8 -0
  403. package/tsconfig.json +17 -0
@@ -0,0 +1,247 @@
1
+ /*
2
+ <MODULE_CONTRACT>
3
+ <purpose>
4
+ RFC-0508: canonical Participant schema — a unified entity model for humans, AI agents,
5
+ organization units, external specialists, partner organizations, and service accounts.
6
+ Extends the People collection (RFC-0200) with type-specific responsibility/authority/evidence
7
+ fields, lifecycle statuses, consent records for humans, and public/private visibility.
8
+ </purpose>
9
+ <non-goals>
10
+ <item>Do not define route generation or page rendering logic — that lives in @warpgogol/werkstatt-site/share/astro.</item>
11
+ <item>Do not define validation rules — that lives in @warpgogol/werkstatt-site/checks/src/participant.ts.</item>
12
+ <item>Do not remove PERSON_AFFILIATIONS from person.ts — it is retained for human governance JSON-LD.</item>
13
+ </non-goals>
14
+ </MODULE_CONTRACT>
15
+ <CHANGE_SUMMARY>
16
+ <item>RFC-0508: initial creation — Participant schema with six types, statuses, relationships, consent, and type-specific fields.</item>
17
+ </CHANGE_SUMMARY>
18
+ */
19
+
20
+ import { z } from "zod";
21
+ import { PERSON_AFFILIATIONS } from "./person.ts";
22
+
23
+ export const PARTICIPANT_TYPES = [
24
+ "human",
25
+ "ai-agent",
26
+ "organization-unit",
27
+ "external-specialist",
28
+ "partner-organization",
29
+ "service-account",
30
+ ] as const;
31
+ export type ParticipantType = (typeof PARTICIPANT_TYPES)[number];
32
+
33
+ export const PARTICIPANT_RELATIONSHIPS = [
34
+ "founder",
35
+ "board",
36
+ "team",
37
+ "patron",
38
+ "author",
39
+ "advisor",
40
+ "contractor",
41
+ "partner",
42
+ "service",
43
+ ] as const;
44
+ export type ParticipantRelationship = (typeof PARTICIPANT_RELATIONSHIPS)[number];
45
+
46
+ export const PARTICIPANT_STATUSES = [
47
+ "active",
48
+ "temporarily-unavailable",
49
+ "on-leave",
50
+ "former",
51
+ "retired",
52
+ "suspended",
53
+ "draft",
54
+ ] as const;
55
+ export type ParticipantStatus = (typeof PARTICIPANT_STATUSES)[number];
56
+
57
+ export const CONSENT_APPROVED_FIELDS = [
58
+ "lifespan.born",
59
+ "lifespan.died",
60
+ "location",
61
+ "bio",
62
+ "photo",
63
+ "sameAs",
64
+ ] as const;
65
+ export type ConsentApprovedField = (typeof CONSENT_APPROVED_FIELDS)[number];
66
+
67
+ const consentSchema = z
68
+ .object({
69
+ consentRecordId: z.string().min(1),
70
+ approvedFields: z.array(z.enum(CONSENT_APPROVED_FIELDS)).default([]),
71
+ approvedMedia: z.array(z.string()).default([]),
72
+ consentDate: z.string().min(1),
73
+ withdrawalRoute: z.string().min(1).optional(),
74
+ profileReviewer: z.string().min(1),
75
+ })
76
+ .strict();
77
+
78
+ const responsibilitySchema = z
79
+ .object({
80
+ summary: z.string(),
81
+ scope: z.string().optional(),
82
+ pbpReferences: z.array(z.string()).default([]),
83
+ })
84
+ .strict();
85
+
86
+ const authoritySchema = z
87
+ .object({
88
+ canSignFor: z.array(z.string()).default([]),
89
+ canCommitTo: z.array(z.string()).default([]),
90
+ escalationRoute: z.string().optional(),
91
+ })
92
+ .strict();
93
+
94
+ const evidenceSchema = z
95
+ .object({
96
+ claims: z
97
+ .array(
98
+ z
99
+ .object({
100
+ claimId: z.string(),
101
+ sourceRef: z.string(),
102
+ verifiedAt: z.string(),
103
+ })
104
+ .strict(),
105
+ )
106
+ .default([]),
107
+ disclosures: z
108
+ .array(
109
+ z
110
+ .object({
111
+ type: z.string(),
112
+ text: z.string(),
113
+ url: z.string().optional(),
114
+ })
115
+ .strict(),
116
+ )
117
+ .default([]),
118
+ })
119
+ .strict();
120
+
121
+ const contactSchema = z
122
+ .object({
123
+ primaryRoute: z.string().optional(),
124
+ pgpFingerprint: z.string().optional(),
125
+ responseTime: z.string().optional(),
126
+ })
127
+ .strict();
128
+
129
+ const lifespanSchema = z
130
+ .object({
131
+ born: z.union([z.string(), z.number()]).optional(),
132
+ died: z.union([z.string(), z.number()]).optional(),
133
+ })
134
+ .strict();
135
+
136
+ const aiAgentFieldsSchema = z
137
+ .object({
138
+ modelId: z.string(),
139
+ provider: z.string(),
140
+ technicalStand: z
141
+ .object({
142
+ agentId: z.string(),
143
+ toolsetVersion: z.string(),
144
+ lastEvaluatedAt: z.string(),
145
+ capabilities: z.array(z.string()).default([]),
146
+ })
147
+ .strict(),
148
+ rightsMatrix: z
149
+ .object({
150
+ canPublish: z.boolean().default(false),
151
+ canEditContent: z.boolean().default(false),
152
+ canManageUsers: z.boolean().default(false),
153
+ canAccessFinancials: z.boolean().default(false),
154
+ })
155
+ .strict(),
156
+ accountableHumanId: z.string().min(1),
157
+ })
158
+ .strict();
159
+
160
+ const organizationUnitFieldsSchema = z
161
+ .object({
162
+ unitName: z.string(),
163
+ parentUnit: z.string().optional(),
164
+ leadParticipantId: z.string().optional(),
165
+ })
166
+ .strict();
167
+
168
+ const externalSpecialistFieldsSchema = z
169
+ .object({
170
+ specialty: z.string(),
171
+ organization: z.string().optional(),
172
+ engagementType: z.string().optional(),
173
+ contractRef: z.string().optional(),
174
+ })
175
+ .strict();
176
+
177
+ const partnerOrganizationFieldsSchema = z
178
+ .object({
179
+ organizationName: z.string(),
180
+ partnershipType: z.string().optional(),
181
+ contactRoute: z.string().optional(),
182
+ })
183
+ .strict();
184
+
185
+ const serviceAccountFieldsSchema = z
186
+ .object({
187
+ serviceName: z.string(),
188
+ provider: z.string(),
189
+ scopeDescription: z.string(),
190
+ credentialsRef: z.string(),
191
+ })
192
+ .strict();
193
+
194
+ export const participantSchema = z
195
+ .object({
196
+ participantId: z.string().min(1),
197
+ participantType: z.enum(PARTICIPANT_TYPES),
198
+ publicName: z.string().min(1),
199
+ slug: z.string().min(1),
200
+ status: z.enum(PARTICIPANT_STATUSES),
201
+ relationshipType: z.enum(PARTICIPANT_RELATIONSHIPS),
202
+
203
+ responsibility: responsibilitySchema.optional(),
204
+ authority: authoritySchema.optional(),
205
+ evidence: evidenceSchema.optional(),
206
+ contact: contactSchema.optional(),
207
+
208
+ visibility: z.enum(["public", "private"]).default("private"),
209
+ profileOwner: z.string().optional(),
210
+ retentionClass: z.enum(["permanent", "standard", "short-term"]).default("standard"),
211
+
212
+ name: z.string().optional(),
213
+ role: z.string().optional(),
214
+ photo: z.string().optional(),
215
+ bio: z.string().optional(),
216
+ affiliations: z.array(z.enum(PERSON_AFFILIATIONS)).default([]),
217
+ order: z.number().int().nonnegative().optional(),
218
+ lifespan: lifespanSchema.optional(),
219
+ statement: z.string().optional(),
220
+ stats: z.array(z.object({ label: z.string(), value: z.string() }).strict()).optional(),
221
+ cta: z.object({ label: z.string(), target: z.string() }).strict().optional(),
222
+ sameAs: z.array(z.string().url()).optional(),
223
+ page: z
224
+ .object({ enabled: z.boolean().default(false) })
225
+ .strict()
226
+ .optional(),
227
+ location: z.string().optional(),
228
+ live: z
229
+ .object({
230
+ src: z.string(),
231
+ poster: z.string().optional(),
232
+ alt: z.string().optional(),
233
+ })
234
+ .strict()
235
+ .optional(),
236
+
237
+ consent: consentSchema.optional(),
238
+
239
+ aiAgent: aiAgentFieldsSchema.optional(),
240
+ organizationUnit: organizationUnitFieldsSchema.optional(),
241
+ externalSpecialist: externalSpecialistFieldsSchema.optional(),
242
+ partnerOrganization: partnerOrganizationFieldsSchema.optional(),
243
+ serviceAccount: serviceAccountFieldsSchema.optional(),
244
+ })
245
+ .strict();
246
+
247
+ export type ParticipantData = z.infer<typeof participantSchema>;
@@ -0,0 +1,24 @@
1
+ /*
2
+ <MODULE_CONTRACT>
3
+ <purpose>
4
+ RFC-0200: closed affiliation vocabulary for Person records. Used by the People
5
+ section check in @warpgogol/site-kernel-checks to validate person affiliations.
6
+ This is a closed vocabulary used by check infrastructure, not PBP entity code.
7
+ </purpose>
8
+ <non-goals>
9
+ <item>Do not export the full personSchema — person records now live in a standalone `people` content collection (RFC-0471).</item>
10
+ </non-goals>
11
+ </MODULE_CONTRACT>
12
+ <CHANGE_SUMMARY>
13
+ <item>RFC-0470: moved PERSON_AFFILIATIONS from @warpgogol/business/schemas/person.ts to @warpgogol/werkstatt-shared/share/schemas/person.ts.</item>
14
+ <item>RFC-0471: @warpgogol/business package deleted. Person records now live in a standalone `people` content collection.</item>
15
+ </CHANGE_SUMMARY>
16
+ */
17
+
18
+ /**
19
+ * Closed affiliation vocabulary. `founder` → Organization.founder, `board` →
20
+ * Organization.member (governance), `team`/`patron`/`author` are presentational
21
+ * roles shown in the People section but not governance JSON-LD.
22
+ */
23
+ export const PERSON_AFFILIATIONS = ["founder", "board", "team", "patron", "author"] as const;
24
+ export type PersonAffiliation = (typeof PERSON_AFFILIATIONS)[number];
@@ -0,0 +1,93 @@
1
+ /*
2
+ <MODULE_CONTRACT>
3
+ <purpose>
4
+ RFC-0257: TypeScript contracts for the print-ready visitor-page system.
5
+ Defines page-level print config, site-level print labels, and the PDF generator
6
+ result shape. Consumed by @warpgogol/werkstatt-shared/ontology schemas, @warpgogol/werkstatt-site/ui layout, and
7
+ @warpgogol/site-kernel-checks validators.
8
+ </purpose>
9
+ <non-goals>
10
+ <item>Do not implement Zod schemas here — @warpgogol/werkstatt-shared/ontology owns the Zod validation schemas.</item>
11
+ <item>Do not import from Astro or app-specific modules.</item>
12
+ <item>Do not define runtime print detection logic — that lives in @warpgogol/werkstatt-site/ui.</item>
13
+ </non-goals>
14
+ </MODULE_CONTRACT>
15
+ <CHANGE_SUMMARY>
16
+ <item>RFC-0257: Initial creation — print content contracts for page frontmatter, site labels, and PDF generator result.</item>
17
+ </CHANGE_SUMMARY>
18
+ */
19
+
20
+ // ---------------------------------------------------------------------------
21
+ // Closed enums
22
+ // ---------------------------------------------------------------------------
23
+
24
+ export const PRINT_ORIENTATIONS = ["portrait", "landscape", "auto"] as const;
25
+ export type PrintOrientation = (typeof PRINT_ORIENTATIONS)[number];
26
+
27
+ export const PRINT_PAGE_SIZES = ["a4", "letter", "legal"] as const;
28
+ export type PrintPageSize = (typeof PRINT_PAGE_SIZES)[number];
29
+
30
+ export const PRINT_MARGINS = ["normal", "narrow", "none"] as const;
31
+ export type PrintMargins = (typeof PRINT_MARGINS)[number];
32
+
33
+ export const PRINT_BACKGROUND_MODES = ["preserve", "flatten"] as const;
34
+ export type PrintBackgroundMode = (typeof PRINT_BACKGROUND_MODES)[number];
35
+
36
+ export const PRINT_REGIONS = [
37
+ "navigation",
38
+ "breadcrumbs",
39
+ "cta",
40
+ "footer-links",
41
+ "header-logo",
42
+ "site-background",
43
+ "hero-animation",
44
+ ] as const;
45
+ export type PrintRegion = (typeof PRINT_REGIONS)[number];
46
+
47
+ // ---------------------------------------------------------------------------
48
+ // Page-level print config (frontmatter `print:` block)
49
+ // ---------------------------------------------------------------------------
50
+
51
+ export interface PagePrintConfig {
52
+ /** When false, no PDF is generated and the browser print shows a disabled notice. Default: true. */
53
+ enabled?: boolean;
54
+ /** Print orientation. Default: auto (generator picks best fit). */
55
+ orientation?: PrintOrientation;
56
+ /** Page size passed to Playwright. Default: a4. */
57
+ pageSize?: PrintPageSize;
58
+ /** Margin preset. Default: normal. */
59
+ margins?: PrintMargins;
60
+ /** When true, expand all <details> before PDF capture. Default: true. */
61
+ expandDetails?: boolean;
62
+ /** Screen regions to suppress in print. Default: []. */
63
+ hide?: PrintRegion[];
64
+ /** Background handling: preserve keeps images/colors, flatten replaces with neutral surface. Default: preserve. */
65
+ background?: PrintBackgroundMode;
66
+ }
67
+
68
+ // ---------------------------------------------------------------------------
69
+ // Site-level print labels (site/{lang}/labels.md `print:` block)
70
+ // ---------------------------------------------------------------------------
71
+
72
+ export interface SitePrintLabels {
73
+ headerLogo?: string;
74
+ headerBrandLabel?: string;
75
+ headerTagline?: string;
76
+ footerLegalNotice?: string;
77
+ footerShowUrl?: boolean;
78
+ footerShowDate?: boolean;
79
+ footerPageNumberLabel?: string;
80
+ printDisabledNotice?: string;
81
+ }
82
+
83
+ // ---------------------------------------------------------------------------
84
+ // PDF generator result (print.pdf.generate command output)
85
+ // ---------------------------------------------------------------------------
86
+
87
+ export interface PrintPdfGenerateResult {
88
+ generated: number;
89
+ skipped: number;
90
+ disabled: number;
91
+ errors: Array<{ route: string; error: string }>;
92
+ outputDir: string;
93
+ }
@@ -0,0 +1,106 @@
1
+ /*
2
+ <MODULE_CONTRACT>
3
+ <purpose>
4
+ [RFC-0101] Canonical SectionBackground discriminated union. Replaces flat
5
+ visual-modifier props (texture / transparent / opacity / verticalFade /
6
+ noTopFade / noBottomFade / topVerticalFadeOpacity / bottomVerticalFadeOpacity)
7
+ across every shared section in packages/ui. Section background is strictly
8
+ independent from the global SiteBackground shell block (RFC-0105).
9
+ </purpose>
10
+ <non-goals>
11
+ <item>Do not include glass effect here (lives in ./glass.ts).</item>
12
+ <item>Do not absorb the full-viewport SiteBackground shell layer (RFC-0105).</item>
13
+ <item>Do not parse image assets; <SectionShell> + <SectionImage> own that.</item>
14
+ </non-goals>
15
+ </MODULE_CONTRACT>
16
+ <CHANGE_SUMMARY>
17
+ <item>RFC-0133: backfilled MODULE_MAP and CHANGE_SUMMARY markers for compass.validate compliance.</item>
18
+ </CHANGE_SUMMARY>
19
+ */
20
+
21
+ import { z } from "zod";
22
+
23
+ const cssValueOrToken = z.string().min(1);
24
+
25
+ /** RFC-0101 — kind: "color". Solid colour background using a CSS token or value. */
26
+ const sectionBackgroundColorSchema = z
27
+ .object({
28
+ kind: z.literal("color"),
29
+ /** Defaults to var(--ds-color-bg) when omitted. */
30
+ color: cssValueOrToken.optional(),
31
+ })
32
+ .strict();
33
+
34
+ /** RFC-0101 — kind: "image". Image background with fit + quality + optional tint overlay. */
35
+ const sectionBackgroundImageSchema = z
36
+ .object({
37
+ kind: z.literal("image"),
38
+ /** Bare image name (RFC-0053); resolved by <SectionShell> via shared image utils. */
39
+ imageName: z.string().min(1),
40
+ fit: z.enum(["cover", "tile", "stretch-width", "stretch-height"]).optional(),
41
+ quality: z.enum(["low", "mid", "high", "max"]).optional(),
42
+ /** 0..1; tint overlay opacity using --ds-color-bg above the image. */
43
+ tintOpacity: z.number().min(0).max(1).optional(),
44
+ })
45
+ .strict();
46
+
47
+ /** RFC-0101 — kind: "texture". Repeating texture pattern (e.g. noise) layered over color. */
48
+ const sectionBackgroundTextureSchema = z
49
+ .object({
50
+ kind: z.literal("texture"),
51
+ /** Texture id — "noise" is the only built-in for now. */
52
+ texture: z.string().min(1),
53
+ })
54
+ .strict();
55
+
56
+ /** RFC-0101 — kind: "transparent". Lets the SiteBackground (RFC-0105) show through. */
57
+ const sectionBackgroundTransparentSchema = z
58
+ .object({
59
+ kind: z.literal("transparent"),
60
+ /** Optional tint opacity (0 = fully transparent, 1 = fully opaque --ds-color-bg). */
61
+ opacity: z.number().min(0).max(1).optional(),
62
+ })
63
+ .strict();
64
+
65
+ /**
66
+ * RFC-0101 — kind: "fade". Linear gradient along one axis. Replaces the
67
+ * legacy verticalFade / noTopFade / noBottomFade / topVerticalFadeOpacity /
68
+ * bottomVerticalFadeOpacity permutation matrix with a single parameterised
69
+ * gradient. Per the accepted RFC, direction is restricted to vertical |
70
+ * horizontal (no diagonal / radial).
71
+ */
72
+ const sectionBackgroundFadeSchema = z
73
+ .object({
74
+ kind: z.literal("fade"),
75
+ direction: z.enum(["vertical", "horizontal"]),
76
+ /** Start colour token / value. Defaults to var(--ds-color-bg). */
77
+ from: cssValueOrToken.optional(),
78
+ /** End colour token / value. Defaults to var(--ds-color-bg). */
79
+ to: cssValueOrToken.optional(),
80
+ /** 0..1; opacity of the gradient at the start edge. Default 1. */
81
+ startOpacity: z.number().min(0).max(1).optional(),
82
+ /** 0..1; opacity of the gradient at the end edge. Default 1. */
83
+ endOpacity: z.number().min(0).max(1).optional(),
84
+ /** 0..0.5; plateau width fraction. Default 0.2. */
85
+ inset: z.number().min(0).max(0.5).optional(),
86
+ /** Suppress fade at the start edge. */
87
+ noStartFade: z.boolean().optional(),
88
+ /** Suppress fade at the end edge. */
89
+ noEndFade: z.boolean().optional(),
90
+ })
91
+ .strict();
92
+
93
+ export const sectionBackgroundSchema = z.discriminatedUnion("kind", [
94
+ sectionBackgroundColorSchema,
95
+ sectionBackgroundImageSchema,
96
+ sectionBackgroundTextureSchema,
97
+ sectionBackgroundTransparentSchema,
98
+ sectionBackgroundFadeSchema,
99
+ ]);
100
+
101
+ export type SectionBackgroundColor = z.infer<typeof sectionBackgroundColorSchema>;
102
+ export type SectionBackgroundImage = z.infer<typeof sectionBackgroundImageSchema>;
103
+ export type SectionBackgroundTexture = z.infer<typeof sectionBackgroundTextureSchema>;
104
+ export type SectionBackgroundTransparent = z.infer<typeof sectionBackgroundTransparentSchema>;
105
+ export type SectionBackgroundFade = z.infer<typeof sectionBackgroundFadeSchema>;
106
+ export type SectionBackground = z.infer<typeof sectionBackgroundSchema>;
@@ -0,0 +1,138 @@
1
+ /*
2
+ <MODULE_CONTRACT>
3
+ <purpose>
4
+ [RFC-0103 + RFC-0134] Canonical SectionBodyContent discriminated union. One shape covers
5
+ every non-composite body kind: list / split-list / stats / cards / paragraphs /
6
+ comparison / rich. Body-level visual effects are authored through composable
7
+ `effects[]` assignments rather than legacy surface-specific props.
8
+ </purpose>
9
+ <non-goals>
10
+ <item>Do not introduce app-specific runtime composition or deployment behavior into this reusable package source file.</item>
11
+ </non-goals>
12
+ </MODULE_CONTRACT>
13
+ <CHANGE_SUMMARY>
14
+ <item>RFC-0133: backfilled MODULE_MAP and CHANGE_SUMMARY markers for compass.validate compliance.</item>
15
+ <item>RFC-0134 replaces legacy surface config with composable effects assignments on supported body kinds.</item>
16
+ </CHANGE_SUMMARY>
17
+ */
18
+
19
+ import { z } from "zod";
20
+ import { effectsSchema } from "./effects.ts";
21
+ import { horizontalAlignSchema } from "./horizontal-align.ts";
22
+ import { iconColorSchema } from "./icon-color.ts";
23
+ import { standardListItemSchema } from "./standard-list-item.ts";
24
+ import { standardCardSchema } from "./section-cards.ts";
25
+ import { statItemSchema } from "./section-stats.ts";
26
+
27
+ export const sectionBodyKindSchema = z.enum([
28
+ "list",
29
+ "split-list",
30
+ "stats",
31
+ "cards",
32
+ "paragraphs",
33
+ "comparison",
34
+ "rich",
35
+ "composite",
36
+ ]);
37
+ export type SectionBodyKind = z.infer<typeof sectionBodyKindSchema>;
38
+
39
+ const listBodySchema = z
40
+ .object({
41
+ kind: z.literal("list"),
42
+ items: z.array(standardListItemSchema).min(1),
43
+ note: z.string().optional(),
44
+ iconColor: iconColorSchema.optional(),
45
+ align: horizontalAlignSchema.optional(),
46
+ itemAlign: horizontalAlignSchema.optional(),
47
+ hideMarkers: z.boolean().optional(),
48
+ effects: effectsSchema.optional(),
49
+ })
50
+ .strict();
51
+
52
+ const splitListBodySchema = z
53
+ .object({
54
+ kind: z.literal("split-list"),
55
+ primaryItems: z.array(standardListItemSchema).min(1),
56
+ secondaryItems: z.array(standardListItemSchema).optional(),
57
+ labels: z
58
+ .object({
59
+ primary: z.string().min(1),
60
+ secondary: z.string().min(1),
61
+ })
62
+ .optional(),
63
+ iconColors: z
64
+ .object({
65
+ primary: iconColorSchema.optional(),
66
+ secondary: iconColorSchema.optional(),
67
+ })
68
+ .optional(),
69
+ align: horizontalAlignSchema.optional(),
70
+ effects: effectsSchema.optional(),
71
+ })
72
+ .strict();
73
+
74
+ const statsBodySchema = z
75
+ .object({
76
+ kind: z.literal("stats"),
77
+ stats: z.array(statItemSchema).min(1),
78
+ animated: z.boolean().optional(),
79
+ align: horizontalAlignSchema.optional(),
80
+ })
81
+ .strict();
82
+
83
+ const cardsBodySchema = z
84
+ .object({
85
+ kind: z.literal("cards"),
86
+ cards: z.array(standardCardSchema).min(1),
87
+ layout: z.enum(["grid", "list"]).optional(),
88
+ columns: z.union([z.literal(2), z.literal(3), z.literal(4)]).optional(),
89
+ align: horizontalAlignSchema.optional(),
90
+ effects: effectsSchema.optional(),
91
+ })
92
+ .strict();
93
+
94
+ const paragraphsBodySchema = z
95
+ .object({
96
+ kind: z.literal("paragraphs"),
97
+ paragraphs: z.array(z.string().min(1)).min(1),
98
+ align: horizontalAlignSchema.optional(),
99
+ })
100
+ .strict();
101
+
102
+ const comparisonBodySchema = z
103
+ .object({
104
+ kind: z.literal("comparison"),
105
+ rows: z.array(z.object({ left: z.string().min(1), right: z.string().min(1) }).strict()).min(1),
106
+ labels: z.object({ left: z.string().min(1), right: z.string().min(1) }).optional(),
107
+ align: horizontalAlignSchema.optional(),
108
+ effects: effectsSchema.optional(),
109
+ })
110
+ .strict();
111
+
112
+ const richBodySchema = z
113
+ .object({
114
+ kind: z.literal("rich"),
115
+ contentRef: z.string().min(1),
116
+ animateNumbers: z.boolean().optional(),
117
+ align: horizontalAlignSchema.optional(),
118
+ })
119
+ .strict();
120
+
121
+ export const sectionBodyContentSchema = z.discriminatedUnion("kind", [
122
+ listBodySchema,
123
+ splitListBodySchema,
124
+ statsBodySchema,
125
+ cardsBodySchema,
126
+ paragraphsBodySchema,
127
+ comparisonBodySchema,
128
+ richBodySchema,
129
+ ]);
130
+
131
+ export type SectionListBody = z.infer<typeof listBodySchema>;
132
+ export type SectionSplitListBody = z.infer<typeof splitListBodySchema>;
133
+ export type SectionStatsBody = z.infer<typeof statsBodySchema>;
134
+ export type SectionCardsBody = z.infer<typeof cardsBodySchema>;
135
+ export type SectionParagraphsBody = z.infer<typeof paragraphsBodySchema>;
136
+ export type SectionComparisonBody = z.infer<typeof comparisonBodySchema>;
137
+ export type SectionRichBody = z.infer<typeof richBodySchema>;
138
+ export type SectionBodyContent = z.infer<typeof sectionBodyContentSchema>;
@@ -0,0 +1,37 @@
1
+ /*
2
+ <MODULE_CONTRACT>
3
+ <purpose>
4
+ [RFC-0103] Canonical StandardCard schema consumed by <SectionCardGrid>. Unifies
5
+ the four ad-hoc card shapes that used to live in `approach`, `audience-cards`,
6
+ `donation-use`, `team` (PersonProfile keeps a richer shape because it owns
7
+ animation hooks).
8
+ </purpose>
9
+ <non-goals>
10
+ <item>Do not introduce app-specific runtime composition or deployment behavior into this reusable package source file.</item>
11
+ </non-goals>
12
+ </MODULE_CONTRACT>
13
+ <CHANGE_SUMMARY>
14
+ <item>RFC-0133: backfilled MODULE_MAP and CHANGE_SUMMARY markers for compass.validate compliance.</item>
15
+ </CHANGE_SUMMARY>
16
+ */
17
+
18
+ import { z } from "zod";
19
+ import { vendorIconConfigSchema } from "./standard-list-item.ts";
20
+
21
+ export const standardCardSchema = z
22
+ .object({
23
+ title: z.string(),
24
+ description: z.string().optional(),
25
+ /** Bare image name (RFC-0053); resolved by <SectionImage> at render. */
26
+ image: z.string().optional(),
27
+ imageAlt: z.string().optional(),
28
+ icon: vendorIconConfigSchema.optional(),
29
+ /** Optional internal pageId or anchor target — turns the card into a link. */
30
+ href: z.string().optional(),
31
+ badge: z.string().optional(),
32
+ /** Optional number display for the card (e.g., "01", "02") */
33
+ number: z.string().optional(),
34
+ })
35
+ .strict();
36
+
37
+ export type StandardCard = z.infer<typeof standardCardSchema>;