/** * What this lab can actually materialise, and a refusal for everything else. * * A declaration the runtime silently ignores is the worst thing this project could ship. * The mesh already has that fault catalogued: a firewall key declared in five manifests * and read by no code, so a manifest appears to restrict a port and restricts nothing * (novox/hq 04-ISSUES/003). A scenario that declares a gateway and raises without one * would be the same fault, in the tool built to catch it. * * So unimplemented parts of the model are refused loudly at raise time rather than * ignored. The declaration schema deliberately runs ahead of the runtime — it is the * design's shape, and validating against it is useful before any of it can be raised — * but the gap between the two has to be visible. */ import type { Scenario } from "../declaration/types.ts"; import { PLACEABLE, planPlacements } from "./place.ts"; export class UnsupportedError extends Error { readonly missing: string[]; constructor(missing: string[]) { super( `this scenario declares things the lab cannot yet materialise:\n - ${missing.join("\n - ")}\n\n` + `Raising it would produce a mesh that silently lacks them, which is the exact fault ` + `this lab exists to catch. Validation accepts them because the declaration model is ` + `complete; the runtime is not.`, ); this.name = "UnsupportedError"; this.missing = missing; } } export function assertSupported(scenario: Scenario): void { const missing: string[] = []; // `place: [host]` works. Everything else in the vocabulary is named individually rather // than refused as a whole, so a scenario that places a host and a substrate is told exactly // which half the lab cannot do. const unplaceable = new Set(); for (const { artifacts } of planPlacements(scenario)) { for (const artifact of artifacts) { if (!(PLACEABLE as readonly string[]).includes(artifact)) unplaceable.add(artifact); } } for (const artifact of [...unplaceable].sort()) { missing.push( `place: ${artifact} — only ${PLACEABLE.join(", ")} can be placed; the tiers above ` + `tier 0 do not exist yet`, ); } if (missing.length > 0) throw new UnsupportedError(missing); }