@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.
- package/README.md +23 -15
- package/README.uk.md +1 -1
- package/package.json +534 -766
- package/src/{share/agent → agent}/api-catalog.ts +14 -1
- package/src/{share/agent → agent}/ard-catalog.ts +6 -1
- package/src/{share/agent → agent}/dns-aid.test.ts +2 -2
- package/src/agent/guidance.ts +52 -0
- package/src/agent/health.ts +68 -0
- package/src/{share/agent → agent}/index.ts +5 -1
- package/src/{share/agent → agent}/manifest.ts +83 -6
- package/src/{share/agent → agent}/openapi.ts +97 -4
- package/src/agent/receipt.ts +123 -0
- package/src/{share/agent → agent}/search.test.ts +3 -0
- package/src/{share/agent → agent}/search.ts +31 -5
- package/src/{share → agent}/tests/api-catalog.test.ts +8 -2
- package/src/{share → agent}/tests/ard-catalog.test.ts +11 -2
- package/src/{share → agent}/tests/capability.test.ts +1 -1
- package/src/{share → agent}/tests/fleet-catalog.test.ts +1 -1
- package/src/{share → agent}/tests/knowledge.test.ts +2 -2
- package/src/{share → agent}/tests/manifest.test.ts +72 -1
- package/src/{share → agent}/tests/mcp-card.test.ts +6 -2
- package/src/{share → agent}/tests/openapi.test.ts +119 -2
- package/src/{share → agent}/tests/proof.test.ts +1 -1
- package/src/{share → attribution}/material-credits.ts +4 -4
- package/src/{share → checks}/check-hints.ts +6 -1
- package/src/checks/index.ts +4 -1
- package/src/checks/lib/astro-site-url.ts +6 -1
- package/src/checks/lib/i18n.ts +14 -0
- package/src/checks/result-helpers.ts +2 -2
- package/src/checks/tests/remediation-auto-populate.test.ts +1 -1
- package/src/{share → client-scripts}/counter-utils.ts +6 -2
- package/src/{share/scripts → client-scripts}/external-link-qr.ts +11 -16
- package/src/{share/scripts → client-scripts}/external-links.ts +12 -1
- package/src/{share/scripts → client-scripts}/gsap-counter.ts +8 -3
- package/src/client-scripts/index.ts +35 -0
- package/src/{share/scripts → client-scripts}/inline-number-animation.ts +1 -1
- package/src/{share/scripts → client-scripts}/lenis.ts +6 -1
- package/src/{share/scripts → client-scripts}/lordicon.ts +6 -1
- package/src/{share/scripts → client-scripts}/orchestrator.ts +10 -1
- package/src/{share/scripts → client-scripts}/scheduler.ts +6 -1
- package/src/client-scripts/scroll-spy.ts +106 -0
- package/src/client-scripts/tests/orchestrator.test.ts +47 -0
- package/src/client-scripts/tests/scroll-spy.test.ts +204 -0
- package/src/{share/scripts → client-scripts/tests}/video-player.test.ts +51 -31
- package/src/component/contracts.ts +206 -0
- package/src/component/index.ts +13 -0
- package/src/{share → content}/content-reference.ts +3 -3
- package/src/{share/content → content}/entity-id.ts +6 -3
- package/src/content/index.ts +3 -0
- package/src/{share/content → content}/merge.ts +6 -1
- package/src/content/system-manifest.test.ts +107 -0
- package/src/content/system-manifest.ts +12 -94
- package/src/{share → content}/tests/resolve-field-path.test.ts +1 -1
- package/src/{share → content}/tests/substitute-deep.test.ts +1 -1
- package/src/content-discipline/index.ts +19 -0
- package/src/{share/content-discipline → content-discipline}/parsers.ts +2 -2
- package/src/{share/env.d.ts → env.d.ts} +6 -3
- package/src/fingerprint/canonical-json.ts +731 -0
- package/src/fingerprint/index.ts +14 -0
- package/src/fingerprint/primitives.ts +72 -0
- package/src/{share/i18n → i18n}/localization.ts +6 -2
- package/src/integration/adapters.ts +10 -71
- package/src/integration/dispatch.ts +1 -1
- package/src/integration/funnel.ts +6 -1
- package/src/integration/idempotency.ts +88 -0
- package/src/integration/index.ts +105 -4
- package/src/integration/lagebild-destination-adapter.ts +108 -0
- package/src/integration/lagebild-ingress.ts +7 -12
- package/src/integration/orchestration.ts +11 -10
- package/src/integration/tests/deliver-event.test.ts +1 -1
- package/src/integration/tests/dispatch.test.ts +4 -4
- package/src/integration/tests/hub-runtime.test.ts +22 -14
- package/src/integration/tests/idempotency.test.ts +81 -0
- package/src/integration/vitest.config.ts +1 -0
- package/src/kernel/desired-state.ts +227 -0
- package/src/kernel/diagnostic.ts +289 -0
- package/src/kernel/drift-guard.ts +166 -0
- package/src/kernel/fs-atomic.ts +131 -0
- package/src/kernel/index.ts +22 -0
- package/src/kernel/tests/drift-guard.test.ts +112 -0
- package/src/kernel/tests/fs-atomic.test.ts +150 -0
- package/src/kernel/tests/workpiece-env.test.ts +44 -0
- package/src/kernel/tests/workspace-io.test.ts +187 -0
- package/src/kernel/types.ts +518 -0
- package/src/kernel/workpiece-env.ts +48 -0
- package/src/kernel/workspace-io.ts +248 -0
- package/src/{share → knowledge}/tests/claim.test.ts +1 -1
- package/src/{share → knowledge}/tests/derivation.test.ts +1 -1
- package/src/{share → knowledge}/tests/freshness.test.ts +1 -1
- package/src/{share → knowledge}/tests/ledger.test.ts +1 -1
- package/src/{share → knowledge}/tests/plan.test.ts +1 -1
- package/src/{share → knowledge}/tests/source.test.ts +1 -1
- package/src/legal/index.ts +15 -0
- package/src/{share/middleware → middleware}/access-protection.ts +11 -8
- package/src/{share/middleware → middleware}/language-redirect.ts +3 -0
- package/src/{share → node}/dev-props-validator.ts +6 -1
- package/src/{share → node}/import-scan.ts +23 -3
- package/src/{share → node}/semantic/derived-prices-loader.ts +4 -2
- package/src/{share → node}/semantic/markdown-twin-provenance.ts +1 -1
- package/src/{share/semantic → node}/tests/derived-prices-loader.test.ts +14 -1
- package/src/{share/semantic → node}/tests/markdown-twin-provenance.test.ts +1 -1
- package/src/observability/env-resolver.ts +6 -1
- package/src/observability/index.ts +14 -1
- package/src/observability/otlp-converter.ts +6 -1
- package/src/observability/otlp-transport.ts +6 -1
- package/src/observability/pipeline-log.ts +81 -0
- package/src/observability/pusher.ts +6 -1
- package/src/observability/redact.ts +6 -1
- package/src/observability/typed-refs.ts +6 -2
- package/src/observability/vitest.config.ts +1 -0
- package/src/{share → offers}/formula-eval.ts +3 -3
- package/src/{share → offers}/tests/formula-eval.test.ts +2 -2
- package/src/onboarding/index.ts +1 -0
- package/src/{share → onboarding}/tests/onboarding-yaml.test.ts +1 -1
- package/src/ontology/archetype-registry.ts +6 -1
- package/src/ontology/archetypes/index.json +33 -1
- package/src/ontology/archetypes/index.yaml +27 -1
- package/src/ontology/archetypes/sections/entity-grid.yaml +46 -0
- package/src/ontology/archetypes/sections/exit-diagram.yaml +43 -0
- package/src/ontology/biome-token-projection.ts +6 -1
- package/src/ontology/capabilities/lead.prepare.yaml +44 -0
- package/src/ontology/capabilities/lead.submit.yaml +20 -3
- package/src/ontology/cosmic/index.ts +6 -1
- package/src/ontology/cosmic/moon-catalog.ts +6 -1
- package/src/ontology/cosmic/planet-catalog.ts +6 -1
- package/src/ontology/cosmic/star-catalog.ts +6 -1
- package/src/ontology/enums.ts +6 -1
- package/src/ontology/external-surfaces/index.ts +1 -1
- package/src/ontology/index.ts +6 -2
- package/src/ontology/manifest.ts +7 -4
- package/src/ontology/operations/artifact-store.ts +45 -0
- package/src/ontology/operations/dht.ts +98 -0
- package/src/ontology/operations/handoff.ts +92 -0
- package/src/ontology/operations/index.ts +193 -1
- package/src/ontology/operations/leitstand.ts +99 -0
- package/src/ontology/operations/materialization.ts +90 -0
- package/src/ontology/operations/mission.ts +111 -0
- package/src/ontology/operations/naming-policy.ts +132 -0
- package/src/ontology/operations/notausgang.ts +108 -0
- package/src/ontology/operations/release.ts +121 -0
- package/src/ontology/operations/sternsystem.ts +192 -0
- package/src/ontology/operations/werkstatt.ts +48 -0
- package/src/ontology/schemas/biome.ts +7 -2
- package/src/ontology/schemas/capability.ts +56 -4
- package/src/ontology/schemas/constellation.ts +6 -1
- package/src/ontology/schemas/index.ts +6 -2
- package/src/ontology/schemas/manifest-resolver.ts +6 -1
- package/src/ontology/schemas/page-entry.ts +9 -5
- package/src/ontology/schemas/system/growth.ts +6 -1
- package/src/ontology/schemas/system/manifest.ts +40 -1
- package/src/ontology/schemas/system/page-output.ts +7 -6
- package/src/ontology/schemas/system/text.ts +15 -0
- package/src/ontology/schemas/system.ts +6 -2
- package/src/ontology/shared-section-props/body-fragments.ts +2 -0
- package/src/ontology/tests/sternsystem-owner.test.ts +1 -1
- package/src/ontology/vitest.config.ts +1 -0
- package/src/{share → page}/page.ts +13 -9
- package/src/{share → page}/tests/dev-props-validator.test.ts +1 -1
- package/src/{share → page}/tests/hero-section-numbering-parity.test.ts +1 -1
- package/src/passport/claim-sign.ts +120 -0
- package/src/passport/index.ts +9 -1
- package/src/passport/key-rotate.ts +10 -2
- package/src/passport/schema.ts +6 -1
- package/src/passport/sign.ts +8 -3
- package/src/passport/vitest.config.ts +1 -0
- package/src/pbt/index.test.ts +95 -0
- package/src/pbt/index.ts +251 -0
- package/src/plugin/plugin-contract.ts +2 -2
- package/src/{share → policy}/entitlement.ts +24 -4
- package/src/{share → policy}/feature-policy.ts +8 -3
- package/src/{share → policy}/visibility.ts +7 -2
- package/src/redirects/redirects.ts +117 -0
- package/src/{share → redirects/tests}/redirects.test.ts +1 -1
- package/src/remediation/remediation-catalog.ts +316 -0
- package/src/{share/routes → routes}/template-filter.ts +1 -1
- package/src/{share → runtime}/runtime-context.ts +7 -2
- package/src/{share → runtime}/shared-context.ts +1 -1
- package/src/{share/schemas → schemas}/claims.ts +2 -2
- package/src/{share/schemas → schemas}/effects.ts +6 -1
- package/src/{share/schemas → schemas}/features.ts +1 -1
- package/src/{share/schemas → schemas}/index.ts +3 -3
- package/src/{share/schemas → schemas}/navigation.ts +6 -1
- package/src/{share/schemas → schemas}/page-base.ts +6 -2
- package/src/{share/schemas → schemas}/person.ts +1 -1
- package/src/{share/schemas → schemas}/standard-list-item.ts +1 -1
- package/src/{share → sections}/rfc0042-utils.ts +1 -1
- package/src/{share/semantic → semantic}/block-extractors/index.ts +20 -1
- package/src/{share/semantic → semantic}/business-projection.ts +95 -1
- package/src/semantic/canonical-uri.ts +74 -0
- package/src/{share/semantic → semantic}/extract.ts +100 -1
- package/src/semantic/fact-extraction.test.ts +47 -0
- package/src/semantic/fact-extraction.ts +46 -0
- package/src/semantic/freshness.ts +67 -0
- package/src/{share/semantic → semantic}/ids.ts +6 -1
- package/src/{share/semantic → semantic}/index.ts +9 -2
- package/src/{share/semantic → semantic}/jsonld/breadcrumb.ts +6 -2
- package/src/{share/semantic → semantic}/jsonld/context.ts +6 -2
- package/src/{share/semantic → semantic}/jsonld/faq.ts +6 -2
- package/src/{share/semantic → semantic}/jsonld/initiative.ts +6 -1
- package/src/{share/semantic → semantic}/jsonld/organization.ts +6 -1
- package/src/{share/semantic → semantic}/jsonld/person.ts +6 -2
- package/src/{share/semantic → semantic}/jsonld/service.ts +6 -2
- package/src/semantic/jsonld/shared.ts +36 -0
- package/src/semantic/jsonld/types.ts +24 -0
- package/src/{share/semantic → semantic}/jsonld/webpage.ts +6 -1
- package/src/semantic/jsonld/website.ts +32 -0
- package/src/{share/semantic → semantic}/jsonld.ts +6 -1
- package/src/{share/semantic → semantic}/llms.ts +51 -5
- package/src/{share/semantic → semantic}/models.ts +26 -38
- package/src/{share/semantic → semantic}/organization-profile.ts +3 -0
- package/src/{share/semantic → semantic}/page-builders/markdown-page.ts +6 -3
- package/src/{share/semantic → semantic}/page-utils.ts +6 -3
- package/src/{share/tests/breadcrumbs.test.ts → semantic/tests/breadcrumbs-0229.test.ts} +1 -1
- package/src/{share → semantic}/tests/build-page-price-markers.test.ts +2 -2
- package/src/{share/semantic → semantic}/tests/business-projection.test.ts +179 -0
- package/src/semantic/tests/canonical-uri.test.ts +68 -0
- package/src/{share/semantic → semantic}/tests/extract.test.ts +83 -0
- package/src/semantic/tests/freshness.pbt.test.ts +108 -0
- package/src/{share/tests/image-sitemap.test.ts → semantic/tests/image-sitemap-0150.test.ts} +1 -1
- package/src/{share → semantic}/tests/jsonld-service.test.ts +2 -2
- package/src/{share → semantic}/tests/jsonld-video.test.ts +3 -3
- package/src/{share → semantic}/tests/jsonld-webpage.test.ts +3 -3
- package/src/{share → semantic}/tests/llms-0789.test.ts +2 -2
- package/src/{share/semantic → semantic}/tests/llms.test.ts +46 -0
- package/src/{share → semantic}/tests/organization-jsonld.test.ts +3 -3
- package/src/{share/tests/output-projection.test.ts → semantic/tests/output-projection-0143.test.ts} +1 -1
- package/src/{share/tests/price-marker-resolver.test.ts → semantic/tests/price-marker-resolver-0767.test.ts} +2 -2
- package/src/{share/semantic → semantic}/tests/price-marker-resolver.test.ts +4 -2
- package/src/semantic/tests/project-claims.pbt.test.ts +60 -0
- package/src/{share/semantic → semantic}/tests/split-sentences.test.ts +1 -1
- package/src/{share → semantic}/tests/twin-path.test.ts +1 -1
- package/src/signing/index.ts +15 -0
- package/src/signing/key.ts +139 -0
- package/src/signing/sign.ts +66 -0
- package/src/signing/types.ts +29 -0
- package/src/{share/slug → slug}/slug-url.ts +4 -1
- package/src/stack/run-tool.ts +106 -0
- package/src/stack/stack-checks.ts +124 -0
- package/src/stack/tests/run-tool.test.ts +138 -0
- package/src/stack/tests/stack-checks.test.ts +141 -0
- package/src/stack/tests/walk-files.test.ts +131 -0
- package/src/stack/walk-files.ts +114 -0
- package/src/surface/blueprint.ts +342 -66
- package/src/surface/decision-composer.ts +6 -1
- package/src/surface/geo.ts +6 -1
- package/src/surface/index.ts +11 -7
- package/src/surface/types.ts +2 -2
- package/src/surface/vitest.config.ts +1 -0
- package/src/tests/signing-core.test.ts +129 -0
- package/src/{share → text}/css-value-normalize.ts +6 -1
- package/src/text/string-utils.ts +24 -0
- package/src/{share → text}/tests/text-normalize.test.ts +5 -0
- package/src/{share → text}/text-normalize.ts +4 -3
- package/src/{share → text}/wrap-inline-numbers.ts +1 -1
- package/src/types/axiom-study.d.ts +36 -0
- package/src/types/hls-js-light.d.ts +21 -0
- package/src/types/qrcode-browser.d.ts +23 -0
- package/src/typography/fix.pbt.test.ts +208 -0
- package/src/typography/fix.ts +148 -0
- package/src/typography/index.ts +54 -0
- package/src/typography/locale-defaults.ts +97 -0
- package/src/typography/rules-tier1.test.ts +459 -0
- package/src/typography/rules-tier1.ts +925 -0
- package/src/typography/rules-tier2-locale.pbt.test.ts +190 -0
- package/src/typography/rules-tier2-locale.test.ts +286 -0
- package/src/typography/rules-tier2-locale.ts +399 -0
- package/src/typography/rules-tier2-structure.test.ts +330 -0
- package/src/typography/rules-tier2-structure.ts +378 -0
- package/src/typography/rules-tier3-advisory.test.ts +290 -0
- package/src/typography/rules-tier3-advisory.ts +239 -0
- package/src/typography/text-surface.test.ts +244 -0
- package/src/typography/text-surface.ts +448 -0
- package/src/index.ts +0 -14
- package/src/integration/port-barrel.ts +0 -105
- package/src/share/agent/tests/api-catalog.test.ts +0 -8
- package/src/share/agent/tests/ard-catalog.test.ts +0 -8
- package/src/share/agent/tests/capability.test.ts +0 -14
- package/src/share/agent/tests/fleet-catalog.test.ts +0 -15
- package/src/share/agent/tests/knowledge.test.ts +0 -20
- package/src/share/agent/tests/manifest.test.ts +0 -9
- package/src/share/agent/tests/mcp-card.test.ts +0 -8
- package/src/share/agent/tests/openapi.test.ts +0 -8
- package/src/share/agent/tests/proof.test.ts +0 -15
- package/src/share/content/index.ts +0 -16
- package/src/share/content-discipline/index.ts +0 -14
- package/src/share/index.ts +0 -86
- package/src/share/knowledge/tests/claim.test.ts +0 -11
- package/src/share/knowledge/tests/derivation.test.ts +0 -30
- package/src/share/knowledge/tests/freshness.test.ts +0 -18
- package/src/share/knowledge/tests/ledger.test.ts +0 -35
- package/src/share/knowledge/tests/plan.test.ts +0 -19
- package/src/share/knowledge/tests/source.test.ts +0 -19
- package/src/share/legal/index.ts +0 -1
- package/src/share/redirects.ts +0 -54
- package/src/share/remediation/remediation-catalog.ts +0 -196
- package/src/share/scripts/index.ts +0 -26
- package/src/share/scripts/tests/orchestrator.test.ts +0 -8
- package/src/share/semantic/jsonld/shared.ts +0 -31
- package/src/share/semantic/jsonld/types.ts +0 -19
- package/src/share/semantic/jsonld/website.ts +0 -27
- package/src/share/string-utils.ts +0 -19
- package/src/share/types/axiom-study.d.ts +0 -22
- package/src/share/types/hls-js-light.d.ts +0 -16
- package/src/share/types/qrcode-browser.d.ts +0 -18
- package/src/share/utility-registry.yaml +0 -50
- package/src/share/vitest.config.ts +0 -8
- package/src/surface/blueprint-schema.ts +0 -314
- package/src/surface/blueprint-types.ts +0 -256
- /package/src/{share/agent → agent}/capability.ts +0 -0
- /package/src/{share/agent → agent}/dns-aid.ts +0 -0
- /package/src/{share/agent → agent}/fleet-catalog.ts +0 -0
- /package/src/{share/agent → agent}/knowledge.ts +0 -0
- /package/src/{share/agent → agent}/mcp-card.ts +0 -0
- /package/src/{share/agent → agent}/omit-empty.ts +0 -0
- /package/src/{share/agent → agent}/proof.ts +0 -0
- /package/src/{share/agent → agent}/tests/omit-empty.test.ts +0 -0
- /package/src/{share → attribution}/attribution-display.ts +0 -0
- /package/src/{share/scripts → client-scripts}/gsap-mountain-journey.ts +0 -0
- /package/src/{share/scripts → client-scripts}/gsap-parallax.ts +0 -0
- /package/src/{share/scripts → client-scripts}/gsap-reveal.ts +0 -0
- /package/src/{share/scripts → client-scripts}/gsap-stagger.ts +0 -0
- /package/src/{share/scripts → client-scripts}/live-photos.ts +0 -0
- /package/src/{share/scripts → client-scripts}/tests/external-link-qr.test.ts +0 -0
- /package/src/{share/scripts → client-scripts}/tests/external-links.test.ts +0 -0
- /package/src/{share/scripts → client-scripts}/tests/gsap-counter.test.ts +0 -0
- /package/src/{share/scripts → client-scripts}/tests/gsap-mountain-journey.test.ts +0 -0
- /package/src/{share/scripts → client-scripts}/tests/gsap-parallax.test.ts +0 -0
- /package/src/{share/scripts → client-scripts}/tests/gsap-reveal.test.ts +0 -0
- /package/src/{share/scripts → client-scripts}/tests/gsap-stagger.test.ts +0 -0
- /package/src/{share/scripts → client-scripts}/tests/inline-number-animation.test.ts +0 -0
- /package/src/{share/scripts → client-scripts}/tests/lenis.test.ts +0 -0
- /package/src/{share/scripts → client-scripts}/tests/live-photos.test.ts +0 -0
- /package/src/{share/scripts → client-scripts}/tests/lordicon.test.ts +0 -0
- /package/src/{share/scripts → client-scripts}/tests/scheduler.test.ts +0 -0
- /package/src/{share/scripts → client-scripts}/video-player.ts +0 -0
- /package/src/{share/content → content}/resolve-field-path.ts +0 -0
- /package/src/{share/content → content}/substitute-deep.ts +0 -0
- /package/src/{share → content}/tests/content-ref-index.test.ts +0 -0
- /package/src/{share/content-discipline → content-discipline}/types.ts +0 -0
- /package/src/{share → image-provider}/image-provider.ts +0 -0
- /package/src/{share/knowledge → knowledge}/claim.ts +0 -0
- /package/src/{share/knowledge → knowledge}/derivation.ts +0 -0
- /package/src/{share/knowledge → knowledge}/freshness.ts +0 -0
- /package/src/{share/knowledge → knowledge}/index.ts +0 -0
- /package/src/{share/knowledge → knowledge}/ledger.ts +0 -0
- /package/src/{share/knowledge → knowledge}/plan.ts +0 -0
- /package/src/{share/knowledge → knowledge}/source.ts +0 -0
- /package/src/{share/legal → legal}/translation-policy.ts +0 -0
- /package/src/{share/middleware → middleware}/tests/access-protection.test.ts +0 -0
- /package/src/{share → node}/fs/index.ts +0 -0
- /package/src/{share/tests/markdown-twin-provenance.test.ts → node/tests/markdown-twin-provenance-0613.test.ts} +0 -0
- /package/src/{share → offers}/offer-capacity.ts +0 -0
- /package/src/{share/onboarding-yaml/index.ts → onboarding/yaml.ts} +0 -0
- /package/src/{share → ontology}/tests/ontology-role-by-cosmic-name.test.ts +0 -0
- /package/src/{share/routes → routes}/tests/template-filter.test.ts +0 -0
- /package/src/{share/schemas → schemas}/claim-records.ts +0 -0
- /package/src/{share/schemas → schemas}/horizontal-align.ts +0 -0
- /package/src/{share/schemas → schemas}/icon-color.ts +0 -0
- /package/src/{share/schemas → schemas}/live-photo.ts +0 -0
- /package/src/{share/schemas → schemas}/material-credit.ts +0 -0
- /package/src/{share/schemas → schemas}/media.ts +0 -0
- /package/src/{share/schemas → schemas}/participant.ts +0 -0
- /package/src/{share/schemas → schemas}/print.ts +0 -0
- /package/src/{share/schemas → schemas}/section-background.ts +0 -0
- /package/src/{share/schemas → schemas}/section-body.ts +0 -0
- /package/src/{share/schemas → schemas}/section-cards.ts +0 -0
- /package/src/{share/schemas → schemas}/section-cta.ts +0 -0
- /package/src/{share/schemas → schemas}/section-header.ts +0 -0
- /package/src/{share/schemas → schemas}/section-image.ts +0 -0
- /package/src/{share/schemas → schemas}/section-motion.ts +0 -0
- /package/src/{share/schemas → schemas}/section-shell.ts +0 -0
- /package/src/{share/schemas → schemas}/section-stats.ts +0 -0
- /package/src/{share/schemas → schemas}/site-background.ts +0 -0
- /package/src/{share/schemas → schemas}/tests/claim-records.test.ts +0 -0
- /package/src/{share/schemas → schemas}/tests/claims.test.ts +0 -0
- /package/src/{share/schemas → schemas}/tests/effects.test.ts +0 -0
- /package/src/{share/schemas → schemas}/tests/features.test.ts +0 -0
- /package/src/{share/schemas → schemas}/tests/horizontal-align.test.ts +0 -0
- /package/src/{share/schemas → schemas}/tests/icon-color.test.ts +0 -0
- /package/src/{share/schemas → schemas}/tests/live-photo.test.ts +0 -0
- /package/src/{share/schemas → schemas}/tests/material-credit.test.ts +0 -0
- /package/src/{share/schemas → schemas}/tests/media.test.ts +0 -0
- /package/src/{share/schemas → schemas}/tests/navigation.test.ts +0 -0
- /package/src/{share/schemas → schemas}/tests/page-base.test.ts +0 -0
- /package/src/{share/schemas → schemas}/tests/participant.test.ts +0 -0
- /package/src/{share/schemas → schemas}/tests/person.test.ts +0 -0
- /package/src/{share/schemas → schemas}/tests/print.test.ts +0 -0
- /package/src/{share/schemas → schemas}/tests/section-background.test.ts +0 -0
- /package/src/{share/schemas → schemas}/tests/section-body.test.ts +0 -0
- /package/src/{share/schemas → schemas}/tests/section-cards.test.ts +0 -0
- /package/src/{share/schemas → schemas}/tests/section-cta.test.ts +0 -0
- /package/src/{share/schemas → schemas}/tests/section-header.test.ts +0 -0
- /package/src/{share/schemas → schemas}/tests/section-image.test.ts +0 -0
- /package/src/{share/schemas → schemas}/tests/section-motion.test.ts +0 -0
- /package/src/{share/schemas → schemas}/tests/section-shell.test.ts +0 -0
- /package/src/{share/schemas → schemas}/tests/section-stats.test.ts +0 -0
- /package/src/{share/schemas → schemas}/tests/site-background.test.ts +0 -0
- /package/src/{share/schemas → schemas}/tests/standard-list-item.test.ts +0 -0
- /package/src/{share/semantic → semantic}/ai.ts +0 -0
- /package/src/{share/semantic → semantic}/block-extraction.ts +0 -0
- /package/src/{share/semantic → semantic}/breadcrumbs.ts +0 -0
- /package/src/{share/semantic → semantic}/build-page.ts +0 -0
- /package/src/{share/semantic → semantic}/feed.ts +0 -0
- /package/src/{share/semantic → semantic}/image-sitemap.ts +0 -0
- /package/src/{share/semantic → semantic}/jsonld/article.ts +0 -0
- /package/src/{share/semantic → semantic}/jsonld/collection-list.ts +0 -0
- /package/src/{share/semantic → semantic}/jsonld/tests/article.test.ts +0 -0
- /package/src/{share/semantic → semantic}/jsonld/tests/breadcrumb.test.ts +0 -0
- /package/src/{share/semantic → semantic}/jsonld/tests/collection-list.test.ts +0 -0
- /package/src/{share/semantic → semantic}/jsonld/tests/faq.test.ts +0 -0
- /package/src/{share/semantic → semantic}/jsonld/tests/initiative.test.ts +0 -0
- /package/src/{share/semantic → semantic}/jsonld/tests/organization.test.ts +0 -0
- /package/src/{share/semantic → semantic}/jsonld/tests/person.test.ts +0 -0
- /package/src/{share/semantic → semantic}/jsonld/tests/service.test.ts +0 -0
- /package/src/{share/semantic → semantic}/jsonld/tests/shared.test.ts +0 -0
- /package/src/{share/semantic → semantic}/jsonld/tests/video.test.ts +0 -0
- /package/src/{share/semantic → semantic}/jsonld/tests/webpage.test.ts +0 -0
- /package/src/{share/semantic → semantic}/jsonld/tests/website.test.ts +0 -0
- /package/src/{share/semantic → semantic}/jsonld/video.ts +0 -0
- /package/src/{share/semantic → semantic}/llms-policy.ts +0 -0
- /package/src/{share/semantic → semantic}/markdown-hygiene.ts +0 -0
- /package/src/{share/semantic → semantic}/output-projection.ts +0 -0
- /package/src/{share/semantic → semantic}/page-markdown.ts +0 -0
- /package/src/{share/semantic → semantic}/price-marker-resolver.ts +0 -0
- /package/src/{share/semantic → semantic}/robots.ts +0 -0
- /package/src/{share/semantic → semantic}/tests/ai.test.ts +0 -0
- /package/src/{share/semantic → semantic}/tests/block-extraction.test.ts +0 -0
- /package/src/{share/semantic → semantic}/tests/breadcrumbs.test.ts +0 -0
- /package/src/{share/semantic → semantic}/tests/build-page.test.ts +0 -0
- /package/src/{share/semantic → semantic}/tests/feed.test.ts +0 -0
- /package/src/{share/semantic → semantic}/tests/helpers.ts +0 -0
- /package/src/{share/semantic → semantic}/tests/ids.test.ts +0 -0
- /package/src/{share/semantic → semantic}/tests/image-sitemap.test.ts +0 -0
- /package/src/{share/semantic → semantic}/tests/jsonld.test.ts +0 -0
- /package/src/{share/semantic → semantic}/tests/llms-policy.test.ts +0 -0
- /package/src/{share/semantic → semantic}/tests/markdown-hygiene.test.ts +0 -0
- /package/src/{share/semantic → semantic}/tests/markdown-page.test.ts +0 -0
- /package/src/{share/semantic → semantic}/tests/organization-profile.test.ts +0 -0
- /package/src/{share/semantic → semantic}/tests/output-projection.test.ts +0 -0
- /package/src/{share/semantic → semantic}/tests/page-markdown.test.ts +0 -0
- /package/src/{share/semantic → semantic}/tests/page-utils.test.ts +0 -0
- /package/src/{share/semantic → semantic}/tests/robots.test.ts +0 -0
- /package/src/{share/semantic → semantic}/tests/update-stamp.test.ts +0 -0
- /package/src/{share/semantic → semantic}/update-stamp.ts +0 -0
- /package/src/{share/slug → slug}/heading-slugger.ts +0 -0
- /package/src/{share/slug → slug}/index.ts +0 -0
- /package/src/{share/slug → slug}/slug-id.ts +0 -0
- /package/src/{share/slug → slug}/strategies.ts +0 -0
- /package/src/{share/slug → slug}/tests/slug.test.ts +0 -0
- /package/src/{share → text}/tests/text-normalize.pbt.test.ts +0 -0
- /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
|
+
}
|
package/src/passport/index.ts
CHANGED
|
@@ -7,7 +7,12 @@
|
|
|
7
7
|
</non-goals>
|
|
8
8
|
</MODULE_CONTRACT>
|
|
9
9
|
<CHANGE_SUMMARY>
|
|
10
|
-
<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>
|
|
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>
|
|
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
|
|
package/src/passport/schema.ts
CHANGED
|
@@ -11,7 +11,12 @@
|
|
|
11
11
|
</MODULE_CONTRACT>
|
|
12
12
|
|
|
13
13
|
<CHANGE_SUMMARY>
|
|
14
|
-
<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
|
|
package/src/passport/sign.ts
CHANGED
|
@@ -7,8 +7,13 @@
|
|
|
7
7
|
</non-goals>
|
|
8
8
|
</MODULE_CONTRACT>
|
|
9
9
|
<CHANGE_SUMMARY>
|
|
10
|
-
<item>
|
|
11
|
-
<item>RFC-
|
|
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-
|
|
40
|
+
} from "@warpgogol/werkstatt-shared/signing";
|
|
36
41
|
import type { VCProof, VerifiableCredential } from "./schema.ts";
|
|
37
42
|
|
|
38
43
|
// ---------------------------------------------------------------------------
|
|
@@ -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
|
+
});
|
package/src/pbt/index.ts
ADDED
|
@@ -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-
|
|
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. "
|
|
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:
|
|
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:
|
|
178
|
+
features: mergeFree(input.stripeFeatures),
|
|
164
179
|
source: "stripe",
|
|
165
180
|
...pseo,
|
|
166
181
|
};
|
|
167
182
|
}
|
|
168
|
-
return {
|
|
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>
|
|
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 "
|
|
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 "
|
|
37
|
+
} from "../schemas/features.ts";
|
|
33
38
|
|
|
34
39
|
export interface FeaturePolicyResolverOptions {
|
|
35
40
|
/**
|