Files
quixos-protocol/src/execution-world/installation.ts
T
Timothy J. Aveni 62a09605cf Reuse verified immutable plans and streamline cooperative hashing
Continue final hosted development reliability qualification.
2026-10-12 20:16:56 -07:00

400 lines
17 KiB
TypeScript

import { executionPlanDigestAsync, ExecutionPlanError, type ExecutionPlan } from "./plan.js";
import { compileInspectionTemplates, type InspectionTemplate, type InspectionKernel } from "./inspection.js";
import path from "node:path";
import { loadCheckedArtifactWorld } from "./receipts.js";
import { contentArtifactUrl, loadArtifactWorld, type LoadedArtifactWorld } from "./files.js";
import { selectArtifactImplementation, type ArtifactImplementation, type ComponentArtifact } from "./artifacts.js";
import {
publicOperationContract,
publicQueryContract,
type PublicOperationContract,
type PublicQueryContract,
} from "./client-contracts.js";
import { resultInterfaces } from "./projections.js";
import type { CandidateMetadataScope } from "./metadata.js";
/** Activation is assigned by graph authority, never by a package artifact. */
export interface ActiveExecutionIdentity {
readonly workspace: string;
readonly world: string;
readonly plan: string;
readonly epoch: string;
}
/** Host-owned execution selection. The lifecycle manager fills its checked inputs. */
export interface ExecutionGroupIdentity {
readonly logicalId: string;
readonly executionDigest: string;
}
export interface ClientContractCatalog {
readonly inspections: readonly InspectionTemplate[];
readonly resultInterfaces: Readonly<Record<string, readonly string[]>>;
readonly operations: readonly PublicOperationContract[];
readonly queries: readonly PublicQueryContract[];
readonly components: readonly InstalledComponent[];
readonly presentations: readonly { id: string; subject: string; packageRevision: string; component: string }[];
readonly moduleBindings: readonly {
atom: string;
interface: string;
member: string;
packageRevision: string;
id: string;
}[];
}
/** Explicit projection prevents accidental spreading of filesystem roots or private bindings. */
export async function clientContractCatalog(
plan: ExecutionPlan,
installation: ExecutionInstallation,
requestedPackages: readonly string[],
checkedKernel?: InspectionKernel,
): Promise<ClientContractCatalog> {
if (installation.plan !== plan.digest || (await executionPlanDigestAsync(plan)) !== plan.digest)
throw new ExecutionPlanError(
"CATALOG_PLAN_MISMATCH",
plan.digest,
"Installation and public catalog must use the same checked plan",
);
const packages = requestedPackages.map((revision) => {
const pkg = plan.definition.workspace.packageImports.find((p) => p.revisionId === revision);
if (!pkg)
throw new ExecutionPlanError("UNINSTALLED_PACKAGE", revision, "Requested catalog package is not installed");
return pkg;
});
// Interface metadata contains no authority or private implementation configuration.
// A later admission optimization can narrow this set without changing operation identities.
const operations = plan.definition.workspace.interfaceImports
.filter((i) => !i.template)
.flatMap((iface) =>
iface.members.flatMap((member) =>
member.operations
.filter((o) => o.mode === "call")
.map((operation) => publicOperationContract(iface, operation)),
),
);
const inspection = compileInspectionTemplates(plan, checkedKernel);
return {
inspections: inspection.templates,
resultInterfaces: Object.fromEntries(
plan.definition.operations.map((operation) => [operation.key, resultInterfaces(plan, operation.key)]),
),
operations,
queries: [
...inspection.contracts,
...packages.flatMap((pkg) => (pkg.checkedQueries ?? []).map((q) => publicQueryContract(pkg, q.declaration.id))),
],
components: installation.components.filter((c) => requestedPackages.includes(c.packageRevision)),
moduleBindings: plan.definition.workspace.conformances.flatMap((c) =>
(c.moduleBindings ?? [])
.filter((b) => requestedPackages.includes(b.packageRevisionId))
.map((b) => ({
atom: c.atomId,
interface: c.interfaceRevisionId,
member: b.memberId,
packageRevision: b.packageRevisionId,
id: b.moduleId,
})),
),
presentations: (plan.definition.presentations ?? [])
.filter((p) => requestedPackages.includes(p.packageRevisionId))
.map((p) => ({ id: p.id, subject: p.subject, packageRevision: p.packageRevisionId, component: p.componentId })),
};
}
/** Candidate-owned compiler output, never graph state or authorization. Compile
* once, then project each requested package set without hashing/recompiling the
* plan. Reserve bounded metadata before compilation; disposal releases both the
* catalog and its charge. Callers must supply the candidate's checked inputs. */
export function createClientContractCatalog(
plan: ExecutionPlan,
installation: ExecutionInstallation,
metadata: CandidateMetadataScope,
checkedKernel?: InspectionKernel,
) {
const revisions = plan.definition.workspace.packageImports.map((pkg) => pkg.revisionId);
const installed = new Set<string>(revisions);
let catalog: ClientContractCatalog | undefined;
let preparing: Promise<void> | undefined;
let release: (() => void) | undefined;
let closed = false;
const freeze = (value: unknown, seen = new WeakSet<object>()) => {
if (!value || typeof value !== "object" || seen.has(value)) return;
seen.add(value);
for (const child of Object.values(value)) freeze(child, seen);
Object.freeze(value);
};
return {
async select(requestedPackages: readonly string[]): Promise<ClientContractCatalog> {
if (closed) throw Error("CANDIDATE_METADATA_CLOSED");
for (const revision of requestedPackages)
if (!installed.has(revision))
throw new ExecutionPlanError("UNINSTALLED_PACKAGE", revision, "Requested catalog package is not installed");
if (!catalog) {
// Like other candidate admission charges, this is an allocation estimate,
// not a V8 heap limit. The process/cgroup ceiling bounds transient work.
preparing ??= (async () => {
const reservation = metadata.reserve(32 * 1024 * 1024);
try {
const compiled = await clientContractCatalog(plan, installation, revisions, checkedKernel);
if (closed) throw Error("CANDIDATE_METADATA_CLOSED");
const bytes = Buffer.byteLength(JSON.stringify(compiled));
if (bytes > 8 * 1024 * 1024) throw Error("CANDIDATE_CATALOG_LIMIT");
freeze(compiled);
// No await between reservations: replacing the transient upper bound
// with a smaller retained estimate cannot race another admission.
reservation();
release = metadata.reserve(Math.max(64 * 1024, bytes * 4));
catalog = compiled;
} catch (error) {
reservation();
throw error;
}
})().finally(() => {
preparing = undefined;
});
await preparing;
}
if (closed || !catalog) throw Error("CANDIDATE_METADATA_CLOSED");
const requested = new Set(requestedPackages);
return {
inspections: catalog.inspections,
resultInterfaces: catalog.resultInterfaces,
operations: catalog.operations,
queries: [
...catalog.queries.filter((query) => !installed.has(query.package)),
...requestedPackages.flatMap((revision) => catalog!.queries.filter((query) => query.package === revision)),
],
components: catalog.components.filter((component) => requested.has(component.packageRevision)),
moduleBindings: catalog.moduleBindings.filter((binding) => requested.has(binding.packageRevision)),
presentations: catalog.presentations.filter((presentation) => requested.has(presentation.packageRevision)),
};
},
close() {
closed = true;
catalog = undefined;
release?.();
release = undefined;
},
};
}
export interface PackageInstallationSelection {
readonly browser?: { readonly id?: string };
readonly service?: { readonly id?: string };
/** Including a module is optional; executing it still requires host trust policy. */
readonly module?: { readonly id?: string };
}
export interface ExecutionInstallation {
readonly codec: "camino-execution-installation-v1";
readonly plan: string;
readonly world: string;
readonly packages: readonly {
readonly revision: string;
readonly root: string;
readonly service?: ArtifactImplementation;
readonly module?: ArtifactImplementation;
/** Checked candidate only; the qualified host verifies its import surface and SDK. */
readonly restricted?: ArtifactImplementation;
readonly browserImplementation?: ArtifactImplementation;
readonly browserURL?: string;
readonly browserRegistry?: string;
}[];
readonly routes: Readonly<Record<string, { readonly path: string; readonly mediaType: string }>>;
readonly coreURL?: string;
readonly engineURL?: string;
readonly components: readonly InstalledComponent[];
}
/** Safe to expose in a presentation catalog: no source paths, state slots, or host configuration. */
export interface InstalledComponent {
readonly role: {
readonly interface: string;
readonly member: string;
readonly subject: string;
readonly contract: string;
readonly typeArguments?: readonly unknown[];
readonly requiredInterfaces?: readonly string[];
};
readonly packageRevision: string;
readonly id: string;
readonly subject: string;
readonly url: string;
readonly exportName: string;
readonly styles: readonly string[];
readonly compatibility: ComponentArtifact["compatibility"];
/** Owned and interpreted by the React artifact consumer. */
readonly preparation?: unknown;
readonly sharedModules: Readonly<Record<keyof ComponentArtifact["sharedModules"], string>>;
}
/** Build-time validation uses the compiler selected by the Nix derivation. */
export async function checkExecutionInstallation(
plan: ExecutionPlan,
roots: Readonly<Record<string, string>>,
generator: string,
selections: Readonly<Record<string, PackageInstallationSelection>> = {},
): Promise<ExecutionInstallation> {
const loaded = await loadCheckedArtifactWorld(plan, roots, generator);
return assembleExecutionInstallation(plan, roots, loaded, selections);
}
/** Load immutable artifacts without regenerating bindings with the host compiler.
* Format, coverage, content and runtime ABI checks still apply. This grants no
* authority to activate a world or run optional modules in process. */
export async function loadExecutionInstallation(
plan: ExecutionPlan,
roots: Readonly<Record<string, string>>,
selections: Readonly<Record<string, PackageInstallationSelection>> = {},
metadata?: CandidateMetadataScope,
): Promise<ExecutionInstallation> {
return assembleExecutionInstallation(plan, roots, await loadArtifactWorld(plan, roots, metadata), selections);
}
function assembleExecutionInstallation(
plan: ExecutionPlan,
roots: Readonly<Record<string, string>>,
loaded: LoadedArtifactWorld,
selections: Readonly<Record<string, PackageInstallationSelection>>,
): ExecutionInstallation {
const fail = (where: string, message: string): never => {
throw new ExecutionPlanError("INSTALLATION_INVALID", where, message);
};
for (const revision of Object.keys(selections))
if (!loaded.manifests.some((manifest) => manifest.packageRevisionId === revision))
fail(revision, "Selection names a package outside this checked world");
const routes: Record<string, { path: string; mediaType: string }> = Object.create(null);
const packages: ExecutionInstallation["packages"][number][] = [];
const components: InstalledComponent[] = [];
const sharedComponentModules = new Map<string, string>();
let coreURL: string | undefined, engineURL: string | undefined;
for (const manifest of loaded.manifests) {
const revision = manifest.packageRevisionId;
const root = roots[revision]!;
const selection = selections[revision] ?? {};
const exports = plan.definition.packages.find((pkg) => pkg.revision === revision)!.exports;
const service =
exports.length || selection.service
? selectArtifactImplementation(manifest, {
...selection.service,
target: "server",
compatibility: "quixos-service-v1",
exports: exports.map((entry) => entry.id),
})
: undefined;
for (const component of manifest.components ?? []) {
const sharedModules = Object.fromEntries(
Object.entries(component.sharedModules).map(([name, filePath]) => {
const file = component.files.find((file) => file.path === filePath)!;
const url = contentArtifactUrl(file),
previous = sharedComponentModules.get(name);
if (previous && previous !== url) fail(component.id, `Components disagree on shared module ${name}`);
sharedComponentModules.set(name, url);
return [name, url];
}),
) as InstalledComponent["sharedModules"];
for (const file of component.files) {
const url = contentArtifactUrl(file);
if (routes[url] && routes[url].mediaType !== file.mediaType) fail(url, "Conflicting artifact media types");
routes[url] ??= { path: path.join(root, file.path), mediaType: file.mediaType };
}
components.push({
...(() => {
const pkg = plan.definition.workspace.packageImports.find((entry) => entry.revisionId === revision);
const artifact = pkg?.buildArtifacts?.["org.quixos.react.preparation/1"] as
| { modules: { module: string }[] }
| undefined;
const preparation = artifact?.modules.find((entry) => entry.module === component.id);
return preparation ? { preparation } : {};
})(),
role: (() => {
const module = plan.definition.packages
.find((p) => p.revision === revision)!
.modules!.find((m) => m.id === component.id)!;
return {
interface: module.interfaceRevisionId,
member: module.memberId,
subject: component.subject,
contract: module.contract,
...(module.typeArguments ? { typeArguments: module.typeArguments } : {}),
...(module.requiredInterfaces ? { requiredInterfaces: module.requiredInterfaces } : {}),
};
})(),
packageRevision: revision,
id: component.id,
subject: component.subject,
compatibility: component.compatibility,
exportName: component.exportName,
styles: component.files.filter((file) => file.mediaType === "text/css").map(contentArtifactUrl),
sharedModules,
url: contentArtifactUrl(component.files.find((file) => file.path === component.path)!),
});
}
const module = selection.module
? selectArtifactImplementation(manifest, {
...selection.module,
target: "server",
compatibility: "quixos-js-module-v1",
exports: exports.map((entry) => entry.id),
})
: undefined;
const restrictedCandidates = manifest.implementations.filter(
(entry) => entry.compatibility === "quixos-restricted-module-v1",
);
if (restrictedCandidates.length > 1) fail(revision, "Ambiguous restricted module candidates");
const restricted = restrictedCandidates[0];
const browserExports = exports.filter(
(entry) =>
entry.execution.kind !== "remote" &&
entry.execution.targets.includes("target:org.quixos.execution.javascript@1"),
);
if (!browserExports.length) {
if (selection.browser) fail(revision, "Package has no browser exports to select");
packages.push({
revision,
root,
...(service ? { service } : {}),
...(module ? { module } : {}),
...(restricted ? { restricted } : {}),
});
continue;
}
const browser = selectArtifactImplementation(manifest, {
...selection.browser,
target: "target:org.quixos.execution.javascript@1",
compatibility: "quixos-js-module-v1",
exports: browserExports.map((entry) => entry.id),
});
const entry = browser.files.find((file) => file.path === browser.path)!;
const shared = (name: string) => {
const files = browser.files.filter((file) => file.path.endsWith("/" + name));
if (files.length !== 1) fail(revision, "Expected one shared " + name);
return contentArtifactUrl(files[0]!);
};
const core = shared("core.mjs"),
engine = shared("engine.mjs");
if ((coreURL && coreURL !== core) || (engineURL && engineURL !== engine))
fail(revision, "Browser packages disagree on the shared runtime identity");
coreURL = core;
engineURL = engine;
for (const file of browser.files) {
const url = contentArtifactUrl(file);
if (routes[url] && routes[url].mediaType !== file.mediaType) fail(url, "Conflicting artifact media types");
routes[url] ??= { path: path.join(root, file.path), mediaType: file.mediaType };
}
packages.push({
revision,
root,
...(service ? { service } : {}),
...(module ? { module } : {}),
...(restricted ? { restricted } : {}),
browserImplementation: browser,
browserURL: contentArtifactUrl(entry),
browserRegistry: browser.registryExport,
});
}
return {
codec: "camino-execution-installation-v1",
plan: plan.digest,
world: loaded.digest,
packages,
components,
routes,
...(coreURL ? { coreURL, engineURL } : {}),
};
}