Files
quixos-protocol/nix/checked-candidate.nix
T

276 lines
10 KiB
Nix

# All source trees and recursive locks are fetched by Nix at exact retained
# revisions. No authoring-directory overlay or externally assembled schema.
{
repository,
commit,
kind,
generator,
contractOnly ? false,
system ? builtins.currentSystem,
}:
let
pkgs = import (/. + "@nixpkgs@") { inherit system; };
protocol = builtins.storePath generator;
sourceKey = source: "${source.kind}:${source.repository}@${source.commit}";
fetch =
source:
builtins.fetchGit {
url = source.repository;
rev = source.commit;
ref = "refs/tags/quixos-reachability/${source.commit}";
shallow = true;
};
load =
ancestors: source:
if builtins.elem (sourceKey source) ancestors then
throw "Source dependency cycle at ${sourceKey source}"
else if builtins.length ancestors >= 100 then
throw "Source dependency depth exceeds 100"
else
let
directory = fetch source;
lockFile = pkgs.runCommand "qx-source-lock.json" { } ''
${protocol}/bin/quixos-lock-check ${directory}/quixos.lock > "$out"
'';
lock = builtins.fromJSON (builtins.readFile lockFile);
children = map (
entry:
load (ancestors ++ [ (sourceKey source) ]) (entry.source // { inherit (entry) kind binding; })
) lock.resources;
in
source // { inherit directory children lock; };
root = load [ ] { inherit kind repository commit; };
configuration =
if builtins.pathExists (root.directory + "/quixos.check.json") then
builtins.fromJSON (builtins.readFile (root.directory + "/quixos.check.json"))
else
{ };
execution = (configuration.backend or "typescript") == "execution";
runtime = builtins.getFlake (
"git+${root.lock.quixos.repository}?rev=${root.lock.quixos.commit}&ref=refs/tags/quixos-reachability/${root.lock.quixos.commit}"
);
runtimePackages = runtime.packages.${system};
flatten = node: [ node ] ++ pkgs.lib.concatMap flatten node.children;
capabilityFlatten =
node:
if node.kind == "build" then
[ ]
else
[ node ] ++ pkgs.lib.concatMap capabilityFlatten node.children;
nodes = builtins.attrValues (
builtins.listToAttrs (
map (node: {
name = sourceKey node;
value = node;
}) (flatten root)
)
);
snapshots = pkgs.writeText "qx-nix-source-graph.json" (
builtins.toJSON {
resources = map (node: {
inherit (node)
kind
repository
commit
directory
;
}) (builtins.filter (node: node.kind != "workspace") nodes);
}
);
compile =
node:
pkgs.runCommand "qx-${node.kind}-contract" { } ''
mkdir -p "$out"
${
if node.kind == "workspace" then
''
${protocol}/bin/quixos-workspace-compile --root ${node.directory} \
--source-root-commit ${pkgs.lib.escapeShellArg node.commit} \
--checkout-root "$TMPDIR/checkouts" --snapshot-map ${snapshots} \
--graph-out "$out/graph.json" --schemas-out "$out/package-schemas.json" \
${pkgs.lib.optionalString execution ''--execution-plan-out "$out/execution-plan.json"''} > "$out/candidate.json"
''
else
''
${protocol}/bin/quixos-resource-compile --root ${node.directory} \
--kind ${node.kind} --repository ${pkgs.lib.escapeShellArg node.repository} \
--commit ${pkgs.lib.escapeShellArg node.commit} \
--checkout-root "$TMPDIR/checkouts" --snapshot-map ${snapshots} --snapshot-only true \
--graph-out "$out/graph.json" --schema-out "$out/bindings.json" > "$out/candidate.json"
''
}
'';
contract = compile root;
buildDependencies =
node:
builtins.listToAttrs (
map (dependency: {
name = dependency.binding;
value = {
src = dependency.directory;
source = { inherit (dependency) repository commit; };
flake = builtins.getFlake "git+${dependency.repository}?rev=${dependency.commit}&ref=refs/tags/quixos-reachability/${dependency.commit}";
};
}) (builtins.filter (dependency: dependency.kind == "build") node.children)
);
reactContracts =
node:
let
interfaces = builtins.attrValues (
builtins.listToAttrs (
map (dependency: {
name = sourceKey dependency;
value = dependency;
}) (builtins.filter (dependency: dependency.kind == "interface") (capabilityFlatten node))
)
);
in
pkgs.lib.concatMap (
dependency:
if !builtins.pathExists (dependency.directory + "/flake.nix") then
[ ]
else
let
source = builtins.getFlake "git+${dependency.repository}?rev=${dependency.commit}&ref=refs/tags/quixos-reachability/${dependency.commit}";
build = source.quixosInterfaces.${system}.reactTypes or null;
in
if build == null then
[ ]
else
[
(build {
interface = "${compile dependency}/candidate.json";
generator = protocol;
typescript = runtimePackages.camino-replica-core.dependencies;
dependencies = buildDependencies dependency;
})
]
) interfaces;
checkPackage =
node:
let
compiled = compile node;
candidate = builtins.fromJSON (builtins.readFile "${compiled}/candidate.json");
componentEntries =
if execution then
(pkgs.lib.findFirst (
entry: entry.revision == candidate.revision.revisionId
) { } (builtins.fromJSON (builtins.readFile "${contract}/execution-plan.json")).definition.packages)
.components or [ ]
else
[ ];
package = builtins.getFlake (
"git+${node.repository}?rev=${node.commit}&ref=refs/tags/quixos-reachability/${node.commit}"
);
checked =
if execution then
package.quixosPackages.${system}.checkedArtifacts
or (throw "Package ${node.repository} lacks checkedArtifacts; execution workspaces cannot import legacy servers.")
else
package.quixosPackages.${system}.checkedServer
or (throw "Package ${node.repository} lacks checkedServer; use the supported package scaffold.");
artifact = checked (
if execution then
{
plan = "${contract}/execution-plan.json";
generator = protocol;
core = runtimePackages.camino-replica-core;
sharedRuntime = runtimePackages.camino-shared-runtime;
typescript = runtimePackages.camino-replica-core.dependencies;
packageRevisionId = candidate.revision.revisionId;
dependencies = buildDependencies node;
}
// pkgs.lib.optionalAttrs (componentEntries != [ ]) {
react = {
sdk = runtimePackages.camino-react;
runtime = runtimePackages.camino-react-runtime;
contracts = reactContracts node;
};
}
else
{
schema =
if kind == "workspace" then
pkgs.writeText "package-specialization-schema.json" (
builtins.toJSON
(builtins.fromJSON (builtins.readFile "${contract}/package-schemas.json"))
.${candidate.revision.revisionId}
)
else
"${compiled}/bindings.json";
generator = protocol;
packageRevisionId = candidate.revision.revisionId;
}
);
in
{
packageRevisionId = candidate.revision.revisionId;
artifactPath = artifact;
};
checks =
if contractOnly then
[ ]
else
map checkPackage (
builtins.filter (node: node.kind == "package") (
builtins.attrValues (
builtins.listToAttrs (
map (node: {
name = sourceKey node;
value = node;
}) (capabilityFlatten root)
)
)
)
);
manifest = pkgs.writeText "qx-candidate-checks.json" (builtins.toJSON checks);
bindingOptions = pkgs.writeText "qx-typescript-options.json" (
builtins.toJSON (
(builtins.fromJSON (builtins.readFile "${root.directory}/quixos.check.json")).options or { }
)
);
in
assert pkgs.lib.assertMsg (!execution || kind == "workspace")
"Execution packages must be checked in their complete workspace; run qx-workspace check from the workspace root.";
pkgs.runCommand (if contractOnly then "qx-contract" else "qx-checked-candidate") { } ''
mkdir -p "$out"
cp ${
pkgs.writeText "qx-candidate-source.json" (builtins.toJSON { inherit repository commit kind; })
} "$out/source.json"
cp ${contract}/candidate.json "$out/candidate.json"
cp ${contract}/graph.json "$out/graph.json"
cp ${manifest} "$out/checks.json"
${pkgs.lib.optionalString execution ''
${
if builtins.pathExists "${root.directory}/quixos.entry.json" then
''
cp ${root.directory}/quixos.entry.json "$out/entry.json"
''
else
''
echo null > "$out/entry.json"
''
}
cp ${contract}/execution-plan.json "$out/execution-plan.json"
${pkgs.lib.optionalString (!contractOnly) ''
${pkgs.nodejs_24}/bin/node ${./check-execution.mjs} \
${protocol}/libexec/quixos-protocol/execution-world.mjs \
"$out/execution-plan.json" "$out/checks.json" "$out"
mkdir -p "$out/bin"
cat > "$out/bin/run-isolated" <<EOF
#!${pkgs.runtimeShell}
exec ${runtimePackages.camino-isolated-workspace}/bin/camino-isolated-workspace "$out" "\$@"
EOF
chmod +x "$out/bin/run-isolated"
''}
''}
${pkgs.lib.optionalString (
kind != "workspace"
) ''cp ${contract}/bindings.json "$out/bindings.json"''}
${pkgs.lib.optionalString (kind == "package") ''
${protocol}/bin/quixos-codegen-ts ${contract}/bindings.json \
${pkgs.lib.escapeShellArg (builtins.fromJSON (builtins.readFile "${contract}/candidate.json")).revision.revisionId} \
"$out/bindings.ts" ${bindingOptions}
''}
''