Select checked implementations explicitly by target and ABI
This commit is contained in:
@@ -113,3 +113,29 @@ Common implementation helpers can still be ordinary generic TypeScript functions
|
|||||||
This does not implement universal runtime type application or legacy constructors.
|
This does not implement universal runtime type application or legacy constructors.
|
||||||
The `camino-portable-bindings` check compiles positive/negative typed consumers and
|
The `camino-portable-bindings` check compiles positive/negative typed consumers and
|
||||||
executes both specializations in Node, Chromium Window, and Worker hosts.
|
executes both specializations in Node, Chromium Window, and Worker hosts.
|
||||||
|
|
||||||
|
Use `selectArtifactImplementation(checkedManifest, selection)` to choose an
|
||||||
|
implementation by target, ABI, required export IDs, and optionally its exact ID.
|
||||||
|
Without an ID, exactly one candidate must match. Missing exports, wrong targets,
|
||||||
|
and ambiguous choices fail; manifest order never determines execution. This
|
||||||
|
selects already checked bytes and does not grant permission to run untrusted
|
||||||
|
package code in process. Multiple selected implementations remain part of the
|
||||||
|
same checked world's complete artifact inventory.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const implementation = selectArtifactImplementation(manifest, {
|
||||||
|
target: "server",
|
||||||
|
compatibility: "quixos-service-v1",
|
||||||
|
id: "isolated-service",
|
||||||
|
exports: requiredExports,
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
Consumers use the selected entrypoint, registry export and export coverage from
|
||||||
|
that manifest. The reader's Nix builder accepts per-package
|
||||||
|
`implementationSelection = { "package:reader-runtime@1" = {
|
||||||
|
browser = "browser-module"; server = "server-module"; service = "service";
|
||||||
|
}; };` overrides. Its fixture requires one implementation per lane covering that
|
||||||
|
lane's needed exports; the selector itself permits a smaller requested subset.
|
||||||
|
The installation records the chosen service and module entries. Process lifecycle
|
||||||
|
and trusted-module placement still belong to the existing runner.
|
||||||
|
|||||||
@@ -28,6 +28,35 @@ export interface PackageArtifacts {
|
|||||||
versions: ExecutionPlan["definition"]["versions"];
|
versions: ExecutionPlan["definition"]["versions"];
|
||||||
implementations: ArtifactImplementation[];
|
implementations: ArtifactImplementation[];
|
||||||
}
|
}
|
||||||
|
export interface ImplementationSelection {
|
||||||
|
target: string;
|
||||||
|
compatibility: ArtifactImplementation["compatibility"];
|
||||||
|
/** Optional only when exactly one compatible implementation covers these exports. */
|
||||||
|
id?: string;
|
||||||
|
exports: readonly string[];
|
||||||
|
}
|
||||||
|
/** Select from a checked manifest; selection does not establish package trust or isolation.
|
||||||
|
* Never resolve ambiguity by manifest order or silently substitute a requested implementation.
|
||||||
|
*/
|
||||||
|
export function selectArtifactImplementation(
|
||||||
|
manifest: PackageArtifacts,
|
||||||
|
selection: ImplementationSelection,
|
||||||
|
): ArtifactImplementation {
|
||||||
|
const candidates = manifest.implementations.filter(
|
||||||
|
(entry) =>
|
||||||
|
(selection.id === undefined || entry.id === selection.id) &&
|
||||||
|
entry.target === selection.target &&
|
||||||
|
entry.compatibility === selection.compatibility &&
|
||||||
|
selection.exports.every((id) => entry.exports.includes(id)),
|
||||||
|
);
|
||||||
|
if (candidates.length !== 1)
|
||||||
|
throw new ExecutionPlanError(
|
||||||
|
candidates.length ? "AMBIGUOUS_IMPLEMENTATION" : "IMPLEMENTATION_UNAVAILABLE",
|
||||||
|
manifest.packageRevisionId,
|
||||||
|
`${selection.id ?? "Select an explicit implementation ID"}: expected one ${selection.target}/${selection.compatibility} implementation covering the requested exports; found ${candidates.length}`,
|
||||||
|
);
|
||||||
|
return candidates[0]!;
|
||||||
|
}
|
||||||
export interface CheckedWorld {
|
export interface CheckedWorld {
|
||||||
codec: "camino-world-v1";
|
codec: "camino-world-v1";
|
||||||
plan: string;
|
plan: string;
|
||||||
|
|||||||
@@ -252,3 +252,35 @@ test("query dependencies propagate target requirements through selected getters"
|
|||||||
field.operations.find((o) => o.displayName === "get")!.execution = { kind: "snapshot", targets: ["browser"] };
|
field.operations.find((o) => o.displayName === "get")!.execution = { kind: "snapshot", targets: ["browser"] };
|
||||||
assert.throws(() => compileExecutionPlan(workspace), /MISSING_EXECUTION_TARGET.*test:selector-query.*server/);
|
assert.throws(() => compileExecutionPlan(workspace), /MISSING_EXECUTION_TARGET.*test:selector-query.*server/);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("implementation selection is explicit, target checked and independent of manifest order", async () => {
|
||||||
|
const { selectArtifactImplementation } = await import("../src/execution-world/index.js");
|
||||||
|
const plan = compileExecutionPlan(await loadReaderWorkspace());
|
||||||
|
const { manifest, read } = buildFixture(plan);
|
||||||
|
const selection = {
|
||||||
|
target: "browser",
|
||||||
|
compatibility: "quixos-js-module-v1" as const,
|
||||||
|
exports: [manifest.implementations[0]!.exports[0]!],
|
||||||
|
};
|
||||||
|
assert.equal(selectArtifactImplementation(manifest, selection).id, "browser");
|
||||||
|
const alternative = structuredClone(manifest.implementations.find((i) => i.id === "browser")!);
|
||||||
|
alternative.id = "browser-alternative";
|
||||||
|
resign(alternative);
|
||||||
|
manifest.implementations.unshift(alternative);
|
||||||
|
await checkExecutionWorld(plan, [manifest], read);
|
||||||
|
assert.throws(() => selectArtifactImplementation(manifest, selection), /AMBIGUOUS_IMPLEMENTATION/);
|
||||||
|
assert.equal(selectArtifactImplementation(manifest, { ...selection, id: alternative.id }).id, alternative.id);
|
||||||
|
manifest.implementations.reverse();
|
||||||
|
assert.equal(selectArtifactImplementation(manifest, { ...selection, id: alternative.id }).id, alternative.id);
|
||||||
|
for (const invalid of [
|
||||||
|
{ ...selection, id: "missing" },
|
||||||
|
{ ...selection, id: "service" },
|
||||||
|
{ ...selection, id: alternative.id, target: "arduino" },
|
||||||
|
{ ...selection, id: alternative.id, exports: ["not-exported"] },
|
||||||
|
])
|
||||||
|
assert.throws(() => selectArtifactImplementation(manifest, invalid), /IMPLEMENTATION_UNAVAILABLE/);
|
||||||
|
assert.equal(
|
||||||
|
selectArtifactImplementation(manifest, { ...selection, target: "server", compatibility: "quixos-service-v1" }).id,
|
||||||
|
"service",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user