@warpgogol/werkstatt-shared 0.14.1 → 0.16.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 (451) hide show
  1. package/README.md +23 -15
  2. package/README.uk.md +1 -1
  3. package/package.json +534 -766
  4. package/src/{share/agent → agent}/api-catalog.ts +14 -1
  5. package/src/{share/agent → agent}/ard-catalog.ts +6 -1
  6. package/src/{share/agent → agent}/dns-aid.test.ts +2 -2
  7. package/src/agent/guidance.ts +52 -0
  8. package/src/agent/health.ts +68 -0
  9. package/src/{share/agent → agent}/index.ts +5 -1
  10. package/src/{share/agent → agent}/manifest.ts +83 -6
  11. package/src/{share/agent → agent}/openapi.ts +97 -4
  12. package/src/agent/receipt.ts +123 -0
  13. package/src/{share/agent → agent}/search.test.ts +3 -0
  14. package/src/{share/agent → agent}/search.ts +31 -5
  15. package/src/{share → agent}/tests/api-catalog.test.ts +8 -2
  16. package/src/{share → agent}/tests/ard-catalog.test.ts +11 -2
  17. package/src/{share → agent}/tests/capability.test.ts +1 -1
  18. package/src/{share → agent}/tests/fleet-catalog.test.ts +1 -1
  19. package/src/{share → agent}/tests/knowledge.test.ts +2 -2
  20. package/src/{share → agent}/tests/manifest.test.ts +72 -1
  21. package/src/{share → agent}/tests/mcp-card.test.ts +6 -2
  22. package/src/{share → agent}/tests/openapi.test.ts +119 -2
  23. package/src/{share → agent}/tests/proof.test.ts +1 -1
  24. package/src/{share → attribution}/material-credits.ts +4 -4
  25. package/src/{share → checks}/check-hints.ts +6 -1
  26. package/src/checks/index.ts +4 -1
  27. package/src/checks/lib/astro-site-url.ts +6 -1
  28. package/src/checks/lib/i18n.ts +14 -0
  29. package/src/checks/result-helpers.ts +2 -2
  30. package/src/checks/tests/remediation-auto-populate.test.ts +1 -1
  31. package/src/{share → client-scripts}/counter-utils.ts +6 -2
  32. package/src/{share/scripts → client-scripts}/external-link-qr.ts +11 -16
  33. package/src/{share/scripts → client-scripts}/external-links.ts +12 -1
  34. package/src/{share/scripts → client-scripts}/gsap-counter.ts +8 -3
  35. package/src/client-scripts/index.ts +35 -0
  36. package/src/{share/scripts → client-scripts}/inline-number-animation.ts +1 -1
  37. package/src/{share/scripts → client-scripts}/lenis.ts +6 -1
  38. package/src/{share/scripts → client-scripts}/lordicon.ts +6 -1
  39. package/src/{share/scripts → client-scripts}/orchestrator.ts +10 -1
  40. package/src/{share/scripts → client-scripts}/scheduler.ts +6 -1
  41. package/src/client-scripts/scroll-spy.ts +106 -0
  42. package/src/client-scripts/tests/orchestrator.test.ts +47 -0
  43. package/src/client-scripts/tests/scroll-spy.test.ts +204 -0
  44. package/src/{share/scripts → client-scripts/tests}/video-player.test.ts +51 -31
  45. package/src/component/contracts.ts +206 -0
  46. package/src/component/index.ts +13 -0
  47. package/src/{share → content}/content-reference.ts +3 -3
  48. package/src/{share/content → content}/entity-id.ts +6 -3
  49. package/src/content/index.ts +3 -0
  50. package/src/{share/content → content}/merge.ts +6 -1
  51. package/src/content/system-manifest.test.ts +107 -0
  52. package/src/content/system-manifest.ts +12 -94
  53. package/src/{share → content}/tests/resolve-field-path.test.ts +1 -1
  54. package/src/{share → content}/tests/substitute-deep.test.ts +1 -1
  55. package/src/content-discipline/index.ts +19 -0
  56. package/src/{share/content-discipline → content-discipline}/parsers.ts +2 -2
  57. package/src/{share/env.d.ts → env.d.ts} +6 -3
  58. package/src/fingerprint/canonical-json.ts +731 -0
  59. package/src/fingerprint/index.ts +14 -0
  60. package/src/fingerprint/primitives.ts +72 -0
  61. package/src/{share/i18n → i18n}/localization.ts +6 -2
  62. package/src/integration/adapters.ts +10 -71
  63. package/src/integration/dispatch.ts +1 -1
  64. package/src/integration/funnel.ts +6 -1
  65. package/src/integration/idempotency.ts +88 -0
  66. package/src/integration/index.ts +105 -4
  67. package/src/integration/lagebild-destination-adapter.ts +108 -0
  68. package/src/integration/lagebild-ingress.ts +7 -12
  69. package/src/integration/orchestration.ts +11 -10
  70. package/src/integration/tests/deliver-event.test.ts +1 -1
  71. package/src/integration/tests/dispatch.test.ts +4 -4
  72. package/src/integration/tests/hub-runtime.test.ts +22 -14
  73. package/src/integration/tests/idempotency.test.ts +81 -0
  74. package/src/integration/vitest.config.ts +1 -0
  75. package/src/kernel/desired-state.ts +227 -0
  76. package/src/kernel/diagnostic.ts +289 -0
  77. package/src/kernel/drift-guard.ts +166 -0
  78. package/src/kernel/fs-atomic.ts +131 -0
  79. package/src/kernel/index.ts +22 -0
  80. package/src/kernel/tests/drift-guard.test.ts +112 -0
  81. package/src/kernel/tests/fs-atomic.test.ts +150 -0
  82. package/src/kernel/tests/workpiece-env.test.ts +44 -0
  83. package/src/kernel/tests/workspace-io.test.ts +187 -0
  84. package/src/kernel/types.ts +518 -0
  85. package/src/kernel/workpiece-env.ts +48 -0
  86. package/src/kernel/workspace-io.ts +248 -0
  87. package/src/{share → knowledge}/tests/claim.test.ts +1 -1
  88. package/src/{share → knowledge}/tests/derivation.test.ts +1 -1
  89. package/src/{share → knowledge}/tests/freshness.test.ts +1 -1
  90. package/src/{share → knowledge}/tests/ledger.test.ts +1 -1
  91. package/src/{share → knowledge}/tests/plan.test.ts +1 -1
  92. package/src/{share → knowledge}/tests/source.test.ts +1 -1
  93. package/src/legal/index.ts +15 -0
  94. package/src/{share/middleware → middleware}/access-protection.ts +11 -8
  95. package/src/{share/middleware → middleware}/language-redirect.ts +3 -0
  96. package/src/{share → node}/dev-props-validator.ts +6 -1
  97. package/src/{share → node}/import-scan.ts +23 -3
  98. package/src/{share → node}/semantic/derived-prices-loader.ts +4 -2
  99. package/src/{share → node}/semantic/markdown-twin-provenance.ts +1 -1
  100. package/src/{share/semantic → node}/tests/derived-prices-loader.test.ts +14 -1
  101. package/src/{share/semantic → node}/tests/markdown-twin-provenance.test.ts +1 -1
  102. package/src/observability/env-resolver.ts +6 -1
  103. package/src/observability/index.ts +14 -1
  104. package/src/observability/otlp-converter.ts +6 -1
  105. package/src/observability/otlp-transport.ts +6 -1
  106. package/src/observability/pipeline-log.ts +81 -0
  107. package/src/observability/pusher.ts +6 -1
  108. package/src/observability/redact.ts +6 -1
  109. package/src/observability/typed-refs.ts +6 -2
  110. package/src/observability/vitest.config.ts +1 -0
  111. package/src/{share → offers}/formula-eval.ts +3 -3
  112. package/src/{share → offers}/tests/formula-eval.test.ts +2 -2
  113. package/src/onboarding/index.ts +1 -0
  114. package/src/{share → onboarding}/tests/onboarding-yaml.test.ts +1 -1
  115. package/src/ontology/archetype-registry.ts +6 -1
  116. package/src/ontology/archetypes/index.json +33 -1
  117. package/src/ontology/archetypes/index.yaml +27 -1
  118. package/src/ontology/archetypes/sections/entity-grid.yaml +46 -0
  119. package/src/ontology/archetypes/sections/exit-diagram.yaml +43 -0
  120. package/src/ontology/biome-token-projection.ts +6 -1
  121. package/src/ontology/capabilities/lead.prepare.yaml +44 -0
  122. package/src/ontology/capabilities/lead.submit.yaml +20 -3
  123. package/src/ontology/cosmic/index.ts +6 -1
  124. package/src/ontology/cosmic/moon-catalog.ts +6 -1
  125. package/src/ontology/cosmic/planet-catalog.ts +6 -1
  126. package/src/ontology/cosmic/star-catalog.ts +6 -1
  127. package/src/ontology/enums.ts +6 -1
  128. package/src/ontology/external-surfaces/index.ts +1 -1
  129. package/src/ontology/index.ts +6 -2
  130. package/src/ontology/manifest.ts +7 -4
  131. package/src/ontology/operations/artifact-store.ts +45 -0
  132. package/src/ontology/operations/dht.ts +98 -0
  133. package/src/ontology/operations/handoff.ts +92 -0
  134. package/src/ontology/operations/index.ts +193 -1
  135. package/src/ontology/operations/leitstand.ts +99 -0
  136. package/src/ontology/operations/materialization.ts +90 -0
  137. package/src/ontology/operations/mission.ts +111 -0
  138. package/src/ontology/operations/naming-policy.ts +132 -0
  139. package/src/ontology/operations/notausgang.ts +108 -0
  140. package/src/ontology/operations/release.ts +121 -0
  141. package/src/ontology/operations/sternsystem.ts +192 -0
  142. package/src/ontology/operations/werkstatt.ts +48 -0
  143. package/src/ontology/schemas/biome.ts +7 -2
  144. package/src/ontology/schemas/capability.ts +56 -4
  145. package/src/ontology/schemas/constellation.ts +6 -1
  146. package/src/ontology/schemas/index.ts +6 -2
  147. package/src/ontology/schemas/manifest-resolver.ts +6 -1
  148. package/src/ontology/schemas/page-entry.ts +9 -5
  149. package/src/ontology/schemas/system/growth.ts +6 -1
  150. package/src/ontology/schemas/system/manifest.ts +40 -1
  151. package/src/ontology/schemas/system/page-output.ts +7 -6
  152. package/src/ontology/schemas/system/text.ts +15 -0
  153. package/src/ontology/schemas/system.ts +6 -2
  154. package/src/ontology/shared-section-props/body-fragments.ts +2 -0
  155. package/src/ontology/tests/sternsystem-owner.test.ts +1 -1
  156. package/src/ontology/vitest.config.ts +1 -0
  157. package/src/{share → page}/page.ts +13 -9
  158. package/src/{share → page}/tests/dev-props-validator.test.ts +1 -1
  159. package/src/{share → page}/tests/hero-section-numbering-parity.test.ts +1 -1
  160. package/src/passport/claim-sign.ts +120 -0
  161. package/src/passport/index.ts +9 -1
  162. package/src/passport/key-rotate.ts +10 -2
  163. package/src/passport/schema.ts +6 -1
  164. package/src/passport/sign.ts +8 -3
  165. package/src/passport/vitest.config.ts +1 -0
  166. package/src/pbt/index.test.ts +95 -0
  167. package/src/pbt/index.ts +251 -0
  168. package/src/plugin/plugin-contract.ts +2 -2
  169. package/src/{share → policy}/entitlement.ts +24 -4
  170. package/src/{share → policy}/feature-policy.ts +8 -3
  171. package/src/{share → policy}/visibility.ts +7 -2
  172. package/src/redirects/redirects.ts +117 -0
  173. package/src/{share → redirects/tests}/redirects.test.ts +1 -1
  174. package/src/remediation/remediation-catalog.ts +316 -0
  175. package/src/{share/routes → routes}/template-filter.ts +1 -1
  176. package/src/{share → runtime}/runtime-context.ts +7 -2
  177. package/src/{share → runtime}/shared-context.ts +1 -1
  178. package/src/{share/schemas → schemas}/claims.ts +2 -2
  179. package/src/{share/schemas → schemas}/effects.ts +6 -1
  180. package/src/{share/schemas → schemas}/features.ts +1 -1
  181. package/src/{share/schemas → schemas}/index.ts +3 -3
  182. package/src/{share/schemas → schemas}/navigation.ts +6 -1
  183. package/src/{share/schemas → schemas}/page-base.ts +6 -2
  184. package/src/{share/schemas → schemas}/person.ts +1 -1
  185. package/src/{share/schemas → schemas}/standard-list-item.ts +1 -1
  186. package/src/{share → sections}/rfc0042-utils.ts +1 -1
  187. package/src/{share/semantic → semantic}/block-extractors/index.ts +20 -1
  188. package/src/{share/semantic → semantic}/business-projection.ts +95 -1
  189. package/src/semantic/canonical-uri.ts +74 -0
  190. package/src/{share/semantic → semantic}/extract.ts +100 -1
  191. package/src/semantic/fact-extraction.test.ts +47 -0
  192. package/src/semantic/fact-extraction.ts +46 -0
  193. package/src/semantic/freshness.ts +67 -0
  194. package/src/{share/semantic → semantic}/ids.ts +6 -1
  195. package/src/{share/semantic → semantic}/index.ts +9 -2
  196. package/src/{share/semantic → semantic}/jsonld/breadcrumb.ts +6 -2
  197. package/src/{share/semantic → semantic}/jsonld/context.ts +6 -2
  198. package/src/{share/semantic → semantic}/jsonld/faq.ts +6 -2
  199. package/src/{share/semantic → semantic}/jsonld/initiative.ts +6 -1
  200. package/src/{share/semantic → semantic}/jsonld/organization.ts +6 -1
  201. package/src/{share/semantic → semantic}/jsonld/person.ts +6 -2
  202. package/src/{share/semantic → semantic}/jsonld/service.ts +6 -2
  203. package/src/semantic/jsonld/shared.ts +36 -0
  204. package/src/semantic/jsonld/types.ts +24 -0
  205. package/src/{share/semantic → semantic}/jsonld/webpage.ts +6 -1
  206. package/src/semantic/jsonld/website.ts +32 -0
  207. package/src/{share/semantic → semantic}/jsonld.ts +6 -1
  208. package/src/{share/semantic → semantic}/llms.ts +51 -5
  209. package/src/{share/semantic → semantic}/models.ts +26 -38
  210. package/src/{share/semantic → semantic}/organization-profile.ts +3 -0
  211. package/src/{share/semantic → semantic}/page-builders/markdown-page.ts +6 -3
  212. package/src/{share/semantic → semantic}/page-utils.ts +6 -3
  213. package/src/{share/tests/breadcrumbs.test.ts → semantic/tests/breadcrumbs-0229.test.ts} +1 -1
  214. package/src/{share → semantic}/tests/build-page-price-markers.test.ts +2 -2
  215. package/src/{share/semantic → semantic}/tests/business-projection.test.ts +179 -0
  216. package/src/semantic/tests/canonical-uri.test.ts +68 -0
  217. package/src/{share/semantic → semantic}/tests/extract.test.ts +83 -0
  218. package/src/semantic/tests/freshness.pbt.test.ts +108 -0
  219. package/src/{share/tests/image-sitemap.test.ts → semantic/tests/image-sitemap-0150.test.ts} +1 -1
  220. package/src/{share → semantic}/tests/jsonld-service.test.ts +2 -2
  221. package/src/{share → semantic}/tests/jsonld-video.test.ts +3 -3
  222. package/src/{share → semantic}/tests/jsonld-webpage.test.ts +3 -3
  223. package/src/{share → semantic}/tests/llms-0789.test.ts +2 -2
  224. package/src/{share/semantic → semantic}/tests/llms.test.ts +46 -0
  225. package/src/{share → semantic}/tests/organization-jsonld.test.ts +3 -3
  226. package/src/{share/tests/output-projection.test.ts → semantic/tests/output-projection-0143.test.ts} +1 -1
  227. package/src/{share/tests/price-marker-resolver.test.ts → semantic/tests/price-marker-resolver-0767.test.ts} +2 -2
  228. package/src/{share/semantic → semantic}/tests/price-marker-resolver.test.ts +4 -2
  229. package/src/semantic/tests/project-claims.pbt.test.ts +60 -0
  230. package/src/{share/semantic → semantic}/tests/split-sentences.test.ts +1 -1
  231. package/src/{share → semantic}/tests/twin-path.test.ts +1 -1
  232. package/src/signing/index.ts +15 -0
  233. package/src/signing/key.ts +139 -0
  234. package/src/signing/sign.ts +66 -0
  235. package/src/signing/types.ts +29 -0
  236. package/src/{share/slug → slug}/slug-url.ts +4 -1
  237. package/src/stack/run-tool.ts +106 -0
  238. package/src/stack/stack-checks.ts +124 -0
  239. package/src/stack/tests/run-tool.test.ts +138 -0
  240. package/src/stack/tests/stack-checks.test.ts +141 -0
  241. package/src/stack/tests/walk-files.test.ts +131 -0
  242. package/src/stack/walk-files.ts +114 -0
  243. package/src/surface/blueprint.ts +342 -66
  244. package/src/surface/decision-composer.ts +6 -1
  245. package/src/surface/geo.ts +6 -1
  246. package/src/surface/index.ts +11 -7
  247. package/src/surface/types.ts +2 -2
  248. package/src/surface/vitest.config.ts +1 -0
  249. package/src/tests/signing-core.test.ts +129 -0
  250. package/src/{share → text}/css-value-normalize.ts +6 -1
  251. package/src/text/string-utils.ts +24 -0
  252. package/src/{share → text}/tests/text-normalize.test.ts +5 -0
  253. package/src/{share → text}/text-normalize.ts +4 -3
  254. package/src/{share → text}/wrap-inline-numbers.ts +1 -1
  255. package/src/types/axiom-study.d.ts +36 -0
  256. package/src/types/hls-js-light.d.ts +21 -0
  257. package/src/types/qrcode-browser.d.ts +23 -0
  258. package/src/typography/fix.pbt.test.ts +208 -0
  259. package/src/typography/fix.ts +148 -0
  260. package/src/typography/index.ts +54 -0
  261. package/src/typography/locale-defaults.ts +97 -0
  262. package/src/typography/rules-tier1.test.ts +459 -0
  263. package/src/typography/rules-tier1.ts +925 -0
  264. package/src/typography/rules-tier2-locale.pbt.test.ts +190 -0
  265. package/src/typography/rules-tier2-locale.test.ts +286 -0
  266. package/src/typography/rules-tier2-locale.ts +399 -0
  267. package/src/typography/rules-tier2-structure.test.ts +330 -0
  268. package/src/typography/rules-tier2-structure.ts +378 -0
  269. package/src/typography/rules-tier3-advisory.test.ts +290 -0
  270. package/src/typography/rules-tier3-advisory.ts +239 -0
  271. package/src/typography/text-surface.test.ts +244 -0
  272. package/src/typography/text-surface.ts +448 -0
  273. package/src/index.ts +0 -14
  274. package/src/integration/port-barrel.ts +0 -105
  275. package/src/share/agent/tests/api-catalog.test.ts +0 -8
  276. package/src/share/agent/tests/ard-catalog.test.ts +0 -8
  277. package/src/share/agent/tests/capability.test.ts +0 -14
  278. package/src/share/agent/tests/fleet-catalog.test.ts +0 -15
  279. package/src/share/agent/tests/knowledge.test.ts +0 -20
  280. package/src/share/agent/tests/manifest.test.ts +0 -9
  281. package/src/share/agent/tests/mcp-card.test.ts +0 -8
  282. package/src/share/agent/tests/openapi.test.ts +0 -8
  283. package/src/share/agent/tests/proof.test.ts +0 -15
  284. package/src/share/content/index.ts +0 -16
  285. package/src/share/content-discipline/index.ts +0 -14
  286. package/src/share/index.ts +0 -86
  287. package/src/share/knowledge/tests/claim.test.ts +0 -11
  288. package/src/share/knowledge/tests/derivation.test.ts +0 -30
  289. package/src/share/knowledge/tests/freshness.test.ts +0 -18
  290. package/src/share/knowledge/tests/ledger.test.ts +0 -35
  291. package/src/share/knowledge/tests/plan.test.ts +0 -19
  292. package/src/share/knowledge/tests/source.test.ts +0 -19
  293. package/src/share/legal/index.ts +0 -1
  294. package/src/share/redirects.ts +0 -54
  295. package/src/share/remediation/remediation-catalog.ts +0 -196
  296. package/src/share/scripts/index.ts +0 -26
  297. package/src/share/scripts/tests/orchestrator.test.ts +0 -8
  298. package/src/share/semantic/jsonld/shared.ts +0 -31
  299. package/src/share/semantic/jsonld/types.ts +0 -19
  300. package/src/share/semantic/jsonld/website.ts +0 -27
  301. package/src/share/string-utils.ts +0 -19
  302. package/src/share/types/axiom-study.d.ts +0 -22
  303. package/src/share/types/hls-js-light.d.ts +0 -16
  304. package/src/share/types/qrcode-browser.d.ts +0 -18
  305. package/src/share/utility-registry.yaml +0 -50
  306. package/src/share/vitest.config.ts +0 -8
  307. package/src/surface/blueprint-schema.ts +0 -314
  308. package/src/surface/blueprint-types.ts +0 -256
  309. /package/src/{share/agent → agent}/capability.ts +0 -0
  310. /package/src/{share/agent → agent}/dns-aid.ts +0 -0
  311. /package/src/{share/agent → agent}/fleet-catalog.ts +0 -0
  312. /package/src/{share/agent → agent}/knowledge.ts +0 -0
  313. /package/src/{share/agent → agent}/mcp-card.ts +0 -0
  314. /package/src/{share/agent → agent}/omit-empty.ts +0 -0
  315. /package/src/{share/agent → agent}/proof.ts +0 -0
  316. /package/src/{share/agent → agent}/tests/omit-empty.test.ts +0 -0
  317. /package/src/{share → attribution}/attribution-display.ts +0 -0
  318. /package/src/{share/scripts → client-scripts}/gsap-mountain-journey.ts +0 -0
  319. /package/src/{share/scripts → client-scripts}/gsap-parallax.ts +0 -0
  320. /package/src/{share/scripts → client-scripts}/gsap-reveal.ts +0 -0
  321. /package/src/{share/scripts → client-scripts}/gsap-stagger.ts +0 -0
  322. /package/src/{share/scripts → client-scripts}/live-photos.ts +0 -0
  323. /package/src/{share/scripts → client-scripts}/tests/external-link-qr.test.ts +0 -0
  324. /package/src/{share/scripts → client-scripts}/tests/external-links.test.ts +0 -0
  325. /package/src/{share/scripts → client-scripts}/tests/gsap-counter.test.ts +0 -0
  326. /package/src/{share/scripts → client-scripts}/tests/gsap-mountain-journey.test.ts +0 -0
  327. /package/src/{share/scripts → client-scripts}/tests/gsap-parallax.test.ts +0 -0
  328. /package/src/{share/scripts → client-scripts}/tests/gsap-reveal.test.ts +0 -0
  329. /package/src/{share/scripts → client-scripts}/tests/gsap-stagger.test.ts +0 -0
  330. /package/src/{share/scripts → client-scripts}/tests/inline-number-animation.test.ts +0 -0
  331. /package/src/{share/scripts → client-scripts}/tests/lenis.test.ts +0 -0
  332. /package/src/{share/scripts → client-scripts}/tests/live-photos.test.ts +0 -0
  333. /package/src/{share/scripts → client-scripts}/tests/lordicon.test.ts +0 -0
  334. /package/src/{share/scripts → client-scripts}/tests/scheduler.test.ts +0 -0
  335. /package/src/{share/scripts → client-scripts}/video-player.ts +0 -0
  336. /package/src/{share/content → content}/resolve-field-path.ts +0 -0
  337. /package/src/{share/content → content}/substitute-deep.ts +0 -0
  338. /package/src/{share → content}/tests/content-ref-index.test.ts +0 -0
  339. /package/src/{share/content-discipline → content-discipline}/types.ts +0 -0
  340. /package/src/{share → image-provider}/image-provider.ts +0 -0
  341. /package/src/{share/knowledge → knowledge}/claim.ts +0 -0
  342. /package/src/{share/knowledge → knowledge}/derivation.ts +0 -0
  343. /package/src/{share/knowledge → knowledge}/freshness.ts +0 -0
  344. /package/src/{share/knowledge → knowledge}/index.ts +0 -0
  345. /package/src/{share/knowledge → knowledge}/ledger.ts +0 -0
  346. /package/src/{share/knowledge → knowledge}/plan.ts +0 -0
  347. /package/src/{share/knowledge → knowledge}/source.ts +0 -0
  348. /package/src/{share/legal → legal}/translation-policy.ts +0 -0
  349. /package/src/{share/middleware → middleware}/tests/access-protection.test.ts +0 -0
  350. /package/src/{share → node}/fs/index.ts +0 -0
  351. /package/src/{share/tests/markdown-twin-provenance.test.ts → node/tests/markdown-twin-provenance-0613.test.ts} +0 -0
  352. /package/src/{share → offers}/offer-capacity.ts +0 -0
  353. /package/src/{share/onboarding-yaml/index.ts → onboarding/yaml.ts} +0 -0
  354. /package/src/{share → ontology}/tests/ontology-role-by-cosmic-name.test.ts +0 -0
  355. /package/src/{share/routes → routes}/tests/template-filter.test.ts +0 -0
  356. /package/src/{share/schemas → schemas}/claim-records.ts +0 -0
  357. /package/src/{share/schemas → schemas}/horizontal-align.ts +0 -0
  358. /package/src/{share/schemas → schemas}/icon-color.ts +0 -0
  359. /package/src/{share/schemas → schemas}/live-photo.ts +0 -0
  360. /package/src/{share/schemas → schemas}/material-credit.ts +0 -0
  361. /package/src/{share/schemas → schemas}/media.ts +0 -0
  362. /package/src/{share/schemas → schemas}/participant.ts +0 -0
  363. /package/src/{share/schemas → schemas}/print.ts +0 -0
  364. /package/src/{share/schemas → schemas}/section-background.ts +0 -0
  365. /package/src/{share/schemas → schemas}/section-body.ts +0 -0
  366. /package/src/{share/schemas → schemas}/section-cards.ts +0 -0
  367. /package/src/{share/schemas → schemas}/section-cta.ts +0 -0
  368. /package/src/{share/schemas → schemas}/section-header.ts +0 -0
  369. /package/src/{share/schemas → schemas}/section-image.ts +0 -0
  370. /package/src/{share/schemas → schemas}/section-motion.ts +0 -0
  371. /package/src/{share/schemas → schemas}/section-shell.ts +0 -0
  372. /package/src/{share/schemas → schemas}/section-stats.ts +0 -0
  373. /package/src/{share/schemas → schemas}/site-background.ts +0 -0
  374. /package/src/{share/schemas → schemas}/tests/claim-records.test.ts +0 -0
  375. /package/src/{share/schemas → schemas}/tests/claims.test.ts +0 -0
  376. /package/src/{share/schemas → schemas}/tests/effects.test.ts +0 -0
  377. /package/src/{share/schemas → schemas}/tests/features.test.ts +0 -0
  378. /package/src/{share/schemas → schemas}/tests/horizontal-align.test.ts +0 -0
  379. /package/src/{share/schemas → schemas}/tests/icon-color.test.ts +0 -0
  380. /package/src/{share/schemas → schemas}/tests/live-photo.test.ts +0 -0
  381. /package/src/{share/schemas → schemas}/tests/material-credit.test.ts +0 -0
  382. /package/src/{share/schemas → schemas}/tests/media.test.ts +0 -0
  383. /package/src/{share/schemas → schemas}/tests/navigation.test.ts +0 -0
  384. /package/src/{share/schemas → schemas}/tests/page-base.test.ts +0 -0
  385. /package/src/{share/schemas → schemas}/tests/participant.test.ts +0 -0
  386. /package/src/{share/schemas → schemas}/tests/person.test.ts +0 -0
  387. /package/src/{share/schemas → schemas}/tests/print.test.ts +0 -0
  388. /package/src/{share/schemas → schemas}/tests/section-background.test.ts +0 -0
  389. /package/src/{share/schemas → schemas}/tests/section-body.test.ts +0 -0
  390. /package/src/{share/schemas → schemas}/tests/section-cards.test.ts +0 -0
  391. /package/src/{share/schemas → schemas}/tests/section-cta.test.ts +0 -0
  392. /package/src/{share/schemas → schemas}/tests/section-header.test.ts +0 -0
  393. /package/src/{share/schemas → schemas}/tests/section-image.test.ts +0 -0
  394. /package/src/{share/schemas → schemas}/tests/section-motion.test.ts +0 -0
  395. /package/src/{share/schemas → schemas}/tests/section-shell.test.ts +0 -0
  396. /package/src/{share/schemas → schemas}/tests/section-stats.test.ts +0 -0
  397. /package/src/{share/schemas → schemas}/tests/site-background.test.ts +0 -0
  398. /package/src/{share/schemas → schemas}/tests/standard-list-item.test.ts +0 -0
  399. /package/src/{share/semantic → semantic}/ai.ts +0 -0
  400. /package/src/{share/semantic → semantic}/block-extraction.ts +0 -0
  401. /package/src/{share/semantic → semantic}/breadcrumbs.ts +0 -0
  402. /package/src/{share/semantic → semantic}/build-page.ts +0 -0
  403. /package/src/{share/semantic → semantic}/feed.ts +0 -0
  404. /package/src/{share/semantic → semantic}/image-sitemap.ts +0 -0
  405. /package/src/{share/semantic → semantic}/jsonld/article.ts +0 -0
  406. /package/src/{share/semantic → semantic}/jsonld/collection-list.ts +0 -0
  407. /package/src/{share/semantic → semantic}/jsonld/tests/article.test.ts +0 -0
  408. /package/src/{share/semantic → semantic}/jsonld/tests/breadcrumb.test.ts +0 -0
  409. /package/src/{share/semantic → semantic}/jsonld/tests/collection-list.test.ts +0 -0
  410. /package/src/{share/semantic → semantic}/jsonld/tests/faq.test.ts +0 -0
  411. /package/src/{share/semantic → semantic}/jsonld/tests/initiative.test.ts +0 -0
  412. /package/src/{share/semantic → semantic}/jsonld/tests/organization.test.ts +0 -0
  413. /package/src/{share/semantic → semantic}/jsonld/tests/person.test.ts +0 -0
  414. /package/src/{share/semantic → semantic}/jsonld/tests/service.test.ts +0 -0
  415. /package/src/{share/semantic → semantic}/jsonld/tests/shared.test.ts +0 -0
  416. /package/src/{share/semantic → semantic}/jsonld/tests/video.test.ts +0 -0
  417. /package/src/{share/semantic → semantic}/jsonld/tests/webpage.test.ts +0 -0
  418. /package/src/{share/semantic → semantic}/jsonld/tests/website.test.ts +0 -0
  419. /package/src/{share/semantic → semantic}/jsonld/video.ts +0 -0
  420. /package/src/{share/semantic → semantic}/llms-policy.ts +0 -0
  421. /package/src/{share/semantic → semantic}/markdown-hygiene.ts +0 -0
  422. /package/src/{share/semantic → semantic}/output-projection.ts +0 -0
  423. /package/src/{share/semantic → semantic}/page-markdown.ts +0 -0
  424. /package/src/{share/semantic → semantic}/price-marker-resolver.ts +0 -0
  425. /package/src/{share/semantic → semantic}/robots.ts +0 -0
  426. /package/src/{share/semantic → semantic}/tests/ai.test.ts +0 -0
  427. /package/src/{share/semantic → semantic}/tests/block-extraction.test.ts +0 -0
  428. /package/src/{share/semantic → semantic}/tests/breadcrumbs.test.ts +0 -0
  429. /package/src/{share/semantic → semantic}/tests/build-page.test.ts +0 -0
  430. /package/src/{share/semantic → semantic}/tests/feed.test.ts +0 -0
  431. /package/src/{share/semantic → semantic}/tests/helpers.ts +0 -0
  432. /package/src/{share/semantic → semantic}/tests/ids.test.ts +0 -0
  433. /package/src/{share/semantic → semantic}/tests/image-sitemap.test.ts +0 -0
  434. /package/src/{share/semantic → semantic}/tests/jsonld.test.ts +0 -0
  435. /package/src/{share/semantic → semantic}/tests/llms-policy.test.ts +0 -0
  436. /package/src/{share/semantic → semantic}/tests/markdown-hygiene.test.ts +0 -0
  437. /package/src/{share/semantic → semantic}/tests/markdown-page.test.ts +0 -0
  438. /package/src/{share/semantic → semantic}/tests/organization-profile.test.ts +0 -0
  439. /package/src/{share/semantic → semantic}/tests/output-projection.test.ts +0 -0
  440. /package/src/{share/semantic → semantic}/tests/page-markdown.test.ts +0 -0
  441. /package/src/{share/semantic → semantic}/tests/page-utils.test.ts +0 -0
  442. /package/src/{share/semantic → semantic}/tests/robots.test.ts +0 -0
  443. /package/src/{share/semantic → semantic}/tests/update-stamp.test.ts +0 -0
  444. /package/src/{share/semantic → semantic}/update-stamp.ts +0 -0
  445. /package/src/{share/slug → slug}/heading-slugger.ts +0 -0
  446. /package/src/{share/slug → slug}/index.ts +0 -0
  447. /package/src/{share/slug → slug}/slug-id.ts +0 -0
  448. /package/src/{share/slug → slug}/strategies.ts +0 -0
  449. /package/src/{share/slug → slug}/tests/slug.test.ts +0 -0
  450. /package/src/{share → text}/tests/text-normalize.pbt.test.ts +0 -0
  451. /package/src/{share → text}/text-position.ts +0 -0
@@ -0,0 +1,120 @@
1
+ /*
2
+ <MODULE_CONTRACT>
3
+ <purpose>
4
+ RFC-1124: Fleet claim signing and verification — canonicalization and
5
+ sign/verify wrappers for FleetClaim, built on the existing Ed25519
6
+ signBytes/verifyBytes primitives from sign.ts. Analogous to dht-sign.ts
7
+ but for the git-native fleet claims registry claim shape.
8
+ </purpose>
9
+ <non-goals>
10
+ <item>Do not handle key storage or management — private keys arrive as env vars.</item>
11
+ <item>Do not assemble W3C VC envelopes — claims use a simple signature string, not VCProof.</item>
12
+ <item>Do not modify sign.ts — this module wraps signBytes/verifyBytes.</item>
13
+ <item>Do not implement claim legitimacy rules (self-claim vs transfer claim) — that lives in the engine's claims-repo.</item>
14
+ </non-goals>
15
+ </MODULE_CONTRACT>
16
+ <CHANGE_SUMMARY>
17
+ <item>RFC-1124: initial fleet claim signing module — FleetClaim contract, claimBytes, signClaim, verifyClaim.</item>
18
+ </CHANGE_SUMMARY>
19
+ */
20
+
21
+ /**
22
+ * @warpgogol/werkstatt-shared/passport/claim-sign — fleet claim signing (RFC-1124)
23
+ *
24
+ * Uses signBytes/verifyBytes from sign.ts with a dedicated canonicalization
25
+ * function for fleet claims. The signature field is excluded from
26
+ * canonicalization (it is computed over the claim data without the signature).
27
+ */
28
+
29
+ import { fromHex } from "@warpgogol/werkstatt-shared/signing";
30
+ import { signBytes, toMultibase, verifyBytes } from "./sign.ts";
31
+
32
+ /**
33
+ * One signed claim file: claims/<system-id>.json in the fleet claims repo.
34
+ *
35
+ * The claim is self-contained for offline signature verification:
36
+ * `signerPublicKey` is embedded, so a verifier needs nothing but the claim
37
+ * file to check the signature. Legitimacy (is this signer allowed to claim?)
38
+ * is decided by the engine — self-claims sign with the creator key, transfer
39
+ * claims sign with the PREVIOUS creator's key and carry `authorizationHash`
40
+ * binding them to the bordbuch `handover` event.
41
+ */
42
+ export interface FleetClaim {
43
+ /** SHA-256 of the canonical passport.json at claim time. */
44
+ passportHash: string;
45
+ systemId: string;
46
+ /** did:web-style creator identity from passport.creator.identity. */
47
+ creatorIdentity: string;
48
+ /** deriveInstanceId(creator.publicKey) — first 16 hex of sha256. */
49
+ instanceId: string;
50
+ /** ISO 8601 — LWW field. */
51
+ claimedAt: string;
52
+ /** Bordbuch tip hash at claim time. */
53
+ bordbuchHead: string;
54
+ /**
55
+ * Tombstone marker — non-null ONLY on a tombstone file: a claim explicitly
56
+ * superseded without a same-id successor (e.g. system-id migration).
57
+ * Normal replacement never writes a tombstone — the new claim replaces the
58
+ * file and git history is the supersession chain.
59
+ */
60
+ supersededBy: string | null;
61
+ /**
62
+ * Hex Ed25519 public key of the signer — same format as
63
+ * passport.creator.publicKey, so deriveInstanceId(signerPublicKey) matches
64
+ * instanceId for self-claims. Embedded so the claims repo is self-contained
65
+ * for offline verification. Equals the creator's key for self-claims;
66
+ * equals the PREVIOUS creator's key for transfer claims.
67
+ */
68
+ signerPublicKey: string;
69
+ /**
70
+ * Transfer claims only: sha256 of the handover-authorization.json that
71
+ * authorizes the creator change (matches bordbuch `handover` event
72
+ * metadata.authorizationHash). Null for self-claims.
73
+ */
74
+ authorizationHash: string | null;
75
+ /** Ed25519 signature over the canonical JSON of all fields above. */
76
+ signature: string;
77
+ }
78
+
79
+ /**
80
+ * FleetClaim without the signature field — the data that is actually signed.
81
+ */
82
+ export type FleetClaimData = Omit<FleetClaim, "signature">;
83
+
84
+ /**
85
+ * Produce canonical UTF-8 bytes from a fleet claim (excluding signature).
86
+ * DETERMINISM: identical inputs → identical bytes (sorted-key JSON, no whitespace).
87
+ */
88
+ export function claimBytes(claim: FleetClaimData): Uint8Array {
89
+ const sorted: Record<string, unknown> = {};
90
+ for (const key of Object.keys(claim).sort()) {
91
+ sorted[key] = (claim as Record<string, unknown>)[key];
92
+ }
93
+ const canonical = JSON.stringify(sorted);
94
+ return new TextEncoder().encode(canonical);
95
+ }
96
+
97
+ /**
98
+ * Sign a fleet claim and return a multibase Ed25519 signature string.
99
+ *
100
+ * @param claim — claim data (without signature)
101
+ * @param privateKeyHex — 32-byte Ed25519 private key as hex (from env secret)
102
+ * @returns multibase base58btc signature string
103
+ */
104
+ export async function signClaim(claim: FleetClaimData, privateKeyHex: string): Promise<string> {
105
+ return signBytes(privateKeyHex, claimBytes(claim));
106
+ }
107
+
108
+ /**
109
+ * Verify a fleet claim signature against the claim's embedded signerPublicKey.
110
+ *
111
+ * @param claim — full fleet claim (including signature)
112
+ * @returns true if signature is valid
113
+ */
114
+ export async function verifyClaim(claim: FleetClaim): Promise<boolean> {
115
+ const { signature, ...claimData } = claim;
116
+ // signerPublicKey is hex (passport.creator.publicKey format); verifyBytes
117
+ // expects multibase — convert here so callers never juggle encodings.
118
+ const signerMultibase = toMultibase(fromHex(claim.signerPublicKey));
119
+ return verifyBytes(signerMultibase, claimBytes(claimData), signature);
120
+ }
@@ -7,7 +7,12 @@
7
7
  </non-goals>
8
8
  </MODULE_CONTRACT>
9
9
  <CHANGE_SUMMARY>
10
- <item>Tidied by compass.changesummary.tidy; see git history for prior entries.</item>
10
+ <item>RFC-1097: step 6 — compass.migrate codemod run
11
+
12
+ Mechanical v1 to v2 header migration across the workspace: 942 files rewritten — CHANGE_SUMMARY windows collapsed into history, forbidden v1 blocks stripped, KEY_DECISIONS seeded from @ai-invariant comments (5 files) or TODO placeholders (103 files), blocks reordered to canonical order.</item>
13
+ <item>RFC-1097: sweep — werkstatt-engine clean
14
+
15
+ Sweep batch 4: 73 Compass headers on headerless engine files (certification, component-runtime, isolation, evolution, testing), real KEY_DECISIONS on 75 files (kernel, cache, dht, swim, gitmesh, runtime), ~80 purpose expansions (CONTRACT-02/PURPOSE-02), non-goals on 13 CONTRACT-03 files, CS-07 history literal fix repo-wide (253 files). Policy: .template.ts/.template.astro excludedPaths. werkstatt-engine now 0 diagnostics.</item>
11
16
  </CHANGE_SUMMARY>
12
17
  */
13
18
 
@@ -51,3 +56,6 @@ export type { IdentityCredentialSubject } from "./identity-sign.ts";
51
56
 
52
57
  export { dhtEntryBytes, signDhtEntry, verifyDhtEntry } from "./dht-sign.ts";
53
58
  export type { DHTEntryData } from "./dht-sign.ts";
59
+
60
+ export { claimBytes, signClaim, verifyClaim } from "./claim-sign.ts";
61
+ export type { FleetClaim, FleetClaimData } from "./claim-sign.ts";
@@ -1,13 +1,21 @@
1
1
  /*
2
2
  <MODULE_CONTRACT>
3
- <purpose>Facilitates the generation and rotation of Ed25519 keypairs for secure application authentication.</purpose>
3
+ <purpose>key-rotate — facilitates the generation and rotation of Ed25519 keypairs for secure application authentication.</purpose>
4
4
  <non-goals>
5
5
  <item>Do not handle raw key parsing or validation beyond schema checks.</item>
6
6
  <item>Do not manage application configuration or orchestration.</item>
7
7
  </non-goals>
8
8
  </MODULE_CONTRACT>
9
9
  <CHANGE_SUMMARY>
10
- <item>Tidied by compass.changesummary.tidy; see git history for prior entries.</item>
10
+ <item>RFC-1097: step 6 — compass.migrate codemod run
11
+
12
+ Mechanical v1 to v2 header migration across the workspace: 942 files rewritten — CHANGE_SUMMARY windows collapsed into history, forbidden v1 blocks stripped, KEY_DECISIONS seeded from @ai-invariant comments (5 files) or TODO placeholders (103 files), blocks reordered to canonical order.</item>
13
+ <item>RFC-1097: sweep — tail packages clean
14
+
15
+ Sweep batch 3: rewrote ~95 purposes across werkstatt-knowledge, werkstatt-shared, godot-game, phaser-game, lifecycle-core, projektarchiv-*, portal-*, billing-*, typescript (CONTRACT-02/PURPOSE-02). Real KEY_DECISIONS on 5 godot utils, non-goals on 5 CONTRACT-03 files, headers on 4 headerless files, CS-07 history literal fix on 2 files. Policy: vitest.config.ts + test-fixtures testPatterns, worker-configuration.d.ts excludedPath. All non-site/engine packages now 0 diagnostics.</item>
16
+ <item>RFC-1097: sweep — werkstatt-engine clean
17
+
18
+ Sweep batch 4: 73 Compass headers on headerless engine files (certification, component-runtime, isolation, evolution, testing), real KEY_DECISIONS on 75 files (kernel, cache, dht, swim, gitmesh, runtime), ~80 purpose expansions (CONTRACT-02/PURPOSE-02), non-goals on 13 CONTRACT-03 files, CS-07 history literal fix repo-wide (253 files). Policy: .template.ts/.template.astro excludedPaths. werkstatt-engine now 0 diagnostics.</item>
11
19
  </CHANGE_SUMMARY>
12
20
  */
13
21
 
@@ -11,7 +11,12 @@
11
11
  </MODULE_CONTRACT>
12
12
 
13
13
  <CHANGE_SUMMARY>
14
- <item>Tidied by compass.changesummary.tidy; see git history for prior entries.</item>
14
+ <item>RFC-1097: step 6 — compass.migrate codemod run
15
+
16
+ Mechanical v1 to v2 header migration across the workspace: 942 files rewritten — CHANGE_SUMMARY windows collapsed into history, forbidden v1 blocks stripped, KEY_DECISIONS seeded from @ai-invariant comments (5 files) or TODO placeholders (103 files), blocks reordered to canonical order.</item>
17
+ <item>RFC-1097: sweep — werkstatt-engine clean
18
+
19
+ Sweep batch 4: 73 Compass headers on headerless engine files (certification, component-runtime, isolation, evolution, testing), real KEY_DECISIONS on 75 files (kernel, cache, dht, swim, gitmesh, runtime), ~80 purpose expansions (CONTRACT-02/PURPOSE-02), non-goals on 13 CONTRACT-03 files, CS-07 history literal fix repo-wide (253 files). Policy: .template.ts/.template.astro excludedPaths. werkstatt-engine now 0 diagnostics.</item>
15
20
  </CHANGE_SUMMARY>
16
21
  *******************************************************************************/
17
22
 
@@ -7,8 +7,13 @@
7
7
  </non-goals>
8
8
  </MODULE_CONTRACT>
9
9
  <CHANGE_SUMMARY>
10
- <item>Tidied by compass.changesummary.tidy; see git history for prior entries.</item>
11
- <item>RFC-0921: delegate Ed25519 sign/verify/keygen to shared signing core (@warpgogol/werkstatt-engine/signing). Remove @noble/ed25519 import.</item>
10
+ <item>RFC-0921: delegate Ed25519 sign/verify/keygen to shared signing core (@warpgogol/werkstatt-shared/signing). Remove @noble/ed25519 import.</item>
11
+ <item>RFC-1097: step 6 — compass.migrate codemod run
12
+
13
+ Mechanical v1 to v2 header migration across the workspace: 942 files rewritten — CHANGE_SUMMARY windows collapsed into history, forbidden v1 blocks stripped, KEY_DECISIONS seeded from @ai-invariant comments (5 files) or TODO placeholders (103 files), blocks reordered to canonical order.</item>
14
+ <item>RFC-1097: sweep — werkstatt-engine clean
15
+
16
+ Sweep batch 4: 73 Compass headers on headerless engine files (certification, component-runtime, isolation, evolution, testing), real KEY_DECISIONS on 75 files (kernel, cache, dht, swim, gitmesh, runtime), ~80 purpose expansions (CONTRACT-02/PURPOSE-02), non-goals on 13 CONTRACT-03 files, CS-07 history literal fix repo-wide (253 files). Policy: .template.ts/.template.astro excludedPaths. werkstatt-engine now 0 diagnostics.</item>
12
17
  </CHANGE_SUMMARY> */
13
18
 
14
19
  /**
@@ -32,7 +37,7 @@ import {
32
37
  verifyBytes as signingVerifyBytes,
33
38
  fromHex,
34
39
  toHex,
35
- } from "@warpgogol/werkstatt-engine/signing";
40
+ } from "@warpgogol/werkstatt-shared/signing";
36
41
  import type { VCProof, VerifiableCredential } from "./schema.ts";
37
42
 
38
43
  // ---------------------------------------------------------------------------
@@ -3,6 +3,7 @@ import { defineConfig } from "vitest/config";
3
3
  export default defineConfig({
4
4
  test: {
5
5
  environment: "node",
6
+ testTimeout: 30_000,
6
7
  include: ["src/**/*.test.ts"],
7
8
  },
8
9
  });
@@ -0,0 +1,95 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import {
3
+ fcAssert,
4
+ letterString,
5
+ composeWord,
6
+ safeText,
7
+ DEFAULT_NUM_RUNS,
8
+ DEFAULT_MAX_SKIPS_PER_RUN,
9
+ } from "./index.ts";
10
+ import fc from "fast-check";
11
+
12
+ describe("PBT helpers", () => {
13
+ describe("constants", () => {
14
+ it("DEFAULT_NUM_RUNS is 50", () => {
15
+ expect(DEFAULT_NUM_RUNS).toBe(50);
16
+ });
17
+
18
+ it("DEFAULT_MAX_SKIPS_PER_RUN is 100", () => {
19
+ expect(DEFAULT_MAX_SKIPS_PER_RUN).toBe(100);
20
+ });
21
+ });
22
+
23
+ describe("letterString", () => {
24
+ it("generates only letters (\\p{L}+)", () => {
25
+ fcAssert(
26
+ fc.property(letterString(1, 10), (word) => {
27
+ return /^\p{L}+$/u.test(word);
28
+ }),
29
+ );
30
+ });
31
+
32
+ it("respects minLength", () => {
33
+ fcAssert(
34
+ fc.property(letterString(3, 5), (word) => {
35
+ return word.length >= 3 && word.length <= 5;
36
+ }),
37
+ );
38
+ });
39
+
40
+ it("never generates empty string when minLength=1", () => {
41
+ fcAssert(
42
+ fc.property(letterString(1, 5), (word) => {
43
+ return word.length > 0;
44
+ }),
45
+ );
46
+ });
47
+ });
48
+
49
+ describe("composeWord", () => {
50
+ it("generates letter + separator + letter", () => {
51
+ const sep = "\u2019";
52
+ fcAssert(
53
+ fc.property(composeWord(sep), (word) => {
54
+ return /\p{L}+\u2019\p{L}+/u.test(word);
55
+ }),
56
+ );
57
+ });
58
+
59
+ it("contains exactly one separator", () => {
60
+ const sep = "-";
61
+ fcAssert(
62
+ fc.property(composeWord(sep), (word) => {
63
+ const count = (word.match(/-/g) ?? []).length;
64
+ return count === 1;
65
+ }),
66
+ );
67
+ });
68
+ });
69
+
70
+ describe("safeText", () => {
71
+ it("respects maxLength", () => {
72
+ fcAssert(
73
+ fc.property(safeText(50), (text) => {
74
+ return text.length <= 50;
75
+ }),
76
+ );
77
+ });
78
+ });
79
+
80
+ describe("fcAssert", () => {
81
+ it("accepts custom numRuns", () => {
82
+ fcAssert(
83
+ fc.property(letterString(1, 3), (word) => word.length > 0),
84
+ { numRuns: 10 },
85
+ );
86
+ });
87
+
88
+ it("accepts custom maxSkipsPerRun", () => {
89
+ fcAssert(
90
+ fc.property(letterString(1, 3), (word) => word.length > 0),
91
+ { maxSkipsPerRun: 50 },
92
+ );
93
+ });
94
+ });
95
+ });
@@ -0,0 +1,251 @@
1
+ /*
2
+ <MODULE_CONTRACT>
3
+ <purpose>
4
+ Canonical PBT (property-based testing) helpers for the Werkstatt.
5
+ Provides safe defaults for `fc.assert` (numRuns, maxSkips) and efficient
6
+ arbitraries that avoid the `fc.string().filter()` anti-pattern that causes
7
+ test hangs when the filter regex rejects most generated candidates.
8
+ </purpose>
9
+ <non-goals>
10
+ <item>Does not wrap every fast-check arbitrary — only the ones that need safety defaults.</item>
11
+ <item>Does not replace `fc.assert` entirely — callers can still use it directly with explicit options.</item>
12
+ </non-goals>
13
+ </MODULE_CONTRACT>
14
+ <CHANGE_SUMMARY>
15
+ <item>RFC-1070: Create PBT helpers (fcAssert, letterString, composeWord) to prevent filter-induced hangs.</item>
16
+ </CHANGE_SUMMARY>
17
+ */
18
+
19
+ import fc from "fast-check";
20
+
21
+ // ---------------------------------------------------------------------------
22
+ // Default PBT configuration
23
+ // ---------------------------------------------------------------------------
24
+
25
+ /** Default number of property runs. fast-check default is 100; we use 50 for speed. */
26
+ export const DEFAULT_NUM_RUNS = 50;
27
+
28
+ /**
29
+ * Default max pre-condition skips per run.
30
+ * fast-check default is 100. We keep it at 100 — this covers `fc.pre()` failures,
31
+ * NOT `.filter()` rejections (which have no limit and are the real hang cause).
32
+ * The hang prevention comes from using `letterString`/`composeWord` instead of
33
+ * `fc.string().filter()`, plus the vitest `testTimeout: 30_000` safety net.
34
+ */
35
+ export const DEFAULT_MAX_SKIPS_PER_RUN = 100;
36
+
37
+ // ---------------------------------------------------------------------------
38
+ // fcAssert — safe wrapper around fc.assert with defaults
39
+ // ---------------------------------------------------------------------------
40
+
41
+ export interface FcAssertOptions {
42
+ numRuns?: number;
43
+ maxSkipsPerRun?: number;
44
+ }
45
+
46
+ /**
47
+ * Wraps `fc.assert` with safe defaults: `numRuns: 50`, `maxSkipsPerRun: 100`.
48
+ * Callers can override either value.
49
+ *
50
+ * Note: `maxSkipsPerRun` only covers `fc.pre()` pre-condition failures.
51
+ * It does NOT cover `.filter()` rejections on arbitraries — those have no
52
+ * limit and are the primary cause of test hangs. Use `letterString` or
53
+ * `composeWord` instead of `fc.string().filter()` to avoid this entirely.
54
+ *
55
+ * @example
56
+ * fcAssert(fc.property(letterString, (word) => { ... }));
57
+ * fcAssert(fc.property(letterString, (word) => { ... }), { numRuns: 100 });
58
+ */
59
+ export function fcAssert<T>(property: fc.IProperty<T>, options?: FcAssertOptions): void {
60
+ fc.assert(property, {
61
+ numRuns: options?.numRuns ?? DEFAULT_NUM_RUNS,
62
+ maxSkipsPerRun: options?.maxSkipsPerRun ?? DEFAULT_MAX_SKIPS_PER_RUN,
63
+ });
64
+ }
65
+
66
+ // ---------------------------------------------------------------------------
67
+ // Efficient letter-only arbitrary — replaces fc.string().filter(/^\p{L}+$/u)
68
+ // ---------------------------------------------------------------------------
69
+
70
+ /**
71
+ * Latin + Cyrillic letter characters for efficient generation.
72
+ * Uses `fc.constantFrom` (no filtering) instead of `fc.string().filter()`.
73
+ */
74
+ const LETTER_CHARS = [
75
+ // Latin lowercase
76
+ "a",
77
+ "b",
78
+ "c",
79
+ "d",
80
+ "e",
81
+ "f",
82
+ "g",
83
+ "h",
84
+ "i",
85
+ "j",
86
+ "k",
87
+ "l",
88
+ "m",
89
+ "n",
90
+ "o",
91
+ "p",
92
+ "q",
93
+ "r",
94
+ "s",
95
+ "t",
96
+ "u",
97
+ "v",
98
+ "w",
99
+ "x",
100
+ "y",
101
+ "z",
102
+ // Latin uppercase
103
+ "A",
104
+ "B",
105
+ "C",
106
+ "D",
107
+ "E",
108
+ "F",
109
+ "G",
110
+ "H",
111
+ "I",
112
+ "J",
113
+ "K",
114
+ "L",
115
+ "M",
116
+ "N",
117
+ "O",
118
+ "P",
119
+ "Q",
120
+ "R",
121
+ "S",
122
+ "T",
123
+ "U",
124
+ "V",
125
+ "W",
126
+ "X",
127
+ "Y",
128
+ "Z",
129
+ // Cyrillic lowercase (Ukrainian + Russian)
130
+ "а",
131
+ "б",
132
+ "в",
133
+ "г",
134
+ "д",
135
+ "е",
136
+ "ж",
137
+ "з",
138
+ "и",
139
+ "і",
140
+ "к",
141
+ "л",
142
+ "м",
143
+ "н",
144
+ "о",
145
+ "п",
146
+ "р",
147
+ "с",
148
+ "т",
149
+ "у",
150
+ "ф",
151
+ "х",
152
+ "ц",
153
+ "ч",
154
+ "ш",
155
+ "щ",
156
+ "ь",
157
+ "ю",
158
+ "я",
159
+ "ї",
160
+ "є",
161
+ "ґ",
162
+ // Cyrillic uppercase
163
+ "А",
164
+ "Б",
165
+ "В",
166
+ "Г",
167
+ "Д",
168
+ "Е",
169
+ "Ж",
170
+ "З",
171
+ "И",
172
+ "І",
173
+ "К",
174
+ "Л",
175
+ "М",
176
+ "Н",
177
+ "О",
178
+ "П",
179
+ "Р",
180
+ "С",
181
+ "Т",
182
+ "У",
183
+ "Ф",
184
+ "Х",
185
+ "Ц",
186
+ "Ч",
187
+ "Ш",
188
+ "Щ",
189
+ "Ь",
190
+ "Ю",
191
+ "Я",
192
+ "Ї",
193
+ "Є",
194
+ "Ґ",
195
+ ];
196
+
197
+ const letterArb = fc.constantFrom(...LETTER_CHARS);
198
+
199
+ /**
200
+ * Generates strings consisting only of letters (Latin + Cyrillic).
201
+ * Efficient: uses `fc.constantFrom` + `fc.array` — no filtering.
202
+ *
203
+ * @example
204
+ * const word = letterString(1, 5); // 1-5 letter word
205
+ * fcAssert(fc.property(word, (w) => /^\p{L}+$/u.test(w)));
206
+ */
207
+ export function letterString(minLength = 1, maxLength = 10): fc.Arbitrary<string> {
208
+ return fc.array(letterArb, { minLength, maxLength }).map((arr) => arr.join(""));
209
+ }
210
+
211
+ // ---------------------------------------------------------------------------
212
+ // composeWord — builds words with guaranteed structure (no filter needed)
213
+ // ---------------------------------------------------------------------------
214
+
215
+ export interface ComposeWordOptions {
216
+ minLength?: number;
217
+ maxLength?: number;
218
+ }
219
+
220
+ /**
221
+ * Generates words with a guaranteed `letter + separator + letter` structure.
222
+ * Eliminates the need for `fc.string().filter()` when testing pattern-based rules.
223
+ *
224
+ * @example
225
+ * const curlyAposWord = composeWord("\u2019"); // e.g. "ім'я"
226
+ * const modAposWord = composeWord("\u02BC"); // e.g. "імʼя"
227
+ */
228
+ export function composeWord(separator: string, options?: ComposeWordOptions): fc.Arbitrary<string> {
229
+ const min = options?.minLength ?? 1;
230
+ const max = options?.maxLength ?? 5;
231
+ return fc
232
+ .tuple(letterString(min, max), letterString(min, max))
233
+ .map(([a, b]) => `${a}${separator}${b}`);
234
+ }
235
+
236
+ // ---------------------------------------------------------------------------
237
+ // safeText — bounded-length string for negative tests (no filter needed)
238
+ // ---------------------------------------------------------------------------
239
+
240
+ /**
241
+ * Generates random strings with a max length for negative property tests.
242
+ * Use when the property should NOT fire on arbitrary text — the test verifies
243
+ * that no findings are produced. The `maxLength` bound prevents excessive
244
+ * string generation time.
245
+ *
246
+ * @example
247
+ * fcAssert(fc.property(safeText(80), (text) => runRule("TYPO-XX", text).length === 0));
248
+ */
249
+ export function safeText(maxLength = 80): fc.Arbitrary<string> {
250
+ return fc.string({ maxLength });
251
+ }
@@ -14,7 +14,7 @@ are shared infrastructure, not engine internals.</purpose>
14
14
  <item>RFC-0942: moved from werkstatt-engine/src/plugin-contract.ts to werkstatt-shared/src/plugin/plugin-contract.ts.</item>
15
15
  </CHANGE_SUMMARY>
16
16
  */
17
- import type { KernelModule, KernelPipelineStep } from "@warpgogol/werkstatt-engine/kernel/types";
17
+ import type { KernelModule, KernelPipelineStep } from "@warpgogol/werkstatt-shared/kernel";
18
18
 
19
19
  /**
20
20
  * Placeholder type for deploy adapter factories.
@@ -95,7 +95,7 @@ export interface WerkstattPlugin {
95
95
  schema: "werkstatt/plugin@1";
96
96
  /** Plugin id: "werkstatt-site" | "werkstatt-phaser-game" | "werkstatt-godot-game". */
97
97
  id: string;
98
- /** Forge stack profile id, e.g. "astro-typescript-turborepo". */
98
+ /** Forge stack profile id, e.g. "site". */
99
99
  profileId: string;
100
100
  /** Kernel modules the plugin contributes (validators, codegen, content, onboarding). */
101
101
  moduleLoaders: Record<string, () => Promise<KernelModule>>;
@@ -10,10 +10,16 @@ agnostic contract consumed by the build-time resolver, the feature gates, and ru
10
10
  </non-goals>
11
11
  </MODULE_CONTRACT>
12
12
  <CHANGE_SUMMARY>
13
- <item>RFC-0169: initial implementation.</item>
14
13
  <item>RFC-0706: add nachweis feature for Nachweisregister commercial module.</item>
15
14
  <item>RFC-0741: add multi-currency feature for multi-currency build pipeline.</item>
16
15
  <item>RFC-0932: add external-link-qr feature for QR code modal entitlement module.</item>
16
+ <item>RFC-1097: step 6 — compass.migrate codemod run
17
+
18
+ Mechanical v1 to v2 header migration across the workspace: 942 files rewritten — CHANGE_SUMMARY windows collapsed into history, forbidden v1 blocks stripped, KEY_DECISIONS seeded from @ai-invariant comments (5 files) or TODO placeholders (103 files), blocks reordered to canonical order.</item>
19
+ <item>RFC-1097: sweep — werkstatt-engine clean
20
+
21
+ Sweep batch 4: 73 Compass headers on headerless engine files (certification, component-runtime, isolation, evolution, testing), real KEY_DECISIONS on 75 files (kernel, cache, dht, swim, gitmesh, runtime), ~80 purpose expansions (CONTRACT-02/PURPOSE-02), non-goals on 13 CONTRACT-03 files, CS-07 history literal fix repo-wide (253 files). Policy: .template.ts/.template.astro excludedPaths. werkstatt-engine now 0 diagnostics.</item>
22
+ <history>RFC-0169</history>
17
23
  </CHANGE_SUMMARY>
18
24
  */
19
25
 
@@ -42,6 +48,12 @@ export const ENTITLED_FEATURES = [
42
48
  "external-link-qr",
43
49
  ] as const;
44
50
 
51
+ /**
52
+ * Features that are always enabled for all sites, regardless of Stripe or override state.
53
+ * These are platform-level capabilities that every site gets for free.
54
+ */
55
+ export const FREE_ENTITLED_FEATURES: EntitledFeature[] = ["external-link-qr"];
56
+
45
57
  export type EntitledFeature = (typeof ENTITLED_FEATURES)[number];
46
58
 
47
59
  /** Stripe Feature `lookup_key` → EntitledFeature. The single mapping point. */
@@ -149,10 +161,13 @@ export function resolveEntitlements(input: {
149
161
  ? { pseo: { indexBudget: input.pseoIndexBudget, regionalUnlocked } }
150
162
  : {};
151
163
 
164
+ const mergeFree = (features: string[]): EntitledFeature[] =>
165
+ dedupe([...features, ...FREE_ENTITLED_FEATURES]);
166
+
152
167
  if (input.override && input.override.length > 0) {
153
168
  return {
154
169
  customerId: input.customerId,
155
- features: dedupe(input.override),
170
+ features: mergeFree(input.override),
156
171
  source: "override",
157
172
  ...pseo,
158
173
  };
@@ -160,12 +175,17 @@ export function resolveEntitlements(input: {
160
175
  if (input.stripeFeatures) {
161
176
  return {
162
177
  customerId: input.customerId,
163
- features: dedupe(input.stripeFeatures),
178
+ features: mergeFree(input.stripeFeatures),
164
179
  source: "stripe",
165
180
  ...pseo,
166
181
  };
167
182
  }
168
- return { customerId: input.customerId, features: [], source: "none", ...pseo };
183
+ return {
184
+ customerId: input.customerId,
185
+ features: dedupe([...FREE_ENTITLED_FEATURES]),
186
+ source: "none",
187
+ ...pseo,
188
+ };
169
189
  }
170
190
 
171
191
  /** Reader used by build gates (which modules compile) and runtime endpoints. */
@@ -9,7 +9,12 @@
9
9
  </MODULE_CONTRACT>
10
10
  <CHANGE_SUMMARY>
11
11
  <item>RFC-0183: Initial runtime resolver for Feature Policy without Feature Graph dependency.</item>
12
- <item>Removed false async from resolveFeaturePolicy; resolveFeaturePolicySync is now a thin alias.</item>
12
+ <item>RFC-1097: step 6 — compass.migrate codemod run
13
+
14
+ Mechanical v1 to v2 header migration across the workspace: 942 files rewritten — CHANGE_SUMMARY windows collapsed into history, forbidden v1 blocks stripped, KEY_DECISIONS seeded from @ai-invariant comments (5 files) or TODO placeholders (103 files), blocks reordered to canonical order.</item>
15
+ <item>RFC-1097: sweep — werkstatt-engine clean
16
+
17
+ Sweep batch 4: 73 Compass headers on headerless engine files (certification, component-runtime, isolation, evolution, testing), real KEY_DECISIONS on 75 files (kernel, cache, dht, swim, gitmesh, runtime), ~80 purpose expansions (CONTRACT-02/PURPOSE-02), non-goals on 13 CONTRACT-03 files, CS-07 history literal fix repo-wide (253 files). Policy: .template.ts/.template.astro excludedPaths. werkstatt-engine now 0 diagnostics.</item>
13
18
  </CHANGE_SUMMARY>
14
19
  */
15
20
 
@@ -19,7 +24,7 @@ import type {
19
24
  FeaturePolicyTargetRef,
20
25
  FeaturePolicyVisibility,
21
26
  ResolvedFeaturePolicy,
22
- } from "./schemas/features.ts";
27
+ } from "../schemas/features.ts";
23
28
 
24
29
  // Re-export types for consumers
25
30
  export type {
@@ -29,7 +34,7 @@ export type {
29
34
  FeaturePolicyTargetRef,
30
35
  FeaturePolicyVisibility,
31
36
  ResolvedFeaturePolicy,
32
- } from "./schemas/features.ts";
37
+ } from "../schemas/features.ts";
33
38
 
34
39
  export interface FeaturePolicyResolverOptions {
35
40
  /**