@legionworks/facet 1.9.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/LICENSE-APACHE +202 -0
- package/LICENSE-MIT +23 -0
- package/README.md +158 -0
- package/dist/gallery/chunk-4g8rem85.css +656 -0
- package/dist/gallery/chunk-c6s9k9ty.js +5970 -0
- package/dist/gallery/frame/artifact.css +8424 -0
- package/dist/gallery/frame/chunks/abnfDiagram-N423BO3Z-jj74szbm.js +155 -0
- package/dist/gallery/frame/chunks/architecture-TIHT7OUA-cvdjn7dt.js +10 -0
- package/dist/gallery/frame/chunks/architectureDiagram-T3A2C74G-n4z77eg6.js +8675 -0
- package/dist/gallery/frame/chunks/blockDiagram-VBNYF7ZC-7xsqzrd1.js +3529 -0
- package/dist/gallery/frame/chunks/c4Diagram-5PPSVZJV-z2zjs7wx.js +2413 -0
- package/dist/gallery/frame/chunks/classDiagram-JCYQIIEL-ve8rngqp.js +47 -0
- package/dist/gallery/frame/chunks/classDiagram-v2-OCEON4UE-8cfaxb8z.js +47 -0
- package/dist/gallery/frame/chunks/cose-bilkent-JH36ORCC-sn92qexx.js +4822 -0
- package/dist/gallery/frame/chunks/cynefin-VYW2F7L2-tqjv913d.js +10 -0
- package/dist/gallery/frame/chunks/cynefinDiagram-MW4NZA55-c1c0dj12.js +500 -0
- package/dist/gallery/frame/chunks/dagre-VZM6K2ZE-7tyg4yt2.js +476 -0
- package/dist/gallery/frame/chunks/diagram-7IWD3JNH-y4eng9sc.js +526 -0
- package/dist/gallery/frame/chunks/diagram-B4RE2ZJO-rn3p7j5h.js +673 -0
- package/dist/gallery/frame/chunks/diagram-LBJQPF4R-w4a2cm9q.js +255 -0
- package/dist/gallery/frame/chunks/diagram-Q27KOJAE-aqc2v7wy.js +575 -0
- package/dist/gallery/frame/chunks/diagram-UB23O5K3-xncy8nyd.js +355 -0
- package/dist/gallery/frame/chunks/ebnfDiagram-BXEA7PRR-acwgxz16.js +175 -0
- package/dist/gallery/frame/chunks/erDiagram-JOGREHBK-mzp5nswt.js +1332 -0
- package/dist/gallery/frame/chunks/eventmodeling-45OFAUF4-sg07qr0c.js +10 -0
- package/dist/gallery/frame/chunks/flowDiagram-UKHOOZJN-2e5ygs44.js +29 -0
- package/dist/gallery/frame/chunks/ganttDiagram-PKOTCBZU-p2hhh7hr.js +2620 -0
- package/dist/gallery/frame/chunks/gitGraph-TEB2WS4Q-j6kw0naa.js +10 -0
- package/dist/gallery/frame/chunks/gitGraphDiagram-DS77QQ5N-4z9z8wjm.js +1347 -0
- package/dist/gallery/frame/chunks/info-DKCQHKI2-mpt80jd3.js +10 -0
- package/dist/gallery/frame/chunks/infoDiagram-6WML65LV-5rqm3mgg.js +65 -0
- package/dist/gallery/frame/chunks/ishikawaDiagram-WSZJBQD7-b51z96jy.js +975 -0
- package/dist/gallery/frame/chunks/journeyDiagram-NVQOT4AX-9jbfp0pk.js +1272 -0
- package/dist/gallery/frame/chunks/kanban-definition-27J2QSJJ-4x0vx4se.js +1116 -0
- package/dist/gallery/frame/chunks/katex-xfgk95tv.js +14034 -0
- package/dist/gallery/frame/chunks/markdown-1s5vwkf2.js +9 -0
- package/dist/gallery/frame/chunks/markdown-2h6bwsms.js +3239 -0
- package/dist/gallery/frame/chunks/markdown-2x113yh8.js +107 -0
- package/dist/gallery/frame/chunks/markdown-30b7rwmp.js +1943 -0
- package/dist/gallery/frame/chunks/markdown-356bfj4g.js +2031 -0
- package/dist/gallery/frame/chunks/markdown-44n9ea69.js +2406 -0
- package/dist/gallery/frame/chunks/markdown-56enrf2r.js +39 -0
- package/dist/gallery/frame/chunks/markdown-5avymm8t.js +725 -0
- package/dist/gallery/frame/chunks/markdown-6r4svars.js +33 -0
- package/dist/gallery/frame/chunks/markdown-6zz8efx2.js +24 -0
- package/dist/gallery/frame/chunks/markdown-7jp6prnb.js +19 -0
- package/dist/gallery/frame/chunks/markdown-809k7q41.js +55 -0
- package/dist/gallery/frame/chunks/markdown-82xmzhzd.js +1076 -0
- package/dist/gallery/frame/chunks/markdown-92n37gd4.js +7627 -0
- package/dist/gallery/frame/chunks/markdown-ag2sssf8.js +36 -0
- package/dist/gallery/frame/chunks/markdown-b4s7ntq2.js +19 -0
- package/dist/gallery/frame/chunks/markdown-c9k0fvp1.js +100 -0
- package/dist/gallery/frame/chunks/markdown-ceefymn8.js +125 -0
- package/dist/gallery/frame/chunks/markdown-d1wfbs70.js +243 -0
- package/dist/gallery/frame/chunks/markdown-dy5sgjhc.js +11022 -0
- package/dist/gallery/frame/chunks/markdown-dz3z5w30.js +30868 -0
- package/dist/gallery/frame/chunks/markdown-eg6ngz7y.js +30340 -0
- package/dist/gallery/frame/chunks/markdown-ff5wvb43.js +1149 -0
- package/dist/gallery/frame/chunks/markdown-ffg06nfz.js +86 -0
- package/dist/gallery/frame/chunks/markdown-fvfncadf.js +472 -0
- package/dist/gallery/frame/chunks/markdown-gvyszqpv.js +19 -0
- package/dist/gallery/frame/chunks/markdown-gx1p0ew0.js +88 -0
- package/dist/gallery/frame/chunks/markdown-gxye5frz.js +65 -0
- package/dist/gallery/frame/chunks/markdown-h7pzv34e.js +105 -0
- package/dist/gallery/frame/chunks/markdown-hab789t9.js +47 -0
- package/dist/gallery/frame/chunks/markdown-hjp6sj8t.js +125 -0
- package/dist/gallery/frame/chunks/markdown-jka64qgp.js +1993 -0
- package/dist/gallery/frame/chunks/markdown-k8xkn8mw.js +56 -0
- package/dist/gallery/frame/chunks/markdown-m7frq8x8.js +112 -0
- package/dist/gallery/frame/chunks/markdown-p740v4qm.js +36 -0
- package/dist/gallery/frame/chunks/markdown-pxfeh231.js +57 -0
- package/dist/gallery/frame/chunks/markdown-pzgd8z3s.js +87 -0
- package/dist/gallery/frame/chunks/markdown-qx3cngz2.js +1673 -0
- package/dist/gallery/frame/chunks/markdown-rawhfvvc.js +85 -0
- package/dist/gallery/frame/chunks/markdown-rd8w0ng9.js +49 -0
- package/dist/gallery/frame/chunks/markdown-rm2yxfjj.js +2773 -0
- package/dist/gallery/frame/chunks/markdown-s1jatrnk.js +993 -0
- package/dist/gallery/frame/chunks/markdown-sgfg5vvq.js +59 -0
- package/dist/gallery/frame/chunks/markdown-t4ethv9d.js +409 -0
- package/dist/gallery/frame/chunks/markdown-tnmabqvz.js +36 -0
- package/dist/gallery/frame/chunks/markdown-tvdpppw8.js +5292 -0
- package/dist/gallery/frame/chunks/markdown-v0x27twr.js +22 -0
- package/dist/gallery/frame/chunks/markdown-v14td68x.js +36 -0
- package/dist/gallery/frame/chunks/markdown-w6sgd54z.js +36 -0
- package/dist/gallery/frame/chunks/markdown-xw8dsk8b.js +2125 -0
- package/dist/gallery/frame/chunks/markdown-y18mve73.js +85 -0
- package/dist/gallery/frame/chunks/markdown-yengsms5.js +427 -0
- package/dist/gallery/frame/chunks/markdown-z1wc0v0d.js +1826 -0
- package/dist/gallery/frame/chunks/markdown-zazx9h4n.js +329 -0
- package/dist/gallery/frame/chunks/mermaid-de7p4v0x.js +30 -0
- package/dist/gallery/frame/chunks/mindmap-definition-FAOFIHXS-ra44cbem.js +1216 -0
- package/dist/gallery/frame/chunks/packet-7NZHBO7P-xppm5913.js +10 -0
- package/dist/gallery/frame/chunks/pegDiagram-VL7TDLO6-a2a4wg03.js +163 -0
- package/dist/gallery/frame/chunks/pie-RZYD4A2V-hnbxk152.js +10 -0
- package/dist/gallery/frame/chunks/pieDiagram-7S7Q4E2Y-f1vxjtmx.js +311 -0
- package/dist/gallery/frame/chunks/quadrantDiagram-CIZ2JOQS-ywafa6kh.js +1390 -0
- package/dist/gallery/frame/chunks/radar-I7S5WNFK-ewqd27se.js +10 -0
- package/dist/gallery/frame/chunks/railroad-3IZDKUUU-5hy4bdx3.js +10 -0
- package/dist/gallery/frame/chunks/railroad-abnf-AHOZXSZD-bh5sxz0d.js +10 -0
- package/dist/gallery/frame/chunks/railroad-ebnf-EBAXGLYW-6b9c3zeh.js +10 -0
- package/dist/gallery/frame/chunks/railroad-peg-LSFZ7HO6-avc8v39s.js +10 -0
- package/dist/gallery/frame/chunks/railroadDiagram-AXF67PYL-qc61wax4.js +131 -0
- package/dist/gallery/frame/chunks/requirementDiagram-LRYGKXZP-9bs4786c.js +1295 -0
- package/dist/gallery/frame/chunks/sankeyDiagram-W5VNT64P-awt1em8b.js +1339 -0
- package/dist/gallery/frame/chunks/sequenceDiagram-SI44F4Z6-qaf9mz3t.js +4324 -0
- package/dist/gallery/frame/chunks/sizeCapture-X5ZJPWSS-9fq685xd.js +64 -0
- package/dist/gallery/frame/chunks/stateDiagram-OKZ733FA-vx7a7hh0.js +456 -0
- package/dist/gallery/frame/chunks/stateDiagram-v2-UEYNNEHI-x4m6ws5t.js +46 -0
- package/dist/gallery/frame/chunks/swimlanes-SLNWSIFB-e4mxm1gh.js +8287 -0
- package/dist/gallery/frame/chunks/swimlanesDiagram-ULZ7WXOC-0h93e2qq.js +42 -0
- package/dist/gallery/frame/chunks/timeline-definition-Z64GVDOM-wp0bhbzg.js +1549 -0
- package/dist/gallery/frame/chunks/treeView-QDETBFTQ-hcx7n0vt.js +10 -0
- package/dist/gallery/frame/chunks/treemap-6X3UGDF4-av02skdw.js +10 -0
- package/dist/gallery/frame/chunks/vennDiagram-T6HMQDX7-pmvk1p7n.js +2566 -0
- package/dist/gallery/frame/chunks/wardley-OPB4EBWU-njsp6e40.js +10 -0
- package/dist/gallery/frame/chunks/wardleyDiagram-T6FBY63Y-eggmnv4z.js +979 -0
- package/dist/gallery/frame/chunks/xychartDiagram-ELKLHX3M-q40tnpe5.js +1954 -0
- package/dist/gallery/frame/frame.css +183 -0
- package/dist/gallery/frame/runtime/chart.js +42744 -0
- package/dist/gallery/frame/runtime/html.js +14 -0
- package/dist/gallery/frame/runtime/markdown.js +1403 -0
- package/dist/gallery/frame/runtime/mermaid.js +32 -0
- package/dist/gallery/frame/runtime/svg.js +14 -0
- package/dist/gallery/frame/runtime/tsx.js +52 -0
- package/dist/gallery/index.html +104 -0
- package/docs/reference/cli.md +163 -0
- package/docs/reference/export.md +106 -0
- package/docs/reference/html.md +215 -0
- package/docs/reference/http.md +85 -0
- package/docs/reference/mcp.md +78 -0
- package/docs/reference/security.md +119 -0
- package/docs/reference/storage.md +93 -0
- package/docs/reference/tsx.md +101 -0
- package/docs/reference/validation.md +212 -0
- package/package.json +89 -0
- package/scripts/build-gallery.ts +127 -0
- package/scripts/launch-netns.sh +67 -0
- package/skills/facet/SKILL.md +100 -0
- package/src/cli/client.ts +311 -0
- package/src/cli/commands/create.ts +49 -0
- package/src/cli/commands/doctor.ts +249 -0
- package/src/cli/commands/export.ts +179 -0
- package/src/cli/commands/instantiate.ts +35 -0
- package/src/cli/commands/list.ts +49 -0
- package/src/cli/commands/open.ts +75 -0
- package/src/cli/commands/pin.ts +39 -0
- package/src/cli/commands/promote.ts +49 -0
- package/src/cli/commands/publish.ts +122 -0
- package/src/cli/commands/read-back.ts +56 -0
- package/src/cli/commands/status.ts +114 -0
- package/src/cli/commands/watch.ts +146 -0
- package/src/cli/main.ts +522 -0
- package/src/cli/output.ts +106 -0
- package/src/cli/parser.ts +376 -0
- package/src/cli/presenter.ts +212 -0
- package/src/cli/service-metadata.ts +134 -0
- package/src/cli/spawn-service.ts +326 -0
- package/src/css.d.ts +4 -0
- package/src/gallery-web/app.ts +1581 -0
- package/src/gallery-web/export-menu.ts +121 -0
- package/src/gallery-web/export.ts +112 -0
- package/src/gallery-web/favicon.ts +54 -0
- package/src/gallery-web/frame/entries/chart.ts +6 -0
- package/src/gallery-web/frame/entries/html.ts +6 -0
- package/src/gallery-web/frame/entries/markdown.ts +6 -0
- package/src/gallery-web/frame/entries/mermaid.ts +6 -0
- package/src/gallery-web/frame/entries/svg.ts +6 -0
- package/src/gallery-web/frame/entries/tsx.ts +6 -0
- package/src/gallery-web/frame/frame-payload.ts +91 -0
- package/src/gallery-web/frame/renderer-validation.ts +13 -0
- package/src/gallery-web/frame/renderers/chart.ts +182 -0
- package/src/gallery-web/frame/renderers/dompurify-shim.ts +112 -0
- package/src/gallery-web/frame/renderers/html.ts +48 -0
- package/src/gallery-web/frame/renderers/markdown.ts +81 -0
- package/src/gallery-web/frame/renderers/mermaid.ts +120 -0
- package/src/gallery-web/frame/renderers/registry.ts +260 -0
- package/src/gallery-web/frame/renderers/svg.ts +393 -0
- package/src/gallery-web/frame/renderers/tsx.ts +61 -0
- package/src/gallery-web/frame/runtime.ts +501 -0
- package/src/gallery-web/frame/styles/artifact.css +8424 -0
- package/src/gallery-web/frame/styles/frame.css +183 -0
- package/src/gallery-web/frame/styles/html-source.css +23 -0
- package/src/gallery-web/frame/view-box.ts +33 -0
- package/src/gallery-web/frame-html.ts +72 -0
- package/src/gallery-web/index.html +104 -0
- package/src/gallery-web/session.ts +107 -0
- package/src/gallery-web/sse-client.ts +212 -0
- package/src/gallery-web/styles/app.css +420 -0
- package/src/gallery-web/styles/tokens.css +112 -0
- package/src/gallery-web/styles/verdict.css +186 -0
- package/src/gallery-web/swap.ts +64 -0
- package/src/gallery-web/theme.ts +40 -0
- package/src/gallery-web/view-state.ts +93 -0
- package/src/harness-adapters/claude-code/README.md +10 -0
- package/src/harness-adapters/claude-code/facet.sh +4 -0
- package/src/harness-adapters/codex/README.md +10 -0
- package/src/harness-adapters/codex/facet.sh +4 -0
- package/src/harness-adapters/mcp/README.md +13 -0
- package/src/harness-adapters/mcp/cli-bridge.ts +216 -0
- package/src/harness-adapters/mcp/main.ts +15 -0
- package/src/harness-adapters/mcp/server.ts +164 -0
- package/src/harness-adapters/mcp/tool-schemas.ts +53 -0
- package/src/harness-adapters/opencode/README.md +10 -0
- package/src/harness-adapters/opencode/facet.sh +4 -0
- package/src/runtime/compiled-entrypoints.ts +69 -0
- package/src/service/dispatcher.ts +717 -0
- package/src/service/export.ts +218 -0
- package/src/service/http-utils.ts +55 -0
- package/src/service/lexical/expectations.ts +210 -0
- package/src/service/lifecycle/idle-controller.ts +125 -0
- package/src/service/lifecycle/orphan-cleanup.ts +128 -0
- package/src/service/lifecycle/process-lock.ts +235 -0
- package/src/service/main.ts +136 -0
- package/src/service/process.ts +240 -0
- package/src/service/router-guards.ts +239 -0
- package/src/service/router.ts +627 -0
- package/src/service/security/auth.ts +168 -0
- package/src/service/security/host-origin.ts +138 -0
- package/src/service/security/http-guards.ts +13 -0
- package/src/service/security/leases.ts +182 -0
- package/src/service/security/token-store.ts +138 -0
- package/src/service/server.ts +356 -0
- package/src/service/store/database.ts +61 -0
- package/src/service/store/evidence-retention.ts +234 -0
- package/src/service/store/migrations.ts +167 -0
- package/src/service/store/repository-lifecycle.ts +121 -0
- package/src/service/store/repository.ts +732 -0
- package/src/service/store/schema.ts +218 -0
- package/src/service/stored-verdict.ts +97 -0
- package/src/service/stream.ts +301 -0
- package/src/service/verdict-enrichment.ts +45 -0
- package/src/shared/build/frame-bundle-plugins.ts +61 -0
- package/src/shared/build-mode.ts +28 -0
- package/src/shared/config/evidence-read.ts +98 -0
- package/src/shared/config/limits.ts +56 -0
- package/src/shared/config/paths.ts +96 -0
- package/src/shared/contracts/artifact-types.ts +2 -0
- package/src/shared/contracts/artifact.ts +98 -0
- package/src/shared/contracts/commands/_shared.ts +59 -0
- package/src/shared/contracts/commands/guards.ts +86 -0
- package/src/shared/contracts/commands/index.ts +204 -0
- package/src/shared/contracts/commands/names.ts +35 -0
- package/src/shared/contracts/commands/requests.ts +149 -0
- package/src/shared/contracts/commands/results.ts +200 -0
- package/src/shared/contracts/envelope.ts +140 -0
- package/src/shared/contracts/events.ts +41 -0
- package/src/shared/contracts/observed-counts.ts +19 -0
- package/src/shared/contracts/renderers.ts +6 -0
- package/src/shared/contracts/validation.ts +296 -0
- package/src/shared/errors/facet-error.ts +127 -0
- package/src/shared/errors/store-error.ts +68 -0
- package/src/shared/evidence-image.ts +37 -0
- package/src/shared/export.ts +31 -0
- package/src/shared/html/policy.ts +108 -0
- package/src/shared/html/style-vocabulary.ts +352 -0
- package/src/shared/logging/logger.ts +108 -0
- package/src/shared/logging/redact.ts +49 -0
- package/src/shared/security/frozen-csp.ts +13 -0
- package/src/shared/storage-version.ts +2 -0
- package/src/shared/tsx/execution.ts +29 -0
- package/src/shared/tsx/import-policy.ts +94 -0
- package/src/shared/util/dir-permissions.ts +94 -0
- package/src/shared/util/mermaid-nodes.ts +230 -0
- package/src/shared/util/process.ts +67 -0
- package/src/shared/util/time.ts +21 -0
- package/src/shared/version.ts +3 -0
- package/src/validation/sandbox/limits.ts +41 -0
- package/src/validation/sandbox/netns.ts +177 -0
- package/src/validation/tier0/chart.ts +177 -0
- package/src/validation/tier0/dom-shim.ts +54 -0
- package/src/validation/tier0/html.ts +408 -0
- package/src/validation/tier0/markdown.ts +285 -0
- package/src/validation/tier0/mermaid.ts +98 -0
- package/src/validation/tier0/runner.ts +504 -0
- package/src/validation/tier0/svg.ts +321 -0
- package/src/validation/tier0/tsx/allowlist-resolver.ts +77 -0
- package/src/validation/tier0/tsx/ast-policy-capabilities.ts +238 -0
- package/src/validation/tier0/tsx/ast-policy-shared.ts +71 -0
- package/src/validation/tier0/tsx/ast-policy.ts +181 -0
- package/src/validation/tier0/tsx/compiler.ts +156 -0
- package/src/validation/tier0/worker-dispatch.ts +211 -0
- package/src/validation/tier0/worker-entry.ts +96 -0
- package/src/validation/tier0/worker-input.ts +75 -0
- package/src/validation/tier1/browser-process.ts +147 -0
- package/src/validation/tier1/cdp-pipe.ts +281 -0
- package/src/validation/tier1/entries/chart.ts +5 -0
- package/src/validation/tier1/entries/html.ts +6 -0
- package/src/validation/tier1/entries/markdown.ts +5 -0
- package/src/validation/tier1/entries/mermaid.ts +5 -0
- package/src/validation/tier1/entries/svg.ts +5 -0
- package/src/validation/tier1/entries/tsx.ts +5 -0
- package/src/validation/tier1/frame-target.ts +162 -0
- package/src/validation/tier1/harness-entry.ts +261 -0
- package/src/validation/tier1/harness.ts +215 -0
- package/src/validation/tier1/isolated-probe.ts +94 -0
- package/src/validation/tier1/launcher.ts +177 -0
- package/src/validation/tier1/limits.ts +80 -0
- package/src/validation/tier1/nonce.ts +17 -0
- package/src/validation/tier1/protocol-probe.ts +519 -0
- package/src/validation/tier1/runner.ts +1122 -0
- package/src/validation/tier1/verdict.ts +246 -0
- package/src/validation/tier1/webp.ts +69 -0
- package/templates/README.md +88 -0
- package/templates/bar-compare.vl.json +63 -0
- package/templates/capacity-report.tsx +102 -0
- package/templates/decision-record.md +24 -0
- package/templates/deployment-state.mmd +40 -0
- package/templates/exemplar.md +91 -0
- package/templates/facet-story.tsx +799 -0
- package/templates/fleet-dashboard.html +141 -0
- package/templates/html-release-ledger.html +91 -0
- package/templates/html-status-report.html +114 -0
- package/templates/incident-console.tsx +147 -0
- package/templates/legion-boundaries.mmd +23 -0
- package/templates/legion-flow.mmd +15 -0
- package/templates/legion-sequence.mmd +14 -0
- package/templates/legion-state.mmd +7 -0
- package/templates/metric-card.svg +29 -0
- package/templates/observability-map.svg +101 -0
- package/templates/pipeline-audit.md +108 -0
- package/templates/release-metrics.vl.json +98 -0
- package/templates/service-topology.mmd +47 -0
- package/templates/status-report.md +32 -0
- package/templates/system-map.svg +53 -0
- package/templates/timeseries.vl.json +71 -0
- package/templates/tsx-interactive-counter.tsx +19 -0
- package/templates/tsx-status-report.tsx +31 -0
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import type { Database } from "bun:sqlite";
|
|
2
|
+
|
|
3
|
+
import { asStoreError, FacetStoreError } from "./database";
|
|
4
|
+
export { INITIAL_SCHEMA } from "./schema";
|
|
5
|
+
import {
|
|
6
|
+
INITIAL_SCHEMA,
|
|
7
|
+
V2_SCHEMA_FRAGMENT,
|
|
8
|
+
V3_SCHEMA_FRAGMENT,
|
|
9
|
+
V4_SCHEMA_FRAGMENT,
|
|
10
|
+
V5_SCHEMA_FRAGMENT,
|
|
11
|
+
V6_SCHEMA_FRAGMENT,
|
|
12
|
+
V7_SCHEMA_FRAGMENT,
|
|
13
|
+
V8_SCHEMA_FRAGMENT,
|
|
14
|
+
V9_SCHEMA_FRAGMENT,
|
|
15
|
+
} from "./schema";
|
|
16
|
+
import { CURRENT_STORAGE_VERSION } from "../../shared/storage-version";
|
|
17
|
+
|
|
18
|
+
export interface MigrationOptions {
|
|
19
|
+
readonly beforeRecordVersion?: (version: number) => void;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
interface MigrationStep {
|
|
23
|
+
readonly version: number;
|
|
24
|
+
/** Idempotent body — safe to re-run against an already-migrated DB. */
|
|
25
|
+
readonly apply: (db: Database) => void;
|
|
26
|
+
/**
|
|
27
|
+
* `true` on steps that use the create-copy-drop-rename pattern on
|
|
28
|
+
* a self-FK-bearing table. SQLite refuses the DROP + ALTER TABLE
|
|
29
|
+
* RENAME sequence inside a transaction with FKs ON, because the
|
|
30
|
+
* inherited FK would dangle across the DROP. Steps that only add
|
|
31
|
+
* columns inherit nothing — a future rebuild opts in explicitly at
|
|
32
|
+
* its definition site. The flag gates the per-run
|
|
33
|
+
* `PRAGMA foreign_keys = OFF` toggle so a no-op re-run on an
|
|
34
|
+
* already-current database does not needlessly disable FKs.
|
|
35
|
+
*/
|
|
36
|
+
readonly requiresForeignKeyDisable?: boolean;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const MIGRATION_STEPS: readonly MigrationStep[] = [
|
|
40
|
+
{
|
|
41
|
+
version: 1,
|
|
42
|
+
apply: (db) => {
|
|
43
|
+
db.exec(INITIAL_SCHEMA);
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
version: 2,
|
|
48
|
+
apply: (db) => {
|
|
49
|
+
// Evidence retention: the `retained` column exempts a render_run
|
|
50
|
+
// from the last-N cleanup policy. Default 0 (not retained) keeps
|
|
51
|
+
// every existing row eligible for eviction.
|
|
52
|
+
db.exec(V2_SCHEMA_FRAGMENT);
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
version: 3,
|
|
57
|
+
apply: (db) => {
|
|
58
|
+
db.exec(V3_SCHEMA_FRAGMENT);
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
version: 4,
|
|
63
|
+
apply: (db) => {
|
|
64
|
+
db.exec(V4_SCHEMA_FRAGMENT);
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
version: 5,
|
|
69
|
+
apply: (db) => {
|
|
70
|
+
db.exec(V5_SCHEMA_FRAGMENT);
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
version: 6,
|
|
75
|
+
apply: (db) => {
|
|
76
|
+
db.exec(V6_SCHEMA_FRAGMENT);
|
|
77
|
+
},
|
|
78
|
+
requiresForeignKeyDisable: true,
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
version: 7,
|
|
82
|
+
apply: (db) => {
|
|
83
|
+
// Backfill the observed_json columns on rows written before
|
|
84
|
+
// `opaqueRegionCount` (opaque-content arc) and `externalImageCount`
|
|
85
|
+
// (this arc) were added. The schema-level repair is the
|
|
86
|
+
// companion to the runtime tolerant read; either one alone
|
|
87
|
+
// would fix this specific break, but treating the instance
|
|
88
|
+
// (`VerdictObservedSchema.optional()`) would leave the next
|
|
89
|
+
// counter addition to recur. Treating the boundary makes it
|
|
90
|
+
// durable.
|
|
91
|
+
db.exec(V7_SCHEMA_FRAGMENT);
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
version: 8,
|
|
96
|
+
apply: (db) => {
|
|
97
|
+
// Widens `revisions.artifact_type` to include `tsx`, adds
|
|
98
|
+
// `revisions.execution` (D2, backfilled to 'static'), and adds
|
|
99
|
+
// `render_runs.compiled_path` (D7, nullable for non-tsx runs
|
|
100
|
+
// and pre-arc rows). The v6 FK-safe rebuild pattern is reused
|
|
101
|
+
// because SQLite cannot alter a CHECK in place. Every prior
|
|
102
|
+
// column is copied explicitly so the schema shape stays
|
|
103
|
+
// traceable from the SQL alone.
|
|
104
|
+
db.exec(V8_SCHEMA_FRAGMENT);
|
|
105
|
+
},
|
|
106
|
+
requiresForeignKeyDisable: true,
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
version: CURRENT_STORAGE_VERSION,
|
|
110
|
+
apply: (db) => {
|
|
111
|
+
db.exec(V9_SCHEMA_FRAGMENT);
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
];
|
|
115
|
+
|
|
116
|
+
export function runMigrations(db: Database, options: MigrationOptions = {}): void {
|
|
117
|
+
try {
|
|
118
|
+
db.exec(
|
|
119
|
+
"CREATE TABLE IF NOT EXISTS schema_migrations(version INTEGER PRIMARY KEY, applied_at TEXT NOT NULL)",
|
|
120
|
+
);
|
|
121
|
+
const applied = db
|
|
122
|
+
.query("SELECT version FROM schema_migrations ORDER BY version")
|
|
123
|
+
.all() as Array<{ version: number }>;
|
|
124
|
+
const appliedSet = new Set(applied.map((row) => row.version));
|
|
125
|
+
const foreignKeys = db.query("PRAGMA foreign_keys").get() as { foreign_keys: number };
|
|
126
|
+
// Gate the FK pragma toggle to steps that opt in via
|
|
127
|
+
// `requiresForeignKeyDisable`. v6 and v8 carry the flag (both
|
|
128
|
+
// rebuild a self-FK-bearing table via create-copy-drop-rename);
|
|
129
|
+
// a v9 that only adds columns inherits nothing. The restore
|
|
130
|
+
// below is unconditional on the FK state, regardless of the
|
|
131
|
+
// entry-point state — a connection that comes in with FKs OFF
|
|
132
|
+
// would otherwise be silently left OFF after migration, breaking
|
|
133
|
+
// the invariant every read path relies on. The row-level
|
|
134
|
+
// constraints the data depended on are re-validated by
|
|
135
|
+
// `PRAGMA foreign_key_check` from every read path.
|
|
136
|
+
const disableForeignKeys =
|
|
137
|
+
foreignKeys.foreign_keys === 1 &&
|
|
138
|
+
MIGRATION_STEPS.some(
|
|
139
|
+
(step) => !appliedSet.has(step.version) && step.requiresForeignKeyDisable === true,
|
|
140
|
+
);
|
|
141
|
+
if (disableForeignKeys) db.exec("PRAGMA foreign_keys = OFF");
|
|
142
|
+
const migrate = db.transaction(() => {
|
|
143
|
+
for (const step of MIGRATION_STEPS) {
|
|
144
|
+
if (appliedSet.has(step.version)) continue;
|
|
145
|
+
step.apply(db);
|
|
146
|
+
options.beforeRecordVersion?.(step.version);
|
|
147
|
+
db.query("INSERT INTO schema_migrations(version, applied_at) VALUES (?, ?)").run(
|
|
148
|
+
step.version,
|
|
149
|
+
new Date().toISOString(),
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
try {
|
|
154
|
+
migrate();
|
|
155
|
+
} finally {
|
|
156
|
+
// Always restore FKs to ON, regardless of the initial state.
|
|
157
|
+
// The restore is unconditional so a connection that arrived
|
|
158
|
+
// with FKs OFF (or a probe that disabled them mid-run) ends
|
|
159
|
+
// up with FKs ON, matching the openDatabase invariant.
|
|
160
|
+
db.exec("PRAGMA foreign_keys = ON");
|
|
161
|
+
}
|
|
162
|
+
} catch (error) {
|
|
163
|
+
const mapped = asStoreError(error);
|
|
164
|
+
if (mapped.code === "database_corrupt" || mapped.code === "database_busy") throw mapped;
|
|
165
|
+
throw new FacetStoreError("migration_failed", mapped.message, { cause: error });
|
|
166
|
+
}
|
|
167
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import type { Database } from "bun:sqlite";
|
|
2
|
+
|
|
3
|
+
import { type Template, TemplateSchema } from "../../shared/contracts/artifact";
|
|
4
|
+
import { now } from "../../shared/util/time";
|
|
5
|
+
import { asStoreError, FacetStoreError } from "./database";
|
|
6
|
+
|
|
7
|
+
export interface TemplateInput {
|
|
8
|
+
readonly artifactId: string;
|
|
9
|
+
readonly revisionId: string;
|
|
10
|
+
readonly name: string;
|
|
11
|
+
readonly description?: string | null;
|
|
12
|
+
readonly promotedBy: string;
|
|
13
|
+
readonly promotedAt?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface PromoteRevisionInput {
|
|
17
|
+
readonly artifactId?: string;
|
|
18
|
+
readonly revisionId: string;
|
|
19
|
+
readonly name: string;
|
|
20
|
+
readonly description?: string | null;
|
|
21
|
+
readonly promotedBy: string;
|
|
22
|
+
readonly promotedAt?: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function evictRevisions(
|
|
26
|
+
db: Database,
|
|
27
|
+
artifactId: string,
|
|
28
|
+
protectedRevisionId?: string,
|
|
29
|
+
): void {
|
|
30
|
+
while (true) {
|
|
31
|
+
const count = db
|
|
32
|
+
.query("SELECT COUNT(*) AS count FROM revisions WHERE artifact_id = ?")
|
|
33
|
+
.get(artifactId) as {
|
|
34
|
+
count: number;
|
|
35
|
+
};
|
|
36
|
+
if (count.count <= 50) return;
|
|
37
|
+
const candidate =
|
|
38
|
+
protectedRevisionId === undefined
|
|
39
|
+
? (db
|
|
40
|
+
.query(
|
|
41
|
+
"SELECT id FROM revisions WHERE artifact_id = ? AND pinned = 0 AND NOT EXISTS (SELECT 1 FROM templates WHERE templates.revision_id = revisions.id) ORDER BY revision_number ASC LIMIT 1",
|
|
42
|
+
)
|
|
43
|
+
.get(artifactId) as { id: string } | null)
|
|
44
|
+
: (db
|
|
45
|
+
.query(
|
|
46
|
+
"SELECT id FROM revisions WHERE artifact_id = ? AND id <> ? AND pinned = 0 AND NOT EXISTS (SELECT 1 FROM templates WHERE templates.revision_id = revisions.id) ORDER BY revision_number ASC LIMIT 1",
|
|
47
|
+
)
|
|
48
|
+
.get(artifactId, protectedRevisionId) as { id: string } | null);
|
|
49
|
+
if (!candidate) {
|
|
50
|
+
throw new FacetStoreError(
|
|
51
|
+
"revision_capacity_pinned",
|
|
52
|
+
`Revision capacity is full for artifact ${artifactId}; all revisions are pinned or template-bound`,
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
db.query("UPDATE revisions SET parent_revision_id = NULL WHERE parent_revision_id = ?").run(
|
|
56
|
+
candidate.id,
|
|
57
|
+
);
|
|
58
|
+
db.query("DELETE FROM revisions WHERE id = ?").run(candidate.id);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function promoteRevision(db: Database, input: PromoteRevisionInput): Template {
|
|
63
|
+
const owner = db
|
|
64
|
+
.query("SELECT artifact_id FROM revisions WHERE id = ?")
|
|
65
|
+
.get(input.revisionId) as { artifact_id: string } | null;
|
|
66
|
+
if (!owner) throw new FacetStoreError("foreign_key", `Revision not found: ${input.revisionId}`);
|
|
67
|
+
// The template table has independent foreign keys on artifact_id and
|
|
68
|
+
// revision_id, not a composite ownership constraint, so an explicit
|
|
69
|
+
// artifactId that disagrees with the revision's real owner would
|
|
70
|
+
// otherwise insert silently — instantiation would then copy the wrong
|
|
71
|
+
// artifact's bytes under the caller-supplied artifact's identity.
|
|
72
|
+
if (input.artifactId !== undefined && input.artifactId !== owner.artifact_id) {
|
|
73
|
+
throw new FacetStoreError(
|
|
74
|
+
"foreign_key",
|
|
75
|
+
`Revision ${input.revisionId} belongs to artifact ${owner.artifact_id}, not ${input.artifactId}`,
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
return createTemplate(db, { ...input, artifactId: owner.artifact_id });
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export function createTemplate(db: Database, input: TemplateInput): Template {
|
|
82
|
+
const promotedAt = input.promotedAt ?? now();
|
|
83
|
+
const value = {
|
|
84
|
+
id: crypto.randomUUID(),
|
|
85
|
+
artifactId: input.artifactId,
|
|
86
|
+
revisionId: input.revisionId,
|
|
87
|
+
name: input.name,
|
|
88
|
+
description: input.description ?? null,
|
|
89
|
+
promotedBy: input.promotedBy,
|
|
90
|
+
promotedAt,
|
|
91
|
+
};
|
|
92
|
+
try {
|
|
93
|
+
db.query(
|
|
94
|
+
"INSERT INTO templates(id, artifact_id, revision_id, name, description, promoted_by, promoted_at) VALUES (?, ?, ?, ?, ?, ?, ?)",
|
|
95
|
+
).run(
|
|
96
|
+
value.id,
|
|
97
|
+
value.artifactId,
|
|
98
|
+
value.revisionId,
|
|
99
|
+
value.name,
|
|
100
|
+
value.description,
|
|
101
|
+
value.promotedBy,
|
|
102
|
+
value.promotedAt,
|
|
103
|
+
);
|
|
104
|
+
return TemplateSchema.parse(value);
|
|
105
|
+
} catch (error) {
|
|
106
|
+
throw asStoreError(error);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export function pinRevision(db: Database, revisionId: string, pinned = true): void {
|
|
111
|
+
try {
|
|
112
|
+
const result = db
|
|
113
|
+
.query("UPDATE revisions SET pinned = ? WHERE id = ?")
|
|
114
|
+
.run(pinned ? 1 : 0, revisionId);
|
|
115
|
+
if (result.changes === 0) {
|
|
116
|
+
throw new FacetStoreError("foreign_key", `Revision not found: ${revisionId}`);
|
|
117
|
+
}
|
|
118
|
+
} catch (error) {
|
|
119
|
+
throw asStoreError(error);
|
|
120
|
+
}
|
|
121
|
+
}
|