From 80b65b6f0cd724eacadc7f853fa6941e7364923c Mon Sep 17 00:00:00 2001 From: "Timothy J. Aveni" Date: Sun, 13 Sep 2026 19:29:33 -0700 Subject: [PATCH] Migrate TODO implementations to generated candidate bindings --- checked-package.nix | 13 +++++++++++++ quixos-package-helpers.nix | 21 ++++++++++++++++----- 2 files changed, 29 insertions(+), 5 deletions(-) create mode 100644 checked-package.nix diff --git a/checked-package.nix b/checked-package.nix new file mode 100644 index 0000000..8e82ae6 --- /dev/null +++ b/checked-package.nix @@ -0,0 +1,13 @@ +# The caller has compiled this package and its exact recursive candidate graph. +# No credentials, mutable references, or workspace-wide unrelated schema enter +# the package derivation. Ordinary #server builds are not promotion evidence. +{ source, schema, generator, packageRevisionId, system ? builtins.currentSystem }: +let + package = builtins.getFlake ("path:" + source); + checked = package.quixosPackages.${system}.checkedServer or + (throw "Package ${packageRevisionId} lacks checkedServer. Upgrade its Nix helper and adopt generated implementation bindings before cutover."); +in checked { + inherit packageRevisionId; + schema = builtins.path { path = /. + schema; name = "candidate-package-bindings.json"; }; + generator = builtins.storePath generator; +} diff --git a/quixos-package-helpers.nix b/quixos-package-helpers.nix index bd4ac77..23c9162 100644 --- a/quixos-package-helpers.nix +++ b/quixos-package-helpers.nix @@ -539,6 +539,7 @@ EOF # An exact, compiler-produced BindingSchema JSON artifact and a backend. # Other language helpers can consume the same schema with their own generator/runtime. bindings ? null, + bindingOptions ? { }, # A dedicated entrypoint calling SDK serveMigration; never start the # normal package server in the isolated migration execution boundary. migrationEntrypoint ? null, @@ -551,6 +552,8 @@ EOF flake-utils.lib.eachDefaultSystem ( system: let + outputsFor = candidateBindings: + let pkgs = import nixpkgs { inherit system; }; lib = pkgs.lib; nodejs = pkgs.${nodejsAttr}; @@ -580,7 +583,8 @@ EOF attrs ); - bindingConfig = if bindings == null then null else callOption bindings; + bindingConfig = if candidateBindings != null then candidateBindings + else if bindings == null then null else callOption bindings; bindingSchema = if bindingConfig == null then null else bindingConfig.schema or (mkQxBindingSchema { inherit pkgs; protocol = bindingConfig.generator; @@ -589,14 +593,14 @@ EOF resources = bindingConfig.resources or [ ]; }); bindingOutput = if bindingConfig == null then "src/gen/qx.ts" else bindingConfig.output or "src/gen/qx.ts"; - bindingOptions = if bindingConfig == null then null else - pkgs.writeText "qx-typescript-options.json" (builtins.toJSON (bindingConfig.options or { })); + bindingOptionsFile = if bindingConfig == null then null else + pkgs.writeText "qx-typescript-options.json" (builtins.toJSON (bindingConfig.options or bindingOptions)); bindingCommand = if bindingConfig == null then "" else '' mkdir -p ${lib.escapeShellArg (dirOf bindingOutput)} ${bindingConfig.generator}/bin/quixos-codegen-ts \ ${lib.escapeShellArg (toString bindingSchema)} \ ${lib.escapeShellArg bindingConfig.packageRevisionId} \ - ${lib.escapeShellArg bindingOutput} ${bindingOptions} + ${lib.escapeShellArg bindingOutput} ${bindingOptionsFile} ''; generateBindings = pkgs.writeShellApplication { name = "qx-generate-bindings"; @@ -742,7 +746,14 @@ EOF # Explicit command keeps shell entry free of source mutations. shellHook = devShellHookBase + callOption devShellHook; }; - } // maybeServerOutputs + } // maybeServerOutputs; + in (outputsFor null) // { + # The workspace supplies a compiler-produced schema for the exact + # candidate graph. Standalone builds may use checked-in authoring types, + # but only this build path regenerates and witnesses candidate contracts. + quixosPackages.checkedServer = { schema, generator, packageRevisionId }: + (outputsFor { inherit schema generator packageRevisionId; }).packages.server; + } ); in {