@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,240 @@
|
|
|
1
|
+
import { createLogger } from "../shared/logging/logger";
|
|
2
|
+
import type {
|
|
3
|
+
InsecureLevel,
|
|
4
|
+
IsolationProbeResult,
|
|
5
|
+
Tier0IsolationProbe,
|
|
6
|
+
Tier0RunnerFactory,
|
|
7
|
+
Tier1AvailabilityProbe,
|
|
8
|
+
Tier1Runner,
|
|
9
|
+
Tier1RunnerFactory,
|
|
10
|
+
} from "../shared/contracts/validation";
|
|
11
|
+
import { FacetError } from "../shared/errors/facet-error";
|
|
12
|
+
|
|
13
|
+
import { startFacetService, type RunningService, type StartServiceOptions } from "./server";
|
|
14
|
+
import { defaultInsecureReason } from "./verdict-enrichment";
|
|
15
|
+
|
|
16
|
+
interface MutableServiceArgs {
|
|
17
|
+
dbPath?: string;
|
|
18
|
+
installTokenPath?: string;
|
|
19
|
+
promoteTokenPath?: string;
|
|
20
|
+
lockPath?: string;
|
|
21
|
+
evidencePath?: string;
|
|
22
|
+
idleTimeoutMs?: number;
|
|
23
|
+
tier0RunnerPath?: string;
|
|
24
|
+
tier1RunnerPath?: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface ParsedServiceArgs {
|
|
28
|
+
readonly dbPath?: string;
|
|
29
|
+
readonly installTokenPath?: string;
|
|
30
|
+
readonly promoteTokenPath?: string;
|
|
31
|
+
readonly lockPath?: string;
|
|
32
|
+
readonly evidencePath?: string;
|
|
33
|
+
readonly idleTimeoutMs?: number;
|
|
34
|
+
readonly tier0RunnerPath?: string;
|
|
35
|
+
readonly tier1RunnerPath?: string;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface LoadedTier0Runner {
|
|
39
|
+
readonly factory: Tier0RunnerFactory;
|
|
40
|
+
readonly probe?: Tier0IsolationProbe;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export interface LoadedTier1Runner {
|
|
44
|
+
readonly factory: Tier1RunnerFactory;
|
|
45
|
+
readonly probe?: Tier1AvailabilityProbe;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export interface ServiceRunnerModules {
|
|
49
|
+
readonly tier0: LoadedTier0Runner;
|
|
50
|
+
readonly loadTier1: () => Promise<LoadedTier1Runner>;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface ServiceProcessHooks {
|
|
54
|
+
readonly onSignal?: (signal: "SIGTERM" | "SIGINT", handler: () => void) => void;
|
|
55
|
+
readonly startService?: (options: StartServiceOptions) => Promise<RunningService>;
|
|
56
|
+
readonly writeStderr?: (line: string) => void;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function parseServiceArgs(argv: readonly string[]): ParsedServiceArgs {
|
|
60
|
+
const out: MutableServiceArgs = {};
|
|
61
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
62
|
+
const arg = argv[i];
|
|
63
|
+
if (arg === "--db-path") {
|
|
64
|
+
const value = argv[i + 1];
|
|
65
|
+
if (value !== undefined) {
|
|
66
|
+
out.dbPath = value;
|
|
67
|
+
i += 1;
|
|
68
|
+
}
|
|
69
|
+
} else if (arg === "--install-token-path") {
|
|
70
|
+
const value = argv[i + 1];
|
|
71
|
+
if (value !== undefined) {
|
|
72
|
+
out.installTokenPath = value;
|
|
73
|
+
i += 1;
|
|
74
|
+
}
|
|
75
|
+
} else if (arg === "--promote-token-path") {
|
|
76
|
+
const value = argv[i + 1];
|
|
77
|
+
if (value !== undefined) {
|
|
78
|
+
out.promoteTokenPath = value;
|
|
79
|
+
i += 1;
|
|
80
|
+
}
|
|
81
|
+
} else if (arg === "--lock-path") {
|
|
82
|
+
const value = argv[i + 1];
|
|
83
|
+
if (value !== undefined) {
|
|
84
|
+
out.lockPath = value;
|
|
85
|
+
i += 1;
|
|
86
|
+
}
|
|
87
|
+
} else if (arg === "--evidence-path") {
|
|
88
|
+
const value = argv[i + 1];
|
|
89
|
+
if (value !== undefined) {
|
|
90
|
+
out.evidencePath = value;
|
|
91
|
+
i += 1;
|
|
92
|
+
}
|
|
93
|
+
} else if (arg === "--idle-timeout-ms") {
|
|
94
|
+
const value = Number(argv[i + 1]);
|
|
95
|
+
if (Number.isFinite(value) && value > 0) {
|
|
96
|
+
out.idleTimeoutMs = value;
|
|
97
|
+
i += 1;
|
|
98
|
+
}
|
|
99
|
+
} else if (arg === "--tier0-runner-path") {
|
|
100
|
+
const value = argv[i + 1];
|
|
101
|
+
if (value !== undefined) {
|
|
102
|
+
out.tier0RunnerPath = value;
|
|
103
|
+
i += 1;
|
|
104
|
+
}
|
|
105
|
+
} else if (arg === "--tier1-runner-path") {
|
|
106
|
+
const value = argv[i + 1];
|
|
107
|
+
if (value !== undefined) {
|
|
108
|
+
out.tier1RunnerPath = value;
|
|
109
|
+
i += 1;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return out;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function parseInsecureLevel(raw: string | undefined): InsecureLevel {
|
|
117
|
+
if (raw === undefined || raw === "0") return 0;
|
|
118
|
+
if (raw === "1" || raw === "2" || raw === "3") return Number(raw) as InsecureLevel;
|
|
119
|
+
throw new FacetError(
|
|
120
|
+
"invalid_request",
|
|
121
|
+
`FACET_INSECURE must be one of 0, 1, 2, or 3; got '${raw}'`,
|
|
122
|
+
{ retryable: false },
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function isAutoFallbackEnabled(raw: string | undefined): boolean {
|
|
127
|
+
return raw === "1";
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function boundedProbeReason(result: IsolationProbeResult): string {
|
|
131
|
+
const reason = result.reason?.trim() || "unavailable";
|
|
132
|
+
return reason.slice(0, 240);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function requireProbe<T>(probe: T | undefined, label: string): T {
|
|
136
|
+
if (probe !== undefined) return probe;
|
|
137
|
+
throw new FacetError("internal", `${label} probe is required for insecure auto fallback`, {
|
|
138
|
+
retryable: false,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function createLazyTier1Runner(
|
|
143
|
+
loadTier1: () => Promise<LoadedTier1Runner>,
|
|
144
|
+
level: InsecureLevel,
|
|
145
|
+
): Tier1Runner {
|
|
146
|
+
let runner: Promise<Tier1Runner> | undefined;
|
|
147
|
+
return async (input) => {
|
|
148
|
+
runner ??= loadTier1().then((tier1) => tier1.factory(level));
|
|
149
|
+
return runner.then((loaded) => loaded(input));
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export async function runServiceProcess(
|
|
154
|
+
argv: readonly string[],
|
|
155
|
+
env: NodeJS.ProcessEnv,
|
|
156
|
+
loadModules: (args: ParsedServiceArgs, env: NodeJS.ProcessEnv) => Promise<ServiceRunnerModules>,
|
|
157
|
+
hooks: ServiceProcessHooks = {},
|
|
158
|
+
): Promise<number> {
|
|
159
|
+
const logger = createLogger({ component: "main" });
|
|
160
|
+
const args = parseServiceArgs(argv);
|
|
161
|
+
const onSignal = hooks.onSignal ?? ((signal, handler) => process.on(signal, handler));
|
|
162
|
+
const startService = hooks.startService ?? startFacetService;
|
|
163
|
+
const writeStderr = hooks.writeStderr ?? ((line) => process.stderr.write(line));
|
|
164
|
+
let running: RunningService | null = null;
|
|
165
|
+
const shutdown = async (signal: string): Promise<void> => {
|
|
166
|
+
logger.info("service.signal", { signal });
|
|
167
|
+
if (running) await running.stop();
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
onSignal("SIGTERM", () => void shutdown("SIGTERM"));
|
|
171
|
+
onSignal("SIGINT", () => void shutdown("SIGINT"));
|
|
172
|
+
|
|
173
|
+
try {
|
|
174
|
+
const forcedLevel = parseInsecureLevel(env.FACET_INSECURE);
|
|
175
|
+
const autoFallback = isAutoFallbackEnabled(env.FACET_INSECURE_AUTO);
|
|
176
|
+
const modules = await loadModules(args, env);
|
|
177
|
+
let insecureLevel = forcedLevel;
|
|
178
|
+
let insecureReason: string | null = null;
|
|
179
|
+
let tier1Module: LoadedTier1Runner | undefined;
|
|
180
|
+
if (autoFallback && forcedLevel < 2) {
|
|
181
|
+
tier1Module = await modules.loadTier1();
|
|
182
|
+
const tier0Probe = requireProbe(modules.tier0.probe, "Tier 0 isolation");
|
|
183
|
+
const tier0 = await tier0Probe();
|
|
184
|
+
if (!tier0.available) {
|
|
185
|
+
insecureLevel = 2;
|
|
186
|
+
insecureReason = `auto:${boundedProbeReason(tier0)}`;
|
|
187
|
+
} else if (forcedLevel === 0) {
|
|
188
|
+
const tier1Probe = requireProbe(tier1Module.probe, "Tier 1 availability");
|
|
189
|
+
const tier1 = await tier1Probe();
|
|
190
|
+
if (!tier1.available) {
|
|
191
|
+
insecureLevel = 1;
|
|
192
|
+
insecureReason = `auto:${boundedProbeReason(tier1)}`;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
if (insecureLevel > 0) {
|
|
197
|
+
const reason = insecureReason ?? defaultInsecureReason(insecureLevel);
|
|
198
|
+
writeStderr(`WARN: FACET_INSECURE=${insecureLevel} — ${reason}\n`);
|
|
199
|
+
}
|
|
200
|
+
running = await startService({
|
|
201
|
+
...(args.dbPath !== undefined ? { dbPath: args.dbPath } : {}),
|
|
202
|
+
...(args.installTokenPath !== undefined ? { installTokenPath: args.installTokenPath } : {}),
|
|
203
|
+
...(args.promoteTokenPath !== undefined ? { promoteTokenPath: args.promoteTokenPath } : {}),
|
|
204
|
+
...(args.lockPath !== undefined ? { lockPath: args.lockPath } : {}),
|
|
205
|
+
...(args.evidencePath !== undefined ? { evidencePath: args.evidencePath } : {}),
|
|
206
|
+
...(args.idleTimeoutMs !== undefined ? { idleTimeoutMs: args.idleTimeoutMs } : {}),
|
|
207
|
+
tier0Runner: modules.tier0.factory(insecureLevel),
|
|
208
|
+
tier1Runner: createLazyTier1Runner(
|
|
209
|
+
() => (tier1Module === undefined ? modules.loadTier1() : Promise.resolve(tier1Module)),
|
|
210
|
+
insecureLevel,
|
|
211
|
+
),
|
|
212
|
+
insecureLevel,
|
|
213
|
+
insecureReason,
|
|
214
|
+
logger,
|
|
215
|
+
});
|
|
216
|
+
writeStderr(
|
|
217
|
+
`${JSON.stringify({
|
|
218
|
+
event: "service.ready",
|
|
219
|
+
component: "main",
|
|
220
|
+
timestamp: new Date().toISOString(),
|
|
221
|
+
pid: process.pid,
|
|
222
|
+
port: running.port,
|
|
223
|
+
url: running.url,
|
|
224
|
+
...(insecureLevel > 0
|
|
225
|
+
? {
|
|
226
|
+
insecureLevel,
|
|
227
|
+
insecureReason: insecureReason ?? defaultInsecureReason(insecureLevel),
|
|
228
|
+
}
|
|
229
|
+
: {}),
|
|
230
|
+
})}\n`,
|
|
231
|
+
);
|
|
232
|
+
await running.waitUntilIdle();
|
|
233
|
+
await running.stop();
|
|
234
|
+
return 0;
|
|
235
|
+
} catch (error) {
|
|
236
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
237
|
+
logger.error("service.failed", { errorMessage: message });
|
|
238
|
+
return 1;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Command-route guard helpers.
|
|
3
|
+
*
|
|
4
|
+
* These support functions implement the per-request checks that sit
|
|
5
|
+
* between `handleCommand`'s header read and its dispatch call:
|
|
6
|
+
* request-metadata extraction, body-cap enforcement, JSON parsing,
|
|
7
|
+
* and the `FacetError.code → HTTP status` mapping used by the
|
|
8
|
+
* catch-all error path. Gallery routes use `resolveGalleryRequest` for the
|
|
9
|
+
* shared host → auth → lease → revision → artifact sequence, while command
|
|
10
|
+
* routes retain their longer orchestration in `router.ts`.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { FacetError } from "../shared/errors/facet-error";
|
|
14
|
+
import { requireAnyBearer } from "./security/auth";
|
|
15
|
+
import {
|
|
16
|
+
checkHostOrigin,
|
|
17
|
+
isCrossSiteRejection,
|
|
18
|
+
isMissingHostRejection,
|
|
19
|
+
resolveHost,
|
|
20
|
+
} from "./security/host-origin";
|
|
21
|
+
import type { GalleryLeaseManager, GalleryLease } from "./security/leases";
|
|
22
|
+
import type { Artifact, Revision } from "../shared/contracts/artifact";
|
|
23
|
+
import type { ArtifactRepository } from "./store/repository";
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Hard ceiling on the raw HTTP body. Distinct from `SOURCE_CAP_BYTES`
|
|
27
|
+
* (which governs artifact payload bytes after decode). 16 MiB is well
|
|
28
|
+
* above 5 MiB source × 4/3 base64 envelope slack, so a legitimate
|
|
29
|
+
* client never hits it.
|
|
30
|
+
*/
|
|
31
|
+
export const RAW_BODY_CAP_BYTES = 16 * 1024 * 1024;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Request metadata extracted from headers — read BEFORE the body.
|
|
35
|
+
* Auth, mutation headers, and the raw size cap all branch on this
|
|
36
|
+
* object; the body itself is read only after those checks pass. This
|
|
37
|
+
* split keeps unauthenticated requests from touching the body at all.
|
|
38
|
+
*/
|
|
39
|
+
export interface RequestMeta {
|
|
40
|
+
readonly url: string;
|
|
41
|
+
readonly method: string;
|
|
42
|
+
readonly host: string | null;
|
|
43
|
+
readonly origin: string | null;
|
|
44
|
+
readonly secFetchSite: string | null;
|
|
45
|
+
readonly contentType: string | null;
|
|
46
|
+
readonly authorization: string | null;
|
|
47
|
+
readonly contentLength: number | null;
|
|
48
|
+
readonly headers: { get(name: string): string | null };
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function readRequestMeta(req: Request): RequestMeta {
|
|
52
|
+
const url = new URL(req.url);
|
|
53
|
+
const cl = req.headers.get("content-length");
|
|
54
|
+
return {
|
|
55
|
+
url: url.pathname + url.search,
|
|
56
|
+
method: req.method,
|
|
57
|
+
host: req.headers.get("host"),
|
|
58
|
+
origin: req.headers.get("origin"),
|
|
59
|
+
secFetchSite: req.headers.get("sec-fetch-site"),
|
|
60
|
+
contentType: req.headers.get("content-type"),
|
|
61
|
+
authorization: req.headers.get("authorization"),
|
|
62
|
+
contentLength: cl !== null ? Number(cl) : null,
|
|
63
|
+
headers: req.headers,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export interface GalleryRequestDeps {
|
|
68
|
+
readonly expectedHost: string | (() => string);
|
|
69
|
+
readonly ownOrigin: string | (() => string);
|
|
70
|
+
readonly installToken: string;
|
|
71
|
+
readonly leases: GalleryLeaseManager;
|
|
72
|
+
readonly repository: ArtifactRepository;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export type GalleryRequestResolution =
|
|
76
|
+
| {
|
|
77
|
+
readonly ok: true;
|
|
78
|
+
readonly meta: RequestMeta;
|
|
79
|
+
readonly lease: GalleryLease;
|
|
80
|
+
readonly artifactId: string;
|
|
81
|
+
readonly revision: Revision;
|
|
82
|
+
readonly artifact: Artifact;
|
|
83
|
+
}
|
|
84
|
+
| { readonly ok: false; readonly response: Response };
|
|
85
|
+
|
|
86
|
+
export function statusForHostCheck(error: FacetError | undefined): number {
|
|
87
|
+
if (isCrossSiteRejection(error)) return 403;
|
|
88
|
+
if (isMissingHostRejection(error)) return 421;
|
|
89
|
+
return 400;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** Resolve the shared host, capability, and bound-revision gallery guards. */
|
|
93
|
+
export function resolveGalleryRequest(
|
|
94
|
+
req: Request,
|
|
95
|
+
deps: GalleryRequestDeps,
|
|
96
|
+
): GalleryRequestResolution {
|
|
97
|
+
const meta = readRequestMeta(req);
|
|
98
|
+
const hostCheck = checkHostOrigin({
|
|
99
|
+
method: meta.method,
|
|
100
|
+
host: meta.host,
|
|
101
|
+
origin: meta.origin,
|
|
102
|
+
secFetchSite: meta.secFetchSite,
|
|
103
|
+
expectedHost: resolveHost(deps.expectedHost),
|
|
104
|
+
ownOrigin: resolveHost(deps.ownOrigin),
|
|
105
|
+
});
|
|
106
|
+
if (!hostCheck.ok)
|
|
107
|
+
return {
|
|
108
|
+
ok: false,
|
|
109
|
+
response: new Response(null, { status: statusForHostCheck(hostCheck.error) }),
|
|
110
|
+
};
|
|
111
|
+
const auth = requireAnyBearer(meta.authorization, [deps.installToken]);
|
|
112
|
+
const leaseId = meta.headers.get("x-gallery-lease");
|
|
113
|
+
const artifactId = meta.headers.get("x-gallery-artifact");
|
|
114
|
+
if (!auth.ok || leaseId === null || artifactId === null) {
|
|
115
|
+
return {
|
|
116
|
+
ok: false,
|
|
117
|
+
response: new Response(null, { status: 401, headers: { "cache-control": "no-store" } }),
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
const lease = deps.leases
|
|
121
|
+
.list()
|
|
122
|
+
.find((entry) => entry.leaseId === leaseId && entry.artifactId === artifactId);
|
|
123
|
+
if (lease === undefined) {
|
|
124
|
+
return {
|
|
125
|
+
ok: false,
|
|
126
|
+
response: new Response(null, { status: 401, headers: { "cache-control": "no-store" } }),
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
const revisionSha = new URL(req.url).searchParams.get("revisionSha");
|
|
130
|
+
if (revisionSha === null || revisionSha.length === 0) {
|
|
131
|
+
return {
|
|
132
|
+
ok: false,
|
|
133
|
+
response: new Response(null, { status: 400, headers: { "cache-control": "no-store" } }),
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
const revision = deps.repository.getRevisionBySha(artifactId, revisionSha);
|
|
137
|
+
if (revision === null) {
|
|
138
|
+
return {
|
|
139
|
+
ok: false,
|
|
140
|
+
response: new Response(null, { status: 404, headers: { "cache-control": "no-store" } }),
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
const artifact = deps.repository.getArtifactById(artifactId);
|
|
144
|
+
if (artifact === null) {
|
|
145
|
+
return {
|
|
146
|
+
ok: false,
|
|
147
|
+
response: new Response(null, { status: 404, headers: { "cache-control": "no-store" } }),
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
return { ok: true, meta, lease, artifactId, revision, artifact };
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Read the request body up to `RAW_BODY_CAP_BYTES`. The Content-Length
|
|
155
|
+
* header is the cheap first check (no body read needed when it already
|
|
156
|
+
* exceeds the cap); a second check after `req.text()` defends against a
|
|
157
|
+
* missing or lying Content-Length. Both violations throw the same typed
|
|
158
|
+
* `payload_too_large` error so the catch path returns a uniform 413.
|
|
159
|
+
*/
|
|
160
|
+
export async function readCappedBody(req: Request, contentLength: number | null): Promise<string> {
|
|
161
|
+
if (contentLength !== null) {
|
|
162
|
+
if (!Number.isFinite(contentLength) || contentLength < 0) {
|
|
163
|
+
throw new FacetError("invalid_request", "Invalid Content-Length", { retryable: false });
|
|
164
|
+
}
|
|
165
|
+
if (contentLength > RAW_BODY_CAP_BYTES) {
|
|
166
|
+
throw new FacetError("payload_too_large", "Request body exceeds raw cap", {
|
|
167
|
+
retryable: false,
|
|
168
|
+
details: { capBytes: RAW_BODY_CAP_BYTES, receivedBytes: contentLength },
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
const bytes = new Uint8Array(await req.arrayBuffer());
|
|
173
|
+
const receivedBytes = bytes.byteLength;
|
|
174
|
+
if (receivedBytes > RAW_BODY_CAP_BYTES) {
|
|
175
|
+
throw new FacetError("payload_too_large", "Request body exceeds raw cap", {
|
|
176
|
+
retryable: false,
|
|
177
|
+
details: { capBytes: RAW_BODY_CAP_BYTES, receivedBytes },
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
return new TextDecoder().decode(bytes);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Parse the body text as JSON. On failure, return a sentinel symbol
|
|
185
|
+
* (`Symbol.for("invalid_json")`) rather than throwing — the caller
|
|
186
|
+
* decides how to surface it as an envelope error, keeping this helper
|
|
187
|
+
* free of envelope concerns.
|
|
188
|
+
*/
|
|
189
|
+
export function parseBody(bodyText: string): unknown {
|
|
190
|
+
try {
|
|
191
|
+
return JSON.parse(bodyText);
|
|
192
|
+
} catch {
|
|
193
|
+
return Symbol.for("invalid_json");
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
export const INVALID_JSON = Symbol.for("invalid_json");
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Map a `FacetError.code` to its HTTP status. Store codes that share
|
|
201
|
+
* a status with non-store codes (e.g. `constraint` and `duplicate_revision`
|
|
202
|
+
* both 409) are grouped so the switch arms stay flat. The default 500
|
|
203
|
+
* covers unrecognized codes; tier1_* failures are handled in runTier1Safe
|
|
204
|
+
* before reaching this function, while other codes without an explicit arm
|
|
205
|
+
* fall through to 500.
|
|
206
|
+
*/
|
|
207
|
+
export function statusFor(error: FacetError): number {
|
|
208
|
+
switch (error.code) {
|
|
209
|
+
case "artifact_not_found":
|
|
210
|
+
case "revision_not_found":
|
|
211
|
+
case "template_not_found":
|
|
212
|
+
case "evidence_unavailable":
|
|
213
|
+
return 404;
|
|
214
|
+
case "payload_too_large":
|
|
215
|
+
return 413;
|
|
216
|
+
case "reserved_not_implemented":
|
|
217
|
+
case "unsupported_reserved_type":
|
|
218
|
+
case "invalid_envelope":
|
|
219
|
+
case "invalid_request":
|
|
220
|
+
case "unknown_schema_version":
|
|
221
|
+
return 400;
|
|
222
|
+
case "tier0_unavailable":
|
|
223
|
+
return 503;
|
|
224
|
+
case "duplicate_revision":
|
|
225
|
+
case "constraint":
|
|
226
|
+
case "foreign_key":
|
|
227
|
+
case "immutable_revision":
|
|
228
|
+
case "invalid_artifact_type":
|
|
229
|
+
case "revision_capacity_pinned":
|
|
230
|
+
return 409;
|
|
231
|
+
case "tier0_timeout":
|
|
232
|
+
case "tier0_protocol_error":
|
|
233
|
+
case "tier0_worker_died":
|
|
234
|
+
case "tier0_output_cap":
|
|
235
|
+
return 422;
|
|
236
|
+
default:
|
|
237
|
+
return 500;
|
|
238
|
+
}
|
|
239
|
+
}
|