From 03ecd24d94e77991cf1c0613812e7bd08168aedb Mon Sep 17 00:00:00 2001 From: EHotwagner Date: Thu, 15 Oct 2026 10:54:40 +0200 Subject: [PATCH 1/6] feat(verify): prepare package-backed provider declaration loader --- Directory.Packages.local.props | 3 + ...ernance-423-neutral-capability-bindings.md | 26 ++ .../FS.GG.Governance.VerifyCommand.fsproj | 4 + .../Interpreter.fs | 6 + .../Interpreter.fsi | 4 + src/FS.GG.Governance.VerifyCommand/Loop.fsi | 2 +- src/FS.GG.Governance.VerifyCommand/Program.fs | 70 ++++- .../ProviderContextLoader.fs | 87 ++++++ .../ProviderContextLoader.fsi | 14 + ...FS.GG.Governance.VerifyCommand.surface.txt | 1 + ...S.GG.Governance.VerifyCommand.Tests.fsproj | 2 + .../ProviderContextLoaderTests.fs | 127 +++++++++ .../ProviderLoaderFixture.fs | 251 ++++++++++++++++++ 13 files changed, 584 insertions(+), 13 deletions(-) create mode 100644 src/FS.GG.Governance.VerifyCommand/ProviderContextLoader.fs create mode 100644 src/FS.GG.Governance.VerifyCommand/ProviderContextLoader.fsi create mode 100644 tests/FS.GG.Governance.VerifyCommand.Tests/ProviderContextLoaderTests.fs create mode 100644 tests/FS.GG.Governance.VerifyCommand.Tests/ProviderLoaderFixture.fs diff --git a/Directory.Packages.local.props b/Directory.Packages.local.props index ec27ded9..c237bbf4 100644 --- a/Directory.Packages.local.props +++ b/Directory.Packages.local.props @@ -36,6 +36,9 @@ (see nuget.config). Contract id: fsgg-contracts (registry/dependencies.yml). --> + + + - + diff --git a/docs/roadmaps/governance-423-neutral-capability-bindings.md b/docs/roadmaps/governance-423-neutral-capability-bindings.md index cc0e561f..e6de1d97 100644 --- a/docs/roadmaps/governance-423-neutral-capability-bindings.md +++ b/docs/roadmaps/governance-423-neutral-capability-bindings.md @@ -365,8 +365,9 @@ with the Atlas helper and verify its immutable source citations before reuse. Source preparation targets the retained SDD Commands/Artifacts 2.3.0 candidate from run `37951954780`, artifact `11626413573`, source -`c8aea9289a6cc410f076823bf1219a02314f00a7`. Selection is not package qualification -or public availability. The package-backed adapter decodes immutable observations from the +`c8aea9289a6cc410f076823bf1219a02314f00a7`. As of 2026-10-22 SDD 2.3.0 is published from that +exact candidate (FS-GG/FS.GG.SDD#1113) and a cold locked restore of the org feed matches the +committed lock hashes and the retained archive digests for Commands, Artifacts and Knowledge. The package-backed adapter decodes immutable observations from the original Ready capture session, strictly parses schema-2 provenance and independently selected policy, binds policy/platform/admission correspondence, and recomputes the whole Config request before catalog selection, cache or execution. Literal argv stays typed throughout. @@ -381,7 +382,10 @@ availability. Legacy invocations retain the existing interpreter path. Focused source controls cover actual package codecs, raw digests, strict UTF-8/schema refusal, independent policy/platform correspondence and the Program-to-planning join. Fixtures are synthetic declarations and observations, not execution evidence. Local CLR, restore/lock -regeneration, compilation and test execution were held under the programme resource limit; -these controls remain unverified. Package-only qualification, exact-head hosted validation, -physical capture acceptance, production owner integration, source/evidence revalidation and +regeneration, compilation and test execution were held under the programme resource limit when +this section was first written; they have since run (2026-10-22: locked restore, build, and the +Verify suite in Debug and Release, with the hosted gate set on the reviewed head). The +`ProviderContextLoader.load` capture-readiness selection and the `CapabilityBindings.Rejected` +branch of `decode` remain without direct tests until a caller-owned ready capture fixture exists. +Package-only qualification, physical capture acceptance, production owner integration, source/evidence revalidation and the real SDD-to-Verify/GateExecution journey remain open. C2 remains unchecked. diff --git a/src/FS.GG.Governance.VerifyCommand/FS.GG.Governance.VerifyCommand.fsproj b/src/FS.GG.Governance.VerifyCommand/FS.GG.Governance.VerifyCommand.fsproj index f46c2d64..c72a780b 100644 --- a/src/FS.GG.Governance.VerifyCommand/FS.GG.Governance.VerifyCommand.fsproj +++ b/src/FS.GG.Governance.VerifyCommand/FS.GG.Governance.VerifyCommand.fsproj @@ -12,7 +12,8 @@ F052 freshness/reuse/execution cores — PLUS the new VerifyJson (NOT AuditJson; verify projects its own document). There is NO `Declaration` adapter and NO new sensing (the F055 release declaration surface was release-specific); "validate generated views/evidence currency" IS the existing F043/F041 - evaluation surfaced and acted on. It adds NO new third-party dependency: git sensing is delegated to + evaluation surfaced and acted on. Its only package references are the first-party FS.GG.SDD Commands/Artifacts 2.3.0 pair used by the explicit + provider loader (ProviderContextLoader); it adds NO new third-party dependency: git sensing is delegated to Snapshot, catalog reads to Config, enforcement/rollup to Enforcement/Ship, serialization to VerifyJson; the only new impure primitives are a `System.IO` write (the ArtifactWriter port) and `Environment.Exit` at the Program edge — both BCL. No YamlDotNet. diff --git a/tests/FS.GG.Governance.VerifyCommand.Tests/ProviderContextLoaderTests.fs b/tests/FS.GG.Governance.VerifyCommand.Tests/ProviderContextLoaderTests.fs index 78ee0d80..8ffe7547 100644 --- a/tests/FS.GG.Governance.VerifyCommand.Tests/ProviderContextLoaderTests.fs +++ b/tests/FS.GG.Governance.VerifyCommand.Tests/ProviderContextLoaderTests.fs @@ -86,6 +86,33 @@ let tests = testList "ProviderContextLoader" [ match ProviderContextLoader.decode (selection provenance policyBytes) provenance policyBytes with | Error errors -> Expect.isNonEmpty errors "actual package refusal" | Ok _ -> failtest "Unsupported schema accepted") + testCase "legacy schema-1 provenance is refused and never becomes legacy mode" (fun _ -> + let provenance = bytes (FS.GG.SDD.Artifacts.ScaffoldProvenance.serialize (coherentRecord ()).Ownership) + let selected = { selection provenance coherentPolicyBytes with Platform = "fixture-platform" } + ProviderContextLoader.decode selected provenance coherentPolicyBytes |> refusedAt "$.provenance.schemaVersion") + testCase "recorded admission budgets above the independent policy ceilings are refused" (fun _ -> + let record = coherentRecord () + let budgets = { record.Declaration.Budgets with AdmittedPreflightSeconds = 31 } + let provenance = provenanceBytes { record with Declaration = { record.Declaration with Budgets = budgets } } + let selected = { selection provenance coherentPolicyBytes with Platform = "fixture-platform" } + ProviderContextLoader.decode selected provenance coherentPolicyBytes |> refusedAt "$.policy.budgets") + testCase "binding to an environment the independent policy does not map is refused at request admission" (fun _ -> + let record = coherentRecord () + let declared = record.Declaration.Descriptor.Capabilities.Head + let binding = + match declared.Binding with + | Fsgg.ProviderCatalog.Command(command, settings) -> + Fsgg.ProviderCatalog.Command(command, { settings with EnvironmentIds = [ "unselected-environment" ] }) + | other -> other + let changed = { record.Declaration.Descriptor with Capabilities = [ { declared with Binding = binding } ] } + let descriptor = ProviderLoaderFixture.reseal changed + let provenance = provenanceBytes { record with Declaration = { record.Declaration with Descriptor = descriptor; Admission = { record.Declaration.Admission with Descriptor = descriptor } } } + let selected = { selection provenance coherentPolicyBytes with Platform = "fixture-platform" } + match ProviderContextLoader.decode selected provenance coherentPolicyBytes with + | Ok _ -> failtest "An unmapped environment must not produce a request" + | Error errors -> + Expect.isNonEmpty errors "rejected" + Expect.isTrue (errors |> List.exists (fun d -> d.Path = "$.descriptor.capabilities.build:build.environments")) (sprintf "located admission diagnostic: %A" errors)) testCase "Program provider path decodes actual bytes and drives nonpassing planning without legacy execution" (fun _ -> let provenance = provenanceBytes (coherentRecord ()) let selected = { selection provenance coherentPolicyBytes with Platform = "fixture-platform" } @@ -109,7 +136,8 @@ let tests = testList "ProviderContextLoader" [ "--provider-platform"; selected.Platform; "--paths"; "src/a.fs" |] let code = Program.runWithProviderLoader load (fun _ -> ports) ignore actualArgv Expect.equal loads 1 "single package-backed admission" - Expect.isTrue (code = 1 || code = 3) "planning refuses or remains blocked, never passes" + Expect.notEqual code 0 "planning never passes" + Expect.isTrue (code = 1 || code = 3) "planning refuses or remains blocked" Expect.isFalse execution "no execution" Expect.isFalse cache "no legacy reuse" Expect.isEmpty cap.Writes "no passing artifact") diff --git a/tests/FS.GG.Governance.VerifyCommand.Tests/ProviderLoaderFixture.fs b/tests/FS.GG.Governance.VerifyCommand.Tests/ProviderLoaderFixture.fs index c99bba91..ded9f96f 100644 --- a/tests/FS.GG.Governance.VerifyCommand.Tests/ProviderLoaderFixture.fs +++ b/tests/FS.GG.Governance.VerifyCommand.Tests/ProviderLoaderFixture.fs @@ -100,6 +100,8 @@ module ProviderLoaderFixture = Skills = [] } + let reseal (d: ProviderCatalog.Descriptor) = { d with DescriptorDigest = digest (ProviderCatalogIntegrity.descriptorBytes d) } + let sealedCatalog () : ProviderCatalog.Catalog = let d = { descriptor with DescriptorDigest = digest (ProviderCatalogIntegrity.descriptorBytes descriptor) } let c = { SchemaVersion = 2; Id = "synthetic-catalog"; Revision = "qualification"; Digest = digest [||]; Providers = [d] }