From 4a0416c569ea6098264b0f53be95a914520bee5b Mon Sep 17 00:00:00 2001 From: bordumb Date: Mon, 5 Oct 2026 21:05:52 +0100 Subject: [PATCH 001/108] feat(gateway): redacted support bundle auths-gateway support-bundle writes one bounded archive: versions, digests, the deployment and credential-store kinds, the qualification state and code, the connection state a serving gateway reports, and the digest and stage of each stored attempt. It is built from a struct with no member that holds text, so a proof, action, body, credential, location, account, resource identifier, or header has no way in. Both attempt stores gain a bounded listing of attempt keys. A test installs a gateway whose credential and account label are the custody fixture's canaries, leaves the other nine beside the installation and in the environment, and scans the archive for all eleven; the assertion that the gateway had no support bundle is retired. Co-Authored-By: Claude Fable 5.1 --- .../auths-gateway/semantic-closure.json | 2 +- .../auths-gateway/src/bin/auths-gateway.rs | 142 ++++++++- product/runtime/auths-gateway/src/lib.rs | 5 + .../src/pending_vectors/production.rs | 17 +- .../auths-gateway/src/scenario_tests.rs | 4 + .../auths-gateway/src/semantic_closure.rs | 2 +- product/runtime/auths-gateway/src/store.rs | 77 +++++ product/runtime/auths-gateway/src/support.rs | 295 ++++++++++++++++++ .../auths-gateway/tests/support_bundle.rs | 208 ++++++++++++ .../auths-stores/src/gateway_attempt.rs | 32 ++ 10 files changed, 761 insertions(+), 23 deletions(-) create mode 100644 product/runtime/auths-gateway/src/support.rs create mode 100644 product/runtime/auths-gateway/tests/support_bundle.rs diff --git a/product/runtime/auths-gateway/semantic-closure.json b/product/runtime/auths-gateway/semantic-closure.json index d575f06ab..5e969b3fd 100644 --- a/product/runtime/auths-gateway/semantic-closure.json +++ b/product/runtime/auths-gateway/semantic-closure.json @@ -1 +1 @@ -{"files":[{"path":"Cargo.lock","sha256":"39d384c460bdf33e011e421d761de9fae7ecd141477a043d45b3c422c08798b9"},{"path":"Cargo.toml","sha256":"6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24"},{"path":"core/adapters/auths-did-keri/Cargo.toml","sha256":"86ba3e3f9a0a70d970568bfb3113b7ba7bbdd81c3eebbb52743dd574a0c0ecaa"},{"path":"core/adapters/auths-did-keri/src/lib.rs","sha256":"a75674842f8a7142004369ccd206ab43e476459293f0ff4bed4d4e659031b3e3"},{"path":"core/adapters/auths-did-key/Cargo.toml","sha256":"d5a3ae07ecde83f91eed4c3785051dd0f44eab6c891754f3309b6b40596707d7"},{"path":"core/adapters/auths-did-key/src/lib.rs","sha256":"b76a3f4528a725df53cfa9242e6e414e1d26caa48468aaed497e28b121f4497c"},{"path":"core/adapters/auths-raw-key/Cargo.toml","sha256":"f49616bc18c19e6aaa7e6a02ccebcdb9f5c1422c1278ef9869e0dbf22ceda7be"},{"path":"core/adapters/auths-raw-key/src/lib.rs","sha256":"45eec1b295dac3bed65cd79c942870b926b06b3f5d38eaebaeb6140ac69315fa"},{"path":"core/crates/auths-algebra-kernel/Cargo.toml","sha256":"0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba"},{"path":"core/crates/auths-algebra-kernel/src/generated.rs","sha256":"ae4bcbef42a408c7ffa0c6a74a42f7de177a6f14479e51d205acf830bda05960"},{"path":"core/crates/auths-algebra-kernel/src/lib.rs","sha256":"6654667eeb9b353d6648954c9fd2e8838462a82ce6b2803eb49e1366892c68c6"},{"path":"core/crates/auths-assurance/Cargo.toml","sha256":"afcb12a97ddd09d7a264b9ecd3fcaefc865ff2c9b4539ee85b00883420ba333a"},{"path":"core/crates/auths-assurance/src/lib.rs","sha256":"0fb2ec844d674b25a9e20b1601452c89c2454901fa506adfa9bb38ef9a7fa213"},{"path":"core/crates/auths-author/Cargo.toml","sha256":"1e6f0e3bc079ddb558decf0db26b291c6e72fc47327b6df1b7650d41689b215f"},{"path":"core/crates/auths-author/src/lib.rs","sha256":"e14475f2f49715a1869d5fa6b11ff1fbb72497e39097e09f833b0bae7e5b3f2b"},{"path":"core/crates/auths-author/src/observations.rs","sha256":"dda7d6bfa6f4bd7e95a480ca283c2c0e996f69c5c15cb0c7197af328131a7066"},{"path":"core/crates/auths-authority/Cargo.toml","sha256":"4f68212938029f79ebd857b4f3038494eb85d0163d49f07e51376715cf959815"},{"path":"core/crates/auths-authority/src/lib.rs","sha256":"da88d5194de4e17449e69972c0fb042afa3c39798a8f570f30771e77c384f1eb"},{"path":"core/crates/auths-codec/Cargo.toml","sha256":"e20e51826e17814effd9d8925d18d5fbdd6c0d37bf50231e743ec2611314722c"},{"path":"core/crates/auths-codec/src/approval.rs","sha256":"fbff43bf4d57f69f8b7738a8647751cde75c5a932dee65d924a1fe9c7202f91f"},{"path":"core/crates/auths-codec/src/bounded_policy.rs","sha256":"d21f6728be2d8a04b6d94921f2b683f7e61cbb42e0ac6866f1c88a49caa534c3"},{"path":"core/crates/auths-codec/src/decode.rs","sha256":"ba2999584cdf53b1b517ecb9c7ea50d39efee17c666a9a38e2ad1ac94379f778"},{"path":"core/crates/auths-codec/src/encode.rs","sha256":"8491192053e2e15d62b4d2a491de22405b7487ead69ab6f6bca40669ce7ca5f7"},{"path":"core/crates/auths-codec/src/error.rs","sha256":"fecb0737c16deb42d859f1dc7727c698438d9ac12064fd99e0024629642c390c"},{"path":"core/crates/auths-codec/src/hash.rs","sha256":"f88e111f1dbb2cef6b7b5e9c948cb45ff92e366710c8a5f5c636138aa748479e"},{"path":"core/crates/auths-codec/src/lib.rs","sha256":"3b0e5c94c6f34f750b88a9333e1d5c8145746d845d3a23e0d2f61807cf592ea7"},{"path":"core/crates/auths-codec/src/observation.rs","sha256":"38328b0c71ff97a4196eeade8b4faa889527ff1f80bb168468bcd49082a3987e"},{"path":"core/crates/auths-composition/Cargo.toml","sha256":"331e13025eb82588b5269ed3975929eb41c823d588c49e4c296273d85c6fe80e"},{"path":"core/crates/auths-composition/src/lib.rs","sha256":"e42e3b0b6a9985b73c533aeb23799c638979aa27a9ce7d0f10a8d60340570fb1"},{"path":"core/crates/auths-model/Cargo.toml","sha256":"565c15302b0cc9270db1e28efa3862804846850ba933cc17aea8abcec4a65987"},{"path":"core/crates/auths-model/src/approval.rs","sha256":"54cf44a9ef747ec21546a4086aecfb130bc7803b0d646430e6082df51e6e305f"},{"path":"core/crates/auths-model/src/bounded.rs","sha256":"f90496abc0a06c028b4d850af6ddab7d850bfafeaa3d042f1b1246a41d8bbbc9"},{"path":"core/crates/auths-model/src/bounded_policy.rs","sha256":"306a8f049cc7cfc7635fe0e4de47eb7813eed63d3c14c3be2b51586aa4eea450"},{"path":"core/crates/auths-model/src/lib.rs","sha256":"e7cfe6bb9574c6b016aa63e70658c31e0b90903ec6479a49f4a2ceb64f5bad97"},{"path":"core/crates/auths-model/src/observation.rs","sha256":"b3ed3e3cc090afca2896a7d3de7988afccc1ee1ea0ebd91b51a8bc0f20ad8dbb"},{"path":"core/crates/auths-multikey/Cargo.toml","sha256":"858756c1197befcada06134742bffe8d58cf674cadd6c046bf710570e96efaf2"},{"path":"core/crates/auths-multikey/src/lib.rs","sha256":"f5177fffb11e40eeaaa665ba886c541fc1f24d5eacdd6983fb03dc20148733f0"},{"path":"core/crates/auths-ports/Cargo.toml","sha256":"596a9b0f5af3717c16a6d13f7054d8a106bcd9f01f5f72c2235dd2afcf0ab16c"},{"path":"core/crates/auths-ports/src/binding.rs","sha256":"a16c012d40aa4249e3ec54372b9611006d0bfe8c7dc3c741911c2194ad17736d"},{"path":"core/crates/auths-ports/src/diagnostics.rs","sha256":"aa596572503b5a65a918bb2ff38281c144ff53821ee914e9325c852828d852df"},{"path":"core/crates/auths-ports/src/lib.rs","sha256":"8da1debf86f9532df0660155d04298beb1ba3a1204508f8586e2e67cd2fb3449"},{"path":"core/crates/auths-ports/src/path.rs","sha256":"b68fc547b4e4d97a60cbbc1cc1939fc6b34a8233b81f840bd396914a707e3ea1"},{"path":"core/crates/auths-raw-key-core/Cargo.toml","sha256":"98c0bc8527a537512e43a74dd6ba9658c6f0cdc16610cf938e3f9b43785d836d"},{"path":"core/crates/auths-raw-key-core/src/lib.rs","sha256":"98c0500c41697aae28708ad0bf970b9a97583d96a3d2c18d23e7fa351e0f7d12"},{"path":"core/crates/auths-registries/Cargo.toml","sha256":"590e49e58b0622d9d6274fea46796dcdb07dec9550eff295cce6a6427ffa51e2"},{"path":"core/crates/auths-registries/src/lib.rs","sha256":"450d3886d85ee333b7e046317fb5b47cde62483d5f3e41d46265e2caf4c373ec"},{"path":"core/crates/auths-registries/src/template.rs","sha256":"1224039dd2b3ce6fa8357613d8cafbae40400493da7176da202b9ade62fa05e4"},{"path":"core/crates/auths-signature-core/Cargo.toml","sha256":"6bee2230eb30af1be0bd5c2d57bd3e1903497a70028d47290d4ac6e9e0e8bca0"},{"path":"core/crates/auths-signature-core/src/lib.rs","sha256":"6e3f9311ded5e49ea50d445eb21e6d8fa12442aa4362a73e0cb6fda15b7cd865"},{"path":"core/crates/auths-signature/Cargo.toml","sha256":"7f7b5682466ba439d8c59579022cb61068cad9fb4bd2d73e1cc21327c902b450"},{"path":"core/crates/auths-signature/src/lib.rs","sha256":"b3d9ac4cc3ba0797b9e1c09f2d6ac05089b25dac4e285a5af28c0165b33d925b"},{"path":"core/crates/auths-verifier/Cargo.toml","sha256":"c43358e06a33324b41a8b93e5cc7279c55f7d21f1f6cfaa539a3fc7b4c27a38f"},{"path":"core/crates/auths-verifier/src/approval.rs","sha256":"c3cae6a49e169051eb555bb092b1069a4d422516d6a2114623a89e5f31ff923f"},{"path":"core/crates/auths-verifier/src/causal.rs","sha256":"9635230f33b13a263573d319ac8a1976addbcc07677514a43e3c7bf28dc04587"},{"path":"core/crates/auths-verifier/src/lib.rs","sha256":"f22dec38dfa47ced8da4f605390da8453273bee1da010f57fd1fdfcb10e0b389"},{"path":"core/crates/auths-verifier/src/observation.rs","sha256":"0bb07f06a0f9524c88427df1c972b1de8ba038a9eeeb15d3134c25125ae84b1e"},{"path":"core/crates/auths-verifier/src/trace.rs","sha256":"2213d72023a1d9e0413a2cf2c51c3dad9e04775d86033a0caaa9d29a8f0036f8"},{"path":"exchange/crates/auths-proof-exchange-model/Cargo.toml","sha256":"34b2db64f93a288e942b5a3918d28cdcbef906e0dc9074ce848018d3d5f7a1fa"},{"path":"exchange/crates/auths-proof-exchange-model/src/lib.rs","sha256":"49fac5aff2339d3a57c41cb8bb2a82852538e8f77ecc4b157c88e264ff31fb55"},{"path":"exchange/crates/auths-proof-exchange-port/Cargo.toml","sha256":"7ff660f1b7579dc570c791090aeb450404fbbf44c92781e289f5ccdde746d739"},{"path":"exchange/crates/auths-proof-exchange-port/src/lib.rs","sha256":"b408fb40c6432edc1facb3d8b3e9433a033f8dc73fe2e0ba5a88c972ca675021"},{"path":"product/config/auths-config/Cargo.toml","sha256":"e4b568ab9f6d84f7d7e6d66443fe825f360db9c27bc7c31d6ddc0647ba3ab304"},{"path":"product/config/auths-config/src/lib.rs","sha256":"fecf00ea65cef9018fda9af2063326d7065b869266d0d9e73a4f06816f1102cc"},{"path":"product/errors/auths-errors/Cargo.toml","sha256":"3b3a199b6460ba75bda84475bb5accd35e1485448a3981038db85bf4772dd350"},{"path":"product/errors/auths-errors/src/lib.rs","sha256":"7feeb9069fa4003f94f1f07c1c94619cf1c883e0dbaaf2187f04d0f742264bdd"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/Cargo.toml","sha256":"716f1f2a117d6d69d8effe9ee9057e24ba3502f20af6a602b06facb638cdabed"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/api.rs","sha256":"b3c4321e0737835ecc4f17235d7589b7f3d62180954ebb98ea9449252300245a"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/clock.rs","sha256":"73f0a6e0f5903883329fa6683f5888288f759512ac69e5c87efd2b6b87f7d79f"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/http.rs","sha256":"14c1fce14e24c984b2a275563a29b6326fb08367922b6e8d37ba38b9cb81aa2b"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/identity.rs","sha256":"186de11230c8b33375951c4368609f8976bf9795f171af3fd7fac26207a94361"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs","sha256":"881ad9ccca369b6eaa6bfd9ec03b1585bff07b042da38942ef57154839449d3e"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/names.rs","sha256":"41bb23572d6002e23ee103d6fe70ecd68764861c6f2e48a1c53af998270a4afa"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs","sha256":"39fed883f4802e68d3b41a68fea0aba0737810996b33d13577de70faba004c29"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/store.rs","sha256":"32bb4b7ff3e7769d0ff46d374f80e4a2c44d7f8e8e82bbea58c9676690db45bb"},{"path":"product/integrations/auths-custody/Cargo.toml","sha256":"1e14034185ad1ec24a977fd5f41d0abee219606245c046ce2a82287fadef448b"},{"path":"product/integrations/auths-custody/src/conformance.rs","sha256":"8ed1afd58f18fc6becc268908aa6419c9aa404c79da0197963eb2599df44acf6"},{"path":"product/integrations/auths-custody/src/key.rs","sha256":"70cbb0fd21b6f5652157845a22c35be2d0f6c05b3d138fc4b9bb6dbdc3d81c40"},{"path":"product/integrations/auths-custody/src/lib.rs","sha256":"8ee593c1f59b0fd2126bdda9138026f5bc531beb64d4489a99785842e7b98b43"},{"path":"product/operations/auths-operations/Cargo.toml","sha256":"73dde1e914ba5e1386f8d49c0d730423cc72ae77ec44c6554a6a75cc8e8922b1"},{"path":"product/operations/auths-operations/src/explanation.rs","sha256":"b4a39bcbd5712cb9e735ee7deeb281f3fa6af5ddca973735bf3d87dce427ef11"},{"path":"product/operations/auths-operations/src/lib.rs","sha256":"3f401a56555113b98f57bca172a2660eaecedf76247b83a3fdbb089c133a29cd"},{"path":"product/operations/auths-operations/src/render/json.rs","sha256":"2ae042639960afee123730e945d373bc5dda1d2b3af20ae16c939a7e99b9e418"},{"path":"product/operations/auths-operations/src/render/mod.rs","sha256":"b3b7f6fe473f49227ace5a68bfc3d8dc14b5db8dd9888fd9e207070337b1b8bf"},{"path":"product/operations/auths-operations/src/render/text.rs","sha256":"f216cf3bdb00e264523271b16e7059535ac6b1aabf271cebd7935af155e4bfec"},{"path":"product/policy/auths-bounded-policy/Cargo.toml","sha256":"babd5d200923137ead71d8c2528f847cea323ce98da942a1320b054436612c47"},{"path":"product/policy/auths-bounded-policy/src/arithmetic.rs","sha256":"75e43c5d4eab8d1f71c1daf53839f5f9fe45a400afc1f63a30c6f55ce3632627"},{"path":"product/policy/auths-bounded-policy/src/commitment.rs","sha256":"c5706f2d583454e1a7f570f7ada138d4d864bef0205dfae7c1296774f396bb3f"},{"path":"product/policy/auths-bounded-policy/src/eligibility.rs","sha256":"c9acdfb793074e687fc36efad506be27dbd99ffbf40387bc66c8de39ef238432"},{"path":"product/policy/auths-bounded-policy/src/identifier.rs","sha256":"0006a32bae9eb16c4178cf797df418d2b0a781f2bc6474b741dc1a908141831c"},{"path":"product/policy/auths-bounded-policy/src/kernel.rs","sha256":"99187c28b161ac70bee1afed60711f7f645adb4d1671a01863f9849b369811d5"},{"path":"product/policy/auths-bounded-policy/src/lib.rs","sha256":"76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c"},{"path":"product/policy/auths-bounded-policy/src/receipt.rs","sha256":"3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad"},{"path":"product/policy/auths-bounded-policy/src/registry.rs","sha256":"4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0"},{"path":"product/profiles/auths-profile-api/Cargo.toml","sha256":"7ae85761f58625b5d678f961fd052eebf3e000ef565c7312e3ac857763c0017f"},{"path":"product/profiles/auths-profile-api/src/lib.rs","sha256":"a194b82b20bf8aa864c2334ef6c6aec30b2154ded972862252d5dcefa488ab95"},{"path":"product/profiles/auths-profile-mcp/Cargo.toml","sha256":"db264fc25242f7b7e4133cbe5782545b3107b406c87168ae072683cfb59eac66"},{"path":"product/profiles/auths-profile-mcp/src/arguments.rs","sha256":"a5de696586d507e2aee4a49fee99ef1ef4c51a2e46603f8838f1af6d9009833f"},{"path":"product/profiles/auths-profile-mcp/src/lib.rs","sha256":"d0f8b733a09ef8408336cdebc8948d6a5861012ce6878598b11be7084dfd4280"},{"path":"product/profiles/auths-profile-mcp/src/session.rs","sha256":"166c281fa66333388e4760d6098dad02d3359e1d5de4b8f93312c014f97abb03"},{"path":"product/qualification/auths-recipe-qualification/Cargo.toml","sha256":"b7b15b30b9a3d96d4f089d514266d3a892de6608d30707aa44be31cca89ca9fe"},{"path":"product/qualification/auths-recipe-qualification/src/canonical.rs","sha256":"30a9b50777f0dcb4b606abfee2467d5a975d9f6ad941ab6c13ca3df5b359f667"},{"path":"product/qualification/auths-recipe-qualification/src/closure.rs","sha256":"0ad6aee9bd981e2863fa725f209ec84031db2ff12f4c7ac3aaf5120f0bb86039"},{"path":"product/qualification/auths-recipe-qualification/src/error.rs","sha256":"52d5cf720a1e4579008fdda90a3ac2c31f0b8db57985f121f65e54b4da2b7dd1"},{"path":"product/qualification/auths-recipe-qualification/src/evidence.rs","sha256":"1a4cb862f725b02f9efd827db99637ea8178a5236aa020ec271a363edbe7b362"},{"path":"product/qualification/auths-recipe-qualification/src/ids.rs","sha256":"e81a906d571497ab2da753e1532d4443706410e0b75fdd59a7d2d788c7aec403"},{"path":"product/qualification/auths-recipe-qualification/src/lib.rs","sha256":"195b19f46e1e94a0f3594ad5958e5715bc5e3ad415bdfe6428dfc1b6dd3f4631"},{"path":"product/qualification/auths-recipe-qualification/src/model.rs","sha256":"3484eb0ec287b23d4682ade7b1b0f8d1335985b3fb180f06fc28716076957d5f"},{"path":"product/qualification/auths-recipe-qualification/src/release.rs","sha256":"d816b53e2275e902c750ad03803061844e259e28560ab2d1c77e8a43981a4d6a"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/mod.rs","sha256":"7f15b68e05a04f202bcb1fb80de1d9a9a4fda8bfd6af2cd4e5c660fc75d96fe5"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/schemas.rs","sha256":"c59feec2805621f341a90f81fc005e2c12f7a70f9d264fdeacccb2be4fe1c046"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/verification.rs","sha256":"6a6b5834c5dae10af1ba8939b2deae43b85db71544dc8f077ff63b7fe68ac8a8"},{"path":"product/qualification/auths-recipe-qualification/src/verify.rs","sha256":"edd33589c54fb79bcfccc4cf4e6ccf95bbca088318bb7f8dfc27da684b4fa671"},{"path":"product/receipts/auths-receipts/Cargo.toml","sha256":"6001fa1375899953aafcb07c23a6da0c8f57ea7ec08bb9c950b12a60a8cc6f0f"},{"path":"product/receipts/auths-receipts/src/disclosure.rs","sha256":"ba9ed439be0a320c8a01f5b6e9b51361c1a37e076947490d8e4a484ba6bb119c"},{"path":"product/receipts/auths-receipts/src/lib.rs","sha256":"547a57c4160256719cafb7d0ab972d9fc80b0da14fbbce4148c70c414070ff36"},{"path":"product/runtime/auths-connections/Cargo.toml","sha256":"babeb6e1dda3dfb66291713ce1e43dce5c349833d0b50ea4dccbf986030026b2"},{"path":"product/runtime/auths-connections/src/credential.rs","sha256":"4d532c221d2fe7a2b47c8720be94c26d0c86a0448c3f66f479ce3b12adf44f25"},{"path":"product/runtime/auths-connections/src/kernel.rs","sha256":"a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8"},{"path":"product/runtime/auths-connections/src/lib.rs","sha256":"79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22"},{"path":"product/runtime/auths-connections/src/model.rs","sha256":"de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77"},{"path":"product/runtime/auths-connections/src/registry.rs","sha256":"e57640e003e72ad3235c567c2bb944a262bd64e673f023b62ea091094cc7e946"},{"path":"product/runtime/auths-gateway-kernel/Cargo.toml","sha256":"34f864e67656af4ac7e5c7a347a23f01fc8ab31365b8e23c0ef474483b14a183"},{"path":"product/runtime/auths-gateway-kernel/src/construct.rs","sha256":"e9d65744bae273d65face4285e5d2da75c06a92ab48f7b8333d496604e31c63c"},{"path":"product/runtime/auths-gateway-kernel/src/lib.rs","sha256":"cfda6f8453426564c085475f183b6f790b438768a19668f1b65d33ba59dc8632"},{"path":"product/runtime/auths-gateway-kernel/src/order.rs","sha256":"e0045f877c4b7fe3860c291039853885064ddcdebba7c9b345ab65e81e646dda"},{"path":"product/runtime/auths-gateway-kernel/src/outcome.rs","sha256":"e9785b1afe70788c89b51b18655bcd5acff7b0c8e3d12fb79c6f05a202e67e6b"},{"path":"product/runtime/auths-gateway-kernel/src/ratio.rs","sha256":"7ace22264812e6fc1ef3a62afee402cf43494bb71ae0d3de219ad1b39d690bcb"},{"path":"product/runtime/auths-gateway-kernel/src/recovery.rs","sha256":"9f46dcd1685ab6e4d1ba04a3fc286a9f3afee8fb47829be1fbc670a7926a2dc6"},{"path":"product/runtime/auths-gateway-kernel/src/transition.rs","sha256":"cefb8f01d915880f6921f2501ff881ad94b9de61072c34d9cd19220992f97374"},{"path":"product/runtime/auths-gateway/Cargo.toml","sha256":"e8c10026fef0daf9f862a3e693770e5a3c18aa7bae91f0c1473eeb185c6ec9f4"},{"path":"product/runtime/auths-gateway/src/admin.rs","sha256":"2d5cc67afac42fbd15f36e2d1693cd1b20cedacf775040dce6ffe04ccc94c9ea"},{"path":"product/runtime/auths-gateway/src/app.rs","sha256":"6f80f63833ea0815bb44fbf3b0cc54624a08e9fb578b035819f2980dc04e8256"},{"path":"product/runtime/auths-gateway/src/audit.rs","sha256":"0edb2037eb7b5d6f13acfce85c54f62a82bf7fdd31bc7e626c4fec183cef61dd"},{"path":"product/runtime/auths-gateway/src/audit_tests.rs","sha256":"990969384a52d75bc2489d9d412a9e7dd814bca1c8f65c701d6205fae62a15d5"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway-harness.rs","sha256":"12b0c24d36b2e6a3be392d3c081a783b355fdd67dc5b54bacc0410e803116b8c"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway.rs","sha256":"112969ee1e833d979dc44cfb2f7fc203a495ddbc93913c3d0359f76162a97740"},{"path":"product/runtime/auths-gateway/src/binding.rs","sha256":"663b0ce878319511aa7d05722ab4ab2fa9be18817884ffb2ee9f131ff1e382d1"},{"path":"product/runtime/auths-gateway/src/bounds.rs","sha256":"9cfa0eae4973e5e047a198360b22f041708fa20276b0b90c2ec440f06915d64b"},{"path":"product/runtime/auths-gateway/src/bounds_aggregate_tests.rs","sha256":"ab34f227b7c8692ba1da88ccb32bb3687a66adf8353d8282fae905d4a88eb612"},{"path":"product/runtime/auths-gateway/src/bounds_tests.rs","sha256":"74136bc570da7b9338b5a1a1ed9d3fd892c55135160964f9d3ac0e2cf5741375"},{"path":"product/runtime/auths-gateway/src/connection.rs","sha256":"1f81f5b1305188176c38090c99b6f8f96e01fef80aa4461813be1c893d9caa8e"},{"path":"product/runtime/auths-gateway/src/echo_verify.rs","sha256":"6d453051665f823abd7354d5c50031d9524cf47d6092d2f09080ae814e3b9575"},{"path":"product/runtime/auths-gateway/src/engine.rs","sha256":"3b50980f55abe6eb89fdeb67dac9df30e77fde01e384d4494a90c6c88fc193b4"},{"path":"product/runtime/auths-gateway/src/fuzzing.rs","sha256":"ed3b0028487eb546a3b0a91d115aa8f18bcea324b61620bfe8e35a9e6ab18758"},{"path":"product/runtime/auths-gateway/src/harness.rs","sha256":"c87e479f3eb281960f6c9c80d43c7560d7ccb654b0154ec823d3fcec4884ac05"},{"path":"product/runtime/auths-gateway/src/lib.rs","sha256":"25cd21174c49d811471f9b67dd2b5da0f1bed58ddf6f5799cfd9121821556875"},{"path":"product/runtime/auths-gateway/src/listener.rs","sha256":"aa08239bcbc1fcb55e8a212fbdf6a84f12985b0d436dcb51dc58b06e59e435f2"},{"path":"product/runtime/auths-gateway/src/observed_tests.rs","sha256":"a22be071695f89ca2578a4d82fd80d9cb82289213c9bdb8f0470f6b2dc3d9201"},{"path":"product/runtime/auths-gateway/src/observer.rs","sha256":"562ffcaea071c3856e0708dc2fe33516917e145d2438aabb75af0a2b6ba01046"},{"path":"product/runtime/auths-gateway/src/onboarding.rs","sha256":"0dfd7d67e7f02f18a28d1c86ca1b7751d7463f5efcdbe3825de0ad8cbccb3891"},{"path":"product/runtime/auths-gateway/src/operator.rs","sha256":"c3c36954a3e86723df035b47f43b85fc8ab3a6292983522b6258d5c6b4e6c4e4"},{"path":"product/runtime/auths-gateway/src/pending_vectors/attempts.rs","sha256":"47ef3c8cb1c5504d47ae9a0088705ce6715fe86bac1671a34a56fb38a64d0dd3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/bounds.rs","sha256":"e612217307e1da5b0eb5ee6582a7458bb064b8aa8a529fc6555b1b334127ab68"},{"path":"product/runtime/auths-gateway/src/pending_vectors/codes.rs","sha256":"e00670a5ef24eb856cc2c6dcda8e5a263842f55c76bb939c0c27bd9df37e5522"},{"path":"product/runtime/auths-gateway/src/pending_vectors/keys.rs","sha256":"f84c56f2ea9cb34b2b79c72d13fbf2c6585010ec1ed450af58a78c80c1ea1edd"},{"path":"product/runtime/auths-gateway/src/pending_vectors/mod.rs","sha256":"5de8340f0ef71a0b57a09e323fefe473d3160c6ae952b9ba46f714825fbacafc"},{"path":"product/runtime/auths-gateway/src/pending_vectors/outcomes.rs","sha256":"8ec07b9511b48913af36ac999d2aa0e82924289f6acb23ddaeb9f00f99815166"},{"path":"product/runtime/auths-gateway/src/pending_vectors/production.rs","sha256":"c42c1a893ef6e74aef074f0644a8d3e3f9394258c0f3d689abd1f19aa5ddba61"},{"path":"product/runtime/auths-gateway/src/pending_vectors/recipes.rs","sha256":"51693208270231c25c3aef2a32151d5962114c71e86b88cb9df83181c7af83d9"},{"path":"product/runtime/auths-gateway/src/pre_entry.rs","sha256":"06ea78ca140468bfaba17d9ab04912ad68673954c3203c98fed28272ff2a00c0"},{"path":"product/runtime/auths-gateway/src/property_tests.rs","sha256":"939c081e2e154aaf10186754044bdd65608932c899b970a04a71d0afaa999a93"},{"path":"product/runtime/auths-gateway/src/qualification.rs","sha256":"a4398512ccb7bb494000fe38f03e0faa7b82d1f80ef5ee2dfa75698ae4f5a9be"},{"path":"product/runtime/auths-gateway/src/qualification_tests.rs","sha256":"c024edea5e67814bf4fee1f04ab7febc760d134a0a16c26558aaaa472fb54e63"},{"path":"product/runtime/auths-gateway/src/quorum_tests.rs","sha256":"a78380b019104d688c11a4410082c7e08ded3106aab099954c4f8a1b4ae0fd89"},{"path":"product/runtime/auths-gateway/src/readiness.rs","sha256":"9e98b19d0c68e84c778bf5565bd1e37899bff95ff8d05d329cfb48f00b246dc7"},{"path":"product/runtime/auths-gateway/src/recipe.rs","sha256":"fecf9af67e7afc48d080e9f8f55f8ce28e49d0e08988717a27908bbda461d6b6"},{"path":"product/runtime/auths-gateway/src/recipe/lower.rs","sha256":"8088b8751ed831dbb48247af953c6290ac95e2a438ccd5bd65eff54be06a1fd1"},{"path":"product/runtime/auths-gateway/src/recipe/review.rs","sha256":"c3eb7d9fdd98dacf52750b14b67ad7b7faaecbbdeafff1e0b049f67d0a2d0139"},{"path":"product/runtime/auths-gateway/src/recipe/runtime.rs","sha256":"c286f0d15f974402822c0810d8e97f98411dc1c557755cc23e540d85e2bb42d9"},{"path":"product/runtime/auths-gateway/src/recipe/source.rs","sha256":"1af50298fb1461e1b24cbdf560d43124d6b1c4c529586c911b1c4797214a69ff"},{"path":"product/runtime/auths-gateway/src/recipe/tests.rs","sha256":"aac551a2481bbc60864c64079bc667dcb232e45a0f41a04073ed84ab5dbe1fce"},{"path":"product/runtime/auths-gateway/src/recipe/validate.rs","sha256":"3711b17605cb7b0d639bc1b180449231f5882a306cab20e2c7782155cc63b0d4"},{"path":"product/runtime/auths-gateway/src/scenario_tests.rs","sha256":"9cfb885c1973cce87024af199097f31c67c0d28617ed61cc2fb4fb2bdee92e63"},{"path":"product/runtime/auths-gateway/src/separation.rs","sha256":"be9306848ca5d801767cf6aa14247c8618312ef0e202f00ce0c24c4844491061"},{"path":"product/runtime/auths-gateway/src/store.rs","sha256":"786bc4b58391eb4330a3a6c4ba224f0b3c9ff3ad619cb7a27f2699c152f42b92"},{"path":"product/runtime/auths-gateway/src/store_testkit.rs","sha256":"88d82fee42f1b8ef521e8deef0216e938ebeaad822eb2f5020e70b89d145ea70"},{"path":"product/runtime/auths-gateway/src/submit.rs","sha256":"c78dbbba7c45b443febf655056c5edcd635e77be7b21c5b2c318097502415ffe"},{"path":"product/runtime/auths-gateway/src/transport.rs","sha256":"be2c6dc75b8daec110bf8749fedc3823f6067d40b999aa3eb21126896a97d3ad"},{"path":"product/runtime/auths-kernel-runtime/Cargo.toml","sha256":"926bcd0053e5edd703be8f0027ad009e2982db013c8174c1366edbf38b48087d"},{"path":"product/runtime/auths-kernel-runtime/src/lib.rs","sha256":"7108faae9ca4bc32dc093ddaf885ac8f74f3c9b8d317b7c7d0ed00d1d0ab5972"},{"path":"product/runtime/auths-lifecycle/Cargo.toml","sha256":"c5053c705f8d5554b44e432fe75287a2faf11d644e5a2552e45ad6cd94176af5"},{"path":"product/runtime/auths-lifecycle/src/codec.rs","sha256":"51c4b746749150e8bfcd8ff972b3f6c1ef40bec15583448ec1b471d9ad737dc0"},{"path":"product/runtime/auths-lifecycle/src/digest.rs","sha256":"55282cd7d8aba37713c2dcb5357c9877819edb72a30eadefb860d28d7d3a3eb7"},{"path":"product/runtime/auths-lifecycle/src/identifier.rs","sha256":"31620e8c16de68d3d2d3b84d6353c1a5b9d4151d8247f91fa389b906a8e660f1"},{"path":"product/runtime/auths-lifecycle/src/kernel.rs","sha256":"2abb8c094b36d35b364e74d78091d14c5d6f3d1eb6552cca3b5538dbd017ce23"},{"path":"product/runtime/auths-lifecycle/src/lib.rs","sha256":"afe5a345cd309b5a4f08ffba3170a6d7f16ff914892b3f2006d5208ed24ec736"},{"path":"product/runtime/auths-lifecycle/src/model.rs","sha256":"1af12bbeeeaa65ec02ddcebd7d2c8c92ec1e339fa40ae85b45ab9b01a722a4fa"},{"path":"product/runtime/auths-lifecycle/src/operation.rs","sha256":"78e6d05fcf5d7ea4f148032a3fa26fdfcab77eb346019effe927b08e0d64d732"},{"path":"product/runtime/auths-lifecycle/src/registry.rs","sha256":"53495fe6f7a77422593a41623e28716f1c140dcc1e00f87f6b0ffbfb93a5ef90"},{"path":"product/runtime/auths-lifecycle/src/sealed.rs","sha256":"2e0c03b5813c926c159598bb7890d1523825edbe57cd687d42a5dfb3374a0c19"},{"path":"product/runtime/auths-lifecycle/src/test_support.rs","sha256":"221d9a5c5ef8e1f9f8fd66927484eaf813571d0568470278ecd8fa08a5eec8cd"},{"path":"product/runtime/auths-lifecycle/src/transition.rs","sha256":"011805a28efdd541f44ccea54dd0e34a1e58f4004447ee58013703b4fb6b2822"},{"path":"product/runtime/auths-runtime/Cargo.toml","sha256":"dd29d80a8b4bb56c869f036a6c9998f6e6d1c0383ac5dc03fa42b24abe2a7ff7"},{"path":"product/runtime/auths-runtime/src/lib.rs","sha256":"132ca03d58c14905d3a822a4972f42a22a5ad33a45f2ba9ca44f3a57d810b4b0"},{"path":"product/runtime/auths-runtime/src/production.rs","sha256":"fd4eff4270c571c10fcff6cf27df28961ebf074de8a1a028f500fda1ca376820"},{"path":"product/sdk/auths-approval-quorum/Cargo.toml","sha256":"df904971fca87a24194c5816738a331588fe8f164acb5d70839a35dca5f57114"},{"path":"product/sdk/auths-approval-quorum/src/lib.rs","sha256":"72e4086088a1c0912e4e1a9e980f26a5c280bf5ab16ea39c9f0f58d5096ac2ce"},{"path":"product/sdk/auths-approval-quorum/src/remote.rs","sha256":"9fa029c7c63003adf260f8aec55160c545681c60c1bace0d934e7525862aac7b"},{"path":"product/sdk/auths-approval-quorum/src/remote_tests.rs","sha256":"8a09ce17cfee82a035a74edd535f3ebeb3db0e078784740d3997b17dbdb10197"},{"path":"product/sdk/auths-approval-quorum/src/tests.rs","sha256":"0acbf12be3e497dcc6c2d8f29c9af3b1a7ed8e11b75f6399570d4f217a785060"},{"path":"product/stores/auths-stores/Cargo.toml","sha256":"a32c4b76d17b264be5d40d24497ff237e1ed87822e8bab86229b3db93106dbe3"},{"path":"product/stores/auths-stores/src/gateway_attempt.rs","sha256":"7683966d54ceae62dcf68a6f3d4e5fc019ffd3b88216fd30cbcecf980e1944d5"},{"path":"product/stores/auths-stores/src/lib.rs","sha256":"e721262edf8a9ab5568ddc27639176312d4a366203b5f73e2d7c11fde2c554e9"},{"path":"product/stores/auths-stores/src/lifecycle.rs","sha256":"94f64d25bc178a9e60ba3c0ee6915d7fb3af7c4468792d76b4e70f43f4de1e2f"}],"schema":"auths.gateway-semantic-closure/1"} \ No newline at end of file +{"files":[{"path":"Cargo.lock","sha256":"39d384c460bdf33e011e421d761de9fae7ecd141477a043d45b3c422c08798b9"},{"path":"Cargo.toml","sha256":"6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24"},{"path":"core/adapters/auths-did-keri/Cargo.toml","sha256":"86ba3e3f9a0a70d970568bfb3113b7ba7bbdd81c3eebbb52743dd574a0c0ecaa"},{"path":"core/adapters/auths-did-keri/src/lib.rs","sha256":"a75674842f8a7142004369ccd206ab43e476459293f0ff4bed4d4e659031b3e3"},{"path":"core/adapters/auths-did-key/Cargo.toml","sha256":"d5a3ae07ecde83f91eed4c3785051dd0f44eab6c891754f3309b6b40596707d7"},{"path":"core/adapters/auths-did-key/src/lib.rs","sha256":"b76a3f4528a725df53cfa9242e6e414e1d26caa48468aaed497e28b121f4497c"},{"path":"core/adapters/auths-raw-key/Cargo.toml","sha256":"f49616bc18c19e6aaa7e6a02ccebcdb9f5c1422c1278ef9869e0dbf22ceda7be"},{"path":"core/adapters/auths-raw-key/src/lib.rs","sha256":"45eec1b295dac3bed65cd79c942870b926b06b3f5d38eaebaeb6140ac69315fa"},{"path":"core/crates/auths-algebra-kernel/Cargo.toml","sha256":"0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba"},{"path":"core/crates/auths-algebra-kernel/src/generated.rs","sha256":"ae4bcbef42a408c7ffa0c6a74a42f7de177a6f14479e51d205acf830bda05960"},{"path":"core/crates/auths-algebra-kernel/src/lib.rs","sha256":"6654667eeb9b353d6648954c9fd2e8838462a82ce6b2803eb49e1366892c68c6"},{"path":"core/crates/auths-assurance/Cargo.toml","sha256":"afcb12a97ddd09d7a264b9ecd3fcaefc865ff2c9b4539ee85b00883420ba333a"},{"path":"core/crates/auths-assurance/src/lib.rs","sha256":"0fb2ec844d674b25a9e20b1601452c89c2454901fa506adfa9bb38ef9a7fa213"},{"path":"core/crates/auths-author/Cargo.toml","sha256":"1e6f0e3bc079ddb558decf0db26b291c6e72fc47327b6df1b7650d41689b215f"},{"path":"core/crates/auths-author/src/lib.rs","sha256":"e14475f2f49715a1869d5fa6b11ff1fbb72497e39097e09f833b0bae7e5b3f2b"},{"path":"core/crates/auths-author/src/observations.rs","sha256":"dda7d6bfa6f4bd7e95a480ca283c2c0e996f69c5c15cb0c7197af328131a7066"},{"path":"core/crates/auths-authority/Cargo.toml","sha256":"4f68212938029f79ebd857b4f3038494eb85d0163d49f07e51376715cf959815"},{"path":"core/crates/auths-authority/src/lib.rs","sha256":"da88d5194de4e17449e69972c0fb042afa3c39798a8f570f30771e77c384f1eb"},{"path":"core/crates/auths-codec/Cargo.toml","sha256":"e20e51826e17814effd9d8925d18d5fbdd6c0d37bf50231e743ec2611314722c"},{"path":"core/crates/auths-codec/src/approval.rs","sha256":"fbff43bf4d57f69f8b7738a8647751cde75c5a932dee65d924a1fe9c7202f91f"},{"path":"core/crates/auths-codec/src/bounded_policy.rs","sha256":"d21f6728be2d8a04b6d94921f2b683f7e61cbb42e0ac6866f1c88a49caa534c3"},{"path":"core/crates/auths-codec/src/decode.rs","sha256":"ba2999584cdf53b1b517ecb9c7ea50d39efee17c666a9a38e2ad1ac94379f778"},{"path":"core/crates/auths-codec/src/encode.rs","sha256":"8491192053e2e15d62b4d2a491de22405b7487ead69ab6f6bca40669ce7ca5f7"},{"path":"core/crates/auths-codec/src/error.rs","sha256":"fecb0737c16deb42d859f1dc7727c698438d9ac12064fd99e0024629642c390c"},{"path":"core/crates/auths-codec/src/hash.rs","sha256":"f88e111f1dbb2cef6b7b5e9c948cb45ff92e366710c8a5f5c636138aa748479e"},{"path":"core/crates/auths-codec/src/lib.rs","sha256":"3b0e5c94c6f34f750b88a9333e1d5c8145746d845d3a23e0d2f61807cf592ea7"},{"path":"core/crates/auths-codec/src/observation.rs","sha256":"38328b0c71ff97a4196eeade8b4faa889527ff1f80bb168468bcd49082a3987e"},{"path":"core/crates/auths-composition/Cargo.toml","sha256":"331e13025eb82588b5269ed3975929eb41c823d588c49e4c296273d85c6fe80e"},{"path":"core/crates/auths-composition/src/lib.rs","sha256":"e42e3b0b6a9985b73c533aeb23799c638979aa27a9ce7d0f10a8d60340570fb1"},{"path":"core/crates/auths-model/Cargo.toml","sha256":"565c15302b0cc9270db1e28efa3862804846850ba933cc17aea8abcec4a65987"},{"path":"core/crates/auths-model/src/approval.rs","sha256":"54cf44a9ef747ec21546a4086aecfb130bc7803b0d646430e6082df51e6e305f"},{"path":"core/crates/auths-model/src/bounded.rs","sha256":"f90496abc0a06c028b4d850af6ddab7d850bfafeaa3d042f1b1246a41d8bbbc9"},{"path":"core/crates/auths-model/src/bounded_policy.rs","sha256":"306a8f049cc7cfc7635fe0e4de47eb7813eed63d3c14c3be2b51586aa4eea450"},{"path":"core/crates/auths-model/src/lib.rs","sha256":"e7cfe6bb9574c6b016aa63e70658c31e0b90903ec6479a49f4a2ceb64f5bad97"},{"path":"core/crates/auths-model/src/observation.rs","sha256":"b3ed3e3cc090afca2896a7d3de7988afccc1ee1ea0ebd91b51a8bc0f20ad8dbb"},{"path":"core/crates/auths-multikey/Cargo.toml","sha256":"858756c1197befcada06134742bffe8d58cf674cadd6c046bf710570e96efaf2"},{"path":"core/crates/auths-multikey/src/lib.rs","sha256":"f5177fffb11e40eeaaa665ba886c541fc1f24d5eacdd6983fb03dc20148733f0"},{"path":"core/crates/auths-ports/Cargo.toml","sha256":"596a9b0f5af3717c16a6d13f7054d8a106bcd9f01f5f72c2235dd2afcf0ab16c"},{"path":"core/crates/auths-ports/src/binding.rs","sha256":"a16c012d40aa4249e3ec54372b9611006d0bfe8c7dc3c741911c2194ad17736d"},{"path":"core/crates/auths-ports/src/diagnostics.rs","sha256":"aa596572503b5a65a918bb2ff38281c144ff53821ee914e9325c852828d852df"},{"path":"core/crates/auths-ports/src/lib.rs","sha256":"8da1debf86f9532df0660155d04298beb1ba3a1204508f8586e2e67cd2fb3449"},{"path":"core/crates/auths-ports/src/path.rs","sha256":"b68fc547b4e4d97a60cbbc1cc1939fc6b34a8233b81f840bd396914a707e3ea1"},{"path":"core/crates/auths-raw-key-core/Cargo.toml","sha256":"98c0bc8527a537512e43a74dd6ba9658c6f0cdc16610cf938e3f9b43785d836d"},{"path":"core/crates/auths-raw-key-core/src/lib.rs","sha256":"98c0500c41697aae28708ad0bf970b9a97583d96a3d2c18d23e7fa351e0f7d12"},{"path":"core/crates/auths-registries/Cargo.toml","sha256":"590e49e58b0622d9d6274fea46796dcdb07dec9550eff295cce6a6427ffa51e2"},{"path":"core/crates/auths-registries/src/lib.rs","sha256":"450d3886d85ee333b7e046317fb5b47cde62483d5f3e41d46265e2caf4c373ec"},{"path":"core/crates/auths-registries/src/template.rs","sha256":"1224039dd2b3ce6fa8357613d8cafbae40400493da7176da202b9ade62fa05e4"},{"path":"core/crates/auths-signature-core/Cargo.toml","sha256":"6bee2230eb30af1be0bd5c2d57bd3e1903497a70028d47290d4ac6e9e0e8bca0"},{"path":"core/crates/auths-signature-core/src/lib.rs","sha256":"6e3f9311ded5e49ea50d445eb21e6d8fa12442aa4362a73e0cb6fda15b7cd865"},{"path":"core/crates/auths-signature/Cargo.toml","sha256":"7f7b5682466ba439d8c59579022cb61068cad9fb4bd2d73e1cc21327c902b450"},{"path":"core/crates/auths-signature/src/lib.rs","sha256":"b3d9ac4cc3ba0797b9e1c09f2d6ac05089b25dac4e285a5af28c0165b33d925b"},{"path":"core/crates/auths-verifier/Cargo.toml","sha256":"c43358e06a33324b41a8b93e5cc7279c55f7d21f1f6cfaa539a3fc7b4c27a38f"},{"path":"core/crates/auths-verifier/src/approval.rs","sha256":"c3cae6a49e169051eb555bb092b1069a4d422516d6a2114623a89e5f31ff923f"},{"path":"core/crates/auths-verifier/src/causal.rs","sha256":"9635230f33b13a263573d319ac8a1976addbcc07677514a43e3c7bf28dc04587"},{"path":"core/crates/auths-verifier/src/lib.rs","sha256":"f22dec38dfa47ced8da4f605390da8453273bee1da010f57fd1fdfcb10e0b389"},{"path":"core/crates/auths-verifier/src/observation.rs","sha256":"0bb07f06a0f9524c88427df1c972b1de8ba038a9eeeb15d3134c25125ae84b1e"},{"path":"core/crates/auths-verifier/src/trace.rs","sha256":"2213d72023a1d9e0413a2cf2c51c3dad9e04775d86033a0caaa9d29a8f0036f8"},{"path":"exchange/crates/auths-proof-exchange-model/Cargo.toml","sha256":"34b2db64f93a288e942b5a3918d28cdcbef906e0dc9074ce848018d3d5f7a1fa"},{"path":"exchange/crates/auths-proof-exchange-model/src/lib.rs","sha256":"49fac5aff2339d3a57c41cb8bb2a82852538e8f77ecc4b157c88e264ff31fb55"},{"path":"exchange/crates/auths-proof-exchange-port/Cargo.toml","sha256":"7ff660f1b7579dc570c791090aeb450404fbbf44c92781e289f5ccdde746d739"},{"path":"exchange/crates/auths-proof-exchange-port/src/lib.rs","sha256":"b408fb40c6432edc1facb3d8b3e9433a033f8dc73fe2e0ba5a88c972ca675021"},{"path":"product/config/auths-config/Cargo.toml","sha256":"e4b568ab9f6d84f7d7e6d66443fe825f360db9c27bc7c31d6ddc0647ba3ab304"},{"path":"product/config/auths-config/src/lib.rs","sha256":"fecf00ea65cef9018fda9af2063326d7065b869266d0d9e73a4f06816f1102cc"},{"path":"product/errors/auths-errors/Cargo.toml","sha256":"3b3a199b6460ba75bda84475bb5accd35e1485448a3981038db85bf4772dd350"},{"path":"product/errors/auths-errors/src/lib.rs","sha256":"7feeb9069fa4003f94f1f07c1c94619cf1c883e0dbaaf2187f04d0f742264bdd"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/Cargo.toml","sha256":"716f1f2a117d6d69d8effe9ee9057e24ba3502f20af6a602b06facb638cdabed"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/api.rs","sha256":"b3c4321e0737835ecc4f17235d7589b7f3d62180954ebb98ea9449252300245a"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/clock.rs","sha256":"73f0a6e0f5903883329fa6683f5888288f759512ac69e5c87efd2b6b87f7d79f"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/http.rs","sha256":"14c1fce14e24c984b2a275563a29b6326fb08367922b6e8d37ba38b9cb81aa2b"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/identity.rs","sha256":"186de11230c8b33375951c4368609f8976bf9795f171af3fd7fac26207a94361"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs","sha256":"881ad9ccca369b6eaa6bfd9ec03b1585bff07b042da38942ef57154839449d3e"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/names.rs","sha256":"41bb23572d6002e23ee103d6fe70ecd68764861c6f2e48a1c53af998270a4afa"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs","sha256":"39fed883f4802e68d3b41a68fea0aba0737810996b33d13577de70faba004c29"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/store.rs","sha256":"32bb4b7ff3e7769d0ff46d374f80e4a2c44d7f8e8e82bbea58c9676690db45bb"},{"path":"product/integrations/auths-custody/Cargo.toml","sha256":"1e14034185ad1ec24a977fd5f41d0abee219606245c046ce2a82287fadef448b"},{"path":"product/integrations/auths-custody/src/conformance.rs","sha256":"8ed1afd58f18fc6becc268908aa6419c9aa404c79da0197963eb2599df44acf6"},{"path":"product/integrations/auths-custody/src/key.rs","sha256":"70cbb0fd21b6f5652157845a22c35be2d0f6c05b3d138fc4b9bb6dbdc3d81c40"},{"path":"product/integrations/auths-custody/src/lib.rs","sha256":"8ee593c1f59b0fd2126bdda9138026f5bc531beb64d4489a99785842e7b98b43"},{"path":"product/operations/auths-operations/Cargo.toml","sha256":"73dde1e914ba5e1386f8d49c0d730423cc72ae77ec44c6554a6a75cc8e8922b1"},{"path":"product/operations/auths-operations/src/explanation.rs","sha256":"b4a39bcbd5712cb9e735ee7deeb281f3fa6af5ddca973735bf3d87dce427ef11"},{"path":"product/operations/auths-operations/src/lib.rs","sha256":"3f401a56555113b98f57bca172a2660eaecedf76247b83a3fdbb089c133a29cd"},{"path":"product/operations/auths-operations/src/render/json.rs","sha256":"2ae042639960afee123730e945d373bc5dda1d2b3af20ae16c939a7e99b9e418"},{"path":"product/operations/auths-operations/src/render/mod.rs","sha256":"b3b7f6fe473f49227ace5a68bfc3d8dc14b5db8dd9888fd9e207070337b1b8bf"},{"path":"product/operations/auths-operations/src/render/text.rs","sha256":"f216cf3bdb00e264523271b16e7059535ac6b1aabf271cebd7935af155e4bfec"},{"path":"product/policy/auths-bounded-policy/Cargo.toml","sha256":"babd5d200923137ead71d8c2528f847cea323ce98da942a1320b054436612c47"},{"path":"product/policy/auths-bounded-policy/src/arithmetic.rs","sha256":"75e43c5d4eab8d1f71c1daf53839f5f9fe45a400afc1f63a30c6f55ce3632627"},{"path":"product/policy/auths-bounded-policy/src/commitment.rs","sha256":"c5706f2d583454e1a7f570f7ada138d4d864bef0205dfae7c1296774f396bb3f"},{"path":"product/policy/auths-bounded-policy/src/eligibility.rs","sha256":"c9acdfb793074e687fc36efad506be27dbd99ffbf40387bc66c8de39ef238432"},{"path":"product/policy/auths-bounded-policy/src/identifier.rs","sha256":"0006a32bae9eb16c4178cf797df418d2b0a781f2bc6474b741dc1a908141831c"},{"path":"product/policy/auths-bounded-policy/src/kernel.rs","sha256":"99187c28b161ac70bee1afed60711f7f645adb4d1671a01863f9849b369811d5"},{"path":"product/policy/auths-bounded-policy/src/lib.rs","sha256":"76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c"},{"path":"product/policy/auths-bounded-policy/src/receipt.rs","sha256":"3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad"},{"path":"product/policy/auths-bounded-policy/src/registry.rs","sha256":"4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0"},{"path":"product/profiles/auths-profile-api/Cargo.toml","sha256":"7ae85761f58625b5d678f961fd052eebf3e000ef565c7312e3ac857763c0017f"},{"path":"product/profiles/auths-profile-api/src/lib.rs","sha256":"a194b82b20bf8aa864c2334ef6c6aec30b2154ded972862252d5dcefa488ab95"},{"path":"product/profiles/auths-profile-mcp/Cargo.toml","sha256":"db264fc25242f7b7e4133cbe5782545b3107b406c87168ae072683cfb59eac66"},{"path":"product/profiles/auths-profile-mcp/src/arguments.rs","sha256":"a5de696586d507e2aee4a49fee99ef1ef4c51a2e46603f8838f1af6d9009833f"},{"path":"product/profiles/auths-profile-mcp/src/lib.rs","sha256":"d0f8b733a09ef8408336cdebc8948d6a5861012ce6878598b11be7084dfd4280"},{"path":"product/profiles/auths-profile-mcp/src/session.rs","sha256":"166c281fa66333388e4760d6098dad02d3359e1d5de4b8f93312c014f97abb03"},{"path":"product/qualification/auths-recipe-qualification/Cargo.toml","sha256":"b7b15b30b9a3d96d4f089d514266d3a892de6608d30707aa44be31cca89ca9fe"},{"path":"product/qualification/auths-recipe-qualification/src/canonical.rs","sha256":"30a9b50777f0dcb4b606abfee2467d5a975d9f6ad941ab6c13ca3df5b359f667"},{"path":"product/qualification/auths-recipe-qualification/src/closure.rs","sha256":"0ad6aee9bd981e2863fa725f209ec84031db2ff12f4c7ac3aaf5120f0bb86039"},{"path":"product/qualification/auths-recipe-qualification/src/error.rs","sha256":"52d5cf720a1e4579008fdda90a3ac2c31f0b8db57985f121f65e54b4da2b7dd1"},{"path":"product/qualification/auths-recipe-qualification/src/evidence.rs","sha256":"1a4cb862f725b02f9efd827db99637ea8178a5236aa020ec271a363edbe7b362"},{"path":"product/qualification/auths-recipe-qualification/src/ids.rs","sha256":"e81a906d571497ab2da753e1532d4443706410e0b75fdd59a7d2d788c7aec403"},{"path":"product/qualification/auths-recipe-qualification/src/lib.rs","sha256":"195b19f46e1e94a0f3594ad5958e5715bc5e3ad415bdfe6428dfc1b6dd3f4631"},{"path":"product/qualification/auths-recipe-qualification/src/model.rs","sha256":"3484eb0ec287b23d4682ade7b1b0f8d1335985b3fb180f06fc28716076957d5f"},{"path":"product/qualification/auths-recipe-qualification/src/release.rs","sha256":"d816b53e2275e902c750ad03803061844e259e28560ab2d1c77e8a43981a4d6a"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/mod.rs","sha256":"7f15b68e05a04f202bcb1fb80de1d9a9a4fda8bfd6af2cd4e5c660fc75d96fe5"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/schemas.rs","sha256":"c59feec2805621f341a90f81fc005e2c12f7a70f9d264fdeacccb2be4fe1c046"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/verification.rs","sha256":"6a6b5834c5dae10af1ba8939b2deae43b85db71544dc8f077ff63b7fe68ac8a8"},{"path":"product/qualification/auths-recipe-qualification/src/verify.rs","sha256":"edd33589c54fb79bcfccc4cf4e6ccf95bbca088318bb7f8dfc27da684b4fa671"},{"path":"product/receipts/auths-receipts/Cargo.toml","sha256":"6001fa1375899953aafcb07c23a6da0c8f57ea7ec08bb9c950b12a60a8cc6f0f"},{"path":"product/receipts/auths-receipts/src/disclosure.rs","sha256":"ba9ed439be0a320c8a01f5b6e9b51361c1a37e076947490d8e4a484ba6bb119c"},{"path":"product/receipts/auths-receipts/src/lib.rs","sha256":"547a57c4160256719cafb7d0ab972d9fc80b0da14fbbce4148c70c414070ff36"},{"path":"product/runtime/auths-connections/Cargo.toml","sha256":"babeb6e1dda3dfb66291713ce1e43dce5c349833d0b50ea4dccbf986030026b2"},{"path":"product/runtime/auths-connections/src/credential.rs","sha256":"4d532c221d2fe7a2b47c8720be94c26d0c86a0448c3f66f479ce3b12adf44f25"},{"path":"product/runtime/auths-connections/src/kernel.rs","sha256":"a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8"},{"path":"product/runtime/auths-connections/src/lib.rs","sha256":"79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22"},{"path":"product/runtime/auths-connections/src/model.rs","sha256":"de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77"},{"path":"product/runtime/auths-connections/src/registry.rs","sha256":"e57640e003e72ad3235c567c2bb944a262bd64e673f023b62ea091094cc7e946"},{"path":"product/runtime/auths-gateway-kernel/Cargo.toml","sha256":"34f864e67656af4ac7e5c7a347a23f01fc8ab31365b8e23c0ef474483b14a183"},{"path":"product/runtime/auths-gateway-kernel/src/construct.rs","sha256":"e9d65744bae273d65face4285e5d2da75c06a92ab48f7b8333d496604e31c63c"},{"path":"product/runtime/auths-gateway-kernel/src/lib.rs","sha256":"cfda6f8453426564c085475f183b6f790b438768a19668f1b65d33ba59dc8632"},{"path":"product/runtime/auths-gateway-kernel/src/order.rs","sha256":"e0045f877c4b7fe3860c291039853885064ddcdebba7c9b345ab65e81e646dda"},{"path":"product/runtime/auths-gateway-kernel/src/outcome.rs","sha256":"e9785b1afe70788c89b51b18655bcd5acff7b0c8e3d12fb79c6f05a202e67e6b"},{"path":"product/runtime/auths-gateway-kernel/src/ratio.rs","sha256":"7ace22264812e6fc1ef3a62afee402cf43494bb71ae0d3de219ad1b39d690bcb"},{"path":"product/runtime/auths-gateway-kernel/src/recovery.rs","sha256":"9f46dcd1685ab6e4d1ba04a3fc286a9f3afee8fb47829be1fbc670a7926a2dc6"},{"path":"product/runtime/auths-gateway-kernel/src/transition.rs","sha256":"cefb8f01d915880f6921f2501ff881ad94b9de61072c34d9cd19220992f97374"},{"path":"product/runtime/auths-gateway/Cargo.toml","sha256":"e8c10026fef0daf9f862a3e693770e5a3c18aa7bae91f0c1473eeb185c6ec9f4"},{"path":"product/runtime/auths-gateway/src/admin.rs","sha256":"2d5cc67afac42fbd15f36e2d1693cd1b20cedacf775040dce6ffe04ccc94c9ea"},{"path":"product/runtime/auths-gateway/src/app.rs","sha256":"6f80f63833ea0815bb44fbf3b0cc54624a08e9fb578b035819f2980dc04e8256"},{"path":"product/runtime/auths-gateway/src/audit.rs","sha256":"0edb2037eb7b5d6f13acfce85c54f62a82bf7fdd31bc7e626c4fec183cef61dd"},{"path":"product/runtime/auths-gateway/src/audit_tests.rs","sha256":"990969384a52d75bc2489d9d412a9e7dd814bca1c8f65c701d6205fae62a15d5"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway-harness.rs","sha256":"12b0c24d36b2e6a3be392d3c081a783b355fdd67dc5b54bacc0410e803116b8c"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway.rs","sha256":"c29ccb304e80d70da5065727ad7d50ec1470a425e78b8cd5c8b9a7fec7bbf04e"},{"path":"product/runtime/auths-gateway/src/binding.rs","sha256":"663b0ce878319511aa7d05722ab4ab2fa9be18817884ffb2ee9f131ff1e382d1"},{"path":"product/runtime/auths-gateway/src/bounds.rs","sha256":"9cfa0eae4973e5e047a198360b22f041708fa20276b0b90c2ec440f06915d64b"},{"path":"product/runtime/auths-gateway/src/bounds_aggregate_tests.rs","sha256":"ab34f227b7c8692ba1da88ccb32bb3687a66adf8353d8282fae905d4a88eb612"},{"path":"product/runtime/auths-gateway/src/bounds_tests.rs","sha256":"74136bc570da7b9338b5a1a1ed9d3fd892c55135160964f9d3ac0e2cf5741375"},{"path":"product/runtime/auths-gateway/src/connection.rs","sha256":"1f81f5b1305188176c38090c99b6f8f96e01fef80aa4461813be1c893d9caa8e"},{"path":"product/runtime/auths-gateway/src/echo_verify.rs","sha256":"6d453051665f823abd7354d5c50031d9524cf47d6092d2f09080ae814e3b9575"},{"path":"product/runtime/auths-gateway/src/engine.rs","sha256":"3b50980f55abe6eb89fdeb67dac9df30e77fde01e384d4494a90c6c88fc193b4"},{"path":"product/runtime/auths-gateway/src/fuzzing.rs","sha256":"ed3b0028487eb546a3b0a91d115aa8f18bcea324b61620bfe8e35a9e6ab18758"},{"path":"product/runtime/auths-gateway/src/harness.rs","sha256":"c87e479f3eb281960f6c9c80d43c7560d7ccb654b0154ec823d3fcec4884ac05"},{"path":"product/runtime/auths-gateway/src/lib.rs","sha256":"2eb650a76bcb531339c084d77a7b57f7b6685e5e04976ca98ba108690cf38fea"},{"path":"product/runtime/auths-gateway/src/listener.rs","sha256":"aa08239bcbc1fcb55e8a212fbdf6a84f12985b0d436dcb51dc58b06e59e435f2"},{"path":"product/runtime/auths-gateway/src/observed_tests.rs","sha256":"a22be071695f89ca2578a4d82fd80d9cb82289213c9bdb8f0470f6b2dc3d9201"},{"path":"product/runtime/auths-gateway/src/observer.rs","sha256":"562ffcaea071c3856e0708dc2fe33516917e145d2438aabb75af0a2b6ba01046"},{"path":"product/runtime/auths-gateway/src/onboarding.rs","sha256":"0dfd7d67e7f02f18a28d1c86ca1b7751d7463f5efcdbe3825de0ad8cbccb3891"},{"path":"product/runtime/auths-gateway/src/operator.rs","sha256":"c3c36954a3e86723df035b47f43b85fc8ab3a6292983522b6258d5c6b4e6c4e4"},{"path":"product/runtime/auths-gateway/src/pending_vectors/attempts.rs","sha256":"47ef3c8cb1c5504d47ae9a0088705ce6715fe86bac1671a34a56fb38a64d0dd3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/bounds.rs","sha256":"e612217307e1da5b0eb5ee6582a7458bb064b8aa8a529fc6555b1b334127ab68"},{"path":"product/runtime/auths-gateway/src/pending_vectors/codes.rs","sha256":"e00670a5ef24eb856cc2c6dcda8e5a263842f55c76bb939c0c27bd9df37e5522"},{"path":"product/runtime/auths-gateway/src/pending_vectors/keys.rs","sha256":"f84c56f2ea9cb34b2b79c72d13fbf2c6585010ec1ed450af58a78c80c1ea1edd"},{"path":"product/runtime/auths-gateway/src/pending_vectors/mod.rs","sha256":"5de8340f0ef71a0b57a09e323fefe473d3160c6ae952b9ba46f714825fbacafc"},{"path":"product/runtime/auths-gateway/src/pending_vectors/outcomes.rs","sha256":"8ec07b9511b48913af36ac999d2aa0e82924289f6acb23ddaeb9f00f99815166"},{"path":"product/runtime/auths-gateway/src/pending_vectors/production.rs","sha256":"817ca8f2baca9ce7c19596d7f23c56224c2d1764f6213924779c50c44e9d6a2c"},{"path":"product/runtime/auths-gateway/src/pending_vectors/recipes.rs","sha256":"51693208270231c25c3aef2a32151d5962114c71e86b88cb9df83181c7af83d9"},{"path":"product/runtime/auths-gateway/src/pre_entry.rs","sha256":"06ea78ca140468bfaba17d9ab04912ad68673954c3203c98fed28272ff2a00c0"},{"path":"product/runtime/auths-gateway/src/property_tests.rs","sha256":"939c081e2e154aaf10186754044bdd65608932c899b970a04a71d0afaa999a93"},{"path":"product/runtime/auths-gateway/src/qualification.rs","sha256":"a4398512ccb7bb494000fe38f03e0faa7b82d1f80ef5ee2dfa75698ae4f5a9be"},{"path":"product/runtime/auths-gateway/src/qualification_tests.rs","sha256":"c024edea5e67814bf4fee1f04ab7febc760d134a0a16c26558aaaa472fb54e63"},{"path":"product/runtime/auths-gateway/src/quorum_tests.rs","sha256":"a78380b019104d688c11a4410082c7e08ded3106aab099954c4f8a1b4ae0fd89"},{"path":"product/runtime/auths-gateway/src/readiness.rs","sha256":"9e98b19d0c68e84c778bf5565bd1e37899bff95ff8d05d329cfb48f00b246dc7"},{"path":"product/runtime/auths-gateway/src/recipe.rs","sha256":"fecf9af67e7afc48d080e9f8f55f8ce28e49d0e08988717a27908bbda461d6b6"},{"path":"product/runtime/auths-gateway/src/recipe/lower.rs","sha256":"8088b8751ed831dbb48247af953c6290ac95e2a438ccd5bd65eff54be06a1fd1"},{"path":"product/runtime/auths-gateway/src/recipe/review.rs","sha256":"c3eb7d9fdd98dacf52750b14b67ad7b7faaecbbdeafff1e0b049f67d0a2d0139"},{"path":"product/runtime/auths-gateway/src/recipe/runtime.rs","sha256":"c286f0d15f974402822c0810d8e97f98411dc1c557755cc23e540d85e2bb42d9"},{"path":"product/runtime/auths-gateway/src/recipe/source.rs","sha256":"1af50298fb1461e1b24cbdf560d43124d6b1c4c529586c911b1c4797214a69ff"},{"path":"product/runtime/auths-gateway/src/recipe/tests.rs","sha256":"aac551a2481bbc60864c64079bc667dcb232e45a0f41a04073ed84ab5dbe1fce"},{"path":"product/runtime/auths-gateway/src/recipe/validate.rs","sha256":"3711b17605cb7b0d639bc1b180449231f5882a306cab20e2c7782155cc63b0d4"},{"path":"product/runtime/auths-gateway/src/scenario_tests.rs","sha256":"ec1d77412635ae407aa1c54d80034e2f1c44522c33636664e0fe92bf5cb65ae5"},{"path":"product/runtime/auths-gateway/src/separation.rs","sha256":"be9306848ca5d801767cf6aa14247c8618312ef0e202f00ce0c24c4844491061"},{"path":"product/runtime/auths-gateway/src/store.rs","sha256":"1e5288345c2cb1421aeda277b3158d07607404b0ec46943222ac107b63dcbb46"},{"path":"product/runtime/auths-gateway/src/store_testkit.rs","sha256":"88d82fee42f1b8ef521e8deef0216e938ebeaad822eb2f5020e70b89d145ea70"},{"path":"product/runtime/auths-gateway/src/submit.rs","sha256":"c78dbbba7c45b443febf655056c5edcd635e77be7b21c5b2c318097502415ffe"},{"path":"product/runtime/auths-gateway/src/support.rs","sha256":"8537d54b8071744a6a3983f48620a8abe1169c6103b281badd701dd0999ac9c7"},{"path":"product/runtime/auths-gateway/src/transport.rs","sha256":"be2c6dc75b8daec110bf8749fedc3823f6067d40b999aa3eb21126896a97d3ad"},{"path":"product/runtime/auths-kernel-runtime/Cargo.toml","sha256":"926bcd0053e5edd703be8f0027ad009e2982db013c8174c1366edbf38b48087d"},{"path":"product/runtime/auths-kernel-runtime/src/lib.rs","sha256":"7108faae9ca4bc32dc093ddaf885ac8f74f3c9b8d317b7c7d0ed00d1d0ab5972"},{"path":"product/runtime/auths-lifecycle/Cargo.toml","sha256":"c5053c705f8d5554b44e432fe75287a2faf11d644e5a2552e45ad6cd94176af5"},{"path":"product/runtime/auths-lifecycle/src/codec.rs","sha256":"51c4b746749150e8bfcd8ff972b3f6c1ef40bec15583448ec1b471d9ad737dc0"},{"path":"product/runtime/auths-lifecycle/src/digest.rs","sha256":"55282cd7d8aba37713c2dcb5357c9877819edb72a30eadefb860d28d7d3a3eb7"},{"path":"product/runtime/auths-lifecycle/src/identifier.rs","sha256":"31620e8c16de68d3d2d3b84d6353c1a5b9d4151d8247f91fa389b906a8e660f1"},{"path":"product/runtime/auths-lifecycle/src/kernel.rs","sha256":"2abb8c094b36d35b364e74d78091d14c5d6f3d1eb6552cca3b5538dbd017ce23"},{"path":"product/runtime/auths-lifecycle/src/lib.rs","sha256":"afe5a345cd309b5a4f08ffba3170a6d7f16ff914892b3f2006d5208ed24ec736"},{"path":"product/runtime/auths-lifecycle/src/model.rs","sha256":"1af12bbeeeaa65ec02ddcebd7d2c8c92ec1e339fa40ae85b45ab9b01a722a4fa"},{"path":"product/runtime/auths-lifecycle/src/operation.rs","sha256":"78e6d05fcf5d7ea4f148032a3fa26fdfcab77eb346019effe927b08e0d64d732"},{"path":"product/runtime/auths-lifecycle/src/registry.rs","sha256":"53495fe6f7a77422593a41623e28716f1c140dcc1e00f87f6b0ffbfb93a5ef90"},{"path":"product/runtime/auths-lifecycle/src/sealed.rs","sha256":"2e0c03b5813c926c159598bb7890d1523825edbe57cd687d42a5dfb3374a0c19"},{"path":"product/runtime/auths-lifecycle/src/test_support.rs","sha256":"221d9a5c5ef8e1f9f8fd66927484eaf813571d0568470278ecd8fa08a5eec8cd"},{"path":"product/runtime/auths-lifecycle/src/transition.rs","sha256":"011805a28efdd541f44ccea54dd0e34a1e58f4004447ee58013703b4fb6b2822"},{"path":"product/runtime/auths-runtime/Cargo.toml","sha256":"dd29d80a8b4bb56c869f036a6c9998f6e6d1c0383ac5dc03fa42b24abe2a7ff7"},{"path":"product/runtime/auths-runtime/src/lib.rs","sha256":"132ca03d58c14905d3a822a4972f42a22a5ad33a45f2ba9ca44f3a57d810b4b0"},{"path":"product/runtime/auths-runtime/src/production.rs","sha256":"fd4eff4270c571c10fcff6cf27df28961ebf074de8a1a028f500fda1ca376820"},{"path":"product/sdk/auths-approval-quorum/Cargo.toml","sha256":"df904971fca87a24194c5816738a331588fe8f164acb5d70839a35dca5f57114"},{"path":"product/sdk/auths-approval-quorum/src/lib.rs","sha256":"72e4086088a1c0912e4e1a9e980f26a5c280bf5ab16ea39c9f0f58d5096ac2ce"},{"path":"product/sdk/auths-approval-quorum/src/remote.rs","sha256":"9fa029c7c63003adf260f8aec55160c545681c60c1bace0d934e7525862aac7b"},{"path":"product/sdk/auths-approval-quorum/src/remote_tests.rs","sha256":"8a09ce17cfee82a035a74edd535f3ebeb3db0e078784740d3997b17dbdb10197"},{"path":"product/sdk/auths-approval-quorum/src/tests.rs","sha256":"0acbf12be3e497dcc6c2d8f29c9af3b1a7ed8e11b75f6399570d4f217a785060"},{"path":"product/stores/auths-stores/Cargo.toml","sha256":"a32c4b76d17b264be5d40d24497ff237e1ed87822e8bab86229b3db93106dbe3"},{"path":"product/stores/auths-stores/src/gateway_attempt.rs","sha256":"185da8f4a220fba836d5b78a9311f03204681c43a3c53951008084d135bf4d21"},{"path":"product/stores/auths-stores/src/lib.rs","sha256":"e721262edf8a9ab5568ddc27639176312d4a366203b5f73e2d7c11fde2c554e9"},{"path":"product/stores/auths-stores/src/lifecycle.rs","sha256":"94f64d25bc178a9e60ba3c0ee6915d7fb3af7c4468792d76b4e70f43f4de1e2f"}],"schema":"auths.gateway-semantic-closure/1"} \ No newline at end of file diff --git a/product/runtime/auths-gateway/src/bin/auths-gateway.rs b/product/runtime/auths-gateway/src/bin/auths-gateway.rs index 454904f9a..4d4d4d3af 100644 --- a/product/runtime/auths-gateway/src/bin/auths-gateway.rs +++ b/product/runtime/auths-gateway/src/bin/auths-gateway.rs @@ -356,6 +356,21 @@ mod unix { #[arg(long, default_value_t = false)] tuple: bool, }, + /// Write a redacted archive for a support request: versions, + /// digests, closed states, stable codes, and the digest and stage of + /// each stored attempt. It holds no proof, action, body, credential, + /// location, account, resource identifier, or header. + SupportBundle { + #[arg(long)] + state_dir: PathBuf, + /// The admin socket `serve` was given with `--admin-socket`; + /// defaults to `/admin.sock`. + #[arg(long)] + admin_socket: Option, + /// Where to write the archive; standard output when absent. + #[arg(long)] + out: Option, + }, /// Ask the private operator socket for the connection state. Status { #[arg(long)] @@ -2420,6 +2435,22 @@ mod unix { command: serde_json::Value, secret: Option<&[u8]>, ) -> Result<(), Failure> { + let response = admin_exchange(state_dir, admin_socket, command, secret).await?; + println!("{response}"); + if response.get("ok").and_then(serde_json::Value::as_bool) == Some(true) { + Ok(()) + } else { + Err("gateway.admin.refused".into()) + } + } + + /// Sends one admin command and returns the gateway's response. + async fn admin_exchange( + state_dir: &Path, + admin_socket: &AdminSocket, + command: serde_json::Value, + secret: Option<&[u8]>, + ) -> Result { const CODE: &str = "gateway.admin.socket-unavailable"; private_root(state_dir)?; check_admin_socket(admin_socket, &CLIENT_ADMIN_SOCKET)?; @@ -2450,14 +2481,89 @@ mod unix { write_frame(&mut stream, secret).await?; } let bytes = read_frame(&mut stream).await?; - let response: serde_json::Value = - serde_json::from_slice(&bytes).map_err(|_| "gateway.admin.invalid-response")?; - println!("{response}"); - if response.get("ok").and_then(serde_json::Value::as_bool) == Some(true) { - Ok(()) - } else { - Err("gateway.admin.refused".into()) - } + Ok(serde_json::from_slice(&bytes).map_err(|_| "gateway.admin.invalid-response")?) + } + + /// What a serving gateway reports about its connection, or `None` when + /// none is serving or its answer is not a status. + async fn support_connection( + state_dir: &Path, + admin_socket: &AdminSocket, + ) -> Option { + use auths_gateway::SupportConnectionState as State; + UnixStream::connect(&admin_socket.path).await.ok()?; + let command = serde_json::json!({"command": "status"}); + let response = admin_exchange(state_dir, admin_socket, command, None) + .await + .ok()?; + let status = response.get("status")?; + let number = |member: &str| status.get(member).and_then(serde_json::Value::as_u64); + Some(auths_gateway::SupportConnection { + state: match status.get("state")?.as_str()? { + "active" => State::Active, + "disabled" => State::Disabled, + "revoked" => State::Revoked, + _ => return None, + }, + generation: number("generation")?, + credential_generation: number("credential_generation")?, + credential_held: status.get("credential_held")?.as_bool()?, + in_flight: number("in_flight")?, + }) + } + + /// The digests, closed states, and attempt stages of an installation. + /// It blocks, so the caller must not be on an async executor. + fn support_facts( + state_dir: &Path, + connection: Option, + ) -> Result { + const CODE: &str = "gateway.support.unavailable"; + let fixed = |text: &str| { + let mut bytes = [0_u8; 32]; + hex::decode_to_slice(text, &mut bytes) + .map(|()| bytes) + .map_err(|_| CODE) + }; + let manifest = installation(state_dir)?; + let executable = fs::read(std::env::current_exe().map_err(|_| CODE)?).map_err(|_| CODE)?; + let listed = open_attempts( + manifest.deployment, + manifest.attempt_store.as_ref().map(PathBuf::from), + ) + .ok() + .and_then(|attempts| { + tokio::runtime::Builder::new_current_thread() + .build() + .ok()? + .block_on(attempts.stages(auths_gateway::MAX_SUPPORT_ATTEMPTS + 1)) + .ok() + }); + let attempts_truncated = listed + .as_ref() + .is_some_and(|listed| listed.len() > auths_gateway::MAX_SUPPORT_ATTEMPTS); + let attempts = listed + .map(|listed| { + listed + .into_iter() + .take(auths_gateway::MAX_SUPPORT_ATTEMPTS) + .map(|(key, stage)| fixed(&key).map(|key| (key, stage))) + .collect::, _>>() + }) + .transpose()?; + Ok(auths_gateway::SupportFacts { + build_sha256: Sha256::digest(&executable).into(), + recipe_sha256: fixed(&manifest.recipe_digest)?, + profile_lock_sha256: fixed(&manifest.profile_lock_sha256)?, + trusted_context_sha256: fixed(&manifest.trusted_context_sha256)?, + production: manifest.deployment == Deployment::Production, + credential_store_kind: CredentialStoreKind::parse(&manifest.credential_store.kind) + .map_err(|_| CODE)?, + qualification: qualification_gate(state_dir, &manifest)?.status(), + connection, + attempts, + attempts_truncated, + }) } async fn rotate( @@ -2793,6 +2899,26 @@ mod unix { let command = serde_json::json!({"command": "qualification-reload"}); admin_command(&state_dir, &admin_socket, command, None).await } + Command::SupportBundle { + state_dir, + admin_socket, + out, + } => { + private_root(&state_dir)?; + let admin_socket = admin_socket_path(&state_dir, admin_socket); + let connection = support_connection(&state_dir, &admin_socket).await; + let facts = + tokio::task::spawn_blocking(move || support_facts(&state_dir, connection)) + .await + .map_err(|_| "gateway.support.unavailable")??; + let archive = auths_gateway::support_bundle(&facts)?; + if let Some(path) = out { + private_file(&path, &archive)?; + } else { + println!("{}", String::from_utf8_lossy(&archive)); + } + Ok(()) + } Command::QualificationStatus { state_dir, tuple } => { tokio::task::spawn_blocking(move || qualification_status(&state_dir, tuple)) .await diff --git a/product/runtime/auths-gateway/src/lib.rs b/product/runtime/auths-gateway/src/lib.rs index b4b3e3f24..254a7ada3 100644 --- a/product/runtime/auths-gateway/src/lib.rs +++ b/product/runtime/auths-gateway/src/lib.rs @@ -30,6 +30,7 @@ mod semantic_closure; mod separation; mod store; mod submit; +mod support; mod transport; #[cfg(test)] @@ -126,4 +127,8 @@ pub use store::{ PrivateDirectoryError, check_private_directory, check_private_directory_owned_by, pre_entry_digest, }; +pub use support::{ + MAX_SUPPORT_ATTEMPTS, SUPPORT_BUNDLE_SCHEMA, SupportConnection, SupportConnectionState, + SupportFacts, support_bundle, +}; pub use transport::MAX_TRANSPORT_DURATION; diff --git a/product/runtime/auths-gateway/src/pending_vectors/production.rs b/product/runtime/auths-gateway/src/pending_vectors/production.rs index 8fc94149c..081aa20fd 100644 --- a/product/runtime/auths-gateway/src/pending_vectors/production.rs +++ b/product/runtime/auths-gateway/src/pending_vectors/production.rs @@ -12,9 +12,9 @@ //! that try to select custody or declare qualification, the fixed //! retirement delay, and redacted debug forms. The qualification codes are //! implemented by the gate, whose tests drive every verification vector. -//! The rest wait for the readiness codes and the support bundle. For those -//! this module asserts the shortfall: no product crate defines a readiness -//! code, and the gateway has no support bundle. The secret-name and version +//! The support bundle exists and its own test scans it for every canary of +//! the `redaction` section. The readiness codes are still pending, and for +//! those this module asserts the shortfall: no product crate defines one. The secret-name and version //! vectors are generated here from the stated derivation and driven by the //! Secrets Manager store's own tests, so the two agree or one of them fails. Those assertions are expected to fail when the implementing work //! lands, wherever it lands, and that work replaces each with the @@ -1130,8 +1130,7 @@ fn every_hostile_class_has_a_vector() { /// The inventory is closed over the vectors, every existing code exists, /// and the rest of the production work has not landed: no product crate -/// defines a new code or a code under a new family, and the gateway has no -/// support bundle under any spelling. The secret-name and version vectors +/// defines a new code or a code under a new family. The secret-name and version vectors /// are no longer pending: the Secrets Manager store derives them, and its /// own tests drive `secret_names` and `version_references`. #[test] @@ -1182,12 +1181,4 @@ fn production_codes_await_their_epics() { ); } } - for (path, text) in &gateway { - let folded = text.to_lowercase().replace(['-', '_', ' '], ""); - assert!( - !folded.contains("supportbundle"), - "{} has a support bundle: scan it for every redaction canary", - path.display() - ); - } } diff --git a/product/runtime/auths-gateway/src/scenario_tests.rs b/product/runtime/auths-gateway/src/scenario_tests.rs index 839ac5cc3..99d806883 100644 --- a/product/runtime/auths-gateway/src/scenario_tests.rs +++ b/product/runtime/auths-gateway/src/scenario_tests.rs @@ -94,6 +94,10 @@ impl RecordingStore { } impl GatewayAttemptStore for RecordingStore { + fn attempt_keys(&self, limit: usize) -> Result, GatewayAttemptError> { + self.inner.attempt_keys(limit) + } + fn insert_all( &self, entries: &[GatewayRecordEntry], diff --git a/product/runtime/auths-gateway/src/semantic_closure.rs b/product/runtime/auths-gateway/src/semantic_closure.rs index ff848f21c..18617249f 100644 --- a/product/runtime/auths-gateway/src/semantic_closure.rs +++ b/product/runtime/auths-gateway/src/semantic_closure.rs @@ -9,7 +9,7 @@ /// The digest of `semantic-closure.json`, the closure of this build. pub const GATEWAY_SEMANTIC_CLOSURE_SHA256: &str = - "1fb4c5a9c89b2c9453d0b341f5d10f59a8e9f745c3b36113cc64259382662881"; + "e0f7c91f21c2c835e9f122618e31387ac7104ea9ca9ae080b9937718eb11648d"; #[cfg(test)] mod tests { diff --git a/product/runtime/auths-gateway/src/store.rs b/product/runtime/auths-gateway/src/store.rs index bdf086179..c18ab29c0 100644 --- a/product/runtime/auths-gateway/src/store.rs +++ b/product/runtime/auths-gateway/src/store.rs @@ -984,6 +984,13 @@ pub trait GatewayAttemptStore: Send + Sync { /// # Errors /// Returns [`GatewayAttemptError::Unavailable`] when storage fails. fn sweep_expired(&self, now: u64, limit: usize) -> Result; + + /// Lists at most `limit` keys of stored attempts, in key order. A key is + /// a digest and names no operation. + /// + /// # Errors + /// Returns [`GatewayAttemptError::Unavailable`] when storage fails. + fn attempt_keys(&self, limit: usize) -> Result, GatewayAttemptError>; } /// Atomic file store for one host. This is not a multi-host store and does @@ -1287,6 +1294,10 @@ fn valid_file_name(name: &str) -> bool { } impl GatewayAttemptStore for FileGatewayAttemptStore { + fn attempt_keys(&self, limit: usize) -> Result, GatewayAttemptError> { + self.claimed_keys(limit) + } + fn insert_all( &self, entries: &[GatewayRecordEntry], @@ -1418,7 +1429,39 @@ impl Drop for PostgresGatewayAttemptStore { } } +impl FileGatewayAttemptStore { + fn claimed_keys(&self, limit: usize) -> Result, GatewayAttemptError> { + let _lock = self.shared()?; + let mut keys = Vec::new(); + for entry in fs::read_dir(&self.root).map_err(|_| GatewayAttemptError::Unavailable)? { + let name = entry + .map_err(|_| GatewayAttemptError::Unavailable)? + .file_name(); + let key = name + .to_str() + .filter(|name| valid_file_name(name)) + .and_then(|name| name.strip_prefix("claim-")) + .and_then(|name| name.strip_suffix(".json")); + if let Some(key) = key { + let mut bytes = [0_u8; 32]; + hex::decode_to_slice(key, &mut bytes).map_err(|_| GatewayAttemptError::Corrupt)?; + keys.push(GatewayAttemptKey(bytes)); + } + } + keys.sort_unstable(); + keys.truncate(limit); + Ok(keys) + } +} + impl GatewayAttemptStore for PostgresGatewayAttemptStore { + fn attempt_keys(&self, limit: usize) -> Result, GatewayAttemptError> { + self.store()? + .list_gateway_record_keys(GatewayRecordKind::Attempt, limit) + .map(|keys| keys.into_iter().map(GatewayAttemptKey).collect()) + .map_err(postgres_error) + } + fn insert_all( &self, entries: &[GatewayRecordEntry], @@ -1581,6 +1624,40 @@ impl GatewayAttempts { }) } + /// Lists at most `limit` stored attempts as the hexadecimal digest that + /// keys each one and its conservative stage. Nothing else of an attempt + /// is returned: no operation identifier, argument, or provider value. + /// + /// # Errors + /// Malformed state is a hard failure. + pub async fn stages( + &self, + limit: usize, + ) -> Result, GatewayAttemptError> { + let store = Arc::clone(&self.store); + blocking(move || { + store + .attempt_keys(limit)? + .into_iter() + .filter_map(|key| { + let stage = store + .load(GatewayRecordKind::Attempt, &key) + .and_then(|bytes| bytes.map(|bytes| decode(&bytes)).transpose()) + .and_then(|record| record.map(|record| record.snapshot(true)).transpose()); + match stage { + Ok(Some(snapshot)) => { + Some(Ok((hex::encode(key.as_bytes()), snapshot.stage()))) + } + // Deleted between the listing and the read. + Ok(None) => None, + Err(error) => Some(Err(error)), + } + }) + .collect() + }) + .await + } + /// Reads a secret-free durable snapshot. An `attempting` stage is /// conservatively projected as `unknown`: another process may hold it, or /// it may have crashed. diff --git a/product/runtime/auths-gateway/src/support.rs b/product/runtime/auths-gateway/src/support.rs new file mode 100644 index 000000000..8d3e354fb --- /dev/null +++ b/product/runtime/auths-gateway/src/support.rs @@ -0,0 +1,295 @@ +//! The redacted archive an operator sends when asking for help. +//! +//! The archive is built from [`SupportFacts`], which has no member that can +//! carry text from a request, a provider, or an operator: every member is a +//! digest, a closed state, a stable code, a count, or a bounded integer. A +//! proof, grant, action, request or response body, credential, credential +//! location, key-manager resource name, provider account or resource +//! identifier, or raw header therefore has no member to arrive through. An +//! attempt appears as the digest that keys it and its stage. + +use crate::{GatewayAttemptStage, QualificationStatus}; +use serde::Serialize; +use std::collections::BTreeMap; + +/// The schema of the archive. +pub const SUPPORT_BUNDLE_SCHEMA: &str = "auths.gateway-support-bundle/1"; +/// The most attempts one archive lists. +pub const MAX_SUPPORT_ATTEMPTS: usize = 256; + +/// The closed state of the shared connection record. +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum SupportConnectionState { + /// Entries may start. + Active, + /// The operator disabled new entries. + Disabled, + /// The connection is revoked. + Revoked, +} + +/// What a serving gateway reported about its connection. +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub struct SupportConnection { + /// The record's state. + pub state: SupportConnectionState, + /// The record's generation. + pub generation: u64, + /// The credential generation the record seals. + pub credential_generation: u64, + /// Whether the process holds the secret the record commits to. + pub credential_held: bool, + /// The process's in-flight entries. + pub in_flight: u64, +} + +/// Everything an archive is built from. No member holds free text. +#[derive(Clone, Debug)] +pub struct SupportFacts { + /// SHA-256 of the running executable. + pub build_sha256: [u8; 32], + /// The compiled recipe's digest. + pub recipe_sha256: [u8; 32], + /// SHA-256 of the installed profile lock. + pub profile_lock_sha256: [u8; 32], + /// SHA-256 of the installed trusted context. + pub trusted_context_sha256: [u8; 32], + /// Whether the installation is a production deployment. + pub production: bool, + /// The credential store in use. + pub credential_store_kind: auths_connections::CredentialStoreKind, + /// The qualification gate's state. + pub qualification: QualificationStatus, + /// The connection, when a serving gateway answered. + pub connection: Option, + /// Stored attempts as key digest and stage, at most + /// [`MAX_SUPPORT_ATTEMPTS`]; `None` when the store could not be read. + pub attempts: Option>, + /// Whether the store holds more attempts than were listed. + pub attempts_truncated: bool, +} + +const fn stage_token(stage: GatewayAttemptStage) -> &'static str { + match stage { + GatewayAttemptStage::NotEntered => "not-entered", + GatewayAttemptStage::Attempting => "attempting", + GatewayAttemptStage::ResponseRecorded => "response-recorded", + GatewayAttemptStage::Unknown => "unknown", + GatewayAttemptStage::Observed => "observed", + GatewayAttemptStage::ObservedByProvider => "observed-by-provider", + } +} + +#[derive(Serialize)] +struct Qualification { + policy: &'static str, + state: &'static str, + code: Option<&'static str>, +} + +#[derive(Serialize)] +struct Connection { + state: &'static str, + generation: u64, + credential_generation: u64, + credential_held: bool, + in_flight: u64, +} + +#[derive(Serialize)] +struct Attempt { + key_sha256: String, + stage: &'static str, +} + +#[derive(Serialize)] +struct Attempts { + listed: usize, + truncated: bool, + by_stage: BTreeMap<&'static str, u64>, + identifiers: Vec, +} + +#[derive(Serialize)] +struct Archive { + schema: &'static str, + gateway_package: &'static str, + gateway_version: &'static str, + semantic_closure_sha256: &'static str, + build_sha256: String, + recipe_sha256: String, + profile_lock_sha256: String, + trusted_context_sha256: String, + deployment: &'static str, + credential_store_kind: &'static str, + qualification: Qualification, + connection: Option, + attempts: Option, + codes: Vec<&'static str>, +} + +/// Builds the archive: canonical JSON of bounded size. +/// +/// # Errors +/// +/// Returns `gateway.support.unavailable` when the archive cannot be encoded. +pub fn support_bundle(facts: &SupportFacts) -> Result, &'static str> { + let attempts = facts.attempts.as_ref().map(|listed| { + let listed = &listed[..listed.len().min(MAX_SUPPORT_ATTEMPTS)]; + let mut by_stage = BTreeMap::new(); + for (_, stage) in listed { + *by_stage.entry(stage_token(*stage)).or_insert(0_u64) += 1; + } + Attempts { + listed: listed.len(), + truncated: facts.attempts_truncated, + by_stage, + identifiers: listed + .iter() + .map(|(key, stage)| Attempt { + key_sha256: hex::encode(key), + stage: stage_token(*stage), + }) + .collect(), + } + }); + let mut codes: Vec<&'static str> = facts.qualification.code.into_iter().collect(); + if facts.attempts.is_none() { + codes.push("gateway.support.attempts-unavailable"); + } + if facts.connection.is_none() { + codes.push("gateway.support.gateway-not-serving"); + } + let archive = Archive { + schema: SUPPORT_BUNDLE_SCHEMA, + gateway_package: env!("CARGO_PKG_NAME"), + gateway_version: env!("CARGO_PKG_VERSION"), + semantic_closure_sha256: crate::GATEWAY_SEMANTIC_CLOSURE_SHA256, + build_sha256: hex::encode(facts.build_sha256), + recipe_sha256: hex::encode(facts.recipe_sha256), + profile_lock_sha256: hex::encode(facts.profile_lock_sha256), + trusted_context_sha256: hex::encode(facts.trusted_context_sha256), + deployment: if facts.production { + "production" + } else { + "development" + }, + credential_store_kind: facts.credential_store_kind.as_str(), + qualification: Qualification { + policy: facts.qualification.policy.as_str(), + state: facts.qualification.state.as_str(), + code: facts.qualification.code, + }, + connection: facts.connection.map(|connection| Connection { + state: match connection.state { + SupportConnectionState::Active => "active", + SupportConnectionState::Disabled => "disabled", + SupportConnectionState::Revoked => "revoked", + }, + generation: connection.generation, + credential_generation: connection.credential_generation, + credential_held: connection.credential_held, + in_flight: connection.in_flight, + }), + attempts, + codes, + }; + serde_json_canonicalizer::to_vec(&archive).map_err(|_| "gateway.support.unavailable") +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{QualificationPolicy, QualificationStatus}; + use auths_recipe_qualification::RecipeQualificationState; + + fn facts() -> SupportFacts { + SupportFacts { + build_sha256: [1; 32], + recipe_sha256: [2; 32], + profile_lock_sha256: [3; 32], + trusted_context_sha256: [4; 32], + production: true, + credential_store_kind: auths_connections::CredentialStoreKind::AwsSecretsManagerV1, + qualification: QualificationStatus { + policy: QualificationPolicy::Required, + state: RecipeQualificationState::Stale, + code: Some("gateway.qualification.revocation-stale"), + }, + connection: Some(SupportConnection { + state: SupportConnectionState::Disabled, + generation: 7, + credential_generation: 3, + credential_held: true, + in_flight: 0, + }), + attempts: Some(vec![ + ([9; 32], GatewayAttemptStage::Unknown), + ([8; 32], GatewayAttemptStage::ObservedByProvider), + ([7; 32], GatewayAttemptStage::Unknown), + ]), + attempts_truncated: false, + } + } + + #[test] + fn an_archive_holds_digests_closed_states_codes_and_counts() { + let archive: serde_json::Value = + serde_json::from_slice(&support_bundle(&facts()).expect("archive")).expect("JSON"); + assert_eq!(archive["schema"], SUPPORT_BUNDLE_SCHEMA); + assert_eq!(archive["deployment"], "production"); + assert_eq!(archive["credential_store_kind"], "aws-secrets-manager-v1"); + assert_eq!(archive["qualification"]["state"], "stale"); + assert_eq!(archive["connection"]["state"], "disabled"); + assert_eq!(archive["attempts"]["by_stage"]["unknown"], 2); + assert_eq!( + archive["attempts"]["identifiers"][1]["key_sha256"], + "08".repeat(32) + ); + assert_eq!( + archive["codes"], + serde_json::json!(["gateway.qualification.revocation-stale"]) + ); + } + + #[test] + fn what_could_not_be_read_is_stated_and_the_listing_is_bounded() { + let mut absent = facts(); + absent.connection = None; + absent.attempts = None; + let archive: serde_json::Value = + serde_json::from_slice(&support_bundle(&absent).expect("archive")).expect("JSON"); + assert!(archive["connection"].is_null() && archive["attempts"].is_null()); + assert_eq!( + archive["codes"], + serde_json::json!([ + "gateway.qualification.revocation-stale", + "gateway.support.attempts-unavailable", + "gateway.support.gateway-not-serving" + ]) + ); + let mut many = facts(); + many.attempts = Some(vec![([5; 32], GatewayAttemptStage::NotEntered); 400]); + many.attempts_truncated = true; + let bytes = support_bundle(&many).expect("archive"); + let archive: serde_json::Value = serde_json::from_slice(&bytes).expect("JSON"); + assert_eq!(archive["attempts"]["listed"], MAX_SUPPORT_ATTEMPTS); + assert_eq!(archive["attempts"]["truncated"], true); + assert!(bytes.len() < 64 * 1024, "the archive is bounded"); + } + + /// The facts an archive is built from have no member that holds text, + /// so nothing a request, provider, or operator wrote can enter one. + #[test] + fn the_facts_have_no_free_text_member() { + let source = include_str!("support.rs"); + let facts = source + .split("pub struct SupportFacts {") + .nth(1) + .and_then(|rest| rest.split("\n}\n").next()) + .expect("the facts"); + for forbidden in ["String", "&str", "Vec", "PathBuf", "Value"] { + assert!(!facts.contains(forbidden), "the facts hold a {forbidden}"); + } + } +} diff --git a/product/runtime/auths-gateway/tests/support_bundle.rs b/product/runtime/auths-gateway/tests/support_bundle.rs new file mode 100644 index 000000000..57fddd890 --- /dev/null +++ b/product/runtime/auths-gateway/tests/support_bundle.rs @@ -0,0 +1,208 @@ +//! The support bundle of a real installation, scanned for every canary the +//! custody fixture plants: the provider credential, the account label, and +//! files and environment variables holding each other excluded source. + +#![cfg(unix)] +#![allow(clippy::too_many_lines, reason = "one journey reads top to bottom")] + +use auths_gateway::CompiledRecipe; +use auths_recipe_qualification_issuance::stages::{ScanSource, SourceKind, redaction}; +use std::{ + fs::{self, File}, + io::{BufRead as _, BufReader, Write as _}, + os::unix::fs::PermissionsExt as _, + path::Path, + process::{Child, Command, Output, Stdio}, +}; + +const BIN: &str = env!("CARGO_BIN_EXE_auths-gateway"); +const RECIPE: &[u8] = include_bytes!("../../../../bindings/fixtures/gateway/airtable/recipe.json"); +const LOCK: &[u8] = + include_bytes!("../../../../bindings/fixtures/gateway/airtable/profile.lock.json"); +const TRUST: &[u8] = + include_bytes!("../../../../core/fixtures/v1/denied/untrusted-root.context.cbor"); +const CUSTODY: &[u8] = include_bytes!("../../../../bindings/fixtures/gateway/custody-hostile.json"); + +struct Running(Child); + +impl Drop for Running { + fn drop(&mut self) { + let _ = self.0.kill(); + let _ = self.0.wait(); + } +} + +/// Every canary of the fixture, by the source it is planted in. +fn canaries() -> Vec<(String, String)> { + let fixture: serde_json::Value = serde_json::from_slice(CUSTODY).expect("fixture"); + fixture["redaction"]["canaries"]["sources"] + .as_array() + .expect("sources") + .iter() + .map(|source| { + let text = |member: &str| source[member].as_str().expect("text").to_owned(); + (text("source"), text("canary")) + }) + .collect() +} + +fn run(command: &mut Command, stdin: &[u8]) -> Output { + let mut child = command + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .spawn() + .expect("spawn"); + child + .stdin + .take() + .expect("stdin") + .write_all(stdin) + .expect("stdin bytes"); + child.wait_with_output().expect("output") +} + +fn bundle(state: &Path, planted: &[(String, String)]) -> Vec { + let mut command = Command::new(BIN); + command.arg("support-bundle").arg("--state-dir").arg(state); + for (source, canary) in planted { + command.env( + format!("AUTHS_TEST_{}", source.replace('-', "_").to_uppercase()), + canary, + ); + } + let output = run(&mut command, b""); + assert!( + output.status.success(), + "{}", + String::from_utf8_lossy(&output.stderr) + ); + output.stdout +} + +#[test] +fn a_support_bundle_holds_no_planted_canary() { + let planted = canaries(); + assert_eq!(planted.len(), 11); + let canary = |source: &str| { + planted + .iter() + .find(|(name, _)| name == source) + .map(|(_, canary)| canary.clone()) + .expect("canary") + }; + let directory = tempfile::tempdir().expect("directory"); + let root = fs::canonicalize(directory.path()).expect("root"); + fs::set_permissions(&root, fs::Permissions::from_mode(0o700)).expect("mode"); + fs::write(root.join("recipe.json"), RECIPE).expect("recipe"); + fs::write(root.join("profile.lock.json"), LOCK).expect("lock"); + fs::write(root.join("trusted.context.cbor"), TRUST).expect("trust"); + let state = root.join("state"); + let digest = CompiledRecipe::compile(RECIPE, LOCK) + .expect("recipe") + .digest_hex(); + + // The credential and the provider account label are the two canaries an + // installation takes in directly. + let installed = run( + Command::new(BIN) + .arg("install") + .arg("--state-dir") + .arg(&state) + .arg("--recipe") + .arg(root.join("recipe.json")) + .arg("--profile-lock") + .arg(root.join("profile.lock.json")) + .arg("--trusted-context") + .arg(root.join("trusted.context.cbor")) + .arg("--approve-digest") + .arg(&digest) + .arg("--provider") + .arg("airtable") + .arg("--alias") + .arg("demo") + .arg("--account-label") + .arg(canary("provider-account-id")) + .arg("--credential-stdin"), + format!("{}\n", canary("credential")).as_bytes(), + ); + assert!( + installed.status.success(), + "{}", + String::from_utf8_lossy(&installed.stderr) + ); + // Every other excluded source, left where a careless collector would + // sweep it up: beside the installation and in the environment. + for (source, canary) in &planted { + fs::write(state.join(format!("{source}.captured")), canary).expect("planted file"); + } + + let offline = bundle(&state, &planted); + let archive: serde_json::Value = serde_json::from_slice(&offline).expect("archive"); + assert_eq!(archive["schema"], "auths.gateway-support-bundle/1"); + assert_eq!(archive["recipe_sha256"], digest.as_str()); + assert_eq!(archive["deployment"], "development"); + assert_eq!(archive["attempts"]["listed"], 0); + assert!(archive["connection"].is_null(), "no gateway is serving"); + assert!( + archive["codes"] + .as_array() + .expect("codes") + .iter() + .any(|code| code == "gateway.support.gateway-not-serving") + ); + + let mut child = Command::new(BIN) + .arg("serve") + .arg("--state-dir") + .arg(&state) + .arg("--app-socket") + .arg(root.join("app.sock")) + .stdout(Stdio::piped()) + .stderr(File::create(root.join("serve.stderr")).expect("stderr")) + .spawn() + .expect("serve"); + let mut ready = String::new(); + BufReader::new(child.stdout.take().expect("stdout")) + .read_line(&mut ready) + .expect("readiness"); + let _serving = Running(child); + assert!(ready.starts_with("app socket ready"), "{ready}"); + let serving = bundle(&state, &planted); + let archive: serde_json::Value = serde_json::from_slice(&serving).expect("archive"); + assert_eq!(archive["connection"]["state"], "active"); + assert_eq!(archive["connection"]["credential_held"], true); + + let secrets: Vec<&[u8]> = planted + .iter() + .map(|(_, canary)| canary.as_bytes()) + .collect(); + let sources = [ + ScanSource { + kind: SourceKind::SupportBundle, + name: "offline", + bytes: &offline, + }, + ScanSource { + kind: SourceKind::SupportBundle, + name: "serving", + bytes: &serving, + }, + ]; + let scanned = redaction(&secrets, &sources).expect("scan"); + assert!(scanned.iter().all(|case| case.passed), "{scanned:?}"); + + // The scan is able to find one: the same bytes with a canary appended + // fail it. + let leaking = [offline.as_slice(), canary("raw-header").as_bytes()].concat(); + let found = redaction( + &secrets, + &[ScanSource { + kind: SourceKind::SupportBundle, + name: "leaking", + bytes: &leaking, + }], + ) + .expect("scan"); + assert!(!found[0].passed); +} diff --git a/product/stores/auths-stores/src/gateway_attempt.rs b/product/stores/auths-stores/src/gateway_attempt.rs index 6d023cd74..b2f85a5ba 100644 --- a/product/stores/auths-stores/src/gateway_attempt.rs +++ b/product/stores/auths-stores/src/gateway_attempt.rs @@ -219,6 +219,38 @@ impl PostgresLifecycleStore { .transpose() } + /// Lists at most `limit` keys of the records of `kind`, in key order. + /// The records themselves are not read. + /// + /// # Errors + /// + /// Returns [`StoreError::LimitExceeded`] for a limit the database cannot + /// hold, [`StoreError::Corrupt`] for a key of another width, and a + /// closed store error when the database is unavailable. + pub fn list_gateway_record_keys( + &self, + kind: GatewayRecordKind, + limit: usize, + ) -> Result, StoreError> { + let limit = i64::try_from(limit).map_err(|_| StoreError::LimitExceeded)?; + let mut client = self.pool.get().map_err(|_| StoreError::PoolExhausted)?; + client + .query( + "SELECT record_key FROM auths_gateway_records + WHERE record_kind = $1 + ORDER BY record_key + LIMIT $2", + &[&kind.as_str(), &limit], + ) + .map_err(|error| map_postgres_error(&error))? + .iter() + .map(|row| { + let key: Vec = row.try_get(0).map_err(|_| StoreError::Corrupt)?; + <[u8; 32]>::try_from(key.as_slice()).map_err(|_| StoreError::Corrupt) + }) + .collect() + } + /// Replaces the record of `kind` under `key` with `next` only while it /// still holds exactly `current`. Slots are insert-only. /// From f02d100f2ffc462b2e6a047cd5b6510d148bc762 Mon Sep 17 00:00:00 2001 From: bordumb Date: Tue, 6 Oct 2026 03:09:36 +0100 Subject: [PATCH 002/108] feat(gateway): check readiness, stop through outages and guard restored generations --- .../fixtures/gateway/production-codes.json | 50 +++- compliance.toml | 10 +- deployment/gateway/README.md | 93 ++++++++ deployment/gateway/operator.conf.example | 6 + deployment/gateway/runtime.conf.example | 6 + .../systemd/auths-gateway-doctor.service | 19 ++ .../systemd/auths-gateway-doctor.timer | 10 + .../gateway/systemd/auths-gateway.service | 37 +++ docs/PROGRAM_BOARD.md | 14 ++ docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md | 119 ++++++++++ ...gateway-polish-and-recipe-qualification.md | 21 ++ .../auths-gateway/semantic-closure.json | 2 +- .../auths-gateway/src/bin/auths-gateway.rs | 223 ++++++++++++++++-- .../runtime/auths-gateway/src/connection.rs | 74 +++++- product/runtime/auths-gateway/src/engine.rs | 181 +++++++++++++- .../auths-gateway/src/generation_floor.rs | 141 +++++++++++ product/runtime/auths-gateway/src/lib.rs | 2 + .../src/pending_vectors/production.rs | 14 +- .../runtime/auths-gateway/src/readiness.rs | 62 +++++ .../auths-gateway/src/semantic_closure.rs | 2 +- .../auths-gateway/tests/isolated_process.rs | 30 ++- release/semantic-freeze-versions.toml | 8 +- release/semantic-freeze.json | 14 +- 23 files changed, 1072 insertions(+), 66 deletions(-) create mode 100644 deployment/gateway/README.md create mode 100644 deployment/gateway/operator.conf.example create mode 100644 deployment/gateway/runtime.conf.example create mode 100644 deployment/gateway/systemd/auths-gateway-doctor.service create mode 100644 deployment/gateway/systemd/auths-gateway-doctor.timer create mode 100644 deployment/gateway/systemd/auths-gateway.service create mode 100644 docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md create mode 100644 product/runtime/auths-gateway/src/generation_floor.rs diff --git a/bindings/fixtures/gateway/production-codes.json b/bindings/fixtures/gateway/production-codes.json index 936860779..e630182c7 100644 --- a/bindings/fixtures/gateway/production-codes.json +++ b/bindings/fixtures/gateway/production-codes.json @@ -23,6 +23,14 @@ "id": "lease-generation-not-held" } }, + { + "code": "gateway.connection.restore-rollback", + "owner": "connection", + "stage": "before-lease", + "status": "implemented", + "epic": 4, + "case": null + }, { "code": "gateway.credential.adapter-unsupported", "owner": "credential-store", @@ -156,7 +164,47 @@ "code": "gateway.readiness.connection-disabled", "owner": "readiness", "stage": "doctor", - "status": "new", + "status": "implemented", + "epic": 4, + "case": null + }, + { + "code": "gateway.readiness.observer-unavailable", + "owner": "readiness", + "stage": "doctor", + "status": "implemented", + "epic": 4, + "case": null + }, + { + "code": "gateway.readiness.recipe-drift", + "owner": "readiness", + "stage": "doctor", + "status": "implemented", + "epic": 4, + "case": null + }, + { + "code": "gateway.readiness.store-unavailable", + "owner": "readiness", + "stage": "doctor", + "status": "implemented", + "epic": 4, + "case": null + }, + { + "code": "gateway.readiness.transport-unavailable", + "owner": "readiness", + "stage": "doctor", + "status": "implemented", + "epic": 4, + "case": null + }, + { + "code": "gateway.readiness.trust-unavailable", + "owner": "readiness", + "stage": "doctor", + "status": "implemented", "epic": 4, "case": null }, diff --git a/compliance.toml b/compliance.toml index d6ab9198b..4f0d8ee5d 100644 --- a/compliance.toml +++ b/compliance.toml @@ -1578,7 +1578,7 @@ kind = "cargo" layer = "product" path = "product/runtime/auths-gateway" core_apis = ["auths-author", "auths-codec", "auths-did-keri", "auths-did-key", "auths-model", "auths-multikey", "auths-ports", "auths-raw-key", "auths-raw-key-core", "auths-registries", "auths-signature", "auths-verifier"] -protocol_versions = ["auths.gateway-installation/5", "auths.recipe-qualification/1", "auths.recipe-qualification-attestation/1", "auths.qualification-trust-root/1", "auths.qualification-signer-certificate/1", "auths.qualification-revocation-list/1", "auths.qualification-release-index/1", "auths.gateway-semantic-closure/1", "auths.qualification-verification-vectors/1", "auths.gateway-operator-attestation/1", "auths.gateway-admin-request/1", "auths.gateway-admin-response/1", "auths.gateway-connection/1", "auths.provider-connection/2", "auths.gateway-key-identity/1", "auths.lifecycle.transactional-store/4", "auths.gateway-recipe-source/2", "auths.gateway-compiled-recipe/2", "auths.gateway-recipe-review/2", "auths.gateway-recovery-capability/1", "auths.gateway-connection-descriptor/1", "auths.gateway-attempt/3", "auths.gateway-pre-entry/1", "auths.lifecycle.postgresql/5", "auths.gateway-echo/1", "auths.gateway-idempotency-key/1", "auths.gateway-observe/2", "auths.gateway-outcome/2", "auths.gateway-readback/1", "auths.self-hosted-profile-lock/1", "mcp-arguments-v1", "auths.gateway-audit-bundle/2", "auths.gateway-audit-report/3", "auths.gateway-counter-set/1", "auths.gateway-echo-verification/1", "auths.gateway-codes/1", "auths.gateway-production-codes/1", "auths.gateway-custody-vectors/1", "auths.gateway-outcome-vectors/1", "bounded-policy-commitment-v1", "auths.approval-response/1", "auths.gateway-bounded-count/2", "auths.gateway-bounded-sum/1", "auths.gateway.argument-ceiling-window-count/2", "auths.gateway.argument-ceiling-policy/2"] +protocol_versions = ["auths.gateway-readiness/1", "auths.gateway-support-bundle/1", "auths.gateway-generation-floor/1", "auths.gateway-emergency-stop/1", "auths.gateway-installation/5", "auths.recipe-qualification/1", "auths.recipe-qualification-attestation/1", "auths.qualification-trust-root/1", "auths.qualification-signer-certificate/1", "auths.qualification-revocation-list/1", "auths.qualification-release-index/1", "auths.gateway-semantic-closure/1", "auths.qualification-verification-vectors/1", "auths.gateway-operator-attestation/1", "auths.gateway-admin-request/1", "auths.gateway-admin-response/1", "auths.gateway-connection/1", "auths.provider-connection/2", "auths.gateway-key-identity/1", "auths.lifecycle.transactional-store/4", "auths.gateway-recipe-source/2", "auths.gateway-compiled-recipe/2", "auths.gateway-recipe-review/2", "auths.gateway-recovery-capability/1", "auths.gateway-connection-descriptor/1", "auths.gateway-attempt/3", "auths.gateway-pre-entry/1", "auths.lifecycle.postgresql/5", "auths.gateway-echo/1", "auths.gateway-idempotency-key/1", "auths.gateway-observe/2", "auths.gateway-outcome/2", "auths.gateway-readback/1", "auths.self-hosted-profile-lock/1", "mcp-arguments-v1", "auths.gateway-audit-bundle/2", "auths.gateway-audit-report/3", "auths.gateway-counter-set/1", "auths.gateway-echo-verification/1", "auths.gateway-codes/1", "auths.gateway-production-codes/1", "auths.gateway-custody-vectors/1", "auths.gateway-outcome-vectors/1", "bounded-policy-commitment-v1", "auths.approval-response/1", "auths.gateway-bounded-count/2", "auths.gateway-bounded-sum/1", "auths.gateway.argument-ceiling-window-count/2", "auths.gateway.argument-ceiling-policy/2"] wire_objects = ["CompiledRecipe", "ClosedProviderRequest", "ClosedCredentialReads", "RecipeReview", "RecoveryCapability", "GatewayAttemptSnapshot", "GatewayPreEntry", "GatewayRecordEntry", "GatewayConnectionDescriptor", "ConnectionRecord", "OperatorAttestation", "OperatorStatement", "GatewayAdminStatus", "GatewayEvidenceSummary", "GatewayObserveRequest", "GatewayObserveResult", "GatewayProviderEvidence", "GatewaySubmitResult", "SignedObservation", "ArgumentCeilingPolicy", "BoundedPolicyCommitment", "AuditReport", "ProviderResult", "AuditedPreEntry", "EchoVerification", "AdminRequestCommand", "ListedValues"] fixture_suites = ["bindings/fixtures/approval", "bindings/fixtures/gateway", "bindings/fixtures/qualification"] principal_families = ["raw-key-v1", "did-key-v1", "did-keri-v1"] @@ -1586,9 +1586,15 @@ signature_families = ["ed25519-v1", "p256-sha256-v1"] profiles = ["auths.mcp/2"] transports = ["bounded-https", "postgresql-tls", "loopback-http-development"] configuration_inputs = ["operator-approved-recipe", "profile-lock", "independently-provisioned-trust", "connection-binding", "observer-anchor", "observer-signing-key", "deployment-kind", "operator-attestation", "app-capacity", "development-shared-file-store", "postgresql-store-configuration", "audit-trust-and-observer-pins", "qualification-policy", "recipe-family", "provider-contract-id", "qualification-release-inputs", "deployment-clock"] -security_state = ["recipe-digest", "logical-operation-claims", "credential-reference-generation", "shared-connection-record", "credential-generation", "in-flight-entry-count", "echo-bound-provider-evidence", "observer-signing-seed", "custody-held-observer-key", "principal-separation", "key-identity-separation", "pre-entry-evidence", "relative-ceiling-basis", "gateway-record-batches", "link-subject-count-and-sum-slots", "verified-qualification-index", "remembered-revocations", "accepted-revocation-sequence", "gateway-semantic-closure"] +security_state = ["host-generation-floor", "recipe-digest", "logical-operation-claims", "credential-reference-generation", "shared-connection-record", "credential-generation", "in-flight-entry-count", "echo-bound-provider-evidence", "observer-signing-seed", "custody-held-observer-key", "principal-separation", "key-identity-separation", "pre-entry-evidence", "relative-ceiling-basis", "gateway-record-batches", "link-subject-count-and-sum-slots", "verified-qualification-index", "remembered-revocations", "accepted-revocation-sequence", "gateway-semantic-closure"] [packages.auths-gateway.claims] +operator-production-readiness = [ + "product/runtime/auths-gateway/src/readiness.rs#the_projection_names_every_check_and_retains_precise_qualification_failure", + "product/runtime/auths-gateway/src/engine.rs#readiness_and_emergency_stop_make_no_credential_lease", + "product/runtime/auths-gateway/src/engine.rs#a_restored_store_below_the_host_floor_cannot_lease_after_restart", + "product/runtime/auths-gateway/tests/support_bundle.rs#a_support_bundle_holds_no_planted_canary", +] configuration-compiler = [ "product/runtime/auths-gateway/src/recipe/tests.rs#three_independent_recipes_compile_without_provider_code", "product/runtime/auths-gateway/src/recipe/tests.rs#hostile_recipe_corpus_fails_with_exact_codes", diff --git a/deployment/gateway/README.md b/deployment/gateway/README.md new file mode 100644 index 000000000..5211f5a2d --- /dev/null +++ b/deployment/gateway/README.md @@ -0,0 +1,93 @@ +# Production reference: two Ubuntu hosts, systemd, PostgreSQL TLS, AWS workload identity + +This reference runs one connection per gateway process on two Ubuntu hosts, +with a shared TLS PostgreSQL lifecycle store and distinct local installation +and monotonic-floor directories. The application talks through a Unix socket; +provider and secret-manager traffic uses bounded HTTPS. There is no external +HTTP gateway listener to terminate. Install exact release binaries and package +checksums under `/opt/auths/bin`; neither source nor a compiler belongs on the +hosts. Current production builds refuse writes until the qualification root +ceremony and both live qualification gates have completed. + +## Host setup + +Create group `auths-app-socket` (GID 62000), user `auths-gateway` (UID 62001), +and application user (UID 62002). The gateway's primary group is +`auths-app-socket`. Create `/var/lib/auths/gateway`, owned by UID 62001, mode +0700, and `/run/auths-app`, owned by UID 62001 and GID 62000, mode 0750. +Recreate the latter with a systemd tmpfiles rule at each boot. The application's +only group access is the 0660 app socket; it cannot reach the gateway state, +admin socket, workload token, operator identity or PostgreSQL client identity. +Keep operator credentials in `/run/auths-identity/operator` and runtime +credentials in `/run/auths-identity/runtime`, each mode 0700. Provision +short-lived, audience-bound web identity tokens through the deployment's +identity issuer. The runtime role has GetSecretValue and the one encryption +key's Decrypt; the operator role additionally has CreateSecret, DeleteSecret +and GenerateDataKey. Neither role can list secrets or alter versions. The +operator executes administration as UID 62001 with its separate token path. +The application receives neither identity directory nor runtime environment. + +Copy `systemd/` and the reviewed public runtime configuration. Never place a +provider token, static AWS access key or release signer in an environment file. +Use certificate/peer authentication for PostgreSQL, or a protected passfile +owned by the gateway; require the expected TLS server name and reviewed CA. +Enable `synchronous_commit`, durable WAL and continuous archive to independent +storage. Let the shipped store apply its current schema; obsolete schemas are +refused rather than translated. Take and restore a database snapshot in the +preproduction exercise before admitting traffic. + +Install the reviewed recipe, profile lock, trusted context, distinct operator +attestation and production credential store using `auths-gateway install`. +Pipe the disposable credential from the operator's secret source into stdin; +never put it in argv or a shell literal. Copy the signed qualification inputs +with `qualification-import`; run `doctor` as root, then use `enable` only +when all required checks pass. `doctor` prints `auths.gateway-readiness/1` and +returns nonzero on any failed check. Development installations always fail +production readiness. Follow the [operations runbook](../../docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md). + +## Network and privilege policy + +Apply host firewall rules by UID/cgroup before starting the gateway. Permit +the application only its own explicit business endpoints and Unix socket; +deny it provider and AWS credential endpoints. Permit the gateway only DNS +to the host resolver, TCP 443 to the recipe's reviewed provider IP set and +regional Secrets Manager and STS IP sets, and TLS PostgreSQL to its fixed +address/port. Resolve and review endpoint changes before updating the allowlist; +a changed address is an outage until reviewed. Deny metadata/container +credential endpoints because this reference uses web identity. Deny all other +egress. No broad HTTPS proxy or arbitrary destination is permitted. Check the +application UID's denied egress from the host firewall separately: doctor +checks process/socket isolation and pinned transport construction, not an +unconfigured external firewall. A successful readiness report is not proof +that an application lacks an independently obtained provider token. + +Enable systemd-timesyncd. Its fixed synchronization marker is the clock trust +input; missing synchronization disables required recipes. Monitor that marker, +not merely a running time service. The optional observer is absent in this +reference, explicitly reported as unavailable for signed outcomes. To add one, +provision the reviewed distinct custody-backed signing identity and restrict +its endpoint; never use a software observer in production. + +## Health, limits and alerts + +The unit bounds memory, CPU, processes, descriptors and shutdown time. The +process is live while its independently limited app/admin listeners answer; +provider, database and credential outages must not cause a liveness restart +loop. Use status/support-bundle for bounded attempt stage counts and in-flight +counts; export numeric metrics from these reports, never labels derived from +provider bodies or account/resource names. Alert on failed doctor checks, +qualification expiry/revocation-list next_update within 24 hours, untrusted +clock, unknown/attempting backlog, missing slot sweep, incomplete shutdown, +and credential deletion failure. Preserve the last report and stable codes. +A SIGTERM stops listeners, waits up to 25 seconds for admitted sessions, removes +socket paths, and reports incomplete drainage rather than success on timeout. + +## Evidence and human trial + +Hosted PostgreSQL and isolation workflows exercise the packaged command's +store, multi-host admin, actual application UID denial and restore-floor +refusal. They use disposable custody and do not establish production workload +identity, firewall or point-in-time restore operation. Record those live +reference exercises before declaring Epic 4 complete. Use the trial protocol +in the runbook with a person unfamiliar with the implementation; an automated +or simulated onboarding run cannot close that gate. diff --git a/deployment/gateway/operator.conf.example b/deployment/gateway/operator.conf.example new file mode 100644 index 000000000..ee0bc0be9 --- /dev/null +++ b/deployment/gateway/operator.conf.example @@ -0,0 +1,6 @@ +# Operator reads and administers custody; runtime role only reads it. +AUTHS_POSTGRES_URL=host=postgres.internal port=5432 dbname=auths user=auths sslmode=require +AUTHS_POSTGRES_CA_PEM=/etc/auths/postgres-ca.pem +AUTHS_POSTGRES_SERVER_NAME=postgres.internal +AWS_ROLE_ARN=arn:aws:iam::ACCOUNT:role/auths-operator +AWS_WEB_IDENTITY_TOKEN_FILE=/run/auths-identity/operator/token diff --git a/deployment/gateway/runtime.conf.example b/deployment/gateway/runtime.conf.example new file mode 100644 index 000000000..aa883e2c2 --- /dev/null +++ b/deployment/gateway/runtime.conf.example @@ -0,0 +1,6 @@ +# Public configuration only. Web identity tokens are short-lived files, never env values. +AUTHS_POSTGRES_URL=host=postgres.internal port=5432 dbname=auths user=auths sslmode=require +AUTHS_POSTGRES_CA_PEM=/etc/auths/postgres-ca.pem +AUTHS_POSTGRES_SERVER_NAME=postgres.internal +AWS_ROLE_ARN=arn:aws:iam::ACCOUNT:role/auths-runtime +AWS_WEB_IDENTITY_TOKEN_FILE=/run/auths-identity/runtime/token diff --git a/deployment/gateway/systemd/auths-gateway-doctor.service b/deployment/gateway/systemd/auths-gateway-doctor.service new file mode 100644 index 000000000..51365e358 --- /dev/null +++ b/deployment/gateway/systemd/auths-gateway-doctor.service @@ -0,0 +1,19 @@ +[Unit] +Description=Check Auths production readiness and emit the bounded report +After=auths-gateway.service + +[Service] +Type=oneshot +User=root +UMask=0077 +EnvironmentFile=/etc/auths/runtime.conf +ExecStart=/opt/auths/bin/auths-gateway doctor --state-dir /var/lib/auths/gateway --app-socket /run/auths-app/gateway.sock --app-uid 62002 --app-gid 62000 +NoNewPrivileges=yes +ProtectSystem=strict +ProtectHome=yes +PrivateTmp=yes +ReadWritePaths=/var/lib/auths/gateway +ReadOnlyPaths=/run/auths-identity/runtime +TimeoutStartSec=60 +StandardOutput=journal +StandardError=journal diff --git a/deployment/gateway/systemd/auths-gateway-doctor.timer b/deployment/gateway/systemd/auths-gateway-doctor.timer new file mode 100644 index 000000000..48766efee --- /dev/null +++ b/deployment/gateway/systemd/auths-gateway-doctor.timer @@ -0,0 +1,10 @@ +[Unit] +Description=Periodic Auths readiness check + +[Timer] +OnBootSec=60 +OnUnitActiveSec=60 +Unit=auths-gateway-doctor.service + +[Install] +WantedBy=timers.target diff --git a/deployment/gateway/systemd/auths-gateway.service b/deployment/gateway/systemd/auths-gateway.service new file mode 100644 index 000000000..8b37a923d --- /dev/null +++ b/deployment/gateway/systemd/auths-gateway.service @@ -0,0 +1,37 @@ +[Unit] +Description=Auths production gateway +After=network-online.target systemd-timesyncd.service +Wants=network-online.target + +[Service] +Type=simple +User=auths-gateway +Group=auths-app-socket +UMask=0077 +EnvironmentFile=/etc/auths/runtime.conf +ExecStart=/opt/auths/bin/auths-gateway serve --state-dir /var/lib/auths/gateway --app-socket /run/auths-app/gateway.sock +Restart=on-failure +RestartSec=5 +TimeoutStopSec=35 +KillSignal=SIGTERM +LimitNOFILE=512 +MemoryMax=512M +CPUQuota=200% +TasksMax=128 +NoNewPrivileges=yes +ProtectSystem=strict +ProtectHome=yes +PrivateTmp=yes +PrivateDevices=yes +ProtectKernelTunables=yes +ProtectKernelModules=yes +ProtectControlGroups=yes +RestrictSUIDSGID=yes +RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6 +ReadWritePaths=/var/lib/auths/gateway /run/auths-app +ReadOnlyPaths=/run/auths-identity/runtime /run/systemd/timesync +StandardOutput=journal +StandardError=journal + +[Install] +WantedBy=multi-user.target diff --git a/docs/PROGRAM_BOARD.md b/docs/PROGRAM_BOARD.md index 8b202cb14..46cb8af06 100644 --- a/docs/PROGRAM_BOARD.md +++ b/docs/PROGRAM_BOARD.md @@ -342,3 +342,17 @@ executable corpus runner and measured-observation contract, workflow wiring, CLI/script-pipeline tests, and direct credential-lease counters. Hosted verification is pending. Production family corpora, the owner's root ceremony, live qualifications, operator trial and launch acceptance remain unclaimed. + + +### AP-SPEC-066 unattended continuation (2026-10-06) + +Owner direction: finish Epic 4, then Epic 5, then publish the Python SDK +release candidate `0.0.1-rc1` and run a simulated onboarding pilot across all +recipes with measured friction and a backlog. Epic 3 PR #204 is merged. +Epic 4 implementation is on `gateway-operator-polish`; acceptance is still +open. The simulated pilot does not replace the independent operator trial or +human release review. Signing environment metadata contains no secret and +neither live recipe environment exists; the offline owner root ceremony and +live-provider qualification remain unclaimed. Python packaging must normalize +the requested semver to PEP 440 `0.0.1rc1`, preserving `0.0.1-rc1` as the +release/tag identifier. No publication or qualified launch is claimed yet. diff --git a/docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md b/docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md new file mode 100644 index 000000000..8e3c46f59 --- /dev/null +++ b/docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md @@ -0,0 +1,119 @@ +# Production gateway operations + +Use the exact installed `auths-gateway` and `auths-qualification` binaries and +verified package checksums. Run operator commands as the gateway state owner, +with operator workload identity for credential mutations; the serving process +keeps its read-only runtime identity. Root is required only for doctor's +privilege-drop test. Application processes receive neither identity nor state. + +## Diagnose and stop + +`doctor --state-dir ... --app-socket ... --app-uid ... --app-gid ...` prints all +nine required typed checks and the optional observer state. It checks the +actual lifecycle record, recipe binding, current credential-store confirmation, +qualification, clock and process isolation. Any failed or unmade check yields +nonzero status. Keep the JSON report. A missing observer explicitly means +signed outcomes are unavailable. `status` reports the serving process's local +in-flight count; it is not a cluster-wide drainage claim. + +If provider, custody or qualification inputs are unavailable, use +`disable --state-dir ... --store-only`. This needs only installation metadata +and the lifecycle store, so it also works with the gateway stopped. It is +idempotent, retains attempts unchanged and claims no drainage. Use +`revoke --state-dir ... --store-only` for permanent revocation. Later run the +normal `revoke` with healthy operator custody to delete the exact credentials; +a deletion error does not undo revocation. Never turn unknown into failure or +submit the operation again. Database failure means no durable stop can be +claimed; isolate app ingress at the host firewall and retain the incident. + +## Provider-secret rotation + +Use the operator identity and `rotate-prepare --operator-process +--credential-stdin --state-dir ...`, piping the new provider secret. It runs +the recipe's fixed credential checks and stores a successor without publishing +it. Retain only the returned reference commitment. Then use `rotate-commit +--operator-process --state-dir ... --commitment ...` to atomically publish it. +Check status on both hosts; each must see the same shared generation and hold +the exact committed credential generation. The old generation remains for at +least the fixed 20-second retirement delay. Repeat the exercise with a stop +between prepare and commit; a stale commitment must fail, leaving the old +record authoritative. For emergency cutover: disable, rotate while disabled, +verify both hosts, then enable. Never retain a new secret in terminal history. +Operator-process drainage describes only that short-lived process; wait for +all serving hosts separately before retiring external credentials. + +## Qualification signer, expiry and revocation + +The offline owner certifies a new protected software release signer with the +ceremony tool. Publish the new certificate, current signed revocation list, +release index and exact attestations together. Import on each host, invoke +qualification-reload on each serving operator socket and inspect derived status. +Do not extend validity by editing files or the clock. Test an expired +attestation, expired certificate, stale revocation list, untrusted clock, +revoked signer and revoked qualification with the disposable trust exercise. +Every required recipe must stop before lease. Keep the signed input digests, +closed codes and zero-entry/lease witnesses; no private key enters support +bundles or gateway hosts. Publish a root-signed revocation list at least every +24 hours (72 hours is the hard maximum), including when nothing is revoked. +Treat a missed update as an incident that disables required recipes. + +A root replacement is a new reviewed gateway build pin and new qualification +run for its exact build/closure, not an operator override. Stop writes, retain +revocation floors, install the newly pinned candidate and import its new-root +inputs. Old-root inputs must refuse. Only resume after exact candidate evidence +and the human boundary review. No root private key is created on a gateway or +in an online agent workspace. + +## Backup, point-in-time restore and restart + +Archive PostgreSQL WAL continuously and take encrypted snapshots. Back up +public installation files, operator attestation, qualification inputs and host +floors. Keep `connection-floor.json` and qualification verifier floors in an +independent current recovery record; never restore older floors together with +an older database. Before an exercise, record connection and credential +generations, recipe/lock digests, qualification issue-time/revocation floors +and attempt counts on both hosts. Disable app ingress and new entries; stop +both binaries and retain unknown/response-recorded operations. + +Restore snapshot plus WAL to a new PostgreSQL endpoint, validate its TLS name +and schema, and keep original hosts stopped. Start each replacement from its +current independently retained floor files and reviewed installed inputs. +A restored connection generation below the host floor, or different bytes at +the same generation, refuses before lease. Recipe drift, unavailable exact +credential generation and rolled-back qualification inputs also refuse. +Never delete floors to make readiness pass. If the store lost committed replay +or budget state, continuity is unproven: quarantine the restored deployment +and rebuild authority/connection state under owner review; do not serve old +operations as fresh. A newly created host without a floor cannot prove that a +database is current; recover its floors before starting it. + +For each response-recorded or unknown operation, use `reobserve --state-dir +... --operation-id ...` once. It uses the stored plan and a fresh read-only +check under the declared capability. Confirmed evidence may advance the +record; missing or delayed evidence stays unknown. Reobserve again after +visibility returns; never issue a new provider write as recovery. Keep the +opaque operation digest and stage only in support evidence. + +## Rolling upgrade + +Require attestations for each candidate's exact binary/semantic closure and +platform tuple. Disable new writes, drain each serving host, capture bounded +support bundles and floors, and upgrade one host. It must derive the same +recipe and connection generations; the old host must refuse a changed binding +rather than choosing a stale credential. A binary without a current exact +tuple attestation stays disabled. Validate doctor and read-only reconciliation +before replacing the second host and enabling. Do not mix obsolete store +schemas or interpret restore as replay continuity. Keep expiry and revocation +updates running during the upgrade. + +## Independent operator trial + +Give a person unfamiliar with this implementation only the signed packaged +binaries, packages, public configuration and this runbook. Record participant +identity/role, artifact digests, dates, timings, attempted commands, redacted +reports and defects. They deploy both hosts, diagnose an unavailable credential, +rotate, disable during outages, restore with retained floors, reject a stale +restore and reconcile unknown without a write. Plant canaries in excluded +sources and scan the actual support archive. Fix every blocking defect and +have that participant rerun its failing step. The implementer cannot supply +this participant result; a simulated SDK onboarding pilot is separate evidence. diff --git a/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md b/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md index 1df15df06..e7e5df3e7 100644 --- a/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md +++ b/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md @@ -1601,3 +1601,24 @@ submission-driver, persistent-store, credential-lease and counting-provider observations into replay and lost-response recovery stages. Hosted verification of these additions is pending; no live qualification or owner trust ceremony is claimed. + + +## 21. Epic 4 implementation and remaining acceptance (2026-10-06) + +The operator-polish branch adds a bounded canary-scanned support bundle, +typed production doctor report, store-only emergency disable/revoke, separate +operator-process rotation under its own workload identity, graceful listener +shutdown and a durable host generation floor. The floor rejects an older +restored connection or changed bytes at an accepted generation before lease. +The maintained systemd deployment reference is `deployment/gateway/`; the +operations and independent trial protocol are in +`docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md`. Hosted verification is pending. + +This is not Epic 4 acceptance yet. A live two-host reference exercise of +workload identity, firewall, PostgreSQL point-in-time restore and the runbooks +remains, as does the independently performed unfamiliar-operator trial and +its defect rerun. The implementer has not simulated that participant. Epic 5 +also lacks the owner's offline root ceremony, protected signer secret, +two protected provider environments and human release review. On 2026-10-06, +GitHub environment/secret metadata confirmed no qualification signer secret +and neither family live environment. No production recipe is qualified. diff --git a/product/runtime/auths-gateway/semantic-closure.json b/product/runtime/auths-gateway/semantic-closure.json index 30d891a49..dc9ce118e 100644 --- a/product/runtime/auths-gateway/semantic-closure.json +++ b/product/runtime/auths-gateway/semantic-closure.json @@ -1 +1 @@ -{"files":[{"path":"Cargo.lock","sha256":"c94ed342774d5e2823f01ecf74b8a4812c5f9a6b0cf811d31f2e2cecb671a275"},{"path":"Cargo.toml","sha256":"6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24"},{"path":"core/adapters/auths-did-keri/Cargo.toml","sha256":"86ba3e3f9a0a70d970568bfb3113b7ba7bbdd81c3eebbb52743dd574a0c0ecaa"},{"path":"core/adapters/auths-did-keri/src/lib.rs","sha256":"a75674842f8a7142004369ccd206ab43e476459293f0ff4bed4d4e659031b3e3"},{"path":"core/adapters/auths-did-key/Cargo.toml","sha256":"d5a3ae07ecde83f91eed4c3785051dd0f44eab6c891754f3309b6b40596707d7"},{"path":"core/adapters/auths-did-key/src/lib.rs","sha256":"b76a3f4528a725df53cfa9242e6e414e1d26caa48468aaed497e28b121f4497c"},{"path":"core/adapters/auths-raw-key/Cargo.toml","sha256":"f49616bc18c19e6aaa7e6a02ccebcdb9f5c1422c1278ef9869e0dbf22ceda7be"},{"path":"core/adapters/auths-raw-key/src/lib.rs","sha256":"45eec1b295dac3bed65cd79c942870b926b06b3f5d38eaebaeb6140ac69315fa"},{"path":"core/crates/auths-algebra-kernel/Cargo.toml","sha256":"0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba"},{"path":"core/crates/auths-algebra-kernel/src/generated.rs","sha256":"ae4bcbef42a408c7ffa0c6a74a42f7de177a6f14479e51d205acf830bda05960"},{"path":"core/crates/auths-algebra-kernel/src/lib.rs","sha256":"6654667eeb9b353d6648954c9fd2e8838462a82ce6b2803eb49e1366892c68c6"},{"path":"core/crates/auths-assurance/Cargo.toml","sha256":"afcb12a97ddd09d7a264b9ecd3fcaefc865ff2c9b4539ee85b00883420ba333a"},{"path":"core/crates/auths-assurance/src/lib.rs","sha256":"0fb2ec844d674b25a9e20b1601452c89c2454901fa506adfa9bb38ef9a7fa213"},{"path":"core/crates/auths-author/Cargo.toml","sha256":"1e6f0e3bc079ddb558decf0db26b291c6e72fc47327b6df1b7650d41689b215f"},{"path":"core/crates/auths-author/src/lib.rs","sha256":"e14475f2f49715a1869d5fa6b11ff1fbb72497e39097e09f833b0bae7e5b3f2b"},{"path":"core/crates/auths-author/src/observations.rs","sha256":"dda7d6bfa6f4bd7e95a480ca283c2c0e996f69c5c15cb0c7197af328131a7066"},{"path":"core/crates/auths-authority/Cargo.toml","sha256":"4f68212938029f79ebd857b4f3038494eb85d0163d49f07e51376715cf959815"},{"path":"core/crates/auths-authority/src/lib.rs","sha256":"da88d5194de4e17449e69972c0fb042afa3c39798a8f570f30771e77c384f1eb"},{"path":"core/crates/auths-codec/Cargo.toml","sha256":"e20e51826e17814effd9d8925d18d5fbdd6c0d37bf50231e743ec2611314722c"},{"path":"core/crates/auths-codec/src/approval.rs","sha256":"fbff43bf4d57f69f8b7738a8647751cde75c5a932dee65d924a1fe9c7202f91f"},{"path":"core/crates/auths-codec/src/bounded_policy.rs","sha256":"d21f6728be2d8a04b6d94921f2b683f7e61cbb42e0ac6866f1c88a49caa534c3"},{"path":"core/crates/auths-codec/src/decode.rs","sha256":"ba2999584cdf53b1b517ecb9c7ea50d39efee17c666a9a38e2ad1ac94379f778"},{"path":"core/crates/auths-codec/src/encode.rs","sha256":"8491192053e2e15d62b4d2a491de22405b7487ead69ab6f6bca40669ce7ca5f7"},{"path":"core/crates/auths-codec/src/error.rs","sha256":"fecb0737c16deb42d859f1dc7727c698438d9ac12064fd99e0024629642c390c"},{"path":"core/crates/auths-codec/src/hash.rs","sha256":"f88e111f1dbb2cef6b7b5e9c948cb45ff92e366710c8a5f5c636138aa748479e"},{"path":"core/crates/auths-codec/src/lib.rs","sha256":"3b0e5c94c6f34f750b88a9333e1d5c8145746d845d3a23e0d2f61807cf592ea7"},{"path":"core/crates/auths-codec/src/observation.rs","sha256":"38328b0c71ff97a4196eeade8b4faa889527ff1f80bb168468bcd49082a3987e"},{"path":"core/crates/auths-composition/Cargo.toml","sha256":"331e13025eb82588b5269ed3975929eb41c823d588c49e4c296273d85c6fe80e"},{"path":"core/crates/auths-composition/src/lib.rs","sha256":"e42e3b0b6a9985b73c533aeb23799c638979aa27a9ce7d0f10a8d60340570fb1"},{"path":"core/crates/auths-model/Cargo.toml","sha256":"565c15302b0cc9270db1e28efa3862804846850ba933cc17aea8abcec4a65987"},{"path":"core/crates/auths-model/src/approval.rs","sha256":"54cf44a9ef747ec21546a4086aecfb130bc7803b0d646430e6082df51e6e305f"},{"path":"core/crates/auths-model/src/bounded.rs","sha256":"f90496abc0a06c028b4d850af6ddab7d850bfafeaa3d042f1b1246a41d8bbbc9"},{"path":"core/crates/auths-model/src/bounded_policy.rs","sha256":"306a8f049cc7cfc7635fe0e4de47eb7813eed63d3c14c3be2b51586aa4eea450"},{"path":"core/crates/auths-model/src/lib.rs","sha256":"e7cfe6bb9574c6b016aa63e70658c31e0b90903ec6479a49f4a2ceb64f5bad97"},{"path":"core/crates/auths-model/src/observation.rs","sha256":"b3ed3e3cc090afca2896a7d3de7988afccc1ee1ea0ebd91b51a8bc0f20ad8dbb"},{"path":"core/crates/auths-multikey/Cargo.toml","sha256":"858756c1197befcada06134742bffe8d58cf674cadd6c046bf710570e96efaf2"},{"path":"core/crates/auths-multikey/src/lib.rs","sha256":"f5177fffb11e40eeaaa665ba886c541fc1f24d5eacdd6983fb03dc20148733f0"},{"path":"core/crates/auths-ports/Cargo.toml","sha256":"596a9b0f5af3717c16a6d13f7054d8a106bcd9f01f5f72c2235dd2afcf0ab16c"},{"path":"core/crates/auths-ports/src/binding.rs","sha256":"a16c012d40aa4249e3ec54372b9611006d0bfe8c7dc3c741911c2194ad17736d"},{"path":"core/crates/auths-ports/src/diagnostics.rs","sha256":"aa596572503b5a65a918bb2ff38281c144ff53821ee914e9325c852828d852df"},{"path":"core/crates/auths-ports/src/lib.rs","sha256":"8da1debf86f9532df0660155d04298beb1ba3a1204508f8586e2e67cd2fb3449"},{"path":"core/crates/auths-ports/src/path.rs","sha256":"b68fc547b4e4d97a60cbbc1cc1939fc6b34a8233b81f840bd396914a707e3ea1"},{"path":"core/crates/auths-raw-key-core/Cargo.toml","sha256":"98c0bc8527a537512e43a74dd6ba9658c6f0cdc16610cf938e3f9b43785d836d"},{"path":"core/crates/auths-raw-key-core/src/lib.rs","sha256":"98c0500c41697aae28708ad0bf970b9a97583d96a3d2c18d23e7fa351e0f7d12"},{"path":"core/crates/auths-registries/Cargo.toml","sha256":"590e49e58b0622d9d6274fea46796dcdb07dec9550eff295cce6a6427ffa51e2"},{"path":"core/crates/auths-registries/src/lib.rs","sha256":"450d3886d85ee333b7e046317fb5b47cde62483d5f3e41d46265e2caf4c373ec"},{"path":"core/crates/auths-registries/src/template.rs","sha256":"1224039dd2b3ce6fa8357613d8cafbae40400493da7176da202b9ade62fa05e4"},{"path":"core/crates/auths-signature-core/Cargo.toml","sha256":"6bee2230eb30af1be0bd5c2d57bd3e1903497a70028d47290d4ac6e9e0e8bca0"},{"path":"core/crates/auths-signature-core/src/lib.rs","sha256":"6e3f9311ded5e49ea50d445eb21e6d8fa12442aa4362a73e0cb6fda15b7cd865"},{"path":"core/crates/auths-signature/Cargo.toml","sha256":"7f7b5682466ba439d8c59579022cb61068cad9fb4bd2d73e1cc21327c902b450"},{"path":"core/crates/auths-signature/src/lib.rs","sha256":"b3d9ac4cc3ba0797b9e1c09f2d6ac05089b25dac4e285a5af28c0165b33d925b"},{"path":"core/crates/auths-verifier/Cargo.toml","sha256":"c43358e06a33324b41a8b93e5cc7279c55f7d21f1f6cfaa539a3fc7b4c27a38f"},{"path":"core/crates/auths-verifier/src/approval.rs","sha256":"c3cae6a49e169051eb555bb092b1069a4d422516d6a2114623a89e5f31ff923f"},{"path":"core/crates/auths-verifier/src/causal.rs","sha256":"9635230f33b13a263573d319ac8a1976addbcc07677514a43e3c7bf28dc04587"},{"path":"core/crates/auths-verifier/src/lib.rs","sha256":"f22dec38dfa47ced8da4f605390da8453273bee1da010f57fd1fdfcb10e0b389"},{"path":"core/crates/auths-verifier/src/observation.rs","sha256":"0bb07f06a0f9524c88427df1c972b1de8ba038a9eeeb15d3134c25125ae84b1e"},{"path":"core/crates/auths-verifier/src/trace.rs","sha256":"2213d72023a1d9e0413a2cf2c51c3dad9e04775d86033a0caaa9d29a8f0036f8"},{"path":"exchange/crates/auths-proof-exchange-model/Cargo.toml","sha256":"34b2db64f93a288e942b5a3918d28cdcbef906e0dc9074ce848018d3d5f7a1fa"},{"path":"exchange/crates/auths-proof-exchange-model/src/lib.rs","sha256":"49fac5aff2339d3a57c41cb8bb2a82852538e8f77ecc4b157c88e264ff31fb55"},{"path":"exchange/crates/auths-proof-exchange-port/Cargo.toml","sha256":"7ff660f1b7579dc570c791090aeb450404fbbf44c92781e289f5ccdde746d739"},{"path":"exchange/crates/auths-proof-exchange-port/src/lib.rs","sha256":"b408fb40c6432edc1facb3d8b3e9433a033f8dc73fe2e0ba5a88c972ca675021"},{"path":"product/config/auths-config/Cargo.toml","sha256":"e4b568ab9f6d84f7d7e6d66443fe825f360db9c27bc7c31d6ddc0647ba3ab304"},{"path":"product/config/auths-config/src/lib.rs","sha256":"fecf00ea65cef9018fda9af2063326d7065b869266d0d9e73a4f06816f1102cc"},{"path":"product/errors/auths-errors/Cargo.toml","sha256":"3b3a199b6460ba75bda84475bb5accd35e1485448a3981038db85bf4772dd350"},{"path":"product/errors/auths-errors/src/lib.rs","sha256":"7feeb9069fa4003f94f1f07c1c94619cf1c883e0dbaaf2187f04d0f742264bdd"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/Cargo.toml","sha256":"716f1f2a117d6d69d8effe9ee9057e24ba3502f20af6a602b06facb638cdabed"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/api.rs","sha256":"b3c4321e0737835ecc4f17235d7589b7f3d62180954ebb98ea9449252300245a"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/clock.rs","sha256":"73f0a6e0f5903883329fa6683f5888288f759512ac69e5c87efd2b6b87f7d79f"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/http.rs","sha256":"14c1fce14e24c984b2a275563a29b6326fb08367922b6e8d37ba38b9cb81aa2b"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/identity.rs","sha256":"186de11230c8b33375951c4368609f8976bf9795f171af3fd7fac26207a94361"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs","sha256":"881ad9ccca369b6eaa6bfd9ec03b1585bff07b042da38942ef57154839449d3e"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/names.rs","sha256":"41bb23572d6002e23ee103d6fe70ecd68764861c6f2e48a1c53af998270a4afa"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs","sha256":"39fed883f4802e68d3b41a68fea0aba0737810996b33d13577de70faba004c29"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/store.rs","sha256":"32bb4b7ff3e7769d0ff46d374f80e4a2c44d7f8e8e82bbea58c9676690db45bb"},{"path":"product/integrations/auths-custody/Cargo.toml","sha256":"1e14034185ad1ec24a977fd5f41d0abee219606245c046ce2a82287fadef448b"},{"path":"product/integrations/auths-custody/src/conformance.rs","sha256":"8ed1afd58f18fc6becc268908aa6419c9aa404c79da0197963eb2599df44acf6"},{"path":"product/integrations/auths-custody/src/key.rs","sha256":"70cbb0fd21b6f5652157845a22c35be2d0f6c05b3d138fc4b9bb6dbdc3d81c40"},{"path":"product/integrations/auths-custody/src/lib.rs","sha256":"8ee593c1f59b0fd2126bdda9138026f5bc531beb64d4489a99785842e7b98b43"},{"path":"product/operations/auths-operations/Cargo.toml","sha256":"73dde1e914ba5e1386f8d49c0d730423cc72ae77ec44c6554a6a75cc8e8922b1"},{"path":"product/operations/auths-operations/src/explanation.rs","sha256":"b4a39bcbd5712cb9e735ee7deeb281f3fa6af5ddca973735bf3d87dce427ef11"},{"path":"product/operations/auths-operations/src/lib.rs","sha256":"3f401a56555113b98f57bca172a2660eaecedf76247b83a3fdbb089c133a29cd"},{"path":"product/operations/auths-operations/src/render/json.rs","sha256":"2ae042639960afee123730e945d373bc5dda1d2b3af20ae16c939a7e99b9e418"},{"path":"product/operations/auths-operations/src/render/mod.rs","sha256":"b3b7f6fe473f49227ace5a68bfc3d8dc14b5db8dd9888fd9e207070337b1b8bf"},{"path":"product/operations/auths-operations/src/render/text.rs","sha256":"f216cf3bdb00e264523271b16e7059535ac6b1aabf271cebd7935af155e4bfec"},{"path":"product/policy/auths-bounded-policy/Cargo.toml","sha256":"babd5d200923137ead71d8c2528f847cea323ce98da942a1320b054436612c47"},{"path":"product/policy/auths-bounded-policy/src/arithmetic.rs","sha256":"75e43c5d4eab8d1f71c1daf53839f5f9fe45a400afc1f63a30c6f55ce3632627"},{"path":"product/policy/auths-bounded-policy/src/commitment.rs","sha256":"c5706f2d583454e1a7f570f7ada138d4d864bef0205dfae7c1296774f396bb3f"},{"path":"product/policy/auths-bounded-policy/src/eligibility.rs","sha256":"c9acdfb793074e687fc36efad506be27dbd99ffbf40387bc66c8de39ef238432"},{"path":"product/policy/auths-bounded-policy/src/identifier.rs","sha256":"0006a32bae9eb16c4178cf797df418d2b0a781f2bc6474b741dc1a908141831c"},{"path":"product/policy/auths-bounded-policy/src/kernel.rs","sha256":"99187c28b161ac70bee1afed60711f7f645adb4d1671a01863f9849b369811d5"},{"path":"product/policy/auths-bounded-policy/src/lib.rs","sha256":"76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c"},{"path":"product/policy/auths-bounded-policy/src/receipt.rs","sha256":"3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad"},{"path":"product/policy/auths-bounded-policy/src/registry.rs","sha256":"4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0"},{"path":"product/profiles/auths-profile-api/Cargo.toml","sha256":"7ae85761f58625b5d678f961fd052eebf3e000ef565c7312e3ac857763c0017f"},{"path":"product/profiles/auths-profile-api/src/lib.rs","sha256":"a194b82b20bf8aa864c2334ef6c6aec30b2154ded972862252d5dcefa488ab95"},{"path":"product/profiles/auths-profile-mcp/Cargo.toml","sha256":"db264fc25242f7b7e4133cbe5782545b3107b406c87168ae072683cfb59eac66"},{"path":"product/profiles/auths-profile-mcp/src/arguments.rs","sha256":"a5de696586d507e2aee4a49fee99ef1ef4c51a2e46603f8838f1af6d9009833f"},{"path":"product/profiles/auths-profile-mcp/src/lib.rs","sha256":"d0f8b733a09ef8408336cdebc8948d6a5861012ce6878598b11be7084dfd4280"},{"path":"product/profiles/auths-profile-mcp/src/session.rs","sha256":"166c281fa66333388e4760d6098dad02d3359e1d5de4b8f93312c014f97abb03"},{"path":"product/qualification/auths-recipe-qualification/Cargo.toml","sha256":"b7b15b30b9a3d96d4f089d514266d3a892de6608d30707aa44be31cca89ca9fe"},{"path":"product/qualification/auths-recipe-qualification/src/canonical.rs","sha256":"30a9b50777f0dcb4b606abfee2467d5a975d9f6ad941ab6c13ca3df5b359f667"},{"path":"product/qualification/auths-recipe-qualification/src/closure.rs","sha256":"0ad6aee9bd981e2863fa725f209ec84031db2ff12f4c7ac3aaf5120f0bb86039"},{"path":"product/qualification/auths-recipe-qualification/src/error.rs","sha256":"52d5cf720a1e4579008fdda90a3ac2c31f0b8db57985f121f65e54b4da2b7dd1"},{"path":"product/qualification/auths-recipe-qualification/src/evidence.rs","sha256":"1a4cb862f725b02f9efd827db99637ea8178a5236aa020ec271a363edbe7b362"},{"path":"product/qualification/auths-recipe-qualification/src/ids.rs","sha256":"e81a906d571497ab2da753e1532d4443706410e0b75fdd59a7d2d788c7aec403"},{"path":"product/qualification/auths-recipe-qualification/src/lib.rs","sha256":"195b19f46e1e94a0f3594ad5958e5715bc5e3ad415bdfe6428dfc1b6dd3f4631"},{"path":"product/qualification/auths-recipe-qualification/src/model.rs","sha256":"3484eb0ec287b23d4682ade7b1b0f8d1335985b3fb180f06fc28716076957d5f"},{"path":"product/qualification/auths-recipe-qualification/src/release.rs","sha256":"d816b53e2275e902c750ad03803061844e259e28560ab2d1c77e8a43981a4d6a"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/mod.rs","sha256":"7f15b68e05a04f202bcb1fb80de1d9a9a4fda8bfd6af2cd4e5c660fc75d96fe5"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/schemas.rs","sha256":"c59feec2805621f341a90f81fc005e2c12f7a70f9d264fdeacccb2be4fe1c046"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/verification.rs","sha256":"6a6b5834c5dae10af1ba8939b2deae43b85db71544dc8f077ff63b7fe68ac8a8"},{"path":"product/qualification/auths-recipe-qualification/src/verify.rs","sha256":"edd33589c54fb79bcfccc4cf4e6ccf95bbca088318bb7f8dfc27da684b4fa671"},{"path":"product/receipts/auths-receipts/Cargo.toml","sha256":"6001fa1375899953aafcb07c23a6da0c8f57ea7ec08bb9c950b12a60a8cc6f0f"},{"path":"product/receipts/auths-receipts/src/disclosure.rs","sha256":"ba9ed439be0a320c8a01f5b6e9b51361c1a37e076947490d8e4a484ba6bb119c"},{"path":"product/receipts/auths-receipts/src/lib.rs","sha256":"547a57c4160256719cafb7d0ab972d9fc80b0da14fbbce4148c70c414070ff36"},{"path":"product/runtime/auths-connections/Cargo.toml","sha256":"babeb6e1dda3dfb66291713ce1e43dce5c349833d0b50ea4dccbf986030026b2"},{"path":"product/runtime/auths-connections/src/credential.rs","sha256":"4d532c221d2fe7a2b47c8720be94c26d0c86a0448c3f66f479ce3b12adf44f25"},{"path":"product/runtime/auths-connections/src/kernel.rs","sha256":"a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8"},{"path":"product/runtime/auths-connections/src/lib.rs","sha256":"79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22"},{"path":"product/runtime/auths-connections/src/model.rs","sha256":"de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77"},{"path":"product/runtime/auths-connections/src/registry.rs","sha256":"e57640e003e72ad3235c567c2bb944a262bd64e673f023b62ea091094cc7e946"},{"path":"product/runtime/auths-gateway-kernel/Cargo.toml","sha256":"34f864e67656af4ac7e5c7a347a23f01fc8ab31365b8e23c0ef474483b14a183"},{"path":"product/runtime/auths-gateway-kernel/src/construct.rs","sha256":"e9d65744bae273d65face4285e5d2da75c06a92ab48f7b8333d496604e31c63c"},{"path":"product/runtime/auths-gateway-kernel/src/lib.rs","sha256":"cfda6f8453426564c085475f183b6f790b438768a19668f1b65d33ba59dc8632"},{"path":"product/runtime/auths-gateway-kernel/src/order.rs","sha256":"e0045f877c4b7fe3860c291039853885064ddcdebba7c9b345ab65e81e646dda"},{"path":"product/runtime/auths-gateway-kernel/src/outcome.rs","sha256":"e9785b1afe70788c89b51b18655bcd5acff7b0c8e3d12fb79c6f05a202e67e6b"},{"path":"product/runtime/auths-gateway-kernel/src/ratio.rs","sha256":"7ace22264812e6fc1ef3a62afee402cf43494bb71ae0d3de219ad1b39d690bcb"},{"path":"product/runtime/auths-gateway-kernel/src/recovery.rs","sha256":"9f46dcd1685ab6e4d1ba04a3fc286a9f3afee8fb47829be1fbc670a7926a2dc6"},{"path":"product/runtime/auths-gateway-kernel/src/transition.rs","sha256":"cefb8f01d915880f6921f2501ff881ad94b9de61072c34d9cd19220992f97374"},{"path":"product/runtime/auths-gateway/Cargo.toml","sha256":"00b28be86921dcdc0ad90cce0c62c2961cafefe96ea6c2edf0e926c3d405ccad"},{"path":"product/runtime/auths-gateway/src/admin.rs","sha256":"2d5cc67afac42fbd15f36e2d1693cd1b20cedacf775040dce6ffe04ccc94c9ea"},{"path":"product/runtime/auths-gateway/src/app.rs","sha256":"6f80f63833ea0815bb44fbf3b0cc54624a08e9fb578b035819f2980dc04e8256"},{"path":"product/runtime/auths-gateway/src/audit.rs","sha256":"0edb2037eb7b5d6f13acfce85c54f62a82bf7fdd31bc7e626c4fec183cef61dd"},{"path":"product/runtime/auths-gateway/src/audit_tests.rs","sha256":"990969384a52d75bc2489d9d412a9e7dd814bca1c8f65c701d6205fae62a15d5"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway-harness.rs","sha256":"12b0c24d36b2e6a3be392d3c081a783b355fdd67dc5b54bacc0410e803116b8c"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway.rs","sha256":"112969ee1e833d979dc44cfb2f7fc203a495ddbc93913c3d0359f76162a97740"},{"path":"product/runtime/auths-gateway/src/binding.rs","sha256":"663b0ce878319511aa7d05722ab4ab2fa9be18817884ffb2ee9f131ff1e382d1"},{"path":"product/runtime/auths-gateway/src/bounds.rs","sha256":"9cfa0eae4973e5e047a198360b22f041708fa20276b0b90c2ec440f06915d64b"},{"path":"product/runtime/auths-gateway/src/bounds_aggregate_tests.rs","sha256":"ab34f227b7c8692ba1da88ccb32bb3687a66adf8353d8282fae905d4a88eb612"},{"path":"product/runtime/auths-gateway/src/bounds_tests.rs","sha256":"74136bc570da7b9338b5a1a1ed9d3fd892c55135160964f9d3ac0e2cf5741375"},{"path":"product/runtime/auths-gateway/src/connection.rs","sha256":"1f81f5b1305188176c38090c99b6f8f96e01fef80aa4461813be1c893d9caa8e"},{"path":"product/runtime/auths-gateway/src/echo_verify.rs","sha256":"6d453051665f823abd7354d5c50031d9524cf47d6092d2f09080ae814e3b9575"},{"path":"product/runtime/auths-gateway/src/engine.rs","sha256":"03d31841f05b957fa5530a135ab609673db38c14301f088938c4c1d94a78537d"},{"path":"product/runtime/auths-gateway/src/fuzzing.rs","sha256":"ed3b0028487eb546a3b0a91d115aa8f18bcea324b61620bfe8e35a9e6ab18758"},{"path":"product/runtime/auths-gateway/src/harness.rs","sha256":"c87e479f3eb281960f6c9c80d43c7560d7ccb654b0154ec823d3fcec4884ac05"},{"path":"product/runtime/auths-gateway/src/lib.rs","sha256":"25cd21174c49d811471f9b67dd2b5da0f1bed58ddf6f5799cfd9121821556875"},{"path":"product/runtime/auths-gateway/src/listener.rs","sha256":"aa08239bcbc1fcb55e8a212fbdf6a84f12985b0d436dcb51dc58b06e59e435f2"},{"path":"product/runtime/auths-gateway/src/observed_tests.rs","sha256":"a22be071695f89ca2578a4d82fd80d9cb82289213c9bdb8f0470f6b2dc3d9201"},{"path":"product/runtime/auths-gateway/src/observer.rs","sha256":"562ffcaea071c3856e0708dc2fe33516917e145d2438aabb75af0a2b6ba01046"},{"path":"product/runtime/auths-gateway/src/onboarding.rs","sha256":"0dfd7d67e7f02f18a28d1c86ca1b7751d7463f5efcdbe3825de0ad8cbccb3891"},{"path":"product/runtime/auths-gateway/src/operator.rs","sha256":"c3c36954a3e86723df035b47f43b85fc8ab3a6292983522b6258d5c6b4e6c4e4"},{"path":"product/runtime/auths-gateway/src/pending_vectors/attempts.rs","sha256":"47ef3c8cb1c5504d47ae9a0088705ce6715fe86bac1671a34a56fb38a64d0dd3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/bounds.rs","sha256":"e612217307e1da5b0eb5ee6582a7458bb064b8aa8a529fc6555b1b334127ab68"},{"path":"product/runtime/auths-gateway/src/pending_vectors/codes.rs","sha256":"e00670a5ef24eb856cc2c6dcda8e5a263842f55c76bb939c0c27bd9df37e5522"},{"path":"product/runtime/auths-gateway/src/pending_vectors/keys.rs","sha256":"f84c56f2ea9cb34b2b79c72d13fbf2c6585010ec1ed450af58a78c80c1ea1edd"},{"path":"product/runtime/auths-gateway/src/pending_vectors/mod.rs","sha256":"5de8340f0ef71a0b57a09e323fefe473d3160c6ae952b9ba46f714825fbacafc"},{"path":"product/runtime/auths-gateway/src/pending_vectors/outcomes.rs","sha256":"8ec07b9511b48913af36ac999d2aa0e82924289f6acb23ddaeb9f00f99815166"},{"path":"product/runtime/auths-gateway/src/pending_vectors/production.rs","sha256":"c42c1a893ef6e74aef074f0644a8d3e3f9394258c0f3d689abd1f19aa5ddba61"},{"path":"product/runtime/auths-gateway/src/pending_vectors/recipes.rs","sha256":"51693208270231c25c3aef2a32151d5962114c71e86b88cb9df83181c7af83d9"},{"path":"product/runtime/auths-gateway/src/pre_entry.rs","sha256":"06ea78ca140468bfaba17d9ab04912ad68673954c3203c98fed28272ff2a00c0"},{"path":"product/runtime/auths-gateway/src/property_tests.rs","sha256":"939c081e2e154aaf10186754044bdd65608932c899b970a04a71d0afaa999a93"},{"path":"product/runtime/auths-gateway/src/qualification.rs","sha256":"a4398512ccb7bb494000fe38f03e0faa7b82d1f80ef5ee2dfa75698ae4f5a9be"},{"path":"product/runtime/auths-gateway/src/qualification_tests.rs","sha256":"4473add5729b97faf04d7be7fd8cf3bbacd7f545e1b61c7d2782563011906b4d"},{"path":"product/runtime/auths-gateway/src/quorum_tests.rs","sha256":"a78380b019104d688c11a4410082c7e08ded3106aab099954c4f8a1b4ae0fd89"},{"path":"product/runtime/auths-gateway/src/readiness.rs","sha256":"9e98b19d0c68e84c778bf5565bd1e37899bff95ff8d05d329cfb48f00b246dc7"},{"path":"product/runtime/auths-gateway/src/recipe.rs","sha256":"fecf9af67e7afc48d080e9f8f55f8ce28e49d0e08988717a27908bbda461d6b6"},{"path":"product/runtime/auths-gateway/src/recipe/lower.rs","sha256":"8088b8751ed831dbb48247af953c6290ac95e2a438ccd5bd65eff54be06a1fd1"},{"path":"product/runtime/auths-gateway/src/recipe/review.rs","sha256":"c3eb7d9fdd98dacf52750b14b67ad7b7faaecbbdeafff1e0b049f67d0a2d0139"},{"path":"product/runtime/auths-gateway/src/recipe/runtime.rs","sha256":"c286f0d15f974402822c0810d8e97f98411dc1c557755cc23e540d85e2bb42d9"},{"path":"product/runtime/auths-gateway/src/recipe/source.rs","sha256":"1af50298fb1461e1b24cbdf560d43124d6b1c4c529586c911b1c4797214a69ff"},{"path":"product/runtime/auths-gateway/src/recipe/tests.rs","sha256":"aac551a2481bbc60864c64079bc667dcb232e45a0f41a04073ed84ab5dbe1fce"},{"path":"product/runtime/auths-gateway/src/recipe/validate.rs","sha256":"3711b17605cb7b0d639bc1b180449231f5882a306cab20e2c7782155cc63b0d4"},{"path":"product/runtime/auths-gateway/src/scenario_tests.rs","sha256":"e342ade2cb08a686cb00c29a7d6153ae3d8c350d5a7d6a115311d96ecef97c35"},{"path":"product/runtime/auths-gateway/src/separation.rs","sha256":"be9306848ca5d801767cf6aa14247c8618312ef0e202f00ce0c24c4844491061"},{"path":"product/runtime/auths-gateway/src/store.rs","sha256":"786bc4b58391eb4330a3a6c4ba224f0b3c9ff3ad619cb7a27f2699c152f42b92"},{"path":"product/runtime/auths-gateway/src/store_testkit.rs","sha256":"88d82fee42f1b8ef521e8deef0216e938ebeaad822eb2f5020e70b89d145ea70"},{"path":"product/runtime/auths-gateway/src/submit.rs","sha256":"c78dbbba7c45b443febf655056c5edcd635e77be7b21c5b2c318097502415ffe"},{"path":"product/runtime/auths-gateway/src/transport.rs","sha256":"be2c6dc75b8daec110bf8749fedc3823f6067d40b999aa3eb21126896a97d3ad"},{"path":"product/runtime/auths-kernel-runtime/Cargo.toml","sha256":"926bcd0053e5edd703be8f0027ad009e2982db013c8174c1366edbf38b48087d"},{"path":"product/runtime/auths-kernel-runtime/src/lib.rs","sha256":"7108faae9ca4bc32dc093ddaf885ac8f74f3c9b8d317b7c7d0ed00d1d0ab5972"},{"path":"product/runtime/auths-lifecycle/Cargo.toml","sha256":"c5053c705f8d5554b44e432fe75287a2faf11d644e5a2552e45ad6cd94176af5"},{"path":"product/runtime/auths-lifecycle/src/codec.rs","sha256":"51c4b746749150e8bfcd8ff972b3f6c1ef40bec15583448ec1b471d9ad737dc0"},{"path":"product/runtime/auths-lifecycle/src/digest.rs","sha256":"55282cd7d8aba37713c2dcb5357c9877819edb72a30eadefb860d28d7d3a3eb7"},{"path":"product/runtime/auths-lifecycle/src/identifier.rs","sha256":"31620e8c16de68d3d2d3b84d6353c1a5b9d4151d8247f91fa389b906a8e660f1"},{"path":"product/runtime/auths-lifecycle/src/kernel.rs","sha256":"2abb8c094b36d35b364e74d78091d14c5d6f3d1eb6552cca3b5538dbd017ce23"},{"path":"product/runtime/auths-lifecycle/src/lib.rs","sha256":"afe5a345cd309b5a4f08ffba3170a6d7f16ff914892b3f2006d5208ed24ec736"},{"path":"product/runtime/auths-lifecycle/src/model.rs","sha256":"1af12bbeeeaa65ec02ddcebd7d2c8c92ec1e339fa40ae85b45ab9b01a722a4fa"},{"path":"product/runtime/auths-lifecycle/src/operation.rs","sha256":"78e6d05fcf5d7ea4f148032a3fa26fdfcab77eb346019effe927b08e0d64d732"},{"path":"product/runtime/auths-lifecycle/src/registry.rs","sha256":"53495fe6f7a77422593a41623e28716f1c140dcc1e00f87f6b0ffbfb93a5ef90"},{"path":"product/runtime/auths-lifecycle/src/sealed.rs","sha256":"2e0c03b5813c926c159598bb7890d1523825edbe57cd687d42a5dfb3374a0c19"},{"path":"product/runtime/auths-lifecycle/src/test_support.rs","sha256":"221d9a5c5ef8e1f9f8fd66927484eaf813571d0568470278ecd8fa08a5eec8cd"},{"path":"product/runtime/auths-lifecycle/src/transition.rs","sha256":"011805a28efdd541f44ccea54dd0e34a1e58f4004447ee58013703b4fb6b2822"},{"path":"product/runtime/auths-runtime/Cargo.toml","sha256":"dd29d80a8b4bb56c869f036a6c9998f6e6d1c0383ac5dc03fa42b24abe2a7ff7"},{"path":"product/runtime/auths-runtime/src/lib.rs","sha256":"132ca03d58c14905d3a822a4972f42a22a5ad33a45f2ba9ca44f3a57d810b4b0"},{"path":"product/runtime/auths-runtime/src/production.rs","sha256":"fd4eff4270c571c10fcff6cf27df28961ebf074de8a1a028f500fda1ca376820"},{"path":"product/sdk/auths-approval-quorum/Cargo.toml","sha256":"df904971fca87a24194c5816738a331588fe8f164acb5d70839a35dca5f57114"},{"path":"product/sdk/auths-approval-quorum/src/lib.rs","sha256":"72e4086088a1c0912e4e1a9e980f26a5c280bf5ab16ea39c9f0f58d5096ac2ce"},{"path":"product/sdk/auths-approval-quorum/src/remote.rs","sha256":"9fa029c7c63003adf260f8aec55160c545681c60c1bace0d934e7525862aac7b"},{"path":"product/sdk/auths-approval-quorum/src/remote_tests.rs","sha256":"8a09ce17cfee82a035a74edd535f3ebeb3db0e078784740d3997b17dbdb10197"},{"path":"product/sdk/auths-approval-quorum/src/tests.rs","sha256":"0acbf12be3e497dcc6c2d8f29c9af3b1a7ed8e11b75f6399570d4f217a785060"},{"path":"product/stores/auths-stores/Cargo.toml","sha256":"a32c4b76d17b264be5d40d24497ff237e1ed87822e8bab86229b3db93106dbe3"},{"path":"product/stores/auths-stores/src/gateway_attempt.rs","sha256":"7683966d54ceae62dcf68a6f3d4e5fc019ffd3b88216fd30cbcecf980e1944d5"},{"path":"product/stores/auths-stores/src/lib.rs","sha256":"e721262edf8a9ab5568ddc27639176312d4a366203b5f73e2d7c11fde2c554e9"},{"path":"product/stores/auths-stores/src/lifecycle.rs","sha256":"94f64d25bc178a9e60ba3c0ee6915d7fb3af7c4468792d76b4e70f43f4de1e2f"}],"schema":"auths.gateway-semantic-closure/1"} \ No newline at end of file +{"files":[{"path":"Cargo.lock","sha256":"c94ed342774d5e2823f01ecf74b8a4812c5f9a6b0cf811d31f2e2cecb671a275"},{"path":"Cargo.toml","sha256":"6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24"},{"path":"core/adapters/auths-did-keri/Cargo.toml","sha256":"86ba3e3f9a0a70d970568bfb3113b7ba7bbdd81c3eebbb52743dd574a0c0ecaa"},{"path":"core/adapters/auths-did-keri/src/lib.rs","sha256":"a75674842f8a7142004369ccd206ab43e476459293f0ff4bed4d4e659031b3e3"},{"path":"core/adapters/auths-did-key/Cargo.toml","sha256":"d5a3ae07ecde83f91eed4c3785051dd0f44eab6c891754f3309b6b40596707d7"},{"path":"core/adapters/auths-did-key/src/lib.rs","sha256":"b76a3f4528a725df53cfa9242e6e414e1d26caa48468aaed497e28b121f4497c"},{"path":"core/adapters/auths-raw-key/Cargo.toml","sha256":"f49616bc18c19e6aaa7e6a02ccebcdb9f5c1422c1278ef9869e0dbf22ceda7be"},{"path":"core/adapters/auths-raw-key/src/lib.rs","sha256":"45eec1b295dac3bed65cd79c942870b926b06b3f5d38eaebaeb6140ac69315fa"},{"path":"core/crates/auths-algebra-kernel/Cargo.toml","sha256":"0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba"},{"path":"core/crates/auths-algebra-kernel/src/generated.rs","sha256":"ae4bcbef42a408c7ffa0c6a74a42f7de177a6f14479e51d205acf830bda05960"},{"path":"core/crates/auths-algebra-kernel/src/lib.rs","sha256":"6654667eeb9b353d6648954c9fd2e8838462a82ce6b2803eb49e1366892c68c6"},{"path":"core/crates/auths-assurance/Cargo.toml","sha256":"afcb12a97ddd09d7a264b9ecd3fcaefc865ff2c9b4539ee85b00883420ba333a"},{"path":"core/crates/auths-assurance/src/lib.rs","sha256":"0fb2ec844d674b25a9e20b1601452c89c2454901fa506adfa9bb38ef9a7fa213"},{"path":"core/crates/auths-author/Cargo.toml","sha256":"1e6f0e3bc079ddb558decf0db26b291c6e72fc47327b6df1b7650d41689b215f"},{"path":"core/crates/auths-author/src/lib.rs","sha256":"e14475f2f49715a1869d5fa6b11ff1fbb72497e39097e09f833b0bae7e5b3f2b"},{"path":"core/crates/auths-author/src/observations.rs","sha256":"dda7d6bfa6f4bd7e95a480ca283c2c0e996f69c5c15cb0c7197af328131a7066"},{"path":"core/crates/auths-authority/Cargo.toml","sha256":"4f68212938029f79ebd857b4f3038494eb85d0163d49f07e51376715cf959815"},{"path":"core/crates/auths-authority/src/lib.rs","sha256":"da88d5194de4e17449e69972c0fb042afa3c39798a8f570f30771e77c384f1eb"},{"path":"core/crates/auths-codec/Cargo.toml","sha256":"e20e51826e17814effd9d8925d18d5fbdd6c0d37bf50231e743ec2611314722c"},{"path":"core/crates/auths-codec/src/approval.rs","sha256":"fbff43bf4d57f69f8b7738a8647751cde75c5a932dee65d924a1fe9c7202f91f"},{"path":"core/crates/auths-codec/src/bounded_policy.rs","sha256":"d21f6728be2d8a04b6d94921f2b683f7e61cbb42e0ac6866f1c88a49caa534c3"},{"path":"core/crates/auths-codec/src/decode.rs","sha256":"ba2999584cdf53b1b517ecb9c7ea50d39efee17c666a9a38e2ad1ac94379f778"},{"path":"core/crates/auths-codec/src/encode.rs","sha256":"8491192053e2e15d62b4d2a491de22405b7487ead69ab6f6bca40669ce7ca5f7"},{"path":"core/crates/auths-codec/src/error.rs","sha256":"fecb0737c16deb42d859f1dc7727c698438d9ac12064fd99e0024629642c390c"},{"path":"core/crates/auths-codec/src/hash.rs","sha256":"f88e111f1dbb2cef6b7b5e9c948cb45ff92e366710c8a5f5c636138aa748479e"},{"path":"core/crates/auths-codec/src/lib.rs","sha256":"3b0e5c94c6f34f750b88a9333e1d5c8145746d845d3a23e0d2f61807cf592ea7"},{"path":"core/crates/auths-codec/src/observation.rs","sha256":"38328b0c71ff97a4196eeade8b4faa889527ff1f80bb168468bcd49082a3987e"},{"path":"core/crates/auths-composition/Cargo.toml","sha256":"331e13025eb82588b5269ed3975929eb41c823d588c49e4c296273d85c6fe80e"},{"path":"core/crates/auths-composition/src/lib.rs","sha256":"e42e3b0b6a9985b73c533aeb23799c638979aa27a9ce7d0f10a8d60340570fb1"},{"path":"core/crates/auths-model/Cargo.toml","sha256":"565c15302b0cc9270db1e28efa3862804846850ba933cc17aea8abcec4a65987"},{"path":"core/crates/auths-model/src/approval.rs","sha256":"54cf44a9ef747ec21546a4086aecfb130bc7803b0d646430e6082df51e6e305f"},{"path":"core/crates/auths-model/src/bounded.rs","sha256":"f90496abc0a06c028b4d850af6ddab7d850bfafeaa3d042f1b1246a41d8bbbc9"},{"path":"core/crates/auths-model/src/bounded_policy.rs","sha256":"306a8f049cc7cfc7635fe0e4de47eb7813eed63d3c14c3be2b51586aa4eea450"},{"path":"core/crates/auths-model/src/lib.rs","sha256":"e7cfe6bb9574c6b016aa63e70658c31e0b90903ec6479a49f4a2ceb64f5bad97"},{"path":"core/crates/auths-model/src/observation.rs","sha256":"b3ed3e3cc090afca2896a7d3de7988afccc1ee1ea0ebd91b51a8bc0f20ad8dbb"},{"path":"core/crates/auths-multikey/Cargo.toml","sha256":"858756c1197befcada06134742bffe8d58cf674cadd6c046bf710570e96efaf2"},{"path":"core/crates/auths-multikey/src/lib.rs","sha256":"f5177fffb11e40eeaaa665ba886c541fc1f24d5eacdd6983fb03dc20148733f0"},{"path":"core/crates/auths-ports/Cargo.toml","sha256":"596a9b0f5af3717c16a6d13f7054d8a106bcd9f01f5f72c2235dd2afcf0ab16c"},{"path":"core/crates/auths-ports/src/binding.rs","sha256":"a16c012d40aa4249e3ec54372b9611006d0bfe8c7dc3c741911c2194ad17736d"},{"path":"core/crates/auths-ports/src/diagnostics.rs","sha256":"aa596572503b5a65a918bb2ff38281c144ff53821ee914e9325c852828d852df"},{"path":"core/crates/auths-ports/src/lib.rs","sha256":"8da1debf86f9532df0660155d04298beb1ba3a1204508f8586e2e67cd2fb3449"},{"path":"core/crates/auths-ports/src/path.rs","sha256":"b68fc547b4e4d97a60cbbc1cc1939fc6b34a8233b81f840bd396914a707e3ea1"},{"path":"core/crates/auths-raw-key-core/Cargo.toml","sha256":"98c0bc8527a537512e43a74dd6ba9658c6f0cdc16610cf938e3f9b43785d836d"},{"path":"core/crates/auths-raw-key-core/src/lib.rs","sha256":"98c0500c41697aae28708ad0bf970b9a97583d96a3d2c18d23e7fa351e0f7d12"},{"path":"core/crates/auths-registries/Cargo.toml","sha256":"590e49e58b0622d9d6274fea46796dcdb07dec9550eff295cce6a6427ffa51e2"},{"path":"core/crates/auths-registries/src/lib.rs","sha256":"450d3886d85ee333b7e046317fb5b47cde62483d5f3e41d46265e2caf4c373ec"},{"path":"core/crates/auths-registries/src/template.rs","sha256":"1224039dd2b3ce6fa8357613d8cafbae40400493da7176da202b9ade62fa05e4"},{"path":"core/crates/auths-signature-core/Cargo.toml","sha256":"6bee2230eb30af1be0bd5c2d57bd3e1903497a70028d47290d4ac6e9e0e8bca0"},{"path":"core/crates/auths-signature-core/src/lib.rs","sha256":"6e3f9311ded5e49ea50d445eb21e6d8fa12442aa4362a73e0cb6fda15b7cd865"},{"path":"core/crates/auths-signature/Cargo.toml","sha256":"7f7b5682466ba439d8c59579022cb61068cad9fb4bd2d73e1cc21327c902b450"},{"path":"core/crates/auths-signature/src/lib.rs","sha256":"b3d9ac4cc3ba0797b9e1c09f2d6ac05089b25dac4e285a5af28c0165b33d925b"},{"path":"core/crates/auths-verifier/Cargo.toml","sha256":"c43358e06a33324b41a8b93e5cc7279c55f7d21f1f6cfaa539a3fc7b4c27a38f"},{"path":"core/crates/auths-verifier/src/approval.rs","sha256":"c3cae6a49e169051eb555bb092b1069a4d422516d6a2114623a89e5f31ff923f"},{"path":"core/crates/auths-verifier/src/causal.rs","sha256":"9635230f33b13a263573d319ac8a1976addbcc07677514a43e3c7bf28dc04587"},{"path":"core/crates/auths-verifier/src/lib.rs","sha256":"f22dec38dfa47ced8da4f605390da8453273bee1da010f57fd1fdfcb10e0b389"},{"path":"core/crates/auths-verifier/src/observation.rs","sha256":"0bb07f06a0f9524c88427df1c972b1de8ba038a9eeeb15d3134c25125ae84b1e"},{"path":"core/crates/auths-verifier/src/trace.rs","sha256":"2213d72023a1d9e0413a2cf2c51c3dad9e04775d86033a0caaa9d29a8f0036f8"},{"path":"exchange/crates/auths-proof-exchange-model/Cargo.toml","sha256":"34b2db64f93a288e942b5a3918d28cdcbef906e0dc9074ce848018d3d5f7a1fa"},{"path":"exchange/crates/auths-proof-exchange-model/src/lib.rs","sha256":"49fac5aff2339d3a57c41cb8bb2a82852538e8f77ecc4b157c88e264ff31fb55"},{"path":"exchange/crates/auths-proof-exchange-port/Cargo.toml","sha256":"7ff660f1b7579dc570c791090aeb450404fbbf44c92781e289f5ccdde746d739"},{"path":"exchange/crates/auths-proof-exchange-port/src/lib.rs","sha256":"b408fb40c6432edc1facb3d8b3e9433a033f8dc73fe2e0ba5a88c972ca675021"},{"path":"product/config/auths-config/Cargo.toml","sha256":"e4b568ab9f6d84f7d7e6d66443fe825f360db9c27bc7c31d6ddc0647ba3ab304"},{"path":"product/config/auths-config/src/lib.rs","sha256":"fecf00ea65cef9018fda9af2063326d7065b869266d0d9e73a4f06816f1102cc"},{"path":"product/errors/auths-errors/Cargo.toml","sha256":"3b3a199b6460ba75bda84475bb5accd35e1485448a3981038db85bf4772dd350"},{"path":"product/errors/auths-errors/src/lib.rs","sha256":"7feeb9069fa4003f94f1f07c1c94619cf1c883e0dbaaf2187f04d0f742264bdd"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/Cargo.toml","sha256":"716f1f2a117d6d69d8effe9ee9057e24ba3502f20af6a602b06facb638cdabed"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/api.rs","sha256":"b3c4321e0737835ecc4f17235d7589b7f3d62180954ebb98ea9449252300245a"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/clock.rs","sha256":"73f0a6e0f5903883329fa6683f5888288f759512ac69e5c87efd2b6b87f7d79f"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/http.rs","sha256":"14c1fce14e24c984b2a275563a29b6326fb08367922b6e8d37ba38b9cb81aa2b"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/identity.rs","sha256":"186de11230c8b33375951c4368609f8976bf9795f171af3fd7fac26207a94361"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs","sha256":"881ad9ccca369b6eaa6bfd9ec03b1585bff07b042da38942ef57154839449d3e"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/names.rs","sha256":"41bb23572d6002e23ee103d6fe70ecd68764861c6f2e48a1c53af998270a4afa"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs","sha256":"39fed883f4802e68d3b41a68fea0aba0737810996b33d13577de70faba004c29"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/store.rs","sha256":"32bb4b7ff3e7769d0ff46d374f80e4a2c44d7f8e8e82bbea58c9676690db45bb"},{"path":"product/integrations/auths-custody/Cargo.toml","sha256":"1e14034185ad1ec24a977fd5f41d0abee219606245c046ce2a82287fadef448b"},{"path":"product/integrations/auths-custody/src/conformance.rs","sha256":"8ed1afd58f18fc6becc268908aa6419c9aa404c79da0197963eb2599df44acf6"},{"path":"product/integrations/auths-custody/src/key.rs","sha256":"70cbb0fd21b6f5652157845a22c35be2d0f6c05b3d138fc4b9bb6dbdc3d81c40"},{"path":"product/integrations/auths-custody/src/lib.rs","sha256":"8ee593c1f59b0fd2126bdda9138026f5bc531beb64d4489a99785842e7b98b43"},{"path":"product/operations/auths-operations/Cargo.toml","sha256":"73dde1e914ba5e1386f8d49c0d730423cc72ae77ec44c6554a6a75cc8e8922b1"},{"path":"product/operations/auths-operations/src/explanation.rs","sha256":"b4a39bcbd5712cb9e735ee7deeb281f3fa6af5ddca973735bf3d87dce427ef11"},{"path":"product/operations/auths-operations/src/lib.rs","sha256":"3f401a56555113b98f57bca172a2660eaecedf76247b83a3fdbb089c133a29cd"},{"path":"product/operations/auths-operations/src/render/json.rs","sha256":"2ae042639960afee123730e945d373bc5dda1d2b3af20ae16c939a7e99b9e418"},{"path":"product/operations/auths-operations/src/render/mod.rs","sha256":"b3b7f6fe473f49227ace5a68bfc3d8dc14b5db8dd9888fd9e207070337b1b8bf"},{"path":"product/operations/auths-operations/src/render/text.rs","sha256":"f216cf3bdb00e264523271b16e7059535ac6b1aabf271cebd7935af155e4bfec"},{"path":"product/policy/auths-bounded-policy/Cargo.toml","sha256":"babd5d200923137ead71d8c2528f847cea323ce98da942a1320b054436612c47"},{"path":"product/policy/auths-bounded-policy/src/arithmetic.rs","sha256":"75e43c5d4eab8d1f71c1daf53839f5f9fe45a400afc1f63a30c6f55ce3632627"},{"path":"product/policy/auths-bounded-policy/src/commitment.rs","sha256":"c5706f2d583454e1a7f570f7ada138d4d864bef0205dfae7c1296774f396bb3f"},{"path":"product/policy/auths-bounded-policy/src/eligibility.rs","sha256":"c9acdfb793074e687fc36efad506be27dbd99ffbf40387bc66c8de39ef238432"},{"path":"product/policy/auths-bounded-policy/src/identifier.rs","sha256":"0006a32bae9eb16c4178cf797df418d2b0a781f2bc6474b741dc1a908141831c"},{"path":"product/policy/auths-bounded-policy/src/kernel.rs","sha256":"99187c28b161ac70bee1afed60711f7f645adb4d1671a01863f9849b369811d5"},{"path":"product/policy/auths-bounded-policy/src/lib.rs","sha256":"76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c"},{"path":"product/policy/auths-bounded-policy/src/receipt.rs","sha256":"3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad"},{"path":"product/policy/auths-bounded-policy/src/registry.rs","sha256":"4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0"},{"path":"product/profiles/auths-profile-api/Cargo.toml","sha256":"7ae85761f58625b5d678f961fd052eebf3e000ef565c7312e3ac857763c0017f"},{"path":"product/profiles/auths-profile-api/src/lib.rs","sha256":"a194b82b20bf8aa864c2334ef6c6aec30b2154ded972862252d5dcefa488ab95"},{"path":"product/profiles/auths-profile-mcp/Cargo.toml","sha256":"db264fc25242f7b7e4133cbe5782545b3107b406c87168ae072683cfb59eac66"},{"path":"product/profiles/auths-profile-mcp/src/arguments.rs","sha256":"a5de696586d507e2aee4a49fee99ef1ef4c51a2e46603f8838f1af6d9009833f"},{"path":"product/profiles/auths-profile-mcp/src/lib.rs","sha256":"d0f8b733a09ef8408336cdebc8948d6a5861012ce6878598b11be7084dfd4280"},{"path":"product/profiles/auths-profile-mcp/src/session.rs","sha256":"166c281fa66333388e4760d6098dad02d3359e1d5de4b8f93312c014f97abb03"},{"path":"product/qualification/auths-recipe-qualification/Cargo.toml","sha256":"b7b15b30b9a3d96d4f089d514266d3a892de6608d30707aa44be31cca89ca9fe"},{"path":"product/qualification/auths-recipe-qualification/src/canonical.rs","sha256":"30a9b50777f0dcb4b606abfee2467d5a975d9f6ad941ab6c13ca3df5b359f667"},{"path":"product/qualification/auths-recipe-qualification/src/closure.rs","sha256":"0ad6aee9bd981e2863fa725f209ec84031db2ff12f4c7ac3aaf5120f0bb86039"},{"path":"product/qualification/auths-recipe-qualification/src/error.rs","sha256":"52d5cf720a1e4579008fdda90a3ac2c31f0b8db57985f121f65e54b4da2b7dd1"},{"path":"product/qualification/auths-recipe-qualification/src/evidence.rs","sha256":"1a4cb862f725b02f9efd827db99637ea8178a5236aa020ec271a363edbe7b362"},{"path":"product/qualification/auths-recipe-qualification/src/ids.rs","sha256":"e81a906d571497ab2da753e1532d4443706410e0b75fdd59a7d2d788c7aec403"},{"path":"product/qualification/auths-recipe-qualification/src/lib.rs","sha256":"195b19f46e1e94a0f3594ad5958e5715bc5e3ad415bdfe6428dfc1b6dd3f4631"},{"path":"product/qualification/auths-recipe-qualification/src/model.rs","sha256":"3484eb0ec287b23d4682ade7b1b0f8d1335985b3fb180f06fc28716076957d5f"},{"path":"product/qualification/auths-recipe-qualification/src/release.rs","sha256":"d816b53e2275e902c750ad03803061844e259e28560ab2d1c77e8a43981a4d6a"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/mod.rs","sha256":"7f15b68e05a04f202bcb1fb80de1d9a9a4fda8bfd6af2cd4e5c660fc75d96fe5"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/schemas.rs","sha256":"c59feec2805621f341a90f81fc005e2c12f7a70f9d264fdeacccb2be4fe1c046"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/verification.rs","sha256":"6a6b5834c5dae10af1ba8939b2deae43b85db71544dc8f077ff63b7fe68ac8a8"},{"path":"product/qualification/auths-recipe-qualification/src/verify.rs","sha256":"edd33589c54fb79bcfccc4cf4e6ccf95bbca088318bb7f8dfc27da684b4fa671"},{"path":"product/receipts/auths-receipts/Cargo.toml","sha256":"6001fa1375899953aafcb07c23a6da0c8f57ea7ec08bb9c950b12a60a8cc6f0f"},{"path":"product/receipts/auths-receipts/src/disclosure.rs","sha256":"ba9ed439be0a320c8a01f5b6e9b51361c1a37e076947490d8e4a484ba6bb119c"},{"path":"product/receipts/auths-receipts/src/lib.rs","sha256":"547a57c4160256719cafb7d0ab972d9fc80b0da14fbbce4148c70c414070ff36"},{"path":"product/runtime/auths-connections/Cargo.toml","sha256":"babeb6e1dda3dfb66291713ce1e43dce5c349833d0b50ea4dccbf986030026b2"},{"path":"product/runtime/auths-connections/src/credential.rs","sha256":"4d532c221d2fe7a2b47c8720be94c26d0c86a0448c3f66f479ce3b12adf44f25"},{"path":"product/runtime/auths-connections/src/kernel.rs","sha256":"a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8"},{"path":"product/runtime/auths-connections/src/lib.rs","sha256":"79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22"},{"path":"product/runtime/auths-connections/src/model.rs","sha256":"de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77"},{"path":"product/runtime/auths-connections/src/registry.rs","sha256":"e57640e003e72ad3235c567c2bb944a262bd64e673f023b62ea091094cc7e946"},{"path":"product/runtime/auths-gateway-kernel/Cargo.toml","sha256":"34f864e67656af4ac7e5c7a347a23f01fc8ab31365b8e23c0ef474483b14a183"},{"path":"product/runtime/auths-gateway-kernel/src/construct.rs","sha256":"e9d65744bae273d65face4285e5d2da75c06a92ab48f7b8333d496604e31c63c"},{"path":"product/runtime/auths-gateway-kernel/src/lib.rs","sha256":"cfda6f8453426564c085475f183b6f790b438768a19668f1b65d33ba59dc8632"},{"path":"product/runtime/auths-gateway-kernel/src/order.rs","sha256":"e0045f877c4b7fe3860c291039853885064ddcdebba7c9b345ab65e81e646dda"},{"path":"product/runtime/auths-gateway-kernel/src/outcome.rs","sha256":"e9785b1afe70788c89b51b18655bcd5acff7b0c8e3d12fb79c6f05a202e67e6b"},{"path":"product/runtime/auths-gateway-kernel/src/ratio.rs","sha256":"7ace22264812e6fc1ef3a62afee402cf43494bb71ae0d3de219ad1b39d690bcb"},{"path":"product/runtime/auths-gateway-kernel/src/recovery.rs","sha256":"9f46dcd1685ab6e4d1ba04a3fc286a9f3afee8fb47829be1fbc670a7926a2dc6"},{"path":"product/runtime/auths-gateway-kernel/src/transition.rs","sha256":"cefb8f01d915880f6921f2501ff881ad94b9de61072c34d9cd19220992f97374"},{"path":"product/runtime/auths-gateway/Cargo.toml","sha256":"00b28be86921dcdc0ad90cce0c62c2961cafefe96ea6c2edf0e926c3d405ccad"},{"path":"product/runtime/auths-gateway/src/admin.rs","sha256":"2d5cc67afac42fbd15f36e2d1693cd1b20cedacf775040dce6ffe04ccc94c9ea"},{"path":"product/runtime/auths-gateway/src/app.rs","sha256":"6f80f63833ea0815bb44fbf3b0cc54624a08e9fb578b035819f2980dc04e8256"},{"path":"product/runtime/auths-gateway/src/audit.rs","sha256":"0edb2037eb7b5d6f13acfce85c54f62a82bf7fdd31bc7e626c4fec183cef61dd"},{"path":"product/runtime/auths-gateway/src/audit_tests.rs","sha256":"990969384a52d75bc2489d9d412a9e7dd814bca1c8f65c701d6205fae62a15d5"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway-harness.rs","sha256":"12b0c24d36b2e6a3be392d3c081a783b355fdd67dc5b54bacc0410e803116b8c"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway.rs","sha256":"fc36ab82a36398f34513502521d462c951a68c47a8eb8edaf35c0ed5e0566a8c"},{"path":"product/runtime/auths-gateway/src/binding.rs","sha256":"663b0ce878319511aa7d05722ab4ab2fa9be18817884ffb2ee9f131ff1e382d1"},{"path":"product/runtime/auths-gateway/src/bounds.rs","sha256":"9cfa0eae4973e5e047a198360b22f041708fa20276b0b90c2ec440f06915d64b"},{"path":"product/runtime/auths-gateway/src/bounds_aggregate_tests.rs","sha256":"ab34f227b7c8692ba1da88ccb32bb3687a66adf8353d8282fae905d4a88eb612"},{"path":"product/runtime/auths-gateway/src/bounds_tests.rs","sha256":"74136bc570da7b9338b5a1a1ed9d3fd892c55135160964f9d3ac0e2cf5741375"},{"path":"product/runtime/auths-gateway/src/connection.rs","sha256":"7b5d049c258a26ed1c93ecf860f51d051a8a65f9b93554af0b1ea93862398ec9"},{"path":"product/runtime/auths-gateway/src/echo_verify.rs","sha256":"6d453051665f823abd7354d5c50031d9524cf47d6092d2f09080ae814e3b9575"},{"path":"product/runtime/auths-gateway/src/engine.rs","sha256":"5d3617774acd9af4b6f0e34bb481bc5500282d2ee75dce7589606d31ac04f8e8"},{"path":"product/runtime/auths-gateway/src/fuzzing.rs","sha256":"ed3b0028487eb546a3b0a91d115aa8f18bcea324b61620bfe8e35a9e6ab18758"},{"path":"product/runtime/auths-gateway/src/generation_floor.rs","sha256":"47964a5f1ca2fc9c4da0b526b6d5c5637fc0ce1d2e429219d02f1b0dc652fdff"},{"path":"product/runtime/auths-gateway/src/harness.rs","sha256":"c87e479f3eb281960f6c9c80d43c7560d7ccb654b0154ec823d3fcec4884ac05"},{"path":"product/runtime/auths-gateway/src/lib.rs","sha256":"f0dc13132a4aa7caff46c56bbd88f4ed5f1b6af666134bab1025aba911bb8440"},{"path":"product/runtime/auths-gateway/src/listener.rs","sha256":"aa08239bcbc1fcb55e8a212fbdf6a84f12985b0d436dcb51dc58b06e59e435f2"},{"path":"product/runtime/auths-gateway/src/observed_tests.rs","sha256":"a22be071695f89ca2578a4d82fd80d9cb82289213c9bdb8f0470f6b2dc3d9201"},{"path":"product/runtime/auths-gateway/src/observer.rs","sha256":"562ffcaea071c3856e0708dc2fe33516917e145d2438aabb75af0a2b6ba01046"},{"path":"product/runtime/auths-gateway/src/onboarding.rs","sha256":"0dfd7d67e7f02f18a28d1c86ca1b7751d7463f5efcdbe3825de0ad8cbccb3891"},{"path":"product/runtime/auths-gateway/src/operator.rs","sha256":"c3c36954a3e86723df035b47f43b85fc8ab3a6292983522b6258d5c6b4e6c4e4"},{"path":"product/runtime/auths-gateway/src/pending_vectors/attempts.rs","sha256":"47ef3c8cb1c5504d47ae9a0088705ce6715fe86bac1671a34a56fb38a64d0dd3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/bounds.rs","sha256":"e612217307e1da5b0eb5ee6582a7458bb064b8aa8a529fc6555b1b334127ab68"},{"path":"product/runtime/auths-gateway/src/pending_vectors/codes.rs","sha256":"e00670a5ef24eb856cc2c6dcda8e5a263842f55c76bb939c0c27bd9df37e5522"},{"path":"product/runtime/auths-gateway/src/pending_vectors/keys.rs","sha256":"f84c56f2ea9cb34b2b79c72d13fbf2c6585010ec1ed450af58a78c80c1ea1edd"},{"path":"product/runtime/auths-gateway/src/pending_vectors/mod.rs","sha256":"5de8340f0ef71a0b57a09e323fefe473d3160c6ae952b9ba46f714825fbacafc"},{"path":"product/runtime/auths-gateway/src/pending_vectors/outcomes.rs","sha256":"8ec07b9511b48913af36ac999d2aa0e82924289f6acb23ddaeb9f00f99815166"},{"path":"product/runtime/auths-gateway/src/pending_vectors/production.rs","sha256":"329bb4b2b4eaef06cfbc9a38458646b34130251fb4a13810b5ac36abce6d981b"},{"path":"product/runtime/auths-gateway/src/pending_vectors/recipes.rs","sha256":"51693208270231c25c3aef2a32151d5962114c71e86b88cb9df83181c7af83d9"},{"path":"product/runtime/auths-gateway/src/pre_entry.rs","sha256":"06ea78ca140468bfaba17d9ab04912ad68673954c3203c98fed28272ff2a00c0"},{"path":"product/runtime/auths-gateway/src/property_tests.rs","sha256":"939c081e2e154aaf10186754044bdd65608932c899b970a04a71d0afaa999a93"},{"path":"product/runtime/auths-gateway/src/qualification.rs","sha256":"a4398512ccb7bb494000fe38f03e0faa7b82d1f80ef5ee2dfa75698ae4f5a9be"},{"path":"product/runtime/auths-gateway/src/qualification_tests.rs","sha256":"4473add5729b97faf04d7be7fd8cf3bbacd7f545e1b61c7d2782563011906b4d"},{"path":"product/runtime/auths-gateway/src/quorum_tests.rs","sha256":"a78380b019104d688c11a4410082c7e08ded3106aab099954c4f8a1b4ae0fd89"},{"path":"product/runtime/auths-gateway/src/readiness.rs","sha256":"8c9c41c5f0e65ed3144b2183f49940bfda0f0db1e4f4a0b6e2f5fb84fe2fba18"},{"path":"product/runtime/auths-gateway/src/recipe.rs","sha256":"fecf9af67e7afc48d080e9f8f55f8ce28e49d0e08988717a27908bbda461d6b6"},{"path":"product/runtime/auths-gateway/src/recipe/lower.rs","sha256":"8088b8751ed831dbb48247af953c6290ac95e2a438ccd5bd65eff54be06a1fd1"},{"path":"product/runtime/auths-gateway/src/recipe/review.rs","sha256":"c3eb7d9fdd98dacf52750b14b67ad7b7faaecbbdeafff1e0b049f67d0a2d0139"},{"path":"product/runtime/auths-gateway/src/recipe/runtime.rs","sha256":"c286f0d15f974402822c0810d8e97f98411dc1c557755cc23e540d85e2bb42d9"},{"path":"product/runtime/auths-gateway/src/recipe/source.rs","sha256":"1af50298fb1461e1b24cbdf560d43124d6b1c4c529586c911b1c4797214a69ff"},{"path":"product/runtime/auths-gateway/src/recipe/tests.rs","sha256":"aac551a2481bbc60864c64079bc667dcb232e45a0f41a04073ed84ab5dbe1fce"},{"path":"product/runtime/auths-gateway/src/recipe/validate.rs","sha256":"3711b17605cb7b0d639bc1b180449231f5882a306cab20e2c7782155cc63b0d4"},{"path":"product/runtime/auths-gateway/src/scenario_tests.rs","sha256":"d8271761b12597bfe1233f8eb5ad1d4e5498c5d03388e832e24ab818484a1de4"},{"path":"product/runtime/auths-gateway/src/separation.rs","sha256":"be9306848ca5d801767cf6aa14247c8618312ef0e202f00ce0c24c4844491061"},{"path":"product/runtime/auths-gateway/src/store.rs","sha256":"1e5288345c2cb1421aeda277b3158d07607404b0ec46943222ac107b63dcbb46"},{"path":"product/runtime/auths-gateway/src/store_testkit.rs","sha256":"88d82fee42f1b8ef521e8deef0216e938ebeaad822eb2f5020e70b89d145ea70"},{"path":"product/runtime/auths-gateway/src/submit.rs","sha256":"c78dbbba7c45b443febf655056c5edcd635e77be7b21c5b2c318097502415ffe"},{"path":"product/runtime/auths-gateway/src/support.rs","sha256":"8537d54b8071744a6a3983f48620a8abe1169c6103b281badd701dd0999ac9c7"},{"path":"product/runtime/auths-gateway/src/transport.rs","sha256":"be2c6dc75b8daec110bf8749fedc3823f6067d40b999aa3eb21126896a97d3ad"},{"path":"product/runtime/auths-kernel-runtime/Cargo.toml","sha256":"926bcd0053e5edd703be8f0027ad009e2982db013c8174c1366edbf38b48087d"},{"path":"product/runtime/auths-kernel-runtime/src/lib.rs","sha256":"7108faae9ca4bc32dc093ddaf885ac8f74f3c9b8d317b7c7d0ed00d1d0ab5972"},{"path":"product/runtime/auths-lifecycle/Cargo.toml","sha256":"c5053c705f8d5554b44e432fe75287a2faf11d644e5a2552e45ad6cd94176af5"},{"path":"product/runtime/auths-lifecycle/src/codec.rs","sha256":"51c4b746749150e8bfcd8ff972b3f6c1ef40bec15583448ec1b471d9ad737dc0"},{"path":"product/runtime/auths-lifecycle/src/digest.rs","sha256":"55282cd7d8aba37713c2dcb5357c9877819edb72a30eadefb860d28d7d3a3eb7"},{"path":"product/runtime/auths-lifecycle/src/identifier.rs","sha256":"31620e8c16de68d3d2d3b84d6353c1a5b9d4151d8247f91fa389b906a8e660f1"},{"path":"product/runtime/auths-lifecycle/src/kernel.rs","sha256":"2abb8c094b36d35b364e74d78091d14c5d6f3d1eb6552cca3b5538dbd017ce23"},{"path":"product/runtime/auths-lifecycle/src/lib.rs","sha256":"afe5a345cd309b5a4f08ffba3170a6d7f16ff914892b3f2006d5208ed24ec736"},{"path":"product/runtime/auths-lifecycle/src/model.rs","sha256":"1af12bbeeeaa65ec02ddcebd7d2c8c92ec1e339fa40ae85b45ab9b01a722a4fa"},{"path":"product/runtime/auths-lifecycle/src/operation.rs","sha256":"78e6d05fcf5d7ea4f148032a3fa26fdfcab77eb346019effe927b08e0d64d732"},{"path":"product/runtime/auths-lifecycle/src/registry.rs","sha256":"53495fe6f7a77422593a41623e28716f1c140dcc1e00f87f6b0ffbfb93a5ef90"},{"path":"product/runtime/auths-lifecycle/src/sealed.rs","sha256":"2e0c03b5813c926c159598bb7890d1523825edbe57cd687d42a5dfb3374a0c19"},{"path":"product/runtime/auths-lifecycle/src/test_support.rs","sha256":"221d9a5c5ef8e1f9f8fd66927484eaf813571d0568470278ecd8fa08a5eec8cd"},{"path":"product/runtime/auths-lifecycle/src/transition.rs","sha256":"011805a28efdd541f44ccea54dd0e34a1e58f4004447ee58013703b4fb6b2822"},{"path":"product/runtime/auths-runtime/Cargo.toml","sha256":"dd29d80a8b4bb56c869f036a6c9998f6e6d1c0383ac5dc03fa42b24abe2a7ff7"},{"path":"product/runtime/auths-runtime/src/lib.rs","sha256":"132ca03d58c14905d3a822a4972f42a22a5ad33a45f2ba9ca44f3a57d810b4b0"},{"path":"product/runtime/auths-runtime/src/production.rs","sha256":"fd4eff4270c571c10fcff6cf27df28961ebf074de8a1a028f500fda1ca376820"},{"path":"product/sdk/auths-approval-quorum/Cargo.toml","sha256":"df904971fca87a24194c5816738a331588fe8f164acb5d70839a35dca5f57114"},{"path":"product/sdk/auths-approval-quorum/src/lib.rs","sha256":"72e4086088a1c0912e4e1a9e980f26a5c280bf5ab16ea39c9f0f58d5096ac2ce"},{"path":"product/sdk/auths-approval-quorum/src/remote.rs","sha256":"9fa029c7c63003adf260f8aec55160c545681c60c1bace0d934e7525862aac7b"},{"path":"product/sdk/auths-approval-quorum/src/remote_tests.rs","sha256":"8a09ce17cfee82a035a74edd535f3ebeb3db0e078784740d3997b17dbdb10197"},{"path":"product/sdk/auths-approval-quorum/src/tests.rs","sha256":"0acbf12be3e497dcc6c2d8f29c9af3b1a7ed8e11b75f6399570d4f217a785060"},{"path":"product/stores/auths-stores/Cargo.toml","sha256":"a32c4b76d17b264be5d40d24497ff237e1ed87822e8bab86229b3db93106dbe3"},{"path":"product/stores/auths-stores/src/gateway_attempt.rs","sha256":"185da8f4a220fba836d5b78a9311f03204681c43a3c53951008084d135bf4d21"},{"path":"product/stores/auths-stores/src/lib.rs","sha256":"e721262edf8a9ab5568ddc27639176312d4a366203b5f73e2d7c11fde2c554e9"},{"path":"product/stores/auths-stores/src/lifecycle.rs","sha256":"94f64d25bc178a9e60ba3c0ee6915d7fb3af7c4468792d76b4e70f43f4de1e2f"}],"schema":"auths.gateway-semantic-closure/1"} \ No newline at end of file diff --git a/product/runtime/auths-gateway/src/bin/auths-gateway.rs b/product/runtime/auths-gateway/src/bin/auths-gateway.rs index 4d4d4d3af..2ddefa65c 100644 --- a/product/runtime/auths-gateway/src/bin/auths-gateway.rs +++ b/product/runtime/auths-gateway/src/bin/auths-gateway.rs @@ -320,6 +320,10 @@ mod unix { /// defaults to `/admin.sock`. #[arg(long)] admin_socket: Option, + /// Commit directly to the shared store without a running gateway. + /// Does not delete credentials or claim in-flight drainage. + #[arg(long, default_value_t = false)] + store_only: bool, }, /// Ask the private operator socket to enable a disabled connection. Enable { @@ -439,6 +443,10 @@ mod unix { /// defaults to `/admin.sock`. #[arg(long)] admin_socket: Option, + /// Commit directly to the shared store without a running gateway. + /// Does not delete credentials or claim in-flight drainage. + #[arg(long, default_value_t = false)] + store_only: bool, }, /// Rotate the credential via the private operator socket and stdin. Rotate { @@ -450,6 +458,10 @@ mod unix { admin_socket: Option, #[arg(long, default_value_t = false)] credential_stdin: bool, + /// Run under the operator's workload identity in this process. + /// The serving gateway may retain its read-only runtime role. + #[arg(long, default_value_t = false)] + operator_process: bool, }, /// First phase of a two-phase rotation: store the new credential /// from stdin without publishing it, and print its commitment. @@ -462,6 +474,10 @@ mod unix { admin_socket: Option, #[arg(long, default_value_t = false)] credential_stdin: bool, + /// Run under the operator's workload identity in this process. + /// The serving gateway may retain its read-only runtime role. + #[arg(long, default_value_t = false)] + operator_process: bool, }, /// Second phase: publish the prepared credential the commitment /// names to every process sharing the store. @@ -475,6 +491,10 @@ mod unix { /// The commitment `rotate-prepare` printed. #[arg(long)] commitment: String, + /// Run under the operator's workload identity in this process. + /// The serving gateway may retain its read-only runtime role. + #[arg(long, default_value_t = false)] + operator_process: bool, }, /// Operator-only: create the observer signing key in gateway state. ObserverInit { @@ -1238,6 +1258,16 @@ mod unix { ) .await?; } + let installed = shared + .load() + .await + .map_err(|_| "gateway.install.connection-store-unavailable")? + .ok_or("gateway.install.connection-store-unavailable")?; + let floor = auths_gateway::GenerationFloor::new(state_dir.clone()); + let record = installed.record().clone(); + tokio::task::spawn_blocking(move || floor.initialize(&record)) + .await + .map_err(|_| "gateway.install.connection-store-unavailable")??; private_file(&state_dir.join("recipe.json"), &source)?; private_file(&state_dir.join("profile.lock.json"), &lock)?; private_file(&state_dir.join("trusted.context.cbor"), &trust)?; @@ -1747,7 +1777,9 @@ mod unix { Some(observer) => engine.with_observer(observer), None => engine, }; - let engine = engine.with_qualification(Arc::new(qualification_gate(state_dir, &manifest)?)); + let engine = engine + .with_qualification(Arc::new(qualification_gate(state_dir, &manifest)?)) + .with_generation_floor(auths_gateway::GenerationFloor::new(state_dir.to_path_buf())); // Separation is checked against an authenticated operator. A // development installation without one keeps its observer key // outside the trust it installed, as `observer-init` creates it after @@ -2134,9 +2166,11 @@ mod unix { // never take an admin permit. let app_engine = Arc::clone(&engine); let sweep_engine = Arc::clone(&engine); + let app_permits = Arc::new(Semaphore::new(app_capacity)); + let admin_permits = Arc::new(Semaphore::new(ADMIN_CAPACITY)); let app_listener = serve_listener( app, - Arc::new(Semaphore::new(app_capacity)), + Arc::clone(&app_permits), "app", |_: &UnixStream| true, move |stream, permit| { @@ -2150,7 +2184,7 @@ mod unix { let owner = rustix::process::geteuid().as_raw(); let admin_listener = serve_listener( admin, - Arc::new(Semaphore::new(ADMIN_CAPACITY)), + Arc::clone(&admin_permits), "admin", move |stream: &UnixStream| admin_peer_admitted(stream, owner), move |stream, permit| { @@ -2173,10 +2207,36 @@ mod unix { } } }; + let mut terminate = + tokio::signal::unix::signal(tokio::signal::unix::SignalKind::terminate()) + .map_err(|_| "gateway.serve.signal-unavailable")?; tokio::select! { never = app_listener => match never {}, never = admin_listener => match never {}, never = sweeper => match never {}, + _ = terminate.recv() => {}, + _ = tokio::signal::ctrl_c() => {}, + } + // The listeners have been dropped: no new session can be admitted. + // Waiting for permits includes pre-entry and admin sessions, not + // just transports already counted by the engine. + let drained = tokio::time::timeout(Duration::from_secs(25), async { + let _app = app_permits + .acquire_many(u32::try_from(app_capacity).map_err(|_| "gateway.serve.capacity")?) + .await + .map_err(|_| "gateway.serve.capacity")?; + let _admin = admin_permits + .acquire_many(u32::try_from(ADMIN_CAPACITY).map_err(|_| "gateway.serve.capacity")?) + .await + .map_err(|_| "gateway.serve.capacity")?; + Ok::<_, &'static str>(()) + }) + .await; + let _ = fs::remove_file(&app_socket); + let _ = fs::remove_file(admin_path); + match drained { + Ok(result) => Ok(result?), + Err(_) => Err("gateway.serve.shutdown-incomplete".into()), } } @@ -2566,11 +2626,60 @@ mod unix { }) } + /// The emergency operator path opens only installation metadata and the + /// shared lifecycle store. It never opens qualification or custody inputs. + async fn emergency_stop(state_dir: &Path, revoke: bool) -> Result<(), Failure> { + private_root(state_dir)?; + let manifest = installation(state_dir)?; + let deployment = manifest.deployment; + let store_path = manifest.attempt_store.as_ref().map(PathBuf::from); + let attempts = tokio::task::spawn_blocking(move || open_attempts(deployment, store_path)) + .await + .map_err(|_| "gateway.admin.connection-unavailable")??; + let shared = SharedConnection::new( + attempts.store(), + ProviderKind::parse(manifest.provider).map_err(|_| "gateway.serve.invalid-provider")?, + ConnectionAlias::parse(manifest.alias).map_err(|_| "gateway.serve.invalid-alias")?, + ); + let record = shared.stop(revoke, now()?).await?; + println!( + "{}", + serde_json::json!({ + "schema": "auths.gateway-emergency-stop/1", + "state": if record.state() == ConnectionState::Revoked { "revoked" } else { "disabled" }, + "generation": record.generation().get(), + "drainage": "not-checked", + "credential_deletion": "not-attempted" + }) + ); + Ok(()) + } + + async fn operator_engine(state_dir: &Path) -> Result { + let directory = state_dir.to_path_buf(); + tokio::task::spawn_blocking(move || load_engine(&directory)) + .await + .map_err(|_| "gateway.admin.load-failed")? + } + + fn print_admin_response(response: AdminResponse) -> Result<(), Failure> { + println!( + "{}", + serde_json::to_string(&response).map_err(|_| "gateway.output")? + ); + if response.ok { + Ok(()) + } else { + Err(response.code.into()) + } + } + async fn rotate( state_dir: &Path, admin_socket: &AdminSocket, credential_stdin: bool, command: &str, + operator_process: bool, ) -> Result<(), Failure> { if !credential_stdin || std::io::stdin().is_terminal() { return Err("gateway.admin.credential-must-be-piped-to-stdin".into()); @@ -2591,6 +2700,22 @@ mod unix { { return Err("gateway.admin.invalid-credential".into()); } + if operator_process { + let engine = operator_engine(state_dir).await?; + let response = if command == "rotate-prepare" { + match engine.prepare_rotation(bytes).await { + Ok(commitment) => AdminResponse { + ok: true, + commitment: Some(hex::encode(commitment)), + ..AdminResponse::refused("gateway.admin.rotation-prepared") + }, + Err(code) => AdminResponse::refused(code), + } + } else { + AdminResponse::of(engine.rotate_connection(bytes).await) + }; + return print_admin_response(response); + } admin_command( state_dir, admin_socket, @@ -2701,7 +2826,7 @@ mod unix { Ok(()) } - fn doctor( + async fn doctor( state_dir: &Path, admin_socket: &Path, app_socket: &Path, @@ -2781,26 +2906,41 @@ mod unix { if !status.success() { return Err("gateway.doctor.isolation-not-established"); } - let observer = if state_dir.join(OBSERVER_SEED).exists() { - "configured" + let directory = state_dir.to_path_buf(); + let engine = tokio::task::spawn_blocking(move || load_engine(&directory)) + .await + .map_err(|_| "gateway.doctor.state-unavailable")? + .map_err(|failure| failure.code)?; + let manifest = installation(state_dir).map_err(|_| "gateway.doctor.state-unavailable")?; + let qualification = engine.qualification().status(); + let kind = CredentialStoreKind::parse(&custody) + .map_err(|_| "gateway.credential.adapter-unsupported")?; + let mut checks = engine.readiness_checks(kind).await; + checks.clock = if auths_gateway::DeploymentClock::trust(&SynchronizedHostClock) + == auths_gateway::ClockTrustState::Trusted + { + auths_gateway::PreconditionState::Ready } else { - "not configured (signed outcomes unavailable)" + auths_gateway::PreconditionState::NotReady }; - println!( - "gateway state and admin socket denied to app UID; app socket reachable. Independent token copies and egress policy not checked." - ); - println!("provider credential store: {custody}"); - println!("observer: {observer}"); - let manifest = installation(state_dir).map_err(|_| "gateway.doctor.state-unavailable")?; - let qualification = qualification_gate(state_dir, &manifest) - .map_err(|failure| failure.code)? - .status(); - println!( - "qualification: policy={} state={} code={}", - qualification.policy.as_str(), - qualification.state.as_str(), - qualification.code.unwrap_or("none") - ); + checks.operator_plane_isolation = auths_gateway::PreconditionState::Ready; + // load_engine verified pins, authenticated operator, separation and + // observer custody. Development is never production-ready. + if manifest.deployment != Deployment::Production { + checks.trust = auths_gateway::PreconditionState::NotReady; + } + let observer = match load_observer(state_dir)? { + None => auths_gateway::ObserverCustodyState::NotConfigured, + Some(key) if key.custody() != ObserverCustody::Software => { + auths_gateway::ObserverCustodyState::Ready + } + Some(_) => auths_gateway::ObserverCustodyState::NotReady, + }; + let readiness = auths_gateway::ProductionReadiness::new(checks, observer); + println!("{}", readiness.report(qualification.code)); + if !readiness.is_ready() { + return Err("gateway.doctor.not-ready"); + } Ok(()) } @@ -2987,7 +3127,11 @@ mod unix { Command::Disable { state_dir, admin_socket, + store_only, } => { + if store_only { + return emergency_stop(&state_dir, false).await; + } let admin_socket = admin_socket_path(&state_dir, admin_socket); let command = serde_json::json!({"command": "disable"}); admin_command(&state_dir, &admin_socket, command, None).await @@ -3003,7 +3147,11 @@ mod unix { Command::Revoke { state_dir, admin_socket, + store_only, } => { + if store_only { + return emergency_stop(&state_dir, true).await; + } let admin_socket = admin_socket_path(&state_dir, admin_socket); let command = serde_json::json!({"command": "revoke"}); admin_command(&state_dir, &admin_socket, command, None).await @@ -3061,14 +3209,23 @@ mod unix { Command::Rotate { state_dir, admin_socket, + operator_process, credential_stdin, } => { let admin_socket = admin_socket_path(&state_dir, admin_socket); - rotate(&state_dir, &admin_socket, credential_stdin, "rotate").await + rotate( + &state_dir, + &admin_socket, + credential_stdin, + "rotate", + operator_process, + ) + .await } Command::RotatePrepare { state_dir, admin_socket, + operator_process, credential_stdin, } => { let admin_socket = admin_socket_path(&state_dir, admin_socket); @@ -3077,14 +3234,31 @@ mod unix { &admin_socket, credential_stdin, "rotate-prepare", + operator_process, ) .await } Command::RotateCommit { state_dir, admin_socket, + operator_process, commitment, } => { + if operator_process { + let engine = operator_engine(&state_dir).await?; + let mut fixed = [0_u8; 32]; + if commitment.len() != 64 + || !commitment + .bytes() + .all(|b| b.is_ascii_digit() || (b'a'..=b'f').contains(&b)) + { + return Err("gateway.admin.invalid-frame".into()); + } + hex::decode_to_slice(&commitment, &mut fixed) + .map_err(|_| "gateway.admin.invalid-frame")?; + let response = AdminResponse::of(engine.commit_rotation(fixed).await); + return print_admin_response(response); + } let admin_socket = admin_socket_path(&state_dir, admin_socket); admin_command( &state_dir, @@ -3133,7 +3307,8 @@ mod unix { &app_socket, app_uid, app_gid, - )?) + ) + .await?) } Command::Probe { state_dir, diff --git a/product/runtime/auths-gateway/src/connection.rs b/product/runtime/auths-gateway/src/connection.rs index 6fed0f0bd..e755d4320 100644 --- a/product/runtime/auths-gateway/src/connection.rs +++ b/product/runtime/auths-gateway/src/connection.rs @@ -25,6 +25,9 @@ const KEY_DOMAIN: &[u8] = b"auths.gateway-connection/1\0"; /// Why the shared connection record could not be read or changed. #[derive(Clone, Copy, Debug, Eq, PartialEq, Error)] pub enum SharedConnectionError { + /// The record is below the host's durable restore floor or has changed at an accepted generation. + #[error("the connection violates its durable generation floor")] + Rollback, /// A record already exists for this provider and alias. #[error("a connection record already exists")] Exists, @@ -82,9 +85,49 @@ pub struct SharedConnection { provider: ProviderKind, alias: ConnectionAlias, key: GatewayAttemptKey, + floor: Option>, } impl SharedConnection { + /// Commits an emergency stop using only the lifecycle store. No recipe, + /// trust input, provider, or credential-store access participates. + /// Existing attempts are untouched. Repeated stops are idempotent and a + /// revoked connection can never become merely disabled. + /// + /// # Errors + /// Returns a stable admin code for missing, corrupt, unavailable, or + /// concurrently changing state. This does not claim in-flight drainage + /// or deletion of the provider credential. + pub async fn stop(&self, revoke: bool, now: u64) -> Result { + for _ in 0..8 { + let current = self + .load() + .await + .map_err(|_| "gateway.admin.connection-unavailable")? + .ok_or("gateway.admin.connection-unavailable")?; + let target = if revoke { + ConnectionState::Revoked + } else { + ConnectionState::Disabled + }; + if current.record().state() == target + || current.record().state() == ConnectionState::Revoked + { + return Ok(current.record().clone()); + } + let next = current + .record() + .transition_state(target, now) + .map_err(|_| "gateway.admin.transition-unavailable")?; + match self.replace(¤t, &next).await { + Ok(committed) => return Ok(committed.record().clone()), + Err(SharedConnectionError::Conflict) => {} + Err(_) => return Err("gateway.admin.transition-unavailable"), + } + } + Err("gateway.admin.generation-conflict") + } + /// Names the record of `provider` and `alias` in `store`. #[must_use] pub fn new( @@ -98,7 +141,31 @@ impl SharedConnection { provider, alias, key, + floor: None, + } + } + + /// Installs the host's durable generation floor. Emergency store-only + /// stops deliberately use a connection without a floor so that even + /// obsolete restored state can be stopped. + #[must_use] + pub fn with_generation_floor(mut self, floor: crate::GenerationFloor) -> Self { + self.floor = Some(Arc::new(floor)); + self + } + + async fn accept_floor( + &self, + loaded: LoadedConnection, + ) -> Result { + if let Some(floor) = self.floor.clone() { + let record = loaded.record().clone(); + tokio::task::spawn_blocking(move || floor.accept(&record)) + .await + .map_err(|_| SharedConnectionError::Rollback)? + .map_err(|_| SharedConnectionError::Rollback)?; } + Ok(loaded) } /// The installed provider. @@ -123,7 +190,10 @@ impl SharedConnection { let key = self.key; let bytes = blocking(move || store.load(crate::GatewayRecordKind::Connection, &key)).await?; - bytes.map(|bytes| self.decode(bytes)).transpose() + match bytes { + Some(bytes) => self.accept_floor(self.decode(bytes)?).await.map(Some), + None => Ok(None), + } } /// Inserts the first record; a record already present is never @@ -170,7 +240,7 @@ impl SharedConnection { store.replace(crate::GatewayRecordKind::Connection, &key, &before, &after) }) .await?; - Ok(loaded) + self.accept_floor(loaded).await } fn encode(&self, record: &ConnectionRecord) -> Result { diff --git a/product/runtime/auths-gateway/src/engine.rs b/product/runtime/auths-gateway/src/engine.rs index 78054b420..2a075b084 100644 --- a/product/runtime/auths-gateway/src/engine.rs +++ b/product/runtime/auths-gateway/src/engine.rs @@ -323,6 +323,13 @@ impl GatewayEngine { self } + /// Pins the host's independently retained anti-rollback witness. + #[must_use] + pub fn with_generation_floor(mut self, floor: crate::GenerationFloor) -> Self { + self.connection = self.connection.with_generation_floor(floor); + self + } + /// Installs the qualification gate the operator plane built for this /// deployment. Without one, every lease is refused as unqualified. #[must_use] @@ -439,18 +446,12 @@ impl GatewayEngine { /// # Errors /// A failed durable transition never reports disabled. pub async fn disable_connection(&self) -> Result { - let disabled = self - .change_state(|record, now| { - if record.state() != ConnectionState::Active { - return Err("gateway.admin.connection-not-active"); - } - record - .transition_state(ConnectionState::Disabled, now) - .map(Some) - .map_err(|_| "gateway.admin.transition-unavailable") - }) + self.connection + .stop( + false, + wall_clock_seconds().ok_or("gateway.admin.clock-unavailable")?, + ) .await?; - self.delete_superseded_credentials(&disabled).await; Ok(self.drained("gateway.admin.disabled").await) } @@ -818,6 +819,52 @@ impl GatewayEngine { }) } + /// Performs the runtime part of production readiness without leasing a + /// credential or contacting a provider. The caller must separately check + /// process isolation, deployment clock and observer policy. This checks + /// the shared record, exact recipe binding, current generation, bounded + /// secret-store confirmation and pinned transport construction. + pub async fn readiness_checks( + &self, + credential_store: auths_connections::CredentialStoreKind, + ) -> crate::RequiredPreconditions { + use crate::PreconditionState::{NotReady, Ready}; + let mut checks = crate::RequiredPreconditions { + trust: Ready, + store: NotReady, + recipe: NotReady, + qualification: if self.qualification.status().state + == auths_recipe_qualification::RecipeQualificationState::Qualified + { + Ready + } else { + NotReady + }, + provider_secret_custody: NotReady, + connection_generation: NotReady, + clock: NotReady, + transport_policy: NotReady, + operator_plane_isolation: NotReady, + }; + if let Ok(Some(loaded)) = self.connection.load().await { + checks.store = Ready; + let record = loaded.record(); + if let Ok(descriptor) = GatewayConnectionDescriptor::from_record(record, &self.recipe) { + checks.recipe = Ready; + if GatewayHttpTransport::prepare(&self.recipe, descriptor.credential()).is_ok() { + checks.transport_policy = Ready; + } + } + if credential_store.is_production() && self.holds(record).await.is_ok() { + checks.provider_secret_custody = Ready; + } + if authorizes_entry(record, &self.workload_id, &self.profile) { + checks.connection_generation = Ready; + } + } + checks + } + /// Performs the operator's read-only re-observation of one stored /// attempt: one read-back from the stored plan under a fresh lease that /// passes every credential check, when the recipe digest is unchanged @@ -916,6 +963,9 @@ impl GatewayEngine { async fn prepare_entry(&self) -> Result { let loaded = match self.connection.load().await { Ok(Some(loaded)) => loaded, + Err(SharedConnectionError::Rollback) => { + return Err("gateway.connection.restore-rollback"); + } Ok(None) | Err(_) => return Err("gateway.connection.unavailable"), }; let record = loaded.record(); @@ -1824,6 +1874,115 @@ pub(crate) mod tests { ); } + #[tokio::test] + async fn a_restored_store_below_the_host_floor_cannot_lease_after_restart() { + restored_store_floor(crate::store_testkit::Backend::File).await; + } + + #[tokio::test] + #[ignore = "requires the TLS PostgreSQL fixture"] + async fn postgres_restore_below_the_host_floor_cannot_lease_after_restart() { + restored_store_floor(crate::store_testkit::Backend::Postgres).await; + } + + async fn restored_store_floor(backend: crate::store_testkit::Backend) { + let installation = installation_on(backend, 8).await; + let first = &installation.first; + let old = first.record().await; + let directory = tempfile::tempdir().expect("floor directory"); + let floor = crate::GenerationFloor::new(directory.path().to_path_buf()); + floor.initialize(&old).expect("first generation"); + let disabled = first + .engine + .connection + .stop(false, wall_clock_seconds().expect("clock")) + .await + .expect("disable"); + floor.accept(&disabled).expect("new generation"); + let raw = SharedConnection::new( + first.engine.attempts.store(), + old.provider_kind().clone(), + old.alias().clone(), + ); + let current = raw.load().await.expect("load").expect("connection"); + raw.replace(¤t, &old) + .await + .expect("simulate restored database"); + let guarded = raw + .with_generation_floor(crate::GenerationFloor::new(directory.path().to_path_buf())); + assert_eq!(guarded.load().await, Err(SharedConnectionError::Rollback)); + let mut restarted = host(first.engine.attempts.clone(), 8); + restarted.engine.connection = guarded; + let before = restarted.leases.load(Ordering::SeqCst); + assert_eq!( + restarted.entry_refusal().await.as_deref(), + Some("gateway.connection.restore-rollback") + ); + assert_eq!(restarted.leases.load(Ordering::SeqCst), before); + assert_eq!( + floor.accept(&old), + Err("gateway.connection.restore-rollback") + ); + std::fs::write(directory.path().join("connection-floor.json"), b"corrupt") + .expect("corrupt floor"); + assert_eq!( + floor.accept(&disabled), + Err("gateway.connection.restore-rollback") + ); + } + + #[tokio::test] + async fn readiness_and_emergency_stop_make_no_credential_lease() { + let installation = installation(8).await; + let host = &installation.first; + let before = host.leases.load(Ordering::SeqCst); + let checked = host + .engine + .readiness_checks(auths_connections::CredentialStoreKind::LocalFileV1) + .await; + assert_eq!(checked.store, crate::PreconditionState::Ready); + assert_eq!(checked.recipe, crate::PreconditionState::Ready); + assert_eq!( + checked.connection_generation, + crate::PreconditionState::Ready + ); + assert_eq!( + checked.provider_secret_custody, + crate::PreconditionState::NotReady + ); + assert_eq!(checked.qualification, crate::PreconditionState::NotReady); + // Remove custody entirely. The store-only stop is still usable, + // is idempotent, and does not touch or reclassify attempts. + std::fs::remove_dir_all(&host.credentials_directory).expect("remove custody"); + let now = wall_clock_seconds().expect("clock"); + let stopped = host.engine.connection.stop(false, now).await.expect("stop"); + assert_eq!(stopped.state(), ConnectionState::Disabled); + let repeated = host + .engine + .connection + .stop(false, now) + .await + .expect("repeat"); + assert_eq!(stopped.generation(), repeated.generation()); + let revoked = host + .engine + .connection + .stop(true, now) + .await + .expect("revoke"); + assert_eq!(revoked.state(), ConnectionState::Revoked); + assert_eq!( + host.engine + .connection + .stop(false, now) + .await + .expect("stop revoked") + .state(), + ConnectionState::Revoked + ); + assert_eq!(host.leases.load(Ordering::SeqCst), before); + } + #[tokio::test] async fn a_prepared_rotation_changes_nothing_until_it_is_committed() { let installation = installation(8).await; diff --git a/product/runtime/auths-gateway/src/generation_floor.rs b/product/runtime/auths-gateway/src/generation_floor.rs new file mode 100644 index 000000000..5c97a93ae --- /dev/null +++ b/product/runtime/auths-gateway/src/generation_floor.rs @@ -0,0 +1,141 @@ +//! Host-local anti-rollback witness retained independently of database backups. +//! It records only a generation and the digest of the exact connection record. + +use auths_connections::ConnectionRecord; +use serde::{Deserialize, Serialize}; +use sha2::{Digest as _, Sha256}; +#[cfg(unix)] +use std::os::unix::fs::{OpenOptionsExt as _, PermissionsExt as _}; +use std::{ + fs::{self, File, OpenOptions}, + io::{Read as _, Write as _}, + path::PathBuf, +}; + +/// A durable floor for the one connection an installed gateway serves. +/// Retain this file and its qualification floors independently of restores. +#[derive(Clone)] +pub struct GenerationFloor { + directory: PathBuf, +} + +#[derive(Deserialize, Serialize)] +#[serde(deny_unknown_fields)] +struct Accepted { + schema: String, + generation: u64, + record_sha256: String, +} + +impl GenerationFloor { + /// Names the already-private installation directory. The gateway CLI + /// checks ownership and rejects symlink paths before using it. + #[must_use] + pub const fn new(directory: PathBuf) -> Self { + Self { directory } + } + + /// Creates the floor during a fresh installation. An existing floor is + /// checked rather than replaced; runtime startup never initializes one. + /// + /// # Errors + /// Returns the restore-rollback code if the floor cannot be persisted. + pub fn initialize(&self, record: &ConnectionRecord) -> Result<(), &'static str> { + self.persist(record, true) + .map_err(|_| "gateway.connection.restore-rollback") + } + + /// Accepts an equal or newer exact record, durably recording a newer one + /// before it can authorize a lease. A missing floor refuses; a + /// malformed, inaccessible, older or substituted floor fails closed. + /// + /// # Errors + /// Returns `gateway.connection.restore-rollback`; no secret is leased. + pub fn accept(&self, record: &ConnectionRecord) -> Result<(), &'static str> { + self.persist(record, false) + .map_err(|_| "gateway.connection.restore-rollback") + } + + #[cfg(unix)] + fn persist(&self, record: &ConnectionRecord, initialize: bool) -> Result<(), ()> { + let mut options = OpenOptions::new(); + options + .read(true) + .write(true) + .create(true) + .truncate(false) + .mode(0o600) + .custom_flags(i32::from_ne_bytes( + rustix::fs::OFlags::NOFOLLOW.bits().to_ne_bytes(), + )); + let lock = options + .open(self.directory.join("connection-floor.lock")) + .map_err(|_| ())?; + rustix::fs::flock(&lock, rustix::fs::FlockOperation::LockExclusive).map_err(|_| ())?; + let path = self.directory.join("connection-floor.json"); + let digest = hex::encode(Sha256::digest(record.to_canonical_cbor().map_err(|_| ())?)); + match fs::symlink_metadata(&path) { + Ok(metadata) => { + if !metadata.is_file() + || metadata.permissions().mode() & 0o077 != 0 + || metadata.len() > 1024 + { + return Err(()); + } + let mut bytes = Vec::new(); + OpenOptions::new() + .read(true) + .custom_flags(i32::from_ne_bytes( + rustix::fs::OFlags::NOFOLLOW.bits().to_ne_bytes(), + )) + .open(&path) + .map_err(|_| ())? + .take(1025) + .read_to_end(&mut bytes) + .map_err(|_| ())?; + if bytes.len() > 1024 { + return Err(()); + } + let old: Accepted = serde_json::from_slice(&bytes).map_err(|_| ())?; + if old.schema != "auths.gateway-generation-floor/1" + || old.generation > record.generation().get() + { + return Err(()); + } + if old.generation == record.generation().get() { + return if old.record_sha256 == digest { + Ok(()) + } else { + Err(()) + }; + } + } + Err(error) if initialize && error.kind() == std::io::ErrorKind::NotFound => {} + Err(_) => return Err(()), + } + let bytes = serde_json::to_vec(&Accepted { + schema: "auths.gateway-generation-floor/1".to_owned(), + generation: record.generation().get(), + record_sha256: digest, + }) + .map_err(|_| ())?; + let mut pending = tempfile::NamedTempFile::new_in(&self.directory).map_err(|_| ())?; + pending + .as_file() + .set_permissions(fs::Permissions::from_mode(0o600)) + .map_err(|_| ())?; + pending + .write_all(&bytes) + .and_then(|()| pending.as_file().sync_all()) + .map_err(|_| ())?; + pending.persist(path).map_err(|_| ())?; + File::open(&self.directory) + .and_then(|dir| dir.sync_all()) + .map_err(|_| ()) + } + + #[cfg(not(unix))] + fn persist(&self, _record: &ConnectionRecord, _initialize: bool) -> Result<(), ()> { + Err(()) + } +} diff --git a/product/runtime/auths-gateway/src/lib.rs b/product/runtime/auths-gateway/src/lib.rs index 254a7ada3..10117e58e 100644 --- a/product/runtime/auths-gateway/src/lib.rs +++ b/product/runtime/auths-gateway/src/lib.rs @@ -17,6 +17,7 @@ mod echo_verify; mod engine; #[cfg(feature = "fuzzing")] pub mod fuzzing; +mod generation_floor; #[cfg(unix)] pub mod listener; mod observer; @@ -79,6 +80,7 @@ pub use engine::{ GatewayEvidenceSummary, GatewayObserveRequest, GatewayObserveResult, GatewaySubmitResult, SLOT_SWEEP_INTERVAL_SECONDS, SLOT_SWEEP_LIMIT, gateway_verifier_configuration, }; +pub use generation_floor::GenerationFloor; pub use observer::{ GatewayObserver, GatewayObserverError, GatewaySignedObservation, OBSERVATION_MEDIA_TYPE, OPERATION_SUBJECT_SCHEME, OUTCOME_SCHEMA, ObserverAnchorTemplate, ObserverCustody, diff --git a/product/runtime/auths-gateway/src/pending_vectors/production.rs b/product/runtime/auths-gateway/src/pending_vectors/production.rs index 081aa20fd..eb1d29a60 100644 --- a/product/runtime/auths-gateway/src/pending_vectors/production.rs +++ b/product/runtime/auths-gateway/src/pending_vectors/production.rs @@ -13,8 +13,8 @@ //! retirement delay, and redacted debug forms. The qualification codes are //! implemented by the gate, whose tests drive every verification vector. //! The support bundle exists and its own test scans it for every canary of -//! the `redaction` section. The readiness codes are still pending, and for -//! those this module asserts the shortfall: no product crate defines one. The secret-name and version +//! the `redaction` section. Readiness checks and restore floors are implemented +//! and exercised in readiness and engine tests. The secret-name and version //! vectors are generated here from the stated derivation and driven by the //! Secrets Manager store's own tests, so the two agree or one of them fails. Those assertions are expected to fail when the implementing work //! lands, wherever it lands, and that work replaces each with the @@ -63,7 +63,13 @@ const ROWS: &[&str] = &[ "gateway.qualification.unavailable qualification before-lease implemented 3 V:index-signature-forged", "gateway.qualification.revocation-stale qualification before-lease implemented 3 V:revocation-list-past-next-update", "gateway.qualification.clock-untrusted qualification before-lease implemented 3 V:clock-untrusted", - "gateway.readiness.connection-disabled readiness doctor new 4 -", + "gateway.readiness.connection-disabled readiness doctor implemented 4 -", + "gateway.readiness.trust-unavailable readiness doctor implemented 4 -", + "gateway.readiness.store-unavailable readiness doctor implemented 4 -", + "gateway.readiness.recipe-drift readiness doctor implemented 4 -", + "gateway.readiness.transport-unavailable readiness doctor implemented 4 -", + "gateway.readiness.observer-unavailable readiness doctor implemented 4 -", + "gateway.connection.restore-rollback connection before-lease implemented 4 -", "gateway.attempt.replay engine recorded existing - C:lease-never-precedes-claim", "gateway.connection.credential-generation-missing engine before-claim existing - C:lease-generation-not-held", "gateway.credential.unavailable engine recorded existing - C:lease-commitment-mismatch", @@ -75,7 +81,7 @@ const ROWS: &[&str] = &[ /// pending. Until their epics land, the gateway defines no code under them. /// The qualification family is implemented: the gate's own tests drive /// every verification vector through it. -const NEW_FAMILIES: &[&str] = &["gateway.readiness."]; +const NEW_FAMILIES: &[&str] = &[]; /// Every hostile class the production work must have a vector for. const REQUIRED_CLASSES: &[&str] = &[ diff --git a/product/runtime/auths-gateway/src/readiness.rs b/product/runtime/auths-gateway/src/readiness.rs index f9eccd154..64505fe13 100644 --- a/product/runtime/auths-gateway/src/readiness.rs +++ b/product/runtime/auths-gateway/src/readiness.rs @@ -123,6 +123,23 @@ pub enum ReadinessPrecondition { } impl ReadinessPrecondition { + /// Stable reason when this typed check failed or could not be made. + #[must_use] + pub const fn code(self) -> &'static str { + match self { + Self::Trust => "gateway.readiness.trust-unavailable", + Self::Store => "gateway.readiness.store-unavailable", + Self::Recipe => "gateway.readiness.recipe-drift", + Self::Qualification => "gateway.qualification.unavailable", + Self::ProviderSecretCustody => "gateway.credential.unavailable", + Self::ConnectionGeneration => "gateway.readiness.connection-disabled", + Self::Clock => "gateway.qualification.clock-untrusted", + Self::TransportPolicy => "gateway.readiness.transport-unavailable", + Self::OperatorPlaneIsolation => "gateway.doctor.isolation-not-established", + Self::ObserverCustody => "gateway.readiness.observer-unavailable", + } + } + /// The preconditions every production deployment requires, in the order /// they are reported. pub const REQUIRED: [Self; 9] = [ @@ -230,6 +247,30 @@ pub struct ProductionReadiness { } impl ProductionReadiness { + /// Secret-free machine-readable diagnostic projection. Every required + /// check is present, including failures; optional observer custody is + /// explicitly reported. A failed qualification retains its precise code. + #[must_use] + pub fn report(&self, qualification_code: Option<&'static str>) -> serde_json::Value { + let mut checks: Vec<_> = ReadinessPrecondition::REQUIRED.into_iter().map(|check| { + let ready = self.required.state(check) == Some(PreconditionState::Ready); + serde_json::json!({ + "check": check.as_str(), "ready": ready, + "code": if ready { None } else if check == ReadinessPrecondition::Qualification { + Some(qualification_code.unwrap_or(check.code())) + } else { Some(check.code()) } + }) + }).collect(); + checks.push( + serde_json::json!({"check": "observer-custody", "state": match self.observer { + ObserverCustodyState::NotConfigured => "not-configured", + ObserverCustodyState::Ready => "ready", + ObserverCustodyState::NotReady => "not-ready", + }}), + ); + serde_json::json!({"schema": "auths.gateway-readiness/1", "ready": self.is_ready(), "checks": checks}) + } + /// Combines the outcome of every check. #[must_use] pub const fn new(required: RequiredPreconditions, observer: ObserverCustodyState) -> Self { @@ -289,6 +330,27 @@ mod tests { } } + #[test] + fn the_projection_names_every_check_and_retains_precise_qualification_failure() { + let readiness = ProductionReadiness::new( + required((1 << 3) | (1 << 5)), + ObserverCustodyState::NotConfigured, + ); + let report = readiness.report(Some("gateway.qualification.revoked")); + assert_eq!(report["ready"], false); + let checks = report["checks"].as_array().expect("checks"); + assert_eq!(checks.len(), 10); + assert_eq!(checks[3]["code"], "gateway.qualification.revoked"); + assert_eq!(checks[5]["code"], "gateway.readiness.connection-disabled"); + assert_eq!(checks[9]["state"], "not-configured"); + for bit in 0..9 { + let report = ProductionReadiness::new(required(1 << bit), ObserverCustodyState::Ready) + .report(None); + assert_eq!(report["ready"], false); + assert!(report["checks"][bit]["code"].is_string()); + } + } + #[test] fn retirement_delay_outlives_entered_transport() { let delay = CredentialRetirementDelay::FIXED.as_duration(); diff --git a/product/runtime/auths-gateway/src/semantic_closure.rs b/product/runtime/auths-gateway/src/semantic_closure.rs index 8ad00f3d0..1270c1059 100644 --- a/product/runtime/auths-gateway/src/semantic_closure.rs +++ b/product/runtime/auths-gateway/src/semantic_closure.rs @@ -10,7 +10,7 @@ /// SHA-256 of the schema, a NUL byte, and `semantic-closure.json`. /// Regenerate through `semantic_closure_is_current` with `AUTHS_UPDATE_FIXTURES=1`. pub const GATEWAY_SEMANTIC_CLOSURE_SHA256: &str = - "92401d5852022a9b5540db598ac6dfb1a8fbb727ff563b66eca7f440176cc057"; + "fbea66a1c8add7315231c5614d4fc9cb29fcd306a632a1b18fc8a9be642f41af"; #[cfg(test)] mod tests { diff --git a/product/runtime/auths-gateway/tests/isolated_process.rs b/product/runtime/auths-gateway/tests/isolated_process.rs index 16c777f42..46d40b895 100644 --- a/product/runtime/auths-gateway/tests/isolated_process.rs +++ b/product/runtime/auths-gateway/tests/isolated_process.rs @@ -73,13 +73,20 @@ fn run_doctor(state: &Path, app_socket: &Path, group: &str, phase: &str) { .output() .expect("run distinct-UID doctor"); assert!( - doctor.status.success(), - "distinct-UID boundary failed during {phase}: {}", - String::from_utf8_lossy(&doctor.stderr) - ); - assert!( - String::from_utf8_lossy(&doctor.stdout).contains("gateway state and admin socket denied") + !doctor.status.success(), + "development is not production-ready during {phase}" ); + assert!(String::from_utf8_lossy(&doctor.stderr).contains("gateway.doctor.not-ready")); + let report: serde_json::Value = + serde_json::from_slice(&doctor.stdout).expect("readiness report"); + assert_eq!(report["ready"], false); + let isolation = report["checks"] + .as_array() + .expect("checks") + .iter() + .find(|check| check["check"] == "operator-plane-isolation") + .expect("isolation check"); + assert_eq!(isolation["ready"], true); } fn doctor_command( @@ -271,10 +278,15 @@ fn distinct_uid_cannot_reach_a_relocated_admin_socket() { let relocated = doctor_command(&state, Some(&admin_socket), &app_socket, group.trim()) .output() .expect("run distinct-UID doctor"); + assert!(!relocated.status.success()); + assert!(String::from_utf8_lossy(&relocated.stderr).contains("gateway.doctor.not-ready")); + let report: serde_json::Value = serde_json::from_slice(&relocated.stdout).expect("report"); assert!( - relocated.status.success(), - "distinct-UID boundary failed with a relocated admin socket: {}", - String::from_utf8_lossy(&relocated.stderr) + report["checks"] + .as_array() + .expect("checks") + .iter() + .any(|check| check["check"] == "operator-plane-isolation" && check["ready"] == true) ); let forgotten = doctor_command(&state, None, &app_socket, group.trim()) diff --git a/release/semantic-freeze-versions.toml b/release/semantic-freeze-versions.toml index 19f4d261f..c7ef5cb1c 100644 --- a/release/semantic-freeze-versions.toml +++ b/release/semantic-freeze-versions.toml @@ -1,4 +1,4 @@ -freeze_version = 358 +freeze_version = 359 # Semantic identity counters live outside the xtask source tree deliberately. # The formal source closure binds xtask's executable code, while the semantic @@ -45,7 +45,7 @@ freeze_version = 358 "auths.frozen-bytes/product/integrations/auths-stripe/fixtures/subscription-create/v1/manifest.sha256.json" = 1 "auths.frozen-bytes/product/integrations/auths-stripe/fixtures/subscription-modify/v1/manifest.sha256.json" = 1 "auths.frozen-bytes/product/integrations/auths-stripe/fixtures/v1/manifest.sha256.json" = 1 -"auths.identity.protocol" = 114 +"auths.identity.protocol" = 115 "auths.modular-components" = 20 "auths.portable-abi-bindings" = 121 "auths.product.bounded-domains" = 19 @@ -60,11 +60,11 @@ freeze_version = 358 "auths.product.mcp-closed-execution" = 31 "auths.product.mechanism-profile-conformance" = 12 "auths.product.operations" = 5 -"auths.product.public-sdk-contract" = 111 +"auths.product.public-sdk-contract" = 112 "auths.product.receipts" = 13 "auths.product.release-assurance" = 7 "auths.product.simplified-waist" = 19 "auths.product.vocabulary" = 23 "auths.release.benchmark-contract" = 1 "auths.release.evolution-contract" = 79 -"auths.release.public-surface" = 358 +"auths.release.public-surface" = 359 diff --git a/release/semantic-freeze.json b/release/semantic-freeze.json index be054f4bd..fa2989588 100644 --- a/release/semantic-freeze.json +++ b/release/semantic-freeze.json @@ -1,6 +1,6 @@ { "schema": "auths.semantic-freeze/1", - "freezeVersion": 358, + "freezeVersion": 359, "publicSurface": { "rustRoots": [ "auths", @@ -550,7 +550,7 @@ }, { "id": "auths.identity.protocol", - "version": 114, + "version": 115, "classification": "frozen-meaning", "categories": [ "identity-protocol-versions", @@ -573,7 +573,7 @@ "core/fixtures/identity/v1/vectors.json", "core/spec/identity/v1" ], - "sha256": "e65c35e8f18375a40e644113e800f56e0ed464988a7e198aa33f2b536aea6bde" + "sha256": "46396d619784df07676d8fe7606d4d24e9312974e0db513847630a48cfab72df" }, { "id": "auths.modular-components", @@ -871,7 +871,7 @@ }, { "id": "auths.product.public-sdk-contract", - "version": 111, + "version": 112, "classification": "frozen-meaning", "categories": [ "rust-sdk-contract", @@ -889,7 +889,7 @@ "product/runtime/auths-runtime/src", "product/sdk/auths-sdk/src" ], - "sha256": "838d240b4b9de1b40ff6067fdf54bb3c12a2c6abc00dd52dcc268e35bdb0064d" + "sha256": "aac1b94991d0b0669f54e1c41284eab01f9a4a31c656fe93b95a92a6e350e29f" }, { "id": "auths.product.receipts", @@ -1011,7 +1011,7 @@ }, { "id": "auths.release.public-surface", - "version": 358, + "version": 359, "classification": "release-metadata", "categories": [ "package-names", @@ -1103,7 +1103,7 @@ "xtask/src/release_control.rs", "xtask/src/semantic_freeze.rs" ], - "sha256": "3ba4d57ecaf562394b7fc08528138a741776607cd448706e550b5bb07ad4a28e" + "sha256": "506c17e8147d2cfcc6e9f695c83a3927e5a9dfa9fe834974545b45ecef3dd08b" } ] } From 86356d67f8553d87a6c65dc4f853825343d3123a Mon Sep 17 00:00:00 2001 From: bordumb Date: Tue, 6 Oct 2026 03:12:38 +0100 Subject: [PATCH 003/108] build(gateway): package the operator handoff and exercise emergency shutdown --- .github/CODEOWNERS | 2 + .../workflows/gateway-operator-package.yml | 63 +++++++++++++++ compliance.toml | 2 +- deployment/gateway/README.md | 16 +++- deployment/gateway/operator.conf.example | 2 +- deployment/gateway/run-with-postgres-url | 6 ++ deployment/gateway/runtime.conf.example | 1 - .../systemd/auths-gateway-doctor.service | 3 +- .../gateway/systemd/auths-gateway.service | 3 +- deployment/gateway/tools/package.py | 53 +++++++++++++ .../auths-gateway/tests/operator_plane.rs | 79 +++++++++++++++++++ release/semantic-freeze-versions.toml | 8 +- release/semantic-freeze.json | 14 ++-- 13 files changed, 233 insertions(+), 19 deletions(-) create mode 100644 .github/workflows/gateway-operator-package.yml create mode 100755 deployment/gateway/run-with-postgres-url create mode 100644 deployment/gateway/tools/package.py diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index f08dcb81a..b117a5524 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -7,3 +7,5 @@ /product/ @auths-dev/product-maintainers @auths-dev/security /bindings/ @auths-dev/binding-maintainers @auths-dev/security /demos/ @auths-dev/product-maintainers + +/deployment/ @auths-dev/product-maintainers @auths-dev/security diff --git a/.github/workflows/gateway-operator-package.yml b/.github/workflows/gateway-operator-package.yml new file mode 100644 index 000000000..706f5e4c8 --- /dev/null +++ b/.github/workflows/gateway-operator-package.yml @@ -0,0 +1,63 @@ +name: Gateway operator package + +on: + pull_request: + paths: + - 'deployment/gateway/**' + - 'product/runtime/auths-gateway/**' + - 'product/qualification/**' + - 'docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md' + - '.github/workflows/gateway-operator-package.yml' + workflow_dispatch: + +permissions: + contents: read + +jobs: + package: + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 + with: + persist-credentials: false + - uses: ./.github/actions/setup-rust-cache + with: + toolchain: 1.97.1 + - name: Build shipped operator binaries without test features + run: cargo build --locked --release -p auths-gateway -p auths-recipe-qualification-issuance --bin auths-gateway --bin auths-qualification + - name: Make the source-free handoff + run: | + python3 deployment/gateway/tools/package.py \ + --gateway target/release/auths-gateway \ + --qualification target/release/auths-qualification \ + --commit "$(git rev-parse HEAD)" \ + --output target/gateway-operator-package.tgz + - name: Verify the packaged payload and command surfaces + run: | + mkdir -p "$RUNNER_TEMP/operator" + tar xzf target/gateway-operator-package.tgz -C "$RUNNER_TEMP/operator" + cd "$RUNNER_TEMP/operator/auths-gateway-operator" + python3 - <<'PY' + import hashlib, json + from pathlib import Path + manifest = json.loads(Path('manifest.json').read_text()) + assert manifest['schema'] == 'auths.gateway-operator-package/1' + for item in manifest['files']: + assert hashlib.sha256(Path(item['path']).read_bytes()).hexdigest() == item['sha256'] + assert not list(Path('.').rglob('*.rs')) + PY + bin/auths-gateway disable --help | grep -- --store-only + bin/auths-gateway rotate-prepare --help | grep -- --operator-process + bin/auths-gateway doctor --help + bin/auths-qualification --help + - name: Verify systemd unit syntax + run: systemd-analyze verify deployment/gateway/systemd/*.service deployment/gateway/systemd/*.timer + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 + with: + name: gateway-operator-package + path: | + target/gateway-operator-package.tgz + target/gateway-operator-package.tgz.sha256 + if-no-files-found: error + retention-days: 30 diff --git a/compliance.toml b/compliance.toml index 4f0d8ee5d..d27733581 100644 --- a/compliance.toml +++ b/compliance.toml @@ -1589,7 +1589,7 @@ configuration_inputs = ["operator-approved-recipe", "profile-lock", "independent security_state = ["host-generation-floor", "recipe-digest", "logical-operation-claims", "credential-reference-generation", "shared-connection-record", "credential-generation", "in-flight-entry-count", "echo-bound-provider-evidence", "observer-signing-seed", "custody-held-observer-key", "principal-separation", "key-identity-separation", "pre-entry-evidence", "relative-ceiling-basis", "gateway-record-batches", "link-subject-count-and-sum-slots", "verified-qualification-index", "remembered-revocations", "accepted-revocation-sequence", "gateway-semantic-closure"] [packages.auths-gateway.claims] -operator-production-readiness = [ +operational-diagnostics = [ "product/runtime/auths-gateway/src/readiness.rs#the_projection_names_every_check_and_retains_precise_qualification_failure", "product/runtime/auths-gateway/src/engine.rs#readiness_and_emergency_stop_make_no_credential_lease", "product/runtime/auths-gateway/src/engine.rs#a_restored_store_below_the_host_floor_cannot_lease_after_restart", diff --git a/deployment/gateway/README.md b/deployment/gateway/README.md index 5211f5a2d..1afd27799 100644 --- a/deployment/gateway/README.md +++ b/deployment/gateway/README.md @@ -9,6 +9,11 @@ checksums under `/opt/auths/bin`; neither source nor a compiler belongs on the hosts. Current production builds refuse writes until the qualification root ceremony and both live qualification gates have completed. +The `Gateway operator package` workflow supplies a source-free archive with +both binaries, these units, a bounded file-digest manifest and the runbook. +Verify the artifact checksum and each payload digest before using it in the +independent trial. A PR artifact is a trial input, not a signed release. + ## Host setup Create group `auths-app-socket` (GID 62000), user `auths-gateway` (UID 62001), @@ -27,10 +32,15 @@ and GenerateDataKey. Neither role can list secrets or alter versions. The operator executes administration as UID 62001 with its separate token path. The application receives neither identity directory nor runtime environment. -Copy `systemd/` and the reviewed public runtime configuration. Never place a +Copy `systemd/`, `run-with-postgres-url` and the reviewed public runtime configuration. +The protected `/etc/auths/postgres-url` file holds the PostgreSQL connection +string; systemd delivers it in its service credential directory. The wrapper +passes it only to the gateway process, whose doctor probe clears its environment. Never place a provider token, static AWS access key or release signer in an environment file. -Use certificate/peer authentication for PostgreSQL, or a protected passfile -owned by the gateway; require the expected TLS server name and reviewed CA. +Use a dedicated PostgreSQL password delivered through systemd LoadCredential, +not an application environment or command argument. The maintained TLS client +authenticates the server with the expected name and reviewed CA; it does not +provide TLS client-certificate authentication. Enable `synchronous_commit`, durable WAL and continuous archive to independent storage. Let the shipped store apply its current schema; obsolete schemas are refused rather than translated. Take and restore a database snapshot in the diff --git a/deployment/gateway/operator.conf.example b/deployment/gateway/operator.conf.example index ee0bc0be9..9d124d6b7 100644 --- a/deployment/gateway/operator.conf.example +++ b/deployment/gateway/operator.conf.example @@ -1,5 +1,5 @@ # Operator reads and administers custody; runtime role only reads it. -AUTHS_POSTGRES_URL=host=postgres.internal port=5432 dbname=auths user=auths sslmode=require +# Supply AUTHS_POSTGRES_URL from the protected operator secret source. AUTHS_POSTGRES_CA_PEM=/etc/auths/postgres-ca.pem AUTHS_POSTGRES_SERVER_NAME=postgres.internal AWS_ROLE_ARN=arn:aws:iam::ACCOUNT:role/auths-operator diff --git a/deployment/gateway/run-with-postgres-url b/deployment/gateway/run-with-postgres-url new file mode 100755 index 000000000..8345a257d --- /dev/null +++ b/deployment/gateway/run-with-postgres-url @@ -0,0 +1,6 @@ +#!/bin/sh +set -eu +: "${CREDENTIALS_DIRECTORY:?systemd credential directory is required}" +AUTHS_POSTGRES_URL=$(cat "$CREDENTIALS_DIRECTORY/postgres-url") +export AUTHS_POSTGRES_URL +exec "$@" diff --git a/deployment/gateway/runtime.conf.example b/deployment/gateway/runtime.conf.example index aa883e2c2..acfc869cb 100644 --- a/deployment/gateway/runtime.conf.example +++ b/deployment/gateway/runtime.conf.example @@ -1,5 +1,4 @@ # Public configuration only. Web identity tokens are short-lived files, never env values. -AUTHS_POSTGRES_URL=host=postgres.internal port=5432 dbname=auths user=auths sslmode=require AUTHS_POSTGRES_CA_PEM=/etc/auths/postgres-ca.pem AUTHS_POSTGRES_SERVER_NAME=postgres.internal AWS_ROLE_ARN=arn:aws:iam::ACCOUNT:role/auths-runtime diff --git a/deployment/gateway/systemd/auths-gateway-doctor.service b/deployment/gateway/systemd/auths-gateway-doctor.service index 51365e358..872eda223 100644 --- a/deployment/gateway/systemd/auths-gateway-doctor.service +++ b/deployment/gateway/systemd/auths-gateway-doctor.service @@ -7,7 +7,8 @@ Type=oneshot User=root UMask=0077 EnvironmentFile=/etc/auths/runtime.conf -ExecStart=/opt/auths/bin/auths-gateway doctor --state-dir /var/lib/auths/gateway --app-socket /run/auths-app/gateway.sock --app-uid 62002 --app-gid 62000 +LoadCredential=postgres-url:/etc/auths/postgres-url +ExecStart=/opt/auths/bin/run-with-postgres-url /opt/auths/bin/auths-gateway doctor --state-dir /var/lib/auths/gateway --app-socket /run/auths-app/gateway.sock --app-uid 62002 --app-gid 62000 NoNewPrivileges=yes ProtectSystem=strict ProtectHome=yes diff --git a/deployment/gateway/systemd/auths-gateway.service b/deployment/gateway/systemd/auths-gateway.service index 8b37a923d..2912915c7 100644 --- a/deployment/gateway/systemd/auths-gateway.service +++ b/deployment/gateway/systemd/auths-gateway.service @@ -9,7 +9,8 @@ User=auths-gateway Group=auths-app-socket UMask=0077 EnvironmentFile=/etc/auths/runtime.conf -ExecStart=/opt/auths/bin/auths-gateway serve --state-dir /var/lib/auths/gateway --app-socket /run/auths-app/gateway.sock +LoadCredential=postgres-url:/etc/auths/postgres-url +ExecStart=/opt/auths/bin/run-with-postgres-url /opt/auths/bin/auths-gateway serve --state-dir /var/lib/auths/gateway --app-socket /run/auths-app/gateway.sock Restart=on-failure RestartSec=5 TimeoutStopSec=35 diff --git a/deployment/gateway/tools/package.py b/deployment/gateway/tools/package.py new file mode 100644 index 000000000..706059e55 --- /dev/null +++ b/deployment/gateway/tools/package.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python3 +"""Make the operator handoff from built binaries and public deployment files.""" +import argparse +import gzip +import hashlib +import io +import json +from pathlib import Path +import tarfile + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("--gateway", type=Path, required=True) + parser.add_argument("--qualification", type=Path, required=True) + parser.add_argument("--commit", required=True) + parser.add_argument("--output", type=Path, required=True) + args = parser.parse_args() + if len(args.commit) != 40 or any(c not in "0123456789abcdef" for c in args.commit): + parser.error("commit must be a full lowercase SHA") + root = Path(__file__).resolve().parents[3] + files = { + "bin/auths-gateway": (args.gateway.read_bytes(), 0o755), + "bin/auths-qualification": (args.qualification.read_bytes(), 0o755), + "bin/run-with-postgres-url": ((root / "deployment/gateway/run-with-postgres-url").read_bytes(), 0o755), + "docs/GATEWAY_PRODUCTION_RUNBOOK.md": ((root / "docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md").read_bytes(), 0o644), + } + reference = root / "deployment/gateway" + for path in sorted(reference.rglob("*")): + if path.is_file() and "tools" not in path.relative_to(reference).parts and path.name != "run-with-postgres-url": + files["reference/" + path.relative_to(reference).as_posix()] = (path.read_bytes(), 0o644) + manifest = { + "schema": "auths.gateway-operator-package/1", + "source_commit": args.commit, + "qualification_claim": "none; verify exact signed inputs separately", + "files": [{"path": name, "sha256": hashlib.sha256(data).hexdigest()} for name, (data, _) in sorted(files.items())], + } + files["manifest.json"] = ((json.dumps(manifest, sort_keys=True, separators=(",", ":")) + "\n").encode(), 0o644) + args.output.parent.mkdir(parents=True, exist_ok=True) + with args.output.open("wb") as destination: + with gzip.GzipFile(fileobj=destination, mode="wb", filename="", mtime=0) as compressed: + with tarfile.open(fileobj=compressed, mode="w", format=tarfile.USTAR_FORMAT) as archive: + for name, (data, mode) in sorted(files.items()): + info = tarfile.TarInfo("auths-gateway-operator/" + name) + info.size, info.mode, info.mtime = len(data), mode, 0 + archive.addfile(info, io.BytesIO(data)) + digest = hashlib.sha256(args.output.read_bytes()).hexdigest() + args.output.with_suffix(args.output.suffix + ".sha256").write_text(digest + " " + args.output.name + "\n") + print(json.dumps({"archive": args.output.name, "sha256": digest, "files": len(files)})) + + +if __name__ == "__main__": + main() diff --git a/product/runtime/auths-gateway/tests/operator_plane.rs b/product/runtime/auths-gateway/tests/operator_plane.rs index 44e4f38e1..ab5f9106d 100644 --- a/product/runtime/auths-gateway/tests/operator_plane.rs +++ b/product/runtime/auths-gateway/tests/operator_plane.rs @@ -589,3 +589,82 @@ fn postgres_production_processes_share_the_connection() { assert_eq!(revoked["code"], "gateway.admin.revoked", "{revoked}"); assert_eq!(status(&second)["state"], "revoked"); } + +#[test] +fn an_emergency_stop_works_with_no_running_gateway_or_readable_custody() { + let (_directory, root) = private_root(); + let state = root.join("emergency"); + let installed = install( + &root, + &state, + &["--account-label", "fixture"], + b"synthetic-token\n", + ); + assert!(installed.status.success(), "{}", stderr(&installed)); + fs::remove_file(state.join("credentials.cbor")).expect("remove custody"); + fs::write( + state.join("qualification-verifier-state.json"), + b"unavailable", + ) + .expect("bad qualification"); + for (command, expected) in [ + ("disable", "disabled"), + ("disable", "disabled"), + ("revoke", "revoked"), + ("disable", "revoked"), + ] { + let stopped = run( + Command::new(BIN) + .arg(command) + .arg("--state-dir") + .arg(&state) + .arg("--store-only"), + b"", + ); + assert!(stopped.status.success(), "{}", stderr(&stopped)); + let report: serde_json::Value = serde_json::from_slice(&stopped.stdout).expect("report"); + assert_eq!(report["state"], expected); + assert_eq!(report["drainage"], "not-checked"); + assert_eq!(report["credential_deletion"], "not-attempted"); + } +} + +#[test] +fn sigterm_drains_admitted_sessions_and_removes_both_socket_paths() { + let (_directory, root) = private_root(); + let state = root.join("shutdown"); + let installed = install( + &root, + &state, + &["--account-label", "fixture"], + b"synthetic-token\n", + ); + assert!(installed.status.success(), "{}", stderr(&installed)); + let app = root.join("shutdown.sock"); + let mut gateway = serve(&state, &app); + let pending = std::os::unix::net::UnixStream::connect(&app).expect("admitted stream"); + thread::sleep(Duration::from_millis(100)); + let signal = Command::new("kill") + .arg("-TERM") + .arg(gateway.0.id().to_string()) + .status() + .expect("signal"); + assert!(signal.success()); + thread::sleep(Duration::from_millis(100)); + assert!( + gateway.0.try_wait().expect("wait").is_none(), + "an admitted session is still draining" + ); + drop(pending); + let deadline = Instant::now() + Duration::from_secs(5); + loop { + if let Some(status) = gateway.0.try_wait().expect("wait") { + assert!(status.success()); + break; + } + assert!(Instant::now() < deadline, "shutdown did not complete"); + thread::sleep(Duration::from_millis(20)); + } + assert!(!app.exists()); + assert!(!state.join("admin.sock").exists()); +} diff --git a/release/semantic-freeze-versions.toml b/release/semantic-freeze-versions.toml index c7ef5cb1c..af1dc6277 100644 --- a/release/semantic-freeze-versions.toml +++ b/release/semantic-freeze-versions.toml @@ -1,4 +1,4 @@ -freeze_version = 359 +freeze_version = 360 # Semantic identity counters live outside the xtask source tree deliberately. # The formal source closure binds xtask's executable code, while the semantic @@ -45,7 +45,7 @@ freeze_version = 359 "auths.frozen-bytes/product/integrations/auths-stripe/fixtures/subscription-create/v1/manifest.sha256.json" = 1 "auths.frozen-bytes/product/integrations/auths-stripe/fixtures/subscription-modify/v1/manifest.sha256.json" = 1 "auths.frozen-bytes/product/integrations/auths-stripe/fixtures/v1/manifest.sha256.json" = 1 -"auths.identity.protocol" = 115 +"auths.identity.protocol" = 116 "auths.modular-components" = 20 "auths.portable-abi-bindings" = 121 "auths.product.bounded-domains" = 19 @@ -60,11 +60,11 @@ freeze_version = 359 "auths.product.mcp-closed-execution" = 31 "auths.product.mechanism-profile-conformance" = 12 "auths.product.operations" = 5 -"auths.product.public-sdk-contract" = 112 +"auths.product.public-sdk-contract" = 113 "auths.product.receipts" = 13 "auths.product.release-assurance" = 7 "auths.product.simplified-waist" = 19 "auths.product.vocabulary" = 23 "auths.release.benchmark-contract" = 1 "auths.release.evolution-contract" = 79 -"auths.release.public-surface" = 359 +"auths.release.public-surface" = 360 diff --git a/release/semantic-freeze.json b/release/semantic-freeze.json index fa2989588..964c0dff4 100644 --- a/release/semantic-freeze.json +++ b/release/semantic-freeze.json @@ -1,6 +1,6 @@ { "schema": "auths.semantic-freeze/1", - "freezeVersion": 359, + "freezeVersion": 360, "publicSurface": { "rustRoots": [ "auths", @@ -550,7 +550,7 @@ }, { "id": "auths.identity.protocol", - "version": 115, + "version": 116, "classification": "frozen-meaning", "categories": [ "identity-protocol-versions", @@ -573,7 +573,7 @@ "core/fixtures/identity/v1/vectors.json", "core/spec/identity/v1" ], - "sha256": "46396d619784df07676d8fe7606d4d24e9312974e0db513847630a48cfab72df" + "sha256": "8332d64571a9d9af8486d75dc680458804f87e1ec79fd00fcdff7cb0a7ffa878" }, { "id": "auths.modular-components", @@ -871,7 +871,7 @@ }, { "id": "auths.product.public-sdk-contract", - "version": 112, + "version": 113, "classification": "frozen-meaning", "categories": [ "rust-sdk-contract", @@ -889,7 +889,7 @@ "product/runtime/auths-runtime/src", "product/sdk/auths-sdk/src" ], - "sha256": "aac1b94991d0b0669f54e1c41284eab01f9a4a31c656fe93b95a92a6e350e29f" + "sha256": "eec5e98f3be166ba41a3cc0fea3e68f9b06b6a70f627e6c0a21197ed6fcb6b6a" }, { "id": "auths.product.receipts", @@ -1011,7 +1011,7 @@ }, { "id": "auths.release.public-surface", - "version": 359, + "version": 360, "classification": "release-metadata", "categories": [ "package-names", @@ -1103,7 +1103,7 @@ "xtask/src/release_control.rs", "xtask/src/semantic_freeze.rs" ], - "sha256": "506c17e8147d2cfcc6e9f695c83a3927e5a9dfa9fe834974545b45ecef3dd08b" + "sha256": "7f3fc11e903ce96749acaebcb5089c7f426d49e4881bd83fd85310f7cca9d838" } ] } From 73694ccedd9b7433813ae1137a9f5d9bc6d2ebda Mon Sep 17 00:00:00 2001 From: bordumb Date: Tue, 6 Oct 2026 03:20:04 +0100 Subject: [PATCH 004/108] fix(gateway): persist credential cleanup and check runtime readiness as its owner --- .../workflows/gateway-operator-package.yml | 5 +- .../fixtures/gateway/production-codes.json | 8 + compliance.toml | 6 +- docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md | 19 +- .../qualification/aeneas/source-closure.json | 4 +- .../src/store.rs | 18 +- .../auths-connections/src/credential.rs | 56 ++++- .../auths-gateway/semantic-closure.json | 2 +- .../auths-gateway/src/bin/auths-gateway.rs | 186 +++++++++++++--- .../auths-gateway/src/credential_journal.rs | 200 ++++++++++++++++++ product/runtime/auths-gateway/src/engine.rs | 157 ++++++++++++++ product/runtime/auths-gateway/src/lib.rs | 2 + .../src/pending_vectors/production.rs | 1 + .../runtime/auths-gateway/src/readiness.rs | 10 +- .../auths-gateway/src/semantic_closure.rs | 2 +- release/semantic-freeze-versions.toml | 10 +- release/semantic-freeze.json | 18 +- 17 files changed, 635 insertions(+), 69 deletions(-) create mode 100644 product/runtime/auths-gateway/src/credential_journal.rs diff --git a/.github/workflows/gateway-operator-package.yml b/.github/workflows/gateway-operator-package.yml index 706f5e4c8..4413dc7e9 100644 --- a/.github/workflows/gateway-operator-package.yml +++ b/.github/workflows/gateway-operator-package.yml @@ -52,7 +52,10 @@ jobs: bin/auths-gateway doctor --help bin/auths-qualification --help - name: Verify systemd unit syntax - run: systemd-analyze verify deployment/gateway/systemd/*.service deployment/gateway/systemd/*.timer + run: | + sudo install -D "$RUNNER_TEMP/operator/auths-gateway-operator/bin/auths-gateway" /opt/auths/bin/auths-gateway + sudo install -D "$RUNNER_TEMP/operator/auths-gateway-operator/bin/run-with-postgres-url" /opt/auths/bin/run-with-postgres-url + systemd-analyze verify deployment/gateway/systemd/*.service deployment/gateway/systemd/*.timer - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: name: gateway-operator-package diff --git a/bindings/fixtures/gateway/production-codes.json b/bindings/fixtures/gateway/production-codes.json index e630182c7..77b9b07c3 100644 --- a/bindings/fixtures/gateway/production-codes.json +++ b/bindings/fixtures/gateway/production-codes.json @@ -1,6 +1,14 @@ { "schema": "auths.gateway-production-codes/1", "codes": [ + { + "code": "gateway.admin.credential-journal-unavailable", + "owner": "operator", + "stage": "before-custody", + "status": "implemented", + "epic": 4, + "case": null + }, { "code": "gateway.attempt.replay", "owner": "engine", diff --git a/compliance.toml b/compliance.toml index d27733581..08ee52285 100644 --- a/compliance.toml +++ b/compliance.toml @@ -1578,7 +1578,7 @@ kind = "cargo" layer = "product" path = "product/runtime/auths-gateway" core_apis = ["auths-author", "auths-codec", "auths-did-keri", "auths-did-key", "auths-model", "auths-multikey", "auths-ports", "auths-raw-key", "auths-raw-key-core", "auths-registries", "auths-signature", "auths-verifier"] -protocol_versions = ["auths.gateway-readiness/1", "auths.gateway-support-bundle/1", "auths.gateway-generation-floor/1", "auths.gateway-emergency-stop/1", "auths.gateway-installation/5", "auths.recipe-qualification/1", "auths.recipe-qualification-attestation/1", "auths.qualification-trust-root/1", "auths.qualification-signer-certificate/1", "auths.qualification-revocation-list/1", "auths.qualification-release-index/1", "auths.gateway-semantic-closure/1", "auths.qualification-verification-vectors/1", "auths.gateway-operator-attestation/1", "auths.gateway-admin-request/1", "auths.gateway-admin-response/1", "auths.gateway-connection/1", "auths.provider-connection/2", "auths.gateway-key-identity/1", "auths.lifecycle.transactional-store/4", "auths.gateway-recipe-source/2", "auths.gateway-compiled-recipe/2", "auths.gateway-recipe-review/2", "auths.gateway-recovery-capability/1", "auths.gateway-connection-descriptor/1", "auths.gateway-attempt/3", "auths.gateway-pre-entry/1", "auths.lifecycle.postgresql/5", "auths.gateway-echo/1", "auths.gateway-idempotency-key/1", "auths.gateway-observe/2", "auths.gateway-outcome/2", "auths.gateway-readback/1", "auths.self-hosted-profile-lock/1", "mcp-arguments-v1", "auths.gateway-audit-bundle/2", "auths.gateway-audit-report/3", "auths.gateway-counter-set/1", "auths.gateway-echo-verification/1", "auths.gateway-codes/1", "auths.gateway-production-codes/1", "auths.gateway-custody-vectors/1", "auths.gateway-outcome-vectors/1", "bounded-policy-commitment-v1", "auths.approval-response/1", "auths.gateway-bounded-count/2", "auths.gateway-bounded-sum/1", "auths.gateway.argument-ceiling-window-count/2", "auths.gateway.argument-ceiling-policy/2"] +protocol_versions = ["auths.gateway-credential-journal/1", "auths.gateway-credential-collection/1", "auths.gateway-readiness/1", "auths.gateway-support-bundle/1", "auths.gateway-generation-floor/1", "auths.gateway-emergency-stop/1", "auths.gateway-installation/5", "auths.recipe-qualification/1", "auths.recipe-qualification-attestation/1", "auths.qualification-trust-root/1", "auths.qualification-signer-certificate/1", "auths.qualification-revocation-list/1", "auths.qualification-release-index/1", "auths.gateway-semantic-closure/1", "auths.qualification-verification-vectors/1", "auths.gateway-operator-attestation/1", "auths.gateway-admin-request/1", "auths.gateway-admin-response/1", "auths.gateway-connection/1", "auths.provider-connection/2", "auths.gateway-key-identity/1", "auths.lifecycle.transactional-store/4", "auths.gateway-recipe-source/2", "auths.gateway-compiled-recipe/2", "auths.gateway-recipe-review/2", "auths.gateway-recovery-capability/1", "auths.gateway-connection-descriptor/1", "auths.gateway-attempt/3", "auths.gateway-pre-entry/1", "auths.lifecycle.postgresql/5", "auths.gateway-echo/1", "auths.gateway-idempotency-key/1", "auths.gateway-observe/2", "auths.gateway-outcome/2", "auths.gateway-readback/1", "auths.self-hosted-profile-lock/1", "mcp-arguments-v1", "auths.gateway-audit-bundle/2", "auths.gateway-audit-report/3", "auths.gateway-counter-set/1", "auths.gateway-echo-verification/1", "auths.gateway-codes/1", "auths.gateway-production-codes/1", "auths.gateway-custody-vectors/1", "auths.gateway-outcome-vectors/1", "bounded-policy-commitment-v1", "auths.approval-response/1", "auths.gateway-bounded-count/2", "auths.gateway-bounded-sum/1", "auths.gateway.argument-ceiling-window-count/2", "auths.gateway.argument-ceiling-policy/2"] wire_objects = ["CompiledRecipe", "ClosedProviderRequest", "ClosedCredentialReads", "RecipeReview", "RecoveryCapability", "GatewayAttemptSnapshot", "GatewayPreEntry", "GatewayRecordEntry", "GatewayConnectionDescriptor", "ConnectionRecord", "OperatorAttestation", "OperatorStatement", "GatewayAdminStatus", "GatewayEvidenceSummary", "GatewayObserveRequest", "GatewayObserveResult", "GatewayProviderEvidence", "GatewaySubmitResult", "SignedObservation", "ArgumentCeilingPolicy", "BoundedPolicyCommitment", "AuditReport", "ProviderResult", "AuditedPreEntry", "EchoVerification", "AdminRequestCommand", "ListedValues"] fixture_suites = ["bindings/fixtures/approval", "bindings/fixtures/gateway", "bindings/fixtures/qualification"] principal_families = ["raw-key-v1", "did-key-v1", "did-keri-v1"] @@ -1586,10 +1586,12 @@ signature_families = ["ed25519-v1", "p256-sha256-v1"] profiles = ["auths.mcp/2"] transports = ["bounded-https", "postgresql-tls", "loopback-http-development"] configuration_inputs = ["operator-approved-recipe", "profile-lock", "independently-provisioned-trust", "connection-binding", "observer-anchor", "observer-signing-key", "deployment-kind", "operator-attestation", "app-capacity", "development-shared-file-store", "postgresql-store-configuration", "audit-trust-and-observer-pins", "qualification-policy", "recipe-family", "provider-contract-id", "qualification-release-inputs", "deployment-clock"] -security_state = ["host-generation-floor", "recipe-digest", "logical-operation-claims", "credential-reference-generation", "shared-connection-record", "credential-generation", "in-flight-entry-count", "echo-bound-provider-evidence", "observer-signing-seed", "custody-held-observer-key", "principal-separation", "key-identity-separation", "pre-entry-evidence", "relative-ceiling-basis", "gateway-record-batches", "link-subject-count-and-sum-slots", "verified-qualification-index", "remembered-revocations", "accepted-revocation-sequence", "gateway-semantic-closure"] +security_state = ["durable-credential-cleanup-notes", "host-generation-floor", "recipe-digest", "logical-operation-claims", "credential-reference-generation", "shared-connection-record", "credential-generation", "in-flight-entry-count", "echo-bound-provider-evidence", "observer-signing-seed", "custody-held-observer-key", "principal-separation", "key-identity-separation", "pre-entry-evidence", "relative-ceiling-basis", "gateway-record-batches", "link-subject-count-and-sum-slots", "verified-qualification-index", "remembered-revocations", "accepted-revocation-sequence", "gateway-semantic-closure"] [packages.auths-gateway.claims] operational-diagnostics = [ + "product/runtime/auths-gateway/src/credential_journal.rs#notes_survive_restart_and_refuse_missing_corrupt_full_or_foreign_state", + "product/runtime/auths-gateway/src/engine.rs#durable_cleanup_retires_abandoned_generations_and_keeps_active_and_future_secrets", "product/runtime/auths-gateway/src/readiness.rs#the_projection_names_every_check_and_retains_precise_qualification_failure", "product/runtime/auths-gateway/src/engine.rs#readiness_and_emergency_stop_make_no_credential_lease", "product/runtime/auths-gateway/src/engine.rs#a_restored_store_below_the_host_floor_cannot_lease_after_restart", diff --git a/docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md b/docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md index 8e3c46f59..1ad561093 100644 --- a/docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md +++ b/docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md @@ -35,10 +35,19 @@ it. Retain only the returned reference commitment. Then use `rotate-commit --operator-process --state-dir ... --commitment ...` to atomically publish it. Check status on both hosts; each must see the same shared generation and hold the exact committed credential generation. The old generation remains for at -least the fixed 20-second retirement delay. Repeat the exercise with a stop +least the fixed 20-second retirement delay. Run `credential-collect --state-dir +...` under operator identity on each host that created a generation; it waits +20 seconds after observing the record, requires that record unchanged, then +deletes at most sixteen obsolete exact generations. It keeps the active and +future prepared generations. Rerun after a conflict or deletion failure. +Durable `credential-journal.json` notes are written before storing a candidate, +so partial setup or a process exit does not lose its cleanup obligation. +An abandoned future generation becomes collectable after disabling advances +the shared generation past it. Collect before preparing another successor. Repeat the exercise with a stop between prepare and commit; a stale commitment must fail, leaving the old -record authoritative. For emergency cutover: disable, rotate while disabled, -verify both hosts, then enable. Never retain a new secret in terminal history. +record authoritative. For emergency cutover: disable, wait the fixed 20 seconds for entries on +both hosts, rotate while disabled, collect old generations under operator +identity, verify both hosts, then enable. Never retain a new secret in terminal history. Operator-process drainage describes only that short-lived process; wait for all serving hosts separately before retiring external credentials. @@ -67,8 +76,8 @@ in an online agent workspace. ## Backup, point-in-time restore and restart Archive PostgreSQL WAL continuously and take encrypted snapshots. Back up -public installation files, operator attestation, qualification inputs and host -floors. Keep `connection-floor.json` and qualification verifier floors in an +public installation files, operator attestation, qualification inputs, credential +journals and host floors. Keep `connection-floor.json` and qualification verifier floors in an independent current recovery record; never restore older floors together with an older database. Before an exercise, record connection and credential generations, recipe/lock digests, qualification issue-time/revocation floors diff --git a/formal/qualification/aeneas/source-closure.json b/formal/qualification/aeneas/source-closure.json index 5516e2872..1c561bf7d 100644 --- a/formal/qualification/aeneas/source-closure.json +++ b/formal/qualification/aeneas/source-closure.json @@ -1,6 +1,6 @@ { "schema": "auths-proof-translation-source-closure/v2", - "digest": "2bca9ace40adf13142803e2d37730f8bb9b4dd622a537ab2e0eb28779561952a", + "digest": "3d7b77451c335933a5aab866761f8672e773055a752661349c71fabf3b9e4f87", "files": [ { "path": ".cargo/config.toml", @@ -157,7 +157,7 @@ }, { "path": "product/runtime/auths-connections/src/credential.rs", - "sha256": "4d532c221d2fe7a2b47c8720be94c26d0c86a0448c3f66f479ce3b12adf44f25" + "sha256": "82921413bb053f0f6c7931fbd4e6a86c8cc1d8c6b51debd9c2cef33a8d5b1c51" }, { "path": "product/runtime/auths-connections/src/kernel.rs", diff --git a/product/integrations/auths-credentials-aws-secrets-manager/src/store.rs b/product/integrations/auths-credentials-aws-secrets-manager/src/store.rs index 725ea506e..c97640677 100644 --- a/product/integrations/auths-credentials-aws-secrets-manager/src/store.rs +++ b/product/integrations/auths-credentials-aws-secrets-manager/src/store.rs @@ -123,10 +123,14 @@ impl ConnectionCredentialStore for AwsSecretsManagerStore { generation: NonZeroU64, ) -> Result<(), CredentialStoreError> { let name = secret_name(&self.namespace, connection_id, generation); - self.api + match self + .api .delete(&name, Instant::now() + ADMINISTRATION_DEADLINE) .await - .map_err(|_| CredentialStoreError::Unavailable) + { + Ok(()) | Err(SecretsApiError::NotFound) => Ok(()), + Err(_) => Err(CredentialStoreError::Unavailable), + } } async fn holds(&self, binding: &CredentialBinding) -> Result<(), CredentialStoreError> { @@ -478,6 +482,16 @@ mod tests { ); } + #[test] + fn deleting_an_exact_generation_is_idempotent_for_cleanup_retries() { + let double = Double::new(); + let store = store(&double); + ready(store.install(&connection(), generation(1), secret(b"first"))).expect("install"); + assert_eq!(ready(store.revoke(&connection(), generation(1))), Ok(())); + assert_eq!(ready(store.revoke(&connection(), generation(1))), Ok(())); + assert_eq!(ready(store.revoke(&connection(), generation(2))), Ok(())); + } + #[test] fn confirming_checks_and_stores_nothing() { let double = Double::new(); diff --git a/product/runtime/auths-connections/src/credential.rs b/product/runtime/auths-connections/src/credential.rs index 1c93f8114..744c4bc84 100644 --- a/product/runtime/auths-connections/src/credential.rs +++ b/product/runtime/auths-connections/src/credential.rs @@ -248,7 +248,8 @@ pub trait ConnectionCredentialStore: Send + Sync { secret: SecretBytes, ) -> Result; - /// Revokes one exact generation. + /// Revokes one exact generation. An already absent generation succeeds, + /// so durable cleanup obligations can be retried after a lost response. async fn revoke( &self, connection_id: &ConnectionId, @@ -449,9 +450,7 @@ impl ConnectionCredentialStore for InMemoryCredentialStore { .entries .write() .map_err(|_| CredentialStoreError::Unavailable)?; - entries - .remove(&key) - .ok_or(CredentialStoreError::Unavailable)?; + entries.remove(&key); Ok(()) } @@ -1042,9 +1041,7 @@ impl ConnectionCredentialStore for PersistentCredentialStore { let key = (connection_id.as_str().to_owned(), generation.get()); self.mutate(|entries| { // Dropping the removed entry zeroizes its secret. - entries - .remove(&key) - .ok_or(CredentialStoreError::Unavailable)?; + entries.remove(&key); Ok(()) }) } @@ -1440,6 +1437,51 @@ mod tests { ); } + #[test] + fn exact_revocation_can_be_retried_after_a_lost_cleanup_response() { + let directory = tempfile::tempdir().expect("directory"); + #[cfg(unix)] + { + use std::os::unix::fs::PermissionsExt as _; + fs::set_permissions(directory.path(), fs::Permissions::from_mode(0o700)) + .expect("private directory"); + } + let memory = InMemoryCredentialStore::new(4, 1024).expect("memory"); + let file = PersistentCredentialStore::open_with_limits( + directory.path().join("credentials.cbor"), + 4, + 1024, + ) + .expect("file"); + let record = record(); + for store in [ + &memory as &dyn ConnectionCredentialStore, + &file as &dyn ConnectionCredentialStore, + ] { + futures_lite_for_tests(store.install( + record.connection_id(), + NonZeroU64::MIN, + SecretBytes::new(b"cleanup-fixture".to_vec()).expect("secret"), + )) + .expect("install"); + assert_eq!( + futures_lite_for_tests(store.revoke(record.connection_id(), NonZeroU64::MIN)), + Ok(()) + ); + assert_eq!( + futures_lite_for_tests(store.revoke(record.connection_id(), NonZeroU64::MIN)), + Ok(()) + ); + assert_eq!( + futures_lite_for_tests(store.revoke( + record.connection_id(), + NonZeroU64::new(2).expect("generation") + )), + Ok(()) + ); + } + } + #[test] fn persistent_store_reopens_exact_generation_without_exposing_secret() { let directory = tempfile::tempdir().unwrap(); diff --git a/product/runtime/auths-gateway/semantic-closure.json b/product/runtime/auths-gateway/semantic-closure.json index dc9ce118e..42aea6ca3 100644 --- a/product/runtime/auths-gateway/semantic-closure.json +++ b/product/runtime/auths-gateway/semantic-closure.json @@ -1 +1 @@ -{"files":[{"path":"Cargo.lock","sha256":"c94ed342774d5e2823f01ecf74b8a4812c5f9a6b0cf811d31f2e2cecb671a275"},{"path":"Cargo.toml","sha256":"6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24"},{"path":"core/adapters/auths-did-keri/Cargo.toml","sha256":"86ba3e3f9a0a70d970568bfb3113b7ba7bbdd81c3eebbb52743dd574a0c0ecaa"},{"path":"core/adapters/auths-did-keri/src/lib.rs","sha256":"a75674842f8a7142004369ccd206ab43e476459293f0ff4bed4d4e659031b3e3"},{"path":"core/adapters/auths-did-key/Cargo.toml","sha256":"d5a3ae07ecde83f91eed4c3785051dd0f44eab6c891754f3309b6b40596707d7"},{"path":"core/adapters/auths-did-key/src/lib.rs","sha256":"b76a3f4528a725df53cfa9242e6e414e1d26caa48468aaed497e28b121f4497c"},{"path":"core/adapters/auths-raw-key/Cargo.toml","sha256":"f49616bc18c19e6aaa7e6a02ccebcdb9f5c1422c1278ef9869e0dbf22ceda7be"},{"path":"core/adapters/auths-raw-key/src/lib.rs","sha256":"45eec1b295dac3bed65cd79c942870b926b06b3f5d38eaebaeb6140ac69315fa"},{"path":"core/crates/auths-algebra-kernel/Cargo.toml","sha256":"0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba"},{"path":"core/crates/auths-algebra-kernel/src/generated.rs","sha256":"ae4bcbef42a408c7ffa0c6a74a42f7de177a6f14479e51d205acf830bda05960"},{"path":"core/crates/auths-algebra-kernel/src/lib.rs","sha256":"6654667eeb9b353d6648954c9fd2e8838462a82ce6b2803eb49e1366892c68c6"},{"path":"core/crates/auths-assurance/Cargo.toml","sha256":"afcb12a97ddd09d7a264b9ecd3fcaefc865ff2c9b4539ee85b00883420ba333a"},{"path":"core/crates/auths-assurance/src/lib.rs","sha256":"0fb2ec844d674b25a9e20b1601452c89c2454901fa506adfa9bb38ef9a7fa213"},{"path":"core/crates/auths-author/Cargo.toml","sha256":"1e6f0e3bc079ddb558decf0db26b291c6e72fc47327b6df1b7650d41689b215f"},{"path":"core/crates/auths-author/src/lib.rs","sha256":"e14475f2f49715a1869d5fa6b11ff1fbb72497e39097e09f833b0bae7e5b3f2b"},{"path":"core/crates/auths-author/src/observations.rs","sha256":"dda7d6bfa6f4bd7e95a480ca283c2c0e996f69c5c15cb0c7197af328131a7066"},{"path":"core/crates/auths-authority/Cargo.toml","sha256":"4f68212938029f79ebd857b4f3038494eb85d0163d49f07e51376715cf959815"},{"path":"core/crates/auths-authority/src/lib.rs","sha256":"da88d5194de4e17449e69972c0fb042afa3c39798a8f570f30771e77c384f1eb"},{"path":"core/crates/auths-codec/Cargo.toml","sha256":"e20e51826e17814effd9d8925d18d5fbdd6c0d37bf50231e743ec2611314722c"},{"path":"core/crates/auths-codec/src/approval.rs","sha256":"fbff43bf4d57f69f8b7738a8647751cde75c5a932dee65d924a1fe9c7202f91f"},{"path":"core/crates/auths-codec/src/bounded_policy.rs","sha256":"d21f6728be2d8a04b6d94921f2b683f7e61cbb42e0ac6866f1c88a49caa534c3"},{"path":"core/crates/auths-codec/src/decode.rs","sha256":"ba2999584cdf53b1b517ecb9c7ea50d39efee17c666a9a38e2ad1ac94379f778"},{"path":"core/crates/auths-codec/src/encode.rs","sha256":"8491192053e2e15d62b4d2a491de22405b7487ead69ab6f6bca40669ce7ca5f7"},{"path":"core/crates/auths-codec/src/error.rs","sha256":"fecb0737c16deb42d859f1dc7727c698438d9ac12064fd99e0024629642c390c"},{"path":"core/crates/auths-codec/src/hash.rs","sha256":"f88e111f1dbb2cef6b7b5e9c948cb45ff92e366710c8a5f5c636138aa748479e"},{"path":"core/crates/auths-codec/src/lib.rs","sha256":"3b0e5c94c6f34f750b88a9333e1d5c8145746d845d3a23e0d2f61807cf592ea7"},{"path":"core/crates/auths-codec/src/observation.rs","sha256":"38328b0c71ff97a4196eeade8b4faa889527ff1f80bb168468bcd49082a3987e"},{"path":"core/crates/auths-composition/Cargo.toml","sha256":"331e13025eb82588b5269ed3975929eb41c823d588c49e4c296273d85c6fe80e"},{"path":"core/crates/auths-composition/src/lib.rs","sha256":"e42e3b0b6a9985b73c533aeb23799c638979aa27a9ce7d0f10a8d60340570fb1"},{"path":"core/crates/auths-model/Cargo.toml","sha256":"565c15302b0cc9270db1e28efa3862804846850ba933cc17aea8abcec4a65987"},{"path":"core/crates/auths-model/src/approval.rs","sha256":"54cf44a9ef747ec21546a4086aecfb130bc7803b0d646430e6082df51e6e305f"},{"path":"core/crates/auths-model/src/bounded.rs","sha256":"f90496abc0a06c028b4d850af6ddab7d850bfafeaa3d042f1b1246a41d8bbbc9"},{"path":"core/crates/auths-model/src/bounded_policy.rs","sha256":"306a8f049cc7cfc7635fe0e4de47eb7813eed63d3c14c3be2b51586aa4eea450"},{"path":"core/crates/auths-model/src/lib.rs","sha256":"e7cfe6bb9574c6b016aa63e70658c31e0b90903ec6479a49f4a2ceb64f5bad97"},{"path":"core/crates/auths-model/src/observation.rs","sha256":"b3ed3e3cc090afca2896a7d3de7988afccc1ee1ea0ebd91b51a8bc0f20ad8dbb"},{"path":"core/crates/auths-multikey/Cargo.toml","sha256":"858756c1197befcada06134742bffe8d58cf674cadd6c046bf710570e96efaf2"},{"path":"core/crates/auths-multikey/src/lib.rs","sha256":"f5177fffb11e40eeaaa665ba886c541fc1f24d5eacdd6983fb03dc20148733f0"},{"path":"core/crates/auths-ports/Cargo.toml","sha256":"596a9b0f5af3717c16a6d13f7054d8a106bcd9f01f5f72c2235dd2afcf0ab16c"},{"path":"core/crates/auths-ports/src/binding.rs","sha256":"a16c012d40aa4249e3ec54372b9611006d0bfe8c7dc3c741911c2194ad17736d"},{"path":"core/crates/auths-ports/src/diagnostics.rs","sha256":"aa596572503b5a65a918bb2ff38281c144ff53821ee914e9325c852828d852df"},{"path":"core/crates/auths-ports/src/lib.rs","sha256":"8da1debf86f9532df0660155d04298beb1ba3a1204508f8586e2e67cd2fb3449"},{"path":"core/crates/auths-ports/src/path.rs","sha256":"b68fc547b4e4d97a60cbbc1cc1939fc6b34a8233b81f840bd396914a707e3ea1"},{"path":"core/crates/auths-raw-key-core/Cargo.toml","sha256":"98c0bc8527a537512e43a74dd6ba9658c6f0cdc16610cf938e3f9b43785d836d"},{"path":"core/crates/auths-raw-key-core/src/lib.rs","sha256":"98c0500c41697aae28708ad0bf970b9a97583d96a3d2c18d23e7fa351e0f7d12"},{"path":"core/crates/auths-registries/Cargo.toml","sha256":"590e49e58b0622d9d6274fea46796dcdb07dec9550eff295cce6a6427ffa51e2"},{"path":"core/crates/auths-registries/src/lib.rs","sha256":"450d3886d85ee333b7e046317fb5b47cde62483d5f3e41d46265e2caf4c373ec"},{"path":"core/crates/auths-registries/src/template.rs","sha256":"1224039dd2b3ce6fa8357613d8cafbae40400493da7176da202b9ade62fa05e4"},{"path":"core/crates/auths-signature-core/Cargo.toml","sha256":"6bee2230eb30af1be0bd5c2d57bd3e1903497a70028d47290d4ac6e9e0e8bca0"},{"path":"core/crates/auths-signature-core/src/lib.rs","sha256":"6e3f9311ded5e49ea50d445eb21e6d8fa12442aa4362a73e0cb6fda15b7cd865"},{"path":"core/crates/auths-signature/Cargo.toml","sha256":"7f7b5682466ba439d8c59579022cb61068cad9fb4bd2d73e1cc21327c902b450"},{"path":"core/crates/auths-signature/src/lib.rs","sha256":"b3d9ac4cc3ba0797b9e1c09f2d6ac05089b25dac4e285a5af28c0165b33d925b"},{"path":"core/crates/auths-verifier/Cargo.toml","sha256":"c43358e06a33324b41a8b93e5cc7279c55f7d21f1f6cfaa539a3fc7b4c27a38f"},{"path":"core/crates/auths-verifier/src/approval.rs","sha256":"c3cae6a49e169051eb555bb092b1069a4d422516d6a2114623a89e5f31ff923f"},{"path":"core/crates/auths-verifier/src/causal.rs","sha256":"9635230f33b13a263573d319ac8a1976addbcc07677514a43e3c7bf28dc04587"},{"path":"core/crates/auths-verifier/src/lib.rs","sha256":"f22dec38dfa47ced8da4f605390da8453273bee1da010f57fd1fdfcb10e0b389"},{"path":"core/crates/auths-verifier/src/observation.rs","sha256":"0bb07f06a0f9524c88427df1c972b1de8ba038a9eeeb15d3134c25125ae84b1e"},{"path":"core/crates/auths-verifier/src/trace.rs","sha256":"2213d72023a1d9e0413a2cf2c51c3dad9e04775d86033a0caaa9d29a8f0036f8"},{"path":"exchange/crates/auths-proof-exchange-model/Cargo.toml","sha256":"34b2db64f93a288e942b5a3918d28cdcbef906e0dc9074ce848018d3d5f7a1fa"},{"path":"exchange/crates/auths-proof-exchange-model/src/lib.rs","sha256":"49fac5aff2339d3a57c41cb8bb2a82852538e8f77ecc4b157c88e264ff31fb55"},{"path":"exchange/crates/auths-proof-exchange-port/Cargo.toml","sha256":"7ff660f1b7579dc570c791090aeb450404fbbf44c92781e289f5ccdde746d739"},{"path":"exchange/crates/auths-proof-exchange-port/src/lib.rs","sha256":"b408fb40c6432edc1facb3d8b3e9433a033f8dc73fe2e0ba5a88c972ca675021"},{"path":"product/config/auths-config/Cargo.toml","sha256":"e4b568ab9f6d84f7d7e6d66443fe825f360db9c27bc7c31d6ddc0647ba3ab304"},{"path":"product/config/auths-config/src/lib.rs","sha256":"fecf00ea65cef9018fda9af2063326d7065b869266d0d9e73a4f06816f1102cc"},{"path":"product/errors/auths-errors/Cargo.toml","sha256":"3b3a199b6460ba75bda84475bb5accd35e1485448a3981038db85bf4772dd350"},{"path":"product/errors/auths-errors/src/lib.rs","sha256":"7feeb9069fa4003f94f1f07c1c94619cf1c883e0dbaaf2187f04d0f742264bdd"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/Cargo.toml","sha256":"716f1f2a117d6d69d8effe9ee9057e24ba3502f20af6a602b06facb638cdabed"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/api.rs","sha256":"b3c4321e0737835ecc4f17235d7589b7f3d62180954ebb98ea9449252300245a"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/clock.rs","sha256":"73f0a6e0f5903883329fa6683f5888288f759512ac69e5c87efd2b6b87f7d79f"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/http.rs","sha256":"14c1fce14e24c984b2a275563a29b6326fb08367922b6e8d37ba38b9cb81aa2b"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/identity.rs","sha256":"186de11230c8b33375951c4368609f8976bf9795f171af3fd7fac26207a94361"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs","sha256":"881ad9ccca369b6eaa6bfd9ec03b1585bff07b042da38942ef57154839449d3e"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/names.rs","sha256":"41bb23572d6002e23ee103d6fe70ecd68764861c6f2e48a1c53af998270a4afa"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs","sha256":"39fed883f4802e68d3b41a68fea0aba0737810996b33d13577de70faba004c29"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/store.rs","sha256":"32bb4b7ff3e7769d0ff46d374f80e4a2c44d7f8e8e82bbea58c9676690db45bb"},{"path":"product/integrations/auths-custody/Cargo.toml","sha256":"1e14034185ad1ec24a977fd5f41d0abee219606245c046ce2a82287fadef448b"},{"path":"product/integrations/auths-custody/src/conformance.rs","sha256":"8ed1afd58f18fc6becc268908aa6419c9aa404c79da0197963eb2599df44acf6"},{"path":"product/integrations/auths-custody/src/key.rs","sha256":"70cbb0fd21b6f5652157845a22c35be2d0f6c05b3d138fc4b9bb6dbdc3d81c40"},{"path":"product/integrations/auths-custody/src/lib.rs","sha256":"8ee593c1f59b0fd2126bdda9138026f5bc531beb64d4489a99785842e7b98b43"},{"path":"product/operations/auths-operations/Cargo.toml","sha256":"73dde1e914ba5e1386f8d49c0d730423cc72ae77ec44c6554a6a75cc8e8922b1"},{"path":"product/operations/auths-operations/src/explanation.rs","sha256":"b4a39bcbd5712cb9e735ee7deeb281f3fa6af5ddca973735bf3d87dce427ef11"},{"path":"product/operations/auths-operations/src/lib.rs","sha256":"3f401a56555113b98f57bca172a2660eaecedf76247b83a3fdbb089c133a29cd"},{"path":"product/operations/auths-operations/src/render/json.rs","sha256":"2ae042639960afee123730e945d373bc5dda1d2b3af20ae16c939a7e99b9e418"},{"path":"product/operations/auths-operations/src/render/mod.rs","sha256":"b3b7f6fe473f49227ace5a68bfc3d8dc14b5db8dd9888fd9e207070337b1b8bf"},{"path":"product/operations/auths-operations/src/render/text.rs","sha256":"f216cf3bdb00e264523271b16e7059535ac6b1aabf271cebd7935af155e4bfec"},{"path":"product/policy/auths-bounded-policy/Cargo.toml","sha256":"babd5d200923137ead71d8c2528f847cea323ce98da942a1320b054436612c47"},{"path":"product/policy/auths-bounded-policy/src/arithmetic.rs","sha256":"75e43c5d4eab8d1f71c1daf53839f5f9fe45a400afc1f63a30c6f55ce3632627"},{"path":"product/policy/auths-bounded-policy/src/commitment.rs","sha256":"c5706f2d583454e1a7f570f7ada138d4d864bef0205dfae7c1296774f396bb3f"},{"path":"product/policy/auths-bounded-policy/src/eligibility.rs","sha256":"c9acdfb793074e687fc36efad506be27dbd99ffbf40387bc66c8de39ef238432"},{"path":"product/policy/auths-bounded-policy/src/identifier.rs","sha256":"0006a32bae9eb16c4178cf797df418d2b0a781f2bc6474b741dc1a908141831c"},{"path":"product/policy/auths-bounded-policy/src/kernel.rs","sha256":"99187c28b161ac70bee1afed60711f7f645adb4d1671a01863f9849b369811d5"},{"path":"product/policy/auths-bounded-policy/src/lib.rs","sha256":"76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c"},{"path":"product/policy/auths-bounded-policy/src/receipt.rs","sha256":"3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad"},{"path":"product/policy/auths-bounded-policy/src/registry.rs","sha256":"4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0"},{"path":"product/profiles/auths-profile-api/Cargo.toml","sha256":"7ae85761f58625b5d678f961fd052eebf3e000ef565c7312e3ac857763c0017f"},{"path":"product/profiles/auths-profile-api/src/lib.rs","sha256":"a194b82b20bf8aa864c2334ef6c6aec30b2154ded972862252d5dcefa488ab95"},{"path":"product/profiles/auths-profile-mcp/Cargo.toml","sha256":"db264fc25242f7b7e4133cbe5782545b3107b406c87168ae072683cfb59eac66"},{"path":"product/profiles/auths-profile-mcp/src/arguments.rs","sha256":"a5de696586d507e2aee4a49fee99ef1ef4c51a2e46603f8838f1af6d9009833f"},{"path":"product/profiles/auths-profile-mcp/src/lib.rs","sha256":"d0f8b733a09ef8408336cdebc8948d6a5861012ce6878598b11be7084dfd4280"},{"path":"product/profiles/auths-profile-mcp/src/session.rs","sha256":"166c281fa66333388e4760d6098dad02d3359e1d5de4b8f93312c014f97abb03"},{"path":"product/qualification/auths-recipe-qualification/Cargo.toml","sha256":"b7b15b30b9a3d96d4f089d514266d3a892de6608d30707aa44be31cca89ca9fe"},{"path":"product/qualification/auths-recipe-qualification/src/canonical.rs","sha256":"30a9b50777f0dcb4b606abfee2467d5a975d9f6ad941ab6c13ca3df5b359f667"},{"path":"product/qualification/auths-recipe-qualification/src/closure.rs","sha256":"0ad6aee9bd981e2863fa725f209ec84031db2ff12f4c7ac3aaf5120f0bb86039"},{"path":"product/qualification/auths-recipe-qualification/src/error.rs","sha256":"52d5cf720a1e4579008fdda90a3ac2c31f0b8db57985f121f65e54b4da2b7dd1"},{"path":"product/qualification/auths-recipe-qualification/src/evidence.rs","sha256":"1a4cb862f725b02f9efd827db99637ea8178a5236aa020ec271a363edbe7b362"},{"path":"product/qualification/auths-recipe-qualification/src/ids.rs","sha256":"e81a906d571497ab2da753e1532d4443706410e0b75fdd59a7d2d788c7aec403"},{"path":"product/qualification/auths-recipe-qualification/src/lib.rs","sha256":"195b19f46e1e94a0f3594ad5958e5715bc5e3ad415bdfe6428dfc1b6dd3f4631"},{"path":"product/qualification/auths-recipe-qualification/src/model.rs","sha256":"3484eb0ec287b23d4682ade7b1b0f8d1335985b3fb180f06fc28716076957d5f"},{"path":"product/qualification/auths-recipe-qualification/src/release.rs","sha256":"d816b53e2275e902c750ad03803061844e259e28560ab2d1c77e8a43981a4d6a"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/mod.rs","sha256":"7f15b68e05a04f202bcb1fb80de1d9a9a4fda8bfd6af2cd4e5c660fc75d96fe5"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/schemas.rs","sha256":"c59feec2805621f341a90f81fc005e2c12f7a70f9d264fdeacccb2be4fe1c046"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/verification.rs","sha256":"6a6b5834c5dae10af1ba8939b2deae43b85db71544dc8f077ff63b7fe68ac8a8"},{"path":"product/qualification/auths-recipe-qualification/src/verify.rs","sha256":"edd33589c54fb79bcfccc4cf4e6ccf95bbca088318bb7f8dfc27da684b4fa671"},{"path":"product/receipts/auths-receipts/Cargo.toml","sha256":"6001fa1375899953aafcb07c23a6da0c8f57ea7ec08bb9c950b12a60a8cc6f0f"},{"path":"product/receipts/auths-receipts/src/disclosure.rs","sha256":"ba9ed439be0a320c8a01f5b6e9b51361c1a37e076947490d8e4a484ba6bb119c"},{"path":"product/receipts/auths-receipts/src/lib.rs","sha256":"547a57c4160256719cafb7d0ab972d9fc80b0da14fbbce4148c70c414070ff36"},{"path":"product/runtime/auths-connections/Cargo.toml","sha256":"babeb6e1dda3dfb66291713ce1e43dce5c349833d0b50ea4dccbf986030026b2"},{"path":"product/runtime/auths-connections/src/credential.rs","sha256":"4d532c221d2fe7a2b47c8720be94c26d0c86a0448c3f66f479ce3b12adf44f25"},{"path":"product/runtime/auths-connections/src/kernel.rs","sha256":"a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8"},{"path":"product/runtime/auths-connections/src/lib.rs","sha256":"79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22"},{"path":"product/runtime/auths-connections/src/model.rs","sha256":"de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77"},{"path":"product/runtime/auths-connections/src/registry.rs","sha256":"e57640e003e72ad3235c567c2bb944a262bd64e673f023b62ea091094cc7e946"},{"path":"product/runtime/auths-gateway-kernel/Cargo.toml","sha256":"34f864e67656af4ac7e5c7a347a23f01fc8ab31365b8e23c0ef474483b14a183"},{"path":"product/runtime/auths-gateway-kernel/src/construct.rs","sha256":"e9d65744bae273d65face4285e5d2da75c06a92ab48f7b8333d496604e31c63c"},{"path":"product/runtime/auths-gateway-kernel/src/lib.rs","sha256":"cfda6f8453426564c085475f183b6f790b438768a19668f1b65d33ba59dc8632"},{"path":"product/runtime/auths-gateway-kernel/src/order.rs","sha256":"e0045f877c4b7fe3860c291039853885064ddcdebba7c9b345ab65e81e646dda"},{"path":"product/runtime/auths-gateway-kernel/src/outcome.rs","sha256":"e9785b1afe70788c89b51b18655bcd5acff7b0c8e3d12fb79c6f05a202e67e6b"},{"path":"product/runtime/auths-gateway-kernel/src/ratio.rs","sha256":"7ace22264812e6fc1ef3a62afee402cf43494bb71ae0d3de219ad1b39d690bcb"},{"path":"product/runtime/auths-gateway-kernel/src/recovery.rs","sha256":"9f46dcd1685ab6e4d1ba04a3fc286a9f3afee8fb47829be1fbc670a7926a2dc6"},{"path":"product/runtime/auths-gateway-kernel/src/transition.rs","sha256":"cefb8f01d915880f6921f2501ff881ad94b9de61072c34d9cd19220992f97374"},{"path":"product/runtime/auths-gateway/Cargo.toml","sha256":"00b28be86921dcdc0ad90cce0c62c2961cafefe96ea6c2edf0e926c3d405ccad"},{"path":"product/runtime/auths-gateway/src/admin.rs","sha256":"2d5cc67afac42fbd15f36e2d1693cd1b20cedacf775040dce6ffe04ccc94c9ea"},{"path":"product/runtime/auths-gateway/src/app.rs","sha256":"6f80f63833ea0815bb44fbf3b0cc54624a08e9fb578b035819f2980dc04e8256"},{"path":"product/runtime/auths-gateway/src/audit.rs","sha256":"0edb2037eb7b5d6f13acfce85c54f62a82bf7fdd31bc7e626c4fec183cef61dd"},{"path":"product/runtime/auths-gateway/src/audit_tests.rs","sha256":"990969384a52d75bc2489d9d412a9e7dd814bca1c8f65c701d6205fae62a15d5"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway-harness.rs","sha256":"12b0c24d36b2e6a3be392d3c081a783b355fdd67dc5b54bacc0410e803116b8c"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway.rs","sha256":"fc36ab82a36398f34513502521d462c951a68c47a8eb8edaf35c0ed5e0566a8c"},{"path":"product/runtime/auths-gateway/src/binding.rs","sha256":"663b0ce878319511aa7d05722ab4ab2fa9be18817884ffb2ee9f131ff1e382d1"},{"path":"product/runtime/auths-gateway/src/bounds.rs","sha256":"9cfa0eae4973e5e047a198360b22f041708fa20276b0b90c2ec440f06915d64b"},{"path":"product/runtime/auths-gateway/src/bounds_aggregate_tests.rs","sha256":"ab34f227b7c8692ba1da88ccb32bb3687a66adf8353d8282fae905d4a88eb612"},{"path":"product/runtime/auths-gateway/src/bounds_tests.rs","sha256":"74136bc570da7b9338b5a1a1ed9d3fd892c55135160964f9d3ac0e2cf5741375"},{"path":"product/runtime/auths-gateway/src/connection.rs","sha256":"7b5d049c258a26ed1c93ecf860f51d051a8a65f9b93554af0b1ea93862398ec9"},{"path":"product/runtime/auths-gateway/src/echo_verify.rs","sha256":"6d453051665f823abd7354d5c50031d9524cf47d6092d2f09080ae814e3b9575"},{"path":"product/runtime/auths-gateway/src/engine.rs","sha256":"5d3617774acd9af4b6f0e34bb481bc5500282d2ee75dce7589606d31ac04f8e8"},{"path":"product/runtime/auths-gateway/src/fuzzing.rs","sha256":"ed3b0028487eb546a3b0a91d115aa8f18bcea324b61620bfe8e35a9e6ab18758"},{"path":"product/runtime/auths-gateway/src/generation_floor.rs","sha256":"47964a5f1ca2fc9c4da0b526b6d5c5637fc0ce1d2e429219d02f1b0dc652fdff"},{"path":"product/runtime/auths-gateway/src/harness.rs","sha256":"c87e479f3eb281960f6c9c80d43c7560d7ccb654b0154ec823d3fcec4884ac05"},{"path":"product/runtime/auths-gateway/src/lib.rs","sha256":"f0dc13132a4aa7caff46c56bbd88f4ed5f1b6af666134bab1025aba911bb8440"},{"path":"product/runtime/auths-gateway/src/listener.rs","sha256":"aa08239bcbc1fcb55e8a212fbdf6a84f12985b0d436dcb51dc58b06e59e435f2"},{"path":"product/runtime/auths-gateway/src/observed_tests.rs","sha256":"a22be071695f89ca2578a4d82fd80d9cb82289213c9bdb8f0470f6b2dc3d9201"},{"path":"product/runtime/auths-gateway/src/observer.rs","sha256":"562ffcaea071c3856e0708dc2fe33516917e145d2438aabb75af0a2b6ba01046"},{"path":"product/runtime/auths-gateway/src/onboarding.rs","sha256":"0dfd7d67e7f02f18a28d1c86ca1b7751d7463f5efcdbe3825de0ad8cbccb3891"},{"path":"product/runtime/auths-gateway/src/operator.rs","sha256":"c3c36954a3e86723df035b47f43b85fc8ab3a6292983522b6258d5c6b4e6c4e4"},{"path":"product/runtime/auths-gateway/src/pending_vectors/attempts.rs","sha256":"47ef3c8cb1c5504d47ae9a0088705ce6715fe86bac1671a34a56fb38a64d0dd3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/bounds.rs","sha256":"e612217307e1da5b0eb5ee6582a7458bb064b8aa8a529fc6555b1b334127ab68"},{"path":"product/runtime/auths-gateway/src/pending_vectors/codes.rs","sha256":"e00670a5ef24eb856cc2c6dcda8e5a263842f55c76bb939c0c27bd9df37e5522"},{"path":"product/runtime/auths-gateway/src/pending_vectors/keys.rs","sha256":"f84c56f2ea9cb34b2b79c72d13fbf2c6585010ec1ed450af58a78c80c1ea1edd"},{"path":"product/runtime/auths-gateway/src/pending_vectors/mod.rs","sha256":"5de8340f0ef71a0b57a09e323fefe473d3160c6ae952b9ba46f714825fbacafc"},{"path":"product/runtime/auths-gateway/src/pending_vectors/outcomes.rs","sha256":"8ec07b9511b48913af36ac999d2aa0e82924289f6acb23ddaeb9f00f99815166"},{"path":"product/runtime/auths-gateway/src/pending_vectors/production.rs","sha256":"329bb4b2b4eaef06cfbc9a38458646b34130251fb4a13810b5ac36abce6d981b"},{"path":"product/runtime/auths-gateway/src/pending_vectors/recipes.rs","sha256":"51693208270231c25c3aef2a32151d5962114c71e86b88cb9df83181c7af83d9"},{"path":"product/runtime/auths-gateway/src/pre_entry.rs","sha256":"06ea78ca140468bfaba17d9ab04912ad68673954c3203c98fed28272ff2a00c0"},{"path":"product/runtime/auths-gateway/src/property_tests.rs","sha256":"939c081e2e154aaf10186754044bdd65608932c899b970a04a71d0afaa999a93"},{"path":"product/runtime/auths-gateway/src/qualification.rs","sha256":"a4398512ccb7bb494000fe38f03e0faa7b82d1f80ef5ee2dfa75698ae4f5a9be"},{"path":"product/runtime/auths-gateway/src/qualification_tests.rs","sha256":"4473add5729b97faf04d7be7fd8cf3bbacd7f545e1b61c7d2782563011906b4d"},{"path":"product/runtime/auths-gateway/src/quorum_tests.rs","sha256":"a78380b019104d688c11a4410082c7e08ded3106aab099954c4f8a1b4ae0fd89"},{"path":"product/runtime/auths-gateway/src/readiness.rs","sha256":"8c9c41c5f0e65ed3144b2183f49940bfda0f0db1e4f4a0b6e2f5fb84fe2fba18"},{"path":"product/runtime/auths-gateway/src/recipe.rs","sha256":"fecf9af67e7afc48d080e9f8f55f8ce28e49d0e08988717a27908bbda461d6b6"},{"path":"product/runtime/auths-gateway/src/recipe/lower.rs","sha256":"8088b8751ed831dbb48247af953c6290ac95e2a438ccd5bd65eff54be06a1fd1"},{"path":"product/runtime/auths-gateway/src/recipe/review.rs","sha256":"c3eb7d9fdd98dacf52750b14b67ad7b7faaecbbdeafff1e0b049f67d0a2d0139"},{"path":"product/runtime/auths-gateway/src/recipe/runtime.rs","sha256":"c286f0d15f974402822c0810d8e97f98411dc1c557755cc23e540d85e2bb42d9"},{"path":"product/runtime/auths-gateway/src/recipe/source.rs","sha256":"1af50298fb1461e1b24cbdf560d43124d6b1c4c529586c911b1c4797214a69ff"},{"path":"product/runtime/auths-gateway/src/recipe/tests.rs","sha256":"aac551a2481bbc60864c64079bc667dcb232e45a0f41a04073ed84ab5dbe1fce"},{"path":"product/runtime/auths-gateway/src/recipe/validate.rs","sha256":"3711b17605cb7b0d639bc1b180449231f5882a306cab20e2c7782155cc63b0d4"},{"path":"product/runtime/auths-gateway/src/scenario_tests.rs","sha256":"d8271761b12597bfe1233f8eb5ad1d4e5498c5d03388e832e24ab818484a1de4"},{"path":"product/runtime/auths-gateway/src/separation.rs","sha256":"be9306848ca5d801767cf6aa14247c8618312ef0e202f00ce0c24c4844491061"},{"path":"product/runtime/auths-gateway/src/store.rs","sha256":"1e5288345c2cb1421aeda277b3158d07607404b0ec46943222ac107b63dcbb46"},{"path":"product/runtime/auths-gateway/src/store_testkit.rs","sha256":"88d82fee42f1b8ef521e8deef0216e938ebeaad822eb2f5020e70b89d145ea70"},{"path":"product/runtime/auths-gateway/src/submit.rs","sha256":"c78dbbba7c45b443febf655056c5edcd635e77be7b21c5b2c318097502415ffe"},{"path":"product/runtime/auths-gateway/src/support.rs","sha256":"8537d54b8071744a6a3983f48620a8abe1169c6103b281badd701dd0999ac9c7"},{"path":"product/runtime/auths-gateway/src/transport.rs","sha256":"be2c6dc75b8daec110bf8749fedc3823f6067d40b999aa3eb21126896a97d3ad"},{"path":"product/runtime/auths-kernel-runtime/Cargo.toml","sha256":"926bcd0053e5edd703be8f0027ad009e2982db013c8174c1366edbf38b48087d"},{"path":"product/runtime/auths-kernel-runtime/src/lib.rs","sha256":"7108faae9ca4bc32dc093ddaf885ac8f74f3c9b8d317b7c7d0ed00d1d0ab5972"},{"path":"product/runtime/auths-lifecycle/Cargo.toml","sha256":"c5053c705f8d5554b44e432fe75287a2faf11d644e5a2552e45ad6cd94176af5"},{"path":"product/runtime/auths-lifecycle/src/codec.rs","sha256":"51c4b746749150e8bfcd8ff972b3f6c1ef40bec15583448ec1b471d9ad737dc0"},{"path":"product/runtime/auths-lifecycle/src/digest.rs","sha256":"55282cd7d8aba37713c2dcb5357c9877819edb72a30eadefb860d28d7d3a3eb7"},{"path":"product/runtime/auths-lifecycle/src/identifier.rs","sha256":"31620e8c16de68d3d2d3b84d6353c1a5b9d4151d8247f91fa389b906a8e660f1"},{"path":"product/runtime/auths-lifecycle/src/kernel.rs","sha256":"2abb8c094b36d35b364e74d78091d14c5d6f3d1eb6552cca3b5538dbd017ce23"},{"path":"product/runtime/auths-lifecycle/src/lib.rs","sha256":"afe5a345cd309b5a4f08ffba3170a6d7f16ff914892b3f2006d5208ed24ec736"},{"path":"product/runtime/auths-lifecycle/src/model.rs","sha256":"1af12bbeeeaa65ec02ddcebd7d2c8c92ec1e339fa40ae85b45ab9b01a722a4fa"},{"path":"product/runtime/auths-lifecycle/src/operation.rs","sha256":"78e6d05fcf5d7ea4f148032a3fa26fdfcab77eb346019effe927b08e0d64d732"},{"path":"product/runtime/auths-lifecycle/src/registry.rs","sha256":"53495fe6f7a77422593a41623e28716f1c140dcc1e00f87f6b0ffbfb93a5ef90"},{"path":"product/runtime/auths-lifecycle/src/sealed.rs","sha256":"2e0c03b5813c926c159598bb7890d1523825edbe57cd687d42a5dfb3374a0c19"},{"path":"product/runtime/auths-lifecycle/src/test_support.rs","sha256":"221d9a5c5ef8e1f9f8fd66927484eaf813571d0568470278ecd8fa08a5eec8cd"},{"path":"product/runtime/auths-lifecycle/src/transition.rs","sha256":"011805a28efdd541f44ccea54dd0e34a1e58f4004447ee58013703b4fb6b2822"},{"path":"product/runtime/auths-runtime/Cargo.toml","sha256":"dd29d80a8b4bb56c869f036a6c9998f6e6d1c0383ac5dc03fa42b24abe2a7ff7"},{"path":"product/runtime/auths-runtime/src/lib.rs","sha256":"132ca03d58c14905d3a822a4972f42a22a5ad33a45f2ba9ca44f3a57d810b4b0"},{"path":"product/runtime/auths-runtime/src/production.rs","sha256":"fd4eff4270c571c10fcff6cf27df28961ebf074de8a1a028f500fda1ca376820"},{"path":"product/sdk/auths-approval-quorum/Cargo.toml","sha256":"df904971fca87a24194c5816738a331588fe8f164acb5d70839a35dca5f57114"},{"path":"product/sdk/auths-approval-quorum/src/lib.rs","sha256":"72e4086088a1c0912e4e1a9e980f26a5c280bf5ab16ea39c9f0f58d5096ac2ce"},{"path":"product/sdk/auths-approval-quorum/src/remote.rs","sha256":"9fa029c7c63003adf260f8aec55160c545681c60c1bace0d934e7525862aac7b"},{"path":"product/sdk/auths-approval-quorum/src/remote_tests.rs","sha256":"8a09ce17cfee82a035a74edd535f3ebeb3db0e078784740d3997b17dbdb10197"},{"path":"product/sdk/auths-approval-quorum/src/tests.rs","sha256":"0acbf12be3e497dcc6c2d8f29c9af3b1a7ed8e11b75f6399570d4f217a785060"},{"path":"product/stores/auths-stores/Cargo.toml","sha256":"a32c4b76d17b264be5d40d24497ff237e1ed87822e8bab86229b3db93106dbe3"},{"path":"product/stores/auths-stores/src/gateway_attempt.rs","sha256":"185da8f4a220fba836d5b78a9311f03204681c43a3c53951008084d135bf4d21"},{"path":"product/stores/auths-stores/src/lib.rs","sha256":"e721262edf8a9ab5568ddc27639176312d4a366203b5f73e2d7c11fde2c554e9"},{"path":"product/stores/auths-stores/src/lifecycle.rs","sha256":"94f64d25bc178a9e60ba3c0ee6915d7fb3af7c4468792d76b4e70f43f4de1e2f"}],"schema":"auths.gateway-semantic-closure/1"} \ No newline at end of file +{"files":[{"path":"Cargo.lock","sha256":"c94ed342774d5e2823f01ecf74b8a4812c5f9a6b0cf811d31f2e2cecb671a275"},{"path":"Cargo.toml","sha256":"6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24"},{"path":"core/adapters/auths-did-keri/Cargo.toml","sha256":"86ba3e3f9a0a70d970568bfb3113b7ba7bbdd81c3eebbb52743dd574a0c0ecaa"},{"path":"core/adapters/auths-did-keri/src/lib.rs","sha256":"a75674842f8a7142004369ccd206ab43e476459293f0ff4bed4d4e659031b3e3"},{"path":"core/adapters/auths-did-key/Cargo.toml","sha256":"d5a3ae07ecde83f91eed4c3785051dd0f44eab6c891754f3309b6b40596707d7"},{"path":"core/adapters/auths-did-key/src/lib.rs","sha256":"b76a3f4528a725df53cfa9242e6e414e1d26caa48468aaed497e28b121f4497c"},{"path":"core/adapters/auths-raw-key/Cargo.toml","sha256":"f49616bc18c19e6aaa7e6a02ccebcdb9f5c1422c1278ef9869e0dbf22ceda7be"},{"path":"core/adapters/auths-raw-key/src/lib.rs","sha256":"45eec1b295dac3bed65cd79c942870b926b06b3f5d38eaebaeb6140ac69315fa"},{"path":"core/crates/auths-algebra-kernel/Cargo.toml","sha256":"0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba"},{"path":"core/crates/auths-algebra-kernel/src/generated.rs","sha256":"ae4bcbef42a408c7ffa0c6a74a42f7de177a6f14479e51d205acf830bda05960"},{"path":"core/crates/auths-algebra-kernel/src/lib.rs","sha256":"6654667eeb9b353d6648954c9fd2e8838462a82ce6b2803eb49e1366892c68c6"},{"path":"core/crates/auths-assurance/Cargo.toml","sha256":"afcb12a97ddd09d7a264b9ecd3fcaefc865ff2c9b4539ee85b00883420ba333a"},{"path":"core/crates/auths-assurance/src/lib.rs","sha256":"0fb2ec844d674b25a9e20b1601452c89c2454901fa506adfa9bb38ef9a7fa213"},{"path":"core/crates/auths-author/Cargo.toml","sha256":"1e6f0e3bc079ddb558decf0db26b291c6e72fc47327b6df1b7650d41689b215f"},{"path":"core/crates/auths-author/src/lib.rs","sha256":"e14475f2f49715a1869d5fa6b11ff1fbb72497e39097e09f833b0bae7e5b3f2b"},{"path":"core/crates/auths-author/src/observations.rs","sha256":"dda7d6bfa6f4bd7e95a480ca283c2c0e996f69c5c15cb0c7197af328131a7066"},{"path":"core/crates/auths-authority/Cargo.toml","sha256":"4f68212938029f79ebd857b4f3038494eb85d0163d49f07e51376715cf959815"},{"path":"core/crates/auths-authority/src/lib.rs","sha256":"da88d5194de4e17449e69972c0fb042afa3c39798a8f570f30771e77c384f1eb"},{"path":"core/crates/auths-codec/Cargo.toml","sha256":"e20e51826e17814effd9d8925d18d5fbdd6c0d37bf50231e743ec2611314722c"},{"path":"core/crates/auths-codec/src/approval.rs","sha256":"fbff43bf4d57f69f8b7738a8647751cde75c5a932dee65d924a1fe9c7202f91f"},{"path":"core/crates/auths-codec/src/bounded_policy.rs","sha256":"d21f6728be2d8a04b6d94921f2b683f7e61cbb42e0ac6866f1c88a49caa534c3"},{"path":"core/crates/auths-codec/src/decode.rs","sha256":"ba2999584cdf53b1b517ecb9c7ea50d39efee17c666a9a38e2ad1ac94379f778"},{"path":"core/crates/auths-codec/src/encode.rs","sha256":"8491192053e2e15d62b4d2a491de22405b7487ead69ab6f6bca40669ce7ca5f7"},{"path":"core/crates/auths-codec/src/error.rs","sha256":"fecb0737c16deb42d859f1dc7727c698438d9ac12064fd99e0024629642c390c"},{"path":"core/crates/auths-codec/src/hash.rs","sha256":"f88e111f1dbb2cef6b7b5e9c948cb45ff92e366710c8a5f5c636138aa748479e"},{"path":"core/crates/auths-codec/src/lib.rs","sha256":"3b0e5c94c6f34f750b88a9333e1d5c8145746d845d3a23e0d2f61807cf592ea7"},{"path":"core/crates/auths-codec/src/observation.rs","sha256":"38328b0c71ff97a4196eeade8b4faa889527ff1f80bb168468bcd49082a3987e"},{"path":"core/crates/auths-composition/Cargo.toml","sha256":"331e13025eb82588b5269ed3975929eb41c823d588c49e4c296273d85c6fe80e"},{"path":"core/crates/auths-composition/src/lib.rs","sha256":"e42e3b0b6a9985b73c533aeb23799c638979aa27a9ce7d0f10a8d60340570fb1"},{"path":"core/crates/auths-model/Cargo.toml","sha256":"565c15302b0cc9270db1e28efa3862804846850ba933cc17aea8abcec4a65987"},{"path":"core/crates/auths-model/src/approval.rs","sha256":"54cf44a9ef747ec21546a4086aecfb130bc7803b0d646430e6082df51e6e305f"},{"path":"core/crates/auths-model/src/bounded.rs","sha256":"f90496abc0a06c028b4d850af6ddab7d850bfafeaa3d042f1b1246a41d8bbbc9"},{"path":"core/crates/auths-model/src/bounded_policy.rs","sha256":"306a8f049cc7cfc7635fe0e4de47eb7813eed63d3c14c3be2b51586aa4eea450"},{"path":"core/crates/auths-model/src/lib.rs","sha256":"e7cfe6bb9574c6b016aa63e70658c31e0b90903ec6479a49f4a2ceb64f5bad97"},{"path":"core/crates/auths-model/src/observation.rs","sha256":"b3ed3e3cc090afca2896a7d3de7988afccc1ee1ea0ebd91b51a8bc0f20ad8dbb"},{"path":"core/crates/auths-multikey/Cargo.toml","sha256":"858756c1197befcada06134742bffe8d58cf674cadd6c046bf710570e96efaf2"},{"path":"core/crates/auths-multikey/src/lib.rs","sha256":"f5177fffb11e40eeaaa665ba886c541fc1f24d5eacdd6983fb03dc20148733f0"},{"path":"core/crates/auths-ports/Cargo.toml","sha256":"596a9b0f5af3717c16a6d13f7054d8a106bcd9f01f5f72c2235dd2afcf0ab16c"},{"path":"core/crates/auths-ports/src/binding.rs","sha256":"a16c012d40aa4249e3ec54372b9611006d0bfe8c7dc3c741911c2194ad17736d"},{"path":"core/crates/auths-ports/src/diagnostics.rs","sha256":"aa596572503b5a65a918bb2ff38281c144ff53821ee914e9325c852828d852df"},{"path":"core/crates/auths-ports/src/lib.rs","sha256":"8da1debf86f9532df0660155d04298beb1ba3a1204508f8586e2e67cd2fb3449"},{"path":"core/crates/auths-ports/src/path.rs","sha256":"b68fc547b4e4d97a60cbbc1cc1939fc6b34a8233b81f840bd396914a707e3ea1"},{"path":"core/crates/auths-raw-key-core/Cargo.toml","sha256":"98c0bc8527a537512e43a74dd6ba9658c6f0cdc16610cf938e3f9b43785d836d"},{"path":"core/crates/auths-raw-key-core/src/lib.rs","sha256":"98c0500c41697aae28708ad0bf970b9a97583d96a3d2c18d23e7fa351e0f7d12"},{"path":"core/crates/auths-registries/Cargo.toml","sha256":"590e49e58b0622d9d6274fea46796dcdb07dec9550eff295cce6a6427ffa51e2"},{"path":"core/crates/auths-registries/src/lib.rs","sha256":"450d3886d85ee333b7e046317fb5b47cde62483d5f3e41d46265e2caf4c373ec"},{"path":"core/crates/auths-registries/src/template.rs","sha256":"1224039dd2b3ce6fa8357613d8cafbae40400493da7176da202b9ade62fa05e4"},{"path":"core/crates/auths-signature-core/Cargo.toml","sha256":"6bee2230eb30af1be0bd5c2d57bd3e1903497a70028d47290d4ac6e9e0e8bca0"},{"path":"core/crates/auths-signature-core/src/lib.rs","sha256":"6e3f9311ded5e49ea50d445eb21e6d8fa12442aa4362a73e0cb6fda15b7cd865"},{"path":"core/crates/auths-signature/Cargo.toml","sha256":"7f7b5682466ba439d8c59579022cb61068cad9fb4bd2d73e1cc21327c902b450"},{"path":"core/crates/auths-signature/src/lib.rs","sha256":"b3d9ac4cc3ba0797b9e1c09f2d6ac05089b25dac4e285a5af28c0165b33d925b"},{"path":"core/crates/auths-verifier/Cargo.toml","sha256":"c43358e06a33324b41a8b93e5cc7279c55f7d21f1f6cfaa539a3fc7b4c27a38f"},{"path":"core/crates/auths-verifier/src/approval.rs","sha256":"c3cae6a49e169051eb555bb092b1069a4d422516d6a2114623a89e5f31ff923f"},{"path":"core/crates/auths-verifier/src/causal.rs","sha256":"9635230f33b13a263573d319ac8a1976addbcc07677514a43e3c7bf28dc04587"},{"path":"core/crates/auths-verifier/src/lib.rs","sha256":"f22dec38dfa47ced8da4f605390da8453273bee1da010f57fd1fdfcb10e0b389"},{"path":"core/crates/auths-verifier/src/observation.rs","sha256":"0bb07f06a0f9524c88427df1c972b1de8ba038a9eeeb15d3134c25125ae84b1e"},{"path":"core/crates/auths-verifier/src/trace.rs","sha256":"2213d72023a1d9e0413a2cf2c51c3dad9e04775d86033a0caaa9d29a8f0036f8"},{"path":"exchange/crates/auths-proof-exchange-model/Cargo.toml","sha256":"34b2db64f93a288e942b5a3918d28cdcbef906e0dc9074ce848018d3d5f7a1fa"},{"path":"exchange/crates/auths-proof-exchange-model/src/lib.rs","sha256":"49fac5aff2339d3a57c41cb8bb2a82852538e8f77ecc4b157c88e264ff31fb55"},{"path":"exchange/crates/auths-proof-exchange-port/Cargo.toml","sha256":"7ff660f1b7579dc570c791090aeb450404fbbf44c92781e289f5ccdde746d739"},{"path":"exchange/crates/auths-proof-exchange-port/src/lib.rs","sha256":"b408fb40c6432edc1facb3d8b3e9433a033f8dc73fe2e0ba5a88c972ca675021"},{"path":"product/config/auths-config/Cargo.toml","sha256":"e4b568ab9f6d84f7d7e6d66443fe825f360db9c27bc7c31d6ddc0647ba3ab304"},{"path":"product/config/auths-config/src/lib.rs","sha256":"fecf00ea65cef9018fda9af2063326d7065b869266d0d9e73a4f06816f1102cc"},{"path":"product/errors/auths-errors/Cargo.toml","sha256":"3b3a199b6460ba75bda84475bb5accd35e1485448a3981038db85bf4772dd350"},{"path":"product/errors/auths-errors/src/lib.rs","sha256":"7feeb9069fa4003f94f1f07c1c94619cf1c883e0dbaaf2187f04d0f742264bdd"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/Cargo.toml","sha256":"716f1f2a117d6d69d8effe9ee9057e24ba3502f20af6a602b06facb638cdabed"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/api.rs","sha256":"b3c4321e0737835ecc4f17235d7589b7f3d62180954ebb98ea9449252300245a"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/clock.rs","sha256":"73f0a6e0f5903883329fa6683f5888288f759512ac69e5c87efd2b6b87f7d79f"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/http.rs","sha256":"14c1fce14e24c984b2a275563a29b6326fb08367922b6e8d37ba38b9cb81aa2b"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/identity.rs","sha256":"186de11230c8b33375951c4368609f8976bf9795f171af3fd7fac26207a94361"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs","sha256":"881ad9ccca369b6eaa6bfd9ec03b1585bff07b042da38942ef57154839449d3e"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/names.rs","sha256":"41bb23572d6002e23ee103d6fe70ecd68764861c6f2e48a1c53af998270a4afa"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs","sha256":"39fed883f4802e68d3b41a68fea0aba0737810996b33d13577de70faba004c29"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/store.rs","sha256":"fc60ee9c49b2f4f063c449b4c78100c5c4872779e94ca168f796603b380ef6e4"},{"path":"product/integrations/auths-custody/Cargo.toml","sha256":"1e14034185ad1ec24a977fd5f41d0abee219606245c046ce2a82287fadef448b"},{"path":"product/integrations/auths-custody/src/conformance.rs","sha256":"8ed1afd58f18fc6becc268908aa6419c9aa404c79da0197963eb2599df44acf6"},{"path":"product/integrations/auths-custody/src/key.rs","sha256":"70cbb0fd21b6f5652157845a22c35be2d0f6c05b3d138fc4b9bb6dbdc3d81c40"},{"path":"product/integrations/auths-custody/src/lib.rs","sha256":"8ee593c1f59b0fd2126bdda9138026f5bc531beb64d4489a99785842e7b98b43"},{"path":"product/operations/auths-operations/Cargo.toml","sha256":"73dde1e914ba5e1386f8d49c0d730423cc72ae77ec44c6554a6a75cc8e8922b1"},{"path":"product/operations/auths-operations/src/explanation.rs","sha256":"b4a39bcbd5712cb9e735ee7deeb281f3fa6af5ddca973735bf3d87dce427ef11"},{"path":"product/operations/auths-operations/src/lib.rs","sha256":"3f401a56555113b98f57bca172a2660eaecedf76247b83a3fdbb089c133a29cd"},{"path":"product/operations/auths-operations/src/render/json.rs","sha256":"2ae042639960afee123730e945d373bc5dda1d2b3af20ae16c939a7e99b9e418"},{"path":"product/operations/auths-operations/src/render/mod.rs","sha256":"b3b7f6fe473f49227ace5a68bfc3d8dc14b5db8dd9888fd9e207070337b1b8bf"},{"path":"product/operations/auths-operations/src/render/text.rs","sha256":"f216cf3bdb00e264523271b16e7059535ac6b1aabf271cebd7935af155e4bfec"},{"path":"product/policy/auths-bounded-policy/Cargo.toml","sha256":"babd5d200923137ead71d8c2528f847cea323ce98da942a1320b054436612c47"},{"path":"product/policy/auths-bounded-policy/src/arithmetic.rs","sha256":"75e43c5d4eab8d1f71c1daf53839f5f9fe45a400afc1f63a30c6f55ce3632627"},{"path":"product/policy/auths-bounded-policy/src/commitment.rs","sha256":"c5706f2d583454e1a7f570f7ada138d4d864bef0205dfae7c1296774f396bb3f"},{"path":"product/policy/auths-bounded-policy/src/eligibility.rs","sha256":"c9acdfb793074e687fc36efad506be27dbd99ffbf40387bc66c8de39ef238432"},{"path":"product/policy/auths-bounded-policy/src/identifier.rs","sha256":"0006a32bae9eb16c4178cf797df418d2b0a781f2bc6474b741dc1a908141831c"},{"path":"product/policy/auths-bounded-policy/src/kernel.rs","sha256":"99187c28b161ac70bee1afed60711f7f645adb4d1671a01863f9849b369811d5"},{"path":"product/policy/auths-bounded-policy/src/lib.rs","sha256":"76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c"},{"path":"product/policy/auths-bounded-policy/src/receipt.rs","sha256":"3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad"},{"path":"product/policy/auths-bounded-policy/src/registry.rs","sha256":"4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0"},{"path":"product/profiles/auths-profile-api/Cargo.toml","sha256":"7ae85761f58625b5d678f961fd052eebf3e000ef565c7312e3ac857763c0017f"},{"path":"product/profiles/auths-profile-api/src/lib.rs","sha256":"a194b82b20bf8aa864c2334ef6c6aec30b2154ded972862252d5dcefa488ab95"},{"path":"product/profiles/auths-profile-mcp/Cargo.toml","sha256":"db264fc25242f7b7e4133cbe5782545b3107b406c87168ae072683cfb59eac66"},{"path":"product/profiles/auths-profile-mcp/src/arguments.rs","sha256":"a5de696586d507e2aee4a49fee99ef1ef4c51a2e46603f8838f1af6d9009833f"},{"path":"product/profiles/auths-profile-mcp/src/lib.rs","sha256":"d0f8b733a09ef8408336cdebc8948d6a5861012ce6878598b11be7084dfd4280"},{"path":"product/profiles/auths-profile-mcp/src/session.rs","sha256":"166c281fa66333388e4760d6098dad02d3359e1d5de4b8f93312c014f97abb03"},{"path":"product/qualification/auths-recipe-qualification/Cargo.toml","sha256":"b7b15b30b9a3d96d4f089d514266d3a892de6608d30707aa44be31cca89ca9fe"},{"path":"product/qualification/auths-recipe-qualification/src/canonical.rs","sha256":"30a9b50777f0dcb4b606abfee2467d5a975d9f6ad941ab6c13ca3df5b359f667"},{"path":"product/qualification/auths-recipe-qualification/src/closure.rs","sha256":"0ad6aee9bd981e2863fa725f209ec84031db2ff12f4c7ac3aaf5120f0bb86039"},{"path":"product/qualification/auths-recipe-qualification/src/error.rs","sha256":"52d5cf720a1e4579008fdda90a3ac2c31f0b8db57985f121f65e54b4da2b7dd1"},{"path":"product/qualification/auths-recipe-qualification/src/evidence.rs","sha256":"1a4cb862f725b02f9efd827db99637ea8178a5236aa020ec271a363edbe7b362"},{"path":"product/qualification/auths-recipe-qualification/src/ids.rs","sha256":"e81a906d571497ab2da753e1532d4443706410e0b75fdd59a7d2d788c7aec403"},{"path":"product/qualification/auths-recipe-qualification/src/lib.rs","sha256":"195b19f46e1e94a0f3594ad5958e5715bc5e3ad415bdfe6428dfc1b6dd3f4631"},{"path":"product/qualification/auths-recipe-qualification/src/model.rs","sha256":"3484eb0ec287b23d4682ade7b1b0f8d1335985b3fb180f06fc28716076957d5f"},{"path":"product/qualification/auths-recipe-qualification/src/release.rs","sha256":"d816b53e2275e902c750ad03803061844e259e28560ab2d1c77e8a43981a4d6a"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/mod.rs","sha256":"7f15b68e05a04f202bcb1fb80de1d9a9a4fda8bfd6af2cd4e5c660fc75d96fe5"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/schemas.rs","sha256":"c59feec2805621f341a90f81fc005e2c12f7a70f9d264fdeacccb2be4fe1c046"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/verification.rs","sha256":"6a6b5834c5dae10af1ba8939b2deae43b85db71544dc8f077ff63b7fe68ac8a8"},{"path":"product/qualification/auths-recipe-qualification/src/verify.rs","sha256":"edd33589c54fb79bcfccc4cf4e6ccf95bbca088318bb7f8dfc27da684b4fa671"},{"path":"product/receipts/auths-receipts/Cargo.toml","sha256":"6001fa1375899953aafcb07c23a6da0c8f57ea7ec08bb9c950b12a60a8cc6f0f"},{"path":"product/receipts/auths-receipts/src/disclosure.rs","sha256":"ba9ed439be0a320c8a01f5b6e9b51361c1a37e076947490d8e4a484ba6bb119c"},{"path":"product/receipts/auths-receipts/src/lib.rs","sha256":"547a57c4160256719cafb7d0ab972d9fc80b0da14fbbce4148c70c414070ff36"},{"path":"product/runtime/auths-connections/Cargo.toml","sha256":"babeb6e1dda3dfb66291713ce1e43dce5c349833d0b50ea4dccbf986030026b2"},{"path":"product/runtime/auths-connections/src/credential.rs","sha256":"82921413bb053f0f6c7931fbd4e6a86c8cc1d8c6b51debd9c2cef33a8d5b1c51"},{"path":"product/runtime/auths-connections/src/kernel.rs","sha256":"a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8"},{"path":"product/runtime/auths-connections/src/lib.rs","sha256":"79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22"},{"path":"product/runtime/auths-connections/src/model.rs","sha256":"de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77"},{"path":"product/runtime/auths-connections/src/registry.rs","sha256":"e57640e003e72ad3235c567c2bb944a262bd64e673f023b62ea091094cc7e946"},{"path":"product/runtime/auths-gateway-kernel/Cargo.toml","sha256":"34f864e67656af4ac7e5c7a347a23f01fc8ab31365b8e23c0ef474483b14a183"},{"path":"product/runtime/auths-gateway-kernel/src/construct.rs","sha256":"e9d65744bae273d65face4285e5d2da75c06a92ab48f7b8333d496604e31c63c"},{"path":"product/runtime/auths-gateway-kernel/src/lib.rs","sha256":"cfda6f8453426564c085475f183b6f790b438768a19668f1b65d33ba59dc8632"},{"path":"product/runtime/auths-gateway-kernel/src/order.rs","sha256":"e0045f877c4b7fe3860c291039853885064ddcdebba7c9b345ab65e81e646dda"},{"path":"product/runtime/auths-gateway-kernel/src/outcome.rs","sha256":"e9785b1afe70788c89b51b18655bcd5acff7b0c8e3d12fb79c6f05a202e67e6b"},{"path":"product/runtime/auths-gateway-kernel/src/ratio.rs","sha256":"7ace22264812e6fc1ef3a62afee402cf43494bb71ae0d3de219ad1b39d690bcb"},{"path":"product/runtime/auths-gateway-kernel/src/recovery.rs","sha256":"9f46dcd1685ab6e4d1ba04a3fc286a9f3afee8fb47829be1fbc670a7926a2dc6"},{"path":"product/runtime/auths-gateway-kernel/src/transition.rs","sha256":"cefb8f01d915880f6921f2501ff881ad94b9de61072c34d9cd19220992f97374"},{"path":"product/runtime/auths-gateway/Cargo.toml","sha256":"00b28be86921dcdc0ad90cce0c62c2961cafefe96ea6c2edf0e926c3d405ccad"},{"path":"product/runtime/auths-gateway/src/admin.rs","sha256":"2d5cc67afac42fbd15f36e2d1693cd1b20cedacf775040dce6ffe04ccc94c9ea"},{"path":"product/runtime/auths-gateway/src/app.rs","sha256":"6f80f63833ea0815bb44fbf3b0cc54624a08e9fb578b035819f2980dc04e8256"},{"path":"product/runtime/auths-gateway/src/audit.rs","sha256":"0edb2037eb7b5d6f13acfce85c54f62a82bf7fdd31bc7e626c4fec183cef61dd"},{"path":"product/runtime/auths-gateway/src/audit_tests.rs","sha256":"990969384a52d75bc2489d9d412a9e7dd814bca1c8f65c701d6205fae62a15d5"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway-harness.rs","sha256":"12b0c24d36b2e6a3be392d3c081a783b355fdd67dc5b54bacc0410e803116b8c"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway.rs","sha256":"04183960205e64657d5862ead36a4713cf4e9c67fa10af24ee179fecab40ac36"},{"path":"product/runtime/auths-gateway/src/binding.rs","sha256":"663b0ce878319511aa7d05722ab4ab2fa9be18817884ffb2ee9f131ff1e382d1"},{"path":"product/runtime/auths-gateway/src/bounds.rs","sha256":"9cfa0eae4973e5e047a198360b22f041708fa20276b0b90c2ec440f06915d64b"},{"path":"product/runtime/auths-gateway/src/bounds_aggregate_tests.rs","sha256":"ab34f227b7c8692ba1da88ccb32bb3687a66adf8353d8282fae905d4a88eb612"},{"path":"product/runtime/auths-gateway/src/bounds_tests.rs","sha256":"74136bc570da7b9338b5a1a1ed9d3fd892c55135160964f9d3ac0e2cf5741375"},{"path":"product/runtime/auths-gateway/src/connection.rs","sha256":"7b5d049c258a26ed1c93ecf860f51d051a8a65f9b93554af0b1ea93862398ec9"},{"path":"product/runtime/auths-gateway/src/credential_journal.rs","sha256":"8e2b0733038d93ca5df770d27a870237e3b65664fa48da017d964a65bbbe25b8"},{"path":"product/runtime/auths-gateway/src/echo_verify.rs","sha256":"6d453051665f823abd7354d5c50031d9524cf47d6092d2f09080ae814e3b9575"},{"path":"product/runtime/auths-gateway/src/engine.rs","sha256":"a9f71575994ff21633ddfc533b1d810515db71aa0146fa8869dad72eddcb2a12"},{"path":"product/runtime/auths-gateway/src/fuzzing.rs","sha256":"ed3b0028487eb546a3b0a91d115aa8f18bcea324b61620bfe8e35a9e6ab18758"},{"path":"product/runtime/auths-gateway/src/generation_floor.rs","sha256":"47964a5f1ca2fc9c4da0b526b6d5c5637fc0ce1d2e429219d02f1b0dc652fdff"},{"path":"product/runtime/auths-gateway/src/harness.rs","sha256":"c87e479f3eb281960f6c9c80d43c7560d7ccb654b0154ec823d3fcec4884ac05"},{"path":"product/runtime/auths-gateway/src/lib.rs","sha256":"b182052835a2cd631d1f801a74788d6ac1ef9cae21ade9ab4ffc270cd6f667ed"},{"path":"product/runtime/auths-gateway/src/listener.rs","sha256":"aa08239bcbc1fcb55e8a212fbdf6a84f12985b0d436dcb51dc58b06e59e435f2"},{"path":"product/runtime/auths-gateway/src/observed_tests.rs","sha256":"a22be071695f89ca2578a4d82fd80d9cb82289213c9bdb8f0470f6b2dc3d9201"},{"path":"product/runtime/auths-gateway/src/observer.rs","sha256":"562ffcaea071c3856e0708dc2fe33516917e145d2438aabb75af0a2b6ba01046"},{"path":"product/runtime/auths-gateway/src/onboarding.rs","sha256":"0dfd7d67e7f02f18a28d1c86ca1b7751d7463f5efcdbe3825de0ad8cbccb3891"},{"path":"product/runtime/auths-gateway/src/operator.rs","sha256":"c3c36954a3e86723df035b47f43b85fc8ab3a6292983522b6258d5c6b4e6c4e4"},{"path":"product/runtime/auths-gateway/src/pending_vectors/attempts.rs","sha256":"47ef3c8cb1c5504d47ae9a0088705ce6715fe86bac1671a34a56fb38a64d0dd3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/bounds.rs","sha256":"e612217307e1da5b0eb5ee6582a7458bb064b8aa8a529fc6555b1b334127ab68"},{"path":"product/runtime/auths-gateway/src/pending_vectors/codes.rs","sha256":"e00670a5ef24eb856cc2c6dcda8e5a263842f55c76bb939c0c27bd9df37e5522"},{"path":"product/runtime/auths-gateway/src/pending_vectors/keys.rs","sha256":"f84c56f2ea9cb34b2b79c72d13fbf2c6585010ec1ed450af58a78c80c1ea1edd"},{"path":"product/runtime/auths-gateway/src/pending_vectors/mod.rs","sha256":"5de8340f0ef71a0b57a09e323fefe473d3160c6ae952b9ba46f714825fbacafc"},{"path":"product/runtime/auths-gateway/src/pending_vectors/outcomes.rs","sha256":"8ec07b9511b48913af36ac999d2aa0e82924289f6acb23ddaeb9f00f99815166"},{"path":"product/runtime/auths-gateway/src/pending_vectors/production.rs","sha256":"c2fa18b5d96c87689fe60d95faadebe2c7fdf5b78be872ca15a67ad980106ed3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/recipes.rs","sha256":"51693208270231c25c3aef2a32151d5962114c71e86b88cb9df83181c7af83d9"},{"path":"product/runtime/auths-gateway/src/pre_entry.rs","sha256":"06ea78ca140468bfaba17d9ab04912ad68673954c3203c98fed28272ff2a00c0"},{"path":"product/runtime/auths-gateway/src/property_tests.rs","sha256":"939c081e2e154aaf10186754044bdd65608932c899b970a04a71d0afaa999a93"},{"path":"product/runtime/auths-gateway/src/qualification.rs","sha256":"a4398512ccb7bb494000fe38f03e0faa7b82d1f80ef5ee2dfa75698ae4f5a9be"},{"path":"product/runtime/auths-gateway/src/qualification_tests.rs","sha256":"4473add5729b97faf04d7be7fd8cf3bbacd7f545e1b61c7d2782563011906b4d"},{"path":"product/runtime/auths-gateway/src/quorum_tests.rs","sha256":"a78380b019104d688c11a4410082c7e08ded3106aab099954c4f8a1b4ae0fd89"},{"path":"product/runtime/auths-gateway/src/readiness.rs","sha256":"911c3f11892f94641574375e2da4c671c802738f71082f12c39832331052d43d"},{"path":"product/runtime/auths-gateway/src/recipe.rs","sha256":"fecf9af67e7afc48d080e9f8f55f8ce28e49d0e08988717a27908bbda461d6b6"},{"path":"product/runtime/auths-gateway/src/recipe/lower.rs","sha256":"8088b8751ed831dbb48247af953c6290ac95e2a438ccd5bd65eff54be06a1fd1"},{"path":"product/runtime/auths-gateway/src/recipe/review.rs","sha256":"c3eb7d9fdd98dacf52750b14b67ad7b7faaecbbdeafff1e0b049f67d0a2d0139"},{"path":"product/runtime/auths-gateway/src/recipe/runtime.rs","sha256":"c286f0d15f974402822c0810d8e97f98411dc1c557755cc23e540d85e2bb42d9"},{"path":"product/runtime/auths-gateway/src/recipe/source.rs","sha256":"1af50298fb1461e1b24cbdf560d43124d6b1c4c529586c911b1c4797214a69ff"},{"path":"product/runtime/auths-gateway/src/recipe/tests.rs","sha256":"aac551a2481bbc60864c64079bc667dcb232e45a0f41a04073ed84ab5dbe1fce"},{"path":"product/runtime/auths-gateway/src/recipe/validate.rs","sha256":"3711b17605cb7b0d639bc1b180449231f5882a306cab20e2c7782155cc63b0d4"},{"path":"product/runtime/auths-gateway/src/scenario_tests.rs","sha256":"d8271761b12597bfe1233f8eb5ad1d4e5498c5d03388e832e24ab818484a1de4"},{"path":"product/runtime/auths-gateway/src/separation.rs","sha256":"be9306848ca5d801767cf6aa14247c8618312ef0e202f00ce0c24c4844491061"},{"path":"product/runtime/auths-gateway/src/store.rs","sha256":"1e5288345c2cb1421aeda277b3158d07607404b0ec46943222ac107b63dcbb46"},{"path":"product/runtime/auths-gateway/src/store_testkit.rs","sha256":"88d82fee42f1b8ef521e8deef0216e938ebeaad822eb2f5020e70b89d145ea70"},{"path":"product/runtime/auths-gateway/src/submit.rs","sha256":"c78dbbba7c45b443febf655056c5edcd635e77be7b21c5b2c318097502415ffe"},{"path":"product/runtime/auths-gateway/src/support.rs","sha256":"8537d54b8071744a6a3983f48620a8abe1169c6103b281badd701dd0999ac9c7"},{"path":"product/runtime/auths-gateway/src/transport.rs","sha256":"be2c6dc75b8daec110bf8749fedc3823f6067d40b999aa3eb21126896a97d3ad"},{"path":"product/runtime/auths-kernel-runtime/Cargo.toml","sha256":"926bcd0053e5edd703be8f0027ad009e2982db013c8174c1366edbf38b48087d"},{"path":"product/runtime/auths-kernel-runtime/src/lib.rs","sha256":"7108faae9ca4bc32dc093ddaf885ac8f74f3c9b8d317b7c7d0ed00d1d0ab5972"},{"path":"product/runtime/auths-lifecycle/Cargo.toml","sha256":"c5053c705f8d5554b44e432fe75287a2faf11d644e5a2552e45ad6cd94176af5"},{"path":"product/runtime/auths-lifecycle/src/codec.rs","sha256":"51c4b746749150e8bfcd8ff972b3f6c1ef40bec15583448ec1b471d9ad737dc0"},{"path":"product/runtime/auths-lifecycle/src/digest.rs","sha256":"55282cd7d8aba37713c2dcb5357c9877819edb72a30eadefb860d28d7d3a3eb7"},{"path":"product/runtime/auths-lifecycle/src/identifier.rs","sha256":"31620e8c16de68d3d2d3b84d6353c1a5b9d4151d8247f91fa389b906a8e660f1"},{"path":"product/runtime/auths-lifecycle/src/kernel.rs","sha256":"2abb8c094b36d35b364e74d78091d14c5d6f3d1eb6552cca3b5538dbd017ce23"},{"path":"product/runtime/auths-lifecycle/src/lib.rs","sha256":"afe5a345cd309b5a4f08ffba3170a6d7f16ff914892b3f2006d5208ed24ec736"},{"path":"product/runtime/auths-lifecycle/src/model.rs","sha256":"1af12bbeeeaa65ec02ddcebd7d2c8c92ec1e339fa40ae85b45ab9b01a722a4fa"},{"path":"product/runtime/auths-lifecycle/src/operation.rs","sha256":"78e6d05fcf5d7ea4f148032a3fa26fdfcab77eb346019effe927b08e0d64d732"},{"path":"product/runtime/auths-lifecycle/src/registry.rs","sha256":"53495fe6f7a77422593a41623e28716f1c140dcc1e00f87f6b0ffbfb93a5ef90"},{"path":"product/runtime/auths-lifecycle/src/sealed.rs","sha256":"2e0c03b5813c926c159598bb7890d1523825edbe57cd687d42a5dfb3374a0c19"},{"path":"product/runtime/auths-lifecycle/src/test_support.rs","sha256":"221d9a5c5ef8e1f9f8fd66927484eaf813571d0568470278ecd8fa08a5eec8cd"},{"path":"product/runtime/auths-lifecycle/src/transition.rs","sha256":"011805a28efdd541f44ccea54dd0e34a1e58f4004447ee58013703b4fb6b2822"},{"path":"product/runtime/auths-runtime/Cargo.toml","sha256":"dd29d80a8b4bb56c869f036a6c9998f6e6d1c0383ac5dc03fa42b24abe2a7ff7"},{"path":"product/runtime/auths-runtime/src/lib.rs","sha256":"132ca03d58c14905d3a822a4972f42a22a5ad33a45f2ba9ca44f3a57d810b4b0"},{"path":"product/runtime/auths-runtime/src/production.rs","sha256":"fd4eff4270c571c10fcff6cf27df28961ebf074de8a1a028f500fda1ca376820"},{"path":"product/sdk/auths-approval-quorum/Cargo.toml","sha256":"df904971fca87a24194c5816738a331588fe8f164acb5d70839a35dca5f57114"},{"path":"product/sdk/auths-approval-quorum/src/lib.rs","sha256":"72e4086088a1c0912e4e1a9e980f26a5c280bf5ab16ea39c9f0f58d5096ac2ce"},{"path":"product/sdk/auths-approval-quorum/src/remote.rs","sha256":"9fa029c7c63003adf260f8aec55160c545681c60c1bace0d934e7525862aac7b"},{"path":"product/sdk/auths-approval-quorum/src/remote_tests.rs","sha256":"8a09ce17cfee82a035a74edd535f3ebeb3db0e078784740d3997b17dbdb10197"},{"path":"product/sdk/auths-approval-quorum/src/tests.rs","sha256":"0acbf12be3e497dcc6c2d8f29c9af3b1a7ed8e11b75f6399570d4f217a785060"},{"path":"product/stores/auths-stores/Cargo.toml","sha256":"a32c4b76d17b264be5d40d24497ff237e1ed87822e8bab86229b3db93106dbe3"},{"path":"product/stores/auths-stores/src/gateway_attempt.rs","sha256":"185da8f4a220fba836d5b78a9311f03204681c43a3c53951008084d135bf4d21"},{"path":"product/stores/auths-stores/src/lib.rs","sha256":"e721262edf8a9ab5568ddc27639176312d4a366203b5f73e2d7c11fde2c554e9"},{"path":"product/stores/auths-stores/src/lifecycle.rs","sha256":"94f64d25bc178a9e60ba3c0ee6915d7fb3af7c4468792d76b4e70f43f4de1e2f"}],"schema":"auths.gateway-semantic-closure/1"} \ No newline at end of file diff --git a/product/runtime/auths-gateway/src/bin/auths-gateway.rs b/product/runtime/auths-gateway/src/bin/auths-gateway.rs index 2ddefa65c..f35650bf9 100644 --- a/product/runtime/auths-gateway/src/bin/auths-gateway.rs +++ b/product/runtime/auths-gateway/src/bin/auths-gateway.rs @@ -448,6 +448,12 @@ mod unix { #[arg(long, default_value_t = false)] store_only: bool, }, + /// Collect exact superseded or abandoned generations under operator + /// workload identity, retaining the active and future generations. + CredentialCollect { + #[arg(long)] + state_dir: PathBuf, + }, /// Rotate the credential via the private operator socket and stdin. Rotate { #[arg(long)] @@ -563,6 +569,12 @@ mod unix { #[arg(long)] app_gid: u32, }, + /// Internal owner-UID runtime checks; isolation is checked by doctor. + #[command(hide = true)] + ReadinessProbe { + #[arg(long)] + state_dir: PathBuf, + }, /// Internal privilege-dropped read/connect probe. No secret is printed. #[command(hide = true)] Probe { @@ -1227,6 +1239,14 @@ mod unix { account_hash.update(account_label.as_bytes()); let account_commitment: [u8; 32] = account_hash.finalize().into(); let timestamp = now()?; + let journal = auths_gateway::CredentialJournal::new(state_dir.clone()); + let id = connection_id.clone(); + tokio::task::spawn_blocking(move || { + journal.initialize(&id)?; + journal.register(&id, NonZeroU64::MIN) + }) + .await + .map_err(|_| "gateway.admin.credential-journal-unavailable")??; let record_id = connection_id.clone(); install_connection( &shared, @@ -1263,6 +1283,16 @@ mod unix { .await .map_err(|_| "gateway.install.connection-store-unavailable")? .ok_or("gateway.install.connection-store-unavailable")?; + if join { + let journal = auths_gateway::CredentialJournal::new(state_dir.clone()); + let record = installed.record().clone(); + tokio::task::spawn_blocking(move || { + journal.initialize(record.connection_id())?; + journal.register(record.connection_id(), record.credential_generation()) + }) + .await + .map_err(|_| "gateway.admin.credential-journal-unavailable")??; + } let floor = auths_gateway::GenerationFloor::new(state_dir.clone()); let record = installed.record().clone(); tokio::task::spawn_blocking(move || floor.initialize(&record)) @@ -1779,7 +1809,10 @@ mod unix { }; let engine = engine .with_qualification(Arc::new(qualification_gate(state_dir, &manifest)?)) - .with_generation_floor(auths_gateway::GenerationFloor::new(state_dir.to_path_buf())); + .with_generation_floor(auths_gateway::GenerationFloor::new(state_dir.to_path_buf())) + .with_credential_journal(auths_gateway::CredentialJournal::new( + state_dir.to_path_buf(), + )); // Separation is checked against an authenticated operator. A // development installation without one keeps its observer key // outside the trust it installed, as `observer-init` creates it after @@ -2826,6 +2859,83 @@ mod unix { Ok(()) } + #[derive(Deserialize, Serialize)] + #[serde(deny_unknown_fields)] + struct DoctorRuntime { + required: auths_gateway::RequiredPreconditions, + observer: auths_gateway::ObserverCustodyState, + qualification_code: Option, + } + + #[derive(Clone, Deserialize, Serialize)] + #[serde(try_from = "String", into = "String")] + struct DoctorCode(&'static str); + + impl TryFrom for DoctorCode { + type Error = &'static str; + fn try_from(code: String) -> Result { + use auths_recipe_qualification::QualificationRefusal; + [ + QualificationRefusal::Unavailable, + QualificationRefusal::Revoked, + QualificationRefusal::ClockUntrusted, + QualificationRefusal::RevocationStale, + QualificationRefusal::Missing, + QualificationRefusal::Expired, + QualificationRefusal::DigestMismatch, + QualificationRefusal::TargetMismatch, + ] + .into_iter() + .map(auths_gateway::qualification_code) + .find(|known| *known == code) + .map(Self) + .ok_or("gateway.doctor.invalid-runtime-report") + } + } + + impl From for String { + fn from(code: DoctorCode) -> Self { + code.0.to_owned() + } + } + + async fn runtime_doctor(state_dir: &Path) -> Result { + let directory = state_dir.to_path_buf(); + let engine = tokio::task::spawn_blocking(move || load_engine(&directory)) + .await + .map_err(|_| "gateway.doctor.state-unavailable")? + .map_err(|failure| failure.code)?; + let manifest = installation(state_dir).map_err(|_| "gateway.doctor.state-unavailable")?; + let qualification = engine.qualification().status(); + let kind = CredentialStoreKind::parse(&manifest.credential_store.kind) + .map_err(|_| "gateway.credential.adapter-unsupported")?; + let mut checks = engine.readiness_checks(kind).await; + checks.clock = if auths_gateway::DeploymentClock::trust(&SynchronizedHostClock) + == auths_gateway::ClockTrustState::Trusted + { + auths_gateway::PreconditionState::Ready + } else { + auths_gateway::PreconditionState::NotReady + }; + // load_engine verified pins, authenticated operator, separation and + // observer custody. Development is never production-ready. + if manifest.deployment != Deployment::Production { + checks.trust = auths_gateway::PreconditionState::NotReady; + } + let observer = match load_observer(state_dir)? { + None => auths_gateway::ObserverCustodyState::NotConfigured, + Some(key) if key.custody() != ObserverCustody::Software => { + auths_gateway::ObserverCustodyState::Ready + } + Some(_) => auths_gateway::ObserverCustodyState::NotReady, + }; + Ok(DoctorRuntime { + required: checks, + observer, + qualification_code: qualification.code.map(DoctorCode), + }) + } + async fn doctor( state_dir: &Path, admin_socket: &Path, @@ -2906,38 +3016,35 @@ mod unix { if !status.success() { return Err("gateway.doctor.isolation-not-established"); } + // Runtime checks run as the actual gateway owner, so root does not + // accidentally bypass file ownership checks or mutate its custody. + let binary = std::env::current_exe().map_err(|_| "gateway.doctor.binary-unavailable")?; let directory = state_dir.to_path_buf(); - let engine = tokio::task::spawn_blocking(move || load_engine(&directory)) - .await - .map_err(|_| "gateway.doctor.state-unavailable")? - .map_err(|failure| failure.code)?; - let manifest = installation(state_dir).map_err(|_| "gateway.doctor.state-unavailable")?; - let qualification = engine.qualification().status(); - let kind = CredentialStoreKind::parse(&custody) - .map_err(|_| "gateway.credential.adapter-unsupported")?; - let mut checks = engine.readiness_checks(kind).await; - checks.clock = if auths_gateway::DeploymentClock::trust(&SynchronizedHostClock) - == auths_gateway::ClockTrustState::Trusted - { - auths_gateway::PreconditionState::Ready - } else { - auths_gateway::PreconditionState::NotReady - }; - checks.operator_plane_isolation = auths_gateway::PreconditionState::Ready; - // load_engine verified pins, authenticated operator, separation and - // observer custody. Development is never production-ready. - if manifest.deployment != Deployment::Production { - checks.trust = auths_gateway::PreconditionState::NotReady; + let uid = state.uid(); + let gid = state.gid(); + let output = tokio::task::spawn_blocking(move || { + std::process::Command::new(binary) + .arg("readiness-probe") + .arg("--state-dir") + .arg(directory) + .uid(uid) + .gid(gid) + .output() + }) + .await + .map_err(|_| "gateway.doctor.probe-unavailable")? + .map_err(|_| "gateway.doctor.probe-unavailable")?; + if !output.status.success() || output.stdout.len() > 64 * 1024 { + return Err("gateway.doctor.runtime-check-unavailable"); } - let observer = match load_observer(state_dir)? { - None => auths_gateway::ObserverCustodyState::NotConfigured, - Some(key) if key.custody() != ObserverCustody::Software => { - auths_gateway::ObserverCustodyState::Ready - } - Some(_) => auths_gateway::ObserverCustodyState::NotReady, - }; - let readiness = auths_gateway::ProductionReadiness::new(checks, observer); - println!("{}", readiness.report(qualification.code)); + let mut checked: DoctorRuntime = serde_json::from_slice(&output.stdout) + .map_err(|_| "gateway.doctor.invalid-runtime-report")?; + checked.required.operator_plane_isolation = auths_gateway::PreconditionState::Ready; + let readiness = auths_gateway::ProductionReadiness::new(checked.required, checked.observer); + println!( + "{}", + readiness.report(checked.qualification_code.map(|code| code.0)) + ); if !readiness.is_ready() { return Err("gateway.doctor.not-ready"); } @@ -3206,6 +3313,15 @@ mod unix { let admin_socket = admin_socket_path(&state_dir, admin_socket); operator_attest(&state_dir, &admin_socket.path, &operator_attestation) } + Command::CredentialCollect { state_dir } => { + let engine = operator_engine(&state_dir).await?; + let deleted = engine.collect_credentials().await?; + println!( + "{}", + serde_json::json!({"schema": "auths.gateway-credential-collection/1", "deleted": deleted}) + ); + Ok(()) + } Command::Rotate { state_dir, admin_socket, @@ -3310,6 +3426,14 @@ mod unix { ) .await?) } + Command::ReadinessProbe { state_dir } => { + let checked = runtime_doctor(&state_dir).await?; + println!( + "{}", + serde_json::to_string(&checked).map_err(|_| "gateway.output")? + ); + Ok(()) + } Command::Probe { state_dir, admin_socket, diff --git a/product/runtime/auths-gateway/src/credential_journal.rs b/product/runtime/auths-gateway/src/credential_journal.rs new file mode 100644 index 000000000..4d04e40b2 --- /dev/null +++ b/product/runtime/auths-gateway/src/credential_journal.rs @@ -0,0 +1,200 @@ +//! Durable exact-generation cleanup notes. These contain no credential or +//! external location and are retained independently of database restores. + +use auths_connections::ConnectionId; +use serde::{Deserialize, Serialize}; +#[cfg(unix)] +use std::os::unix::fs::{OpenOptionsExt as _, PermissionsExt as _}; +use std::{ + fs::{self, File, OpenOptions}, + io::{Read as _, Write as _}, + num::NonZeroU64, + path::PathBuf, +}; + +const MAX_GENERATIONS: usize = 64; +const MAX_BYTES: u64 = 4096; +const CODE: &str = "gateway.admin.credential-journal-unavailable"; + +/// The private host's exact credential-generation cleanup notes. +#[derive(Clone)] +pub struct CredentialJournal { + directory: PathBuf, +} + +#[derive(Deserialize, Serialize)] +#[serde(deny_unknown_fields)] +struct Notes { + schema: String, + connection_id: String, + generations: Vec, +} + +impl CredentialJournal { + /// Names a private installation directory validated by the gateway CLI. + #[must_use] + pub const fn new(directory: PathBuf) -> Self { + Self { directory } + } + + /// Initializes a fresh installation's journal before storing a secret. + /// + /// # Errors + /// Refuses an existing journal for another connection or invalid state. + pub fn initialize(&self, id: &ConnectionId) -> Result<(), &'static str> { + self.change(id, true, |_| Ok(())).map(|_| ()) + } + + /// Records an exact generation before a custody mutation can create it. + /// + /// # Errors + /// Missing, malformed, oversized or full journals stop the mutation. + pub fn register(&self, id: &ConnectionId, generation: NonZeroU64) -> Result<(), &'static str> { + self.change(id, false, |notes| { + if !notes.generations.contains(&generation) { + notes.generations.push(generation); + notes.generations.sort_unstable(); + } + if notes.generations.len() > MAX_GENERATIONS { + return Err(CODE); + } + Ok(()) + }) + .map(|_| ()) + } + + /// Reads the bounded set of exact known generations, never a remote list. + /// + /// # Errors + /// Missing or damaged state is refused, not treated as an empty journal. + pub fn generations(&self, id: &ConnectionId) -> Result, &'static str> { + self.change(id, false, |_| Ok(())) + } + + /// Removes a note only after exact deletion succeeded. + /// + /// # Errors + /// An unavailable journal retains the cleanup obligation. + pub fn forget(&self, id: &ConnectionId, generation: NonZeroU64) -> Result<(), &'static str> { + self.change(id, false, |notes| { + notes.generations.retain(|known| *known != generation); + Ok(()) + }) + .map(|_| ()) + } + + #[cfg(unix)] + fn change( + &self, + id: &ConnectionId, + initialize: bool, + update: impl FnOnce(&mut Notes) -> Result<(), &'static str>, + ) -> Result, &'static str> { + let flags = i32::from_ne_bytes(rustix::fs::OFlags::NOFOLLOW.bits().to_ne_bytes()); + let lock = OpenOptions::new() + .read(true) + .write(true) + .create(true) + .truncate(false) + .mode(0o600) + .custom_flags(flags) + .open(self.directory.join("credential-journal.lock")) + .map_err(|_| CODE)?; + rustix::fs::flock(&lock, rustix::fs::FlockOperation::LockExclusive).map_err(|_| CODE)?; + let path = self.directory.join("credential-journal.json"); + let mut notes = match fs::symlink_metadata(&path) { + Ok(metadata) => { + if !metadata.is_file() + || metadata.permissions().mode() & 0o077 != 0 + || metadata.len() > MAX_BYTES + { + return Err(CODE); + } + let mut bytes = Vec::new(); + OpenOptions::new() + .read(true) + .custom_flags(flags) + .open(&path) + .map_err(|_| CODE)? + .take(MAX_BYTES + 1) + .read_to_end(&mut bytes) + .map_err(|_| CODE)?; + if bytes.len() as u64 > MAX_BYTES { + return Err(CODE); + } + serde_json::from_slice::(&bytes).map_err(|_| CODE)? + } + Err(error) if initialize && error.kind() == std::io::ErrorKind::NotFound => Notes { + schema: "auths.gateway-credential-journal/1".to_owned(), + connection_id: id.as_str().to_owned(), + generations: Vec::new(), + }, + Err(_) => return Err(CODE), + }; + if notes.schema != "auths.gateway-credential-journal/1" + || notes.connection_id != id.as_str() + || notes.generations.len() > MAX_GENERATIONS + || !notes.generations.windows(2).all(|pair| pair[0] < pair[1]) + { + return Err(CODE); + } + update(&mut notes)?; + let bytes = serde_json::to_vec(¬es).map_err(|_| CODE)?; + let mut pending = tempfile::NamedTempFile::new_in(&self.directory).map_err(|_| CODE)?; + pending + .as_file() + .set_permissions(fs::Permissions::from_mode(0o600)) + .map_err(|_| CODE)?; + pending + .write_all(&bytes) + .and_then(|()| pending.as_file().sync_all()) + .map_err(|_| CODE)?; + pending.persist(path).map_err(|_| CODE)?; + File::open(&self.directory) + .and_then(|dir| dir.sync_all()) + .map_err(|_| CODE)?; + Ok(notes.generations) + } + + #[cfg(not(unix))] + fn change( + &self, + _id: &ConnectionId, + _initialize: bool, + _update: impl FnOnce(&mut Notes) -> Result<(), &'static str>, + ) -> Result, &'static str> { + Err(CODE) + } +} + +#[cfg(all(test, unix))] +mod tests { + use super::*; + #[test] + fn notes_survive_restart_and_refuse_missing_corrupt_full_or_foreign_state() { + let directory = tempfile::tempdir().expect("directory"); + let id = ConnectionId::parse("conn_AAAAAAAAAAAAAAAAAAAAAA").expect("id"); + let journal = CredentialJournal::new(directory.path().to_path_buf()); + assert_eq!(journal.generations(&id), Err(CODE)); + journal.initialize(&id).expect("initialize"); + for generation in 1..=64 { + journal + .register(&id, NonZeroU64::new(generation).expect("generation")) + .expect("note"); + } + assert_eq!( + journal.register(&id, NonZeroU64::new(65).expect("generation")), + Err(CODE) + ); + let reopened = CredentialJournal::new(directory.path().to_path_buf()); + assert_eq!(reopened.generations(&id).expect("notes").len(), 64); + let foreign = ConnectionId::parse("conn_BBBBBBBBBBBBBBBBBBBBBB").expect("id"); + assert_eq!(reopened.generations(&foreign), Err(CODE)); + reopened + .forget(&id, NonZeroU64::MIN) + .expect("deleted generation"); + assert_eq!(reopened.generations(&id).expect("notes").len(), 63); + fs::write(directory.path().join("credential-journal.json"), b"corrupt").expect("corrupt"); + assert_eq!(reopened.generations(&id), Err(CODE)); + } +} diff --git a/product/runtime/auths-gateway/src/engine.rs b/product/runtime/auths-gateway/src/engine.rs index 2a075b084..df0310190 100644 --- a/product/runtime/auths-gateway/src/engine.rs +++ b/product/runtime/auths-gateway/src/engine.rs @@ -234,6 +234,7 @@ pub struct GatewayEngine { profile: ConnectionProfile, connection: SharedConnection, credentials: Arc, + credential_journal: Option, /// Whether this deployment's recipe is qualified; consulted before every /// lease. qualification: Arc, @@ -302,6 +303,7 @@ impl GatewayEngine { profile, connection: SharedConnection::new(attempts.store(), provider, alias), credentials, + credential_journal: None, qualification: Arc::new(crate::QualificationGate::unconfigured()), attempts, in_flight: AtomicU64::new(0), @@ -330,6 +332,81 @@ impl GatewayEngine { self } + /// Attaches durable cleanup notes recorded before custody writes. + #[must_use] + pub fn with_credential_journal(mut self, journal: crate::CredentialJournal) -> Self { + self.credential_journal = Some(journal); + self + } + + async fn note_credential( + &self, + record: &ConnectionRecord, + next: std::num::NonZeroU64, + ) -> Result<(), &'static str> { + if let Some(journal) = self.credential_journal.clone() { + let id = record.connection_id().clone(); + let current = record.credential_generation(); + tokio::task::spawn_blocking(move || { + journal.register(&id, current)?; + journal.register(&id, next) + }) + .await + .map_err(|_| "gateway.admin.credential-journal-unavailable")??; + } + Ok(()) + } + + /// Collects at most sixteen exact generations from durable notes. It + /// waits the fixed retirement delay after observing the shared record, + /// requires it unchanged, and never deletes its active credential or a + /// future prepared generation. Run under operator workload identity. + /// Existing attempts and provider state are never changed. + /// + /// # Errors + /// A damaged journal, changed connection or failed deletion refuses and + /// retains the obligation for a later operator run. + pub async fn collect_credentials(&self) -> Result { + let journal = self + .credential_journal + .clone() + .ok_or("gateway.admin.credential-journal-unavailable")?; + let current = self.load_for_admin().await?; + let record = current.record().clone(); + let id = record.connection_id().clone(); + let reading = journal.clone(); + let generations = tokio::task::spawn_blocking(move || reading.generations(&id)) + .await + .map_err(|_| "gateway.admin.credential-journal-unavailable")??; + tokio::time::sleep(self.retirement_delay).await; + let latest = self.load_for_admin().await?; + if !latest.unchanged(¤t) { + return Err("gateway.admin.generation-conflict"); + } + let mut deleted = 0; + for generation in generations + .into_iter() + .filter(|generation| { + *generation <= record.generation() + && (record.state() == ConnectionState::Revoked + || *generation != record.credential_generation()) + }) + .take(16) + { + self.credentials + .revoke(record.connection_id(), generation) + .await + .map_err(|_| "gateway.admin.credential-deletion-incomplete")?; + let updating = journal.clone(); + let id = record.connection_id().clone(); + tokio::task::spawn_blocking(move || updating.forget(&id, generation)) + .await + .map_err(|_| "gateway.admin.credential-journal-unavailable")??; + deleted += 1; + } + Ok(deleted) + } + /// Installs the qualification gate the operator plane built for this /// deployment. Without one, every lease is refused as unqualified. #[must_use] @@ -541,6 +618,7 @@ impl GatewayEngine { let next = auths_connections::kernel::next_generation(record.generation().get()) .and_then(std::num::NonZeroU64::new) .ok_or("gateway.admin.generation-exhausted")?; + self.note_credential(record, next).await?; // Nothing can name a generation the record has not reached, so a // successor left by an earlier failed rotation is discarded, not reused. let _ = self.credentials.revoke(record.connection_id(), next).await; @@ -1931,6 +2009,85 @@ pub(crate) mod tests { ); } + #[tokio::test] + async fn durable_cleanup_retires_abandoned_generations_and_keeps_active_and_future_secrets() + { + let mut installation = installation(8).await; + let host = &mut installation.first; + let record = host.record().await; + let journal = crate::CredentialJournal::new( + host.credentials_directory + .parent() + .expect("private root") + .to_path_buf(), + ); + journal.initialize(record.connection_id()).expect("journal"); + journal + .register(record.connection_id(), record.credential_generation()) + .expect("initial note"); + host.engine.credential_journal = Some(journal.clone()); + host.engine + .prepare_rotation(candidate("abandoned-secret")) + .await + .expect("prepare"); + assert_eq!(host.stored(&installation.connection_id), [1, 2]); + host.engine.disable_connection().await.expect("disable"); + // Reopening notes models the operator process exiting after prepare. + host.engine.credential_journal = Some(crate::CredentialJournal::new( + host.credentials_directory + .parent() + .expect("root") + .to_path_buf(), + )); + assert_eq!( + host.engine + .collect_credentials() + .await + .expect("collect abandoned"), + 1 + ); + assert_eq!(host.stored(&installation.connection_id), [1]); + host.engine + .rotate_connection(candidate("published-secret")) + .await + .expect("rotate while disabled"); + host.engine + .collect_credentials() + .await + .expect("collect old"); + assert_eq!(host.stored(&installation.connection_id), [3]); + host.engine + .prepare_rotation(candidate("future-secret")) + .await + .expect("prepare future"); + assert_eq!( + host.engine + .collect_credentials() + .await + .expect("keep future"), + 0 + ); + assert_eq!(host.stored(&installation.connection_id), [3, 4]); + let before = host.leases.load(Ordering::SeqCst); + host.engine + .connection + .stop(true, wall_clock_seconds().expect("clock")) + .await + .expect("store-only revoke"); + host.engine + .collect_credentials() + .await + .expect("collect revoked"); + assert!(host.stored(&installation.connection_id).is_empty()); + assert_eq!(host.leases.load(Ordering::SeqCst), before); + assert!( + journal + .generations(&installation.connection_id) + .expect("notes") + .is_empty() + ); + } + #[tokio::test] async fn readiness_and_emergency_stop_make_no_credential_lease() { let installation = installation(8).await; diff --git a/product/runtime/auths-gateway/src/lib.rs b/product/runtime/auths-gateway/src/lib.rs index 10117e58e..094e32937 100644 --- a/product/runtime/auths-gateway/src/lib.rs +++ b/product/runtime/auths-gateway/src/lib.rs @@ -13,6 +13,7 @@ mod audit; mod binding; mod bounds; mod connection; +mod credential_journal; mod echo_verify; mod engine; #[cfg(feature = "fuzzing")] @@ -70,6 +71,7 @@ pub use connection::{ LoadedConnection, SharedConnection, SharedConnectionError, authorizes_entry, connection_key, install_connection, join_connection, }; +pub use credential_journal::CredentialJournal; pub use echo_verify::{ ECHO_VERIFICATION_NOTE, ECHO_VERIFICATION_SCHEMA, EchoResult, EchoVerification, EchoVerifyError, MAX_ECHO_POINTER_BYTES, MAX_ECHO_RECORD_BYTES, canonical_action_commitment, diff --git a/product/runtime/auths-gateway/src/pending_vectors/production.rs b/product/runtime/auths-gateway/src/pending_vectors/production.rs index eb1d29a60..a26a54e4d 100644 --- a/product/runtime/auths-gateway/src/pending_vectors/production.rs +++ b/product/runtime/auths-gateway/src/pending_vectors/production.rs @@ -70,6 +70,7 @@ const ROWS: &[&str] = &[ "gateway.readiness.transport-unavailable readiness doctor implemented 4 -", "gateway.readiness.observer-unavailable readiness doctor implemented 4 -", "gateway.connection.restore-rollback connection before-lease implemented 4 -", + "gateway.admin.credential-journal-unavailable operator before-custody implemented 4 -", "gateway.attempt.replay engine recorded existing - C:lease-never-precedes-claim", "gateway.connection.credential-generation-missing engine before-claim existing - C:lease-generation-not-held", "gateway.credential.unavailable engine recorded existing - C:lease-commitment-mismatch", diff --git a/product/runtime/auths-gateway/src/readiness.rs b/product/runtime/auths-gateway/src/readiness.rs index 64505fe13..cdf0138f7 100644 --- a/product/runtime/auths-gateway/src/readiness.rs +++ b/product/runtime/auths-gateway/src/readiness.rs @@ -9,6 +9,7 @@ use crate::MAX_TRANSPORT_DURATION; use auths_connections::CredentialStoreKind; +use serde::{Deserialize, Serialize}; use std::time::Duration; /// Decides which credential store an operator's token selects. @@ -173,7 +174,8 @@ impl ReadinessPrecondition { } /// The outcome of one required check. -#[derive(Clone, Copy, Debug, Eq, PartialEq)] +#[derive(Clone, Copy, Debug, Eq, PartialEq, Deserialize, Serialize)] +#[serde(rename_all = "kebab-case")] pub enum PreconditionState { /// The check was made and passed. Ready, @@ -182,7 +184,8 @@ pub enum PreconditionState { } /// The state of observer signing custody. -#[derive(Clone, Copy, Debug, Eq, PartialEq)] +#[derive(Clone, Copy, Debug, Eq, PartialEq, Deserialize, Serialize)] +#[serde(rename_all = "kebab-case")] pub enum ObserverCustodyState { /// No observer is configured. Signed observer outcomes are unavailable, /// which is reported and does not make the deployment unready. @@ -195,7 +198,8 @@ pub enum ObserverCustodyState { /// The state of every required precondition. Each one must be named: there /// is no default, so a check that was never made cannot be read as passed. -#[derive(Clone, Copy, Debug, Eq, PartialEq)] +#[derive(Clone, Copy, Debug, Eq, PartialEq, Deserialize, Serialize)] +#[serde(deny_unknown_fields)] pub struct RequiredPreconditions { /// See [`ReadinessPrecondition::Trust`]. pub trust: PreconditionState, diff --git a/product/runtime/auths-gateway/src/semantic_closure.rs b/product/runtime/auths-gateway/src/semantic_closure.rs index 1270c1059..1aafca768 100644 --- a/product/runtime/auths-gateway/src/semantic_closure.rs +++ b/product/runtime/auths-gateway/src/semantic_closure.rs @@ -10,7 +10,7 @@ /// SHA-256 of the schema, a NUL byte, and `semantic-closure.json`. /// Regenerate through `semantic_closure_is_current` with `AUTHS_UPDATE_FIXTURES=1`. pub const GATEWAY_SEMANTIC_CLOSURE_SHA256: &str = - "fbea66a1c8add7315231c5614d4fc9cb29fcd306a632a1b18fc8a9be642f41af"; + "39736fd77bf533996d0e03cc3d7997469da381cebc294c0d4299dc024e8a3726"; #[cfg(test)] mod tests { diff --git a/release/semantic-freeze-versions.toml b/release/semantic-freeze-versions.toml index af1dc6277..a508c8bd8 100644 --- a/release/semantic-freeze-versions.toml +++ b/release/semantic-freeze-versions.toml @@ -1,4 +1,4 @@ -freeze_version = 360 +freeze_version = 361 # Semantic identity counters live outside the xtask source tree deliberately. # The formal source closure binds xtask's executable code, while the semantic @@ -19,7 +19,7 @@ freeze_version = 360 "auths.frozen-bytes/formal/assurance-manifest-v1.toml" = 57 "auths.frozen-bytes/formal/qualification/aeneas/generated" = 19 "auths.frozen-bytes/formal/qualification/aeneas/qualification.toml" = 16 -"auths.frozen-bytes/formal/qualification/aeneas/source-closure.json" = 95 +"auths.frozen-bytes/formal/qualification/aeneas/source-closure.json" = 96 "auths.frozen-bytes/product/conformance/v1/mechanism-profile-conformance.json" = 1 "auths.frozen-bytes/product/conformance/v1/simplified-product-waist.json" = 4 "auths.frozen-bytes/product/fixtures/v1/bounded-policy/manifest.json" = 3 @@ -45,7 +45,7 @@ freeze_version = 360 "auths.frozen-bytes/product/integrations/auths-stripe/fixtures/subscription-create/v1/manifest.sha256.json" = 1 "auths.frozen-bytes/product/integrations/auths-stripe/fixtures/subscription-modify/v1/manifest.sha256.json" = 1 "auths.frozen-bytes/product/integrations/auths-stripe/fixtures/v1/manifest.sha256.json" = 1 -"auths.identity.protocol" = 116 +"auths.identity.protocol" = 117 "auths.modular-components" = 20 "auths.portable-abi-bindings" = 121 "auths.product.bounded-domains" = 19 @@ -60,11 +60,11 @@ freeze_version = 360 "auths.product.mcp-closed-execution" = 31 "auths.product.mechanism-profile-conformance" = 12 "auths.product.operations" = 5 -"auths.product.public-sdk-contract" = 113 +"auths.product.public-sdk-contract" = 114 "auths.product.receipts" = 13 "auths.product.release-assurance" = 7 "auths.product.simplified-waist" = 19 "auths.product.vocabulary" = 23 "auths.release.benchmark-contract" = 1 "auths.release.evolution-contract" = 79 -"auths.release.public-surface" = 360 +"auths.release.public-surface" = 361 diff --git a/release/semantic-freeze.json b/release/semantic-freeze.json index 964c0dff4..fbf72c960 100644 --- a/release/semantic-freeze.json +++ b/release/semantic-freeze.json @@ -1,6 +1,6 @@ { "schema": "auths.semantic-freeze/1", - "freezeVersion": 360, + "freezeVersion": 361, "publicSurface": { "rustRoots": [ "auths", @@ -238,7 +238,7 @@ }, { "id": "auths.frozen-bytes/formal/qualification/aeneas/source-closure.json", - "version": 95, + "version": 96, "classification": "frozen-bytes", "categories": [ "canonical-generated-evidence" @@ -246,7 +246,7 @@ "owners": [ "formal/qualification/aeneas/source-closure.json" ], - "sha256": "671652536007842f3a6999e2f1af224ef2580fb83ab02411a15dde3e5323b901" + "sha256": "999fbdc0b91332440a3025203cbcaa109a04a5385f7bf2d6d90895645cc1a8db" }, { "id": "auths.frozen-bytes/product/conformance/v1/mechanism-profile-conformance.json", @@ -550,7 +550,7 @@ }, { "id": "auths.identity.protocol", - "version": 116, + "version": 117, "classification": "frozen-meaning", "categories": [ "identity-protocol-versions", @@ -573,7 +573,7 @@ "core/fixtures/identity/v1/vectors.json", "core/spec/identity/v1" ], - "sha256": "8332d64571a9d9af8486d75dc680458804f87e1ec79fd00fcdff7cb0a7ffa878" + "sha256": "f3e9a6379f0260d117dd3e454707497a7d35208a0878482d919a11be48c0a8c4" }, { "id": "auths.modular-components", @@ -871,7 +871,7 @@ }, { "id": "auths.product.public-sdk-contract", - "version": 113, + "version": 114, "classification": "frozen-meaning", "categories": [ "rust-sdk-contract", @@ -889,7 +889,7 @@ "product/runtime/auths-runtime/src", "product/sdk/auths-sdk/src" ], - "sha256": "eec5e98f3be166ba41a3cc0fea3e68f9b06b6a70f627e6c0a21197ed6fcb6b6a" + "sha256": "2fbab558a6ebdb407cc2a14ac580677d2a20352573ad92ad3351a699930557c8" }, { "id": "auths.product.receipts", @@ -1011,7 +1011,7 @@ }, { "id": "auths.release.public-surface", - "version": 360, + "version": 361, "classification": "release-metadata", "categories": [ "package-names", @@ -1103,7 +1103,7 @@ "xtask/src/release_control.rs", "xtask/src/semantic_freeze.rs" ], - "sha256": "7f3fc11e903ce96749acaebcb5089c7f426d49e4881bd83fd85310f7cca9d838" + "sha256": "08626d8a6586356fe38e02bbd389099c91037979a1e4b70193dfe4f18d25869f" } ] } From 94fc4fc6adf1d316d1acb675e4c75e4a4f93e83e Mon Sep 17 00:00:00 2001 From: bordumb Date: Tue, 6 Oct 2026 03:25:50 +0100 Subject: [PATCH 005/108] test(gateway): rehearse physical restore and preserve operator refusal projections --- .github/workflows/postgres-lifecycle.yml | 3 + bindings/python/docs/INTEGRATION_RECIPES.md | 18 ++++++ bindings/python/tests/test_gateway_client.py | 20 ++++++ .../test/unit/gateway-client.test.js | 13 ++++ deployment/gateway/README.md | 5 ++ .../tools/exercise-postgres-restore.sh | 61 +++++++++++++++++++ docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md | 16 +++++ release/semantic-freeze-versions.toml | 8 +-- release/semantic-freeze.json | 10 +-- 9 files changed, 145 insertions(+), 9 deletions(-) create mode 100755 deployment/gateway/tools/exercise-postgres-restore.sh diff --git a/.github/workflows/postgres-lifecycle.yml b/.github/workflows/postgres-lifecycle.yml index 9cc872da3..781fe2469 100644 --- a/.github/workflows/postgres-lifecycle.yml +++ b/.github/workflows/postgres-lifecycle.yml @@ -8,6 +8,7 @@ on: - "product/stores/auths-stores/**" - "bindings/fixtures/gateway/**" - ".github/workflows/postgres-lifecycle.yml" + - "deployment/gateway/**" workflow_dispatch: permissions: @@ -40,6 +41,8 @@ jobs: run: | cargo test -p auths-gateway --lib -- --ignored postgres cargo test -p auths-gateway --features testkit-production-plaintext,testkit-production-unqualified --test operator_plane -- --ignored postgres + - name: Rehearse a physical backup and point-in-time restore + run: deployment/gateway/tools/exercise-postgres-restore.sh - name: Stop fixture if: always() run: docker compose -f product/stores/auths-stores/tests/postgres_tls/compose.yaml down -v diff --git a/bindings/python/docs/INTEGRATION_RECIPES.md b/bindings/python/docs/INTEGRATION_RECIPES.md index ad1c3bc1c..b63be8204 100644 --- a/bindings/python/docs/INTEGRATION_RECIPES.md +++ b/bindings/python/docs/INTEGRATION_RECIPES.md @@ -37,3 +37,21 @@ Identity, custody, reservation, and bounded-transport extension contracts have their own conformance suites. Passing one of those suites qualifies only the named mechanism. It does not qualify a new provider domain, domain errors, reconciliation behavior, or receipt semantics. + + +## Production diagnostics and recovery + +The operator's `auths-gateway doctor` reports `auths.gateway-readiness/1`, +with every required check and the optional observer state; any failed or +unmade check gives a nonzero exit. Keep this output on the operator plane. +The application receives `not-entered` with the gateway's exact stable code +when qualification or a restore floor prevents a lease. It needs operator +repair of the connection or signed inputs before another authorized operation +can proceed. An `unknown` write retains its operation identity and is +reconciled by read-only `reobserve`, without issuing another provider write. + +Signed observations require a configured observer. Production may be ready +with no observer; that deployment reports signed outcomes unavailable. +The [production runbook](../../../docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md) +covers disable/revoke during custody outages, exact-generation collection, +rotation, qualification expiry/revocation and restore-floor recovery. diff --git a/bindings/python/tests/test_gateway_client.py b/bindings/python/tests/test_gateway_client.py index 69dd3efb8..487e46961 100644 --- a/bindings/python/tests/test_gateway_client.py +++ b/bindings/python/tests/test_gateway_client.py @@ -21,6 +21,7 @@ GatewayClient, GatewayEndpoint, GatewayObservationRefused, + GatewayNotEntered, GatewayObserved, GatewayObservedByProvider, GatewayPreEntryObservations, @@ -105,6 +106,25 @@ def test_client_rejects_invalid_endpoint_and_oversized_input(socket_dir) -> None asyncio.run(client.submit(proof=b"", action=b"action")) +@pytest.mark.parametrize("code", [ + "gateway.qualification.missing", + "gateway.qualification.expired", + "gateway.qualification.revoked", + "gateway.qualification.digest-mismatch", + "gateway.qualification.target-mismatch", + "gateway.qualification.unavailable", + "gateway.qualification.revocation-stale", + "gateway.qualification.clock-untrusted", + "gateway.connection.restore-rollback", +]) +def test_operator_gate_refusals_remain_not_entered_with_the_native_code(code) -> None: + from auths.gateway import _parse_result + + result = _parse_result(json.dumps({"outcome": "not-entered", "code": code}).encode()) + assert result == GatewayNotEntered(code) + assert result.outcome == "not-entered" + + def test_result_parser_does_not_infer_effect() -> None: from auths.gateway import _parse_result diff --git a/bindings/typescript/test/unit/gateway-client.test.js b/bindings/typescript/test/unit/gateway-client.test.js index b93430530..fd3482028 100644 --- a/bindings/typescript/test/unit/gateway-client.test.js +++ b/bindings/typescript/test/unit/gateway-client.test.js @@ -296,3 +296,16 @@ test("gateway client refuses unbounded observation requests before connecting", await assert.rejects(client.observePreEntry(operation), TypeError); } }); + + +test("operator gate refusals remain not-entered with the native code", { skip: process.platform === "win32" }, async () => { + for (const code of [ + "gateway.qualification.missing", "gateway.qualification.expired", + "gateway.qualification.revoked", "gateway.qualification.digest-mismatch", + "gateway.qualification.target-mismatch", "gateway.qualification.unavailable", + "gateway.qualification.revocation-stale", "gateway.qualification.clock-untrusted", + "gateway.connection.restore-rollback", + ]) { + assert.deepEqual(await replyOnce(JSON.stringify({ outcome: "not-entered", code })), { outcome: "not-entered", code }); + } +}); diff --git a/deployment/gateway/README.md b/deployment/gateway/README.md index 1afd27799..1361b9357 100644 --- a/deployment/gateway/README.md +++ b/deployment/gateway/README.md @@ -94,6 +94,11 @@ socket paths, and reports incomplete drainage rather than success on timeout. ## Evidence and human trial +The PostgreSQL workflow also runs `tools/exercise-postgres-restore.sh`: it +takes a physical backup, archives WAL, restores to a named point, confirms +pre-target records survive and post-target records do not. This is a disposable +database rehearsal and explicitly makes no replay-continuity claim. + Hosted PostgreSQL and isolation workflows exercise the packaged command's store, multi-host admin, actual application UID denial and restore-floor refusal. They use disposable custody and do not establish production workload diff --git a/deployment/gateway/tools/exercise-postgres-restore.sh b/deployment/gateway/tools/exercise-postgres-restore.sh new file mode 100755 index 000000000..54e4943b1 --- /dev/null +++ b/deployment/gateway/tools/exercise-postgres-restore.sh @@ -0,0 +1,61 @@ +#!/usr/bin/env bash +# A real physical backup plus WAL restore to a named point on the disposable +# PostgreSQL fixture. This rehearses the database mechanics, not replay continuity. +set -euo pipefail +fixture=product/stores/auths-stores/tests/postgres_tls/compose.yaml +source_id=$(docker compose -f "$fixture" ps -q postgres) +: "${source_id:?start the PostgreSQL fixture first}" +: "${RUNNER_TEMP:?a disposable runner directory is required}" +work=$(mktemp -d "$RUNNER_TEMP/auths-pitr.XXXXXXXX") +restore_name="auths-pitr-$(basename "$work")" +cleanup() { + docker rm -f "$restore_name" >/dev/null 2>&1 || true + sudo rm -rf -- "$work" +} +trap cleanup EXIT +sql() { docker exec -u postgres "$source_id" psql -U auths -d auths_lifecycle -v ON_ERROR_STOP=1 -Atc "$1"; } +sql "ALTER SYSTEM SET archive_mode = 'on'" >/dev/null +sql "ALTER SYSTEM SET archive_command = 'cp %p /var/lib/postgresql/data/operator-wal/%f'" >/dev/null +docker exec -u postgres "$source_id" mkdir -p /var/lib/postgresql/data/operator-wal +docker restart "$source_id" >/dev/null +for attempt in {1..60}; do + if docker exec "$source_id" pg_isready -U auths -d auths_lifecycle >/dev/null; then break; fi + sleep 1 +done +sql 'CREATE TABLE auths_operator_restore_marker (id integer PRIMARY KEY); INSERT INTO auths_operator_restore_marker VALUES (1)' >/dev/null +docker exec -u postgres "$source_id" pg_basebackup -U auths -D /tmp/operator-base -Fp -Xs -c fast +sql 'INSERT INTO auths_operator_restore_marker VALUES (2)' >/dev/null +sql "SELECT pg_create_restore_point('auths-before-cutover')" >/dev/null +sql 'INSERT INTO auths_operator_restore_marker VALUES (3)' >/dev/null +wal=$(sql 'SELECT pg_walfile_name(pg_current_wal_lsn())') +sql 'SELECT pg_switch_wal()' >/dev/null +for attempt in {1..60}; do + if docker exec "$source_id" test -f "/var/lib/postgresql/data/operator-wal/$wal"; then break; fi + sleep 1 +done +docker exec "$source_id" test -f "/var/lib/postgresql/data/operator-wal/$wal" +docker cp "$source_id:/tmp/operator-base" "$work/base" +docker cp "$source_id:/var/lib/postgresql/data/operator-wal" "$work/archive" +cat >> "$work/base/postgresql.auto.conf" <<'CONFIG' +restore_command = 'cp /archive/%f %p' +recovery_target_name = 'auths-before-cutover' +recovery_target_action = 'promote' +archive_mode = 'off' +CONFIG +touch "$work/base/recovery.signal" +# The disposable image's postgres user is UID/GID 999. Preserve ownership of +# copied PostgreSQL files; these are fixture database bytes, never provider secrets. +sudo chown -R 999:999 "$work/base" "$work/archive" +sudo chmod 700 "$work/base" +docker run -d --name "$restore_name" \ + -v "$work/base:/var/lib/postgresql/data" \ + -v "$work/archive:/archive:ro" \ + -v "$(pwd)/product/stores/auths-stores/tests/postgres_tls:/fixture:ro" \ + postgres:17.10-bookworm >/dev/null +for attempt in {1..60}; do + if docker exec "$restore_name" psql -U auths -d auths_lifecycle -Atc 'SELECT NOT pg_is_in_recovery()' 2>/dev/null | grep -qx t; then break; fi + sleep 1 +done +observed=$(docker exec "$restore_name" psql -U auths -d auths_lifecycle -v ON_ERROR_STOP=1 -Atc "SELECT string_agg(id::text, ', ' ORDER BY id) FROM auths_operator_restore_marker") +[[ "$observed" == '1, 2' ]] +printf '%s\n' '{"schema":"auths.gateway-restore-exercise/1","backup":"physical-with-wal","target":"named-restore-point","before_target_retained":true,"after_target_excluded":true,"replay_continuity_claim":false}' diff --git a/docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md b/docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md index 1ad561093..caa3e5bc3 100644 --- a/docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md +++ b/docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md @@ -84,6 +84,22 @@ generations, recipe/lock digests, qualification issue-time/revocation floors and attempt counts on both hosts. Disable app ingress and new entries; stop both binaries and retain unknown/response-recorded operations. +For a self-hosted PostgreSQL server, take the physical backup with the +maintained PostgreSQL client: `pg_basebackup --host postgres.internal +--username auths_backup --pgdata /secure/backups/candidate --format plain +--wal-method stream --checkpoint fast`. Supply the password with an owner-only +PGPASSFILE and require `PGSSLMODE=verify-full` with the reviewed CA. Test WAL +archiving before the backup. Create a named point with +`SELECT pg_create_restore_point('reviewed_restore_point')` and retain its WAL. +On the isolated replacement server, restore the physical backup into an empty +private data directory, create `recovery.signal`, and set `restore_command` +to copy exact archived WAL files, `recovery_target_name` to that reviewed point +and `recovery_target_action` to `promote`. Start with the replacement's own TLS +certificate and hostname. Verify records committed before the target exist +and those committed after it do not; retain the closed exercise report. +The disposable hosted exercise automates these mechanics. It does not make a +claim about missing replay rows or external provider effects. + Restore snapshot plus WAL to a new PostgreSQL endpoint, validate its TLS name and schema, and keep original hosts stopped. Start each replacement from its current independently retained floor files and reviewed installed inputs. diff --git a/release/semantic-freeze-versions.toml b/release/semantic-freeze-versions.toml index a508c8bd8..6c75bdb46 100644 --- a/release/semantic-freeze-versions.toml +++ b/release/semantic-freeze-versions.toml @@ -1,4 +1,4 @@ -freeze_version = 361 +freeze_version = 362 # Semantic identity counters live outside the xtask source tree deliberately. # The formal source closure binds xtask's executable code, while the semantic @@ -45,7 +45,7 @@ freeze_version = 361 "auths.frozen-bytes/product/integrations/auths-stripe/fixtures/subscription-create/v1/manifest.sha256.json" = 1 "auths.frozen-bytes/product/integrations/auths-stripe/fixtures/subscription-modify/v1/manifest.sha256.json" = 1 "auths.frozen-bytes/product/integrations/auths-stripe/fixtures/v1/manifest.sha256.json" = 1 -"auths.identity.protocol" = 117 +"auths.identity.protocol" = 118 "auths.modular-components" = 20 "auths.portable-abi-bindings" = 121 "auths.product.bounded-domains" = 19 @@ -60,11 +60,11 @@ freeze_version = 361 "auths.product.mcp-closed-execution" = 31 "auths.product.mechanism-profile-conformance" = 12 "auths.product.operations" = 5 -"auths.product.public-sdk-contract" = 114 +"auths.product.public-sdk-contract" = 115 "auths.product.receipts" = 13 "auths.product.release-assurance" = 7 "auths.product.simplified-waist" = 19 "auths.product.vocabulary" = 23 "auths.release.benchmark-contract" = 1 "auths.release.evolution-contract" = 79 -"auths.release.public-surface" = 361 +"auths.release.public-surface" = 362 diff --git a/release/semantic-freeze.json b/release/semantic-freeze.json index fbf72c960..e984f52f7 100644 --- a/release/semantic-freeze.json +++ b/release/semantic-freeze.json @@ -1,6 +1,6 @@ { "schema": "auths.semantic-freeze/1", - "freezeVersion": 361, + "freezeVersion": 362, "publicSurface": { "rustRoots": [ "auths", @@ -550,7 +550,7 @@ }, { "id": "auths.identity.protocol", - "version": 117, + "version": 118, "classification": "frozen-meaning", "categories": [ "identity-protocol-versions", @@ -871,7 +871,7 @@ }, { "id": "auths.product.public-sdk-contract", - "version": 114, + "version": 115, "classification": "frozen-meaning", "categories": [ "rust-sdk-contract", @@ -1011,7 +1011,7 @@ }, { "id": "auths.release.public-surface", - "version": 361, + "version": 362, "classification": "release-metadata", "categories": [ "package-names", @@ -1103,7 +1103,7 @@ "xtask/src/release_control.rs", "xtask/src/semantic_freeze.rs" ], - "sha256": "08626d8a6586356fe38e02bbd389099c91037979a1e4b70193dfe4f18d25869f" + "sha256": "81863e20ecfc3ae2e47000dd997fdedde6df068cc51b79f799b91e710184db62" } ] } From 7b83fd84461d52aa444af15a7679d901140f8425 Mon Sep 17 00:00:00 2001 From: bordumb Date: Tue, 6 Oct 2026 03:32:48 +0100 Subject: [PATCH 006/108] fix(gateway): decode closed readiness codes and exercise extracted operator binaries --- .github/workflows/gateway-operator-package.yml | 8 ++++++++ bindings/typescript/README.md | 13 +++++++++++++ deployment/gateway/README.md | 6 ++++-- deployment/gateway/tools/package.py | 5 ++++- .../runtime/auths-gateway/semantic-closure.json | 2 +- .../runtime/auths-gateway/src/bin/auths-gateway.rs | 13 +++++++++++-- .../runtime/auths-gateway/src/semantic_closure.rs | 2 +- .../auths-gateway/tests/isolated_process.rs | 5 ++++- .../runtime/auths-gateway/tests/operator_plane.rs | 11 +++++------ .../runtime/auths-gateway/tests/support_bundle.rs | 5 ++++- release/semantic-freeze-versions.toml | 10 +++++----- release/semantic-freeze.json | 14 +++++++------- 12 files changed, 67 insertions(+), 27 deletions(-) diff --git a/.github/workflows/gateway-operator-package.yml b/.github/workflows/gateway-operator-package.yml index 4413dc7e9..975a1e235 100644 --- a/.github/workflows/gateway-operator-package.yml +++ b/.github/workflows/gateway-operator-package.yml @@ -46,6 +46,8 @@ jobs: for item in manifest['files']: assert hashlib.sha256(Path(item['path']).read_bytes()).hexdigest() == item['sha256'] assert not list(Path('.').rglob('*.rs')) + assert (Path('reference') / '../docs/GATEWAY_PRODUCTION_RUNBOOK.md').is_file() + assert '../docs/GATEWAY_PRODUCTION_RUNBOOK.md' in Path('reference/README.md').read_text() PY bin/auths-gateway disable --help | grep -- --store-only bin/auths-gateway rotate-prepare --help | grep -- --operator-process @@ -56,6 +58,12 @@ jobs: sudo install -D "$RUNNER_TEMP/operator/auths-gateway-operator/bin/auths-gateway" /opt/auths/bin/auths-gateway sudo install -D "$RUNNER_TEMP/operator/auths-gateway-operator/bin/run-with-postgres-url" /opt/auths/bin/run-with-postgres-url systemd-analyze verify deployment/gateway/systemd/*.service deployment/gateway/systemd/*.timer + - name: Exercise the extracted release binary with disposable installations + env: + AUTHS_GATEWAY_OPERATOR_TEST_BINARY: ${{ runner.temp }}/operator/auths-gateway-operator/bin/auths-gateway + run: | + cargo test --locked -p auths-gateway --test operator_plane --test support_bundle + cargo test --locked -p auths-gateway --test isolated_process -- --ignored - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: name: gateway-operator-package diff --git a/bindings/typescript/README.md b/bindings/typescript/README.md index 73f414819..9ced86a87 100644 --- a/bindings/typescript/README.md +++ b/bindings/typescript/README.md @@ -50,6 +50,19 @@ The [Stripe refund example](../../examples/stripe-refund-approval/README.md) runs the whole journey: a grant with limits, a 2-of-3 approval quorum, gateway submission, and an offline audit. +Keep the exact `code` on a `not-entered` result. Qualification refusals and +`gateway.connection.restore-rollback` mean this submission stopped before +provider entry; they do not establish the outcome of any earlier attempt. +An `unknown` result means the write may have happened. Retain its operation +identifier and ask the operator to reconcile it with `reobserve`; do not +resubmit it as a new operation. Signed observations require a separately +configured observer. An absent observer does not establish a signed outcome. + +The operator's `doctor` report lists each required production check and +returns nonzero if any check fails. Use the +[production operations runbook](../../docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md) +for diagnosis, emergency stop, rotation and recovery. + ## Author the proof `@auths-dev/sdk/self-hosted` generates an exact MCP-shaped tool from a diff --git a/deployment/gateway/README.md b/deployment/gateway/README.md index 1361b9357..96cd39786 100644 --- a/deployment/gateway/README.md +++ b/deployment/gateway/README.md @@ -51,7 +51,9 @@ attestation and production credential store using `auths-gateway install`. Pipe the disposable credential from the operator's secret source into stdin; never put it in argv or a shell literal. Copy the signed qualification inputs with `qualification-import`; run `doctor` as root, then use `enable` only -when all required checks pass. `doctor` prints `auths.gateway-readiness/1` and +after all other required checks pass. While disabled, the connection check +correctly fails: keep app ingress isolated, enable, rerun doctor, and only +admit app traffic after the full report passes. `doctor` prints `auths.gateway-readiness/1` and returns nonzero on any failed check. Development installations always fail production readiness. Follow the [operations runbook](../../docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md). @@ -102,7 +104,7 @@ database rehearsal and explicitly makes no replay-continuity claim. Hosted PostgreSQL and isolation workflows exercise the packaged command's store, multi-host admin, actual application UID denial and restore-floor refusal. They use disposable custody and do not establish production workload -identity, firewall or point-in-time restore operation. Record those live +identity, firewall or production point-in-time restore operation. Record those live reference exercises before declaring Epic 4 complete. Use the trial protocol in the runbook with a person unfamiliar with the implementation; an automated or simulated onboarding run cannot close that gate. diff --git a/deployment/gateway/tools/package.py b/deployment/gateway/tools/package.py index 706059e55..eafad0f4e 100644 --- a/deployment/gateway/tools/package.py +++ b/deployment/gateway/tools/package.py @@ -28,7 +28,10 @@ def main(): reference = root / "deployment/gateway" for path in sorted(reference.rglob("*")): if path.is_file() and "tools" not in path.relative_to(reference).parts and path.name != "run-with-postgres-url": - files["reference/" + path.relative_to(reference).as_posix()] = (path.read_bytes(), 0o644) + data = path.read_bytes() + if path == reference / "README.md": + data = data.replace(b"../../docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md", b"../docs/GATEWAY_PRODUCTION_RUNBOOK.md") + files["reference/" + path.relative_to(reference).as_posix()] = (data, 0o644) manifest = { "schema": "auths.gateway-operator-package/1", "source_commit": args.commit, diff --git a/product/runtime/auths-gateway/semantic-closure.json b/product/runtime/auths-gateway/semantic-closure.json index 42aea6ca3..e22adc5b7 100644 --- a/product/runtime/auths-gateway/semantic-closure.json +++ b/product/runtime/auths-gateway/semantic-closure.json @@ -1 +1 @@ -{"files":[{"path":"Cargo.lock","sha256":"c94ed342774d5e2823f01ecf74b8a4812c5f9a6b0cf811d31f2e2cecb671a275"},{"path":"Cargo.toml","sha256":"6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24"},{"path":"core/adapters/auths-did-keri/Cargo.toml","sha256":"86ba3e3f9a0a70d970568bfb3113b7ba7bbdd81c3eebbb52743dd574a0c0ecaa"},{"path":"core/adapters/auths-did-keri/src/lib.rs","sha256":"a75674842f8a7142004369ccd206ab43e476459293f0ff4bed4d4e659031b3e3"},{"path":"core/adapters/auths-did-key/Cargo.toml","sha256":"d5a3ae07ecde83f91eed4c3785051dd0f44eab6c891754f3309b6b40596707d7"},{"path":"core/adapters/auths-did-key/src/lib.rs","sha256":"b76a3f4528a725df53cfa9242e6e414e1d26caa48468aaed497e28b121f4497c"},{"path":"core/adapters/auths-raw-key/Cargo.toml","sha256":"f49616bc18c19e6aaa7e6a02ccebcdb9f5c1422c1278ef9869e0dbf22ceda7be"},{"path":"core/adapters/auths-raw-key/src/lib.rs","sha256":"45eec1b295dac3bed65cd79c942870b926b06b3f5d38eaebaeb6140ac69315fa"},{"path":"core/crates/auths-algebra-kernel/Cargo.toml","sha256":"0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba"},{"path":"core/crates/auths-algebra-kernel/src/generated.rs","sha256":"ae4bcbef42a408c7ffa0c6a74a42f7de177a6f14479e51d205acf830bda05960"},{"path":"core/crates/auths-algebra-kernel/src/lib.rs","sha256":"6654667eeb9b353d6648954c9fd2e8838462a82ce6b2803eb49e1366892c68c6"},{"path":"core/crates/auths-assurance/Cargo.toml","sha256":"afcb12a97ddd09d7a264b9ecd3fcaefc865ff2c9b4539ee85b00883420ba333a"},{"path":"core/crates/auths-assurance/src/lib.rs","sha256":"0fb2ec844d674b25a9e20b1601452c89c2454901fa506adfa9bb38ef9a7fa213"},{"path":"core/crates/auths-author/Cargo.toml","sha256":"1e6f0e3bc079ddb558decf0db26b291c6e72fc47327b6df1b7650d41689b215f"},{"path":"core/crates/auths-author/src/lib.rs","sha256":"e14475f2f49715a1869d5fa6b11ff1fbb72497e39097e09f833b0bae7e5b3f2b"},{"path":"core/crates/auths-author/src/observations.rs","sha256":"dda7d6bfa6f4bd7e95a480ca283c2c0e996f69c5c15cb0c7197af328131a7066"},{"path":"core/crates/auths-authority/Cargo.toml","sha256":"4f68212938029f79ebd857b4f3038494eb85d0163d49f07e51376715cf959815"},{"path":"core/crates/auths-authority/src/lib.rs","sha256":"da88d5194de4e17449e69972c0fb042afa3c39798a8f570f30771e77c384f1eb"},{"path":"core/crates/auths-codec/Cargo.toml","sha256":"e20e51826e17814effd9d8925d18d5fbdd6c0d37bf50231e743ec2611314722c"},{"path":"core/crates/auths-codec/src/approval.rs","sha256":"fbff43bf4d57f69f8b7738a8647751cde75c5a932dee65d924a1fe9c7202f91f"},{"path":"core/crates/auths-codec/src/bounded_policy.rs","sha256":"d21f6728be2d8a04b6d94921f2b683f7e61cbb42e0ac6866f1c88a49caa534c3"},{"path":"core/crates/auths-codec/src/decode.rs","sha256":"ba2999584cdf53b1b517ecb9c7ea50d39efee17c666a9a38e2ad1ac94379f778"},{"path":"core/crates/auths-codec/src/encode.rs","sha256":"8491192053e2e15d62b4d2a491de22405b7487ead69ab6f6bca40669ce7ca5f7"},{"path":"core/crates/auths-codec/src/error.rs","sha256":"fecb0737c16deb42d859f1dc7727c698438d9ac12064fd99e0024629642c390c"},{"path":"core/crates/auths-codec/src/hash.rs","sha256":"f88e111f1dbb2cef6b7b5e9c948cb45ff92e366710c8a5f5c636138aa748479e"},{"path":"core/crates/auths-codec/src/lib.rs","sha256":"3b0e5c94c6f34f750b88a9333e1d5c8145746d845d3a23e0d2f61807cf592ea7"},{"path":"core/crates/auths-codec/src/observation.rs","sha256":"38328b0c71ff97a4196eeade8b4faa889527ff1f80bb168468bcd49082a3987e"},{"path":"core/crates/auths-composition/Cargo.toml","sha256":"331e13025eb82588b5269ed3975929eb41c823d588c49e4c296273d85c6fe80e"},{"path":"core/crates/auths-composition/src/lib.rs","sha256":"e42e3b0b6a9985b73c533aeb23799c638979aa27a9ce7d0f10a8d60340570fb1"},{"path":"core/crates/auths-model/Cargo.toml","sha256":"565c15302b0cc9270db1e28efa3862804846850ba933cc17aea8abcec4a65987"},{"path":"core/crates/auths-model/src/approval.rs","sha256":"54cf44a9ef747ec21546a4086aecfb130bc7803b0d646430e6082df51e6e305f"},{"path":"core/crates/auths-model/src/bounded.rs","sha256":"f90496abc0a06c028b4d850af6ddab7d850bfafeaa3d042f1b1246a41d8bbbc9"},{"path":"core/crates/auths-model/src/bounded_policy.rs","sha256":"306a8f049cc7cfc7635fe0e4de47eb7813eed63d3c14c3be2b51586aa4eea450"},{"path":"core/crates/auths-model/src/lib.rs","sha256":"e7cfe6bb9574c6b016aa63e70658c31e0b90903ec6479a49f4a2ceb64f5bad97"},{"path":"core/crates/auths-model/src/observation.rs","sha256":"b3ed3e3cc090afca2896a7d3de7988afccc1ee1ea0ebd91b51a8bc0f20ad8dbb"},{"path":"core/crates/auths-multikey/Cargo.toml","sha256":"858756c1197befcada06134742bffe8d58cf674cadd6c046bf710570e96efaf2"},{"path":"core/crates/auths-multikey/src/lib.rs","sha256":"f5177fffb11e40eeaaa665ba886c541fc1f24d5eacdd6983fb03dc20148733f0"},{"path":"core/crates/auths-ports/Cargo.toml","sha256":"596a9b0f5af3717c16a6d13f7054d8a106bcd9f01f5f72c2235dd2afcf0ab16c"},{"path":"core/crates/auths-ports/src/binding.rs","sha256":"a16c012d40aa4249e3ec54372b9611006d0bfe8c7dc3c741911c2194ad17736d"},{"path":"core/crates/auths-ports/src/diagnostics.rs","sha256":"aa596572503b5a65a918bb2ff38281c144ff53821ee914e9325c852828d852df"},{"path":"core/crates/auths-ports/src/lib.rs","sha256":"8da1debf86f9532df0660155d04298beb1ba3a1204508f8586e2e67cd2fb3449"},{"path":"core/crates/auths-ports/src/path.rs","sha256":"b68fc547b4e4d97a60cbbc1cc1939fc6b34a8233b81f840bd396914a707e3ea1"},{"path":"core/crates/auths-raw-key-core/Cargo.toml","sha256":"98c0bc8527a537512e43a74dd6ba9658c6f0cdc16610cf938e3f9b43785d836d"},{"path":"core/crates/auths-raw-key-core/src/lib.rs","sha256":"98c0500c41697aae28708ad0bf970b9a97583d96a3d2c18d23e7fa351e0f7d12"},{"path":"core/crates/auths-registries/Cargo.toml","sha256":"590e49e58b0622d9d6274fea46796dcdb07dec9550eff295cce6a6427ffa51e2"},{"path":"core/crates/auths-registries/src/lib.rs","sha256":"450d3886d85ee333b7e046317fb5b47cde62483d5f3e41d46265e2caf4c373ec"},{"path":"core/crates/auths-registries/src/template.rs","sha256":"1224039dd2b3ce6fa8357613d8cafbae40400493da7176da202b9ade62fa05e4"},{"path":"core/crates/auths-signature-core/Cargo.toml","sha256":"6bee2230eb30af1be0bd5c2d57bd3e1903497a70028d47290d4ac6e9e0e8bca0"},{"path":"core/crates/auths-signature-core/src/lib.rs","sha256":"6e3f9311ded5e49ea50d445eb21e6d8fa12442aa4362a73e0cb6fda15b7cd865"},{"path":"core/crates/auths-signature/Cargo.toml","sha256":"7f7b5682466ba439d8c59579022cb61068cad9fb4bd2d73e1cc21327c902b450"},{"path":"core/crates/auths-signature/src/lib.rs","sha256":"b3d9ac4cc3ba0797b9e1c09f2d6ac05089b25dac4e285a5af28c0165b33d925b"},{"path":"core/crates/auths-verifier/Cargo.toml","sha256":"c43358e06a33324b41a8b93e5cc7279c55f7d21f1f6cfaa539a3fc7b4c27a38f"},{"path":"core/crates/auths-verifier/src/approval.rs","sha256":"c3cae6a49e169051eb555bb092b1069a4d422516d6a2114623a89e5f31ff923f"},{"path":"core/crates/auths-verifier/src/causal.rs","sha256":"9635230f33b13a263573d319ac8a1976addbcc07677514a43e3c7bf28dc04587"},{"path":"core/crates/auths-verifier/src/lib.rs","sha256":"f22dec38dfa47ced8da4f605390da8453273bee1da010f57fd1fdfcb10e0b389"},{"path":"core/crates/auths-verifier/src/observation.rs","sha256":"0bb07f06a0f9524c88427df1c972b1de8ba038a9eeeb15d3134c25125ae84b1e"},{"path":"core/crates/auths-verifier/src/trace.rs","sha256":"2213d72023a1d9e0413a2cf2c51c3dad9e04775d86033a0caaa9d29a8f0036f8"},{"path":"exchange/crates/auths-proof-exchange-model/Cargo.toml","sha256":"34b2db64f93a288e942b5a3918d28cdcbef906e0dc9074ce848018d3d5f7a1fa"},{"path":"exchange/crates/auths-proof-exchange-model/src/lib.rs","sha256":"49fac5aff2339d3a57c41cb8bb2a82852538e8f77ecc4b157c88e264ff31fb55"},{"path":"exchange/crates/auths-proof-exchange-port/Cargo.toml","sha256":"7ff660f1b7579dc570c791090aeb450404fbbf44c92781e289f5ccdde746d739"},{"path":"exchange/crates/auths-proof-exchange-port/src/lib.rs","sha256":"b408fb40c6432edc1facb3d8b3e9433a033f8dc73fe2e0ba5a88c972ca675021"},{"path":"product/config/auths-config/Cargo.toml","sha256":"e4b568ab9f6d84f7d7e6d66443fe825f360db9c27bc7c31d6ddc0647ba3ab304"},{"path":"product/config/auths-config/src/lib.rs","sha256":"fecf00ea65cef9018fda9af2063326d7065b869266d0d9e73a4f06816f1102cc"},{"path":"product/errors/auths-errors/Cargo.toml","sha256":"3b3a199b6460ba75bda84475bb5accd35e1485448a3981038db85bf4772dd350"},{"path":"product/errors/auths-errors/src/lib.rs","sha256":"7feeb9069fa4003f94f1f07c1c94619cf1c883e0dbaaf2187f04d0f742264bdd"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/Cargo.toml","sha256":"716f1f2a117d6d69d8effe9ee9057e24ba3502f20af6a602b06facb638cdabed"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/api.rs","sha256":"b3c4321e0737835ecc4f17235d7589b7f3d62180954ebb98ea9449252300245a"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/clock.rs","sha256":"73f0a6e0f5903883329fa6683f5888288f759512ac69e5c87efd2b6b87f7d79f"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/http.rs","sha256":"14c1fce14e24c984b2a275563a29b6326fb08367922b6e8d37ba38b9cb81aa2b"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/identity.rs","sha256":"186de11230c8b33375951c4368609f8976bf9795f171af3fd7fac26207a94361"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs","sha256":"881ad9ccca369b6eaa6bfd9ec03b1585bff07b042da38942ef57154839449d3e"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/names.rs","sha256":"41bb23572d6002e23ee103d6fe70ecd68764861c6f2e48a1c53af998270a4afa"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs","sha256":"39fed883f4802e68d3b41a68fea0aba0737810996b33d13577de70faba004c29"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/store.rs","sha256":"fc60ee9c49b2f4f063c449b4c78100c5c4872779e94ca168f796603b380ef6e4"},{"path":"product/integrations/auths-custody/Cargo.toml","sha256":"1e14034185ad1ec24a977fd5f41d0abee219606245c046ce2a82287fadef448b"},{"path":"product/integrations/auths-custody/src/conformance.rs","sha256":"8ed1afd58f18fc6becc268908aa6419c9aa404c79da0197963eb2599df44acf6"},{"path":"product/integrations/auths-custody/src/key.rs","sha256":"70cbb0fd21b6f5652157845a22c35be2d0f6c05b3d138fc4b9bb6dbdc3d81c40"},{"path":"product/integrations/auths-custody/src/lib.rs","sha256":"8ee593c1f59b0fd2126bdda9138026f5bc531beb64d4489a99785842e7b98b43"},{"path":"product/operations/auths-operations/Cargo.toml","sha256":"73dde1e914ba5e1386f8d49c0d730423cc72ae77ec44c6554a6a75cc8e8922b1"},{"path":"product/operations/auths-operations/src/explanation.rs","sha256":"b4a39bcbd5712cb9e735ee7deeb281f3fa6af5ddca973735bf3d87dce427ef11"},{"path":"product/operations/auths-operations/src/lib.rs","sha256":"3f401a56555113b98f57bca172a2660eaecedf76247b83a3fdbb089c133a29cd"},{"path":"product/operations/auths-operations/src/render/json.rs","sha256":"2ae042639960afee123730e945d373bc5dda1d2b3af20ae16c939a7e99b9e418"},{"path":"product/operations/auths-operations/src/render/mod.rs","sha256":"b3b7f6fe473f49227ace5a68bfc3d8dc14b5db8dd9888fd9e207070337b1b8bf"},{"path":"product/operations/auths-operations/src/render/text.rs","sha256":"f216cf3bdb00e264523271b16e7059535ac6b1aabf271cebd7935af155e4bfec"},{"path":"product/policy/auths-bounded-policy/Cargo.toml","sha256":"babd5d200923137ead71d8c2528f847cea323ce98da942a1320b054436612c47"},{"path":"product/policy/auths-bounded-policy/src/arithmetic.rs","sha256":"75e43c5d4eab8d1f71c1daf53839f5f9fe45a400afc1f63a30c6f55ce3632627"},{"path":"product/policy/auths-bounded-policy/src/commitment.rs","sha256":"c5706f2d583454e1a7f570f7ada138d4d864bef0205dfae7c1296774f396bb3f"},{"path":"product/policy/auths-bounded-policy/src/eligibility.rs","sha256":"c9acdfb793074e687fc36efad506be27dbd99ffbf40387bc66c8de39ef238432"},{"path":"product/policy/auths-bounded-policy/src/identifier.rs","sha256":"0006a32bae9eb16c4178cf797df418d2b0a781f2bc6474b741dc1a908141831c"},{"path":"product/policy/auths-bounded-policy/src/kernel.rs","sha256":"99187c28b161ac70bee1afed60711f7f645adb4d1671a01863f9849b369811d5"},{"path":"product/policy/auths-bounded-policy/src/lib.rs","sha256":"76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c"},{"path":"product/policy/auths-bounded-policy/src/receipt.rs","sha256":"3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad"},{"path":"product/policy/auths-bounded-policy/src/registry.rs","sha256":"4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0"},{"path":"product/profiles/auths-profile-api/Cargo.toml","sha256":"7ae85761f58625b5d678f961fd052eebf3e000ef565c7312e3ac857763c0017f"},{"path":"product/profiles/auths-profile-api/src/lib.rs","sha256":"a194b82b20bf8aa864c2334ef6c6aec30b2154ded972862252d5dcefa488ab95"},{"path":"product/profiles/auths-profile-mcp/Cargo.toml","sha256":"db264fc25242f7b7e4133cbe5782545b3107b406c87168ae072683cfb59eac66"},{"path":"product/profiles/auths-profile-mcp/src/arguments.rs","sha256":"a5de696586d507e2aee4a49fee99ef1ef4c51a2e46603f8838f1af6d9009833f"},{"path":"product/profiles/auths-profile-mcp/src/lib.rs","sha256":"d0f8b733a09ef8408336cdebc8948d6a5861012ce6878598b11be7084dfd4280"},{"path":"product/profiles/auths-profile-mcp/src/session.rs","sha256":"166c281fa66333388e4760d6098dad02d3359e1d5de4b8f93312c014f97abb03"},{"path":"product/qualification/auths-recipe-qualification/Cargo.toml","sha256":"b7b15b30b9a3d96d4f089d514266d3a892de6608d30707aa44be31cca89ca9fe"},{"path":"product/qualification/auths-recipe-qualification/src/canonical.rs","sha256":"30a9b50777f0dcb4b606abfee2467d5a975d9f6ad941ab6c13ca3df5b359f667"},{"path":"product/qualification/auths-recipe-qualification/src/closure.rs","sha256":"0ad6aee9bd981e2863fa725f209ec84031db2ff12f4c7ac3aaf5120f0bb86039"},{"path":"product/qualification/auths-recipe-qualification/src/error.rs","sha256":"52d5cf720a1e4579008fdda90a3ac2c31f0b8db57985f121f65e54b4da2b7dd1"},{"path":"product/qualification/auths-recipe-qualification/src/evidence.rs","sha256":"1a4cb862f725b02f9efd827db99637ea8178a5236aa020ec271a363edbe7b362"},{"path":"product/qualification/auths-recipe-qualification/src/ids.rs","sha256":"e81a906d571497ab2da753e1532d4443706410e0b75fdd59a7d2d788c7aec403"},{"path":"product/qualification/auths-recipe-qualification/src/lib.rs","sha256":"195b19f46e1e94a0f3594ad5958e5715bc5e3ad415bdfe6428dfc1b6dd3f4631"},{"path":"product/qualification/auths-recipe-qualification/src/model.rs","sha256":"3484eb0ec287b23d4682ade7b1b0f8d1335985b3fb180f06fc28716076957d5f"},{"path":"product/qualification/auths-recipe-qualification/src/release.rs","sha256":"d816b53e2275e902c750ad03803061844e259e28560ab2d1c77e8a43981a4d6a"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/mod.rs","sha256":"7f15b68e05a04f202bcb1fb80de1d9a9a4fda8bfd6af2cd4e5c660fc75d96fe5"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/schemas.rs","sha256":"c59feec2805621f341a90f81fc005e2c12f7a70f9d264fdeacccb2be4fe1c046"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/verification.rs","sha256":"6a6b5834c5dae10af1ba8939b2deae43b85db71544dc8f077ff63b7fe68ac8a8"},{"path":"product/qualification/auths-recipe-qualification/src/verify.rs","sha256":"edd33589c54fb79bcfccc4cf4e6ccf95bbca088318bb7f8dfc27da684b4fa671"},{"path":"product/receipts/auths-receipts/Cargo.toml","sha256":"6001fa1375899953aafcb07c23a6da0c8f57ea7ec08bb9c950b12a60a8cc6f0f"},{"path":"product/receipts/auths-receipts/src/disclosure.rs","sha256":"ba9ed439be0a320c8a01f5b6e9b51361c1a37e076947490d8e4a484ba6bb119c"},{"path":"product/receipts/auths-receipts/src/lib.rs","sha256":"547a57c4160256719cafb7d0ab972d9fc80b0da14fbbce4148c70c414070ff36"},{"path":"product/runtime/auths-connections/Cargo.toml","sha256":"babeb6e1dda3dfb66291713ce1e43dce5c349833d0b50ea4dccbf986030026b2"},{"path":"product/runtime/auths-connections/src/credential.rs","sha256":"82921413bb053f0f6c7931fbd4e6a86c8cc1d8c6b51debd9c2cef33a8d5b1c51"},{"path":"product/runtime/auths-connections/src/kernel.rs","sha256":"a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8"},{"path":"product/runtime/auths-connections/src/lib.rs","sha256":"79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22"},{"path":"product/runtime/auths-connections/src/model.rs","sha256":"de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77"},{"path":"product/runtime/auths-connections/src/registry.rs","sha256":"e57640e003e72ad3235c567c2bb944a262bd64e673f023b62ea091094cc7e946"},{"path":"product/runtime/auths-gateway-kernel/Cargo.toml","sha256":"34f864e67656af4ac7e5c7a347a23f01fc8ab31365b8e23c0ef474483b14a183"},{"path":"product/runtime/auths-gateway-kernel/src/construct.rs","sha256":"e9d65744bae273d65face4285e5d2da75c06a92ab48f7b8333d496604e31c63c"},{"path":"product/runtime/auths-gateway-kernel/src/lib.rs","sha256":"cfda6f8453426564c085475f183b6f790b438768a19668f1b65d33ba59dc8632"},{"path":"product/runtime/auths-gateway-kernel/src/order.rs","sha256":"e0045f877c4b7fe3860c291039853885064ddcdebba7c9b345ab65e81e646dda"},{"path":"product/runtime/auths-gateway-kernel/src/outcome.rs","sha256":"e9785b1afe70788c89b51b18655bcd5acff7b0c8e3d12fb79c6f05a202e67e6b"},{"path":"product/runtime/auths-gateway-kernel/src/ratio.rs","sha256":"7ace22264812e6fc1ef3a62afee402cf43494bb71ae0d3de219ad1b39d690bcb"},{"path":"product/runtime/auths-gateway-kernel/src/recovery.rs","sha256":"9f46dcd1685ab6e4d1ba04a3fc286a9f3afee8fb47829be1fbc670a7926a2dc6"},{"path":"product/runtime/auths-gateway-kernel/src/transition.rs","sha256":"cefb8f01d915880f6921f2501ff881ad94b9de61072c34d9cd19220992f97374"},{"path":"product/runtime/auths-gateway/Cargo.toml","sha256":"00b28be86921dcdc0ad90cce0c62c2961cafefe96ea6c2edf0e926c3d405ccad"},{"path":"product/runtime/auths-gateway/src/admin.rs","sha256":"2d5cc67afac42fbd15f36e2d1693cd1b20cedacf775040dce6ffe04ccc94c9ea"},{"path":"product/runtime/auths-gateway/src/app.rs","sha256":"6f80f63833ea0815bb44fbf3b0cc54624a08e9fb578b035819f2980dc04e8256"},{"path":"product/runtime/auths-gateway/src/audit.rs","sha256":"0edb2037eb7b5d6f13acfce85c54f62a82bf7fdd31bc7e626c4fec183cef61dd"},{"path":"product/runtime/auths-gateway/src/audit_tests.rs","sha256":"990969384a52d75bc2489d9d412a9e7dd814bca1c8f65c701d6205fae62a15d5"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway-harness.rs","sha256":"12b0c24d36b2e6a3be392d3c081a783b355fdd67dc5b54bacc0410e803116b8c"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway.rs","sha256":"04183960205e64657d5862ead36a4713cf4e9c67fa10af24ee179fecab40ac36"},{"path":"product/runtime/auths-gateway/src/binding.rs","sha256":"663b0ce878319511aa7d05722ab4ab2fa9be18817884ffb2ee9f131ff1e382d1"},{"path":"product/runtime/auths-gateway/src/bounds.rs","sha256":"9cfa0eae4973e5e047a198360b22f041708fa20276b0b90c2ec440f06915d64b"},{"path":"product/runtime/auths-gateway/src/bounds_aggregate_tests.rs","sha256":"ab34f227b7c8692ba1da88ccb32bb3687a66adf8353d8282fae905d4a88eb612"},{"path":"product/runtime/auths-gateway/src/bounds_tests.rs","sha256":"74136bc570da7b9338b5a1a1ed9d3fd892c55135160964f9d3ac0e2cf5741375"},{"path":"product/runtime/auths-gateway/src/connection.rs","sha256":"7b5d049c258a26ed1c93ecf860f51d051a8a65f9b93554af0b1ea93862398ec9"},{"path":"product/runtime/auths-gateway/src/credential_journal.rs","sha256":"8e2b0733038d93ca5df770d27a870237e3b65664fa48da017d964a65bbbe25b8"},{"path":"product/runtime/auths-gateway/src/echo_verify.rs","sha256":"6d453051665f823abd7354d5c50031d9524cf47d6092d2f09080ae814e3b9575"},{"path":"product/runtime/auths-gateway/src/engine.rs","sha256":"a9f71575994ff21633ddfc533b1d810515db71aa0146fa8869dad72eddcb2a12"},{"path":"product/runtime/auths-gateway/src/fuzzing.rs","sha256":"ed3b0028487eb546a3b0a91d115aa8f18bcea324b61620bfe8e35a9e6ab18758"},{"path":"product/runtime/auths-gateway/src/generation_floor.rs","sha256":"47964a5f1ca2fc9c4da0b526b6d5c5637fc0ce1d2e429219d02f1b0dc652fdff"},{"path":"product/runtime/auths-gateway/src/harness.rs","sha256":"c87e479f3eb281960f6c9c80d43c7560d7ccb654b0154ec823d3fcec4884ac05"},{"path":"product/runtime/auths-gateway/src/lib.rs","sha256":"b182052835a2cd631d1f801a74788d6ac1ef9cae21ade9ab4ffc270cd6f667ed"},{"path":"product/runtime/auths-gateway/src/listener.rs","sha256":"aa08239bcbc1fcb55e8a212fbdf6a84f12985b0d436dcb51dc58b06e59e435f2"},{"path":"product/runtime/auths-gateway/src/observed_tests.rs","sha256":"a22be071695f89ca2578a4d82fd80d9cb82289213c9bdb8f0470f6b2dc3d9201"},{"path":"product/runtime/auths-gateway/src/observer.rs","sha256":"562ffcaea071c3856e0708dc2fe33516917e145d2438aabb75af0a2b6ba01046"},{"path":"product/runtime/auths-gateway/src/onboarding.rs","sha256":"0dfd7d67e7f02f18a28d1c86ca1b7751d7463f5efcdbe3825de0ad8cbccb3891"},{"path":"product/runtime/auths-gateway/src/operator.rs","sha256":"c3c36954a3e86723df035b47f43b85fc8ab3a6292983522b6258d5c6b4e6c4e4"},{"path":"product/runtime/auths-gateway/src/pending_vectors/attempts.rs","sha256":"47ef3c8cb1c5504d47ae9a0088705ce6715fe86bac1671a34a56fb38a64d0dd3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/bounds.rs","sha256":"e612217307e1da5b0eb5ee6582a7458bb064b8aa8a529fc6555b1b334127ab68"},{"path":"product/runtime/auths-gateway/src/pending_vectors/codes.rs","sha256":"e00670a5ef24eb856cc2c6dcda8e5a263842f55c76bb939c0c27bd9df37e5522"},{"path":"product/runtime/auths-gateway/src/pending_vectors/keys.rs","sha256":"f84c56f2ea9cb34b2b79c72d13fbf2c6585010ec1ed450af58a78c80c1ea1edd"},{"path":"product/runtime/auths-gateway/src/pending_vectors/mod.rs","sha256":"5de8340f0ef71a0b57a09e323fefe473d3160c6ae952b9ba46f714825fbacafc"},{"path":"product/runtime/auths-gateway/src/pending_vectors/outcomes.rs","sha256":"8ec07b9511b48913af36ac999d2aa0e82924289f6acb23ddaeb9f00f99815166"},{"path":"product/runtime/auths-gateway/src/pending_vectors/production.rs","sha256":"c2fa18b5d96c87689fe60d95faadebe2c7fdf5b78be872ca15a67ad980106ed3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/recipes.rs","sha256":"51693208270231c25c3aef2a32151d5962114c71e86b88cb9df83181c7af83d9"},{"path":"product/runtime/auths-gateway/src/pre_entry.rs","sha256":"06ea78ca140468bfaba17d9ab04912ad68673954c3203c98fed28272ff2a00c0"},{"path":"product/runtime/auths-gateway/src/property_tests.rs","sha256":"939c081e2e154aaf10186754044bdd65608932c899b970a04a71d0afaa999a93"},{"path":"product/runtime/auths-gateway/src/qualification.rs","sha256":"a4398512ccb7bb494000fe38f03e0faa7b82d1f80ef5ee2dfa75698ae4f5a9be"},{"path":"product/runtime/auths-gateway/src/qualification_tests.rs","sha256":"4473add5729b97faf04d7be7fd8cf3bbacd7f545e1b61c7d2782563011906b4d"},{"path":"product/runtime/auths-gateway/src/quorum_tests.rs","sha256":"a78380b019104d688c11a4410082c7e08ded3106aab099954c4f8a1b4ae0fd89"},{"path":"product/runtime/auths-gateway/src/readiness.rs","sha256":"911c3f11892f94641574375e2da4c671c802738f71082f12c39832331052d43d"},{"path":"product/runtime/auths-gateway/src/recipe.rs","sha256":"fecf9af67e7afc48d080e9f8f55f8ce28e49d0e08988717a27908bbda461d6b6"},{"path":"product/runtime/auths-gateway/src/recipe/lower.rs","sha256":"8088b8751ed831dbb48247af953c6290ac95e2a438ccd5bd65eff54be06a1fd1"},{"path":"product/runtime/auths-gateway/src/recipe/review.rs","sha256":"c3eb7d9fdd98dacf52750b14b67ad7b7faaecbbdeafff1e0b049f67d0a2d0139"},{"path":"product/runtime/auths-gateway/src/recipe/runtime.rs","sha256":"c286f0d15f974402822c0810d8e97f98411dc1c557755cc23e540d85e2bb42d9"},{"path":"product/runtime/auths-gateway/src/recipe/source.rs","sha256":"1af50298fb1461e1b24cbdf560d43124d6b1c4c529586c911b1c4797214a69ff"},{"path":"product/runtime/auths-gateway/src/recipe/tests.rs","sha256":"aac551a2481bbc60864c64079bc667dcb232e45a0f41a04073ed84ab5dbe1fce"},{"path":"product/runtime/auths-gateway/src/recipe/validate.rs","sha256":"3711b17605cb7b0d639bc1b180449231f5882a306cab20e2c7782155cc63b0d4"},{"path":"product/runtime/auths-gateway/src/scenario_tests.rs","sha256":"d8271761b12597bfe1233f8eb5ad1d4e5498c5d03388e832e24ab818484a1de4"},{"path":"product/runtime/auths-gateway/src/separation.rs","sha256":"be9306848ca5d801767cf6aa14247c8618312ef0e202f00ce0c24c4844491061"},{"path":"product/runtime/auths-gateway/src/store.rs","sha256":"1e5288345c2cb1421aeda277b3158d07607404b0ec46943222ac107b63dcbb46"},{"path":"product/runtime/auths-gateway/src/store_testkit.rs","sha256":"88d82fee42f1b8ef521e8deef0216e938ebeaad822eb2f5020e70b89d145ea70"},{"path":"product/runtime/auths-gateway/src/submit.rs","sha256":"c78dbbba7c45b443febf655056c5edcd635e77be7b21c5b2c318097502415ffe"},{"path":"product/runtime/auths-gateway/src/support.rs","sha256":"8537d54b8071744a6a3983f48620a8abe1169c6103b281badd701dd0999ac9c7"},{"path":"product/runtime/auths-gateway/src/transport.rs","sha256":"be2c6dc75b8daec110bf8749fedc3823f6067d40b999aa3eb21126896a97d3ad"},{"path":"product/runtime/auths-kernel-runtime/Cargo.toml","sha256":"926bcd0053e5edd703be8f0027ad009e2982db013c8174c1366edbf38b48087d"},{"path":"product/runtime/auths-kernel-runtime/src/lib.rs","sha256":"7108faae9ca4bc32dc093ddaf885ac8f74f3c9b8d317b7c7d0ed00d1d0ab5972"},{"path":"product/runtime/auths-lifecycle/Cargo.toml","sha256":"c5053c705f8d5554b44e432fe75287a2faf11d644e5a2552e45ad6cd94176af5"},{"path":"product/runtime/auths-lifecycle/src/codec.rs","sha256":"51c4b746749150e8bfcd8ff972b3f6c1ef40bec15583448ec1b471d9ad737dc0"},{"path":"product/runtime/auths-lifecycle/src/digest.rs","sha256":"55282cd7d8aba37713c2dcb5357c9877819edb72a30eadefb860d28d7d3a3eb7"},{"path":"product/runtime/auths-lifecycle/src/identifier.rs","sha256":"31620e8c16de68d3d2d3b84d6353c1a5b9d4151d8247f91fa389b906a8e660f1"},{"path":"product/runtime/auths-lifecycle/src/kernel.rs","sha256":"2abb8c094b36d35b364e74d78091d14c5d6f3d1eb6552cca3b5538dbd017ce23"},{"path":"product/runtime/auths-lifecycle/src/lib.rs","sha256":"afe5a345cd309b5a4f08ffba3170a6d7f16ff914892b3f2006d5208ed24ec736"},{"path":"product/runtime/auths-lifecycle/src/model.rs","sha256":"1af12bbeeeaa65ec02ddcebd7d2c8c92ec1e339fa40ae85b45ab9b01a722a4fa"},{"path":"product/runtime/auths-lifecycle/src/operation.rs","sha256":"78e6d05fcf5d7ea4f148032a3fa26fdfcab77eb346019effe927b08e0d64d732"},{"path":"product/runtime/auths-lifecycle/src/registry.rs","sha256":"53495fe6f7a77422593a41623e28716f1c140dcc1e00f87f6b0ffbfb93a5ef90"},{"path":"product/runtime/auths-lifecycle/src/sealed.rs","sha256":"2e0c03b5813c926c159598bb7890d1523825edbe57cd687d42a5dfb3374a0c19"},{"path":"product/runtime/auths-lifecycle/src/test_support.rs","sha256":"221d9a5c5ef8e1f9f8fd66927484eaf813571d0568470278ecd8fa08a5eec8cd"},{"path":"product/runtime/auths-lifecycle/src/transition.rs","sha256":"011805a28efdd541f44ccea54dd0e34a1e58f4004447ee58013703b4fb6b2822"},{"path":"product/runtime/auths-runtime/Cargo.toml","sha256":"dd29d80a8b4bb56c869f036a6c9998f6e6d1c0383ac5dc03fa42b24abe2a7ff7"},{"path":"product/runtime/auths-runtime/src/lib.rs","sha256":"132ca03d58c14905d3a822a4972f42a22a5ad33a45f2ba9ca44f3a57d810b4b0"},{"path":"product/runtime/auths-runtime/src/production.rs","sha256":"fd4eff4270c571c10fcff6cf27df28961ebf074de8a1a028f500fda1ca376820"},{"path":"product/sdk/auths-approval-quorum/Cargo.toml","sha256":"df904971fca87a24194c5816738a331588fe8f164acb5d70839a35dca5f57114"},{"path":"product/sdk/auths-approval-quorum/src/lib.rs","sha256":"72e4086088a1c0912e4e1a9e980f26a5c280bf5ab16ea39c9f0f58d5096ac2ce"},{"path":"product/sdk/auths-approval-quorum/src/remote.rs","sha256":"9fa029c7c63003adf260f8aec55160c545681c60c1bace0d934e7525862aac7b"},{"path":"product/sdk/auths-approval-quorum/src/remote_tests.rs","sha256":"8a09ce17cfee82a035a74edd535f3ebeb3db0e078784740d3997b17dbdb10197"},{"path":"product/sdk/auths-approval-quorum/src/tests.rs","sha256":"0acbf12be3e497dcc6c2d8f29c9af3b1a7ed8e11b75f6399570d4f217a785060"},{"path":"product/stores/auths-stores/Cargo.toml","sha256":"a32c4b76d17b264be5d40d24497ff237e1ed87822e8bab86229b3db93106dbe3"},{"path":"product/stores/auths-stores/src/gateway_attempt.rs","sha256":"185da8f4a220fba836d5b78a9311f03204681c43a3c53951008084d135bf4d21"},{"path":"product/stores/auths-stores/src/lib.rs","sha256":"e721262edf8a9ab5568ddc27639176312d4a366203b5f73e2d7c11fde2c554e9"},{"path":"product/stores/auths-stores/src/lifecycle.rs","sha256":"94f64d25bc178a9e60ba3c0ee6915d7fb3af7c4468792d76b4e70f43f4de1e2f"}],"schema":"auths.gateway-semantic-closure/1"} \ No newline at end of file +{"files":[{"path":"Cargo.lock","sha256":"c94ed342774d5e2823f01ecf74b8a4812c5f9a6b0cf811d31f2e2cecb671a275"},{"path":"Cargo.toml","sha256":"6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24"},{"path":"core/adapters/auths-did-keri/Cargo.toml","sha256":"86ba3e3f9a0a70d970568bfb3113b7ba7bbdd81c3eebbb52743dd574a0c0ecaa"},{"path":"core/adapters/auths-did-keri/src/lib.rs","sha256":"a75674842f8a7142004369ccd206ab43e476459293f0ff4bed4d4e659031b3e3"},{"path":"core/adapters/auths-did-key/Cargo.toml","sha256":"d5a3ae07ecde83f91eed4c3785051dd0f44eab6c891754f3309b6b40596707d7"},{"path":"core/adapters/auths-did-key/src/lib.rs","sha256":"b76a3f4528a725df53cfa9242e6e414e1d26caa48468aaed497e28b121f4497c"},{"path":"core/adapters/auths-raw-key/Cargo.toml","sha256":"f49616bc18c19e6aaa7e6a02ccebcdb9f5c1422c1278ef9869e0dbf22ceda7be"},{"path":"core/adapters/auths-raw-key/src/lib.rs","sha256":"45eec1b295dac3bed65cd79c942870b926b06b3f5d38eaebaeb6140ac69315fa"},{"path":"core/crates/auths-algebra-kernel/Cargo.toml","sha256":"0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba"},{"path":"core/crates/auths-algebra-kernel/src/generated.rs","sha256":"ae4bcbef42a408c7ffa0c6a74a42f7de177a6f14479e51d205acf830bda05960"},{"path":"core/crates/auths-algebra-kernel/src/lib.rs","sha256":"6654667eeb9b353d6648954c9fd2e8838462a82ce6b2803eb49e1366892c68c6"},{"path":"core/crates/auths-assurance/Cargo.toml","sha256":"afcb12a97ddd09d7a264b9ecd3fcaefc865ff2c9b4539ee85b00883420ba333a"},{"path":"core/crates/auths-assurance/src/lib.rs","sha256":"0fb2ec844d674b25a9e20b1601452c89c2454901fa506adfa9bb38ef9a7fa213"},{"path":"core/crates/auths-author/Cargo.toml","sha256":"1e6f0e3bc079ddb558decf0db26b291c6e72fc47327b6df1b7650d41689b215f"},{"path":"core/crates/auths-author/src/lib.rs","sha256":"e14475f2f49715a1869d5fa6b11ff1fbb72497e39097e09f833b0bae7e5b3f2b"},{"path":"core/crates/auths-author/src/observations.rs","sha256":"dda7d6bfa6f4bd7e95a480ca283c2c0e996f69c5c15cb0c7197af328131a7066"},{"path":"core/crates/auths-authority/Cargo.toml","sha256":"4f68212938029f79ebd857b4f3038494eb85d0163d49f07e51376715cf959815"},{"path":"core/crates/auths-authority/src/lib.rs","sha256":"da88d5194de4e17449e69972c0fb042afa3c39798a8f570f30771e77c384f1eb"},{"path":"core/crates/auths-codec/Cargo.toml","sha256":"e20e51826e17814effd9d8925d18d5fbdd6c0d37bf50231e743ec2611314722c"},{"path":"core/crates/auths-codec/src/approval.rs","sha256":"fbff43bf4d57f69f8b7738a8647751cde75c5a932dee65d924a1fe9c7202f91f"},{"path":"core/crates/auths-codec/src/bounded_policy.rs","sha256":"d21f6728be2d8a04b6d94921f2b683f7e61cbb42e0ac6866f1c88a49caa534c3"},{"path":"core/crates/auths-codec/src/decode.rs","sha256":"ba2999584cdf53b1b517ecb9c7ea50d39efee17c666a9a38e2ad1ac94379f778"},{"path":"core/crates/auths-codec/src/encode.rs","sha256":"8491192053e2e15d62b4d2a491de22405b7487ead69ab6f6bca40669ce7ca5f7"},{"path":"core/crates/auths-codec/src/error.rs","sha256":"fecb0737c16deb42d859f1dc7727c698438d9ac12064fd99e0024629642c390c"},{"path":"core/crates/auths-codec/src/hash.rs","sha256":"f88e111f1dbb2cef6b7b5e9c948cb45ff92e366710c8a5f5c636138aa748479e"},{"path":"core/crates/auths-codec/src/lib.rs","sha256":"3b0e5c94c6f34f750b88a9333e1d5c8145746d845d3a23e0d2f61807cf592ea7"},{"path":"core/crates/auths-codec/src/observation.rs","sha256":"38328b0c71ff97a4196eeade8b4faa889527ff1f80bb168468bcd49082a3987e"},{"path":"core/crates/auths-composition/Cargo.toml","sha256":"331e13025eb82588b5269ed3975929eb41c823d588c49e4c296273d85c6fe80e"},{"path":"core/crates/auths-composition/src/lib.rs","sha256":"e42e3b0b6a9985b73c533aeb23799c638979aa27a9ce7d0f10a8d60340570fb1"},{"path":"core/crates/auths-model/Cargo.toml","sha256":"565c15302b0cc9270db1e28efa3862804846850ba933cc17aea8abcec4a65987"},{"path":"core/crates/auths-model/src/approval.rs","sha256":"54cf44a9ef747ec21546a4086aecfb130bc7803b0d646430e6082df51e6e305f"},{"path":"core/crates/auths-model/src/bounded.rs","sha256":"f90496abc0a06c028b4d850af6ddab7d850bfafeaa3d042f1b1246a41d8bbbc9"},{"path":"core/crates/auths-model/src/bounded_policy.rs","sha256":"306a8f049cc7cfc7635fe0e4de47eb7813eed63d3c14c3be2b51586aa4eea450"},{"path":"core/crates/auths-model/src/lib.rs","sha256":"e7cfe6bb9574c6b016aa63e70658c31e0b90903ec6479a49f4a2ceb64f5bad97"},{"path":"core/crates/auths-model/src/observation.rs","sha256":"b3ed3e3cc090afca2896a7d3de7988afccc1ee1ea0ebd91b51a8bc0f20ad8dbb"},{"path":"core/crates/auths-multikey/Cargo.toml","sha256":"858756c1197befcada06134742bffe8d58cf674cadd6c046bf710570e96efaf2"},{"path":"core/crates/auths-multikey/src/lib.rs","sha256":"f5177fffb11e40eeaaa665ba886c541fc1f24d5eacdd6983fb03dc20148733f0"},{"path":"core/crates/auths-ports/Cargo.toml","sha256":"596a9b0f5af3717c16a6d13f7054d8a106bcd9f01f5f72c2235dd2afcf0ab16c"},{"path":"core/crates/auths-ports/src/binding.rs","sha256":"a16c012d40aa4249e3ec54372b9611006d0bfe8c7dc3c741911c2194ad17736d"},{"path":"core/crates/auths-ports/src/diagnostics.rs","sha256":"aa596572503b5a65a918bb2ff38281c144ff53821ee914e9325c852828d852df"},{"path":"core/crates/auths-ports/src/lib.rs","sha256":"8da1debf86f9532df0660155d04298beb1ba3a1204508f8586e2e67cd2fb3449"},{"path":"core/crates/auths-ports/src/path.rs","sha256":"b68fc547b4e4d97a60cbbc1cc1939fc6b34a8233b81f840bd396914a707e3ea1"},{"path":"core/crates/auths-raw-key-core/Cargo.toml","sha256":"98c0bc8527a537512e43a74dd6ba9658c6f0cdc16610cf938e3f9b43785d836d"},{"path":"core/crates/auths-raw-key-core/src/lib.rs","sha256":"98c0500c41697aae28708ad0bf970b9a97583d96a3d2c18d23e7fa351e0f7d12"},{"path":"core/crates/auths-registries/Cargo.toml","sha256":"590e49e58b0622d9d6274fea46796dcdb07dec9550eff295cce6a6427ffa51e2"},{"path":"core/crates/auths-registries/src/lib.rs","sha256":"450d3886d85ee333b7e046317fb5b47cde62483d5f3e41d46265e2caf4c373ec"},{"path":"core/crates/auths-registries/src/template.rs","sha256":"1224039dd2b3ce6fa8357613d8cafbae40400493da7176da202b9ade62fa05e4"},{"path":"core/crates/auths-signature-core/Cargo.toml","sha256":"6bee2230eb30af1be0bd5c2d57bd3e1903497a70028d47290d4ac6e9e0e8bca0"},{"path":"core/crates/auths-signature-core/src/lib.rs","sha256":"6e3f9311ded5e49ea50d445eb21e6d8fa12442aa4362a73e0cb6fda15b7cd865"},{"path":"core/crates/auths-signature/Cargo.toml","sha256":"7f7b5682466ba439d8c59579022cb61068cad9fb4bd2d73e1cc21327c902b450"},{"path":"core/crates/auths-signature/src/lib.rs","sha256":"b3d9ac4cc3ba0797b9e1c09f2d6ac05089b25dac4e285a5af28c0165b33d925b"},{"path":"core/crates/auths-verifier/Cargo.toml","sha256":"c43358e06a33324b41a8b93e5cc7279c55f7d21f1f6cfaa539a3fc7b4c27a38f"},{"path":"core/crates/auths-verifier/src/approval.rs","sha256":"c3cae6a49e169051eb555bb092b1069a4d422516d6a2114623a89e5f31ff923f"},{"path":"core/crates/auths-verifier/src/causal.rs","sha256":"9635230f33b13a263573d319ac8a1976addbcc07677514a43e3c7bf28dc04587"},{"path":"core/crates/auths-verifier/src/lib.rs","sha256":"f22dec38dfa47ced8da4f605390da8453273bee1da010f57fd1fdfcb10e0b389"},{"path":"core/crates/auths-verifier/src/observation.rs","sha256":"0bb07f06a0f9524c88427df1c972b1de8ba038a9eeeb15d3134c25125ae84b1e"},{"path":"core/crates/auths-verifier/src/trace.rs","sha256":"2213d72023a1d9e0413a2cf2c51c3dad9e04775d86033a0caaa9d29a8f0036f8"},{"path":"exchange/crates/auths-proof-exchange-model/Cargo.toml","sha256":"34b2db64f93a288e942b5a3918d28cdcbef906e0dc9074ce848018d3d5f7a1fa"},{"path":"exchange/crates/auths-proof-exchange-model/src/lib.rs","sha256":"49fac5aff2339d3a57c41cb8bb2a82852538e8f77ecc4b157c88e264ff31fb55"},{"path":"exchange/crates/auths-proof-exchange-port/Cargo.toml","sha256":"7ff660f1b7579dc570c791090aeb450404fbbf44c92781e289f5ccdde746d739"},{"path":"exchange/crates/auths-proof-exchange-port/src/lib.rs","sha256":"b408fb40c6432edc1facb3d8b3e9433a033f8dc73fe2e0ba5a88c972ca675021"},{"path":"product/config/auths-config/Cargo.toml","sha256":"e4b568ab9f6d84f7d7e6d66443fe825f360db9c27bc7c31d6ddc0647ba3ab304"},{"path":"product/config/auths-config/src/lib.rs","sha256":"fecf00ea65cef9018fda9af2063326d7065b869266d0d9e73a4f06816f1102cc"},{"path":"product/errors/auths-errors/Cargo.toml","sha256":"3b3a199b6460ba75bda84475bb5accd35e1485448a3981038db85bf4772dd350"},{"path":"product/errors/auths-errors/src/lib.rs","sha256":"7feeb9069fa4003f94f1f07c1c94619cf1c883e0dbaaf2187f04d0f742264bdd"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/Cargo.toml","sha256":"716f1f2a117d6d69d8effe9ee9057e24ba3502f20af6a602b06facb638cdabed"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/api.rs","sha256":"b3c4321e0737835ecc4f17235d7589b7f3d62180954ebb98ea9449252300245a"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/clock.rs","sha256":"73f0a6e0f5903883329fa6683f5888288f759512ac69e5c87efd2b6b87f7d79f"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/http.rs","sha256":"14c1fce14e24c984b2a275563a29b6326fb08367922b6e8d37ba38b9cb81aa2b"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/identity.rs","sha256":"186de11230c8b33375951c4368609f8976bf9795f171af3fd7fac26207a94361"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs","sha256":"881ad9ccca369b6eaa6bfd9ec03b1585bff07b042da38942ef57154839449d3e"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/names.rs","sha256":"41bb23572d6002e23ee103d6fe70ecd68764861c6f2e48a1c53af998270a4afa"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs","sha256":"39fed883f4802e68d3b41a68fea0aba0737810996b33d13577de70faba004c29"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/store.rs","sha256":"fc60ee9c49b2f4f063c449b4c78100c5c4872779e94ca168f796603b380ef6e4"},{"path":"product/integrations/auths-custody/Cargo.toml","sha256":"1e14034185ad1ec24a977fd5f41d0abee219606245c046ce2a82287fadef448b"},{"path":"product/integrations/auths-custody/src/conformance.rs","sha256":"8ed1afd58f18fc6becc268908aa6419c9aa404c79da0197963eb2599df44acf6"},{"path":"product/integrations/auths-custody/src/key.rs","sha256":"70cbb0fd21b6f5652157845a22c35be2d0f6c05b3d138fc4b9bb6dbdc3d81c40"},{"path":"product/integrations/auths-custody/src/lib.rs","sha256":"8ee593c1f59b0fd2126bdda9138026f5bc531beb64d4489a99785842e7b98b43"},{"path":"product/operations/auths-operations/Cargo.toml","sha256":"73dde1e914ba5e1386f8d49c0d730423cc72ae77ec44c6554a6a75cc8e8922b1"},{"path":"product/operations/auths-operations/src/explanation.rs","sha256":"b4a39bcbd5712cb9e735ee7deeb281f3fa6af5ddca973735bf3d87dce427ef11"},{"path":"product/operations/auths-operations/src/lib.rs","sha256":"3f401a56555113b98f57bca172a2660eaecedf76247b83a3fdbb089c133a29cd"},{"path":"product/operations/auths-operations/src/render/json.rs","sha256":"2ae042639960afee123730e945d373bc5dda1d2b3af20ae16c939a7e99b9e418"},{"path":"product/operations/auths-operations/src/render/mod.rs","sha256":"b3b7f6fe473f49227ace5a68bfc3d8dc14b5db8dd9888fd9e207070337b1b8bf"},{"path":"product/operations/auths-operations/src/render/text.rs","sha256":"f216cf3bdb00e264523271b16e7059535ac6b1aabf271cebd7935af155e4bfec"},{"path":"product/policy/auths-bounded-policy/Cargo.toml","sha256":"babd5d200923137ead71d8c2528f847cea323ce98da942a1320b054436612c47"},{"path":"product/policy/auths-bounded-policy/src/arithmetic.rs","sha256":"75e43c5d4eab8d1f71c1daf53839f5f9fe45a400afc1f63a30c6f55ce3632627"},{"path":"product/policy/auths-bounded-policy/src/commitment.rs","sha256":"c5706f2d583454e1a7f570f7ada138d4d864bef0205dfae7c1296774f396bb3f"},{"path":"product/policy/auths-bounded-policy/src/eligibility.rs","sha256":"c9acdfb793074e687fc36efad506be27dbd99ffbf40387bc66c8de39ef238432"},{"path":"product/policy/auths-bounded-policy/src/identifier.rs","sha256":"0006a32bae9eb16c4178cf797df418d2b0a781f2bc6474b741dc1a908141831c"},{"path":"product/policy/auths-bounded-policy/src/kernel.rs","sha256":"99187c28b161ac70bee1afed60711f7f645adb4d1671a01863f9849b369811d5"},{"path":"product/policy/auths-bounded-policy/src/lib.rs","sha256":"76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c"},{"path":"product/policy/auths-bounded-policy/src/receipt.rs","sha256":"3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad"},{"path":"product/policy/auths-bounded-policy/src/registry.rs","sha256":"4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0"},{"path":"product/profiles/auths-profile-api/Cargo.toml","sha256":"7ae85761f58625b5d678f961fd052eebf3e000ef565c7312e3ac857763c0017f"},{"path":"product/profiles/auths-profile-api/src/lib.rs","sha256":"a194b82b20bf8aa864c2334ef6c6aec30b2154ded972862252d5dcefa488ab95"},{"path":"product/profiles/auths-profile-mcp/Cargo.toml","sha256":"db264fc25242f7b7e4133cbe5782545b3107b406c87168ae072683cfb59eac66"},{"path":"product/profiles/auths-profile-mcp/src/arguments.rs","sha256":"a5de696586d507e2aee4a49fee99ef1ef4c51a2e46603f8838f1af6d9009833f"},{"path":"product/profiles/auths-profile-mcp/src/lib.rs","sha256":"d0f8b733a09ef8408336cdebc8948d6a5861012ce6878598b11be7084dfd4280"},{"path":"product/profiles/auths-profile-mcp/src/session.rs","sha256":"166c281fa66333388e4760d6098dad02d3359e1d5de4b8f93312c014f97abb03"},{"path":"product/qualification/auths-recipe-qualification/Cargo.toml","sha256":"b7b15b30b9a3d96d4f089d514266d3a892de6608d30707aa44be31cca89ca9fe"},{"path":"product/qualification/auths-recipe-qualification/src/canonical.rs","sha256":"30a9b50777f0dcb4b606abfee2467d5a975d9f6ad941ab6c13ca3df5b359f667"},{"path":"product/qualification/auths-recipe-qualification/src/closure.rs","sha256":"0ad6aee9bd981e2863fa725f209ec84031db2ff12f4c7ac3aaf5120f0bb86039"},{"path":"product/qualification/auths-recipe-qualification/src/error.rs","sha256":"52d5cf720a1e4579008fdda90a3ac2c31f0b8db57985f121f65e54b4da2b7dd1"},{"path":"product/qualification/auths-recipe-qualification/src/evidence.rs","sha256":"1a4cb862f725b02f9efd827db99637ea8178a5236aa020ec271a363edbe7b362"},{"path":"product/qualification/auths-recipe-qualification/src/ids.rs","sha256":"e81a906d571497ab2da753e1532d4443706410e0b75fdd59a7d2d788c7aec403"},{"path":"product/qualification/auths-recipe-qualification/src/lib.rs","sha256":"195b19f46e1e94a0f3594ad5958e5715bc5e3ad415bdfe6428dfc1b6dd3f4631"},{"path":"product/qualification/auths-recipe-qualification/src/model.rs","sha256":"3484eb0ec287b23d4682ade7b1b0f8d1335985b3fb180f06fc28716076957d5f"},{"path":"product/qualification/auths-recipe-qualification/src/release.rs","sha256":"d816b53e2275e902c750ad03803061844e259e28560ab2d1c77e8a43981a4d6a"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/mod.rs","sha256":"7f15b68e05a04f202bcb1fb80de1d9a9a4fda8bfd6af2cd4e5c660fc75d96fe5"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/schemas.rs","sha256":"c59feec2805621f341a90f81fc005e2c12f7a70f9d264fdeacccb2be4fe1c046"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/verification.rs","sha256":"6a6b5834c5dae10af1ba8939b2deae43b85db71544dc8f077ff63b7fe68ac8a8"},{"path":"product/qualification/auths-recipe-qualification/src/verify.rs","sha256":"edd33589c54fb79bcfccc4cf4e6ccf95bbca088318bb7f8dfc27da684b4fa671"},{"path":"product/receipts/auths-receipts/Cargo.toml","sha256":"6001fa1375899953aafcb07c23a6da0c8f57ea7ec08bb9c950b12a60a8cc6f0f"},{"path":"product/receipts/auths-receipts/src/disclosure.rs","sha256":"ba9ed439be0a320c8a01f5b6e9b51361c1a37e076947490d8e4a484ba6bb119c"},{"path":"product/receipts/auths-receipts/src/lib.rs","sha256":"547a57c4160256719cafb7d0ab972d9fc80b0da14fbbce4148c70c414070ff36"},{"path":"product/runtime/auths-connections/Cargo.toml","sha256":"babeb6e1dda3dfb66291713ce1e43dce5c349833d0b50ea4dccbf986030026b2"},{"path":"product/runtime/auths-connections/src/credential.rs","sha256":"82921413bb053f0f6c7931fbd4e6a86c8cc1d8c6b51debd9c2cef33a8d5b1c51"},{"path":"product/runtime/auths-connections/src/kernel.rs","sha256":"a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8"},{"path":"product/runtime/auths-connections/src/lib.rs","sha256":"79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22"},{"path":"product/runtime/auths-connections/src/model.rs","sha256":"de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77"},{"path":"product/runtime/auths-connections/src/registry.rs","sha256":"e57640e003e72ad3235c567c2bb944a262bd64e673f023b62ea091094cc7e946"},{"path":"product/runtime/auths-gateway-kernel/Cargo.toml","sha256":"34f864e67656af4ac7e5c7a347a23f01fc8ab31365b8e23c0ef474483b14a183"},{"path":"product/runtime/auths-gateway-kernel/src/construct.rs","sha256":"e9d65744bae273d65face4285e5d2da75c06a92ab48f7b8333d496604e31c63c"},{"path":"product/runtime/auths-gateway-kernel/src/lib.rs","sha256":"cfda6f8453426564c085475f183b6f790b438768a19668f1b65d33ba59dc8632"},{"path":"product/runtime/auths-gateway-kernel/src/order.rs","sha256":"e0045f877c4b7fe3860c291039853885064ddcdebba7c9b345ab65e81e646dda"},{"path":"product/runtime/auths-gateway-kernel/src/outcome.rs","sha256":"e9785b1afe70788c89b51b18655bcd5acff7b0c8e3d12fb79c6f05a202e67e6b"},{"path":"product/runtime/auths-gateway-kernel/src/ratio.rs","sha256":"7ace22264812e6fc1ef3a62afee402cf43494bb71ae0d3de219ad1b39d690bcb"},{"path":"product/runtime/auths-gateway-kernel/src/recovery.rs","sha256":"9f46dcd1685ab6e4d1ba04a3fc286a9f3afee8fb47829be1fbc670a7926a2dc6"},{"path":"product/runtime/auths-gateway-kernel/src/transition.rs","sha256":"cefb8f01d915880f6921f2501ff881ad94b9de61072c34d9cd19220992f97374"},{"path":"product/runtime/auths-gateway/Cargo.toml","sha256":"00b28be86921dcdc0ad90cce0c62c2961cafefe96ea6c2edf0e926c3d405ccad"},{"path":"product/runtime/auths-gateway/src/admin.rs","sha256":"2d5cc67afac42fbd15f36e2d1693cd1b20cedacf775040dce6ffe04ccc94c9ea"},{"path":"product/runtime/auths-gateway/src/app.rs","sha256":"6f80f63833ea0815bb44fbf3b0cc54624a08e9fb578b035819f2980dc04e8256"},{"path":"product/runtime/auths-gateway/src/audit.rs","sha256":"0edb2037eb7b5d6f13acfce85c54f62a82bf7fdd31bc7e626c4fec183cef61dd"},{"path":"product/runtime/auths-gateway/src/audit_tests.rs","sha256":"990969384a52d75bc2489d9d412a9e7dd814bca1c8f65c701d6205fae62a15d5"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway-harness.rs","sha256":"12b0c24d36b2e6a3be392d3c081a783b355fdd67dc5b54bacc0410e803116b8c"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway.rs","sha256":"9f4b46006fbc28a71c07f14f1f40837782407628c094d7c17f216f9be75e2dde"},{"path":"product/runtime/auths-gateway/src/binding.rs","sha256":"663b0ce878319511aa7d05722ab4ab2fa9be18817884ffb2ee9f131ff1e382d1"},{"path":"product/runtime/auths-gateway/src/bounds.rs","sha256":"9cfa0eae4973e5e047a198360b22f041708fa20276b0b90c2ec440f06915d64b"},{"path":"product/runtime/auths-gateway/src/bounds_aggregate_tests.rs","sha256":"ab34f227b7c8692ba1da88ccb32bb3687a66adf8353d8282fae905d4a88eb612"},{"path":"product/runtime/auths-gateway/src/bounds_tests.rs","sha256":"74136bc570da7b9338b5a1a1ed9d3fd892c55135160964f9d3ac0e2cf5741375"},{"path":"product/runtime/auths-gateway/src/connection.rs","sha256":"7b5d049c258a26ed1c93ecf860f51d051a8a65f9b93554af0b1ea93862398ec9"},{"path":"product/runtime/auths-gateway/src/credential_journal.rs","sha256":"8e2b0733038d93ca5df770d27a870237e3b65664fa48da017d964a65bbbe25b8"},{"path":"product/runtime/auths-gateway/src/echo_verify.rs","sha256":"6d453051665f823abd7354d5c50031d9524cf47d6092d2f09080ae814e3b9575"},{"path":"product/runtime/auths-gateway/src/engine.rs","sha256":"a9f71575994ff21633ddfc533b1d810515db71aa0146fa8869dad72eddcb2a12"},{"path":"product/runtime/auths-gateway/src/fuzzing.rs","sha256":"ed3b0028487eb546a3b0a91d115aa8f18bcea324b61620bfe8e35a9e6ab18758"},{"path":"product/runtime/auths-gateway/src/generation_floor.rs","sha256":"47964a5f1ca2fc9c4da0b526b6d5c5637fc0ce1d2e429219d02f1b0dc652fdff"},{"path":"product/runtime/auths-gateway/src/harness.rs","sha256":"c87e479f3eb281960f6c9c80d43c7560d7ccb654b0154ec823d3fcec4884ac05"},{"path":"product/runtime/auths-gateway/src/lib.rs","sha256":"b182052835a2cd631d1f801a74788d6ac1ef9cae21ade9ab4ffc270cd6f667ed"},{"path":"product/runtime/auths-gateway/src/listener.rs","sha256":"aa08239bcbc1fcb55e8a212fbdf6a84f12985b0d436dcb51dc58b06e59e435f2"},{"path":"product/runtime/auths-gateway/src/observed_tests.rs","sha256":"a22be071695f89ca2578a4d82fd80d9cb82289213c9bdb8f0470f6b2dc3d9201"},{"path":"product/runtime/auths-gateway/src/observer.rs","sha256":"562ffcaea071c3856e0708dc2fe33516917e145d2438aabb75af0a2b6ba01046"},{"path":"product/runtime/auths-gateway/src/onboarding.rs","sha256":"0dfd7d67e7f02f18a28d1c86ca1b7751d7463f5efcdbe3825de0ad8cbccb3891"},{"path":"product/runtime/auths-gateway/src/operator.rs","sha256":"c3c36954a3e86723df035b47f43b85fc8ab3a6292983522b6258d5c6b4e6c4e4"},{"path":"product/runtime/auths-gateway/src/pending_vectors/attempts.rs","sha256":"47ef3c8cb1c5504d47ae9a0088705ce6715fe86bac1671a34a56fb38a64d0dd3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/bounds.rs","sha256":"e612217307e1da5b0eb5ee6582a7458bb064b8aa8a529fc6555b1b334127ab68"},{"path":"product/runtime/auths-gateway/src/pending_vectors/codes.rs","sha256":"e00670a5ef24eb856cc2c6dcda8e5a263842f55c76bb939c0c27bd9df37e5522"},{"path":"product/runtime/auths-gateway/src/pending_vectors/keys.rs","sha256":"f84c56f2ea9cb34b2b79c72d13fbf2c6585010ec1ed450af58a78c80c1ea1edd"},{"path":"product/runtime/auths-gateway/src/pending_vectors/mod.rs","sha256":"5de8340f0ef71a0b57a09e323fefe473d3160c6ae952b9ba46f714825fbacafc"},{"path":"product/runtime/auths-gateway/src/pending_vectors/outcomes.rs","sha256":"8ec07b9511b48913af36ac999d2aa0e82924289f6acb23ddaeb9f00f99815166"},{"path":"product/runtime/auths-gateway/src/pending_vectors/production.rs","sha256":"c2fa18b5d96c87689fe60d95faadebe2c7fdf5b78be872ca15a67ad980106ed3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/recipes.rs","sha256":"51693208270231c25c3aef2a32151d5962114c71e86b88cb9df83181c7af83d9"},{"path":"product/runtime/auths-gateway/src/pre_entry.rs","sha256":"06ea78ca140468bfaba17d9ab04912ad68673954c3203c98fed28272ff2a00c0"},{"path":"product/runtime/auths-gateway/src/property_tests.rs","sha256":"939c081e2e154aaf10186754044bdd65608932c899b970a04a71d0afaa999a93"},{"path":"product/runtime/auths-gateway/src/qualification.rs","sha256":"a4398512ccb7bb494000fe38f03e0faa7b82d1f80ef5ee2dfa75698ae4f5a9be"},{"path":"product/runtime/auths-gateway/src/qualification_tests.rs","sha256":"4473add5729b97faf04d7be7fd8cf3bbacd7f545e1b61c7d2782563011906b4d"},{"path":"product/runtime/auths-gateway/src/quorum_tests.rs","sha256":"a78380b019104d688c11a4410082c7e08ded3106aab099954c4f8a1b4ae0fd89"},{"path":"product/runtime/auths-gateway/src/readiness.rs","sha256":"911c3f11892f94641574375e2da4c671c802738f71082f12c39832331052d43d"},{"path":"product/runtime/auths-gateway/src/recipe.rs","sha256":"fecf9af67e7afc48d080e9f8f55f8ce28e49d0e08988717a27908bbda461d6b6"},{"path":"product/runtime/auths-gateway/src/recipe/lower.rs","sha256":"8088b8751ed831dbb48247af953c6290ac95e2a438ccd5bd65eff54be06a1fd1"},{"path":"product/runtime/auths-gateway/src/recipe/review.rs","sha256":"c3eb7d9fdd98dacf52750b14b67ad7b7faaecbbdeafff1e0b049f67d0a2d0139"},{"path":"product/runtime/auths-gateway/src/recipe/runtime.rs","sha256":"c286f0d15f974402822c0810d8e97f98411dc1c557755cc23e540d85e2bb42d9"},{"path":"product/runtime/auths-gateway/src/recipe/source.rs","sha256":"1af50298fb1461e1b24cbdf560d43124d6b1c4c529586c911b1c4797214a69ff"},{"path":"product/runtime/auths-gateway/src/recipe/tests.rs","sha256":"aac551a2481bbc60864c64079bc667dcb232e45a0f41a04073ed84ab5dbe1fce"},{"path":"product/runtime/auths-gateway/src/recipe/validate.rs","sha256":"3711b17605cb7b0d639bc1b180449231f5882a306cab20e2c7782155cc63b0d4"},{"path":"product/runtime/auths-gateway/src/scenario_tests.rs","sha256":"d8271761b12597bfe1233f8eb5ad1d4e5498c5d03388e832e24ab818484a1de4"},{"path":"product/runtime/auths-gateway/src/separation.rs","sha256":"be9306848ca5d801767cf6aa14247c8618312ef0e202f00ce0c24c4844491061"},{"path":"product/runtime/auths-gateway/src/store.rs","sha256":"1e5288345c2cb1421aeda277b3158d07607404b0ec46943222ac107b63dcbb46"},{"path":"product/runtime/auths-gateway/src/store_testkit.rs","sha256":"88d82fee42f1b8ef521e8deef0216e938ebeaad822eb2f5020e70b89d145ea70"},{"path":"product/runtime/auths-gateway/src/submit.rs","sha256":"c78dbbba7c45b443febf655056c5edcd635e77be7b21c5b2c318097502415ffe"},{"path":"product/runtime/auths-gateway/src/support.rs","sha256":"8537d54b8071744a6a3983f48620a8abe1169c6103b281badd701dd0999ac9c7"},{"path":"product/runtime/auths-gateway/src/transport.rs","sha256":"be2c6dc75b8daec110bf8749fedc3823f6067d40b999aa3eb21126896a97d3ad"},{"path":"product/runtime/auths-kernel-runtime/Cargo.toml","sha256":"926bcd0053e5edd703be8f0027ad009e2982db013c8174c1366edbf38b48087d"},{"path":"product/runtime/auths-kernel-runtime/src/lib.rs","sha256":"7108faae9ca4bc32dc093ddaf885ac8f74f3c9b8d317b7c7d0ed00d1d0ab5972"},{"path":"product/runtime/auths-lifecycle/Cargo.toml","sha256":"c5053c705f8d5554b44e432fe75287a2faf11d644e5a2552e45ad6cd94176af5"},{"path":"product/runtime/auths-lifecycle/src/codec.rs","sha256":"51c4b746749150e8bfcd8ff972b3f6c1ef40bec15583448ec1b471d9ad737dc0"},{"path":"product/runtime/auths-lifecycle/src/digest.rs","sha256":"55282cd7d8aba37713c2dcb5357c9877819edb72a30eadefb860d28d7d3a3eb7"},{"path":"product/runtime/auths-lifecycle/src/identifier.rs","sha256":"31620e8c16de68d3d2d3b84d6353c1a5b9d4151d8247f91fa389b906a8e660f1"},{"path":"product/runtime/auths-lifecycle/src/kernel.rs","sha256":"2abb8c094b36d35b364e74d78091d14c5d6f3d1eb6552cca3b5538dbd017ce23"},{"path":"product/runtime/auths-lifecycle/src/lib.rs","sha256":"afe5a345cd309b5a4f08ffba3170a6d7f16ff914892b3f2006d5208ed24ec736"},{"path":"product/runtime/auths-lifecycle/src/model.rs","sha256":"1af12bbeeeaa65ec02ddcebd7d2c8c92ec1e339fa40ae85b45ab9b01a722a4fa"},{"path":"product/runtime/auths-lifecycle/src/operation.rs","sha256":"78e6d05fcf5d7ea4f148032a3fa26fdfcab77eb346019effe927b08e0d64d732"},{"path":"product/runtime/auths-lifecycle/src/registry.rs","sha256":"53495fe6f7a77422593a41623e28716f1c140dcc1e00f87f6b0ffbfb93a5ef90"},{"path":"product/runtime/auths-lifecycle/src/sealed.rs","sha256":"2e0c03b5813c926c159598bb7890d1523825edbe57cd687d42a5dfb3374a0c19"},{"path":"product/runtime/auths-lifecycle/src/test_support.rs","sha256":"221d9a5c5ef8e1f9f8fd66927484eaf813571d0568470278ecd8fa08a5eec8cd"},{"path":"product/runtime/auths-lifecycle/src/transition.rs","sha256":"011805a28efdd541f44ccea54dd0e34a1e58f4004447ee58013703b4fb6b2822"},{"path":"product/runtime/auths-runtime/Cargo.toml","sha256":"dd29d80a8b4bb56c869f036a6c9998f6e6d1c0383ac5dc03fa42b24abe2a7ff7"},{"path":"product/runtime/auths-runtime/src/lib.rs","sha256":"132ca03d58c14905d3a822a4972f42a22a5ad33a45f2ba9ca44f3a57d810b4b0"},{"path":"product/runtime/auths-runtime/src/production.rs","sha256":"fd4eff4270c571c10fcff6cf27df28961ebf074de8a1a028f500fda1ca376820"},{"path":"product/sdk/auths-approval-quorum/Cargo.toml","sha256":"df904971fca87a24194c5816738a331588fe8f164acb5d70839a35dca5f57114"},{"path":"product/sdk/auths-approval-quorum/src/lib.rs","sha256":"72e4086088a1c0912e4e1a9e980f26a5c280bf5ab16ea39c9f0f58d5096ac2ce"},{"path":"product/sdk/auths-approval-quorum/src/remote.rs","sha256":"9fa029c7c63003adf260f8aec55160c545681c60c1bace0d934e7525862aac7b"},{"path":"product/sdk/auths-approval-quorum/src/remote_tests.rs","sha256":"8a09ce17cfee82a035a74edd535f3ebeb3db0e078784740d3997b17dbdb10197"},{"path":"product/sdk/auths-approval-quorum/src/tests.rs","sha256":"0acbf12be3e497dcc6c2d8f29c9af3b1a7ed8e11b75f6399570d4f217a785060"},{"path":"product/stores/auths-stores/Cargo.toml","sha256":"a32c4b76d17b264be5d40d24497ff237e1ed87822e8bab86229b3db93106dbe3"},{"path":"product/stores/auths-stores/src/gateway_attempt.rs","sha256":"185da8f4a220fba836d5b78a9311f03204681c43a3c53951008084d135bf4d21"},{"path":"product/stores/auths-stores/src/lib.rs","sha256":"e721262edf8a9ab5568ddc27639176312d4a366203b5f73e2d7c11fde2c554e9"},{"path":"product/stores/auths-stores/src/lifecycle.rs","sha256":"94f64d25bc178a9e60ba3c0ee6915d7fb3af7c4468792d76b4e70f43f4de1e2f"}],"schema":"auths.gateway-semantic-closure/1"} \ No newline at end of file diff --git a/product/runtime/auths-gateway/src/bin/auths-gateway.rs b/product/runtime/auths-gateway/src/bin/auths-gateway.rs index f35650bf9..523bef672 100644 --- a/product/runtime/auths-gateway/src/bin/auths-gateway.rs +++ b/product/runtime/auths-gateway/src/bin/auths-gateway.rs @@ -2867,10 +2867,19 @@ mod unix { qualification_code: Option, } - #[derive(Clone, Deserialize, Serialize)] - #[serde(try_from = "String", into = "String")] + #[derive(Clone, Serialize)] + #[serde(into = "String")] struct DoctorCode(&'static str); + impl<'de> Deserialize<'de> for DoctorCode { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + Self::try_from(String::deserialize(deserializer)?).map_err(serde::de::Error::custom) + } + } + impl TryFrom for DoctorCode { type Error = &'static str; fn try_from(code: String) -> Result { diff --git a/product/runtime/auths-gateway/src/semantic_closure.rs b/product/runtime/auths-gateway/src/semantic_closure.rs index 1aafca768..4340afec1 100644 --- a/product/runtime/auths-gateway/src/semantic_closure.rs +++ b/product/runtime/auths-gateway/src/semantic_closure.rs @@ -10,7 +10,7 @@ /// SHA-256 of the schema, a NUL byte, and `semantic-closure.json`. /// Regenerate through `semantic_closure_is_current` with `AUTHS_UPDATE_FIXTURES=1`. pub const GATEWAY_SEMANTIC_CLOSURE_SHA256: &str = - "39736fd77bf533996d0e03cc3d7997469da381cebc294c0d4299dc024e8a3726"; + "a6bc2c9f24395c8eaf1ae05ec77e37926297d8c06e59cbde9ce2694e7c7eb75c"; #[cfg(test)] mod tests { diff --git a/product/runtime/auths-gateway/tests/isolated_process.rs b/product/runtime/auths-gateway/tests/isolated_process.rs index 46d40b895..325c71383 100644 --- a/product/runtime/auths-gateway/tests/isolated_process.rs +++ b/product/runtime/auths-gateway/tests/isolated_process.rs @@ -16,7 +16,10 @@ use std::{ time::{Duration, Instant}, }; -const BIN: &str = env!("CARGO_BIN_EXE_auths-gateway"); +const BIN: &str = match option_env!("AUTHS_GATEWAY_OPERATOR_TEST_BINARY") { + Some(packaged) => packaged, + None => env!("CARGO_BIN_EXE_auths-gateway"), +}; const RECIPE: &[u8] = include_bytes!("../../../../bindings/fixtures/gateway/airtable/recipe.json"); const LOCK: &[u8] = include_bytes!("../../../../bindings/fixtures/gateway/airtable/profile.lock.json"); diff --git a/product/runtime/auths-gateway/tests/operator_plane.rs b/product/runtime/auths-gateway/tests/operator_plane.rs index ab5f9106d..64bb5088a 100644 --- a/product/runtime/auths-gateway/tests/operator_plane.rs +++ b/product/runtime/auths-gateway/tests/operator_plane.rs @@ -19,7 +19,10 @@ use std::{ time::{Duration, Instant}, }; -const BIN: &str = env!("CARGO_BIN_EXE_auths-gateway"); +const BIN: &str = match option_env!("AUTHS_GATEWAY_OPERATOR_TEST_BINARY") { + Some(packaged) => packaged, + None => env!("CARGO_BIN_EXE_auths-gateway"), +}; const RECIPE: &[u8] = include_bytes!("../../../../bindings/fixtures/gateway/airtable/recipe.json"); const LOCK: &[u8] = include_bytes!("../../../../bindings/fixtures/gateway/airtable/profile.lock.json"); @@ -602,11 +605,7 @@ fn an_emergency_stop_works_with_no_running_gateway_or_readable_custody() { ); assert!(installed.status.success(), "{}", stderr(&installed)); fs::remove_file(state.join("credentials.cbor")).expect("remove custody"); - fs::write( - state.join("qualification-verifier-state.json"), - b"unavailable", - ) - .expect("bad qualification"); + fs::write(state.join("qualification-state.json"), b"unavailable").expect("bad qualification"); for (command, expected) in [ ("disable", "disabled"), ("disable", "disabled"), diff --git a/product/runtime/auths-gateway/tests/support_bundle.rs b/product/runtime/auths-gateway/tests/support_bundle.rs index 57fddd890..7da08e959 100644 --- a/product/runtime/auths-gateway/tests/support_bundle.rs +++ b/product/runtime/auths-gateway/tests/support_bundle.rs @@ -15,7 +15,10 @@ use std::{ process::{Child, Command, Output, Stdio}, }; -const BIN: &str = env!("CARGO_BIN_EXE_auths-gateway"); +const BIN: &str = match option_env!("AUTHS_GATEWAY_OPERATOR_TEST_BINARY") { + Some(packaged) => packaged, + None => env!("CARGO_BIN_EXE_auths-gateway"), +}; const RECIPE: &[u8] = include_bytes!("../../../../bindings/fixtures/gateway/airtable/recipe.json"); const LOCK: &[u8] = include_bytes!("../../../../bindings/fixtures/gateway/airtable/profile.lock.json"); diff --git a/release/semantic-freeze-versions.toml b/release/semantic-freeze-versions.toml index 6c75bdb46..c905fe950 100644 --- a/release/semantic-freeze-versions.toml +++ b/release/semantic-freeze-versions.toml @@ -1,4 +1,4 @@ -freeze_version = 362 +freeze_version = 363 # Semantic identity counters live outside the xtask source tree deliberately. # The formal source closure binds xtask's executable code, while the semantic @@ -45,7 +45,7 @@ freeze_version = 362 "auths.frozen-bytes/product/integrations/auths-stripe/fixtures/subscription-create/v1/manifest.sha256.json" = 1 "auths.frozen-bytes/product/integrations/auths-stripe/fixtures/subscription-modify/v1/manifest.sha256.json" = 1 "auths.frozen-bytes/product/integrations/auths-stripe/fixtures/v1/manifest.sha256.json" = 1 -"auths.identity.protocol" = 118 +"auths.identity.protocol" = 119 "auths.modular-components" = 20 "auths.portable-abi-bindings" = 121 "auths.product.bounded-domains" = 19 @@ -60,11 +60,11 @@ freeze_version = 362 "auths.product.mcp-closed-execution" = 31 "auths.product.mechanism-profile-conformance" = 12 "auths.product.operations" = 5 -"auths.product.public-sdk-contract" = 115 +"auths.product.public-sdk-contract" = 116 "auths.product.receipts" = 13 "auths.product.release-assurance" = 7 "auths.product.simplified-waist" = 19 -"auths.product.vocabulary" = 23 +"auths.product.vocabulary" = 24 "auths.release.benchmark-contract" = 1 "auths.release.evolution-contract" = 79 -"auths.release.public-surface" = 362 +"auths.release.public-surface" = 363 diff --git a/release/semantic-freeze.json b/release/semantic-freeze.json index e984f52f7..64b58a20c 100644 --- a/release/semantic-freeze.json +++ b/release/semantic-freeze.json @@ -1,6 +1,6 @@ { "schema": "auths.semantic-freeze/1", - "freezeVersion": 362, + "freezeVersion": 363, "publicSurface": { "rustRoots": [ "auths", @@ -550,7 +550,7 @@ }, { "id": "auths.identity.protocol", - "version": 118, + "version": 119, "classification": "frozen-meaning", "categories": [ "identity-protocol-versions", @@ -871,7 +871,7 @@ }, { "id": "auths.product.public-sdk-contract", - "version": 115, + "version": 116, "classification": "frozen-meaning", "categories": [ "rust-sdk-contract", @@ -947,7 +947,7 @@ }, { "id": "auths.product.vocabulary", - "version": 23, + "version": 24, "classification": "frozen-meaning", "categories": [ "customer-vocabulary", @@ -965,7 +965,7 @@ "product/sdk/auths-sdk/Cargo.toml", "xtask/src/sdk_vocabulary.rs" ], - "sha256": "2d81589c35f1b410a03d66d8d921bbeb3844d3af43f3e20de5fefd4d5bbfd7bb" + "sha256": "58d763d436b6b376d5b36e59a26b7dd4633c6f09950d7d85cc63c88ebd8eee2b" }, { "id": "auths.release.benchmark-contract", @@ -1011,7 +1011,7 @@ }, { "id": "auths.release.public-surface", - "version": 362, + "version": 363, "classification": "release-metadata", "categories": [ "package-names", @@ -1103,7 +1103,7 @@ "xtask/src/release_control.rs", "xtask/src/semantic_freeze.rs" ], - "sha256": "81863e20ecfc3ae2e47000dd997fdedde6df068cc51b79f799b91e710184db62" + "sha256": "ed0196ce5ce67794bdee6ae189a4a859e0d16602210d683155cc0defc19714e1" } ] } From b786d9d6cab1ccf210f172d1cd165167e0a54f04 Mon Sep 17 00:00:00 2001 From: bordumb Date: Tue, 6 Oct 2026 03:34:19 +0100 Subject: [PATCH 007/108] fix(gateway): reject arbitrary diagnostic text in support archives --- .../tools/exercise-postgres-restore.sh | 1 + .../auths-gateway/semantic-closure.json | 2 +- .../auths-gateway/src/semantic_closure.rs | 2 +- product/runtime/auths-gateway/src/support.rs | 51 +++++++++++++------ release/semantic-freeze-versions.toml | 8 +-- release/semantic-freeze.json | 10 ++-- 6 files changed, 47 insertions(+), 27 deletions(-) diff --git a/deployment/gateway/tools/exercise-postgres-restore.sh b/deployment/gateway/tools/exercise-postgres-restore.sh index 54e4943b1..c89ab6e03 100755 --- a/deployment/gateway/tools/exercise-postgres-restore.sh +++ b/deployment/gateway/tools/exercise-postgres-restore.sh @@ -56,6 +56,7 @@ for attempt in {1..60}; do if docker exec "$restore_name" psql -U auths -d auths_lifecycle -Atc 'SELECT NOT pg_is_in_recovery()' 2>/dev/null | grep -qx t; then break; fi sleep 1 done +docker exec "$restore_name" psql -U auths -d auths_lifecycle -v ON_ERROR_STOP=1 -Atc 'SELECT NOT pg_is_in_recovery()' | grep -qx t observed=$(docker exec "$restore_name" psql -U auths -d auths_lifecycle -v ON_ERROR_STOP=1 -Atc "SELECT string_agg(id::text, ', ' ORDER BY id) FROM auths_operator_restore_marker") [[ "$observed" == '1, 2' ]] printf '%s\n' '{"schema":"auths.gateway-restore-exercise/1","backup":"physical-with-wal","target":"named-restore-point","before_target_retained":true,"after_target_excluded":true,"replay_continuity_claim":false}' diff --git a/product/runtime/auths-gateway/semantic-closure.json b/product/runtime/auths-gateway/semantic-closure.json index e22adc5b7..112722939 100644 --- a/product/runtime/auths-gateway/semantic-closure.json +++ b/product/runtime/auths-gateway/semantic-closure.json @@ -1 +1 @@ -{"files":[{"path":"Cargo.lock","sha256":"c94ed342774d5e2823f01ecf74b8a4812c5f9a6b0cf811d31f2e2cecb671a275"},{"path":"Cargo.toml","sha256":"6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24"},{"path":"core/adapters/auths-did-keri/Cargo.toml","sha256":"86ba3e3f9a0a70d970568bfb3113b7ba7bbdd81c3eebbb52743dd574a0c0ecaa"},{"path":"core/adapters/auths-did-keri/src/lib.rs","sha256":"a75674842f8a7142004369ccd206ab43e476459293f0ff4bed4d4e659031b3e3"},{"path":"core/adapters/auths-did-key/Cargo.toml","sha256":"d5a3ae07ecde83f91eed4c3785051dd0f44eab6c891754f3309b6b40596707d7"},{"path":"core/adapters/auths-did-key/src/lib.rs","sha256":"b76a3f4528a725df53cfa9242e6e414e1d26caa48468aaed497e28b121f4497c"},{"path":"core/adapters/auths-raw-key/Cargo.toml","sha256":"f49616bc18c19e6aaa7e6a02ccebcdb9f5c1422c1278ef9869e0dbf22ceda7be"},{"path":"core/adapters/auths-raw-key/src/lib.rs","sha256":"45eec1b295dac3bed65cd79c942870b926b06b3f5d38eaebaeb6140ac69315fa"},{"path":"core/crates/auths-algebra-kernel/Cargo.toml","sha256":"0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba"},{"path":"core/crates/auths-algebra-kernel/src/generated.rs","sha256":"ae4bcbef42a408c7ffa0c6a74a42f7de177a6f14479e51d205acf830bda05960"},{"path":"core/crates/auths-algebra-kernel/src/lib.rs","sha256":"6654667eeb9b353d6648954c9fd2e8838462a82ce6b2803eb49e1366892c68c6"},{"path":"core/crates/auths-assurance/Cargo.toml","sha256":"afcb12a97ddd09d7a264b9ecd3fcaefc865ff2c9b4539ee85b00883420ba333a"},{"path":"core/crates/auths-assurance/src/lib.rs","sha256":"0fb2ec844d674b25a9e20b1601452c89c2454901fa506adfa9bb38ef9a7fa213"},{"path":"core/crates/auths-author/Cargo.toml","sha256":"1e6f0e3bc079ddb558decf0db26b291c6e72fc47327b6df1b7650d41689b215f"},{"path":"core/crates/auths-author/src/lib.rs","sha256":"e14475f2f49715a1869d5fa6b11ff1fbb72497e39097e09f833b0bae7e5b3f2b"},{"path":"core/crates/auths-author/src/observations.rs","sha256":"dda7d6bfa6f4bd7e95a480ca283c2c0e996f69c5c15cb0c7197af328131a7066"},{"path":"core/crates/auths-authority/Cargo.toml","sha256":"4f68212938029f79ebd857b4f3038494eb85d0163d49f07e51376715cf959815"},{"path":"core/crates/auths-authority/src/lib.rs","sha256":"da88d5194de4e17449e69972c0fb042afa3c39798a8f570f30771e77c384f1eb"},{"path":"core/crates/auths-codec/Cargo.toml","sha256":"e20e51826e17814effd9d8925d18d5fbdd6c0d37bf50231e743ec2611314722c"},{"path":"core/crates/auths-codec/src/approval.rs","sha256":"fbff43bf4d57f69f8b7738a8647751cde75c5a932dee65d924a1fe9c7202f91f"},{"path":"core/crates/auths-codec/src/bounded_policy.rs","sha256":"d21f6728be2d8a04b6d94921f2b683f7e61cbb42e0ac6866f1c88a49caa534c3"},{"path":"core/crates/auths-codec/src/decode.rs","sha256":"ba2999584cdf53b1b517ecb9c7ea50d39efee17c666a9a38e2ad1ac94379f778"},{"path":"core/crates/auths-codec/src/encode.rs","sha256":"8491192053e2e15d62b4d2a491de22405b7487ead69ab6f6bca40669ce7ca5f7"},{"path":"core/crates/auths-codec/src/error.rs","sha256":"fecb0737c16deb42d859f1dc7727c698438d9ac12064fd99e0024629642c390c"},{"path":"core/crates/auths-codec/src/hash.rs","sha256":"f88e111f1dbb2cef6b7b5e9c948cb45ff92e366710c8a5f5c636138aa748479e"},{"path":"core/crates/auths-codec/src/lib.rs","sha256":"3b0e5c94c6f34f750b88a9333e1d5c8145746d845d3a23e0d2f61807cf592ea7"},{"path":"core/crates/auths-codec/src/observation.rs","sha256":"38328b0c71ff97a4196eeade8b4faa889527ff1f80bb168468bcd49082a3987e"},{"path":"core/crates/auths-composition/Cargo.toml","sha256":"331e13025eb82588b5269ed3975929eb41c823d588c49e4c296273d85c6fe80e"},{"path":"core/crates/auths-composition/src/lib.rs","sha256":"e42e3b0b6a9985b73c533aeb23799c638979aa27a9ce7d0f10a8d60340570fb1"},{"path":"core/crates/auths-model/Cargo.toml","sha256":"565c15302b0cc9270db1e28efa3862804846850ba933cc17aea8abcec4a65987"},{"path":"core/crates/auths-model/src/approval.rs","sha256":"54cf44a9ef747ec21546a4086aecfb130bc7803b0d646430e6082df51e6e305f"},{"path":"core/crates/auths-model/src/bounded.rs","sha256":"f90496abc0a06c028b4d850af6ddab7d850bfafeaa3d042f1b1246a41d8bbbc9"},{"path":"core/crates/auths-model/src/bounded_policy.rs","sha256":"306a8f049cc7cfc7635fe0e4de47eb7813eed63d3c14c3be2b51586aa4eea450"},{"path":"core/crates/auths-model/src/lib.rs","sha256":"e7cfe6bb9574c6b016aa63e70658c31e0b90903ec6479a49f4a2ceb64f5bad97"},{"path":"core/crates/auths-model/src/observation.rs","sha256":"b3ed3e3cc090afca2896a7d3de7988afccc1ee1ea0ebd91b51a8bc0f20ad8dbb"},{"path":"core/crates/auths-multikey/Cargo.toml","sha256":"858756c1197befcada06134742bffe8d58cf674cadd6c046bf710570e96efaf2"},{"path":"core/crates/auths-multikey/src/lib.rs","sha256":"f5177fffb11e40eeaaa665ba886c541fc1f24d5eacdd6983fb03dc20148733f0"},{"path":"core/crates/auths-ports/Cargo.toml","sha256":"596a9b0f5af3717c16a6d13f7054d8a106bcd9f01f5f72c2235dd2afcf0ab16c"},{"path":"core/crates/auths-ports/src/binding.rs","sha256":"a16c012d40aa4249e3ec54372b9611006d0bfe8c7dc3c741911c2194ad17736d"},{"path":"core/crates/auths-ports/src/diagnostics.rs","sha256":"aa596572503b5a65a918bb2ff38281c144ff53821ee914e9325c852828d852df"},{"path":"core/crates/auths-ports/src/lib.rs","sha256":"8da1debf86f9532df0660155d04298beb1ba3a1204508f8586e2e67cd2fb3449"},{"path":"core/crates/auths-ports/src/path.rs","sha256":"b68fc547b4e4d97a60cbbc1cc1939fc6b34a8233b81f840bd396914a707e3ea1"},{"path":"core/crates/auths-raw-key-core/Cargo.toml","sha256":"98c0bc8527a537512e43a74dd6ba9658c6f0cdc16610cf938e3f9b43785d836d"},{"path":"core/crates/auths-raw-key-core/src/lib.rs","sha256":"98c0500c41697aae28708ad0bf970b9a97583d96a3d2c18d23e7fa351e0f7d12"},{"path":"core/crates/auths-registries/Cargo.toml","sha256":"590e49e58b0622d9d6274fea46796dcdb07dec9550eff295cce6a6427ffa51e2"},{"path":"core/crates/auths-registries/src/lib.rs","sha256":"450d3886d85ee333b7e046317fb5b47cde62483d5f3e41d46265e2caf4c373ec"},{"path":"core/crates/auths-registries/src/template.rs","sha256":"1224039dd2b3ce6fa8357613d8cafbae40400493da7176da202b9ade62fa05e4"},{"path":"core/crates/auths-signature-core/Cargo.toml","sha256":"6bee2230eb30af1be0bd5c2d57bd3e1903497a70028d47290d4ac6e9e0e8bca0"},{"path":"core/crates/auths-signature-core/src/lib.rs","sha256":"6e3f9311ded5e49ea50d445eb21e6d8fa12442aa4362a73e0cb6fda15b7cd865"},{"path":"core/crates/auths-signature/Cargo.toml","sha256":"7f7b5682466ba439d8c59579022cb61068cad9fb4bd2d73e1cc21327c902b450"},{"path":"core/crates/auths-signature/src/lib.rs","sha256":"b3d9ac4cc3ba0797b9e1c09f2d6ac05089b25dac4e285a5af28c0165b33d925b"},{"path":"core/crates/auths-verifier/Cargo.toml","sha256":"c43358e06a33324b41a8b93e5cc7279c55f7d21f1f6cfaa539a3fc7b4c27a38f"},{"path":"core/crates/auths-verifier/src/approval.rs","sha256":"c3cae6a49e169051eb555bb092b1069a4d422516d6a2114623a89e5f31ff923f"},{"path":"core/crates/auths-verifier/src/causal.rs","sha256":"9635230f33b13a263573d319ac8a1976addbcc07677514a43e3c7bf28dc04587"},{"path":"core/crates/auths-verifier/src/lib.rs","sha256":"f22dec38dfa47ced8da4f605390da8453273bee1da010f57fd1fdfcb10e0b389"},{"path":"core/crates/auths-verifier/src/observation.rs","sha256":"0bb07f06a0f9524c88427df1c972b1de8ba038a9eeeb15d3134c25125ae84b1e"},{"path":"core/crates/auths-verifier/src/trace.rs","sha256":"2213d72023a1d9e0413a2cf2c51c3dad9e04775d86033a0caaa9d29a8f0036f8"},{"path":"exchange/crates/auths-proof-exchange-model/Cargo.toml","sha256":"34b2db64f93a288e942b5a3918d28cdcbef906e0dc9074ce848018d3d5f7a1fa"},{"path":"exchange/crates/auths-proof-exchange-model/src/lib.rs","sha256":"49fac5aff2339d3a57c41cb8bb2a82852538e8f77ecc4b157c88e264ff31fb55"},{"path":"exchange/crates/auths-proof-exchange-port/Cargo.toml","sha256":"7ff660f1b7579dc570c791090aeb450404fbbf44c92781e289f5ccdde746d739"},{"path":"exchange/crates/auths-proof-exchange-port/src/lib.rs","sha256":"b408fb40c6432edc1facb3d8b3e9433a033f8dc73fe2e0ba5a88c972ca675021"},{"path":"product/config/auths-config/Cargo.toml","sha256":"e4b568ab9f6d84f7d7e6d66443fe825f360db9c27bc7c31d6ddc0647ba3ab304"},{"path":"product/config/auths-config/src/lib.rs","sha256":"fecf00ea65cef9018fda9af2063326d7065b869266d0d9e73a4f06816f1102cc"},{"path":"product/errors/auths-errors/Cargo.toml","sha256":"3b3a199b6460ba75bda84475bb5accd35e1485448a3981038db85bf4772dd350"},{"path":"product/errors/auths-errors/src/lib.rs","sha256":"7feeb9069fa4003f94f1f07c1c94619cf1c883e0dbaaf2187f04d0f742264bdd"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/Cargo.toml","sha256":"716f1f2a117d6d69d8effe9ee9057e24ba3502f20af6a602b06facb638cdabed"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/api.rs","sha256":"b3c4321e0737835ecc4f17235d7589b7f3d62180954ebb98ea9449252300245a"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/clock.rs","sha256":"73f0a6e0f5903883329fa6683f5888288f759512ac69e5c87efd2b6b87f7d79f"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/http.rs","sha256":"14c1fce14e24c984b2a275563a29b6326fb08367922b6e8d37ba38b9cb81aa2b"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/identity.rs","sha256":"186de11230c8b33375951c4368609f8976bf9795f171af3fd7fac26207a94361"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs","sha256":"881ad9ccca369b6eaa6bfd9ec03b1585bff07b042da38942ef57154839449d3e"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/names.rs","sha256":"41bb23572d6002e23ee103d6fe70ecd68764861c6f2e48a1c53af998270a4afa"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs","sha256":"39fed883f4802e68d3b41a68fea0aba0737810996b33d13577de70faba004c29"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/store.rs","sha256":"fc60ee9c49b2f4f063c449b4c78100c5c4872779e94ca168f796603b380ef6e4"},{"path":"product/integrations/auths-custody/Cargo.toml","sha256":"1e14034185ad1ec24a977fd5f41d0abee219606245c046ce2a82287fadef448b"},{"path":"product/integrations/auths-custody/src/conformance.rs","sha256":"8ed1afd58f18fc6becc268908aa6419c9aa404c79da0197963eb2599df44acf6"},{"path":"product/integrations/auths-custody/src/key.rs","sha256":"70cbb0fd21b6f5652157845a22c35be2d0f6c05b3d138fc4b9bb6dbdc3d81c40"},{"path":"product/integrations/auths-custody/src/lib.rs","sha256":"8ee593c1f59b0fd2126bdda9138026f5bc531beb64d4489a99785842e7b98b43"},{"path":"product/operations/auths-operations/Cargo.toml","sha256":"73dde1e914ba5e1386f8d49c0d730423cc72ae77ec44c6554a6a75cc8e8922b1"},{"path":"product/operations/auths-operations/src/explanation.rs","sha256":"b4a39bcbd5712cb9e735ee7deeb281f3fa6af5ddca973735bf3d87dce427ef11"},{"path":"product/operations/auths-operations/src/lib.rs","sha256":"3f401a56555113b98f57bca172a2660eaecedf76247b83a3fdbb089c133a29cd"},{"path":"product/operations/auths-operations/src/render/json.rs","sha256":"2ae042639960afee123730e945d373bc5dda1d2b3af20ae16c939a7e99b9e418"},{"path":"product/operations/auths-operations/src/render/mod.rs","sha256":"b3b7f6fe473f49227ace5a68bfc3d8dc14b5db8dd9888fd9e207070337b1b8bf"},{"path":"product/operations/auths-operations/src/render/text.rs","sha256":"f216cf3bdb00e264523271b16e7059535ac6b1aabf271cebd7935af155e4bfec"},{"path":"product/policy/auths-bounded-policy/Cargo.toml","sha256":"babd5d200923137ead71d8c2528f847cea323ce98da942a1320b054436612c47"},{"path":"product/policy/auths-bounded-policy/src/arithmetic.rs","sha256":"75e43c5d4eab8d1f71c1daf53839f5f9fe45a400afc1f63a30c6f55ce3632627"},{"path":"product/policy/auths-bounded-policy/src/commitment.rs","sha256":"c5706f2d583454e1a7f570f7ada138d4d864bef0205dfae7c1296774f396bb3f"},{"path":"product/policy/auths-bounded-policy/src/eligibility.rs","sha256":"c9acdfb793074e687fc36efad506be27dbd99ffbf40387bc66c8de39ef238432"},{"path":"product/policy/auths-bounded-policy/src/identifier.rs","sha256":"0006a32bae9eb16c4178cf797df418d2b0a781f2bc6474b741dc1a908141831c"},{"path":"product/policy/auths-bounded-policy/src/kernel.rs","sha256":"99187c28b161ac70bee1afed60711f7f645adb4d1671a01863f9849b369811d5"},{"path":"product/policy/auths-bounded-policy/src/lib.rs","sha256":"76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c"},{"path":"product/policy/auths-bounded-policy/src/receipt.rs","sha256":"3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad"},{"path":"product/policy/auths-bounded-policy/src/registry.rs","sha256":"4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0"},{"path":"product/profiles/auths-profile-api/Cargo.toml","sha256":"7ae85761f58625b5d678f961fd052eebf3e000ef565c7312e3ac857763c0017f"},{"path":"product/profiles/auths-profile-api/src/lib.rs","sha256":"a194b82b20bf8aa864c2334ef6c6aec30b2154ded972862252d5dcefa488ab95"},{"path":"product/profiles/auths-profile-mcp/Cargo.toml","sha256":"db264fc25242f7b7e4133cbe5782545b3107b406c87168ae072683cfb59eac66"},{"path":"product/profiles/auths-profile-mcp/src/arguments.rs","sha256":"a5de696586d507e2aee4a49fee99ef1ef4c51a2e46603f8838f1af6d9009833f"},{"path":"product/profiles/auths-profile-mcp/src/lib.rs","sha256":"d0f8b733a09ef8408336cdebc8948d6a5861012ce6878598b11be7084dfd4280"},{"path":"product/profiles/auths-profile-mcp/src/session.rs","sha256":"166c281fa66333388e4760d6098dad02d3359e1d5de4b8f93312c014f97abb03"},{"path":"product/qualification/auths-recipe-qualification/Cargo.toml","sha256":"b7b15b30b9a3d96d4f089d514266d3a892de6608d30707aa44be31cca89ca9fe"},{"path":"product/qualification/auths-recipe-qualification/src/canonical.rs","sha256":"30a9b50777f0dcb4b606abfee2467d5a975d9f6ad941ab6c13ca3df5b359f667"},{"path":"product/qualification/auths-recipe-qualification/src/closure.rs","sha256":"0ad6aee9bd981e2863fa725f209ec84031db2ff12f4c7ac3aaf5120f0bb86039"},{"path":"product/qualification/auths-recipe-qualification/src/error.rs","sha256":"52d5cf720a1e4579008fdda90a3ac2c31f0b8db57985f121f65e54b4da2b7dd1"},{"path":"product/qualification/auths-recipe-qualification/src/evidence.rs","sha256":"1a4cb862f725b02f9efd827db99637ea8178a5236aa020ec271a363edbe7b362"},{"path":"product/qualification/auths-recipe-qualification/src/ids.rs","sha256":"e81a906d571497ab2da753e1532d4443706410e0b75fdd59a7d2d788c7aec403"},{"path":"product/qualification/auths-recipe-qualification/src/lib.rs","sha256":"195b19f46e1e94a0f3594ad5958e5715bc5e3ad415bdfe6428dfc1b6dd3f4631"},{"path":"product/qualification/auths-recipe-qualification/src/model.rs","sha256":"3484eb0ec287b23d4682ade7b1b0f8d1335985b3fb180f06fc28716076957d5f"},{"path":"product/qualification/auths-recipe-qualification/src/release.rs","sha256":"d816b53e2275e902c750ad03803061844e259e28560ab2d1c77e8a43981a4d6a"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/mod.rs","sha256":"7f15b68e05a04f202bcb1fb80de1d9a9a4fda8bfd6af2cd4e5c660fc75d96fe5"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/schemas.rs","sha256":"c59feec2805621f341a90f81fc005e2c12f7a70f9d264fdeacccb2be4fe1c046"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/verification.rs","sha256":"6a6b5834c5dae10af1ba8939b2deae43b85db71544dc8f077ff63b7fe68ac8a8"},{"path":"product/qualification/auths-recipe-qualification/src/verify.rs","sha256":"edd33589c54fb79bcfccc4cf4e6ccf95bbca088318bb7f8dfc27da684b4fa671"},{"path":"product/receipts/auths-receipts/Cargo.toml","sha256":"6001fa1375899953aafcb07c23a6da0c8f57ea7ec08bb9c950b12a60a8cc6f0f"},{"path":"product/receipts/auths-receipts/src/disclosure.rs","sha256":"ba9ed439be0a320c8a01f5b6e9b51361c1a37e076947490d8e4a484ba6bb119c"},{"path":"product/receipts/auths-receipts/src/lib.rs","sha256":"547a57c4160256719cafb7d0ab972d9fc80b0da14fbbce4148c70c414070ff36"},{"path":"product/runtime/auths-connections/Cargo.toml","sha256":"babeb6e1dda3dfb66291713ce1e43dce5c349833d0b50ea4dccbf986030026b2"},{"path":"product/runtime/auths-connections/src/credential.rs","sha256":"82921413bb053f0f6c7931fbd4e6a86c8cc1d8c6b51debd9c2cef33a8d5b1c51"},{"path":"product/runtime/auths-connections/src/kernel.rs","sha256":"a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8"},{"path":"product/runtime/auths-connections/src/lib.rs","sha256":"79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22"},{"path":"product/runtime/auths-connections/src/model.rs","sha256":"de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77"},{"path":"product/runtime/auths-connections/src/registry.rs","sha256":"e57640e003e72ad3235c567c2bb944a262bd64e673f023b62ea091094cc7e946"},{"path":"product/runtime/auths-gateway-kernel/Cargo.toml","sha256":"34f864e67656af4ac7e5c7a347a23f01fc8ab31365b8e23c0ef474483b14a183"},{"path":"product/runtime/auths-gateway-kernel/src/construct.rs","sha256":"e9d65744bae273d65face4285e5d2da75c06a92ab48f7b8333d496604e31c63c"},{"path":"product/runtime/auths-gateway-kernel/src/lib.rs","sha256":"cfda6f8453426564c085475f183b6f790b438768a19668f1b65d33ba59dc8632"},{"path":"product/runtime/auths-gateway-kernel/src/order.rs","sha256":"e0045f877c4b7fe3860c291039853885064ddcdebba7c9b345ab65e81e646dda"},{"path":"product/runtime/auths-gateway-kernel/src/outcome.rs","sha256":"e9785b1afe70788c89b51b18655bcd5acff7b0c8e3d12fb79c6f05a202e67e6b"},{"path":"product/runtime/auths-gateway-kernel/src/ratio.rs","sha256":"7ace22264812e6fc1ef3a62afee402cf43494bb71ae0d3de219ad1b39d690bcb"},{"path":"product/runtime/auths-gateway-kernel/src/recovery.rs","sha256":"9f46dcd1685ab6e4d1ba04a3fc286a9f3afee8fb47829be1fbc670a7926a2dc6"},{"path":"product/runtime/auths-gateway-kernel/src/transition.rs","sha256":"cefb8f01d915880f6921f2501ff881ad94b9de61072c34d9cd19220992f97374"},{"path":"product/runtime/auths-gateway/Cargo.toml","sha256":"00b28be86921dcdc0ad90cce0c62c2961cafefe96ea6c2edf0e926c3d405ccad"},{"path":"product/runtime/auths-gateway/src/admin.rs","sha256":"2d5cc67afac42fbd15f36e2d1693cd1b20cedacf775040dce6ffe04ccc94c9ea"},{"path":"product/runtime/auths-gateway/src/app.rs","sha256":"6f80f63833ea0815bb44fbf3b0cc54624a08e9fb578b035819f2980dc04e8256"},{"path":"product/runtime/auths-gateway/src/audit.rs","sha256":"0edb2037eb7b5d6f13acfce85c54f62a82bf7fdd31bc7e626c4fec183cef61dd"},{"path":"product/runtime/auths-gateway/src/audit_tests.rs","sha256":"990969384a52d75bc2489d9d412a9e7dd814bca1c8f65c701d6205fae62a15d5"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway-harness.rs","sha256":"12b0c24d36b2e6a3be392d3c081a783b355fdd67dc5b54bacc0410e803116b8c"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway.rs","sha256":"9f4b46006fbc28a71c07f14f1f40837782407628c094d7c17f216f9be75e2dde"},{"path":"product/runtime/auths-gateway/src/binding.rs","sha256":"663b0ce878319511aa7d05722ab4ab2fa9be18817884ffb2ee9f131ff1e382d1"},{"path":"product/runtime/auths-gateway/src/bounds.rs","sha256":"9cfa0eae4973e5e047a198360b22f041708fa20276b0b90c2ec440f06915d64b"},{"path":"product/runtime/auths-gateway/src/bounds_aggregate_tests.rs","sha256":"ab34f227b7c8692ba1da88ccb32bb3687a66adf8353d8282fae905d4a88eb612"},{"path":"product/runtime/auths-gateway/src/bounds_tests.rs","sha256":"74136bc570da7b9338b5a1a1ed9d3fd892c55135160964f9d3ac0e2cf5741375"},{"path":"product/runtime/auths-gateway/src/connection.rs","sha256":"7b5d049c258a26ed1c93ecf860f51d051a8a65f9b93554af0b1ea93862398ec9"},{"path":"product/runtime/auths-gateway/src/credential_journal.rs","sha256":"8e2b0733038d93ca5df770d27a870237e3b65664fa48da017d964a65bbbe25b8"},{"path":"product/runtime/auths-gateway/src/echo_verify.rs","sha256":"6d453051665f823abd7354d5c50031d9524cf47d6092d2f09080ae814e3b9575"},{"path":"product/runtime/auths-gateway/src/engine.rs","sha256":"a9f71575994ff21633ddfc533b1d810515db71aa0146fa8869dad72eddcb2a12"},{"path":"product/runtime/auths-gateway/src/fuzzing.rs","sha256":"ed3b0028487eb546a3b0a91d115aa8f18bcea324b61620bfe8e35a9e6ab18758"},{"path":"product/runtime/auths-gateway/src/generation_floor.rs","sha256":"47964a5f1ca2fc9c4da0b526b6d5c5637fc0ce1d2e429219d02f1b0dc652fdff"},{"path":"product/runtime/auths-gateway/src/harness.rs","sha256":"c87e479f3eb281960f6c9c80d43c7560d7ccb654b0154ec823d3fcec4884ac05"},{"path":"product/runtime/auths-gateway/src/lib.rs","sha256":"b182052835a2cd631d1f801a74788d6ac1ef9cae21ade9ab4ffc270cd6f667ed"},{"path":"product/runtime/auths-gateway/src/listener.rs","sha256":"aa08239bcbc1fcb55e8a212fbdf6a84f12985b0d436dcb51dc58b06e59e435f2"},{"path":"product/runtime/auths-gateway/src/observed_tests.rs","sha256":"a22be071695f89ca2578a4d82fd80d9cb82289213c9bdb8f0470f6b2dc3d9201"},{"path":"product/runtime/auths-gateway/src/observer.rs","sha256":"562ffcaea071c3856e0708dc2fe33516917e145d2438aabb75af0a2b6ba01046"},{"path":"product/runtime/auths-gateway/src/onboarding.rs","sha256":"0dfd7d67e7f02f18a28d1c86ca1b7751d7463f5efcdbe3825de0ad8cbccb3891"},{"path":"product/runtime/auths-gateway/src/operator.rs","sha256":"c3c36954a3e86723df035b47f43b85fc8ab3a6292983522b6258d5c6b4e6c4e4"},{"path":"product/runtime/auths-gateway/src/pending_vectors/attempts.rs","sha256":"47ef3c8cb1c5504d47ae9a0088705ce6715fe86bac1671a34a56fb38a64d0dd3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/bounds.rs","sha256":"e612217307e1da5b0eb5ee6582a7458bb064b8aa8a529fc6555b1b334127ab68"},{"path":"product/runtime/auths-gateway/src/pending_vectors/codes.rs","sha256":"e00670a5ef24eb856cc2c6dcda8e5a263842f55c76bb939c0c27bd9df37e5522"},{"path":"product/runtime/auths-gateway/src/pending_vectors/keys.rs","sha256":"f84c56f2ea9cb34b2b79c72d13fbf2c6585010ec1ed450af58a78c80c1ea1edd"},{"path":"product/runtime/auths-gateway/src/pending_vectors/mod.rs","sha256":"5de8340f0ef71a0b57a09e323fefe473d3160c6ae952b9ba46f714825fbacafc"},{"path":"product/runtime/auths-gateway/src/pending_vectors/outcomes.rs","sha256":"8ec07b9511b48913af36ac999d2aa0e82924289f6acb23ddaeb9f00f99815166"},{"path":"product/runtime/auths-gateway/src/pending_vectors/production.rs","sha256":"c2fa18b5d96c87689fe60d95faadebe2c7fdf5b78be872ca15a67ad980106ed3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/recipes.rs","sha256":"51693208270231c25c3aef2a32151d5962114c71e86b88cb9df83181c7af83d9"},{"path":"product/runtime/auths-gateway/src/pre_entry.rs","sha256":"06ea78ca140468bfaba17d9ab04912ad68673954c3203c98fed28272ff2a00c0"},{"path":"product/runtime/auths-gateway/src/property_tests.rs","sha256":"939c081e2e154aaf10186754044bdd65608932c899b970a04a71d0afaa999a93"},{"path":"product/runtime/auths-gateway/src/qualification.rs","sha256":"a4398512ccb7bb494000fe38f03e0faa7b82d1f80ef5ee2dfa75698ae4f5a9be"},{"path":"product/runtime/auths-gateway/src/qualification_tests.rs","sha256":"4473add5729b97faf04d7be7fd8cf3bbacd7f545e1b61c7d2782563011906b4d"},{"path":"product/runtime/auths-gateway/src/quorum_tests.rs","sha256":"a78380b019104d688c11a4410082c7e08ded3106aab099954c4f8a1b4ae0fd89"},{"path":"product/runtime/auths-gateway/src/readiness.rs","sha256":"911c3f11892f94641574375e2da4c671c802738f71082f12c39832331052d43d"},{"path":"product/runtime/auths-gateway/src/recipe.rs","sha256":"fecf9af67e7afc48d080e9f8f55f8ce28e49d0e08988717a27908bbda461d6b6"},{"path":"product/runtime/auths-gateway/src/recipe/lower.rs","sha256":"8088b8751ed831dbb48247af953c6290ac95e2a438ccd5bd65eff54be06a1fd1"},{"path":"product/runtime/auths-gateway/src/recipe/review.rs","sha256":"c3eb7d9fdd98dacf52750b14b67ad7b7faaecbbdeafff1e0b049f67d0a2d0139"},{"path":"product/runtime/auths-gateway/src/recipe/runtime.rs","sha256":"c286f0d15f974402822c0810d8e97f98411dc1c557755cc23e540d85e2bb42d9"},{"path":"product/runtime/auths-gateway/src/recipe/source.rs","sha256":"1af50298fb1461e1b24cbdf560d43124d6b1c4c529586c911b1c4797214a69ff"},{"path":"product/runtime/auths-gateway/src/recipe/tests.rs","sha256":"aac551a2481bbc60864c64079bc667dcb232e45a0f41a04073ed84ab5dbe1fce"},{"path":"product/runtime/auths-gateway/src/recipe/validate.rs","sha256":"3711b17605cb7b0d639bc1b180449231f5882a306cab20e2c7782155cc63b0d4"},{"path":"product/runtime/auths-gateway/src/scenario_tests.rs","sha256":"d8271761b12597bfe1233f8eb5ad1d4e5498c5d03388e832e24ab818484a1de4"},{"path":"product/runtime/auths-gateway/src/separation.rs","sha256":"be9306848ca5d801767cf6aa14247c8618312ef0e202f00ce0c24c4844491061"},{"path":"product/runtime/auths-gateway/src/store.rs","sha256":"1e5288345c2cb1421aeda277b3158d07607404b0ec46943222ac107b63dcbb46"},{"path":"product/runtime/auths-gateway/src/store_testkit.rs","sha256":"88d82fee42f1b8ef521e8deef0216e938ebeaad822eb2f5020e70b89d145ea70"},{"path":"product/runtime/auths-gateway/src/submit.rs","sha256":"c78dbbba7c45b443febf655056c5edcd635e77be7b21c5b2c318097502415ffe"},{"path":"product/runtime/auths-gateway/src/support.rs","sha256":"8537d54b8071744a6a3983f48620a8abe1169c6103b281badd701dd0999ac9c7"},{"path":"product/runtime/auths-gateway/src/transport.rs","sha256":"be2c6dc75b8daec110bf8749fedc3823f6067d40b999aa3eb21126896a97d3ad"},{"path":"product/runtime/auths-kernel-runtime/Cargo.toml","sha256":"926bcd0053e5edd703be8f0027ad009e2982db013c8174c1366edbf38b48087d"},{"path":"product/runtime/auths-kernel-runtime/src/lib.rs","sha256":"7108faae9ca4bc32dc093ddaf885ac8f74f3c9b8d317b7c7d0ed00d1d0ab5972"},{"path":"product/runtime/auths-lifecycle/Cargo.toml","sha256":"c5053c705f8d5554b44e432fe75287a2faf11d644e5a2552e45ad6cd94176af5"},{"path":"product/runtime/auths-lifecycle/src/codec.rs","sha256":"51c4b746749150e8bfcd8ff972b3f6c1ef40bec15583448ec1b471d9ad737dc0"},{"path":"product/runtime/auths-lifecycle/src/digest.rs","sha256":"55282cd7d8aba37713c2dcb5357c9877819edb72a30eadefb860d28d7d3a3eb7"},{"path":"product/runtime/auths-lifecycle/src/identifier.rs","sha256":"31620e8c16de68d3d2d3b84d6353c1a5b9d4151d8247f91fa389b906a8e660f1"},{"path":"product/runtime/auths-lifecycle/src/kernel.rs","sha256":"2abb8c094b36d35b364e74d78091d14c5d6f3d1eb6552cca3b5538dbd017ce23"},{"path":"product/runtime/auths-lifecycle/src/lib.rs","sha256":"afe5a345cd309b5a4f08ffba3170a6d7f16ff914892b3f2006d5208ed24ec736"},{"path":"product/runtime/auths-lifecycle/src/model.rs","sha256":"1af12bbeeeaa65ec02ddcebd7d2c8c92ec1e339fa40ae85b45ab9b01a722a4fa"},{"path":"product/runtime/auths-lifecycle/src/operation.rs","sha256":"78e6d05fcf5d7ea4f148032a3fa26fdfcab77eb346019effe927b08e0d64d732"},{"path":"product/runtime/auths-lifecycle/src/registry.rs","sha256":"53495fe6f7a77422593a41623e28716f1c140dcc1e00f87f6b0ffbfb93a5ef90"},{"path":"product/runtime/auths-lifecycle/src/sealed.rs","sha256":"2e0c03b5813c926c159598bb7890d1523825edbe57cd687d42a5dfb3374a0c19"},{"path":"product/runtime/auths-lifecycle/src/test_support.rs","sha256":"221d9a5c5ef8e1f9f8fd66927484eaf813571d0568470278ecd8fa08a5eec8cd"},{"path":"product/runtime/auths-lifecycle/src/transition.rs","sha256":"011805a28efdd541f44ccea54dd0e34a1e58f4004447ee58013703b4fb6b2822"},{"path":"product/runtime/auths-runtime/Cargo.toml","sha256":"dd29d80a8b4bb56c869f036a6c9998f6e6d1c0383ac5dc03fa42b24abe2a7ff7"},{"path":"product/runtime/auths-runtime/src/lib.rs","sha256":"132ca03d58c14905d3a822a4972f42a22a5ad33a45f2ba9ca44f3a57d810b4b0"},{"path":"product/runtime/auths-runtime/src/production.rs","sha256":"fd4eff4270c571c10fcff6cf27df28961ebf074de8a1a028f500fda1ca376820"},{"path":"product/sdk/auths-approval-quorum/Cargo.toml","sha256":"df904971fca87a24194c5816738a331588fe8f164acb5d70839a35dca5f57114"},{"path":"product/sdk/auths-approval-quorum/src/lib.rs","sha256":"72e4086088a1c0912e4e1a9e980f26a5c280bf5ab16ea39c9f0f58d5096ac2ce"},{"path":"product/sdk/auths-approval-quorum/src/remote.rs","sha256":"9fa029c7c63003adf260f8aec55160c545681c60c1bace0d934e7525862aac7b"},{"path":"product/sdk/auths-approval-quorum/src/remote_tests.rs","sha256":"8a09ce17cfee82a035a74edd535f3ebeb3db0e078784740d3997b17dbdb10197"},{"path":"product/sdk/auths-approval-quorum/src/tests.rs","sha256":"0acbf12be3e497dcc6c2d8f29c9af3b1a7ed8e11b75f6399570d4f217a785060"},{"path":"product/stores/auths-stores/Cargo.toml","sha256":"a32c4b76d17b264be5d40d24497ff237e1ed87822e8bab86229b3db93106dbe3"},{"path":"product/stores/auths-stores/src/gateway_attempt.rs","sha256":"185da8f4a220fba836d5b78a9311f03204681c43a3c53951008084d135bf4d21"},{"path":"product/stores/auths-stores/src/lib.rs","sha256":"e721262edf8a9ab5568ddc27639176312d4a366203b5f73e2d7c11fde2c554e9"},{"path":"product/stores/auths-stores/src/lifecycle.rs","sha256":"94f64d25bc178a9e60ba3c0ee6915d7fb3af7c4468792d76b4e70f43f4de1e2f"}],"schema":"auths.gateway-semantic-closure/1"} \ No newline at end of file +{"files":[{"path":"Cargo.lock","sha256":"c94ed342774d5e2823f01ecf74b8a4812c5f9a6b0cf811d31f2e2cecb671a275"},{"path":"Cargo.toml","sha256":"6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24"},{"path":"core/adapters/auths-did-keri/Cargo.toml","sha256":"86ba3e3f9a0a70d970568bfb3113b7ba7bbdd81c3eebbb52743dd574a0c0ecaa"},{"path":"core/adapters/auths-did-keri/src/lib.rs","sha256":"a75674842f8a7142004369ccd206ab43e476459293f0ff4bed4d4e659031b3e3"},{"path":"core/adapters/auths-did-key/Cargo.toml","sha256":"d5a3ae07ecde83f91eed4c3785051dd0f44eab6c891754f3309b6b40596707d7"},{"path":"core/adapters/auths-did-key/src/lib.rs","sha256":"b76a3f4528a725df53cfa9242e6e414e1d26caa48468aaed497e28b121f4497c"},{"path":"core/adapters/auths-raw-key/Cargo.toml","sha256":"f49616bc18c19e6aaa7e6a02ccebcdb9f5c1422c1278ef9869e0dbf22ceda7be"},{"path":"core/adapters/auths-raw-key/src/lib.rs","sha256":"45eec1b295dac3bed65cd79c942870b926b06b3f5d38eaebaeb6140ac69315fa"},{"path":"core/crates/auths-algebra-kernel/Cargo.toml","sha256":"0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba"},{"path":"core/crates/auths-algebra-kernel/src/generated.rs","sha256":"ae4bcbef42a408c7ffa0c6a74a42f7de177a6f14479e51d205acf830bda05960"},{"path":"core/crates/auths-algebra-kernel/src/lib.rs","sha256":"6654667eeb9b353d6648954c9fd2e8838462a82ce6b2803eb49e1366892c68c6"},{"path":"core/crates/auths-assurance/Cargo.toml","sha256":"afcb12a97ddd09d7a264b9ecd3fcaefc865ff2c9b4539ee85b00883420ba333a"},{"path":"core/crates/auths-assurance/src/lib.rs","sha256":"0fb2ec844d674b25a9e20b1601452c89c2454901fa506adfa9bb38ef9a7fa213"},{"path":"core/crates/auths-author/Cargo.toml","sha256":"1e6f0e3bc079ddb558decf0db26b291c6e72fc47327b6df1b7650d41689b215f"},{"path":"core/crates/auths-author/src/lib.rs","sha256":"e14475f2f49715a1869d5fa6b11ff1fbb72497e39097e09f833b0bae7e5b3f2b"},{"path":"core/crates/auths-author/src/observations.rs","sha256":"dda7d6bfa6f4bd7e95a480ca283c2c0e996f69c5c15cb0c7197af328131a7066"},{"path":"core/crates/auths-authority/Cargo.toml","sha256":"4f68212938029f79ebd857b4f3038494eb85d0163d49f07e51376715cf959815"},{"path":"core/crates/auths-authority/src/lib.rs","sha256":"da88d5194de4e17449e69972c0fb042afa3c39798a8f570f30771e77c384f1eb"},{"path":"core/crates/auths-codec/Cargo.toml","sha256":"e20e51826e17814effd9d8925d18d5fbdd6c0d37bf50231e743ec2611314722c"},{"path":"core/crates/auths-codec/src/approval.rs","sha256":"fbff43bf4d57f69f8b7738a8647751cde75c5a932dee65d924a1fe9c7202f91f"},{"path":"core/crates/auths-codec/src/bounded_policy.rs","sha256":"d21f6728be2d8a04b6d94921f2b683f7e61cbb42e0ac6866f1c88a49caa534c3"},{"path":"core/crates/auths-codec/src/decode.rs","sha256":"ba2999584cdf53b1b517ecb9c7ea50d39efee17c666a9a38e2ad1ac94379f778"},{"path":"core/crates/auths-codec/src/encode.rs","sha256":"8491192053e2e15d62b4d2a491de22405b7487ead69ab6f6bca40669ce7ca5f7"},{"path":"core/crates/auths-codec/src/error.rs","sha256":"fecb0737c16deb42d859f1dc7727c698438d9ac12064fd99e0024629642c390c"},{"path":"core/crates/auths-codec/src/hash.rs","sha256":"f88e111f1dbb2cef6b7b5e9c948cb45ff92e366710c8a5f5c636138aa748479e"},{"path":"core/crates/auths-codec/src/lib.rs","sha256":"3b0e5c94c6f34f750b88a9333e1d5c8145746d845d3a23e0d2f61807cf592ea7"},{"path":"core/crates/auths-codec/src/observation.rs","sha256":"38328b0c71ff97a4196eeade8b4faa889527ff1f80bb168468bcd49082a3987e"},{"path":"core/crates/auths-composition/Cargo.toml","sha256":"331e13025eb82588b5269ed3975929eb41c823d588c49e4c296273d85c6fe80e"},{"path":"core/crates/auths-composition/src/lib.rs","sha256":"e42e3b0b6a9985b73c533aeb23799c638979aa27a9ce7d0f10a8d60340570fb1"},{"path":"core/crates/auths-model/Cargo.toml","sha256":"565c15302b0cc9270db1e28efa3862804846850ba933cc17aea8abcec4a65987"},{"path":"core/crates/auths-model/src/approval.rs","sha256":"54cf44a9ef747ec21546a4086aecfb130bc7803b0d646430e6082df51e6e305f"},{"path":"core/crates/auths-model/src/bounded.rs","sha256":"f90496abc0a06c028b4d850af6ddab7d850bfafeaa3d042f1b1246a41d8bbbc9"},{"path":"core/crates/auths-model/src/bounded_policy.rs","sha256":"306a8f049cc7cfc7635fe0e4de47eb7813eed63d3c14c3be2b51586aa4eea450"},{"path":"core/crates/auths-model/src/lib.rs","sha256":"e7cfe6bb9574c6b016aa63e70658c31e0b90903ec6479a49f4a2ceb64f5bad97"},{"path":"core/crates/auths-model/src/observation.rs","sha256":"b3ed3e3cc090afca2896a7d3de7988afccc1ee1ea0ebd91b51a8bc0f20ad8dbb"},{"path":"core/crates/auths-multikey/Cargo.toml","sha256":"858756c1197befcada06134742bffe8d58cf674cadd6c046bf710570e96efaf2"},{"path":"core/crates/auths-multikey/src/lib.rs","sha256":"f5177fffb11e40eeaaa665ba886c541fc1f24d5eacdd6983fb03dc20148733f0"},{"path":"core/crates/auths-ports/Cargo.toml","sha256":"596a9b0f5af3717c16a6d13f7054d8a106bcd9f01f5f72c2235dd2afcf0ab16c"},{"path":"core/crates/auths-ports/src/binding.rs","sha256":"a16c012d40aa4249e3ec54372b9611006d0bfe8c7dc3c741911c2194ad17736d"},{"path":"core/crates/auths-ports/src/diagnostics.rs","sha256":"aa596572503b5a65a918bb2ff38281c144ff53821ee914e9325c852828d852df"},{"path":"core/crates/auths-ports/src/lib.rs","sha256":"8da1debf86f9532df0660155d04298beb1ba3a1204508f8586e2e67cd2fb3449"},{"path":"core/crates/auths-ports/src/path.rs","sha256":"b68fc547b4e4d97a60cbbc1cc1939fc6b34a8233b81f840bd396914a707e3ea1"},{"path":"core/crates/auths-raw-key-core/Cargo.toml","sha256":"98c0bc8527a537512e43a74dd6ba9658c6f0cdc16610cf938e3f9b43785d836d"},{"path":"core/crates/auths-raw-key-core/src/lib.rs","sha256":"98c0500c41697aae28708ad0bf970b9a97583d96a3d2c18d23e7fa351e0f7d12"},{"path":"core/crates/auths-registries/Cargo.toml","sha256":"590e49e58b0622d9d6274fea46796dcdb07dec9550eff295cce6a6427ffa51e2"},{"path":"core/crates/auths-registries/src/lib.rs","sha256":"450d3886d85ee333b7e046317fb5b47cde62483d5f3e41d46265e2caf4c373ec"},{"path":"core/crates/auths-registries/src/template.rs","sha256":"1224039dd2b3ce6fa8357613d8cafbae40400493da7176da202b9ade62fa05e4"},{"path":"core/crates/auths-signature-core/Cargo.toml","sha256":"6bee2230eb30af1be0bd5c2d57bd3e1903497a70028d47290d4ac6e9e0e8bca0"},{"path":"core/crates/auths-signature-core/src/lib.rs","sha256":"6e3f9311ded5e49ea50d445eb21e6d8fa12442aa4362a73e0cb6fda15b7cd865"},{"path":"core/crates/auths-signature/Cargo.toml","sha256":"7f7b5682466ba439d8c59579022cb61068cad9fb4bd2d73e1cc21327c902b450"},{"path":"core/crates/auths-signature/src/lib.rs","sha256":"b3d9ac4cc3ba0797b9e1c09f2d6ac05089b25dac4e285a5af28c0165b33d925b"},{"path":"core/crates/auths-verifier/Cargo.toml","sha256":"c43358e06a33324b41a8b93e5cc7279c55f7d21f1f6cfaa539a3fc7b4c27a38f"},{"path":"core/crates/auths-verifier/src/approval.rs","sha256":"c3cae6a49e169051eb555bb092b1069a4d422516d6a2114623a89e5f31ff923f"},{"path":"core/crates/auths-verifier/src/causal.rs","sha256":"9635230f33b13a263573d319ac8a1976addbcc07677514a43e3c7bf28dc04587"},{"path":"core/crates/auths-verifier/src/lib.rs","sha256":"f22dec38dfa47ced8da4f605390da8453273bee1da010f57fd1fdfcb10e0b389"},{"path":"core/crates/auths-verifier/src/observation.rs","sha256":"0bb07f06a0f9524c88427df1c972b1de8ba038a9eeeb15d3134c25125ae84b1e"},{"path":"core/crates/auths-verifier/src/trace.rs","sha256":"2213d72023a1d9e0413a2cf2c51c3dad9e04775d86033a0caaa9d29a8f0036f8"},{"path":"exchange/crates/auths-proof-exchange-model/Cargo.toml","sha256":"34b2db64f93a288e942b5a3918d28cdcbef906e0dc9074ce848018d3d5f7a1fa"},{"path":"exchange/crates/auths-proof-exchange-model/src/lib.rs","sha256":"49fac5aff2339d3a57c41cb8bb2a82852538e8f77ecc4b157c88e264ff31fb55"},{"path":"exchange/crates/auths-proof-exchange-port/Cargo.toml","sha256":"7ff660f1b7579dc570c791090aeb450404fbbf44c92781e289f5ccdde746d739"},{"path":"exchange/crates/auths-proof-exchange-port/src/lib.rs","sha256":"b408fb40c6432edc1facb3d8b3e9433a033f8dc73fe2e0ba5a88c972ca675021"},{"path":"product/config/auths-config/Cargo.toml","sha256":"e4b568ab9f6d84f7d7e6d66443fe825f360db9c27bc7c31d6ddc0647ba3ab304"},{"path":"product/config/auths-config/src/lib.rs","sha256":"fecf00ea65cef9018fda9af2063326d7065b869266d0d9e73a4f06816f1102cc"},{"path":"product/errors/auths-errors/Cargo.toml","sha256":"3b3a199b6460ba75bda84475bb5accd35e1485448a3981038db85bf4772dd350"},{"path":"product/errors/auths-errors/src/lib.rs","sha256":"7feeb9069fa4003f94f1f07c1c94619cf1c883e0dbaaf2187f04d0f742264bdd"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/Cargo.toml","sha256":"716f1f2a117d6d69d8effe9ee9057e24ba3502f20af6a602b06facb638cdabed"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/api.rs","sha256":"b3c4321e0737835ecc4f17235d7589b7f3d62180954ebb98ea9449252300245a"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/clock.rs","sha256":"73f0a6e0f5903883329fa6683f5888288f759512ac69e5c87efd2b6b87f7d79f"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/http.rs","sha256":"14c1fce14e24c984b2a275563a29b6326fb08367922b6e8d37ba38b9cb81aa2b"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/identity.rs","sha256":"186de11230c8b33375951c4368609f8976bf9795f171af3fd7fac26207a94361"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs","sha256":"881ad9ccca369b6eaa6bfd9ec03b1585bff07b042da38942ef57154839449d3e"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/names.rs","sha256":"41bb23572d6002e23ee103d6fe70ecd68764861c6f2e48a1c53af998270a4afa"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs","sha256":"39fed883f4802e68d3b41a68fea0aba0737810996b33d13577de70faba004c29"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/store.rs","sha256":"fc60ee9c49b2f4f063c449b4c78100c5c4872779e94ca168f796603b380ef6e4"},{"path":"product/integrations/auths-custody/Cargo.toml","sha256":"1e14034185ad1ec24a977fd5f41d0abee219606245c046ce2a82287fadef448b"},{"path":"product/integrations/auths-custody/src/conformance.rs","sha256":"8ed1afd58f18fc6becc268908aa6419c9aa404c79da0197963eb2599df44acf6"},{"path":"product/integrations/auths-custody/src/key.rs","sha256":"70cbb0fd21b6f5652157845a22c35be2d0f6c05b3d138fc4b9bb6dbdc3d81c40"},{"path":"product/integrations/auths-custody/src/lib.rs","sha256":"8ee593c1f59b0fd2126bdda9138026f5bc531beb64d4489a99785842e7b98b43"},{"path":"product/operations/auths-operations/Cargo.toml","sha256":"73dde1e914ba5e1386f8d49c0d730423cc72ae77ec44c6554a6a75cc8e8922b1"},{"path":"product/operations/auths-operations/src/explanation.rs","sha256":"b4a39bcbd5712cb9e735ee7deeb281f3fa6af5ddca973735bf3d87dce427ef11"},{"path":"product/operations/auths-operations/src/lib.rs","sha256":"3f401a56555113b98f57bca172a2660eaecedf76247b83a3fdbb089c133a29cd"},{"path":"product/operations/auths-operations/src/render/json.rs","sha256":"2ae042639960afee123730e945d373bc5dda1d2b3af20ae16c939a7e99b9e418"},{"path":"product/operations/auths-operations/src/render/mod.rs","sha256":"b3b7f6fe473f49227ace5a68bfc3d8dc14b5db8dd9888fd9e207070337b1b8bf"},{"path":"product/operations/auths-operations/src/render/text.rs","sha256":"f216cf3bdb00e264523271b16e7059535ac6b1aabf271cebd7935af155e4bfec"},{"path":"product/policy/auths-bounded-policy/Cargo.toml","sha256":"babd5d200923137ead71d8c2528f847cea323ce98da942a1320b054436612c47"},{"path":"product/policy/auths-bounded-policy/src/arithmetic.rs","sha256":"75e43c5d4eab8d1f71c1daf53839f5f9fe45a400afc1f63a30c6f55ce3632627"},{"path":"product/policy/auths-bounded-policy/src/commitment.rs","sha256":"c5706f2d583454e1a7f570f7ada138d4d864bef0205dfae7c1296774f396bb3f"},{"path":"product/policy/auths-bounded-policy/src/eligibility.rs","sha256":"c9acdfb793074e687fc36efad506be27dbd99ffbf40387bc66c8de39ef238432"},{"path":"product/policy/auths-bounded-policy/src/identifier.rs","sha256":"0006a32bae9eb16c4178cf797df418d2b0a781f2bc6474b741dc1a908141831c"},{"path":"product/policy/auths-bounded-policy/src/kernel.rs","sha256":"99187c28b161ac70bee1afed60711f7f645adb4d1671a01863f9849b369811d5"},{"path":"product/policy/auths-bounded-policy/src/lib.rs","sha256":"76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c"},{"path":"product/policy/auths-bounded-policy/src/receipt.rs","sha256":"3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad"},{"path":"product/policy/auths-bounded-policy/src/registry.rs","sha256":"4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0"},{"path":"product/profiles/auths-profile-api/Cargo.toml","sha256":"7ae85761f58625b5d678f961fd052eebf3e000ef565c7312e3ac857763c0017f"},{"path":"product/profiles/auths-profile-api/src/lib.rs","sha256":"a194b82b20bf8aa864c2334ef6c6aec30b2154ded972862252d5dcefa488ab95"},{"path":"product/profiles/auths-profile-mcp/Cargo.toml","sha256":"db264fc25242f7b7e4133cbe5782545b3107b406c87168ae072683cfb59eac66"},{"path":"product/profiles/auths-profile-mcp/src/arguments.rs","sha256":"a5de696586d507e2aee4a49fee99ef1ef4c51a2e46603f8838f1af6d9009833f"},{"path":"product/profiles/auths-profile-mcp/src/lib.rs","sha256":"d0f8b733a09ef8408336cdebc8948d6a5861012ce6878598b11be7084dfd4280"},{"path":"product/profiles/auths-profile-mcp/src/session.rs","sha256":"166c281fa66333388e4760d6098dad02d3359e1d5de4b8f93312c014f97abb03"},{"path":"product/qualification/auths-recipe-qualification/Cargo.toml","sha256":"b7b15b30b9a3d96d4f089d514266d3a892de6608d30707aa44be31cca89ca9fe"},{"path":"product/qualification/auths-recipe-qualification/src/canonical.rs","sha256":"30a9b50777f0dcb4b606abfee2467d5a975d9f6ad941ab6c13ca3df5b359f667"},{"path":"product/qualification/auths-recipe-qualification/src/closure.rs","sha256":"0ad6aee9bd981e2863fa725f209ec84031db2ff12f4c7ac3aaf5120f0bb86039"},{"path":"product/qualification/auths-recipe-qualification/src/error.rs","sha256":"52d5cf720a1e4579008fdda90a3ac2c31f0b8db57985f121f65e54b4da2b7dd1"},{"path":"product/qualification/auths-recipe-qualification/src/evidence.rs","sha256":"1a4cb862f725b02f9efd827db99637ea8178a5236aa020ec271a363edbe7b362"},{"path":"product/qualification/auths-recipe-qualification/src/ids.rs","sha256":"e81a906d571497ab2da753e1532d4443706410e0b75fdd59a7d2d788c7aec403"},{"path":"product/qualification/auths-recipe-qualification/src/lib.rs","sha256":"195b19f46e1e94a0f3594ad5958e5715bc5e3ad415bdfe6428dfc1b6dd3f4631"},{"path":"product/qualification/auths-recipe-qualification/src/model.rs","sha256":"3484eb0ec287b23d4682ade7b1b0f8d1335985b3fb180f06fc28716076957d5f"},{"path":"product/qualification/auths-recipe-qualification/src/release.rs","sha256":"d816b53e2275e902c750ad03803061844e259e28560ab2d1c77e8a43981a4d6a"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/mod.rs","sha256":"7f15b68e05a04f202bcb1fb80de1d9a9a4fda8bfd6af2cd4e5c660fc75d96fe5"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/schemas.rs","sha256":"c59feec2805621f341a90f81fc005e2c12f7a70f9d264fdeacccb2be4fe1c046"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/verification.rs","sha256":"6a6b5834c5dae10af1ba8939b2deae43b85db71544dc8f077ff63b7fe68ac8a8"},{"path":"product/qualification/auths-recipe-qualification/src/verify.rs","sha256":"edd33589c54fb79bcfccc4cf4e6ccf95bbca088318bb7f8dfc27da684b4fa671"},{"path":"product/receipts/auths-receipts/Cargo.toml","sha256":"6001fa1375899953aafcb07c23a6da0c8f57ea7ec08bb9c950b12a60a8cc6f0f"},{"path":"product/receipts/auths-receipts/src/disclosure.rs","sha256":"ba9ed439be0a320c8a01f5b6e9b51361c1a37e076947490d8e4a484ba6bb119c"},{"path":"product/receipts/auths-receipts/src/lib.rs","sha256":"547a57c4160256719cafb7d0ab972d9fc80b0da14fbbce4148c70c414070ff36"},{"path":"product/runtime/auths-connections/Cargo.toml","sha256":"babeb6e1dda3dfb66291713ce1e43dce5c349833d0b50ea4dccbf986030026b2"},{"path":"product/runtime/auths-connections/src/credential.rs","sha256":"82921413bb053f0f6c7931fbd4e6a86c8cc1d8c6b51debd9c2cef33a8d5b1c51"},{"path":"product/runtime/auths-connections/src/kernel.rs","sha256":"a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8"},{"path":"product/runtime/auths-connections/src/lib.rs","sha256":"79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22"},{"path":"product/runtime/auths-connections/src/model.rs","sha256":"de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77"},{"path":"product/runtime/auths-connections/src/registry.rs","sha256":"e57640e003e72ad3235c567c2bb944a262bd64e673f023b62ea091094cc7e946"},{"path":"product/runtime/auths-gateway-kernel/Cargo.toml","sha256":"34f864e67656af4ac7e5c7a347a23f01fc8ab31365b8e23c0ef474483b14a183"},{"path":"product/runtime/auths-gateway-kernel/src/construct.rs","sha256":"e9d65744bae273d65face4285e5d2da75c06a92ab48f7b8333d496604e31c63c"},{"path":"product/runtime/auths-gateway-kernel/src/lib.rs","sha256":"cfda6f8453426564c085475f183b6f790b438768a19668f1b65d33ba59dc8632"},{"path":"product/runtime/auths-gateway-kernel/src/order.rs","sha256":"e0045f877c4b7fe3860c291039853885064ddcdebba7c9b345ab65e81e646dda"},{"path":"product/runtime/auths-gateway-kernel/src/outcome.rs","sha256":"e9785b1afe70788c89b51b18655bcd5acff7b0c8e3d12fb79c6f05a202e67e6b"},{"path":"product/runtime/auths-gateway-kernel/src/ratio.rs","sha256":"7ace22264812e6fc1ef3a62afee402cf43494bb71ae0d3de219ad1b39d690bcb"},{"path":"product/runtime/auths-gateway-kernel/src/recovery.rs","sha256":"9f46dcd1685ab6e4d1ba04a3fc286a9f3afee8fb47829be1fbc670a7926a2dc6"},{"path":"product/runtime/auths-gateway-kernel/src/transition.rs","sha256":"cefb8f01d915880f6921f2501ff881ad94b9de61072c34d9cd19220992f97374"},{"path":"product/runtime/auths-gateway/Cargo.toml","sha256":"00b28be86921dcdc0ad90cce0c62c2961cafefe96ea6c2edf0e926c3d405ccad"},{"path":"product/runtime/auths-gateway/src/admin.rs","sha256":"2d5cc67afac42fbd15f36e2d1693cd1b20cedacf775040dce6ffe04ccc94c9ea"},{"path":"product/runtime/auths-gateway/src/app.rs","sha256":"6f80f63833ea0815bb44fbf3b0cc54624a08e9fb578b035819f2980dc04e8256"},{"path":"product/runtime/auths-gateway/src/audit.rs","sha256":"0edb2037eb7b5d6f13acfce85c54f62a82bf7fdd31bc7e626c4fec183cef61dd"},{"path":"product/runtime/auths-gateway/src/audit_tests.rs","sha256":"990969384a52d75bc2489d9d412a9e7dd814bca1c8f65c701d6205fae62a15d5"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway-harness.rs","sha256":"12b0c24d36b2e6a3be392d3c081a783b355fdd67dc5b54bacc0410e803116b8c"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway.rs","sha256":"9f4b46006fbc28a71c07f14f1f40837782407628c094d7c17f216f9be75e2dde"},{"path":"product/runtime/auths-gateway/src/binding.rs","sha256":"663b0ce878319511aa7d05722ab4ab2fa9be18817884ffb2ee9f131ff1e382d1"},{"path":"product/runtime/auths-gateway/src/bounds.rs","sha256":"9cfa0eae4973e5e047a198360b22f041708fa20276b0b90c2ec440f06915d64b"},{"path":"product/runtime/auths-gateway/src/bounds_aggregate_tests.rs","sha256":"ab34f227b7c8692ba1da88ccb32bb3687a66adf8353d8282fae905d4a88eb612"},{"path":"product/runtime/auths-gateway/src/bounds_tests.rs","sha256":"74136bc570da7b9338b5a1a1ed9d3fd892c55135160964f9d3ac0e2cf5741375"},{"path":"product/runtime/auths-gateway/src/connection.rs","sha256":"7b5d049c258a26ed1c93ecf860f51d051a8a65f9b93554af0b1ea93862398ec9"},{"path":"product/runtime/auths-gateway/src/credential_journal.rs","sha256":"8e2b0733038d93ca5df770d27a870237e3b65664fa48da017d964a65bbbe25b8"},{"path":"product/runtime/auths-gateway/src/echo_verify.rs","sha256":"6d453051665f823abd7354d5c50031d9524cf47d6092d2f09080ae814e3b9575"},{"path":"product/runtime/auths-gateway/src/engine.rs","sha256":"a9f71575994ff21633ddfc533b1d810515db71aa0146fa8869dad72eddcb2a12"},{"path":"product/runtime/auths-gateway/src/fuzzing.rs","sha256":"ed3b0028487eb546a3b0a91d115aa8f18bcea324b61620bfe8e35a9e6ab18758"},{"path":"product/runtime/auths-gateway/src/generation_floor.rs","sha256":"47964a5f1ca2fc9c4da0b526b6d5c5637fc0ce1d2e429219d02f1b0dc652fdff"},{"path":"product/runtime/auths-gateway/src/harness.rs","sha256":"c87e479f3eb281960f6c9c80d43c7560d7ccb654b0154ec823d3fcec4884ac05"},{"path":"product/runtime/auths-gateway/src/lib.rs","sha256":"b182052835a2cd631d1f801a74788d6ac1ef9cae21ade9ab4ffc270cd6f667ed"},{"path":"product/runtime/auths-gateway/src/listener.rs","sha256":"aa08239bcbc1fcb55e8a212fbdf6a84f12985b0d436dcb51dc58b06e59e435f2"},{"path":"product/runtime/auths-gateway/src/observed_tests.rs","sha256":"a22be071695f89ca2578a4d82fd80d9cb82289213c9bdb8f0470f6b2dc3d9201"},{"path":"product/runtime/auths-gateway/src/observer.rs","sha256":"562ffcaea071c3856e0708dc2fe33516917e145d2438aabb75af0a2b6ba01046"},{"path":"product/runtime/auths-gateway/src/onboarding.rs","sha256":"0dfd7d67e7f02f18a28d1c86ca1b7751d7463f5efcdbe3825de0ad8cbccb3891"},{"path":"product/runtime/auths-gateway/src/operator.rs","sha256":"c3c36954a3e86723df035b47f43b85fc8ab3a6292983522b6258d5c6b4e6c4e4"},{"path":"product/runtime/auths-gateway/src/pending_vectors/attempts.rs","sha256":"47ef3c8cb1c5504d47ae9a0088705ce6715fe86bac1671a34a56fb38a64d0dd3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/bounds.rs","sha256":"e612217307e1da5b0eb5ee6582a7458bb064b8aa8a529fc6555b1b334127ab68"},{"path":"product/runtime/auths-gateway/src/pending_vectors/codes.rs","sha256":"e00670a5ef24eb856cc2c6dcda8e5a263842f55c76bb939c0c27bd9df37e5522"},{"path":"product/runtime/auths-gateway/src/pending_vectors/keys.rs","sha256":"f84c56f2ea9cb34b2b79c72d13fbf2c6585010ec1ed450af58a78c80c1ea1edd"},{"path":"product/runtime/auths-gateway/src/pending_vectors/mod.rs","sha256":"5de8340f0ef71a0b57a09e323fefe473d3160c6ae952b9ba46f714825fbacafc"},{"path":"product/runtime/auths-gateway/src/pending_vectors/outcomes.rs","sha256":"8ec07b9511b48913af36ac999d2aa0e82924289f6acb23ddaeb9f00f99815166"},{"path":"product/runtime/auths-gateway/src/pending_vectors/production.rs","sha256":"c2fa18b5d96c87689fe60d95faadebe2c7fdf5b78be872ca15a67ad980106ed3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/recipes.rs","sha256":"51693208270231c25c3aef2a32151d5962114c71e86b88cb9df83181c7af83d9"},{"path":"product/runtime/auths-gateway/src/pre_entry.rs","sha256":"06ea78ca140468bfaba17d9ab04912ad68673954c3203c98fed28272ff2a00c0"},{"path":"product/runtime/auths-gateway/src/property_tests.rs","sha256":"939c081e2e154aaf10186754044bdd65608932c899b970a04a71d0afaa999a93"},{"path":"product/runtime/auths-gateway/src/qualification.rs","sha256":"a4398512ccb7bb494000fe38f03e0faa7b82d1f80ef5ee2dfa75698ae4f5a9be"},{"path":"product/runtime/auths-gateway/src/qualification_tests.rs","sha256":"4473add5729b97faf04d7be7fd8cf3bbacd7f545e1b61c7d2782563011906b4d"},{"path":"product/runtime/auths-gateway/src/quorum_tests.rs","sha256":"a78380b019104d688c11a4410082c7e08ded3106aab099954c4f8a1b4ae0fd89"},{"path":"product/runtime/auths-gateway/src/readiness.rs","sha256":"911c3f11892f94641574375e2da4c671c802738f71082f12c39832331052d43d"},{"path":"product/runtime/auths-gateway/src/recipe.rs","sha256":"fecf9af67e7afc48d080e9f8f55f8ce28e49d0e08988717a27908bbda461d6b6"},{"path":"product/runtime/auths-gateway/src/recipe/lower.rs","sha256":"8088b8751ed831dbb48247af953c6290ac95e2a438ccd5bd65eff54be06a1fd1"},{"path":"product/runtime/auths-gateway/src/recipe/review.rs","sha256":"c3eb7d9fdd98dacf52750b14b67ad7b7faaecbbdeafff1e0b049f67d0a2d0139"},{"path":"product/runtime/auths-gateway/src/recipe/runtime.rs","sha256":"c286f0d15f974402822c0810d8e97f98411dc1c557755cc23e540d85e2bb42d9"},{"path":"product/runtime/auths-gateway/src/recipe/source.rs","sha256":"1af50298fb1461e1b24cbdf560d43124d6b1c4c529586c911b1c4797214a69ff"},{"path":"product/runtime/auths-gateway/src/recipe/tests.rs","sha256":"aac551a2481bbc60864c64079bc667dcb232e45a0f41a04073ed84ab5dbe1fce"},{"path":"product/runtime/auths-gateway/src/recipe/validate.rs","sha256":"3711b17605cb7b0d639bc1b180449231f5882a306cab20e2c7782155cc63b0d4"},{"path":"product/runtime/auths-gateway/src/scenario_tests.rs","sha256":"d8271761b12597bfe1233f8eb5ad1d4e5498c5d03388e832e24ab818484a1de4"},{"path":"product/runtime/auths-gateway/src/separation.rs","sha256":"be9306848ca5d801767cf6aa14247c8618312ef0e202f00ce0c24c4844491061"},{"path":"product/runtime/auths-gateway/src/store.rs","sha256":"1e5288345c2cb1421aeda277b3158d07607404b0ec46943222ac107b63dcbb46"},{"path":"product/runtime/auths-gateway/src/store_testkit.rs","sha256":"88d82fee42f1b8ef521e8deef0216e938ebeaad822eb2f5020e70b89d145ea70"},{"path":"product/runtime/auths-gateway/src/submit.rs","sha256":"c78dbbba7c45b443febf655056c5edcd635e77be7b21c5b2c318097502415ffe"},{"path":"product/runtime/auths-gateway/src/support.rs","sha256":"33c87008b6643e3e595e5af0c221ee5460df69e17cc69be2edcae13474d0cdb9"},{"path":"product/runtime/auths-gateway/src/transport.rs","sha256":"be2c6dc75b8daec110bf8749fedc3823f6067d40b999aa3eb21126896a97d3ad"},{"path":"product/runtime/auths-kernel-runtime/Cargo.toml","sha256":"926bcd0053e5edd703be8f0027ad009e2982db013c8174c1366edbf38b48087d"},{"path":"product/runtime/auths-kernel-runtime/src/lib.rs","sha256":"7108faae9ca4bc32dc093ddaf885ac8f74f3c9b8d317b7c7d0ed00d1d0ab5972"},{"path":"product/runtime/auths-lifecycle/Cargo.toml","sha256":"c5053c705f8d5554b44e432fe75287a2faf11d644e5a2552e45ad6cd94176af5"},{"path":"product/runtime/auths-lifecycle/src/codec.rs","sha256":"51c4b746749150e8bfcd8ff972b3f6c1ef40bec15583448ec1b471d9ad737dc0"},{"path":"product/runtime/auths-lifecycle/src/digest.rs","sha256":"55282cd7d8aba37713c2dcb5357c9877819edb72a30eadefb860d28d7d3a3eb7"},{"path":"product/runtime/auths-lifecycle/src/identifier.rs","sha256":"31620e8c16de68d3d2d3b84d6353c1a5b9d4151d8247f91fa389b906a8e660f1"},{"path":"product/runtime/auths-lifecycle/src/kernel.rs","sha256":"2abb8c094b36d35b364e74d78091d14c5d6f3d1eb6552cca3b5538dbd017ce23"},{"path":"product/runtime/auths-lifecycle/src/lib.rs","sha256":"afe5a345cd309b5a4f08ffba3170a6d7f16ff914892b3f2006d5208ed24ec736"},{"path":"product/runtime/auths-lifecycle/src/model.rs","sha256":"1af12bbeeeaa65ec02ddcebd7d2c8c92ec1e339fa40ae85b45ab9b01a722a4fa"},{"path":"product/runtime/auths-lifecycle/src/operation.rs","sha256":"78e6d05fcf5d7ea4f148032a3fa26fdfcab77eb346019effe927b08e0d64d732"},{"path":"product/runtime/auths-lifecycle/src/registry.rs","sha256":"53495fe6f7a77422593a41623e28716f1c140dcc1e00f87f6b0ffbfb93a5ef90"},{"path":"product/runtime/auths-lifecycle/src/sealed.rs","sha256":"2e0c03b5813c926c159598bb7890d1523825edbe57cd687d42a5dfb3374a0c19"},{"path":"product/runtime/auths-lifecycle/src/test_support.rs","sha256":"221d9a5c5ef8e1f9f8fd66927484eaf813571d0568470278ecd8fa08a5eec8cd"},{"path":"product/runtime/auths-lifecycle/src/transition.rs","sha256":"011805a28efdd541f44ccea54dd0e34a1e58f4004447ee58013703b4fb6b2822"},{"path":"product/runtime/auths-runtime/Cargo.toml","sha256":"dd29d80a8b4bb56c869f036a6c9998f6e6d1c0383ac5dc03fa42b24abe2a7ff7"},{"path":"product/runtime/auths-runtime/src/lib.rs","sha256":"132ca03d58c14905d3a822a4972f42a22a5ad33a45f2ba9ca44f3a57d810b4b0"},{"path":"product/runtime/auths-runtime/src/production.rs","sha256":"fd4eff4270c571c10fcff6cf27df28961ebf074de8a1a028f500fda1ca376820"},{"path":"product/sdk/auths-approval-quorum/Cargo.toml","sha256":"df904971fca87a24194c5816738a331588fe8f164acb5d70839a35dca5f57114"},{"path":"product/sdk/auths-approval-quorum/src/lib.rs","sha256":"72e4086088a1c0912e4e1a9e980f26a5c280bf5ab16ea39c9f0f58d5096ac2ce"},{"path":"product/sdk/auths-approval-quorum/src/remote.rs","sha256":"9fa029c7c63003adf260f8aec55160c545681c60c1bace0d934e7525862aac7b"},{"path":"product/sdk/auths-approval-quorum/src/remote_tests.rs","sha256":"8a09ce17cfee82a035a74edd535f3ebeb3db0e078784740d3997b17dbdb10197"},{"path":"product/sdk/auths-approval-quorum/src/tests.rs","sha256":"0acbf12be3e497dcc6c2d8f29c9af3b1a7ed8e11b75f6399570d4f217a785060"},{"path":"product/stores/auths-stores/Cargo.toml","sha256":"a32c4b76d17b264be5d40d24497ff237e1ed87822e8bab86229b3db93106dbe3"},{"path":"product/stores/auths-stores/src/gateway_attempt.rs","sha256":"185da8f4a220fba836d5b78a9311f03204681c43a3c53951008084d135bf4d21"},{"path":"product/stores/auths-stores/src/lib.rs","sha256":"e721262edf8a9ab5568ddc27639176312d4a366203b5f73e2d7c11fde2c554e9"},{"path":"product/stores/auths-stores/src/lifecycle.rs","sha256":"94f64d25bc178a9e60ba3c0ee6915d7fb3af7c4468792d76b4e70f43f4de1e2f"}],"schema":"auths.gateway-semantic-closure/1"} \ No newline at end of file diff --git a/product/runtime/auths-gateway/src/semantic_closure.rs b/product/runtime/auths-gateway/src/semantic_closure.rs index 4340afec1..224ec4a82 100644 --- a/product/runtime/auths-gateway/src/semantic_closure.rs +++ b/product/runtime/auths-gateway/src/semantic_closure.rs @@ -10,7 +10,7 @@ /// SHA-256 of the schema, a NUL byte, and `semantic-closure.json`. /// Regenerate through `semantic_closure_is_current` with `AUTHS_UPDATE_FIXTURES=1`. pub const GATEWAY_SEMANTIC_CLOSURE_SHA256: &str = - "a6bc2c9f24395c8eaf1ae05ec77e37926297d8c06e59cbde9ce2694e7c7eb75c"; + "09df4a87c61ecc639aeb860dcc35980afb737055412fa48aedf39d1d070cf59f"; #[cfg(test)] mod tests { diff --git a/product/runtime/auths-gateway/src/support.rs b/product/runtime/auths-gateway/src/support.rs index 8d3e354fb..52634bd6d 100644 --- a/product/runtime/auths-gateway/src/support.rs +++ b/product/runtime/auths-gateway/src/support.rs @@ -132,17 +132,35 @@ struct Archive { /// /// # Errors /// -/// Returns `gateway.support.unavailable` when the archive cannot be encoded. +/// Returns `gateway.support.unavailable` when the archive cannot be encoded +/// or a supplied diagnostic code is outside the closed qualification set. pub fn support_bundle(facts: &SupportFacts) -> Result, &'static str> { - let attempts = facts.attempts.as_ref().map(|listed| { - let listed = &listed[..listed.len().min(MAX_SUPPORT_ATTEMPTS)]; + use auths_recipe_qualification::QualificationRefusal; + if facts.qualification.code.is_some_and(|code| { + ![ + QualificationRefusal::Unavailable, + QualificationRefusal::Revoked, + QualificationRefusal::ClockUntrusted, + QualificationRefusal::RevocationStale, + QualificationRefusal::Missing, + QualificationRefusal::Expired, + QualificationRefusal::DigestMismatch, + QualificationRefusal::TargetMismatch, + ] + .into_iter() + .any(|refusal| crate::qualification_code(refusal) == code) + }) { + return Err("gateway.support.unavailable"); + } + let attempts = facts.attempts.as_ref().map(|available| { + let listed = &available[..available.len().min(MAX_SUPPORT_ATTEMPTS)]; let mut by_stage = BTreeMap::new(); for (_, stage) in listed { *by_stage.entry(stage_token(*stage)).or_insert(0_u64) += 1; } Attempts { listed: listed.len(), - truncated: facts.attempts_truncated, + truncated: facts.attempts_truncated || available.len() > MAX_SUPPORT_ATTEMPTS, by_stage, identifiers: listed .iter() @@ -270,7 +288,7 @@ mod tests { ); let mut many = facts(); many.attempts = Some(vec![([5; 32], GatewayAttemptStage::NotEntered); 400]); - many.attempts_truncated = true; + many.attempts_truncated = false; let bytes = support_bundle(&many).expect("archive"); let archive: serde_json::Value = serde_json::from_slice(&bytes).expect("JSON"); assert_eq!(archive["attempts"]["listed"], MAX_SUPPORT_ATTEMPTS); @@ -278,18 +296,19 @@ mod tests { assert!(bytes.len() < 64 * 1024, "the archive is bounded"); } - /// The facts an archive is built from have no member that holds text, - /// so nothing a request, provider, or operator wrote can enter one. #[test] - fn the_facts_have_no_free_text_member() { - let source = include_str!("support.rs"); - let facts = source - .split("pub struct SupportFacts {") - .nth(1) - .and_then(|rest| rest.split("\n}\n").next()) - .expect("the facts"); - for forbidden in ["String", "&str", "Vec", "PathBuf", "Value"] { - assert!(!facts.contains(forbidden), "the facts hold a {forbidden}"); + fn arbitrary_diagnostic_text_cannot_enter_the_archive() { + let mut contaminated = facts(); + for code in [ + "synthetic-canary-provider-response", + "gateway.qualification.revoked synthetic-canary-raw-header", + "gateway.qualification.unknown-code", + ] { + contaminated.qualification.code = Some(code); + assert_eq!( + support_bundle(&contaminated), + Err("gateway.support.unavailable") + ); } } } diff --git a/release/semantic-freeze-versions.toml b/release/semantic-freeze-versions.toml index c905fe950..2a0e5898f 100644 --- a/release/semantic-freeze-versions.toml +++ b/release/semantic-freeze-versions.toml @@ -1,4 +1,4 @@ -freeze_version = 363 +freeze_version = 364 # Semantic identity counters live outside the xtask source tree deliberately. # The formal source closure binds xtask's executable code, while the semantic @@ -45,7 +45,7 @@ freeze_version = 363 "auths.frozen-bytes/product/integrations/auths-stripe/fixtures/subscription-create/v1/manifest.sha256.json" = 1 "auths.frozen-bytes/product/integrations/auths-stripe/fixtures/subscription-modify/v1/manifest.sha256.json" = 1 "auths.frozen-bytes/product/integrations/auths-stripe/fixtures/v1/manifest.sha256.json" = 1 -"auths.identity.protocol" = 119 +"auths.identity.protocol" = 120 "auths.modular-components" = 20 "auths.portable-abi-bindings" = 121 "auths.product.bounded-domains" = 19 @@ -60,11 +60,11 @@ freeze_version = 363 "auths.product.mcp-closed-execution" = 31 "auths.product.mechanism-profile-conformance" = 12 "auths.product.operations" = 5 -"auths.product.public-sdk-contract" = 116 +"auths.product.public-sdk-contract" = 117 "auths.product.receipts" = 13 "auths.product.release-assurance" = 7 "auths.product.simplified-waist" = 19 "auths.product.vocabulary" = 24 "auths.release.benchmark-contract" = 1 "auths.release.evolution-contract" = 79 -"auths.release.public-surface" = 363 +"auths.release.public-surface" = 364 diff --git a/release/semantic-freeze.json b/release/semantic-freeze.json index 64b58a20c..01128b31b 100644 --- a/release/semantic-freeze.json +++ b/release/semantic-freeze.json @@ -1,6 +1,6 @@ { "schema": "auths.semantic-freeze/1", - "freezeVersion": 363, + "freezeVersion": 364, "publicSurface": { "rustRoots": [ "auths", @@ -550,7 +550,7 @@ }, { "id": "auths.identity.protocol", - "version": 119, + "version": 120, "classification": "frozen-meaning", "categories": [ "identity-protocol-versions", @@ -871,7 +871,7 @@ }, { "id": "auths.product.public-sdk-contract", - "version": 116, + "version": 117, "classification": "frozen-meaning", "categories": [ "rust-sdk-contract", @@ -1011,7 +1011,7 @@ }, { "id": "auths.release.public-surface", - "version": 363, + "version": 364, "classification": "release-metadata", "categories": [ "package-names", @@ -1103,7 +1103,7 @@ "xtask/src/release_control.rs", "xtask/src/semantic_freeze.rs" ], - "sha256": "ed0196ce5ce67794bdee6ae189a4a859e0d16602210d683155cc0defc19714e1" + "sha256": "a975b622614180a785b2909e94385845bfeddc5708d68be2c732e7326fed537a" } ] } From ad6bc4853964abb97d2b9d1aa1a268f1035c76ae Mon Sep 17 00:00:00 2001 From: bordumb Date: Tue, 6 Oct 2026 03:39:52 +0100 Subject: [PATCH 008/108] fix(gateway): split operator credential reads and writes by workload identity --- compliance.toml | 5 +- deployment/gateway/README.md | 11 +- deployment/gateway/operator.conf.example | 3 + docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md | 10 +- .../src/api.rs | 151 ++++++++++++++++++ .../src/lib.rs | 2 +- .../tests/live.rs | 26 ++- .../auths-gateway/semantic-closure.json | 2 +- .../auths-gateway/src/bin/auths-gateway.rs | 65 +++++++- .../auths-gateway/src/semantic_closure.rs | 2 +- release/semantic-freeze-versions.toml | 8 +- release/semantic-freeze.json | 14 +- 12 files changed, 268 insertions(+), 31 deletions(-) diff --git a/compliance.toml b/compliance.toml index 08ee52285..c04ae0bc3 100644 --- a/compliance.toml +++ b/compliance.toml @@ -198,8 +198,8 @@ principal_families = [] signature_families = [] profiles = [] transports = [] -configuration_inputs = ["deployment-namespace"] -security_state = ["credential-generation", "credential-reference", "exact-secret-version"] +configuration_inputs = ["deployment-namespace", "runtime-workload-identity", "operator-workload-identity"] +security_state = ["credential-generation", "credential-reference", "exact-secret-version", "separate-runtime-reader-and-operator-writer"] [packages.auths-credentials-aws-secrets-manager.claims] independent-semantic-implementation = [ @@ -207,6 +207,7 @@ independent-semantic-implementation = [ "product/integrations/auths-credentials-aws-secrets-manager/src/names.rs#frozen_version_references_are_classified", "product/integrations/auths-credentials-aws-secrets-manager/src/store.rs#hostile_answers_never_reach_the_caller", "product/integrations/auths-credentials-aws-secrets-manager/src/store.rs#rotation_keeps_the_old_generation_until_it_is_revoked", + "product/integrations/auths-credentials-aws-secrets-manager/src/api.rs#operator_administration_uses_separate_permissions_without_fallback", "product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs#the_published_plain_get_vector_is_reproduced", ] diff --git a/deployment/gateway/README.md b/deployment/gateway/README.md index 96cd39786..7b89ef2f4 100644 --- a/deployment/gateway/README.md +++ b/deployment/gateway/README.md @@ -27,9 +27,12 @@ Keep operator credentials in `/run/auths-identity/operator` and runtime credentials in `/run/auths-identity/runtime`, each mode 0700. Provision short-lived, audience-bound web identity tokens through the deployment's identity issuer. The runtime role has GetSecretValue and the one encryption -key's Decrypt; the operator role additionally has CreateSecret, DeleteSecret -and GenerateDataKey. Neither role can list secrets or alter versions. The +key's Decrypt; the operator role has CreateSecret, DeleteSecret +and GenerateDataKey, with no secret-read permission. Neither role can list secrets or alter versions. The operator executes administration as UID 62001 with its separate token path. +Its process uses the explicit runtime-role/token settings in `operator.conf.example` +for read confirmation, and the operator identity for creates and deletes. +Missing identities refuse the operation; neither falls back to the other. The application receives neither identity directory nor runtime environment. Copy `systemd/`, `run-with-postgres-url` and the reviewed public runtime configuration. @@ -49,7 +52,9 @@ preproduction exercise before admitting traffic. Install the reviewed recipe, profile lock, trusted context, distinct operator attestation and production credential store using `auths-gateway install`. Pipe the disposable credential from the operator's secret source into stdin; -never put it in argv or a shell literal. Copy the signed qualification inputs +never put it in argv or a shell literal. The first install uses the write-only +operator role. A second host's `install --join` confirms the existing secret +under the read-only runtime role; it creates no secret. Copy the signed qualification inputs with `qualification-import`; run `doctor` as root, then use `enable` only after all other required checks pass. While disabled, the connection check correctly fails: keep app ingress isolated, enable, rerun doctor, and only diff --git a/deployment/gateway/operator.conf.example b/deployment/gateway/operator.conf.example index 9d124d6b7..8c6561e27 100644 --- a/deployment/gateway/operator.conf.example +++ b/deployment/gateway/operator.conf.example @@ -4,3 +4,6 @@ AUTHS_POSTGRES_CA_PEM=/etc/auths/postgres-ca.pem AUTHS_POSTGRES_SERVER_NAME=postgres.internal AWS_ROLE_ARN=arn:aws:iam::ACCOUNT:role/auths-operator AWS_WEB_IDENTITY_TOKEN_FILE=/run/auths-identity/operator/token +# Read confirmation during rotation uses the separately provisioned runtime identity. +AUTHS_GATEWAY_RUNTIME_ROLE_ARN=arn:aws:iam::ACCOUNT:role/auths-runtime +AUTHS_GATEWAY_RUNTIME_TOKEN_FILE=/run/auths-identity/runtime/token diff --git a/docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md b/docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md index caa3e5bc3..d90bb2d1e 100644 --- a/docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md +++ b/docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md @@ -21,13 +21,21 @@ If provider, custody or qualification inputs are unavailable, use and the lifecycle store, so it also works with the gateway stopped. It is idempotent, retains attempts unchanged and claims no drainage. Use `revoke --state-dir ... --store-only` for permanent revocation. Later run the -normal `revoke` with healthy operator custody to delete the exact credentials; +`credential-collect` with healthy operator custody on every host that recorded +credential generations to delete the exact credentials; a deletion error does not undo revocation. Never turn unknown into failure or submit the operation again. Database failure means no durable stop can be claimed; isolate app ingress at the host firewall and retain the incident. ## Provider-secret rotation +For the web-identity reference, the operator configuration must explicitly +provide `AUTHS_GATEWAY_RUNTIME_ROLE_ARN` and `AUTHS_GATEWAY_RUNTIME_TOKEN_FILE` +for read confirmation. `AWS_ROLE_ARN` and `AWS_WEB_IDENTITY_TOKEN_FILE` name +the write-only operator identity. The operator process reads with the former +and creates/deletes with the latter; the serving process keeps only its +read-only identity. Neither role needs broader permissions. + Use the operator identity and `rotate-prepare --operator-process --credential-stdin --state-dir ...`, piping the new provider secret. It runs the recipe's fixed credential checks and stores a successor without publishing diff --git a/product/integrations/auths-credentials-aws-secrets-manager/src/api.rs b/product/integrations/auths-credentials-aws-secrets-manager/src/api.rs index 196c5b612..fb1830716 100644 --- a/product/integrations/auths-credentials-aws-secrets-manager/src/api.rs +++ b/product/integrations/auths-credentials-aws-secrets-manager/src/api.rs @@ -53,3 +53,154 @@ pub trait SecretsApi: Send + Sync { /// Deletes the secret named `name` at once, with no recovery window. async fn delete(&self, name: &str, deadline: Instant) -> Result<(), SecretsApiError>; } + +/// An operator process's separate read and write workload identities. +/// Reads use only `reader`; creates and exact deletes use only `writer`. +/// No failure falls back to the other identity or changes the request. +pub struct AdministrativeSecretsApi { + reader: R, + writer: W, +} + +impl AdministrativeSecretsApi { + /// Combines independently configured clients for one reviewed deployment. + #[must_use] + pub const fn new(reader: R, writer: W) -> Self { + Self { reader, writer } + } +} + +#[async_trait] +impl SecretsApi for AdministrativeSecretsApi { + async fn create( + &self, + name: &str, + version: &str, + secret: &[u8], + deadline: Instant, + ) -> Result<(), SecretsApiError> { + self.writer.create(name, version, secret, deadline).await + } + + async fn get( + &self, + name: &str, + version: &str, + deadline: Instant, + ) -> Result { + self.reader.get(name, version, deadline).await + } + + async fn delete(&self, name: &str, deadline: Instant) -> Result<(), SecretsApiError> { + self.writer.delete(name, deadline).await + } +} + +#[cfg(test)] +mod tests { + use super::*; + + enum Role { + Reader, + Writer, + } + + struct RoleClient { + role: Role, + unavailable: bool, + } + + #[async_trait] + impl SecretsApi for RoleClient { + async fn create( + &self, + name: &str, + version: &str, + secret: &[u8], + deadline: Instant, + ) -> Result<(), SecretsApiError> { + assert_eq!( + (name, version, secret), + ("exact-name", "exact-version", b"synthetic-value".as_slice()) + ); + assert!(deadline > Instant::now()); + assert!(matches!(self.role, Role::Writer), "reader cannot create"); + if self.unavailable { + Err(SecretsApiError::Unavailable) + } else { + Ok(()) + } + } + + async fn get( + &self, + name: &str, + version: &str, + deadline: Instant, + ) -> Result { + assert_eq!((name, version), ("exact-name", "exact-version")); + assert!(deadline > Instant::now()); + assert!(matches!(self.role, Role::Reader), "writer cannot read"); + if self.unavailable { + Err(SecretsApiError::Unavailable) + } else { + Ok(FetchedSecret { + version: version.to_owned(), + bytes: Zeroizing::new(b"synthetic-value".to_vec()), + }) + } + } + + async fn delete(&self, name: &str, deadline: Instant) -> Result<(), SecretsApiError> { + assert_eq!(name, "exact-name"); + assert!(deadline > Instant::now()); + assert!(matches!(self.role, Role::Writer), "reader cannot delete"); + if self.unavailable { + Err(SecretsApiError::Unavailable) + } else { + Ok(()) + } + } + } + + #[tokio::test] + async fn operator_administration_uses_separate_permissions_without_fallback() { + for reader_failed in [false, true] { + for writer_failed in [false, true] { + let api = AdministrativeSecretsApi::new( + RoleClient { + role: Role::Reader, + unavailable: reader_failed, + }, + RoleClient { + role: Role::Writer, + unavailable: writer_failed, + }, + ); + let deadline = Instant::now() + std::time::Duration::from_secs(5); + let write = if writer_failed { + Err(SecretsApiError::Unavailable) + } else { + Ok(()) + }; + assert_eq!( + api.create("exact-name", "exact-version", b"synthetic-value", deadline) + .await, + write + ); + assert_eq!(api.delete("exact-name", deadline).await, write); + match api.get("exact-name", "exact-version", deadline).await { + Ok(secret) => { + assert!(!reader_failed); + assert_eq!(secret.version, "exact-version"); + assert_eq!(&*secret.bytes, b"synthetic-value"); + } + Err(error) => { + assert!(reader_failed); + assert_eq!(error, SecretsApiError::Unavailable); + } + } + } + } + } +} diff --git a/product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs b/product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs index e35d8052c..57945cc15 100644 --- a/product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs +++ b/product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs @@ -25,7 +25,7 @@ mod names; mod sigv4; mod store; -pub use api::{FetchedSecret, SecretsApi, SecretsApiError}; +pub use api::{AdministrativeSecretsApi, FetchedSecret, SecretsApi, SecretsApiError}; pub use http::{HttpSecretsApi, InvalidDeployment, Region}; pub use identity::{ ContainerEndpoint, InstanceMetadata, SessionCredentials, WebIdentity, WorkloadIdentity, diff --git a/product/integrations/auths-credentials-aws-secrets-manager/tests/live.rs b/product/integrations/auths-credentials-aws-secrets-manager/tests/live.rs index fdc93f8f1..62ef25f30 100644 --- a/product/integrations/auths-credentials-aws-secrets-manager/tests/live.rs +++ b/product/integrations/auths-credentials-aws-secrets-manager/tests/live.rs @@ -12,8 +12,8 @@ use auths_connections::{ CredentialStoreError, ProviderKind, SecretBytes, SemanticId, }; use auths_credentials_aws_secrets_manager::{ - AwsSecretsManagerStore, DeploymentNamespace, HttpSecretsApi, Region, WebIdentity, - WorkloadIdentity as _, + AdministrativeSecretsApi, AwsSecretsManagerStore, DeploymentNamespace, HttpSecretsApi, Region, + WebIdentity, WorkloadIdentity as _, }; use std::num::NonZeroU64; use std::time::{Duration, Instant}; @@ -22,7 +22,7 @@ fn setting(name: &str) -> String { std::env::var(name).unwrap_or_else(|_| panic!("{name} is not set")) } -fn store(role: &str) -> AwsSecretsManagerStore> { +fn api(role: &str) -> HttpSecretsApi { let region = Region::parse(setting("AUTHS_CUSTODY_LIVE_REGION")).expect("region"); let identity = WebIdentity::new( ®ion, @@ -31,10 +31,13 @@ fn store(role: &str) -> AwsSecretsManagerStore> { ) .expect("identity"); let key = std::env::var("AUTHS_CUSTODY_LIVE_KMS_KEY").ok(); - let api = HttpSecretsApi::new(region, key, identity).expect("client"); + HttpSecretsApi::new(region, key, identity).expect("client") +} + +fn store(role: &str) -> AwsSecretsManagerStore> { let namespace = DeploymentNamespace::parse(setting("AUTHS_CUSTODY_LIVE_NAMESPACE")).expect("namespace"); - AwsSecretsManagerStore::new(api, namespace) + AwsSecretsManagerStore::new(api(role), namespace) } fn generation(value: u64) -> NonZeroU64 { @@ -119,6 +122,13 @@ async fn the_store_holds_its_contract_against_the_service() { } let operator = store("AUTHS_CUSTODY_LIVE_OPERATOR_ROLE"); let runtime = store("AUTHS_CUSTODY_LIVE_RUNTIME_ROLE"); + let administrative = AwsSecretsManagerStore::new( + AdministrativeSecretsApi::new( + api("AUTHS_CUSTODY_LIVE_RUNTIME_ROLE"), + api("AUTHS_CUSTODY_LIVE_OPERATOR_ROLE"), + ), + DeploymentNamespace::parse(setting("AUTHS_CUSTODY_LIVE_NAMESPACE")).expect("namespace"), + ); let connection = ConnectionId::generate().expect("connection"); // Generation 9 is the write the runtime role must be refused; it is // listed so that a role that was wrongly allowed leaves nothing behind. @@ -143,6 +153,7 @@ async fn the_store_holds_its_contract_against_the_service() { b"auths-live-first-not-a-secret" ); runtime.holds(&serving).await?; + administrative.holds(&serving).await?; // Another commitment names another version, which does not exist. let other = CredentialReferenceCommitment::of(&connection, generation(1), b"other"); @@ -181,7 +192,7 @@ async fn the_store_holds_its_contract_against_the_service() { // Rotation: the old generation is kept until it is revoked, and a // revoked generation is never answered by its successor. - let second = operator + let second = administrative .replace( &connection, generation(1), @@ -191,6 +202,7 @@ async fn the_store_holds_its_contract_against_the_service() { .await?; let old = binding(&connection, 1, 1, first); let new = binding(&connection, 2, 2, second); + administrative.holds(&new).await?; assert_eq!( leased(&runtime, &old).await?, b"auths-live-first-not-a-secret" @@ -199,7 +211,7 @@ async fn the_store_holds_its_contract_against_the_service() { leased(&runtime, &new).await?, b"auths-live-second-not-a-secret" ); - operator.revoke(&connection, generation(1)).await?; + administrative.revoke(&connection, generation(1)).await?; assert_eq!( leased(&runtime, &old).await, Err(CredentialStoreError::Unavailable) diff --git a/product/runtime/auths-gateway/semantic-closure.json b/product/runtime/auths-gateway/semantic-closure.json index 112722939..8dc26813e 100644 --- a/product/runtime/auths-gateway/semantic-closure.json +++ b/product/runtime/auths-gateway/semantic-closure.json @@ -1 +1 @@ -{"files":[{"path":"Cargo.lock","sha256":"c94ed342774d5e2823f01ecf74b8a4812c5f9a6b0cf811d31f2e2cecb671a275"},{"path":"Cargo.toml","sha256":"6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24"},{"path":"core/adapters/auths-did-keri/Cargo.toml","sha256":"86ba3e3f9a0a70d970568bfb3113b7ba7bbdd81c3eebbb52743dd574a0c0ecaa"},{"path":"core/adapters/auths-did-keri/src/lib.rs","sha256":"a75674842f8a7142004369ccd206ab43e476459293f0ff4bed4d4e659031b3e3"},{"path":"core/adapters/auths-did-key/Cargo.toml","sha256":"d5a3ae07ecde83f91eed4c3785051dd0f44eab6c891754f3309b6b40596707d7"},{"path":"core/adapters/auths-did-key/src/lib.rs","sha256":"b76a3f4528a725df53cfa9242e6e414e1d26caa48468aaed497e28b121f4497c"},{"path":"core/adapters/auths-raw-key/Cargo.toml","sha256":"f49616bc18c19e6aaa7e6a02ccebcdb9f5c1422c1278ef9869e0dbf22ceda7be"},{"path":"core/adapters/auths-raw-key/src/lib.rs","sha256":"45eec1b295dac3bed65cd79c942870b926b06b3f5d38eaebaeb6140ac69315fa"},{"path":"core/crates/auths-algebra-kernel/Cargo.toml","sha256":"0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba"},{"path":"core/crates/auths-algebra-kernel/src/generated.rs","sha256":"ae4bcbef42a408c7ffa0c6a74a42f7de177a6f14479e51d205acf830bda05960"},{"path":"core/crates/auths-algebra-kernel/src/lib.rs","sha256":"6654667eeb9b353d6648954c9fd2e8838462a82ce6b2803eb49e1366892c68c6"},{"path":"core/crates/auths-assurance/Cargo.toml","sha256":"afcb12a97ddd09d7a264b9ecd3fcaefc865ff2c9b4539ee85b00883420ba333a"},{"path":"core/crates/auths-assurance/src/lib.rs","sha256":"0fb2ec844d674b25a9e20b1601452c89c2454901fa506adfa9bb38ef9a7fa213"},{"path":"core/crates/auths-author/Cargo.toml","sha256":"1e6f0e3bc079ddb558decf0db26b291c6e72fc47327b6df1b7650d41689b215f"},{"path":"core/crates/auths-author/src/lib.rs","sha256":"e14475f2f49715a1869d5fa6b11ff1fbb72497e39097e09f833b0bae7e5b3f2b"},{"path":"core/crates/auths-author/src/observations.rs","sha256":"dda7d6bfa6f4bd7e95a480ca283c2c0e996f69c5c15cb0c7197af328131a7066"},{"path":"core/crates/auths-authority/Cargo.toml","sha256":"4f68212938029f79ebd857b4f3038494eb85d0163d49f07e51376715cf959815"},{"path":"core/crates/auths-authority/src/lib.rs","sha256":"da88d5194de4e17449e69972c0fb042afa3c39798a8f570f30771e77c384f1eb"},{"path":"core/crates/auths-codec/Cargo.toml","sha256":"e20e51826e17814effd9d8925d18d5fbdd6c0d37bf50231e743ec2611314722c"},{"path":"core/crates/auths-codec/src/approval.rs","sha256":"fbff43bf4d57f69f8b7738a8647751cde75c5a932dee65d924a1fe9c7202f91f"},{"path":"core/crates/auths-codec/src/bounded_policy.rs","sha256":"d21f6728be2d8a04b6d94921f2b683f7e61cbb42e0ac6866f1c88a49caa534c3"},{"path":"core/crates/auths-codec/src/decode.rs","sha256":"ba2999584cdf53b1b517ecb9c7ea50d39efee17c666a9a38e2ad1ac94379f778"},{"path":"core/crates/auths-codec/src/encode.rs","sha256":"8491192053e2e15d62b4d2a491de22405b7487ead69ab6f6bca40669ce7ca5f7"},{"path":"core/crates/auths-codec/src/error.rs","sha256":"fecb0737c16deb42d859f1dc7727c698438d9ac12064fd99e0024629642c390c"},{"path":"core/crates/auths-codec/src/hash.rs","sha256":"f88e111f1dbb2cef6b7b5e9c948cb45ff92e366710c8a5f5c636138aa748479e"},{"path":"core/crates/auths-codec/src/lib.rs","sha256":"3b0e5c94c6f34f750b88a9333e1d5c8145746d845d3a23e0d2f61807cf592ea7"},{"path":"core/crates/auths-codec/src/observation.rs","sha256":"38328b0c71ff97a4196eeade8b4faa889527ff1f80bb168468bcd49082a3987e"},{"path":"core/crates/auths-composition/Cargo.toml","sha256":"331e13025eb82588b5269ed3975929eb41c823d588c49e4c296273d85c6fe80e"},{"path":"core/crates/auths-composition/src/lib.rs","sha256":"e42e3b0b6a9985b73c533aeb23799c638979aa27a9ce7d0f10a8d60340570fb1"},{"path":"core/crates/auths-model/Cargo.toml","sha256":"565c15302b0cc9270db1e28efa3862804846850ba933cc17aea8abcec4a65987"},{"path":"core/crates/auths-model/src/approval.rs","sha256":"54cf44a9ef747ec21546a4086aecfb130bc7803b0d646430e6082df51e6e305f"},{"path":"core/crates/auths-model/src/bounded.rs","sha256":"f90496abc0a06c028b4d850af6ddab7d850bfafeaa3d042f1b1246a41d8bbbc9"},{"path":"core/crates/auths-model/src/bounded_policy.rs","sha256":"306a8f049cc7cfc7635fe0e4de47eb7813eed63d3c14c3be2b51586aa4eea450"},{"path":"core/crates/auths-model/src/lib.rs","sha256":"e7cfe6bb9574c6b016aa63e70658c31e0b90903ec6479a49f4a2ceb64f5bad97"},{"path":"core/crates/auths-model/src/observation.rs","sha256":"b3ed3e3cc090afca2896a7d3de7988afccc1ee1ea0ebd91b51a8bc0f20ad8dbb"},{"path":"core/crates/auths-multikey/Cargo.toml","sha256":"858756c1197befcada06134742bffe8d58cf674cadd6c046bf710570e96efaf2"},{"path":"core/crates/auths-multikey/src/lib.rs","sha256":"f5177fffb11e40eeaaa665ba886c541fc1f24d5eacdd6983fb03dc20148733f0"},{"path":"core/crates/auths-ports/Cargo.toml","sha256":"596a9b0f5af3717c16a6d13f7054d8a106bcd9f01f5f72c2235dd2afcf0ab16c"},{"path":"core/crates/auths-ports/src/binding.rs","sha256":"a16c012d40aa4249e3ec54372b9611006d0bfe8c7dc3c741911c2194ad17736d"},{"path":"core/crates/auths-ports/src/diagnostics.rs","sha256":"aa596572503b5a65a918bb2ff38281c144ff53821ee914e9325c852828d852df"},{"path":"core/crates/auths-ports/src/lib.rs","sha256":"8da1debf86f9532df0660155d04298beb1ba3a1204508f8586e2e67cd2fb3449"},{"path":"core/crates/auths-ports/src/path.rs","sha256":"b68fc547b4e4d97a60cbbc1cc1939fc6b34a8233b81f840bd396914a707e3ea1"},{"path":"core/crates/auths-raw-key-core/Cargo.toml","sha256":"98c0bc8527a537512e43a74dd6ba9658c6f0cdc16610cf938e3f9b43785d836d"},{"path":"core/crates/auths-raw-key-core/src/lib.rs","sha256":"98c0500c41697aae28708ad0bf970b9a97583d96a3d2c18d23e7fa351e0f7d12"},{"path":"core/crates/auths-registries/Cargo.toml","sha256":"590e49e58b0622d9d6274fea46796dcdb07dec9550eff295cce6a6427ffa51e2"},{"path":"core/crates/auths-registries/src/lib.rs","sha256":"450d3886d85ee333b7e046317fb5b47cde62483d5f3e41d46265e2caf4c373ec"},{"path":"core/crates/auths-registries/src/template.rs","sha256":"1224039dd2b3ce6fa8357613d8cafbae40400493da7176da202b9ade62fa05e4"},{"path":"core/crates/auths-signature-core/Cargo.toml","sha256":"6bee2230eb30af1be0bd5c2d57bd3e1903497a70028d47290d4ac6e9e0e8bca0"},{"path":"core/crates/auths-signature-core/src/lib.rs","sha256":"6e3f9311ded5e49ea50d445eb21e6d8fa12442aa4362a73e0cb6fda15b7cd865"},{"path":"core/crates/auths-signature/Cargo.toml","sha256":"7f7b5682466ba439d8c59579022cb61068cad9fb4bd2d73e1cc21327c902b450"},{"path":"core/crates/auths-signature/src/lib.rs","sha256":"b3d9ac4cc3ba0797b9e1c09f2d6ac05089b25dac4e285a5af28c0165b33d925b"},{"path":"core/crates/auths-verifier/Cargo.toml","sha256":"c43358e06a33324b41a8b93e5cc7279c55f7d21f1f6cfaa539a3fc7b4c27a38f"},{"path":"core/crates/auths-verifier/src/approval.rs","sha256":"c3cae6a49e169051eb555bb092b1069a4d422516d6a2114623a89e5f31ff923f"},{"path":"core/crates/auths-verifier/src/causal.rs","sha256":"9635230f33b13a263573d319ac8a1976addbcc07677514a43e3c7bf28dc04587"},{"path":"core/crates/auths-verifier/src/lib.rs","sha256":"f22dec38dfa47ced8da4f605390da8453273bee1da010f57fd1fdfcb10e0b389"},{"path":"core/crates/auths-verifier/src/observation.rs","sha256":"0bb07f06a0f9524c88427df1c972b1de8ba038a9eeeb15d3134c25125ae84b1e"},{"path":"core/crates/auths-verifier/src/trace.rs","sha256":"2213d72023a1d9e0413a2cf2c51c3dad9e04775d86033a0caaa9d29a8f0036f8"},{"path":"exchange/crates/auths-proof-exchange-model/Cargo.toml","sha256":"34b2db64f93a288e942b5a3918d28cdcbef906e0dc9074ce848018d3d5f7a1fa"},{"path":"exchange/crates/auths-proof-exchange-model/src/lib.rs","sha256":"49fac5aff2339d3a57c41cb8bb2a82852538e8f77ecc4b157c88e264ff31fb55"},{"path":"exchange/crates/auths-proof-exchange-port/Cargo.toml","sha256":"7ff660f1b7579dc570c791090aeb450404fbbf44c92781e289f5ccdde746d739"},{"path":"exchange/crates/auths-proof-exchange-port/src/lib.rs","sha256":"b408fb40c6432edc1facb3d8b3e9433a033f8dc73fe2e0ba5a88c972ca675021"},{"path":"product/config/auths-config/Cargo.toml","sha256":"e4b568ab9f6d84f7d7e6d66443fe825f360db9c27bc7c31d6ddc0647ba3ab304"},{"path":"product/config/auths-config/src/lib.rs","sha256":"fecf00ea65cef9018fda9af2063326d7065b869266d0d9e73a4f06816f1102cc"},{"path":"product/errors/auths-errors/Cargo.toml","sha256":"3b3a199b6460ba75bda84475bb5accd35e1485448a3981038db85bf4772dd350"},{"path":"product/errors/auths-errors/src/lib.rs","sha256":"7feeb9069fa4003f94f1f07c1c94619cf1c883e0dbaaf2187f04d0f742264bdd"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/Cargo.toml","sha256":"716f1f2a117d6d69d8effe9ee9057e24ba3502f20af6a602b06facb638cdabed"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/api.rs","sha256":"b3c4321e0737835ecc4f17235d7589b7f3d62180954ebb98ea9449252300245a"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/clock.rs","sha256":"73f0a6e0f5903883329fa6683f5888288f759512ac69e5c87efd2b6b87f7d79f"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/http.rs","sha256":"14c1fce14e24c984b2a275563a29b6326fb08367922b6e8d37ba38b9cb81aa2b"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/identity.rs","sha256":"186de11230c8b33375951c4368609f8976bf9795f171af3fd7fac26207a94361"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs","sha256":"881ad9ccca369b6eaa6bfd9ec03b1585bff07b042da38942ef57154839449d3e"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/names.rs","sha256":"41bb23572d6002e23ee103d6fe70ecd68764861c6f2e48a1c53af998270a4afa"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs","sha256":"39fed883f4802e68d3b41a68fea0aba0737810996b33d13577de70faba004c29"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/store.rs","sha256":"fc60ee9c49b2f4f063c449b4c78100c5c4872779e94ca168f796603b380ef6e4"},{"path":"product/integrations/auths-custody/Cargo.toml","sha256":"1e14034185ad1ec24a977fd5f41d0abee219606245c046ce2a82287fadef448b"},{"path":"product/integrations/auths-custody/src/conformance.rs","sha256":"8ed1afd58f18fc6becc268908aa6419c9aa404c79da0197963eb2599df44acf6"},{"path":"product/integrations/auths-custody/src/key.rs","sha256":"70cbb0fd21b6f5652157845a22c35be2d0f6c05b3d138fc4b9bb6dbdc3d81c40"},{"path":"product/integrations/auths-custody/src/lib.rs","sha256":"8ee593c1f59b0fd2126bdda9138026f5bc531beb64d4489a99785842e7b98b43"},{"path":"product/operations/auths-operations/Cargo.toml","sha256":"73dde1e914ba5e1386f8d49c0d730423cc72ae77ec44c6554a6a75cc8e8922b1"},{"path":"product/operations/auths-operations/src/explanation.rs","sha256":"b4a39bcbd5712cb9e735ee7deeb281f3fa6af5ddca973735bf3d87dce427ef11"},{"path":"product/operations/auths-operations/src/lib.rs","sha256":"3f401a56555113b98f57bca172a2660eaecedf76247b83a3fdbb089c133a29cd"},{"path":"product/operations/auths-operations/src/render/json.rs","sha256":"2ae042639960afee123730e945d373bc5dda1d2b3af20ae16c939a7e99b9e418"},{"path":"product/operations/auths-operations/src/render/mod.rs","sha256":"b3b7f6fe473f49227ace5a68bfc3d8dc14b5db8dd9888fd9e207070337b1b8bf"},{"path":"product/operations/auths-operations/src/render/text.rs","sha256":"f216cf3bdb00e264523271b16e7059535ac6b1aabf271cebd7935af155e4bfec"},{"path":"product/policy/auths-bounded-policy/Cargo.toml","sha256":"babd5d200923137ead71d8c2528f847cea323ce98da942a1320b054436612c47"},{"path":"product/policy/auths-bounded-policy/src/arithmetic.rs","sha256":"75e43c5d4eab8d1f71c1daf53839f5f9fe45a400afc1f63a30c6f55ce3632627"},{"path":"product/policy/auths-bounded-policy/src/commitment.rs","sha256":"c5706f2d583454e1a7f570f7ada138d4d864bef0205dfae7c1296774f396bb3f"},{"path":"product/policy/auths-bounded-policy/src/eligibility.rs","sha256":"c9acdfb793074e687fc36efad506be27dbd99ffbf40387bc66c8de39ef238432"},{"path":"product/policy/auths-bounded-policy/src/identifier.rs","sha256":"0006a32bae9eb16c4178cf797df418d2b0a781f2bc6474b741dc1a908141831c"},{"path":"product/policy/auths-bounded-policy/src/kernel.rs","sha256":"99187c28b161ac70bee1afed60711f7f645adb4d1671a01863f9849b369811d5"},{"path":"product/policy/auths-bounded-policy/src/lib.rs","sha256":"76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c"},{"path":"product/policy/auths-bounded-policy/src/receipt.rs","sha256":"3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad"},{"path":"product/policy/auths-bounded-policy/src/registry.rs","sha256":"4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0"},{"path":"product/profiles/auths-profile-api/Cargo.toml","sha256":"7ae85761f58625b5d678f961fd052eebf3e000ef565c7312e3ac857763c0017f"},{"path":"product/profiles/auths-profile-api/src/lib.rs","sha256":"a194b82b20bf8aa864c2334ef6c6aec30b2154ded972862252d5dcefa488ab95"},{"path":"product/profiles/auths-profile-mcp/Cargo.toml","sha256":"db264fc25242f7b7e4133cbe5782545b3107b406c87168ae072683cfb59eac66"},{"path":"product/profiles/auths-profile-mcp/src/arguments.rs","sha256":"a5de696586d507e2aee4a49fee99ef1ef4c51a2e46603f8838f1af6d9009833f"},{"path":"product/profiles/auths-profile-mcp/src/lib.rs","sha256":"d0f8b733a09ef8408336cdebc8948d6a5861012ce6878598b11be7084dfd4280"},{"path":"product/profiles/auths-profile-mcp/src/session.rs","sha256":"166c281fa66333388e4760d6098dad02d3359e1d5de4b8f93312c014f97abb03"},{"path":"product/qualification/auths-recipe-qualification/Cargo.toml","sha256":"b7b15b30b9a3d96d4f089d514266d3a892de6608d30707aa44be31cca89ca9fe"},{"path":"product/qualification/auths-recipe-qualification/src/canonical.rs","sha256":"30a9b50777f0dcb4b606abfee2467d5a975d9f6ad941ab6c13ca3df5b359f667"},{"path":"product/qualification/auths-recipe-qualification/src/closure.rs","sha256":"0ad6aee9bd981e2863fa725f209ec84031db2ff12f4c7ac3aaf5120f0bb86039"},{"path":"product/qualification/auths-recipe-qualification/src/error.rs","sha256":"52d5cf720a1e4579008fdda90a3ac2c31f0b8db57985f121f65e54b4da2b7dd1"},{"path":"product/qualification/auths-recipe-qualification/src/evidence.rs","sha256":"1a4cb862f725b02f9efd827db99637ea8178a5236aa020ec271a363edbe7b362"},{"path":"product/qualification/auths-recipe-qualification/src/ids.rs","sha256":"e81a906d571497ab2da753e1532d4443706410e0b75fdd59a7d2d788c7aec403"},{"path":"product/qualification/auths-recipe-qualification/src/lib.rs","sha256":"195b19f46e1e94a0f3594ad5958e5715bc5e3ad415bdfe6428dfc1b6dd3f4631"},{"path":"product/qualification/auths-recipe-qualification/src/model.rs","sha256":"3484eb0ec287b23d4682ade7b1b0f8d1335985b3fb180f06fc28716076957d5f"},{"path":"product/qualification/auths-recipe-qualification/src/release.rs","sha256":"d816b53e2275e902c750ad03803061844e259e28560ab2d1c77e8a43981a4d6a"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/mod.rs","sha256":"7f15b68e05a04f202bcb1fb80de1d9a9a4fda8bfd6af2cd4e5c660fc75d96fe5"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/schemas.rs","sha256":"c59feec2805621f341a90f81fc005e2c12f7a70f9d264fdeacccb2be4fe1c046"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/verification.rs","sha256":"6a6b5834c5dae10af1ba8939b2deae43b85db71544dc8f077ff63b7fe68ac8a8"},{"path":"product/qualification/auths-recipe-qualification/src/verify.rs","sha256":"edd33589c54fb79bcfccc4cf4e6ccf95bbca088318bb7f8dfc27da684b4fa671"},{"path":"product/receipts/auths-receipts/Cargo.toml","sha256":"6001fa1375899953aafcb07c23a6da0c8f57ea7ec08bb9c950b12a60a8cc6f0f"},{"path":"product/receipts/auths-receipts/src/disclosure.rs","sha256":"ba9ed439be0a320c8a01f5b6e9b51361c1a37e076947490d8e4a484ba6bb119c"},{"path":"product/receipts/auths-receipts/src/lib.rs","sha256":"547a57c4160256719cafb7d0ab972d9fc80b0da14fbbce4148c70c414070ff36"},{"path":"product/runtime/auths-connections/Cargo.toml","sha256":"babeb6e1dda3dfb66291713ce1e43dce5c349833d0b50ea4dccbf986030026b2"},{"path":"product/runtime/auths-connections/src/credential.rs","sha256":"82921413bb053f0f6c7931fbd4e6a86c8cc1d8c6b51debd9c2cef33a8d5b1c51"},{"path":"product/runtime/auths-connections/src/kernel.rs","sha256":"a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8"},{"path":"product/runtime/auths-connections/src/lib.rs","sha256":"79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22"},{"path":"product/runtime/auths-connections/src/model.rs","sha256":"de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77"},{"path":"product/runtime/auths-connections/src/registry.rs","sha256":"e57640e003e72ad3235c567c2bb944a262bd64e673f023b62ea091094cc7e946"},{"path":"product/runtime/auths-gateway-kernel/Cargo.toml","sha256":"34f864e67656af4ac7e5c7a347a23f01fc8ab31365b8e23c0ef474483b14a183"},{"path":"product/runtime/auths-gateway-kernel/src/construct.rs","sha256":"e9d65744bae273d65face4285e5d2da75c06a92ab48f7b8333d496604e31c63c"},{"path":"product/runtime/auths-gateway-kernel/src/lib.rs","sha256":"cfda6f8453426564c085475f183b6f790b438768a19668f1b65d33ba59dc8632"},{"path":"product/runtime/auths-gateway-kernel/src/order.rs","sha256":"e0045f877c4b7fe3860c291039853885064ddcdebba7c9b345ab65e81e646dda"},{"path":"product/runtime/auths-gateway-kernel/src/outcome.rs","sha256":"e9785b1afe70788c89b51b18655bcd5acff7b0c8e3d12fb79c6f05a202e67e6b"},{"path":"product/runtime/auths-gateway-kernel/src/ratio.rs","sha256":"7ace22264812e6fc1ef3a62afee402cf43494bb71ae0d3de219ad1b39d690bcb"},{"path":"product/runtime/auths-gateway-kernel/src/recovery.rs","sha256":"9f46dcd1685ab6e4d1ba04a3fc286a9f3afee8fb47829be1fbc670a7926a2dc6"},{"path":"product/runtime/auths-gateway-kernel/src/transition.rs","sha256":"cefb8f01d915880f6921f2501ff881ad94b9de61072c34d9cd19220992f97374"},{"path":"product/runtime/auths-gateway/Cargo.toml","sha256":"00b28be86921dcdc0ad90cce0c62c2961cafefe96ea6c2edf0e926c3d405ccad"},{"path":"product/runtime/auths-gateway/src/admin.rs","sha256":"2d5cc67afac42fbd15f36e2d1693cd1b20cedacf775040dce6ffe04ccc94c9ea"},{"path":"product/runtime/auths-gateway/src/app.rs","sha256":"6f80f63833ea0815bb44fbf3b0cc54624a08e9fb578b035819f2980dc04e8256"},{"path":"product/runtime/auths-gateway/src/audit.rs","sha256":"0edb2037eb7b5d6f13acfce85c54f62a82bf7fdd31bc7e626c4fec183cef61dd"},{"path":"product/runtime/auths-gateway/src/audit_tests.rs","sha256":"990969384a52d75bc2489d9d412a9e7dd814bca1c8f65c701d6205fae62a15d5"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway-harness.rs","sha256":"12b0c24d36b2e6a3be392d3c081a783b355fdd67dc5b54bacc0410e803116b8c"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway.rs","sha256":"9f4b46006fbc28a71c07f14f1f40837782407628c094d7c17f216f9be75e2dde"},{"path":"product/runtime/auths-gateway/src/binding.rs","sha256":"663b0ce878319511aa7d05722ab4ab2fa9be18817884ffb2ee9f131ff1e382d1"},{"path":"product/runtime/auths-gateway/src/bounds.rs","sha256":"9cfa0eae4973e5e047a198360b22f041708fa20276b0b90c2ec440f06915d64b"},{"path":"product/runtime/auths-gateway/src/bounds_aggregate_tests.rs","sha256":"ab34f227b7c8692ba1da88ccb32bb3687a66adf8353d8282fae905d4a88eb612"},{"path":"product/runtime/auths-gateway/src/bounds_tests.rs","sha256":"74136bc570da7b9338b5a1a1ed9d3fd892c55135160964f9d3ac0e2cf5741375"},{"path":"product/runtime/auths-gateway/src/connection.rs","sha256":"7b5d049c258a26ed1c93ecf860f51d051a8a65f9b93554af0b1ea93862398ec9"},{"path":"product/runtime/auths-gateway/src/credential_journal.rs","sha256":"8e2b0733038d93ca5df770d27a870237e3b65664fa48da017d964a65bbbe25b8"},{"path":"product/runtime/auths-gateway/src/echo_verify.rs","sha256":"6d453051665f823abd7354d5c50031d9524cf47d6092d2f09080ae814e3b9575"},{"path":"product/runtime/auths-gateway/src/engine.rs","sha256":"a9f71575994ff21633ddfc533b1d810515db71aa0146fa8869dad72eddcb2a12"},{"path":"product/runtime/auths-gateway/src/fuzzing.rs","sha256":"ed3b0028487eb546a3b0a91d115aa8f18bcea324b61620bfe8e35a9e6ab18758"},{"path":"product/runtime/auths-gateway/src/generation_floor.rs","sha256":"47964a5f1ca2fc9c4da0b526b6d5c5637fc0ce1d2e429219d02f1b0dc652fdff"},{"path":"product/runtime/auths-gateway/src/harness.rs","sha256":"c87e479f3eb281960f6c9c80d43c7560d7ccb654b0154ec823d3fcec4884ac05"},{"path":"product/runtime/auths-gateway/src/lib.rs","sha256":"b182052835a2cd631d1f801a74788d6ac1ef9cae21ade9ab4ffc270cd6f667ed"},{"path":"product/runtime/auths-gateway/src/listener.rs","sha256":"aa08239bcbc1fcb55e8a212fbdf6a84f12985b0d436dcb51dc58b06e59e435f2"},{"path":"product/runtime/auths-gateway/src/observed_tests.rs","sha256":"a22be071695f89ca2578a4d82fd80d9cb82289213c9bdb8f0470f6b2dc3d9201"},{"path":"product/runtime/auths-gateway/src/observer.rs","sha256":"562ffcaea071c3856e0708dc2fe33516917e145d2438aabb75af0a2b6ba01046"},{"path":"product/runtime/auths-gateway/src/onboarding.rs","sha256":"0dfd7d67e7f02f18a28d1c86ca1b7751d7463f5efcdbe3825de0ad8cbccb3891"},{"path":"product/runtime/auths-gateway/src/operator.rs","sha256":"c3c36954a3e86723df035b47f43b85fc8ab3a6292983522b6258d5c6b4e6c4e4"},{"path":"product/runtime/auths-gateway/src/pending_vectors/attempts.rs","sha256":"47ef3c8cb1c5504d47ae9a0088705ce6715fe86bac1671a34a56fb38a64d0dd3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/bounds.rs","sha256":"e612217307e1da5b0eb5ee6582a7458bb064b8aa8a529fc6555b1b334127ab68"},{"path":"product/runtime/auths-gateway/src/pending_vectors/codes.rs","sha256":"e00670a5ef24eb856cc2c6dcda8e5a263842f55c76bb939c0c27bd9df37e5522"},{"path":"product/runtime/auths-gateway/src/pending_vectors/keys.rs","sha256":"f84c56f2ea9cb34b2b79c72d13fbf2c6585010ec1ed450af58a78c80c1ea1edd"},{"path":"product/runtime/auths-gateway/src/pending_vectors/mod.rs","sha256":"5de8340f0ef71a0b57a09e323fefe473d3160c6ae952b9ba46f714825fbacafc"},{"path":"product/runtime/auths-gateway/src/pending_vectors/outcomes.rs","sha256":"8ec07b9511b48913af36ac999d2aa0e82924289f6acb23ddaeb9f00f99815166"},{"path":"product/runtime/auths-gateway/src/pending_vectors/production.rs","sha256":"c2fa18b5d96c87689fe60d95faadebe2c7fdf5b78be872ca15a67ad980106ed3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/recipes.rs","sha256":"51693208270231c25c3aef2a32151d5962114c71e86b88cb9df83181c7af83d9"},{"path":"product/runtime/auths-gateway/src/pre_entry.rs","sha256":"06ea78ca140468bfaba17d9ab04912ad68673954c3203c98fed28272ff2a00c0"},{"path":"product/runtime/auths-gateway/src/property_tests.rs","sha256":"939c081e2e154aaf10186754044bdd65608932c899b970a04a71d0afaa999a93"},{"path":"product/runtime/auths-gateway/src/qualification.rs","sha256":"a4398512ccb7bb494000fe38f03e0faa7b82d1f80ef5ee2dfa75698ae4f5a9be"},{"path":"product/runtime/auths-gateway/src/qualification_tests.rs","sha256":"4473add5729b97faf04d7be7fd8cf3bbacd7f545e1b61c7d2782563011906b4d"},{"path":"product/runtime/auths-gateway/src/quorum_tests.rs","sha256":"a78380b019104d688c11a4410082c7e08ded3106aab099954c4f8a1b4ae0fd89"},{"path":"product/runtime/auths-gateway/src/readiness.rs","sha256":"911c3f11892f94641574375e2da4c671c802738f71082f12c39832331052d43d"},{"path":"product/runtime/auths-gateway/src/recipe.rs","sha256":"fecf9af67e7afc48d080e9f8f55f8ce28e49d0e08988717a27908bbda461d6b6"},{"path":"product/runtime/auths-gateway/src/recipe/lower.rs","sha256":"8088b8751ed831dbb48247af953c6290ac95e2a438ccd5bd65eff54be06a1fd1"},{"path":"product/runtime/auths-gateway/src/recipe/review.rs","sha256":"c3eb7d9fdd98dacf52750b14b67ad7b7faaecbbdeafff1e0b049f67d0a2d0139"},{"path":"product/runtime/auths-gateway/src/recipe/runtime.rs","sha256":"c286f0d15f974402822c0810d8e97f98411dc1c557755cc23e540d85e2bb42d9"},{"path":"product/runtime/auths-gateway/src/recipe/source.rs","sha256":"1af50298fb1461e1b24cbdf560d43124d6b1c4c529586c911b1c4797214a69ff"},{"path":"product/runtime/auths-gateway/src/recipe/tests.rs","sha256":"aac551a2481bbc60864c64079bc667dcb232e45a0f41a04073ed84ab5dbe1fce"},{"path":"product/runtime/auths-gateway/src/recipe/validate.rs","sha256":"3711b17605cb7b0d639bc1b180449231f5882a306cab20e2c7782155cc63b0d4"},{"path":"product/runtime/auths-gateway/src/scenario_tests.rs","sha256":"d8271761b12597bfe1233f8eb5ad1d4e5498c5d03388e832e24ab818484a1de4"},{"path":"product/runtime/auths-gateway/src/separation.rs","sha256":"be9306848ca5d801767cf6aa14247c8618312ef0e202f00ce0c24c4844491061"},{"path":"product/runtime/auths-gateway/src/store.rs","sha256":"1e5288345c2cb1421aeda277b3158d07607404b0ec46943222ac107b63dcbb46"},{"path":"product/runtime/auths-gateway/src/store_testkit.rs","sha256":"88d82fee42f1b8ef521e8deef0216e938ebeaad822eb2f5020e70b89d145ea70"},{"path":"product/runtime/auths-gateway/src/submit.rs","sha256":"c78dbbba7c45b443febf655056c5edcd635e77be7b21c5b2c318097502415ffe"},{"path":"product/runtime/auths-gateway/src/support.rs","sha256":"33c87008b6643e3e595e5af0c221ee5460df69e17cc69be2edcae13474d0cdb9"},{"path":"product/runtime/auths-gateway/src/transport.rs","sha256":"be2c6dc75b8daec110bf8749fedc3823f6067d40b999aa3eb21126896a97d3ad"},{"path":"product/runtime/auths-kernel-runtime/Cargo.toml","sha256":"926bcd0053e5edd703be8f0027ad009e2982db013c8174c1366edbf38b48087d"},{"path":"product/runtime/auths-kernel-runtime/src/lib.rs","sha256":"7108faae9ca4bc32dc093ddaf885ac8f74f3c9b8d317b7c7d0ed00d1d0ab5972"},{"path":"product/runtime/auths-lifecycle/Cargo.toml","sha256":"c5053c705f8d5554b44e432fe75287a2faf11d644e5a2552e45ad6cd94176af5"},{"path":"product/runtime/auths-lifecycle/src/codec.rs","sha256":"51c4b746749150e8bfcd8ff972b3f6c1ef40bec15583448ec1b471d9ad737dc0"},{"path":"product/runtime/auths-lifecycle/src/digest.rs","sha256":"55282cd7d8aba37713c2dcb5357c9877819edb72a30eadefb860d28d7d3a3eb7"},{"path":"product/runtime/auths-lifecycle/src/identifier.rs","sha256":"31620e8c16de68d3d2d3b84d6353c1a5b9d4151d8247f91fa389b906a8e660f1"},{"path":"product/runtime/auths-lifecycle/src/kernel.rs","sha256":"2abb8c094b36d35b364e74d78091d14c5d6f3d1eb6552cca3b5538dbd017ce23"},{"path":"product/runtime/auths-lifecycle/src/lib.rs","sha256":"afe5a345cd309b5a4f08ffba3170a6d7f16ff914892b3f2006d5208ed24ec736"},{"path":"product/runtime/auths-lifecycle/src/model.rs","sha256":"1af12bbeeeaa65ec02ddcebd7d2c8c92ec1e339fa40ae85b45ab9b01a722a4fa"},{"path":"product/runtime/auths-lifecycle/src/operation.rs","sha256":"78e6d05fcf5d7ea4f148032a3fa26fdfcab77eb346019effe927b08e0d64d732"},{"path":"product/runtime/auths-lifecycle/src/registry.rs","sha256":"53495fe6f7a77422593a41623e28716f1c140dcc1e00f87f6b0ffbfb93a5ef90"},{"path":"product/runtime/auths-lifecycle/src/sealed.rs","sha256":"2e0c03b5813c926c159598bb7890d1523825edbe57cd687d42a5dfb3374a0c19"},{"path":"product/runtime/auths-lifecycle/src/test_support.rs","sha256":"221d9a5c5ef8e1f9f8fd66927484eaf813571d0568470278ecd8fa08a5eec8cd"},{"path":"product/runtime/auths-lifecycle/src/transition.rs","sha256":"011805a28efdd541f44ccea54dd0e34a1e58f4004447ee58013703b4fb6b2822"},{"path":"product/runtime/auths-runtime/Cargo.toml","sha256":"dd29d80a8b4bb56c869f036a6c9998f6e6d1c0383ac5dc03fa42b24abe2a7ff7"},{"path":"product/runtime/auths-runtime/src/lib.rs","sha256":"132ca03d58c14905d3a822a4972f42a22a5ad33a45f2ba9ca44f3a57d810b4b0"},{"path":"product/runtime/auths-runtime/src/production.rs","sha256":"fd4eff4270c571c10fcff6cf27df28961ebf074de8a1a028f500fda1ca376820"},{"path":"product/sdk/auths-approval-quorum/Cargo.toml","sha256":"df904971fca87a24194c5816738a331588fe8f164acb5d70839a35dca5f57114"},{"path":"product/sdk/auths-approval-quorum/src/lib.rs","sha256":"72e4086088a1c0912e4e1a9e980f26a5c280bf5ab16ea39c9f0f58d5096ac2ce"},{"path":"product/sdk/auths-approval-quorum/src/remote.rs","sha256":"9fa029c7c63003adf260f8aec55160c545681c60c1bace0d934e7525862aac7b"},{"path":"product/sdk/auths-approval-quorum/src/remote_tests.rs","sha256":"8a09ce17cfee82a035a74edd535f3ebeb3db0e078784740d3997b17dbdb10197"},{"path":"product/sdk/auths-approval-quorum/src/tests.rs","sha256":"0acbf12be3e497dcc6c2d8f29c9af3b1a7ed8e11b75f6399570d4f217a785060"},{"path":"product/stores/auths-stores/Cargo.toml","sha256":"a32c4b76d17b264be5d40d24497ff237e1ed87822e8bab86229b3db93106dbe3"},{"path":"product/stores/auths-stores/src/gateway_attempt.rs","sha256":"185da8f4a220fba836d5b78a9311f03204681c43a3c53951008084d135bf4d21"},{"path":"product/stores/auths-stores/src/lib.rs","sha256":"e721262edf8a9ab5568ddc27639176312d4a366203b5f73e2d7c11fde2c554e9"},{"path":"product/stores/auths-stores/src/lifecycle.rs","sha256":"94f64d25bc178a9e60ba3c0ee6915d7fb3af7c4468792d76b4e70f43f4de1e2f"}],"schema":"auths.gateway-semantic-closure/1"} \ No newline at end of file +{"files":[{"path":"Cargo.lock","sha256":"c94ed342774d5e2823f01ecf74b8a4812c5f9a6b0cf811d31f2e2cecb671a275"},{"path":"Cargo.toml","sha256":"6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24"},{"path":"core/adapters/auths-did-keri/Cargo.toml","sha256":"86ba3e3f9a0a70d970568bfb3113b7ba7bbdd81c3eebbb52743dd574a0c0ecaa"},{"path":"core/adapters/auths-did-keri/src/lib.rs","sha256":"a75674842f8a7142004369ccd206ab43e476459293f0ff4bed4d4e659031b3e3"},{"path":"core/adapters/auths-did-key/Cargo.toml","sha256":"d5a3ae07ecde83f91eed4c3785051dd0f44eab6c891754f3309b6b40596707d7"},{"path":"core/adapters/auths-did-key/src/lib.rs","sha256":"b76a3f4528a725df53cfa9242e6e414e1d26caa48468aaed497e28b121f4497c"},{"path":"core/adapters/auths-raw-key/Cargo.toml","sha256":"f49616bc18c19e6aaa7e6a02ccebcdb9f5c1422c1278ef9869e0dbf22ceda7be"},{"path":"core/adapters/auths-raw-key/src/lib.rs","sha256":"45eec1b295dac3bed65cd79c942870b926b06b3f5d38eaebaeb6140ac69315fa"},{"path":"core/crates/auths-algebra-kernel/Cargo.toml","sha256":"0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba"},{"path":"core/crates/auths-algebra-kernel/src/generated.rs","sha256":"ae4bcbef42a408c7ffa0c6a74a42f7de177a6f14479e51d205acf830bda05960"},{"path":"core/crates/auths-algebra-kernel/src/lib.rs","sha256":"6654667eeb9b353d6648954c9fd2e8838462a82ce6b2803eb49e1366892c68c6"},{"path":"core/crates/auths-assurance/Cargo.toml","sha256":"afcb12a97ddd09d7a264b9ecd3fcaefc865ff2c9b4539ee85b00883420ba333a"},{"path":"core/crates/auths-assurance/src/lib.rs","sha256":"0fb2ec844d674b25a9e20b1601452c89c2454901fa506adfa9bb38ef9a7fa213"},{"path":"core/crates/auths-author/Cargo.toml","sha256":"1e6f0e3bc079ddb558decf0db26b291c6e72fc47327b6df1b7650d41689b215f"},{"path":"core/crates/auths-author/src/lib.rs","sha256":"e14475f2f49715a1869d5fa6b11ff1fbb72497e39097e09f833b0bae7e5b3f2b"},{"path":"core/crates/auths-author/src/observations.rs","sha256":"dda7d6bfa6f4bd7e95a480ca283c2c0e996f69c5c15cb0c7197af328131a7066"},{"path":"core/crates/auths-authority/Cargo.toml","sha256":"4f68212938029f79ebd857b4f3038494eb85d0163d49f07e51376715cf959815"},{"path":"core/crates/auths-authority/src/lib.rs","sha256":"da88d5194de4e17449e69972c0fb042afa3c39798a8f570f30771e77c384f1eb"},{"path":"core/crates/auths-codec/Cargo.toml","sha256":"e20e51826e17814effd9d8925d18d5fbdd6c0d37bf50231e743ec2611314722c"},{"path":"core/crates/auths-codec/src/approval.rs","sha256":"fbff43bf4d57f69f8b7738a8647751cde75c5a932dee65d924a1fe9c7202f91f"},{"path":"core/crates/auths-codec/src/bounded_policy.rs","sha256":"d21f6728be2d8a04b6d94921f2b683f7e61cbb42e0ac6866f1c88a49caa534c3"},{"path":"core/crates/auths-codec/src/decode.rs","sha256":"ba2999584cdf53b1b517ecb9c7ea50d39efee17c666a9a38e2ad1ac94379f778"},{"path":"core/crates/auths-codec/src/encode.rs","sha256":"8491192053e2e15d62b4d2a491de22405b7487ead69ab6f6bca40669ce7ca5f7"},{"path":"core/crates/auths-codec/src/error.rs","sha256":"fecb0737c16deb42d859f1dc7727c698438d9ac12064fd99e0024629642c390c"},{"path":"core/crates/auths-codec/src/hash.rs","sha256":"f88e111f1dbb2cef6b7b5e9c948cb45ff92e366710c8a5f5c636138aa748479e"},{"path":"core/crates/auths-codec/src/lib.rs","sha256":"3b0e5c94c6f34f750b88a9333e1d5c8145746d845d3a23e0d2f61807cf592ea7"},{"path":"core/crates/auths-codec/src/observation.rs","sha256":"38328b0c71ff97a4196eeade8b4faa889527ff1f80bb168468bcd49082a3987e"},{"path":"core/crates/auths-composition/Cargo.toml","sha256":"331e13025eb82588b5269ed3975929eb41c823d588c49e4c296273d85c6fe80e"},{"path":"core/crates/auths-composition/src/lib.rs","sha256":"e42e3b0b6a9985b73c533aeb23799c638979aa27a9ce7d0f10a8d60340570fb1"},{"path":"core/crates/auths-model/Cargo.toml","sha256":"565c15302b0cc9270db1e28efa3862804846850ba933cc17aea8abcec4a65987"},{"path":"core/crates/auths-model/src/approval.rs","sha256":"54cf44a9ef747ec21546a4086aecfb130bc7803b0d646430e6082df51e6e305f"},{"path":"core/crates/auths-model/src/bounded.rs","sha256":"f90496abc0a06c028b4d850af6ddab7d850bfafeaa3d042f1b1246a41d8bbbc9"},{"path":"core/crates/auths-model/src/bounded_policy.rs","sha256":"306a8f049cc7cfc7635fe0e4de47eb7813eed63d3c14c3be2b51586aa4eea450"},{"path":"core/crates/auths-model/src/lib.rs","sha256":"e7cfe6bb9574c6b016aa63e70658c31e0b90903ec6479a49f4a2ceb64f5bad97"},{"path":"core/crates/auths-model/src/observation.rs","sha256":"b3ed3e3cc090afca2896a7d3de7988afccc1ee1ea0ebd91b51a8bc0f20ad8dbb"},{"path":"core/crates/auths-multikey/Cargo.toml","sha256":"858756c1197befcada06134742bffe8d58cf674cadd6c046bf710570e96efaf2"},{"path":"core/crates/auths-multikey/src/lib.rs","sha256":"f5177fffb11e40eeaaa665ba886c541fc1f24d5eacdd6983fb03dc20148733f0"},{"path":"core/crates/auths-ports/Cargo.toml","sha256":"596a9b0f5af3717c16a6d13f7054d8a106bcd9f01f5f72c2235dd2afcf0ab16c"},{"path":"core/crates/auths-ports/src/binding.rs","sha256":"a16c012d40aa4249e3ec54372b9611006d0bfe8c7dc3c741911c2194ad17736d"},{"path":"core/crates/auths-ports/src/diagnostics.rs","sha256":"aa596572503b5a65a918bb2ff38281c144ff53821ee914e9325c852828d852df"},{"path":"core/crates/auths-ports/src/lib.rs","sha256":"8da1debf86f9532df0660155d04298beb1ba3a1204508f8586e2e67cd2fb3449"},{"path":"core/crates/auths-ports/src/path.rs","sha256":"b68fc547b4e4d97a60cbbc1cc1939fc6b34a8233b81f840bd396914a707e3ea1"},{"path":"core/crates/auths-raw-key-core/Cargo.toml","sha256":"98c0bc8527a537512e43a74dd6ba9658c6f0cdc16610cf938e3f9b43785d836d"},{"path":"core/crates/auths-raw-key-core/src/lib.rs","sha256":"98c0500c41697aae28708ad0bf970b9a97583d96a3d2c18d23e7fa351e0f7d12"},{"path":"core/crates/auths-registries/Cargo.toml","sha256":"590e49e58b0622d9d6274fea46796dcdb07dec9550eff295cce6a6427ffa51e2"},{"path":"core/crates/auths-registries/src/lib.rs","sha256":"450d3886d85ee333b7e046317fb5b47cde62483d5f3e41d46265e2caf4c373ec"},{"path":"core/crates/auths-registries/src/template.rs","sha256":"1224039dd2b3ce6fa8357613d8cafbae40400493da7176da202b9ade62fa05e4"},{"path":"core/crates/auths-signature-core/Cargo.toml","sha256":"6bee2230eb30af1be0bd5c2d57bd3e1903497a70028d47290d4ac6e9e0e8bca0"},{"path":"core/crates/auths-signature-core/src/lib.rs","sha256":"6e3f9311ded5e49ea50d445eb21e6d8fa12442aa4362a73e0cb6fda15b7cd865"},{"path":"core/crates/auths-signature/Cargo.toml","sha256":"7f7b5682466ba439d8c59579022cb61068cad9fb4bd2d73e1cc21327c902b450"},{"path":"core/crates/auths-signature/src/lib.rs","sha256":"b3d9ac4cc3ba0797b9e1c09f2d6ac05089b25dac4e285a5af28c0165b33d925b"},{"path":"core/crates/auths-verifier/Cargo.toml","sha256":"c43358e06a33324b41a8b93e5cc7279c55f7d21f1f6cfaa539a3fc7b4c27a38f"},{"path":"core/crates/auths-verifier/src/approval.rs","sha256":"c3cae6a49e169051eb555bb092b1069a4d422516d6a2114623a89e5f31ff923f"},{"path":"core/crates/auths-verifier/src/causal.rs","sha256":"9635230f33b13a263573d319ac8a1976addbcc07677514a43e3c7bf28dc04587"},{"path":"core/crates/auths-verifier/src/lib.rs","sha256":"f22dec38dfa47ced8da4f605390da8453273bee1da010f57fd1fdfcb10e0b389"},{"path":"core/crates/auths-verifier/src/observation.rs","sha256":"0bb07f06a0f9524c88427df1c972b1de8ba038a9eeeb15d3134c25125ae84b1e"},{"path":"core/crates/auths-verifier/src/trace.rs","sha256":"2213d72023a1d9e0413a2cf2c51c3dad9e04775d86033a0caaa9d29a8f0036f8"},{"path":"exchange/crates/auths-proof-exchange-model/Cargo.toml","sha256":"34b2db64f93a288e942b5a3918d28cdcbef906e0dc9074ce848018d3d5f7a1fa"},{"path":"exchange/crates/auths-proof-exchange-model/src/lib.rs","sha256":"49fac5aff2339d3a57c41cb8bb2a82852538e8f77ecc4b157c88e264ff31fb55"},{"path":"exchange/crates/auths-proof-exchange-port/Cargo.toml","sha256":"7ff660f1b7579dc570c791090aeb450404fbbf44c92781e289f5ccdde746d739"},{"path":"exchange/crates/auths-proof-exchange-port/src/lib.rs","sha256":"b408fb40c6432edc1facb3d8b3e9433a033f8dc73fe2e0ba5a88c972ca675021"},{"path":"product/config/auths-config/Cargo.toml","sha256":"e4b568ab9f6d84f7d7e6d66443fe825f360db9c27bc7c31d6ddc0647ba3ab304"},{"path":"product/config/auths-config/src/lib.rs","sha256":"fecf00ea65cef9018fda9af2063326d7065b869266d0d9e73a4f06816f1102cc"},{"path":"product/errors/auths-errors/Cargo.toml","sha256":"3b3a199b6460ba75bda84475bb5accd35e1485448a3981038db85bf4772dd350"},{"path":"product/errors/auths-errors/src/lib.rs","sha256":"7feeb9069fa4003f94f1f07c1c94619cf1c883e0dbaaf2187f04d0f742264bdd"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/Cargo.toml","sha256":"716f1f2a117d6d69d8effe9ee9057e24ba3502f20af6a602b06facb638cdabed"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/api.rs","sha256":"9ea61dd7ddd93282b073b98e453e6b75b26dc49689c04e9782435d06a3a09e48"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/clock.rs","sha256":"73f0a6e0f5903883329fa6683f5888288f759512ac69e5c87efd2b6b87f7d79f"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/http.rs","sha256":"14c1fce14e24c984b2a275563a29b6326fb08367922b6e8d37ba38b9cb81aa2b"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/identity.rs","sha256":"186de11230c8b33375951c4368609f8976bf9795f171af3fd7fac26207a94361"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs","sha256":"0b4617d044f5254a5ab22f5a2578f91cc025206a8c1845be39c1c56dcdf7a5df"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/names.rs","sha256":"41bb23572d6002e23ee103d6fe70ecd68764861c6f2e48a1c53af998270a4afa"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs","sha256":"39fed883f4802e68d3b41a68fea0aba0737810996b33d13577de70faba004c29"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/store.rs","sha256":"fc60ee9c49b2f4f063c449b4c78100c5c4872779e94ca168f796603b380ef6e4"},{"path":"product/integrations/auths-custody/Cargo.toml","sha256":"1e14034185ad1ec24a977fd5f41d0abee219606245c046ce2a82287fadef448b"},{"path":"product/integrations/auths-custody/src/conformance.rs","sha256":"8ed1afd58f18fc6becc268908aa6419c9aa404c79da0197963eb2599df44acf6"},{"path":"product/integrations/auths-custody/src/key.rs","sha256":"70cbb0fd21b6f5652157845a22c35be2d0f6c05b3d138fc4b9bb6dbdc3d81c40"},{"path":"product/integrations/auths-custody/src/lib.rs","sha256":"8ee593c1f59b0fd2126bdda9138026f5bc531beb64d4489a99785842e7b98b43"},{"path":"product/operations/auths-operations/Cargo.toml","sha256":"73dde1e914ba5e1386f8d49c0d730423cc72ae77ec44c6554a6a75cc8e8922b1"},{"path":"product/operations/auths-operations/src/explanation.rs","sha256":"b4a39bcbd5712cb9e735ee7deeb281f3fa6af5ddca973735bf3d87dce427ef11"},{"path":"product/operations/auths-operations/src/lib.rs","sha256":"3f401a56555113b98f57bca172a2660eaecedf76247b83a3fdbb089c133a29cd"},{"path":"product/operations/auths-operations/src/render/json.rs","sha256":"2ae042639960afee123730e945d373bc5dda1d2b3af20ae16c939a7e99b9e418"},{"path":"product/operations/auths-operations/src/render/mod.rs","sha256":"b3b7f6fe473f49227ace5a68bfc3d8dc14b5db8dd9888fd9e207070337b1b8bf"},{"path":"product/operations/auths-operations/src/render/text.rs","sha256":"f216cf3bdb00e264523271b16e7059535ac6b1aabf271cebd7935af155e4bfec"},{"path":"product/policy/auths-bounded-policy/Cargo.toml","sha256":"babd5d200923137ead71d8c2528f847cea323ce98da942a1320b054436612c47"},{"path":"product/policy/auths-bounded-policy/src/arithmetic.rs","sha256":"75e43c5d4eab8d1f71c1daf53839f5f9fe45a400afc1f63a30c6f55ce3632627"},{"path":"product/policy/auths-bounded-policy/src/commitment.rs","sha256":"c5706f2d583454e1a7f570f7ada138d4d864bef0205dfae7c1296774f396bb3f"},{"path":"product/policy/auths-bounded-policy/src/eligibility.rs","sha256":"c9acdfb793074e687fc36efad506be27dbd99ffbf40387bc66c8de39ef238432"},{"path":"product/policy/auths-bounded-policy/src/identifier.rs","sha256":"0006a32bae9eb16c4178cf797df418d2b0a781f2bc6474b741dc1a908141831c"},{"path":"product/policy/auths-bounded-policy/src/kernel.rs","sha256":"99187c28b161ac70bee1afed60711f7f645adb4d1671a01863f9849b369811d5"},{"path":"product/policy/auths-bounded-policy/src/lib.rs","sha256":"76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c"},{"path":"product/policy/auths-bounded-policy/src/receipt.rs","sha256":"3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad"},{"path":"product/policy/auths-bounded-policy/src/registry.rs","sha256":"4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0"},{"path":"product/profiles/auths-profile-api/Cargo.toml","sha256":"7ae85761f58625b5d678f961fd052eebf3e000ef565c7312e3ac857763c0017f"},{"path":"product/profiles/auths-profile-api/src/lib.rs","sha256":"a194b82b20bf8aa864c2334ef6c6aec30b2154ded972862252d5dcefa488ab95"},{"path":"product/profiles/auths-profile-mcp/Cargo.toml","sha256":"db264fc25242f7b7e4133cbe5782545b3107b406c87168ae072683cfb59eac66"},{"path":"product/profiles/auths-profile-mcp/src/arguments.rs","sha256":"a5de696586d507e2aee4a49fee99ef1ef4c51a2e46603f8838f1af6d9009833f"},{"path":"product/profiles/auths-profile-mcp/src/lib.rs","sha256":"d0f8b733a09ef8408336cdebc8948d6a5861012ce6878598b11be7084dfd4280"},{"path":"product/profiles/auths-profile-mcp/src/session.rs","sha256":"166c281fa66333388e4760d6098dad02d3359e1d5de4b8f93312c014f97abb03"},{"path":"product/qualification/auths-recipe-qualification/Cargo.toml","sha256":"b7b15b30b9a3d96d4f089d514266d3a892de6608d30707aa44be31cca89ca9fe"},{"path":"product/qualification/auths-recipe-qualification/src/canonical.rs","sha256":"30a9b50777f0dcb4b606abfee2467d5a975d9f6ad941ab6c13ca3df5b359f667"},{"path":"product/qualification/auths-recipe-qualification/src/closure.rs","sha256":"0ad6aee9bd981e2863fa725f209ec84031db2ff12f4c7ac3aaf5120f0bb86039"},{"path":"product/qualification/auths-recipe-qualification/src/error.rs","sha256":"52d5cf720a1e4579008fdda90a3ac2c31f0b8db57985f121f65e54b4da2b7dd1"},{"path":"product/qualification/auths-recipe-qualification/src/evidence.rs","sha256":"1a4cb862f725b02f9efd827db99637ea8178a5236aa020ec271a363edbe7b362"},{"path":"product/qualification/auths-recipe-qualification/src/ids.rs","sha256":"e81a906d571497ab2da753e1532d4443706410e0b75fdd59a7d2d788c7aec403"},{"path":"product/qualification/auths-recipe-qualification/src/lib.rs","sha256":"195b19f46e1e94a0f3594ad5958e5715bc5e3ad415bdfe6428dfc1b6dd3f4631"},{"path":"product/qualification/auths-recipe-qualification/src/model.rs","sha256":"3484eb0ec287b23d4682ade7b1b0f8d1335985b3fb180f06fc28716076957d5f"},{"path":"product/qualification/auths-recipe-qualification/src/release.rs","sha256":"d816b53e2275e902c750ad03803061844e259e28560ab2d1c77e8a43981a4d6a"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/mod.rs","sha256":"7f15b68e05a04f202bcb1fb80de1d9a9a4fda8bfd6af2cd4e5c660fc75d96fe5"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/schemas.rs","sha256":"c59feec2805621f341a90f81fc005e2c12f7a70f9d264fdeacccb2be4fe1c046"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/verification.rs","sha256":"6a6b5834c5dae10af1ba8939b2deae43b85db71544dc8f077ff63b7fe68ac8a8"},{"path":"product/qualification/auths-recipe-qualification/src/verify.rs","sha256":"edd33589c54fb79bcfccc4cf4e6ccf95bbca088318bb7f8dfc27da684b4fa671"},{"path":"product/receipts/auths-receipts/Cargo.toml","sha256":"6001fa1375899953aafcb07c23a6da0c8f57ea7ec08bb9c950b12a60a8cc6f0f"},{"path":"product/receipts/auths-receipts/src/disclosure.rs","sha256":"ba9ed439be0a320c8a01f5b6e9b51361c1a37e076947490d8e4a484ba6bb119c"},{"path":"product/receipts/auths-receipts/src/lib.rs","sha256":"547a57c4160256719cafb7d0ab972d9fc80b0da14fbbce4148c70c414070ff36"},{"path":"product/runtime/auths-connections/Cargo.toml","sha256":"babeb6e1dda3dfb66291713ce1e43dce5c349833d0b50ea4dccbf986030026b2"},{"path":"product/runtime/auths-connections/src/credential.rs","sha256":"82921413bb053f0f6c7931fbd4e6a86c8cc1d8c6b51debd9c2cef33a8d5b1c51"},{"path":"product/runtime/auths-connections/src/kernel.rs","sha256":"a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8"},{"path":"product/runtime/auths-connections/src/lib.rs","sha256":"79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22"},{"path":"product/runtime/auths-connections/src/model.rs","sha256":"de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77"},{"path":"product/runtime/auths-connections/src/registry.rs","sha256":"e57640e003e72ad3235c567c2bb944a262bd64e673f023b62ea091094cc7e946"},{"path":"product/runtime/auths-gateway-kernel/Cargo.toml","sha256":"34f864e67656af4ac7e5c7a347a23f01fc8ab31365b8e23c0ef474483b14a183"},{"path":"product/runtime/auths-gateway-kernel/src/construct.rs","sha256":"e9d65744bae273d65face4285e5d2da75c06a92ab48f7b8333d496604e31c63c"},{"path":"product/runtime/auths-gateway-kernel/src/lib.rs","sha256":"cfda6f8453426564c085475f183b6f790b438768a19668f1b65d33ba59dc8632"},{"path":"product/runtime/auths-gateway-kernel/src/order.rs","sha256":"e0045f877c4b7fe3860c291039853885064ddcdebba7c9b345ab65e81e646dda"},{"path":"product/runtime/auths-gateway-kernel/src/outcome.rs","sha256":"e9785b1afe70788c89b51b18655bcd5acff7b0c8e3d12fb79c6f05a202e67e6b"},{"path":"product/runtime/auths-gateway-kernel/src/ratio.rs","sha256":"7ace22264812e6fc1ef3a62afee402cf43494bb71ae0d3de219ad1b39d690bcb"},{"path":"product/runtime/auths-gateway-kernel/src/recovery.rs","sha256":"9f46dcd1685ab6e4d1ba04a3fc286a9f3afee8fb47829be1fbc670a7926a2dc6"},{"path":"product/runtime/auths-gateway-kernel/src/transition.rs","sha256":"cefb8f01d915880f6921f2501ff881ad94b9de61072c34d9cd19220992f97374"},{"path":"product/runtime/auths-gateway/Cargo.toml","sha256":"00b28be86921dcdc0ad90cce0c62c2961cafefe96ea6c2edf0e926c3d405ccad"},{"path":"product/runtime/auths-gateway/src/admin.rs","sha256":"2d5cc67afac42fbd15f36e2d1693cd1b20cedacf775040dce6ffe04ccc94c9ea"},{"path":"product/runtime/auths-gateway/src/app.rs","sha256":"6f80f63833ea0815bb44fbf3b0cc54624a08e9fb578b035819f2980dc04e8256"},{"path":"product/runtime/auths-gateway/src/audit.rs","sha256":"0edb2037eb7b5d6f13acfce85c54f62a82bf7fdd31bc7e626c4fec183cef61dd"},{"path":"product/runtime/auths-gateway/src/audit_tests.rs","sha256":"990969384a52d75bc2489d9d412a9e7dd814bca1c8f65c701d6205fae62a15d5"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway-harness.rs","sha256":"12b0c24d36b2e6a3be392d3c081a783b355fdd67dc5b54bacc0410e803116b8c"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway.rs","sha256":"c1775bbe7b049a9f051332920fac51de0065040938df74fbcb53825593bd5a3b"},{"path":"product/runtime/auths-gateway/src/binding.rs","sha256":"663b0ce878319511aa7d05722ab4ab2fa9be18817884ffb2ee9f131ff1e382d1"},{"path":"product/runtime/auths-gateway/src/bounds.rs","sha256":"9cfa0eae4973e5e047a198360b22f041708fa20276b0b90c2ec440f06915d64b"},{"path":"product/runtime/auths-gateway/src/bounds_aggregate_tests.rs","sha256":"ab34f227b7c8692ba1da88ccb32bb3687a66adf8353d8282fae905d4a88eb612"},{"path":"product/runtime/auths-gateway/src/bounds_tests.rs","sha256":"74136bc570da7b9338b5a1a1ed9d3fd892c55135160964f9d3ac0e2cf5741375"},{"path":"product/runtime/auths-gateway/src/connection.rs","sha256":"7b5d049c258a26ed1c93ecf860f51d051a8a65f9b93554af0b1ea93862398ec9"},{"path":"product/runtime/auths-gateway/src/credential_journal.rs","sha256":"8e2b0733038d93ca5df770d27a870237e3b65664fa48da017d964a65bbbe25b8"},{"path":"product/runtime/auths-gateway/src/echo_verify.rs","sha256":"6d453051665f823abd7354d5c50031d9524cf47d6092d2f09080ae814e3b9575"},{"path":"product/runtime/auths-gateway/src/engine.rs","sha256":"a9f71575994ff21633ddfc533b1d810515db71aa0146fa8869dad72eddcb2a12"},{"path":"product/runtime/auths-gateway/src/fuzzing.rs","sha256":"ed3b0028487eb546a3b0a91d115aa8f18bcea324b61620bfe8e35a9e6ab18758"},{"path":"product/runtime/auths-gateway/src/generation_floor.rs","sha256":"47964a5f1ca2fc9c4da0b526b6d5c5637fc0ce1d2e429219d02f1b0dc652fdff"},{"path":"product/runtime/auths-gateway/src/harness.rs","sha256":"c87e479f3eb281960f6c9c80d43c7560d7ccb654b0154ec823d3fcec4884ac05"},{"path":"product/runtime/auths-gateway/src/lib.rs","sha256":"b182052835a2cd631d1f801a74788d6ac1ef9cae21ade9ab4ffc270cd6f667ed"},{"path":"product/runtime/auths-gateway/src/listener.rs","sha256":"aa08239bcbc1fcb55e8a212fbdf6a84f12985b0d436dcb51dc58b06e59e435f2"},{"path":"product/runtime/auths-gateway/src/observed_tests.rs","sha256":"a22be071695f89ca2578a4d82fd80d9cb82289213c9bdb8f0470f6b2dc3d9201"},{"path":"product/runtime/auths-gateway/src/observer.rs","sha256":"562ffcaea071c3856e0708dc2fe33516917e145d2438aabb75af0a2b6ba01046"},{"path":"product/runtime/auths-gateway/src/onboarding.rs","sha256":"0dfd7d67e7f02f18a28d1c86ca1b7751d7463f5efcdbe3825de0ad8cbccb3891"},{"path":"product/runtime/auths-gateway/src/operator.rs","sha256":"c3c36954a3e86723df035b47f43b85fc8ab3a6292983522b6258d5c6b4e6c4e4"},{"path":"product/runtime/auths-gateway/src/pending_vectors/attempts.rs","sha256":"47ef3c8cb1c5504d47ae9a0088705ce6715fe86bac1671a34a56fb38a64d0dd3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/bounds.rs","sha256":"e612217307e1da5b0eb5ee6582a7458bb064b8aa8a529fc6555b1b334127ab68"},{"path":"product/runtime/auths-gateway/src/pending_vectors/codes.rs","sha256":"e00670a5ef24eb856cc2c6dcda8e5a263842f55c76bb939c0c27bd9df37e5522"},{"path":"product/runtime/auths-gateway/src/pending_vectors/keys.rs","sha256":"f84c56f2ea9cb34b2b79c72d13fbf2c6585010ec1ed450af58a78c80c1ea1edd"},{"path":"product/runtime/auths-gateway/src/pending_vectors/mod.rs","sha256":"5de8340f0ef71a0b57a09e323fefe473d3160c6ae952b9ba46f714825fbacafc"},{"path":"product/runtime/auths-gateway/src/pending_vectors/outcomes.rs","sha256":"8ec07b9511b48913af36ac999d2aa0e82924289f6acb23ddaeb9f00f99815166"},{"path":"product/runtime/auths-gateway/src/pending_vectors/production.rs","sha256":"c2fa18b5d96c87689fe60d95faadebe2c7fdf5b78be872ca15a67ad980106ed3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/recipes.rs","sha256":"51693208270231c25c3aef2a32151d5962114c71e86b88cb9df83181c7af83d9"},{"path":"product/runtime/auths-gateway/src/pre_entry.rs","sha256":"06ea78ca140468bfaba17d9ab04912ad68673954c3203c98fed28272ff2a00c0"},{"path":"product/runtime/auths-gateway/src/property_tests.rs","sha256":"939c081e2e154aaf10186754044bdd65608932c899b970a04a71d0afaa999a93"},{"path":"product/runtime/auths-gateway/src/qualification.rs","sha256":"a4398512ccb7bb494000fe38f03e0faa7b82d1f80ef5ee2dfa75698ae4f5a9be"},{"path":"product/runtime/auths-gateway/src/qualification_tests.rs","sha256":"4473add5729b97faf04d7be7fd8cf3bbacd7f545e1b61c7d2782563011906b4d"},{"path":"product/runtime/auths-gateway/src/quorum_tests.rs","sha256":"a78380b019104d688c11a4410082c7e08ded3106aab099954c4f8a1b4ae0fd89"},{"path":"product/runtime/auths-gateway/src/readiness.rs","sha256":"911c3f11892f94641574375e2da4c671c802738f71082f12c39832331052d43d"},{"path":"product/runtime/auths-gateway/src/recipe.rs","sha256":"fecf9af67e7afc48d080e9f8f55f8ce28e49d0e08988717a27908bbda461d6b6"},{"path":"product/runtime/auths-gateway/src/recipe/lower.rs","sha256":"8088b8751ed831dbb48247af953c6290ac95e2a438ccd5bd65eff54be06a1fd1"},{"path":"product/runtime/auths-gateway/src/recipe/review.rs","sha256":"c3eb7d9fdd98dacf52750b14b67ad7b7faaecbbdeafff1e0b049f67d0a2d0139"},{"path":"product/runtime/auths-gateway/src/recipe/runtime.rs","sha256":"c286f0d15f974402822c0810d8e97f98411dc1c557755cc23e540d85e2bb42d9"},{"path":"product/runtime/auths-gateway/src/recipe/source.rs","sha256":"1af50298fb1461e1b24cbdf560d43124d6b1c4c529586c911b1c4797214a69ff"},{"path":"product/runtime/auths-gateway/src/recipe/tests.rs","sha256":"aac551a2481bbc60864c64079bc667dcb232e45a0f41a04073ed84ab5dbe1fce"},{"path":"product/runtime/auths-gateway/src/recipe/validate.rs","sha256":"3711b17605cb7b0d639bc1b180449231f5882a306cab20e2c7782155cc63b0d4"},{"path":"product/runtime/auths-gateway/src/scenario_tests.rs","sha256":"d8271761b12597bfe1233f8eb5ad1d4e5498c5d03388e832e24ab818484a1de4"},{"path":"product/runtime/auths-gateway/src/separation.rs","sha256":"be9306848ca5d801767cf6aa14247c8618312ef0e202f00ce0c24c4844491061"},{"path":"product/runtime/auths-gateway/src/store.rs","sha256":"1e5288345c2cb1421aeda277b3158d07607404b0ec46943222ac107b63dcbb46"},{"path":"product/runtime/auths-gateway/src/store_testkit.rs","sha256":"88d82fee42f1b8ef521e8deef0216e938ebeaad822eb2f5020e70b89d145ea70"},{"path":"product/runtime/auths-gateway/src/submit.rs","sha256":"c78dbbba7c45b443febf655056c5edcd635e77be7b21c5b2c318097502415ffe"},{"path":"product/runtime/auths-gateway/src/support.rs","sha256":"33c87008b6643e3e595e5af0c221ee5460df69e17cc69be2edcae13474d0cdb9"},{"path":"product/runtime/auths-gateway/src/transport.rs","sha256":"be2c6dc75b8daec110bf8749fedc3823f6067d40b999aa3eb21126896a97d3ad"},{"path":"product/runtime/auths-kernel-runtime/Cargo.toml","sha256":"926bcd0053e5edd703be8f0027ad009e2982db013c8174c1366edbf38b48087d"},{"path":"product/runtime/auths-kernel-runtime/src/lib.rs","sha256":"7108faae9ca4bc32dc093ddaf885ac8f74f3c9b8d317b7c7d0ed00d1d0ab5972"},{"path":"product/runtime/auths-lifecycle/Cargo.toml","sha256":"c5053c705f8d5554b44e432fe75287a2faf11d644e5a2552e45ad6cd94176af5"},{"path":"product/runtime/auths-lifecycle/src/codec.rs","sha256":"51c4b746749150e8bfcd8ff972b3f6c1ef40bec15583448ec1b471d9ad737dc0"},{"path":"product/runtime/auths-lifecycle/src/digest.rs","sha256":"55282cd7d8aba37713c2dcb5357c9877819edb72a30eadefb860d28d7d3a3eb7"},{"path":"product/runtime/auths-lifecycle/src/identifier.rs","sha256":"31620e8c16de68d3d2d3b84d6353c1a5b9d4151d8247f91fa389b906a8e660f1"},{"path":"product/runtime/auths-lifecycle/src/kernel.rs","sha256":"2abb8c094b36d35b364e74d78091d14c5d6f3d1eb6552cca3b5538dbd017ce23"},{"path":"product/runtime/auths-lifecycle/src/lib.rs","sha256":"afe5a345cd309b5a4f08ffba3170a6d7f16ff914892b3f2006d5208ed24ec736"},{"path":"product/runtime/auths-lifecycle/src/model.rs","sha256":"1af12bbeeeaa65ec02ddcebd7d2c8c92ec1e339fa40ae85b45ab9b01a722a4fa"},{"path":"product/runtime/auths-lifecycle/src/operation.rs","sha256":"78e6d05fcf5d7ea4f148032a3fa26fdfcab77eb346019effe927b08e0d64d732"},{"path":"product/runtime/auths-lifecycle/src/registry.rs","sha256":"53495fe6f7a77422593a41623e28716f1c140dcc1e00f87f6b0ffbfb93a5ef90"},{"path":"product/runtime/auths-lifecycle/src/sealed.rs","sha256":"2e0c03b5813c926c159598bb7890d1523825edbe57cd687d42a5dfb3374a0c19"},{"path":"product/runtime/auths-lifecycle/src/test_support.rs","sha256":"221d9a5c5ef8e1f9f8fd66927484eaf813571d0568470278ecd8fa08a5eec8cd"},{"path":"product/runtime/auths-lifecycle/src/transition.rs","sha256":"011805a28efdd541f44ccea54dd0e34a1e58f4004447ee58013703b4fb6b2822"},{"path":"product/runtime/auths-runtime/Cargo.toml","sha256":"dd29d80a8b4bb56c869f036a6c9998f6e6d1c0383ac5dc03fa42b24abe2a7ff7"},{"path":"product/runtime/auths-runtime/src/lib.rs","sha256":"132ca03d58c14905d3a822a4972f42a22a5ad33a45f2ba9ca44f3a57d810b4b0"},{"path":"product/runtime/auths-runtime/src/production.rs","sha256":"fd4eff4270c571c10fcff6cf27df28961ebf074de8a1a028f500fda1ca376820"},{"path":"product/sdk/auths-approval-quorum/Cargo.toml","sha256":"df904971fca87a24194c5816738a331588fe8f164acb5d70839a35dca5f57114"},{"path":"product/sdk/auths-approval-quorum/src/lib.rs","sha256":"72e4086088a1c0912e4e1a9e980f26a5c280bf5ab16ea39c9f0f58d5096ac2ce"},{"path":"product/sdk/auths-approval-quorum/src/remote.rs","sha256":"9fa029c7c63003adf260f8aec55160c545681c60c1bace0d934e7525862aac7b"},{"path":"product/sdk/auths-approval-quorum/src/remote_tests.rs","sha256":"8a09ce17cfee82a035a74edd535f3ebeb3db0e078784740d3997b17dbdb10197"},{"path":"product/sdk/auths-approval-quorum/src/tests.rs","sha256":"0acbf12be3e497dcc6c2d8f29c9af3b1a7ed8e11b75f6399570d4f217a785060"},{"path":"product/stores/auths-stores/Cargo.toml","sha256":"a32c4b76d17b264be5d40d24497ff237e1ed87822e8bab86229b3db93106dbe3"},{"path":"product/stores/auths-stores/src/gateway_attempt.rs","sha256":"185da8f4a220fba836d5b78a9311f03204681c43a3c53951008084d135bf4d21"},{"path":"product/stores/auths-stores/src/lib.rs","sha256":"e721262edf8a9ab5568ddc27639176312d4a366203b5f73e2d7c11fde2c554e9"},{"path":"product/stores/auths-stores/src/lifecycle.rs","sha256":"94f64d25bc178a9e60ba3c0ee6915d7fb3af7c4468792d76b4e70f43f4de1e2f"}],"schema":"auths.gateway-semantic-closure/1"} \ No newline at end of file diff --git a/product/runtime/auths-gateway/src/bin/auths-gateway.rs b/product/runtime/auths-gateway/src/bin/auths-gateway.rs index 523bef672..e401e622c 100644 --- a/product/runtime/auths-gateway/src/bin/auths-gateway.rs +++ b/product/runtime/auths-gateway/src/bin/auths-gateway.rs @@ -755,10 +755,33 @@ mod unix { settings: &CredentialStoreSettings, deployment: Deployment, unavailable: &'static str, + ) -> Result, &'static str> { + open_credentials_for( + state_dir, + settings, + deployment, + unavailable, + CredentialAccess::Runtime, + ) + } + + #[derive(Clone, Copy, Eq, PartialEq)] + enum CredentialAccess { + Runtime, + Operator, + } + + fn open_credentials_for( + state_dir: &Path, + settings: &CredentialStoreSettings, + deployment: Deployment, + unavailable: &'static str, + access: CredentialAccess, ) -> Result, &'static str> { use auths_credentials_aws_secrets_manager::{ - AwsSecretsManagerStore, ContainerEndpoint, DeploymentNamespace, HttpSecretsApi, - InstanceMetadata, Region, WebIdentity, WorkloadIdentity, + AdministrativeSecretsApi, AwsSecretsManagerStore, ContainerEndpoint, + DeploymentNamespace, HttpSecretsApi, InstanceMetadata, Region, WebIdentity, + WorkloadIdentity, }; let kind = auths_gateway::credential_store_policy(&settings.kind, production_custody(deployment))?; @@ -812,6 +835,32 @@ mod unix { } _ => return Err(unavailable), }; + if access == CredentialAccess::Operator { + // The maintained operator reference is web identity. It + // reads under the runtime role and writes under the + // distinct operator role; neither role is broadened. + if settings.identity.as_deref() != Some("web-identity") { + return Err(unavailable); + } + let reader_role = variable("AUTHS_GATEWAY_RUNTIME_ROLE_ARN")?; + if reader_role == variable("AWS_ROLE_ARN")? { + return Err(unavailable); + } + let reader = WebIdentity::new( + ®ion, + reader_role, + variable("AUTHS_GATEWAY_RUNTIME_TOKEN_FILE")?, + ) + .map_err(|_| unavailable)?; + let reader = HttpSecretsApi::new(region.clone(), None, reader) + .map_err(|_| unavailable)?; + let writer = HttpSecretsApi::new(region, settings.kms_key.clone(), identity) + .map_err(|_| unavailable)?; + return Ok(Arc::new(AwsSecretsManagerStore::new( + AdministrativeSecretsApi::new(reader, writer), + namespace, + ))); + } let api = HttpSecretsApi::new(region, settings.kms_key.clone(), identity) .map_err(|_| unavailable)?; Ok(Arc::new(AwsSecretsManagerStore::new(api, namespace))) @@ -1732,6 +1781,13 @@ mod unix { } fn load_engine(state_dir: &Path) -> Result { + load_engine_for(state_dir, CredentialAccess::Runtime) + } + + fn load_engine_for( + state_dir: &Path, + access: CredentialAccess, + ) -> Result { private_root(state_dir)?; let manifest = installation(state_dir)?; let source = read_bounded(&state_dir.join("recipe.json"), 65_536)?; @@ -1791,11 +1847,12 @@ mod unix { .map_err(|_| "gateway.serve.invalid-alias")?, "gateway".to_owned(), profile, - open_credentials( + open_credentials_for( state_dir, &manifest.credential_store, manifest.deployment, "gateway.serve.credential-store-unavailable", + access, )?, open_attempts( manifest.deployment, @@ -2690,7 +2747,7 @@ mod unix { async fn operator_engine(state_dir: &Path) -> Result { let directory = state_dir.to_path_buf(); - tokio::task::spawn_blocking(move || load_engine(&directory)) + tokio::task::spawn_blocking(move || load_engine_for(&directory, CredentialAccess::Operator)) .await .map_err(|_| "gateway.admin.load-failed")? } diff --git a/product/runtime/auths-gateway/src/semantic_closure.rs b/product/runtime/auths-gateway/src/semantic_closure.rs index 224ec4a82..058ea6059 100644 --- a/product/runtime/auths-gateway/src/semantic_closure.rs +++ b/product/runtime/auths-gateway/src/semantic_closure.rs @@ -10,7 +10,7 @@ /// SHA-256 of the schema, a NUL byte, and `semantic-closure.json`. /// Regenerate through `semantic_closure_is_current` with `AUTHS_UPDATE_FIXTURES=1`. pub const GATEWAY_SEMANTIC_CLOSURE_SHA256: &str = - "09df4a87c61ecc639aeb860dcc35980afb737055412fa48aedf39d1d070cf59f"; + "337a10a522211b4ff80e5191cc1b4b8460d2d028ec3f21870d6cfd8e53b5abf0"; #[cfg(test)] mod tests { diff --git a/release/semantic-freeze-versions.toml b/release/semantic-freeze-versions.toml index 2a0e5898f..8ea4b85fe 100644 --- a/release/semantic-freeze-versions.toml +++ b/release/semantic-freeze-versions.toml @@ -1,4 +1,4 @@ -freeze_version = 364 +freeze_version = 365 # Semantic identity counters live outside the xtask source tree deliberately. # The formal source closure binds xtask's executable code, while the semantic @@ -45,7 +45,7 @@ freeze_version = 364 "auths.frozen-bytes/product/integrations/auths-stripe/fixtures/subscription-create/v1/manifest.sha256.json" = 1 "auths.frozen-bytes/product/integrations/auths-stripe/fixtures/subscription-modify/v1/manifest.sha256.json" = 1 "auths.frozen-bytes/product/integrations/auths-stripe/fixtures/v1/manifest.sha256.json" = 1 -"auths.identity.protocol" = 120 +"auths.identity.protocol" = 121 "auths.modular-components" = 20 "auths.portable-abi-bindings" = 121 "auths.product.bounded-domains" = 19 @@ -60,11 +60,11 @@ freeze_version = 364 "auths.product.mcp-closed-execution" = 31 "auths.product.mechanism-profile-conformance" = 12 "auths.product.operations" = 5 -"auths.product.public-sdk-contract" = 117 +"auths.product.public-sdk-contract" = 118 "auths.product.receipts" = 13 "auths.product.release-assurance" = 7 "auths.product.simplified-waist" = 19 "auths.product.vocabulary" = 24 "auths.release.benchmark-contract" = 1 "auths.release.evolution-contract" = 79 -"auths.release.public-surface" = 364 +"auths.release.public-surface" = 365 diff --git a/release/semantic-freeze.json b/release/semantic-freeze.json index 01128b31b..e4b6357be 100644 --- a/release/semantic-freeze.json +++ b/release/semantic-freeze.json @@ -1,6 +1,6 @@ { "schema": "auths.semantic-freeze/1", - "freezeVersion": 364, + "freezeVersion": 365, "publicSurface": { "rustRoots": [ "auths", @@ -550,7 +550,7 @@ }, { "id": "auths.identity.protocol", - "version": 120, + "version": 121, "classification": "frozen-meaning", "categories": [ "identity-protocol-versions", @@ -573,7 +573,7 @@ "core/fixtures/identity/v1/vectors.json", "core/spec/identity/v1" ], - "sha256": "f3e9a6379f0260d117dd3e454707497a7d35208a0878482d919a11be48c0a8c4" + "sha256": "0c4b941cb584536dc88468e2f053c982fade8ef68cfd3cdbe435fcb488f90e37" }, { "id": "auths.modular-components", @@ -871,7 +871,7 @@ }, { "id": "auths.product.public-sdk-contract", - "version": 117, + "version": 118, "classification": "frozen-meaning", "categories": [ "rust-sdk-contract", @@ -889,7 +889,7 @@ "product/runtime/auths-runtime/src", "product/sdk/auths-sdk/src" ], - "sha256": "2fbab558a6ebdb407cc2a14ac580677d2a20352573ad92ad3351a699930557c8" + "sha256": "0413cb945fe2517496cb751a8f61142e0d6d6a3881b8a2a9a60065526ccb3211" }, { "id": "auths.product.receipts", @@ -1011,7 +1011,7 @@ }, { "id": "auths.release.public-surface", - "version": 364, + "version": 365, "classification": "release-metadata", "categories": [ "package-names", @@ -1103,7 +1103,7 @@ "xtask/src/release_control.rs", "xtask/src/semantic_freeze.rs" ], - "sha256": "a975b622614180a785b2909e94385845bfeddc5708d68be2c732e7326fed537a" + "sha256": "73ac80785dac5a005702d9c8b1df49ccf25bc0321f53ad8c8c9830ae3ff7325c" } ] } From 2906cabdee8666b8d9103c2e5345e49f7005d2db Mon Sep 17 00:00:00 2001 From: bordumb Date: Tue, 6 Oct 2026 03:43:08 +0100 Subject: [PATCH 009/108] build(gateway): bind operator archives to the exact pull request candidate --- .github/workflows/gateway-operator-package.yml | 1 + docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/gateway-operator-package.yml b/.github/workflows/gateway-operator-package.yml index 975a1e235..9c3edd133 100644 --- a/.github/workflows/gateway-operator-package.yml +++ b/.github/workflows/gateway-operator-package.yml @@ -20,6 +20,7 @@ jobs: steps: - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 with: + ref: ${{ github.event.pull_request.head.sha || github.sha }} persist-credentials: false - uses: ./.github/actions/setup-rust-cache with: diff --git a/docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md b/docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md index d90bb2d1e..ee11f3add 100644 --- a/docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md +++ b/docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md @@ -141,7 +141,7 @@ updates running during the upgrade. ## Independent operator trial -Give a person unfamiliar with this implementation only the signed packaged +Give a person unfamiliar with this implementation only the verified packaged binaries, packages, public configuration and this runbook. Record participant identity/role, artifact digests, dates, timings, attempted commands, redacted reports and defects. They deploy both hosts, diagnose an unavailable credential, From 7b80638a117b7b6e848f58084a8ff2be00b9e2a9 Mon Sep 17 00:00:00 2001 From: bordumb Date: Tue, 6 Oct 2026 03:49:52 +0100 Subject: [PATCH 010/108] fix(gateway): bound outage support collection and refuse damaged restore floors --- .../fixtures/gateway/production-codes.json | 24 ++++++++++++ .../auths-gateway/semantic-closure.json | 2 +- .../auths-gateway/src/bin/auths-gateway.rs | 11 ++++-- product/runtime/auths-gateway/src/engine.rs | 24 ++++++++++++ .../auths-gateway/src/generation_floor.rs | 16 +++++--- .../src/pending_vectors/production.rs | 3 ++ .../auths-gateway/src/semantic_closure.rs | 2 +- product/runtime/auths-gateway/src/support.rs | 4 +- .../auths-gateway/tests/support_bundle.rs | 39 ++++++++++++++++++- release/semantic-freeze-versions.toml | 8 ++-- release/semantic-freeze.json | 10 ++--- 11 files changed, 119 insertions(+), 24 deletions(-) diff --git a/bindings/fixtures/gateway/production-codes.json b/bindings/fixtures/gateway/production-codes.json index 77b9b07c3..41c40edaf 100644 --- a/bindings/fixtures/gateway/production-codes.json +++ b/bindings/fixtures/gateway/production-codes.json @@ -223,6 +223,30 @@ "status": "existing", "epic": null, "case": null + }, + { + "code": "gateway.support.attempts-unavailable", + "owner": "support", + "stage": "support-bundle", + "status": "implemented", + "epic": 4, + "case": null + }, + { + "code": "gateway.support.connection-unavailable", + "owner": "support", + "stage": "support-bundle", + "status": "implemented", + "epic": 4, + "case": null + }, + { + "code": "gateway.support.unavailable", + "owner": "support", + "stage": "support-bundle", + "status": "implemented", + "epic": 4, + "case": null } ] } diff --git a/product/runtime/auths-gateway/semantic-closure.json b/product/runtime/auths-gateway/semantic-closure.json index 8dc26813e..ed3cbf4a2 100644 --- a/product/runtime/auths-gateway/semantic-closure.json +++ b/product/runtime/auths-gateway/semantic-closure.json @@ -1 +1 @@ -{"files":[{"path":"Cargo.lock","sha256":"c94ed342774d5e2823f01ecf74b8a4812c5f9a6b0cf811d31f2e2cecb671a275"},{"path":"Cargo.toml","sha256":"6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24"},{"path":"core/adapters/auths-did-keri/Cargo.toml","sha256":"86ba3e3f9a0a70d970568bfb3113b7ba7bbdd81c3eebbb52743dd574a0c0ecaa"},{"path":"core/adapters/auths-did-keri/src/lib.rs","sha256":"a75674842f8a7142004369ccd206ab43e476459293f0ff4bed4d4e659031b3e3"},{"path":"core/adapters/auths-did-key/Cargo.toml","sha256":"d5a3ae07ecde83f91eed4c3785051dd0f44eab6c891754f3309b6b40596707d7"},{"path":"core/adapters/auths-did-key/src/lib.rs","sha256":"b76a3f4528a725df53cfa9242e6e414e1d26caa48468aaed497e28b121f4497c"},{"path":"core/adapters/auths-raw-key/Cargo.toml","sha256":"f49616bc18c19e6aaa7e6a02ccebcdb9f5c1422c1278ef9869e0dbf22ceda7be"},{"path":"core/adapters/auths-raw-key/src/lib.rs","sha256":"45eec1b295dac3bed65cd79c942870b926b06b3f5d38eaebaeb6140ac69315fa"},{"path":"core/crates/auths-algebra-kernel/Cargo.toml","sha256":"0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba"},{"path":"core/crates/auths-algebra-kernel/src/generated.rs","sha256":"ae4bcbef42a408c7ffa0c6a74a42f7de177a6f14479e51d205acf830bda05960"},{"path":"core/crates/auths-algebra-kernel/src/lib.rs","sha256":"6654667eeb9b353d6648954c9fd2e8838462a82ce6b2803eb49e1366892c68c6"},{"path":"core/crates/auths-assurance/Cargo.toml","sha256":"afcb12a97ddd09d7a264b9ecd3fcaefc865ff2c9b4539ee85b00883420ba333a"},{"path":"core/crates/auths-assurance/src/lib.rs","sha256":"0fb2ec844d674b25a9e20b1601452c89c2454901fa506adfa9bb38ef9a7fa213"},{"path":"core/crates/auths-author/Cargo.toml","sha256":"1e6f0e3bc079ddb558decf0db26b291c6e72fc47327b6df1b7650d41689b215f"},{"path":"core/crates/auths-author/src/lib.rs","sha256":"e14475f2f49715a1869d5fa6b11ff1fbb72497e39097e09f833b0bae7e5b3f2b"},{"path":"core/crates/auths-author/src/observations.rs","sha256":"dda7d6bfa6f4bd7e95a480ca283c2c0e996f69c5c15cb0c7197af328131a7066"},{"path":"core/crates/auths-authority/Cargo.toml","sha256":"4f68212938029f79ebd857b4f3038494eb85d0163d49f07e51376715cf959815"},{"path":"core/crates/auths-authority/src/lib.rs","sha256":"da88d5194de4e17449e69972c0fb042afa3c39798a8f570f30771e77c384f1eb"},{"path":"core/crates/auths-codec/Cargo.toml","sha256":"e20e51826e17814effd9d8925d18d5fbdd6c0d37bf50231e743ec2611314722c"},{"path":"core/crates/auths-codec/src/approval.rs","sha256":"fbff43bf4d57f69f8b7738a8647751cde75c5a932dee65d924a1fe9c7202f91f"},{"path":"core/crates/auths-codec/src/bounded_policy.rs","sha256":"d21f6728be2d8a04b6d94921f2b683f7e61cbb42e0ac6866f1c88a49caa534c3"},{"path":"core/crates/auths-codec/src/decode.rs","sha256":"ba2999584cdf53b1b517ecb9c7ea50d39efee17c666a9a38e2ad1ac94379f778"},{"path":"core/crates/auths-codec/src/encode.rs","sha256":"8491192053e2e15d62b4d2a491de22405b7487ead69ab6f6bca40669ce7ca5f7"},{"path":"core/crates/auths-codec/src/error.rs","sha256":"fecb0737c16deb42d859f1dc7727c698438d9ac12064fd99e0024629642c390c"},{"path":"core/crates/auths-codec/src/hash.rs","sha256":"f88e111f1dbb2cef6b7b5e9c948cb45ff92e366710c8a5f5c636138aa748479e"},{"path":"core/crates/auths-codec/src/lib.rs","sha256":"3b0e5c94c6f34f750b88a9333e1d5c8145746d845d3a23e0d2f61807cf592ea7"},{"path":"core/crates/auths-codec/src/observation.rs","sha256":"38328b0c71ff97a4196eeade8b4faa889527ff1f80bb168468bcd49082a3987e"},{"path":"core/crates/auths-composition/Cargo.toml","sha256":"331e13025eb82588b5269ed3975929eb41c823d588c49e4c296273d85c6fe80e"},{"path":"core/crates/auths-composition/src/lib.rs","sha256":"e42e3b0b6a9985b73c533aeb23799c638979aa27a9ce7d0f10a8d60340570fb1"},{"path":"core/crates/auths-model/Cargo.toml","sha256":"565c15302b0cc9270db1e28efa3862804846850ba933cc17aea8abcec4a65987"},{"path":"core/crates/auths-model/src/approval.rs","sha256":"54cf44a9ef747ec21546a4086aecfb130bc7803b0d646430e6082df51e6e305f"},{"path":"core/crates/auths-model/src/bounded.rs","sha256":"f90496abc0a06c028b4d850af6ddab7d850bfafeaa3d042f1b1246a41d8bbbc9"},{"path":"core/crates/auths-model/src/bounded_policy.rs","sha256":"306a8f049cc7cfc7635fe0e4de47eb7813eed63d3c14c3be2b51586aa4eea450"},{"path":"core/crates/auths-model/src/lib.rs","sha256":"e7cfe6bb9574c6b016aa63e70658c31e0b90903ec6479a49f4a2ceb64f5bad97"},{"path":"core/crates/auths-model/src/observation.rs","sha256":"b3ed3e3cc090afca2896a7d3de7988afccc1ee1ea0ebd91b51a8bc0f20ad8dbb"},{"path":"core/crates/auths-multikey/Cargo.toml","sha256":"858756c1197befcada06134742bffe8d58cf674cadd6c046bf710570e96efaf2"},{"path":"core/crates/auths-multikey/src/lib.rs","sha256":"f5177fffb11e40eeaaa665ba886c541fc1f24d5eacdd6983fb03dc20148733f0"},{"path":"core/crates/auths-ports/Cargo.toml","sha256":"596a9b0f5af3717c16a6d13f7054d8a106bcd9f01f5f72c2235dd2afcf0ab16c"},{"path":"core/crates/auths-ports/src/binding.rs","sha256":"a16c012d40aa4249e3ec54372b9611006d0bfe8c7dc3c741911c2194ad17736d"},{"path":"core/crates/auths-ports/src/diagnostics.rs","sha256":"aa596572503b5a65a918bb2ff38281c144ff53821ee914e9325c852828d852df"},{"path":"core/crates/auths-ports/src/lib.rs","sha256":"8da1debf86f9532df0660155d04298beb1ba3a1204508f8586e2e67cd2fb3449"},{"path":"core/crates/auths-ports/src/path.rs","sha256":"b68fc547b4e4d97a60cbbc1cc1939fc6b34a8233b81f840bd396914a707e3ea1"},{"path":"core/crates/auths-raw-key-core/Cargo.toml","sha256":"98c0bc8527a537512e43a74dd6ba9658c6f0cdc16610cf938e3f9b43785d836d"},{"path":"core/crates/auths-raw-key-core/src/lib.rs","sha256":"98c0500c41697aae28708ad0bf970b9a97583d96a3d2c18d23e7fa351e0f7d12"},{"path":"core/crates/auths-registries/Cargo.toml","sha256":"590e49e58b0622d9d6274fea46796dcdb07dec9550eff295cce6a6427ffa51e2"},{"path":"core/crates/auths-registries/src/lib.rs","sha256":"450d3886d85ee333b7e046317fb5b47cde62483d5f3e41d46265e2caf4c373ec"},{"path":"core/crates/auths-registries/src/template.rs","sha256":"1224039dd2b3ce6fa8357613d8cafbae40400493da7176da202b9ade62fa05e4"},{"path":"core/crates/auths-signature-core/Cargo.toml","sha256":"6bee2230eb30af1be0bd5c2d57bd3e1903497a70028d47290d4ac6e9e0e8bca0"},{"path":"core/crates/auths-signature-core/src/lib.rs","sha256":"6e3f9311ded5e49ea50d445eb21e6d8fa12442aa4362a73e0cb6fda15b7cd865"},{"path":"core/crates/auths-signature/Cargo.toml","sha256":"7f7b5682466ba439d8c59579022cb61068cad9fb4bd2d73e1cc21327c902b450"},{"path":"core/crates/auths-signature/src/lib.rs","sha256":"b3d9ac4cc3ba0797b9e1c09f2d6ac05089b25dac4e285a5af28c0165b33d925b"},{"path":"core/crates/auths-verifier/Cargo.toml","sha256":"c43358e06a33324b41a8b93e5cc7279c55f7d21f1f6cfaa539a3fc7b4c27a38f"},{"path":"core/crates/auths-verifier/src/approval.rs","sha256":"c3cae6a49e169051eb555bb092b1069a4d422516d6a2114623a89e5f31ff923f"},{"path":"core/crates/auths-verifier/src/causal.rs","sha256":"9635230f33b13a263573d319ac8a1976addbcc07677514a43e3c7bf28dc04587"},{"path":"core/crates/auths-verifier/src/lib.rs","sha256":"f22dec38dfa47ced8da4f605390da8453273bee1da010f57fd1fdfcb10e0b389"},{"path":"core/crates/auths-verifier/src/observation.rs","sha256":"0bb07f06a0f9524c88427df1c972b1de8ba038a9eeeb15d3134c25125ae84b1e"},{"path":"core/crates/auths-verifier/src/trace.rs","sha256":"2213d72023a1d9e0413a2cf2c51c3dad9e04775d86033a0caaa9d29a8f0036f8"},{"path":"exchange/crates/auths-proof-exchange-model/Cargo.toml","sha256":"34b2db64f93a288e942b5a3918d28cdcbef906e0dc9074ce848018d3d5f7a1fa"},{"path":"exchange/crates/auths-proof-exchange-model/src/lib.rs","sha256":"49fac5aff2339d3a57c41cb8bb2a82852538e8f77ecc4b157c88e264ff31fb55"},{"path":"exchange/crates/auths-proof-exchange-port/Cargo.toml","sha256":"7ff660f1b7579dc570c791090aeb450404fbbf44c92781e289f5ccdde746d739"},{"path":"exchange/crates/auths-proof-exchange-port/src/lib.rs","sha256":"b408fb40c6432edc1facb3d8b3e9433a033f8dc73fe2e0ba5a88c972ca675021"},{"path":"product/config/auths-config/Cargo.toml","sha256":"e4b568ab9f6d84f7d7e6d66443fe825f360db9c27bc7c31d6ddc0647ba3ab304"},{"path":"product/config/auths-config/src/lib.rs","sha256":"fecf00ea65cef9018fda9af2063326d7065b869266d0d9e73a4f06816f1102cc"},{"path":"product/errors/auths-errors/Cargo.toml","sha256":"3b3a199b6460ba75bda84475bb5accd35e1485448a3981038db85bf4772dd350"},{"path":"product/errors/auths-errors/src/lib.rs","sha256":"7feeb9069fa4003f94f1f07c1c94619cf1c883e0dbaaf2187f04d0f742264bdd"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/Cargo.toml","sha256":"716f1f2a117d6d69d8effe9ee9057e24ba3502f20af6a602b06facb638cdabed"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/api.rs","sha256":"9ea61dd7ddd93282b073b98e453e6b75b26dc49689c04e9782435d06a3a09e48"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/clock.rs","sha256":"73f0a6e0f5903883329fa6683f5888288f759512ac69e5c87efd2b6b87f7d79f"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/http.rs","sha256":"14c1fce14e24c984b2a275563a29b6326fb08367922b6e8d37ba38b9cb81aa2b"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/identity.rs","sha256":"186de11230c8b33375951c4368609f8976bf9795f171af3fd7fac26207a94361"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs","sha256":"0b4617d044f5254a5ab22f5a2578f91cc025206a8c1845be39c1c56dcdf7a5df"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/names.rs","sha256":"41bb23572d6002e23ee103d6fe70ecd68764861c6f2e48a1c53af998270a4afa"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs","sha256":"39fed883f4802e68d3b41a68fea0aba0737810996b33d13577de70faba004c29"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/store.rs","sha256":"fc60ee9c49b2f4f063c449b4c78100c5c4872779e94ca168f796603b380ef6e4"},{"path":"product/integrations/auths-custody/Cargo.toml","sha256":"1e14034185ad1ec24a977fd5f41d0abee219606245c046ce2a82287fadef448b"},{"path":"product/integrations/auths-custody/src/conformance.rs","sha256":"8ed1afd58f18fc6becc268908aa6419c9aa404c79da0197963eb2599df44acf6"},{"path":"product/integrations/auths-custody/src/key.rs","sha256":"70cbb0fd21b6f5652157845a22c35be2d0f6c05b3d138fc4b9bb6dbdc3d81c40"},{"path":"product/integrations/auths-custody/src/lib.rs","sha256":"8ee593c1f59b0fd2126bdda9138026f5bc531beb64d4489a99785842e7b98b43"},{"path":"product/operations/auths-operations/Cargo.toml","sha256":"73dde1e914ba5e1386f8d49c0d730423cc72ae77ec44c6554a6a75cc8e8922b1"},{"path":"product/operations/auths-operations/src/explanation.rs","sha256":"b4a39bcbd5712cb9e735ee7deeb281f3fa6af5ddca973735bf3d87dce427ef11"},{"path":"product/operations/auths-operations/src/lib.rs","sha256":"3f401a56555113b98f57bca172a2660eaecedf76247b83a3fdbb089c133a29cd"},{"path":"product/operations/auths-operations/src/render/json.rs","sha256":"2ae042639960afee123730e945d373bc5dda1d2b3af20ae16c939a7e99b9e418"},{"path":"product/operations/auths-operations/src/render/mod.rs","sha256":"b3b7f6fe473f49227ace5a68bfc3d8dc14b5db8dd9888fd9e207070337b1b8bf"},{"path":"product/operations/auths-operations/src/render/text.rs","sha256":"f216cf3bdb00e264523271b16e7059535ac6b1aabf271cebd7935af155e4bfec"},{"path":"product/policy/auths-bounded-policy/Cargo.toml","sha256":"babd5d200923137ead71d8c2528f847cea323ce98da942a1320b054436612c47"},{"path":"product/policy/auths-bounded-policy/src/arithmetic.rs","sha256":"75e43c5d4eab8d1f71c1daf53839f5f9fe45a400afc1f63a30c6f55ce3632627"},{"path":"product/policy/auths-bounded-policy/src/commitment.rs","sha256":"c5706f2d583454e1a7f570f7ada138d4d864bef0205dfae7c1296774f396bb3f"},{"path":"product/policy/auths-bounded-policy/src/eligibility.rs","sha256":"c9acdfb793074e687fc36efad506be27dbd99ffbf40387bc66c8de39ef238432"},{"path":"product/policy/auths-bounded-policy/src/identifier.rs","sha256":"0006a32bae9eb16c4178cf797df418d2b0a781f2bc6474b741dc1a908141831c"},{"path":"product/policy/auths-bounded-policy/src/kernel.rs","sha256":"99187c28b161ac70bee1afed60711f7f645adb4d1671a01863f9849b369811d5"},{"path":"product/policy/auths-bounded-policy/src/lib.rs","sha256":"76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c"},{"path":"product/policy/auths-bounded-policy/src/receipt.rs","sha256":"3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad"},{"path":"product/policy/auths-bounded-policy/src/registry.rs","sha256":"4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0"},{"path":"product/profiles/auths-profile-api/Cargo.toml","sha256":"7ae85761f58625b5d678f961fd052eebf3e000ef565c7312e3ac857763c0017f"},{"path":"product/profiles/auths-profile-api/src/lib.rs","sha256":"a194b82b20bf8aa864c2334ef6c6aec30b2154ded972862252d5dcefa488ab95"},{"path":"product/profiles/auths-profile-mcp/Cargo.toml","sha256":"db264fc25242f7b7e4133cbe5782545b3107b406c87168ae072683cfb59eac66"},{"path":"product/profiles/auths-profile-mcp/src/arguments.rs","sha256":"a5de696586d507e2aee4a49fee99ef1ef4c51a2e46603f8838f1af6d9009833f"},{"path":"product/profiles/auths-profile-mcp/src/lib.rs","sha256":"d0f8b733a09ef8408336cdebc8948d6a5861012ce6878598b11be7084dfd4280"},{"path":"product/profiles/auths-profile-mcp/src/session.rs","sha256":"166c281fa66333388e4760d6098dad02d3359e1d5de4b8f93312c014f97abb03"},{"path":"product/qualification/auths-recipe-qualification/Cargo.toml","sha256":"b7b15b30b9a3d96d4f089d514266d3a892de6608d30707aa44be31cca89ca9fe"},{"path":"product/qualification/auths-recipe-qualification/src/canonical.rs","sha256":"30a9b50777f0dcb4b606abfee2467d5a975d9f6ad941ab6c13ca3df5b359f667"},{"path":"product/qualification/auths-recipe-qualification/src/closure.rs","sha256":"0ad6aee9bd981e2863fa725f209ec84031db2ff12f4c7ac3aaf5120f0bb86039"},{"path":"product/qualification/auths-recipe-qualification/src/error.rs","sha256":"52d5cf720a1e4579008fdda90a3ac2c31f0b8db57985f121f65e54b4da2b7dd1"},{"path":"product/qualification/auths-recipe-qualification/src/evidence.rs","sha256":"1a4cb862f725b02f9efd827db99637ea8178a5236aa020ec271a363edbe7b362"},{"path":"product/qualification/auths-recipe-qualification/src/ids.rs","sha256":"e81a906d571497ab2da753e1532d4443706410e0b75fdd59a7d2d788c7aec403"},{"path":"product/qualification/auths-recipe-qualification/src/lib.rs","sha256":"195b19f46e1e94a0f3594ad5958e5715bc5e3ad415bdfe6428dfc1b6dd3f4631"},{"path":"product/qualification/auths-recipe-qualification/src/model.rs","sha256":"3484eb0ec287b23d4682ade7b1b0f8d1335985b3fb180f06fc28716076957d5f"},{"path":"product/qualification/auths-recipe-qualification/src/release.rs","sha256":"d816b53e2275e902c750ad03803061844e259e28560ab2d1c77e8a43981a4d6a"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/mod.rs","sha256":"7f15b68e05a04f202bcb1fb80de1d9a9a4fda8bfd6af2cd4e5c660fc75d96fe5"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/schemas.rs","sha256":"c59feec2805621f341a90f81fc005e2c12f7a70f9d264fdeacccb2be4fe1c046"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/verification.rs","sha256":"6a6b5834c5dae10af1ba8939b2deae43b85db71544dc8f077ff63b7fe68ac8a8"},{"path":"product/qualification/auths-recipe-qualification/src/verify.rs","sha256":"edd33589c54fb79bcfccc4cf4e6ccf95bbca088318bb7f8dfc27da684b4fa671"},{"path":"product/receipts/auths-receipts/Cargo.toml","sha256":"6001fa1375899953aafcb07c23a6da0c8f57ea7ec08bb9c950b12a60a8cc6f0f"},{"path":"product/receipts/auths-receipts/src/disclosure.rs","sha256":"ba9ed439be0a320c8a01f5b6e9b51361c1a37e076947490d8e4a484ba6bb119c"},{"path":"product/receipts/auths-receipts/src/lib.rs","sha256":"547a57c4160256719cafb7d0ab972d9fc80b0da14fbbce4148c70c414070ff36"},{"path":"product/runtime/auths-connections/Cargo.toml","sha256":"babeb6e1dda3dfb66291713ce1e43dce5c349833d0b50ea4dccbf986030026b2"},{"path":"product/runtime/auths-connections/src/credential.rs","sha256":"82921413bb053f0f6c7931fbd4e6a86c8cc1d8c6b51debd9c2cef33a8d5b1c51"},{"path":"product/runtime/auths-connections/src/kernel.rs","sha256":"a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8"},{"path":"product/runtime/auths-connections/src/lib.rs","sha256":"79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22"},{"path":"product/runtime/auths-connections/src/model.rs","sha256":"de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77"},{"path":"product/runtime/auths-connections/src/registry.rs","sha256":"e57640e003e72ad3235c567c2bb944a262bd64e673f023b62ea091094cc7e946"},{"path":"product/runtime/auths-gateway-kernel/Cargo.toml","sha256":"34f864e67656af4ac7e5c7a347a23f01fc8ab31365b8e23c0ef474483b14a183"},{"path":"product/runtime/auths-gateway-kernel/src/construct.rs","sha256":"e9d65744bae273d65face4285e5d2da75c06a92ab48f7b8333d496604e31c63c"},{"path":"product/runtime/auths-gateway-kernel/src/lib.rs","sha256":"cfda6f8453426564c085475f183b6f790b438768a19668f1b65d33ba59dc8632"},{"path":"product/runtime/auths-gateway-kernel/src/order.rs","sha256":"e0045f877c4b7fe3860c291039853885064ddcdebba7c9b345ab65e81e646dda"},{"path":"product/runtime/auths-gateway-kernel/src/outcome.rs","sha256":"e9785b1afe70788c89b51b18655bcd5acff7b0c8e3d12fb79c6f05a202e67e6b"},{"path":"product/runtime/auths-gateway-kernel/src/ratio.rs","sha256":"7ace22264812e6fc1ef3a62afee402cf43494bb71ae0d3de219ad1b39d690bcb"},{"path":"product/runtime/auths-gateway-kernel/src/recovery.rs","sha256":"9f46dcd1685ab6e4d1ba04a3fc286a9f3afee8fb47829be1fbc670a7926a2dc6"},{"path":"product/runtime/auths-gateway-kernel/src/transition.rs","sha256":"cefb8f01d915880f6921f2501ff881ad94b9de61072c34d9cd19220992f97374"},{"path":"product/runtime/auths-gateway/Cargo.toml","sha256":"00b28be86921dcdc0ad90cce0c62c2961cafefe96ea6c2edf0e926c3d405ccad"},{"path":"product/runtime/auths-gateway/src/admin.rs","sha256":"2d5cc67afac42fbd15f36e2d1693cd1b20cedacf775040dce6ffe04ccc94c9ea"},{"path":"product/runtime/auths-gateway/src/app.rs","sha256":"6f80f63833ea0815bb44fbf3b0cc54624a08e9fb578b035819f2980dc04e8256"},{"path":"product/runtime/auths-gateway/src/audit.rs","sha256":"0edb2037eb7b5d6f13acfce85c54f62a82bf7fdd31bc7e626c4fec183cef61dd"},{"path":"product/runtime/auths-gateway/src/audit_tests.rs","sha256":"990969384a52d75bc2489d9d412a9e7dd814bca1c8f65c701d6205fae62a15d5"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway-harness.rs","sha256":"12b0c24d36b2e6a3be392d3c081a783b355fdd67dc5b54bacc0410e803116b8c"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway.rs","sha256":"c1775bbe7b049a9f051332920fac51de0065040938df74fbcb53825593bd5a3b"},{"path":"product/runtime/auths-gateway/src/binding.rs","sha256":"663b0ce878319511aa7d05722ab4ab2fa9be18817884ffb2ee9f131ff1e382d1"},{"path":"product/runtime/auths-gateway/src/bounds.rs","sha256":"9cfa0eae4973e5e047a198360b22f041708fa20276b0b90c2ec440f06915d64b"},{"path":"product/runtime/auths-gateway/src/bounds_aggregate_tests.rs","sha256":"ab34f227b7c8692ba1da88ccb32bb3687a66adf8353d8282fae905d4a88eb612"},{"path":"product/runtime/auths-gateway/src/bounds_tests.rs","sha256":"74136bc570da7b9338b5a1a1ed9d3fd892c55135160964f9d3ac0e2cf5741375"},{"path":"product/runtime/auths-gateway/src/connection.rs","sha256":"7b5d049c258a26ed1c93ecf860f51d051a8a65f9b93554af0b1ea93862398ec9"},{"path":"product/runtime/auths-gateway/src/credential_journal.rs","sha256":"8e2b0733038d93ca5df770d27a870237e3b65664fa48da017d964a65bbbe25b8"},{"path":"product/runtime/auths-gateway/src/echo_verify.rs","sha256":"6d453051665f823abd7354d5c50031d9524cf47d6092d2f09080ae814e3b9575"},{"path":"product/runtime/auths-gateway/src/engine.rs","sha256":"a9f71575994ff21633ddfc533b1d810515db71aa0146fa8869dad72eddcb2a12"},{"path":"product/runtime/auths-gateway/src/fuzzing.rs","sha256":"ed3b0028487eb546a3b0a91d115aa8f18bcea324b61620bfe8e35a9e6ab18758"},{"path":"product/runtime/auths-gateway/src/generation_floor.rs","sha256":"47964a5f1ca2fc9c4da0b526b6d5c5637fc0ce1d2e429219d02f1b0dc652fdff"},{"path":"product/runtime/auths-gateway/src/harness.rs","sha256":"c87e479f3eb281960f6c9c80d43c7560d7ccb654b0154ec823d3fcec4884ac05"},{"path":"product/runtime/auths-gateway/src/lib.rs","sha256":"b182052835a2cd631d1f801a74788d6ac1ef9cae21ade9ab4ffc270cd6f667ed"},{"path":"product/runtime/auths-gateway/src/listener.rs","sha256":"aa08239bcbc1fcb55e8a212fbdf6a84f12985b0d436dcb51dc58b06e59e435f2"},{"path":"product/runtime/auths-gateway/src/observed_tests.rs","sha256":"a22be071695f89ca2578a4d82fd80d9cb82289213c9bdb8f0470f6b2dc3d9201"},{"path":"product/runtime/auths-gateway/src/observer.rs","sha256":"562ffcaea071c3856e0708dc2fe33516917e145d2438aabb75af0a2b6ba01046"},{"path":"product/runtime/auths-gateway/src/onboarding.rs","sha256":"0dfd7d67e7f02f18a28d1c86ca1b7751d7463f5efcdbe3825de0ad8cbccb3891"},{"path":"product/runtime/auths-gateway/src/operator.rs","sha256":"c3c36954a3e86723df035b47f43b85fc8ab3a6292983522b6258d5c6b4e6c4e4"},{"path":"product/runtime/auths-gateway/src/pending_vectors/attempts.rs","sha256":"47ef3c8cb1c5504d47ae9a0088705ce6715fe86bac1671a34a56fb38a64d0dd3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/bounds.rs","sha256":"e612217307e1da5b0eb5ee6582a7458bb064b8aa8a529fc6555b1b334127ab68"},{"path":"product/runtime/auths-gateway/src/pending_vectors/codes.rs","sha256":"e00670a5ef24eb856cc2c6dcda8e5a263842f55c76bb939c0c27bd9df37e5522"},{"path":"product/runtime/auths-gateway/src/pending_vectors/keys.rs","sha256":"f84c56f2ea9cb34b2b79c72d13fbf2c6585010ec1ed450af58a78c80c1ea1edd"},{"path":"product/runtime/auths-gateway/src/pending_vectors/mod.rs","sha256":"5de8340f0ef71a0b57a09e323fefe473d3160c6ae952b9ba46f714825fbacafc"},{"path":"product/runtime/auths-gateway/src/pending_vectors/outcomes.rs","sha256":"8ec07b9511b48913af36ac999d2aa0e82924289f6acb23ddaeb9f00f99815166"},{"path":"product/runtime/auths-gateway/src/pending_vectors/production.rs","sha256":"c2fa18b5d96c87689fe60d95faadebe2c7fdf5b78be872ca15a67ad980106ed3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/recipes.rs","sha256":"51693208270231c25c3aef2a32151d5962114c71e86b88cb9df83181c7af83d9"},{"path":"product/runtime/auths-gateway/src/pre_entry.rs","sha256":"06ea78ca140468bfaba17d9ab04912ad68673954c3203c98fed28272ff2a00c0"},{"path":"product/runtime/auths-gateway/src/property_tests.rs","sha256":"939c081e2e154aaf10186754044bdd65608932c899b970a04a71d0afaa999a93"},{"path":"product/runtime/auths-gateway/src/qualification.rs","sha256":"a4398512ccb7bb494000fe38f03e0faa7b82d1f80ef5ee2dfa75698ae4f5a9be"},{"path":"product/runtime/auths-gateway/src/qualification_tests.rs","sha256":"4473add5729b97faf04d7be7fd8cf3bbacd7f545e1b61c7d2782563011906b4d"},{"path":"product/runtime/auths-gateway/src/quorum_tests.rs","sha256":"a78380b019104d688c11a4410082c7e08ded3106aab099954c4f8a1b4ae0fd89"},{"path":"product/runtime/auths-gateway/src/readiness.rs","sha256":"911c3f11892f94641574375e2da4c671c802738f71082f12c39832331052d43d"},{"path":"product/runtime/auths-gateway/src/recipe.rs","sha256":"fecf9af67e7afc48d080e9f8f55f8ce28e49d0e08988717a27908bbda461d6b6"},{"path":"product/runtime/auths-gateway/src/recipe/lower.rs","sha256":"8088b8751ed831dbb48247af953c6290ac95e2a438ccd5bd65eff54be06a1fd1"},{"path":"product/runtime/auths-gateway/src/recipe/review.rs","sha256":"c3eb7d9fdd98dacf52750b14b67ad7b7faaecbbdeafff1e0b049f67d0a2d0139"},{"path":"product/runtime/auths-gateway/src/recipe/runtime.rs","sha256":"c286f0d15f974402822c0810d8e97f98411dc1c557755cc23e540d85e2bb42d9"},{"path":"product/runtime/auths-gateway/src/recipe/source.rs","sha256":"1af50298fb1461e1b24cbdf560d43124d6b1c4c529586c911b1c4797214a69ff"},{"path":"product/runtime/auths-gateway/src/recipe/tests.rs","sha256":"aac551a2481bbc60864c64079bc667dcb232e45a0f41a04073ed84ab5dbe1fce"},{"path":"product/runtime/auths-gateway/src/recipe/validate.rs","sha256":"3711b17605cb7b0d639bc1b180449231f5882a306cab20e2c7782155cc63b0d4"},{"path":"product/runtime/auths-gateway/src/scenario_tests.rs","sha256":"d8271761b12597bfe1233f8eb5ad1d4e5498c5d03388e832e24ab818484a1de4"},{"path":"product/runtime/auths-gateway/src/separation.rs","sha256":"be9306848ca5d801767cf6aa14247c8618312ef0e202f00ce0c24c4844491061"},{"path":"product/runtime/auths-gateway/src/store.rs","sha256":"1e5288345c2cb1421aeda277b3158d07607404b0ec46943222ac107b63dcbb46"},{"path":"product/runtime/auths-gateway/src/store_testkit.rs","sha256":"88d82fee42f1b8ef521e8deef0216e938ebeaad822eb2f5020e70b89d145ea70"},{"path":"product/runtime/auths-gateway/src/submit.rs","sha256":"c78dbbba7c45b443febf655056c5edcd635e77be7b21c5b2c318097502415ffe"},{"path":"product/runtime/auths-gateway/src/support.rs","sha256":"33c87008b6643e3e595e5af0c221ee5460df69e17cc69be2edcae13474d0cdb9"},{"path":"product/runtime/auths-gateway/src/transport.rs","sha256":"be2c6dc75b8daec110bf8749fedc3823f6067d40b999aa3eb21126896a97d3ad"},{"path":"product/runtime/auths-kernel-runtime/Cargo.toml","sha256":"926bcd0053e5edd703be8f0027ad009e2982db013c8174c1366edbf38b48087d"},{"path":"product/runtime/auths-kernel-runtime/src/lib.rs","sha256":"7108faae9ca4bc32dc093ddaf885ac8f74f3c9b8d317b7c7d0ed00d1d0ab5972"},{"path":"product/runtime/auths-lifecycle/Cargo.toml","sha256":"c5053c705f8d5554b44e432fe75287a2faf11d644e5a2552e45ad6cd94176af5"},{"path":"product/runtime/auths-lifecycle/src/codec.rs","sha256":"51c4b746749150e8bfcd8ff972b3f6c1ef40bec15583448ec1b471d9ad737dc0"},{"path":"product/runtime/auths-lifecycle/src/digest.rs","sha256":"55282cd7d8aba37713c2dcb5357c9877819edb72a30eadefb860d28d7d3a3eb7"},{"path":"product/runtime/auths-lifecycle/src/identifier.rs","sha256":"31620e8c16de68d3d2d3b84d6353c1a5b9d4151d8247f91fa389b906a8e660f1"},{"path":"product/runtime/auths-lifecycle/src/kernel.rs","sha256":"2abb8c094b36d35b364e74d78091d14c5d6f3d1eb6552cca3b5538dbd017ce23"},{"path":"product/runtime/auths-lifecycle/src/lib.rs","sha256":"afe5a345cd309b5a4f08ffba3170a6d7f16ff914892b3f2006d5208ed24ec736"},{"path":"product/runtime/auths-lifecycle/src/model.rs","sha256":"1af12bbeeeaa65ec02ddcebd7d2c8c92ec1e339fa40ae85b45ab9b01a722a4fa"},{"path":"product/runtime/auths-lifecycle/src/operation.rs","sha256":"78e6d05fcf5d7ea4f148032a3fa26fdfcab77eb346019effe927b08e0d64d732"},{"path":"product/runtime/auths-lifecycle/src/registry.rs","sha256":"53495fe6f7a77422593a41623e28716f1c140dcc1e00f87f6b0ffbfb93a5ef90"},{"path":"product/runtime/auths-lifecycle/src/sealed.rs","sha256":"2e0c03b5813c926c159598bb7890d1523825edbe57cd687d42a5dfb3374a0c19"},{"path":"product/runtime/auths-lifecycle/src/test_support.rs","sha256":"221d9a5c5ef8e1f9f8fd66927484eaf813571d0568470278ecd8fa08a5eec8cd"},{"path":"product/runtime/auths-lifecycle/src/transition.rs","sha256":"011805a28efdd541f44ccea54dd0e34a1e58f4004447ee58013703b4fb6b2822"},{"path":"product/runtime/auths-runtime/Cargo.toml","sha256":"dd29d80a8b4bb56c869f036a6c9998f6e6d1c0383ac5dc03fa42b24abe2a7ff7"},{"path":"product/runtime/auths-runtime/src/lib.rs","sha256":"132ca03d58c14905d3a822a4972f42a22a5ad33a45f2ba9ca44f3a57d810b4b0"},{"path":"product/runtime/auths-runtime/src/production.rs","sha256":"fd4eff4270c571c10fcff6cf27df28961ebf074de8a1a028f500fda1ca376820"},{"path":"product/sdk/auths-approval-quorum/Cargo.toml","sha256":"df904971fca87a24194c5816738a331588fe8f164acb5d70839a35dca5f57114"},{"path":"product/sdk/auths-approval-quorum/src/lib.rs","sha256":"72e4086088a1c0912e4e1a9e980f26a5c280bf5ab16ea39c9f0f58d5096ac2ce"},{"path":"product/sdk/auths-approval-quorum/src/remote.rs","sha256":"9fa029c7c63003adf260f8aec55160c545681c60c1bace0d934e7525862aac7b"},{"path":"product/sdk/auths-approval-quorum/src/remote_tests.rs","sha256":"8a09ce17cfee82a035a74edd535f3ebeb3db0e078784740d3997b17dbdb10197"},{"path":"product/sdk/auths-approval-quorum/src/tests.rs","sha256":"0acbf12be3e497dcc6c2d8f29c9af3b1a7ed8e11b75f6399570d4f217a785060"},{"path":"product/stores/auths-stores/Cargo.toml","sha256":"a32c4b76d17b264be5d40d24497ff237e1ed87822e8bab86229b3db93106dbe3"},{"path":"product/stores/auths-stores/src/gateway_attempt.rs","sha256":"185da8f4a220fba836d5b78a9311f03204681c43a3c53951008084d135bf4d21"},{"path":"product/stores/auths-stores/src/lib.rs","sha256":"e721262edf8a9ab5568ddc27639176312d4a366203b5f73e2d7c11fde2c554e9"},{"path":"product/stores/auths-stores/src/lifecycle.rs","sha256":"94f64d25bc178a9e60ba3c0ee6915d7fb3af7c4468792d76b4e70f43f4de1e2f"}],"schema":"auths.gateway-semantic-closure/1"} \ No newline at end of file +{"files":[{"path":"Cargo.lock","sha256":"c94ed342774d5e2823f01ecf74b8a4812c5f9a6b0cf811d31f2e2cecb671a275"},{"path":"Cargo.toml","sha256":"6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24"},{"path":"core/adapters/auths-did-keri/Cargo.toml","sha256":"86ba3e3f9a0a70d970568bfb3113b7ba7bbdd81c3eebbb52743dd574a0c0ecaa"},{"path":"core/adapters/auths-did-keri/src/lib.rs","sha256":"a75674842f8a7142004369ccd206ab43e476459293f0ff4bed4d4e659031b3e3"},{"path":"core/adapters/auths-did-key/Cargo.toml","sha256":"d5a3ae07ecde83f91eed4c3785051dd0f44eab6c891754f3309b6b40596707d7"},{"path":"core/adapters/auths-did-key/src/lib.rs","sha256":"b76a3f4528a725df53cfa9242e6e414e1d26caa48468aaed497e28b121f4497c"},{"path":"core/adapters/auths-raw-key/Cargo.toml","sha256":"f49616bc18c19e6aaa7e6a02ccebcdb9f5c1422c1278ef9869e0dbf22ceda7be"},{"path":"core/adapters/auths-raw-key/src/lib.rs","sha256":"45eec1b295dac3bed65cd79c942870b926b06b3f5d38eaebaeb6140ac69315fa"},{"path":"core/crates/auths-algebra-kernel/Cargo.toml","sha256":"0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba"},{"path":"core/crates/auths-algebra-kernel/src/generated.rs","sha256":"ae4bcbef42a408c7ffa0c6a74a42f7de177a6f14479e51d205acf830bda05960"},{"path":"core/crates/auths-algebra-kernel/src/lib.rs","sha256":"6654667eeb9b353d6648954c9fd2e8838462a82ce6b2803eb49e1366892c68c6"},{"path":"core/crates/auths-assurance/Cargo.toml","sha256":"afcb12a97ddd09d7a264b9ecd3fcaefc865ff2c9b4539ee85b00883420ba333a"},{"path":"core/crates/auths-assurance/src/lib.rs","sha256":"0fb2ec844d674b25a9e20b1601452c89c2454901fa506adfa9bb38ef9a7fa213"},{"path":"core/crates/auths-author/Cargo.toml","sha256":"1e6f0e3bc079ddb558decf0db26b291c6e72fc47327b6df1b7650d41689b215f"},{"path":"core/crates/auths-author/src/lib.rs","sha256":"e14475f2f49715a1869d5fa6b11ff1fbb72497e39097e09f833b0bae7e5b3f2b"},{"path":"core/crates/auths-author/src/observations.rs","sha256":"dda7d6bfa6f4bd7e95a480ca283c2c0e996f69c5c15cb0c7197af328131a7066"},{"path":"core/crates/auths-authority/Cargo.toml","sha256":"4f68212938029f79ebd857b4f3038494eb85d0163d49f07e51376715cf959815"},{"path":"core/crates/auths-authority/src/lib.rs","sha256":"da88d5194de4e17449e69972c0fb042afa3c39798a8f570f30771e77c384f1eb"},{"path":"core/crates/auths-codec/Cargo.toml","sha256":"e20e51826e17814effd9d8925d18d5fbdd6c0d37bf50231e743ec2611314722c"},{"path":"core/crates/auths-codec/src/approval.rs","sha256":"fbff43bf4d57f69f8b7738a8647751cde75c5a932dee65d924a1fe9c7202f91f"},{"path":"core/crates/auths-codec/src/bounded_policy.rs","sha256":"d21f6728be2d8a04b6d94921f2b683f7e61cbb42e0ac6866f1c88a49caa534c3"},{"path":"core/crates/auths-codec/src/decode.rs","sha256":"ba2999584cdf53b1b517ecb9c7ea50d39efee17c666a9a38e2ad1ac94379f778"},{"path":"core/crates/auths-codec/src/encode.rs","sha256":"8491192053e2e15d62b4d2a491de22405b7487ead69ab6f6bca40669ce7ca5f7"},{"path":"core/crates/auths-codec/src/error.rs","sha256":"fecb0737c16deb42d859f1dc7727c698438d9ac12064fd99e0024629642c390c"},{"path":"core/crates/auths-codec/src/hash.rs","sha256":"f88e111f1dbb2cef6b7b5e9c948cb45ff92e366710c8a5f5c636138aa748479e"},{"path":"core/crates/auths-codec/src/lib.rs","sha256":"3b0e5c94c6f34f750b88a9333e1d5c8145746d845d3a23e0d2f61807cf592ea7"},{"path":"core/crates/auths-codec/src/observation.rs","sha256":"38328b0c71ff97a4196eeade8b4faa889527ff1f80bb168468bcd49082a3987e"},{"path":"core/crates/auths-composition/Cargo.toml","sha256":"331e13025eb82588b5269ed3975929eb41c823d588c49e4c296273d85c6fe80e"},{"path":"core/crates/auths-composition/src/lib.rs","sha256":"e42e3b0b6a9985b73c533aeb23799c638979aa27a9ce7d0f10a8d60340570fb1"},{"path":"core/crates/auths-model/Cargo.toml","sha256":"565c15302b0cc9270db1e28efa3862804846850ba933cc17aea8abcec4a65987"},{"path":"core/crates/auths-model/src/approval.rs","sha256":"54cf44a9ef747ec21546a4086aecfb130bc7803b0d646430e6082df51e6e305f"},{"path":"core/crates/auths-model/src/bounded.rs","sha256":"f90496abc0a06c028b4d850af6ddab7d850bfafeaa3d042f1b1246a41d8bbbc9"},{"path":"core/crates/auths-model/src/bounded_policy.rs","sha256":"306a8f049cc7cfc7635fe0e4de47eb7813eed63d3c14c3be2b51586aa4eea450"},{"path":"core/crates/auths-model/src/lib.rs","sha256":"e7cfe6bb9574c6b016aa63e70658c31e0b90903ec6479a49f4a2ceb64f5bad97"},{"path":"core/crates/auths-model/src/observation.rs","sha256":"b3ed3e3cc090afca2896a7d3de7988afccc1ee1ea0ebd91b51a8bc0f20ad8dbb"},{"path":"core/crates/auths-multikey/Cargo.toml","sha256":"858756c1197befcada06134742bffe8d58cf674cadd6c046bf710570e96efaf2"},{"path":"core/crates/auths-multikey/src/lib.rs","sha256":"f5177fffb11e40eeaaa665ba886c541fc1f24d5eacdd6983fb03dc20148733f0"},{"path":"core/crates/auths-ports/Cargo.toml","sha256":"596a9b0f5af3717c16a6d13f7054d8a106bcd9f01f5f72c2235dd2afcf0ab16c"},{"path":"core/crates/auths-ports/src/binding.rs","sha256":"a16c012d40aa4249e3ec54372b9611006d0bfe8c7dc3c741911c2194ad17736d"},{"path":"core/crates/auths-ports/src/diagnostics.rs","sha256":"aa596572503b5a65a918bb2ff38281c144ff53821ee914e9325c852828d852df"},{"path":"core/crates/auths-ports/src/lib.rs","sha256":"8da1debf86f9532df0660155d04298beb1ba3a1204508f8586e2e67cd2fb3449"},{"path":"core/crates/auths-ports/src/path.rs","sha256":"b68fc547b4e4d97a60cbbc1cc1939fc6b34a8233b81f840bd396914a707e3ea1"},{"path":"core/crates/auths-raw-key-core/Cargo.toml","sha256":"98c0bc8527a537512e43a74dd6ba9658c6f0cdc16610cf938e3f9b43785d836d"},{"path":"core/crates/auths-raw-key-core/src/lib.rs","sha256":"98c0500c41697aae28708ad0bf970b9a97583d96a3d2c18d23e7fa351e0f7d12"},{"path":"core/crates/auths-registries/Cargo.toml","sha256":"590e49e58b0622d9d6274fea46796dcdb07dec9550eff295cce6a6427ffa51e2"},{"path":"core/crates/auths-registries/src/lib.rs","sha256":"450d3886d85ee333b7e046317fb5b47cde62483d5f3e41d46265e2caf4c373ec"},{"path":"core/crates/auths-registries/src/template.rs","sha256":"1224039dd2b3ce6fa8357613d8cafbae40400493da7176da202b9ade62fa05e4"},{"path":"core/crates/auths-signature-core/Cargo.toml","sha256":"6bee2230eb30af1be0bd5c2d57bd3e1903497a70028d47290d4ac6e9e0e8bca0"},{"path":"core/crates/auths-signature-core/src/lib.rs","sha256":"6e3f9311ded5e49ea50d445eb21e6d8fa12442aa4362a73e0cb6fda15b7cd865"},{"path":"core/crates/auths-signature/Cargo.toml","sha256":"7f7b5682466ba439d8c59579022cb61068cad9fb4bd2d73e1cc21327c902b450"},{"path":"core/crates/auths-signature/src/lib.rs","sha256":"b3d9ac4cc3ba0797b9e1c09f2d6ac05089b25dac4e285a5af28c0165b33d925b"},{"path":"core/crates/auths-verifier/Cargo.toml","sha256":"c43358e06a33324b41a8b93e5cc7279c55f7d21f1f6cfaa539a3fc7b4c27a38f"},{"path":"core/crates/auths-verifier/src/approval.rs","sha256":"c3cae6a49e169051eb555bb092b1069a4d422516d6a2114623a89e5f31ff923f"},{"path":"core/crates/auths-verifier/src/causal.rs","sha256":"9635230f33b13a263573d319ac8a1976addbcc07677514a43e3c7bf28dc04587"},{"path":"core/crates/auths-verifier/src/lib.rs","sha256":"f22dec38dfa47ced8da4f605390da8453273bee1da010f57fd1fdfcb10e0b389"},{"path":"core/crates/auths-verifier/src/observation.rs","sha256":"0bb07f06a0f9524c88427df1c972b1de8ba038a9eeeb15d3134c25125ae84b1e"},{"path":"core/crates/auths-verifier/src/trace.rs","sha256":"2213d72023a1d9e0413a2cf2c51c3dad9e04775d86033a0caaa9d29a8f0036f8"},{"path":"exchange/crates/auths-proof-exchange-model/Cargo.toml","sha256":"34b2db64f93a288e942b5a3918d28cdcbef906e0dc9074ce848018d3d5f7a1fa"},{"path":"exchange/crates/auths-proof-exchange-model/src/lib.rs","sha256":"49fac5aff2339d3a57c41cb8bb2a82852538e8f77ecc4b157c88e264ff31fb55"},{"path":"exchange/crates/auths-proof-exchange-port/Cargo.toml","sha256":"7ff660f1b7579dc570c791090aeb450404fbbf44c92781e289f5ccdde746d739"},{"path":"exchange/crates/auths-proof-exchange-port/src/lib.rs","sha256":"b408fb40c6432edc1facb3d8b3e9433a033f8dc73fe2e0ba5a88c972ca675021"},{"path":"product/config/auths-config/Cargo.toml","sha256":"e4b568ab9f6d84f7d7e6d66443fe825f360db9c27bc7c31d6ddc0647ba3ab304"},{"path":"product/config/auths-config/src/lib.rs","sha256":"fecf00ea65cef9018fda9af2063326d7065b869266d0d9e73a4f06816f1102cc"},{"path":"product/errors/auths-errors/Cargo.toml","sha256":"3b3a199b6460ba75bda84475bb5accd35e1485448a3981038db85bf4772dd350"},{"path":"product/errors/auths-errors/src/lib.rs","sha256":"7feeb9069fa4003f94f1f07c1c94619cf1c883e0dbaaf2187f04d0f742264bdd"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/Cargo.toml","sha256":"716f1f2a117d6d69d8effe9ee9057e24ba3502f20af6a602b06facb638cdabed"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/api.rs","sha256":"9ea61dd7ddd93282b073b98e453e6b75b26dc49689c04e9782435d06a3a09e48"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/clock.rs","sha256":"73f0a6e0f5903883329fa6683f5888288f759512ac69e5c87efd2b6b87f7d79f"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/http.rs","sha256":"14c1fce14e24c984b2a275563a29b6326fb08367922b6e8d37ba38b9cb81aa2b"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/identity.rs","sha256":"186de11230c8b33375951c4368609f8976bf9795f171af3fd7fac26207a94361"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs","sha256":"0b4617d044f5254a5ab22f5a2578f91cc025206a8c1845be39c1c56dcdf7a5df"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/names.rs","sha256":"41bb23572d6002e23ee103d6fe70ecd68764861c6f2e48a1c53af998270a4afa"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs","sha256":"39fed883f4802e68d3b41a68fea0aba0737810996b33d13577de70faba004c29"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/store.rs","sha256":"fc60ee9c49b2f4f063c449b4c78100c5c4872779e94ca168f796603b380ef6e4"},{"path":"product/integrations/auths-custody/Cargo.toml","sha256":"1e14034185ad1ec24a977fd5f41d0abee219606245c046ce2a82287fadef448b"},{"path":"product/integrations/auths-custody/src/conformance.rs","sha256":"8ed1afd58f18fc6becc268908aa6419c9aa404c79da0197963eb2599df44acf6"},{"path":"product/integrations/auths-custody/src/key.rs","sha256":"70cbb0fd21b6f5652157845a22c35be2d0f6c05b3d138fc4b9bb6dbdc3d81c40"},{"path":"product/integrations/auths-custody/src/lib.rs","sha256":"8ee593c1f59b0fd2126bdda9138026f5bc531beb64d4489a99785842e7b98b43"},{"path":"product/operations/auths-operations/Cargo.toml","sha256":"73dde1e914ba5e1386f8d49c0d730423cc72ae77ec44c6554a6a75cc8e8922b1"},{"path":"product/operations/auths-operations/src/explanation.rs","sha256":"b4a39bcbd5712cb9e735ee7deeb281f3fa6af5ddca973735bf3d87dce427ef11"},{"path":"product/operations/auths-operations/src/lib.rs","sha256":"3f401a56555113b98f57bca172a2660eaecedf76247b83a3fdbb089c133a29cd"},{"path":"product/operations/auths-operations/src/render/json.rs","sha256":"2ae042639960afee123730e945d373bc5dda1d2b3af20ae16c939a7e99b9e418"},{"path":"product/operations/auths-operations/src/render/mod.rs","sha256":"b3b7f6fe473f49227ace5a68bfc3d8dc14b5db8dd9888fd9e207070337b1b8bf"},{"path":"product/operations/auths-operations/src/render/text.rs","sha256":"f216cf3bdb00e264523271b16e7059535ac6b1aabf271cebd7935af155e4bfec"},{"path":"product/policy/auths-bounded-policy/Cargo.toml","sha256":"babd5d200923137ead71d8c2528f847cea323ce98da942a1320b054436612c47"},{"path":"product/policy/auths-bounded-policy/src/arithmetic.rs","sha256":"75e43c5d4eab8d1f71c1daf53839f5f9fe45a400afc1f63a30c6f55ce3632627"},{"path":"product/policy/auths-bounded-policy/src/commitment.rs","sha256":"c5706f2d583454e1a7f570f7ada138d4d864bef0205dfae7c1296774f396bb3f"},{"path":"product/policy/auths-bounded-policy/src/eligibility.rs","sha256":"c9acdfb793074e687fc36efad506be27dbd99ffbf40387bc66c8de39ef238432"},{"path":"product/policy/auths-bounded-policy/src/identifier.rs","sha256":"0006a32bae9eb16c4178cf797df418d2b0a781f2bc6474b741dc1a908141831c"},{"path":"product/policy/auths-bounded-policy/src/kernel.rs","sha256":"99187c28b161ac70bee1afed60711f7f645adb4d1671a01863f9849b369811d5"},{"path":"product/policy/auths-bounded-policy/src/lib.rs","sha256":"76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c"},{"path":"product/policy/auths-bounded-policy/src/receipt.rs","sha256":"3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad"},{"path":"product/policy/auths-bounded-policy/src/registry.rs","sha256":"4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0"},{"path":"product/profiles/auths-profile-api/Cargo.toml","sha256":"7ae85761f58625b5d678f961fd052eebf3e000ef565c7312e3ac857763c0017f"},{"path":"product/profiles/auths-profile-api/src/lib.rs","sha256":"a194b82b20bf8aa864c2334ef6c6aec30b2154ded972862252d5dcefa488ab95"},{"path":"product/profiles/auths-profile-mcp/Cargo.toml","sha256":"db264fc25242f7b7e4133cbe5782545b3107b406c87168ae072683cfb59eac66"},{"path":"product/profiles/auths-profile-mcp/src/arguments.rs","sha256":"a5de696586d507e2aee4a49fee99ef1ef4c51a2e46603f8838f1af6d9009833f"},{"path":"product/profiles/auths-profile-mcp/src/lib.rs","sha256":"d0f8b733a09ef8408336cdebc8948d6a5861012ce6878598b11be7084dfd4280"},{"path":"product/profiles/auths-profile-mcp/src/session.rs","sha256":"166c281fa66333388e4760d6098dad02d3359e1d5de4b8f93312c014f97abb03"},{"path":"product/qualification/auths-recipe-qualification/Cargo.toml","sha256":"b7b15b30b9a3d96d4f089d514266d3a892de6608d30707aa44be31cca89ca9fe"},{"path":"product/qualification/auths-recipe-qualification/src/canonical.rs","sha256":"30a9b50777f0dcb4b606abfee2467d5a975d9f6ad941ab6c13ca3df5b359f667"},{"path":"product/qualification/auths-recipe-qualification/src/closure.rs","sha256":"0ad6aee9bd981e2863fa725f209ec84031db2ff12f4c7ac3aaf5120f0bb86039"},{"path":"product/qualification/auths-recipe-qualification/src/error.rs","sha256":"52d5cf720a1e4579008fdda90a3ac2c31f0b8db57985f121f65e54b4da2b7dd1"},{"path":"product/qualification/auths-recipe-qualification/src/evidence.rs","sha256":"1a4cb862f725b02f9efd827db99637ea8178a5236aa020ec271a363edbe7b362"},{"path":"product/qualification/auths-recipe-qualification/src/ids.rs","sha256":"e81a906d571497ab2da753e1532d4443706410e0b75fdd59a7d2d788c7aec403"},{"path":"product/qualification/auths-recipe-qualification/src/lib.rs","sha256":"195b19f46e1e94a0f3594ad5958e5715bc5e3ad415bdfe6428dfc1b6dd3f4631"},{"path":"product/qualification/auths-recipe-qualification/src/model.rs","sha256":"3484eb0ec287b23d4682ade7b1b0f8d1335985b3fb180f06fc28716076957d5f"},{"path":"product/qualification/auths-recipe-qualification/src/release.rs","sha256":"d816b53e2275e902c750ad03803061844e259e28560ab2d1c77e8a43981a4d6a"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/mod.rs","sha256":"7f15b68e05a04f202bcb1fb80de1d9a9a4fda8bfd6af2cd4e5c660fc75d96fe5"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/schemas.rs","sha256":"c59feec2805621f341a90f81fc005e2c12f7a70f9d264fdeacccb2be4fe1c046"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/verification.rs","sha256":"6a6b5834c5dae10af1ba8939b2deae43b85db71544dc8f077ff63b7fe68ac8a8"},{"path":"product/qualification/auths-recipe-qualification/src/verify.rs","sha256":"edd33589c54fb79bcfccc4cf4e6ccf95bbca088318bb7f8dfc27da684b4fa671"},{"path":"product/receipts/auths-receipts/Cargo.toml","sha256":"6001fa1375899953aafcb07c23a6da0c8f57ea7ec08bb9c950b12a60a8cc6f0f"},{"path":"product/receipts/auths-receipts/src/disclosure.rs","sha256":"ba9ed439be0a320c8a01f5b6e9b51361c1a37e076947490d8e4a484ba6bb119c"},{"path":"product/receipts/auths-receipts/src/lib.rs","sha256":"547a57c4160256719cafb7d0ab972d9fc80b0da14fbbce4148c70c414070ff36"},{"path":"product/runtime/auths-connections/Cargo.toml","sha256":"babeb6e1dda3dfb66291713ce1e43dce5c349833d0b50ea4dccbf986030026b2"},{"path":"product/runtime/auths-connections/src/credential.rs","sha256":"82921413bb053f0f6c7931fbd4e6a86c8cc1d8c6b51debd9c2cef33a8d5b1c51"},{"path":"product/runtime/auths-connections/src/kernel.rs","sha256":"a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8"},{"path":"product/runtime/auths-connections/src/lib.rs","sha256":"79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22"},{"path":"product/runtime/auths-connections/src/model.rs","sha256":"de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77"},{"path":"product/runtime/auths-connections/src/registry.rs","sha256":"e57640e003e72ad3235c567c2bb944a262bd64e673f023b62ea091094cc7e946"},{"path":"product/runtime/auths-gateway-kernel/Cargo.toml","sha256":"34f864e67656af4ac7e5c7a347a23f01fc8ab31365b8e23c0ef474483b14a183"},{"path":"product/runtime/auths-gateway-kernel/src/construct.rs","sha256":"e9d65744bae273d65face4285e5d2da75c06a92ab48f7b8333d496604e31c63c"},{"path":"product/runtime/auths-gateway-kernel/src/lib.rs","sha256":"cfda6f8453426564c085475f183b6f790b438768a19668f1b65d33ba59dc8632"},{"path":"product/runtime/auths-gateway-kernel/src/order.rs","sha256":"e0045f877c4b7fe3860c291039853885064ddcdebba7c9b345ab65e81e646dda"},{"path":"product/runtime/auths-gateway-kernel/src/outcome.rs","sha256":"e9785b1afe70788c89b51b18655bcd5acff7b0c8e3d12fb79c6f05a202e67e6b"},{"path":"product/runtime/auths-gateway-kernel/src/ratio.rs","sha256":"7ace22264812e6fc1ef3a62afee402cf43494bb71ae0d3de219ad1b39d690bcb"},{"path":"product/runtime/auths-gateway-kernel/src/recovery.rs","sha256":"9f46dcd1685ab6e4d1ba04a3fc286a9f3afee8fb47829be1fbc670a7926a2dc6"},{"path":"product/runtime/auths-gateway-kernel/src/transition.rs","sha256":"cefb8f01d915880f6921f2501ff881ad94b9de61072c34d9cd19220992f97374"},{"path":"product/runtime/auths-gateway/Cargo.toml","sha256":"00b28be86921dcdc0ad90cce0c62c2961cafefe96ea6c2edf0e926c3d405ccad"},{"path":"product/runtime/auths-gateway/src/admin.rs","sha256":"2d5cc67afac42fbd15f36e2d1693cd1b20cedacf775040dce6ffe04ccc94c9ea"},{"path":"product/runtime/auths-gateway/src/app.rs","sha256":"6f80f63833ea0815bb44fbf3b0cc54624a08e9fb578b035819f2980dc04e8256"},{"path":"product/runtime/auths-gateway/src/audit.rs","sha256":"0edb2037eb7b5d6f13acfce85c54f62a82bf7fdd31bc7e626c4fec183cef61dd"},{"path":"product/runtime/auths-gateway/src/audit_tests.rs","sha256":"990969384a52d75bc2489d9d412a9e7dd814bca1c8f65c701d6205fae62a15d5"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway-harness.rs","sha256":"12b0c24d36b2e6a3be392d3c081a783b355fdd67dc5b54bacc0410e803116b8c"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway.rs","sha256":"b1dab74ec9a0c301fc9896de15d4676274461928f8b09f5346c561d731d123b0"},{"path":"product/runtime/auths-gateway/src/binding.rs","sha256":"663b0ce878319511aa7d05722ab4ab2fa9be18817884ffb2ee9f131ff1e382d1"},{"path":"product/runtime/auths-gateway/src/bounds.rs","sha256":"9cfa0eae4973e5e047a198360b22f041708fa20276b0b90c2ec440f06915d64b"},{"path":"product/runtime/auths-gateway/src/bounds_aggregate_tests.rs","sha256":"ab34f227b7c8692ba1da88ccb32bb3687a66adf8353d8282fae905d4a88eb612"},{"path":"product/runtime/auths-gateway/src/bounds_tests.rs","sha256":"74136bc570da7b9338b5a1a1ed9d3fd892c55135160964f9d3ac0e2cf5741375"},{"path":"product/runtime/auths-gateway/src/connection.rs","sha256":"7b5d049c258a26ed1c93ecf860f51d051a8a65f9b93554af0b1ea93862398ec9"},{"path":"product/runtime/auths-gateway/src/credential_journal.rs","sha256":"8e2b0733038d93ca5df770d27a870237e3b65664fa48da017d964a65bbbe25b8"},{"path":"product/runtime/auths-gateway/src/echo_verify.rs","sha256":"6d453051665f823abd7354d5c50031d9524cf47d6092d2f09080ae814e3b9575"},{"path":"product/runtime/auths-gateway/src/engine.rs","sha256":"5c04a836112d02677de66a1b79d7487fc95fcaac4a9dfc9e1044a6c19ea1282d"},{"path":"product/runtime/auths-gateway/src/fuzzing.rs","sha256":"ed3b0028487eb546a3b0a91d115aa8f18bcea324b61620bfe8e35a9e6ab18758"},{"path":"product/runtime/auths-gateway/src/generation_floor.rs","sha256":"999ec17cd6f0c11ab144d971e75dcf824b8b71fbffa355cde0dff9555dd7db78"},{"path":"product/runtime/auths-gateway/src/harness.rs","sha256":"c87e479f3eb281960f6c9c80d43c7560d7ccb654b0154ec823d3fcec4884ac05"},{"path":"product/runtime/auths-gateway/src/lib.rs","sha256":"b182052835a2cd631d1f801a74788d6ac1ef9cae21ade9ab4ffc270cd6f667ed"},{"path":"product/runtime/auths-gateway/src/listener.rs","sha256":"aa08239bcbc1fcb55e8a212fbdf6a84f12985b0d436dcb51dc58b06e59e435f2"},{"path":"product/runtime/auths-gateway/src/observed_tests.rs","sha256":"a22be071695f89ca2578a4d82fd80d9cb82289213c9bdb8f0470f6b2dc3d9201"},{"path":"product/runtime/auths-gateway/src/observer.rs","sha256":"562ffcaea071c3856e0708dc2fe33516917e145d2438aabb75af0a2b6ba01046"},{"path":"product/runtime/auths-gateway/src/onboarding.rs","sha256":"0dfd7d67e7f02f18a28d1c86ca1b7751d7463f5efcdbe3825de0ad8cbccb3891"},{"path":"product/runtime/auths-gateway/src/operator.rs","sha256":"c3c36954a3e86723df035b47f43b85fc8ab3a6292983522b6258d5c6b4e6c4e4"},{"path":"product/runtime/auths-gateway/src/pending_vectors/attempts.rs","sha256":"47ef3c8cb1c5504d47ae9a0088705ce6715fe86bac1671a34a56fb38a64d0dd3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/bounds.rs","sha256":"e612217307e1da5b0eb5ee6582a7458bb064b8aa8a529fc6555b1b334127ab68"},{"path":"product/runtime/auths-gateway/src/pending_vectors/codes.rs","sha256":"e00670a5ef24eb856cc2c6dcda8e5a263842f55c76bb939c0c27bd9df37e5522"},{"path":"product/runtime/auths-gateway/src/pending_vectors/keys.rs","sha256":"f84c56f2ea9cb34b2b79c72d13fbf2c6585010ec1ed450af58a78c80c1ea1edd"},{"path":"product/runtime/auths-gateway/src/pending_vectors/mod.rs","sha256":"5de8340f0ef71a0b57a09e323fefe473d3160c6ae952b9ba46f714825fbacafc"},{"path":"product/runtime/auths-gateway/src/pending_vectors/outcomes.rs","sha256":"8ec07b9511b48913af36ac999d2aa0e82924289f6acb23ddaeb9f00f99815166"},{"path":"product/runtime/auths-gateway/src/pending_vectors/production.rs","sha256":"f574cabfa4687a4fc846b8f6a234b68ec53b876aed548b11445729cac1a55ede"},{"path":"product/runtime/auths-gateway/src/pending_vectors/recipes.rs","sha256":"51693208270231c25c3aef2a32151d5962114c71e86b88cb9df83181c7af83d9"},{"path":"product/runtime/auths-gateway/src/pre_entry.rs","sha256":"06ea78ca140468bfaba17d9ab04912ad68673954c3203c98fed28272ff2a00c0"},{"path":"product/runtime/auths-gateway/src/property_tests.rs","sha256":"939c081e2e154aaf10186754044bdd65608932c899b970a04a71d0afaa999a93"},{"path":"product/runtime/auths-gateway/src/qualification.rs","sha256":"a4398512ccb7bb494000fe38f03e0faa7b82d1f80ef5ee2dfa75698ae4f5a9be"},{"path":"product/runtime/auths-gateway/src/qualification_tests.rs","sha256":"4473add5729b97faf04d7be7fd8cf3bbacd7f545e1b61c7d2782563011906b4d"},{"path":"product/runtime/auths-gateway/src/quorum_tests.rs","sha256":"a78380b019104d688c11a4410082c7e08ded3106aab099954c4f8a1b4ae0fd89"},{"path":"product/runtime/auths-gateway/src/readiness.rs","sha256":"911c3f11892f94641574375e2da4c671c802738f71082f12c39832331052d43d"},{"path":"product/runtime/auths-gateway/src/recipe.rs","sha256":"fecf9af67e7afc48d080e9f8f55f8ce28e49d0e08988717a27908bbda461d6b6"},{"path":"product/runtime/auths-gateway/src/recipe/lower.rs","sha256":"8088b8751ed831dbb48247af953c6290ac95e2a438ccd5bd65eff54be06a1fd1"},{"path":"product/runtime/auths-gateway/src/recipe/review.rs","sha256":"c3eb7d9fdd98dacf52750b14b67ad7b7faaecbbdeafff1e0b049f67d0a2d0139"},{"path":"product/runtime/auths-gateway/src/recipe/runtime.rs","sha256":"c286f0d15f974402822c0810d8e97f98411dc1c557755cc23e540d85e2bb42d9"},{"path":"product/runtime/auths-gateway/src/recipe/source.rs","sha256":"1af50298fb1461e1b24cbdf560d43124d6b1c4c529586c911b1c4797214a69ff"},{"path":"product/runtime/auths-gateway/src/recipe/tests.rs","sha256":"aac551a2481bbc60864c64079bc667dcb232e45a0f41a04073ed84ab5dbe1fce"},{"path":"product/runtime/auths-gateway/src/recipe/validate.rs","sha256":"3711b17605cb7b0d639bc1b180449231f5882a306cab20e2c7782155cc63b0d4"},{"path":"product/runtime/auths-gateway/src/scenario_tests.rs","sha256":"d8271761b12597bfe1233f8eb5ad1d4e5498c5d03388e832e24ab818484a1de4"},{"path":"product/runtime/auths-gateway/src/separation.rs","sha256":"be9306848ca5d801767cf6aa14247c8618312ef0e202f00ce0c24c4844491061"},{"path":"product/runtime/auths-gateway/src/store.rs","sha256":"1e5288345c2cb1421aeda277b3158d07607404b0ec46943222ac107b63dcbb46"},{"path":"product/runtime/auths-gateway/src/store_testkit.rs","sha256":"88d82fee42f1b8ef521e8deef0216e938ebeaad822eb2f5020e70b89d145ea70"},{"path":"product/runtime/auths-gateway/src/submit.rs","sha256":"c78dbbba7c45b443febf655056c5edcd635e77be7b21c5b2c318097502415ffe"},{"path":"product/runtime/auths-gateway/src/support.rs","sha256":"9fd979029793a22b15d9776a7fc172476fd7c126a80d4080c65d720845becbcb"},{"path":"product/runtime/auths-gateway/src/transport.rs","sha256":"be2c6dc75b8daec110bf8749fedc3823f6067d40b999aa3eb21126896a97d3ad"},{"path":"product/runtime/auths-kernel-runtime/Cargo.toml","sha256":"926bcd0053e5edd703be8f0027ad009e2982db013c8174c1366edbf38b48087d"},{"path":"product/runtime/auths-kernel-runtime/src/lib.rs","sha256":"7108faae9ca4bc32dc093ddaf885ac8f74f3c9b8d317b7c7d0ed00d1d0ab5972"},{"path":"product/runtime/auths-lifecycle/Cargo.toml","sha256":"c5053c705f8d5554b44e432fe75287a2faf11d644e5a2552e45ad6cd94176af5"},{"path":"product/runtime/auths-lifecycle/src/codec.rs","sha256":"51c4b746749150e8bfcd8ff972b3f6c1ef40bec15583448ec1b471d9ad737dc0"},{"path":"product/runtime/auths-lifecycle/src/digest.rs","sha256":"55282cd7d8aba37713c2dcb5357c9877819edb72a30eadefb860d28d7d3a3eb7"},{"path":"product/runtime/auths-lifecycle/src/identifier.rs","sha256":"31620e8c16de68d3d2d3b84d6353c1a5b9d4151d8247f91fa389b906a8e660f1"},{"path":"product/runtime/auths-lifecycle/src/kernel.rs","sha256":"2abb8c094b36d35b364e74d78091d14c5d6f3d1eb6552cca3b5538dbd017ce23"},{"path":"product/runtime/auths-lifecycle/src/lib.rs","sha256":"afe5a345cd309b5a4f08ffba3170a6d7f16ff914892b3f2006d5208ed24ec736"},{"path":"product/runtime/auths-lifecycle/src/model.rs","sha256":"1af12bbeeeaa65ec02ddcebd7d2c8c92ec1e339fa40ae85b45ab9b01a722a4fa"},{"path":"product/runtime/auths-lifecycle/src/operation.rs","sha256":"78e6d05fcf5d7ea4f148032a3fa26fdfcab77eb346019effe927b08e0d64d732"},{"path":"product/runtime/auths-lifecycle/src/registry.rs","sha256":"53495fe6f7a77422593a41623e28716f1c140dcc1e00f87f6b0ffbfb93a5ef90"},{"path":"product/runtime/auths-lifecycle/src/sealed.rs","sha256":"2e0c03b5813c926c159598bb7890d1523825edbe57cd687d42a5dfb3374a0c19"},{"path":"product/runtime/auths-lifecycle/src/test_support.rs","sha256":"221d9a5c5ef8e1f9f8fd66927484eaf813571d0568470278ecd8fa08a5eec8cd"},{"path":"product/runtime/auths-lifecycle/src/transition.rs","sha256":"011805a28efdd541f44ccea54dd0e34a1e58f4004447ee58013703b4fb6b2822"},{"path":"product/runtime/auths-runtime/Cargo.toml","sha256":"dd29d80a8b4bb56c869f036a6c9998f6e6d1c0383ac5dc03fa42b24abe2a7ff7"},{"path":"product/runtime/auths-runtime/src/lib.rs","sha256":"132ca03d58c14905d3a822a4972f42a22a5ad33a45f2ba9ca44f3a57d810b4b0"},{"path":"product/runtime/auths-runtime/src/production.rs","sha256":"fd4eff4270c571c10fcff6cf27df28961ebf074de8a1a028f500fda1ca376820"},{"path":"product/sdk/auths-approval-quorum/Cargo.toml","sha256":"df904971fca87a24194c5816738a331588fe8f164acb5d70839a35dca5f57114"},{"path":"product/sdk/auths-approval-quorum/src/lib.rs","sha256":"72e4086088a1c0912e4e1a9e980f26a5c280bf5ab16ea39c9f0f58d5096ac2ce"},{"path":"product/sdk/auths-approval-quorum/src/remote.rs","sha256":"9fa029c7c63003adf260f8aec55160c545681c60c1bace0d934e7525862aac7b"},{"path":"product/sdk/auths-approval-quorum/src/remote_tests.rs","sha256":"8a09ce17cfee82a035a74edd535f3ebeb3db0e078784740d3997b17dbdb10197"},{"path":"product/sdk/auths-approval-quorum/src/tests.rs","sha256":"0acbf12be3e497dcc6c2d8f29c9af3b1a7ed8e11b75f6399570d4f217a785060"},{"path":"product/stores/auths-stores/Cargo.toml","sha256":"a32c4b76d17b264be5d40d24497ff237e1ed87822e8bab86229b3db93106dbe3"},{"path":"product/stores/auths-stores/src/gateway_attempt.rs","sha256":"185da8f4a220fba836d5b78a9311f03204681c43a3c53951008084d135bf4d21"},{"path":"product/stores/auths-stores/src/lib.rs","sha256":"e721262edf8a9ab5568ddc27639176312d4a366203b5f73e2d7c11fde2c554e9"},{"path":"product/stores/auths-stores/src/lifecycle.rs","sha256":"94f64d25bc178a9e60ba3c0ee6915d7fb3af7c4468792d76b4e70f43f4de1e2f"}],"schema":"auths.gateway-semantic-closure/1"} \ No newline at end of file diff --git a/product/runtime/auths-gateway/src/bin/auths-gateway.rs b/product/runtime/auths-gateway/src/bin/auths-gateway.rs index e401e622c..2e2424fed 100644 --- a/product/runtime/auths-gateway/src/bin/auths-gateway.rs +++ b/product/runtime/auths-gateway/src/bin/auths-gateway.rs @@ -2641,11 +2641,14 @@ mod unix { admin_socket: &AdminSocket, ) -> Option { use auths_gateway::SupportConnectionState as State; - UnixStream::connect(&admin_socket.path).await.ok()?; let command = serde_json::json!({"command": "status"}); - let response = admin_exchange(state_dir, admin_socket, command, None) - .await - .ok()?; + let response = tokio::time::timeout( + Duration::from_secs(20), + admin_exchange(state_dir, admin_socket, command, None), + ) + .await + .ok()? + .ok()?; let status = response.get("status")?; let number = |member: &str| status.get(member).and_then(serde_json::Value::as_u64); Some(auths_gateway::SupportConnection { diff --git a/product/runtime/auths-gateway/src/engine.rs b/product/runtime/auths-gateway/src/engine.rs index df0310190..a7691274c 100644 --- a/product/runtime/auths-gateway/src/engine.rs +++ b/product/runtime/auths-gateway/src/engine.rs @@ -2007,6 +2007,30 @@ pub(crate) mod tests { floor.accept(&disabled), Err("gateway.connection.restore-rollback") ); + for (generation, digest) in [ + (0, "00".repeat(32)), + (1, "invalid-digest".to_owned()), + (1, "AA".repeat(32)), + ] { + let damaged = serde_json::to_vec(&serde_json::json!({ + "schema": "auths.gateway-generation-floor/1", + "generation": generation, + "record_sha256": digest, + })) + .expect("damaged floor"); + let path = directory.path().join("connection-floor.json"); + std::fs::write(&path, &damaged).expect("write damaged floor"); + assert_eq!( + floor.accept(&disabled), + Err("gateway.connection.restore-rollback") + ); + assert_eq!(std::fs::read(path).expect("retained floor"), damaged); + assert_eq!( + restarted.entry_refusal().await.as_deref(), + Some("gateway.connection.restore-rollback") + ); + assert_eq!(restarted.leases.load(Ordering::SeqCst), before); + } } #[tokio::test] diff --git a/product/runtime/auths-gateway/src/generation_floor.rs b/product/runtime/auths-gateway/src/generation_floor.rs index 5c97a93ae..4673a397f 100644 --- a/product/runtime/auths-gateway/src/generation_floor.rs +++ b/product/runtime/auths-gateway/src/generation_floor.rs @@ -2,6 +2,7 @@ //! It records only a generation and the digest of the exact connection record. use auths_connections::ConnectionRecord; +use auths_recipe_qualification::Sha256Digest; use serde::{Deserialize, Serialize}; use sha2::{Digest as _, Sha256}; #[cfg(unix)] @@ -9,6 +10,7 @@ use std::os::unix::fs::{OpenOptionsExt as _, PermissionsExt as _}; use std::{ fs::{self, File, OpenOptions}, io::{Read as _, Write as _}, + num::NonZeroU64, path::PathBuf, }; @@ -23,8 +25,8 @@ pub struct GenerationFloor { #[serde(deny_unknown_fields)] struct Accepted { schema: String, - generation: u64, - record_sha256: String, + generation: NonZeroU64, + record_sha256: Sha256Digest, } impl GenerationFloor { @@ -73,7 +75,9 @@ impl GenerationFloor { .map_err(|_| ())?; rustix::fs::flock(&lock, rustix::fs::FlockOperation::LockExclusive).map_err(|_| ())?; let path = self.directory.join("connection-floor.json"); - let digest = hex::encode(Sha256::digest(record.to_canonical_cbor().map_err(|_| ())?)); + let digest = Sha256Digest::from_bytes( + Sha256::digest(record.to_canonical_cbor().map_err(|_| ())?).into(), + ); match fs::symlink_metadata(&path) { Ok(metadata) => { if !metadata.is_file() @@ -98,11 +102,11 @@ impl GenerationFloor { } let old: Accepted = serde_json::from_slice(&bytes).map_err(|_| ())?; if old.schema != "auths.gateway-generation-floor/1" - || old.generation > record.generation().get() + || old.generation > record.generation() { return Err(()); } - if old.generation == record.generation().get() { + if old.generation == record.generation() { return if old.record_sha256 == digest { Ok(()) } else { @@ -115,7 +119,7 @@ impl GenerationFloor { } let bytes = serde_json::to_vec(&Accepted { schema: "auths.gateway-generation-floor/1".to_owned(), - generation: record.generation().get(), + generation: record.generation(), record_sha256: digest, }) .map_err(|_| ())?; diff --git a/product/runtime/auths-gateway/src/pending_vectors/production.rs b/product/runtime/auths-gateway/src/pending_vectors/production.rs index a26a54e4d..69fd3ba26 100644 --- a/product/runtime/auths-gateway/src/pending_vectors/production.rs +++ b/product/runtime/auths-gateway/src/pending_vectors/production.rs @@ -71,6 +71,9 @@ const ROWS: &[&str] = &[ "gateway.readiness.observer-unavailable readiness doctor implemented 4 -", "gateway.connection.restore-rollback connection before-lease implemented 4 -", "gateway.admin.credential-journal-unavailable operator before-custody implemented 4 -", + "gateway.support.unavailable support support-bundle implemented 4 -", + "gateway.support.attempts-unavailable support support-bundle implemented 4 -", + "gateway.support.connection-unavailable support support-bundle implemented 4 -", "gateway.attempt.replay engine recorded existing - C:lease-never-precedes-claim", "gateway.connection.credential-generation-missing engine before-claim existing - C:lease-generation-not-held", "gateway.credential.unavailable engine recorded existing - C:lease-commitment-mismatch", diff --git a/product/runtime/auths-gateway/src/semantic_closure.rs b/product/runtime/auths-gateway/src/semantic_closure.rs index 058ea6059..8ce8f3747 100644 --- a/product/runtime/auths-gateway/src/semantic_closure.rs +++ b/product/runtime/auths-gateway/src/semantic_closure.rs @@ -10,7 +10,7 @@ /// SHA-256 of the schema, a NUL byte, and `semantic-closure.json`. /// Regenerate through `semantic_closure_is_current` with `AUTHS_UPDATE_FIXTURES=1`. pub const GATEWAY_SEMANTIC_CLOSURE_SHA256: &str = - "337a10a522211b4ff80e5191cc1b4b8460d2d028ec3f21870d6cfd8e53b5abf0"; + "9d91a6ab6eae2c0840549a22050d9e088a574ae210cdbc2eb65e386dd16858b7"; #[cfg(test)] mod tests { diff --git a/product/runtime/auths-gateway/src/support.rs b/product/runtime/auths-gateway/src/support.rs index 52634bd6d..bdc382932 100644 --- a/product/runtime/auths-gateway/src/support.rs +++ b/product/runtime/auths-gateway/src/support.rs @@ -176,7 +176,7 @@ pub fn support_bundle(facts: &SupportFacts) -> Result, &'static str> { codes.push("gateway.support.attempts-unavailable"); } if facts.connection.is_none() { - codes.push("gateway.support.gateway-not-serving"); + codes.push("gateway.support.connection-unavailable"); } let archive = Archive { schema: SUPPORT_BUNDLE_SCHEMA, @@ -283,7 +283,7 @@ mod tests { serde_json::json!([ "gateway.qualification.revocation-stale", "gateway.support.attempts-unavailable", - "gateway.support.gateway-not-serving" + "gateway.support.connection-unavailable" ]) ); let mut many = facts(); diff --git a/product/runtime/auths-gateway/tests/support_bundle.rs b/product/runtime/auths-gateway/tests/support_bundle.rs index 7da08e959..a69cfbb8f 100644 --- a/product/runtime/auths-gateway/tests/support_bundle.rs +++ b/product/runtime/auths-gateway/tests/support_bundle.rs @@ -13,6 +13,8 @@ use std::{ os::unix::fs::PermissionsExt as _, path::Path, process::{Child, Command, Output, Stdio}, + thread, + time::{Duration, Instant}, }; const BIN: &str = match option_env!("AUTHS_GATEWAY_OPERATOR_TEST_BINARY") { @@ -62,6 +64,15 @@ fn run(command: &mut Command, stdin: &[u8]) -> Output { .expect("stdin") .write_all(stdin) .expect("stdin bytes"); + let deadline = Instant::now() + Duration::from_secs(30); + while child.try_wait().expect("poll command").is_none() { + if Instant::now() >= deadline { + let _ = child.kill(); + let _ = child.wait(); + panic!("the support command exceeded its deadline"); + } + thread::sleep(Duration::from_millis(20)); + } child.wait_with_output().expect("output") } @@ -152,8 +163,29 @@ fn a_support_bundle_holds_no_planted_canary() { .as_array() .expect("codes") .iter() - .any(|code| code == "gateway.support.gateway-not-serving") + .any(|code| code == "gateway.support.connection-unavailable") + ); + + // A socket can exist and accept connections without ever returning a + // status. Collection must finish with partial, explicitly unavailable + // facts rather than hang or claim that the process is not serving. + let admin_path = state.join("admin.sock"); + let unavailable_admin = std::os::unix::net::UnixListener::bind(&admin_path).expect("socket"); + fs::set_permissions(&admin_path, fs::Permissions::from_mode(0o600)).expect("socket mode"); + let started = Instant::now(); + let unavailable = bundle(&state, &planted); + assert!(started.elapsed() < Duration::from_secs(25)); + let report: serde_json::Value = serde_json::from_slice(&unavailable).expect("report"); + assert!(report["connection"].is_null()); + assert!( + report["codes"] + .as_array() + .expect("codes") + .iter() + .any(|code| code == "gateway.support.connection-unavailable") ); + drop(unavailable_admin); + fs::remove_file(&admin_path).expect("remove unavailable socket"); let mut child = Command::new(BIN) .arg("serve") @@ -191,6 +223,11 @@ fn a_support_bundle_holds_no_planted_canary() { name: "serving", bytes: &serving, }, + ScanSource { + kind: SourceKind::SupportBundle, + name: "unavailable-admin", + bytes: &unavailable, + }, ]; let scanned = redaction(&secrets, &sources).expect("scan"); assert!(scanned.iter().all(|case| case.passed), "{scanned:?}"); diff --git a/release/semantic-freeze-versions.toml b/release/semantic-freeze-versions.toml index 8ea4b85fe..92be8cbbd 100644 --- a/release/semantic-freeze-versions.toml +++ b/release/semantic-freeze-versions.toml @@ -1,4 +1,4 @@ -freeze_version = 365 +freeze_version = 366 # Semantic identity counters live outside the xtask source tree deliberately. # The formal source closure binds xtask's executable code, while the semantic @@ -45,7 +45,7 @@ freeze_version = 365 "auths.frozen-bytes/product/integrations/auths-stripe/fixtures/subscription-create/v1/manifest.sha256.json" = 1 "auths.frozen-bytes/product/integrations/auths-stripe/fixtures/subscription-modify/v1/manifest.sha256.json" = 1 "auths.frozen-bytes/product/integrations/auths-stripe/fixtures/v1/manifest.sha256.json" = 1 -"auths.identity.protocol" = 121 +"auths.identity.protocol" = 122 "auths.modular-components" = 20 "auths.portable-abi-bindings" = 121 "auths.product.bounded-domains" = 19 @@ -60,11 +60,11 @@ freeze_version = 365 "auths.product.mcp-closed-execution" = 31 "auths.product.mechanism-profile-conformance" = 12 "auths.product.operations" = 5 -"auths.product.public-sdk-contract" = 118 +"auths.product.public-sdk-contract" = 119 "auths.product.receipts" = 13 "auths.product.release-assurance" = 7 "auths.product.simplified-waist" = 19 "auths.product.vocabulary" = 24 "auths.release.benchmark-contract" = 1 "auths.release.evolution-contract" = 79 -"auths.release.public-surface" = 365 +"auths.release.public-surface" = 366 diff --git a/release/semantic-freeze.json b/release/semantic-freeze.json index e4b6357be..a76891f8f 100644 --- a/release/semantic-freeze.json +++ b/release/semantic-freeze.json @@ -1,6 +1,6 @@ { "schema": "auths.semantic-freeze/1", - "freezeVersion": 365, + "freezeVersion": 366, "publicSurface": { "rustRoots": [ "auths", @@ -550,7 +550,7 @@ }, { "id": "auths.identity.protocol", - "version": 121, + "version": 122, "classification": "frozen-meaning", "categories": [ "identity-protocol-versions", @@ -871,7 +871,7 @@ }, { "id": "auths.product.public-sdk-contract", - "version": 118, + "version": 119, "classification": "frozen-meaning", "categories": [ "rust-sdk-contract", @@ -1011,7 +1011,7 @@ }, { "id": "auths.release.public-surface", - "version": 365, + "version": 366, "classification": "release-metadata", "categories": [ "package-names", @@ -1103,7 +1103,7 @@ "xtask/src/release_control.rs", "xtask/src/semantic_freeze.rs" ], - "sha256": "73ac80785dac5a005702d9c8b1df49ccf25bc0321f53ad8c8c9830ae3ff7325c" + "sha256": "9009fddbe9d202d12742dd88b582456231c08702f038d036118205067e62a5ff" } ] } From 33e69524a5434730bd8df1f9c8976a9c04b3359d Mon Sep 17 00:00:00 2001 From: bordumb Date: Tue, 6 Oct 2026 04:07:15 +0100 Subject: [PATCH 011/108] fix(ci): assign gateway deployment verification phases --- .github/ci/phase-ownership.toml | 8 ++++++++ formal/qualification/aeneas/source-closure.json | 4 ++-- release/semantic-freeze-versions.toml | 6 +++--- release/semantic-freeze.json | 10 +++++----- xtask/ci-plan/src/lib.rs | 15 +++++++++++++++ 5 files changed, 33 insertions(+), 10 deletions(-) diff --git a/.github/ci/phase-ownership.toml b/.github/ci/phase-ownership.toml index c6d0ec7e8..7c8060a74 100644 --- a/.github/ci/phase-ownership.toml +++ b/.github/ci/phase-ownership.toml @@ -155,6 +155,14 @@ kind = "prefix" value = "qualification/" phases = ["authoritative", "compliance", "secrets"] +# Gateway deployment and packaged operator assets include the PostgreSQL +# recovery boundary and release handoff, without changing other providers. +[[rules]] +id = "gateway-deployment" +kind = "prefix" +value = "deployment/gateway/" +phases = ["authoritative", "compliance", "secrets", "postgresql_live", "release"] + [[rules]] id = "interoperability-fixtures" kind = "prefix" diff --git a/formal/qualification/aeneas/source-closure.json b/formal/qualification/aeneas/source-closure.json index 1c561bf7d..029640dd5 100644 --- a/formal/qualification/aeneas/source-closure.json +++ b/formal/qualification/aeneas/source-closure.json @@ -1,6 +1,6 @@ { "schema": "auths-proof-translation-source-closure/v2", - "digest": "3d7b77451c335933a5aab866761f8672e773055a752661349c71fabf3b9e4f87", + "digest": "f3b8cc9336cc95cfabab6629e583f58717601435d678375a62416160a2efb461", "files": [ { "path": ".cargo/config.toml", @@ -273,7 +273,7 @@ }, { "path": "xtask/ci-plan/src/lib.rs", - "sha256": "b1cc615464d99787ff3259678f98a7644ee3715ce20c6bd308f391c4822dd7cb" + "sha256": "aeae292998e347454a2396933d4e4968460c70c165f88b7a6586985582a0463c" }, { "path": "xtask/ci-plan/src/main.rs", diff --git a/release/semantic-freeze-versions.toml b/release/semantic-freeze-versions.toml index 92be8cbbd..0ab49f7b2 100644 --- a/release/semantic-freeze-versions.toml +++ b/release/semantic-freeze-versions.toml @@ -1,4 +1,4 @@ -freeze_version = 366 +freeze_version = 367 # Semantic identity counters live outside the xtask source tree deliberately. # The formal source closure binds xtask's executable code, while the semantic @@ -19,7 +19,7 @@ freeze_version = 366 "auths.frozen-bytes/formal/assurance-manifest-v1.toml" = 57 "auths.frozen-bytes/formal/qualification/aeneas/generated" = 19 "auths.frozen-bytes/formal/qualification/aeneas/qualification.toml" = 16 -"auths.frozen-bytes/formal/qualification/aeneas/source-closure.json" = 96 +"auths.frozen-bytes/formal/qualification/aeneas/source-closure.json" = 97 "auths.frozen-bytes/product/conformance/v1/mechanism-profile-conformance.json" = 1 "auths.frozen-bytes/product/conformance/v1/simplified-product-waist.json" = 4 "auths.frozen-bytes/product/fixtures/v1/bounded-policy/manifest.json" = 3 @@ -67,4 +67,4 @@ freeze_version = 366 "auths.product.vocabulary" = 24 "auths.release.benchmark-contract" = 1 "auths.release.evolution-contract" = 79 -"auths.release.public-surface" = 366 +"auths.release.public-surface" = 367 diff --git a/release/semantic-freeze.json b/release/semantic-freeze.json index a76891f8f..afeba4bbd 100644 --- a/release/semantic-freeze.json +++ b/release/semantic-freeze.json @@ -1,6 +1,6 @@ { "schema": "auths.semantic-freeze/1", - "freezeVersion": 366, + "freezeVersion": 367, "publicSurface": { "rustRoots": [ "auths", @@ -238,7 +238,7 @@ }, { "id": "auths.frozen-bytes/formal/qualification/aeneas/source-closure.json", - "version": 96, + "version": 97, "classification": "frozen-bytes", "categories": [ "canonical-generated-evidence" @@ -246,7 +246,7 @@ "owners": [ "formal/qualification/aeneas/source-closure.json" ], - "sha256": "999fbdc0b91332440a3025203cbcaa109a04a5385f7bf2d6d90895645cc1a8db" + "sha256": "32b4ba2c0a643b402d2109abc0b4dbe125827a20d4760911654e078dcfe02d29" }, { "id": "auths.frozen-bytes/product/conformance/v1/mechanism-profile-conformance.json", @@ -1011,7 +1011,7 @@ }, { "id": "auths.release.public-surface", - "version": 366, + "version": 367, "classification": "release-metadata", "categories": [ "package-names", @@ -1103,7 +1103,7 @@ "xtask/src/release_control.rs", "xtask/src/semantic_freeze.rs" ], - "sha256": "9009fddbe9d202d12742dd88b582456231c08702f038d036118205067e62a5ff" + "sha256": "dc074161594b1d496b5ea5c93a246f3f026aef44196d634f76c5a8a4d534ccd1" } ] } diff --git a/xtask/ci-plan/src/lib.rs b/xtask/ci-plan/src/lib.rs index 2814e8a92..1e81bbe63 100644 --- a/xtask/ci-plan/src/lib.rs +++ b/xtask/ci-plan/src/lib.rs @@ -3329,6 +3329,21 @@ serde = "1" assert!(!opentofu.contains("postgresql_live")); assert!(!opentofu.contains("records_api_live")); + assert_eq!( + phases_for("deployment/gateway/systemd/auths-gateway.service"), + BTreeSet::from([ + "authoritative", + "compliance", + "secrets", + "postgresql_live", + "release" + ]) + ); + assert_eq!( + phases_for("deployment/gateway/tools/exercise-postgres-restore.sh"), + phases_for("deployment/gateway/systemd/auths-gateway.service") + ); + let control_plane = phases_for(".github/actions/setup-rust-cache/action.yml"); for phase in &loaded.manifest.phases { assert!(control_plane.contains(phase.id.as_str())); From 90357c09ae21ad57e79d3d989d5470a8e3bbac92 Mon Sep 17 00:00:00 2001 From: bordumb Date: Tue, 6 Oct 2026 04:09:24 +0100 Subject: [PATCH 012/108] docs(gateway): make qualification runbook commands executable --- docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md b/docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md index ee11f3add..479c65516 100644 --- a/docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md +++ b/docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md @@ -63,12 +63,23 @@ all serving hosts separately before retiring external credentials. The offline owner certifies a new protected software release signer with the ceremony tool. Publish the new certificate, current signed revocation list, -release index and exact attestations together. Import on each host, invoke -qualification-reload on each serving operator socket and inspect derived status. -Do not extend validity by editing files or the clock. Test an expired -attestation, expired certificate, stale revocation list, untrusted clock, -revoked signer and revoked qualification with the disposable trust exercise. -Every required recipe must stop before lease. Keep the signed input digests, +release index and exact attestations together. On each host, run +`auths-gateway qualification-import --state-dir ... --from ...`; add +`--admin-socket ...` when serving uses a nondefault socket. Import verifies and +stores the inputs, then automatically requests `qualification-reload` from +the serving operator socket. If the gateway is stopped, it reads them at its +next start. There is no separate `qualification-reload` CLI command. Inspect +`auths-gateway qualification-status --state-dir ...` and the serving `status` +response after import, so a failed reload cannot be mistaken for acceptance. +Do not extend validity by editing files or the clock. Rehearse signer rotation, +signer revocation, stale revocation inputs and untrusted-clock refusal with +`auths-qualification stage-trust --tuple ... --out ...`, using the candidate's +public tuple. That tool uses disposable test signing material and proves the +trust mechanism; it does not rotate a production root or prove a gateway's +lease boundary. Separately exercise expired attestations, expired certificates, +revoked qualifications and those other signed input faults on the disposable +gateway deployment: every required recipe must stop before lease. Keep the +signed input digests, closed codes and zero-entry/lease witnesses; no private key enters support bundles or gateway hosts. Publish a root-signed revocation list at least every 24 hours (72 hours is the hard maximum), including when nothing is revoked. From 10111b9c9592bb3099b68ef10d0affd3e2e5848c Mon Sep 17 00:00:00 2001 From: bordumb Date: Tue, 6 Oct 2026 04:18:17 +0100 Subject: [PATCH 013/108] fix(gateway): expire stale clock synchronization samples --- compliance.toml | 2 + deployment/gateway/README.md | 13 +- .../gateway/timesyncd/50-auths-gateway.conf | 5 + docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md | 5 + ...gateway-polish-and-recipe-qualification.md | 7 + .../auths-gateway/semantic-closure.json | 2 +- .../auths-gateway/src/qualification.rs | 121 ++++++++++++++++-- .../auths-gateway/src/semantic_closure.rs | 2 +- release/semantic-freeze-versions.toml | 8 +- release/semantic-freeze.json | 14 +- 10 files changed, 153 insertions(+), 26 deletions(-) create mode 100644 deployment/gateway/timesyncd/50-auths-gateway.conf diff --git a/compliance.toml b/compliance.toml index c04ae0bc3..c6581ec06 100644 --- a/compliance.toml +++ b/compliance.toml @@ -1591,6 +1591,8 @@ security_state = ["durable-credential-cleanup-notes", "host-generation-floor", " [packages.auths-gateway.claims] operational-diagnostics = [ + "product/runtime/auths-gateway/src/qualification.rs#synchronization_marker_requires_a_recent_nonfuture_sample", + "product/runtime/auths-gateway/src/qualification.rs#synchronization_marker_refuses_links_and_untrusted_write_permissions", "product/runtime/auths-gateway/src/credential_journal.rs#notes_survive_restart_and_refuse_missing_corrupt_full_or_foreign_state", "product/runtime/auths-gateway/src/engine.rs#durable_cleanup_retires_abandoned_generations_and_keeps_active_and_future_secrets", "product/runtime/auths-gateway/src/readiness.rs#the_projection_names_every_check_and_retains_precise_qualification_failure", diff --git a/deployment/gateway/README.md b/deployment/gateway/README.md index 7b89ef2f4..501eff307 100644 --- a/deployment/gateway/README.md +++ b/deployment/gateway/README.md @@ -78,9 +78,16 @@ checks process/socket isolation and pinned transport construction, not an unconfigured external firewall. A successful readiness report is not proof that an application lacks an independently obtained provider token. -Enable systemd-timesyncd. Its fixed synchronization marker is the clock trust -input; missing synchronization disables required recipes. Monitor that marker, -not merely a running time service. The optional observer is absent in this +Install `timesyncd/50-auths-gateway.conf` as +`/etc/systemd/timesyncd.conf.d/50-auths-gateway.conf`, configure the reviewed +time sources and restart systemd-timesyncd. The drop-in caps polling at five +minutes. Its fixed synchronization marker is the clock trust input; samples +older than fifteen minutes, future-dated samples, missing/nonregular markers +and group/world-writable markers disable required recipes. This bounds the +trust retained after synchronization stops; it does not establish that an +untrusted time source is correct. Permit the synchronization service's separate +UID only the reviewed time endpoints, and alert before the sample-age limit. +The optional observer is absent in this reference, explicitly reported as unavailable for signed outcomes. To add one, provision the reviewed distinct custody-backed signing identity and restrict its endpoint; never use a software observer in production. diff --git a/deployment/gateway/timesyncd/50-auths-gateway.conf b/deployment/gateway/timesyncd/50-auths-gateway.conf new file mode 100644 index 000000000..6b0e88fa6 --- /dev/null +++ b/deployment/gateway/timesyncd/50-auths-gateway.conf @@ -0,0 +1,5 @@ +# Install as /etc/systemd/timesyncd.conf.d/50-auths-gateway.conf. +# The gateway refuses synchronization samples older than fifteen minutes. +[Time] +PollIntervalMinSec=32s +PollIntervalMaxSec=5min diff --git a/docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md b/docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md index 479c65516..a3a90276c 100644 --- a/docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md +++ b/docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md @@ -71,6 +71,11 @@ the serving operator socket. If the gateway is stopped, it reads them at its next start. There is no separate `qualification-reload` CLI command. Inspect `auths-gateway qualification-status --state-dir ...` and the serving `status` response after import, so a failed reload cannot be mistaken for acceptance. +The production clock requires a synchronization sample at most fifteen minutes +old, with no future timestamp; stopping time synchronization must make +`gateway.qualification.clock-untrusted` appear once that bound is exceeded. +Restore synchronization through the reviewed time service, not by touching its +marker. The reference polling interval is at most five minutes. Do not extend validity by editing files or the clock. Rehearse signer rotation, signer revocation, stale revocation inputs and untrusted-clock refusal with `auths-qualification stage-trust --tuple ... --out ...`, using the candidate's diff --git a/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md b/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md index e7e5df3e7..912e230ea 100644 --- a/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md +++ b/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md @@ -1614,6 +1614,13 @@ The maintained systemd deployment reference is `deployment/gateway/`; the operations and independent trial protocol are in `docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md`. Hosted verification is pending. +The production clock adapter now rejects a synchronization marker older than +fifteen minutes, a future timestamp, a symlink/nonregular file or an unsafe +write mode. Mere existence did not bound trust after synchronization stopped. +The packaged reference caps systemd-timesyncd polling at five minutes. This is +a fixed adapter bound, not an operator override of signed validity windows or +a claim that a compromised time source is trustworthy. + This is not Epic 4 acceptance yet. A live two-host reference exercise of workload identity, firewall, PostgreSQL point-in-time restore and the runbooks remains, as does the independently performed unfamiliar-operator trial and diff --git a/product/runtime/auths-gateway/semantic-closure.json b/product/runtime/auths-gateway/semantic-closure.json index ed3cbf4a2..3207c3e82 100644 --- a/product/runtime/auths-gateway/semantic-closure.json +++ b/product/runtime/auths-gateway/semantic-closure.json @@ -1 +1 @@ -{"files":[{"path":"Cargo.lock","sha256":"c94ed342774d5e2823f01ecf74b8a4812c5f9a6b0cf811d31f2e2cecb671a275"},{"path":"Cargo.toml","sha256":"6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24"},{"path":"core/adapters/auths-did-keri/Cargo.toml","sha256":"86ba3e3f9a0a70d970568bfb3113b7ba7bbdd81c3eebbb52743dd574a0c0ecaa"},{"path":"core/adapters/auths-did-keri/src/lib.rs","sha256":"a75674842f8a7142004369ccd206ab43e476459293f0ff4bed4d4e659031b3e3"},{"path":"core/adapters/auths-did-key/Cargo.toml","sha256":"d5a3ae07ecde83f91eed4c3785051dd0f44eab6c891754f3309b6b40596707d7"},{"path":"core/adapters/auths-did-key/src/lib.rs","sha256":"b76a3f4528a725df53cfa9242e6e414e1d26caa48468aaed497e28b121f4497c"},{"path":"core/adapters/auths-raw-key/Cargo.toml","sha256":"f49616bc18c19e6aaa7e6a02ccebcdb9f5c1422c1278ef9869e0dbf22ceda7be"},{"path":"core/adapters/auths-raw-key/src/lib.rs","sha256":"45eec1b295dac3bed65cd79c942870b926b06b3f5d38eaebaeb6140ac69315fa"},{"path":"core/crates/auths-algebra-kernel/Cargo.toml","sha256":"0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba"},{"path":"core/crates/auths-algebra-kernel/src/generated.rs","sha256":"ae4bcbef42a408c7ffa0c6a74a42f7de177a6f14479e51d205acf830bda05960"},{"path":"core/crates/auths-algebra-kernel/src/lib.rs","sha256":"6654667eeb9b353d6648954c9fd2e8838462a82ce6b2803eb49e1366892c68c6"},{"path":"core/crates/auths-assurance/Cargo.toml","sha256":"afcb12a97ddd09d7a264b9ecd3fcaefc865ff2c9b4539ee85b00883420ba333a"},{"path":"core/crates/auths-assurance/src/lib.rs","sha256":"0fb2ec844d674b25a9e20b1601452c89c2454901fa506adfa9bb38ef9a7fa213"},{"path":"core/crates/auths-author/Cargo.toml","sha256":"1e6f0e3bc079ddb558decf0db26b291c6e72fc47327b6df1b7650d41689b215f"},{"path":"core/crates/auths-author/src/lib.rs","sha256":"e14475f2f49715a1869d5fa6b11ff1fbb72497e39097e09f833b0bae7e5b3f2b"},{"path":"core/crates/auths-author/src/observations.rs","sha256":"dda7d6bfa6f4bd7e95a480ca283c2c0e996f69c5c15cb0c7197af328131a7066"},{"path":"core/crates/auths-authority/Cargo.toml","sha256":"4f68212938029f79ebd857b4f3038494eb85d0163d49f07e51376715cf959815"},{"path":"core/crates/auths-authority/src/lib.rs","sha256":"da88d5194de4e17449e69972c0fb042afa3c39798a8f570f30771e77c384f1eb"},{"path":"core/crates/auths-codec/Cargo.toml","sha256":"e20e51826e17814effd9d8925d18d5fbdd6c0d37bf50231e743ec2611314722c"},{"path":"core/crates/auths-codec/src/approval.rs","sha256":"fbff43bf4d57f69f8b7738a8647751cde75c5a932dee65d924a1fe9c7202f91f"},{"path":"core/crates/auths-codec/src/bounded_policy.rs","sha256":"d21f6728be2d8a04b6d94921f2b683f7e61cbb42e0ac6866f1c88a49caa534c3"},{"path":"core/crates/auths-codec/src/decode.rs","sha256":"ba2999584cdf53b1b517ecb9c7ea50d39efee17c666a9a38e2ad1ac94379f778"},{"path":"core/crates/auths-codec/src/encode.rs","sha256":"8491192053e2e15d62b4d2a491de22405b7487ead69ab6f6bca40669ce7ca5f7"},{"path":"core/crates/auths-codec/src/error.rs","sha256":"fecb0737c16deb42d859f1dc7727c698438d9ac12064fd99e0024629642c390c"},{"path":"core/crates/auths-codec/src/hash.rs","sha256":"f88e111f1dbb2cef6b7b5e9c948cb45ff92e366710c8a5f5c636138aa748479e"},{"path":"core/crates/auths-codec/src/lib.rs","sha256":"3b0e5c94c6f34f750b88a9333e1d5c8145746d845d3a23e0d2f61807cf592ea7"},{"path":"core/crates/auths-codec/src/observation.rs","sha256":"38328b0c71ff97a4196eeade8b4faa889527ff1f80bb168468bcd49082a3987e"},{"path":"core/crates/auths-composition/Cargo.toml","sha256":"331e13025eb82588b5269ed3975929eb41c823d588c49e4c296273d85c6fe80e"},{"path":"core/crates/auths-composition/src/lib.rs","sha256":"e42e3b0b6a9985b73c533aeb23799c638979aa27a9ce7d0f10a8d60340570fb1"},{"path":"core/crates/auths-model/Cargo.toml","sha256":"565c15302b0cc9270db1e28efa3862804846850ba933cc17aea8abcec4a65987"},{"path":"core/crates/auths-model/src/approval.rs","sha256":"54cf44a9ef747ec21546a4086aecfb130bc7803b0d646430e6082df51e6e305f"},{"path":"core/crates/auths-model/src/bounded.rs","sha256":"f90496abc0a06c028b4d850af6ddab7d850bfafeaa3d042f1b1246a41d8bbbc9"},{"path":"core/crates/auths-model/src/bounded_policy.rs","sha256":"306a8f049cc7cfc7635fe0e4de47eb7813eed63d3c14c3be2b51586aa4eea450"},{"path":"core/crates/auths-model/src/lib.rs","sha256":"e7cfe6bb9574c6b016aa63e70658c31e0b90903ec6479a49f4a2ceb64f5bad97"},{"path":"core/crates/auths-model/src/observation.rs","sha256":"b3ed3e3cc090afca2896a7d3de7988afccc1ee1ea0ebd91b51a8bc0f20ad8dbb"},{"path":"core/crates/auths-multikey/Cargo.toml","sha256":"858756c1197befcada06134742bffe8d58cf674cadd6c046bf710570e96efaf2"},{"path":"core/crates/auths-multikey/src/lib.rs","sha256":"f5177fffb11e40eeaaa665ba886c541fc1f24d5eacdd6983fb03dc20148733f0"},{"path":"core/crates/auths-ports/Cargo.toml","sha256":"596a9b0f5af3717c16a6d13f7054d8a106bcd9f01f5f72c2235dd2afcf0ab16c"},{"path":"core/crates/auths-ports/src/binding.rs","sha256":"a16c012d40aa4249e3ec54372b9611006d0bfe8c7dc3c741911c2194ad17736d"},{"path":"core/crates/auths-ports/src/diagnostics.rs","sha256":"aa596572503b5a65a918bb2ff38281c144ff53821ee914e9325c852828d852df"},{"path":"core/crates/auths-ports/src/lib.rs","sha256":"8da1debf86f9532df0660155d04298beb1ba3a1204508f8586e2e67cd2fb3449"},{"path":"core/crates/auths-ports/src/path.rs","sha256":"b68fc547b4e4d97a60cbbc1cc1939fc6b34a8233b81f840bd396914a707e3ea1"},{"path":"core/crates/auths-raw-key-core/Cargo.toml","sha256":"98c0bc8527a537512e43a74dd6ba9658c6f0cdc16610cf938e3f9b43785d836d"},{"path":"core/crates/auths-raw-key-core/src/lib.rs","sha256":"98c0500c41697aae28708ad0bf970b9a97583d96a3d2c18d23e7fa351e0f7d12"},{"path":"core/crates/auths-registries/Cargo.toml","sha256":"590e49e58b0622d9d6274fea46796dcdb07dec9550eff295cce6a6427ffa51e2"},{"path":"core/crates/auths-registries/src/lib.rs","sha256":"450d3886d85ee333b7e046317fb5b47cde62483d5f3e41d46265e2caf4c373ec"},{"path":"core/crates/auths-registries/src/template.rs","sha256":"1224039dd2b3ce6fa8357613d8cafbae40400493da7176da202b9ade62fa05e4"},{"path":"core/crates/auths-signature-core/Cargo.toml","sha256":"6bee2230eb30af1be0bd5c2d57bd3e1903497a70028d47290d4ac6e9e0e8bca0"},{"path":"core/crates/auths-signature-core/src/lib.rs","sha256":"6e3f9311ded5e49ea50d445eb21e6d8fa12442aa4362a73e0cb6fda15b7cd865"},{"path":"core/crates/auths-signature/Cargo.toml","sha256":"7f7b5682466ba439d8c59579022cb61068cad9fb4bd2d73e1cc21327c902b450"},{"path":"core/crates/auths-signature/src/lib.rs","sha256":"b3d9ac4cc3ba0797b9e1c09f2d6ac05089b25dac4e285a5af28c0165b33d925b"},{"path":"core/crates/auths-verifier/Cargo.toml","sha256":"c43358e06a33324b41a8b93e5cc7279c55f7d21f1f6cfaa539a3fc7b4c27a38f"},{"path":"core/crates/auths-verifier/src/approval.rs","sha256":"c3cae6a49e169051eb555bb092b1069a4d422516d6a2114623a89e5f31ff923f"},{"path":"core/crates/auths-verifier/src/causal.rs","sha256":"9635230f33b13a263573d319ac8a1976addbcc07677514a43e3c7bf28dc04587"},{"path":"core/crates/auths-verifier/src/lib.rs","sha256":"f22dec38dfa47ced8da4f605390da8453273bee1da010f57fd1fdfcb10e0b389"},{"path":"core/crates/auths-verifier/src/observation.rs","sha256":"0bb07f06a0f9524c88427df1c972b1de8ba038a9eeeb15d3134c25125ae84b1e"},{"path":"core/crates/auths-verifier/src/trace.rs","sha256":"2213d72023a1d9e0413a2cf2c51c3dad9e04775d86033a0caaa9d29a8f0036f8"},{"path":"exchange/crates/auths-proof-exchange-model/Cargo.toml","sha256":"34b2db64f93a288e942b5a3918d28cdcbef906e0dc9074ce848018d3d5f7a1fa"},{"path":"exchange/crates/auths-proof-exchange-model/src/lib.rs","sha256":"49fac5aff2339d3a57c41cb8bb2a82852538e8f77ecc4b157c88e264ff31fb55"},{"path":"exchange/crates/auths-proof-exchange-port/Cargo.toml","sha256":"7ff660f1b7579dc570c791090aeb450404fbbf44c92781e289f5ccdde746d739"},{"path":"exchange/crates/auths-proof-exchange-port/src/lib.rs","sha256":"b408fb40c6432edc1facb3d8b3e9433a033f8dc73fe2e0ba5a88c972ca675021"},{"path":"product/config/auths-config/Cargo.toml","sha256":"e4b568ab9f6d84f7d7e6d66443fe825f360db9c27bc7c31d6ddc0647ba3ab304"},{"path":"product/config/auths-config/src/lib.rs","sha256":"fecf00ea65cef9018fda9af2063326d7065b869266d0d9e73a4f06816f1102cc"},{"path":"product/errors/auths-errors/Cargo.toml","sha256":"3b3a199b6460ba75bda84475bb5accd35e1485448a3981038db85bf4772dd350"},{"path":"product/errors/auths-errors/src/lib.rs","sha256":"7feeb9069fa4003f94f1f07c1c94619cf1c883e0dbaaf2187f04d0f742264bdd"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/Cargo.toml","sha256":"716f1f2a117d6d69d8effe9ee9057e24ba3502f20af6a602b06facb638cdabed"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/api.rs","sha256":"9ea61dd7ddd93282b073b98e453e6b75b26dc49689c04e9782435d06a3a09e48"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/clock.rs","sha256":"73f0a6e0f5903883329fa6683f5888288f759512ac69e5c87efd2b6b87f7d79f"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/http.rs","sha256":"14c1fce14e24c984b2a275563a29b6326fb08367922b6e8d37ba38b9cb81aa2b"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/identity.rs","sha256":"186de11230c8b33375951c4368609f8976bf9795f171af3fd7fac26207a94361"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs","sha256":"0b4617d044f5254a5ab22f5a2578f91cc025206a8c1845be39c1c56dcdf7a5df"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/names.rs","sha256":"41bb23572d6002e23ee103d6fe70ecd68764861c6f2e48a1c53af998270a4afa"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs","sha256":"39fed883f4802e68d3b41a68fea0aba0737810996b33d13577de70faba004c29"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/store.rs","sha256":"fc60ee9c49b2f4f063c449b4c78100c5c4872779e94ca168f796603b380ef6e4"},{"path":"product/integrations/auths-custody/Cargo.toml","sha256":"1e14034185ad1ec24a977fd5f41d0abee219606245c046ce2a82287fadef448b"},{"path":"product/integrations/auths-custody/src/conformance.rs","sha256":"8ed1afd58f18fc6becc268908aa6419c9aa404c79da0197963eb2599df44acf6"},{"path":"product/integrations/auths-custody/src/key.rs","sha256":"70cbb0fd21b6f5652157845a22c35be2d0f6c05b3d138fc4b9bb6dbdc3d81c40"},{"path":"product/integrations/auths-custody/src/lib.rs","sha256":"8ee593c1f59b0fd2126bdda9138026f5bc531beb64d4489a99785842e7b98b43"},{"path":"product/operations/auths-operations/Cargo.toml","sha256":"73dde1e914ba5e1386f8d49c0d730423cc72ae77ec44c6554a6a75cc8e8922b1"},{"path":"product/operations/auths-operations/src/explanation.rs","sha256":"b4a39bcbd5712cb9e735ee7deeb281f3fa6af5ddca973735bf3d87dce427ef11"},{"path":"product/operations/auths-operations/src/lib.rs","sha256":"3f401a56555113b98f57bca172a2660eaecedf76247b83a3fdbb089c133a29cd"},{"path":"product/operations/auths-operations/src/render/json.rs","sha256":"2ae042639960afee123730e945d373bc5dda1d2b3af20ae16c939a7e99b9e418"},{"path":"product/operations/auths-operations/src/render/mod.rs","sha256":"b3b7f6fe473f49227ace5a68bfc3d8dc14b5db8dd9888fd9e207070337b1b8bf"},{"path":"product/operations/auths-operations/src/render/text.rs","sha256":"f216cf3bdb00e264523271b16e7059535ac6b1aabf271cebd7935af155e4bfec"},{"path":"product/policy/auths-bounded-policy/Cargo.toml","sha256":"babd5d200923137ead71d8c2528f847cea323ce98da942a1320b054436612c47"},{"path":"product/policy/auths-bounded-policy/src/arithmetic.rs","sha256":"75e43c5d4eab8d1f71c1daf53839f5f9fe45a400afc1f63a30c6f55ce3632627"},{"path":"product/policy/auths-bounded-policy/src/commitment.rs","sha256":"c5706f2d583454e1a7f570f7ada138d4d864bef0205dfae7c1296774f396bb3f"},{"path":"product/policy/auths-bounded-policy/src/eligibility.rs","sha256":"c9acdfb793074e687fc36efad506be27dbd99ffbf40387bc66c8de39ef238432"},{"path":"product/policy/auths-bounded-policy/src/identifier.rs","sha256":"0006a32bae9eb16c4178cf797df418d2b0a781f2bc6474b741dc1a908141831c"},{"path":"product/policy/auths-bounded-policy/src/kernel.rs","sha256":"99187c28b161ac70bee1afed60711f7f645adb4d1671a01863f9849b369811d5"},{"path":"product/policy/auths-bounded-policy/src/lib.rs","sha256":"76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c"},{"path":"product/policy/auths-bounded-policy/src/receipt.rs","sha256":"3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad"},{"path":"product/policy/auths-bounded-policy/src/registry.rs","sha256":"4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0"},{"path":"product/profiles/auths-profile-api/Cargo.toml","sha256":"7ae85761f58625b5d678f961fd052eebf3e000ef565c7312e3ac857763c0017f"},{"path":"product/profiles/auths-profile-api/src/lib.rs","sha256":"a194b82b20bf8aa864c2334ef6c6aec30b2154ded972862252d5dcefa488ab95"},{"path":"product/profiles/auths-profile-mcp/Cargo.toml","sha256":"db264fc25242f7b7e4133cbe5782545b3107b406c87168ae072683cfb59eac66"},{"path":"product/profiles/auths-profile-mcp/src/arguments.rs","sha256":"a5de696586d507e2aee4a49fee99ef1ef4c51a2e46603f8838f1af6d9009833f"},{"path":"product/profiles/auths-profile-mcp/src/lib.rs","sha256":"d0f8b733a09ef8408336cdebc8948d6a5861012ce6878598b11be7084dfd4280"},{"path":"product/profiles/auths-profile-mcp/src/session.rs","sha256":"166c281fa66333388e4760d6098dad02d3359e1d5de4b8f93312c014f97abb03"},{"path":"product/qualification/auths-recipe-qualification/Cargo.toml","sha256":"b7b15b30b9a3d96d4f089d514266d3a892de6608d30707aa44be31cca89ca9fe"},{"path":"product/qualification/auths-recipe-qualification/src/canonical.rs","sha256":"30a9b50777f0dcb4b606abfee2467d5a975d9f6ad941ab6c13ca3df5b359f667"},{"path":"product/qualification/auths-recipe-qualification/src/closure.rs","sha256":"0ad6aee9bd981e2863fa725f209ec84031db2ff12f4c7ac3aaf5120f0bb86039"},{"path":"product/qualification/auths-recipe-qualification/src/error.rs","sha256":"52d5cf720a1e4579008fdda90a3ac2c31f0b8db57985f121f65e54b4da2b7dd1"},{"path":"product/qualification/auths-recipe-qualification/src/evidence.rs","sha256":"1a4cb862f725b02f9efd827db99637ea8178a5236aa020ec271a363edbe7b362"},{"path":"product/qualification/auths-recipe-qualification/src/ids.rs","sha256":"e81a906d571497ab2da753e1532d4443706410e0b75fdd59a7d2d788c7aec403"},{"path":"product/qualification/auths-recipe-qualification/src/lib.rs","sha256":"195b19f46e1e94a0f3594ad5958e5715bc5e3ad415bdfe6428dfc1b6dd3f4631"},{"path":"product/qualification/auths-recipe-qualification/src/model.rs","sha256":"3484eb0ec287b23d4682ade7b1b0f8d1335985b3fb180f06fc28716076957d5f"},{"path":"product/qualification/auths-recipe-qualification/src/release.rs","sha256":"d816b53e2275e902c750ad03803061844e259e28560ab2d1c77e8a43981a4d6a"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/mod.rs","sha256":"7f15b68e05a04f202bcb1fb80de1d9a9a4fda8bfd6af2cd4e5c660fc75d96fe5"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/schemas.rs","sha256":"c59feec2805621f341a90f81fc005e2c12f7a70f9d264fdeacccb2be4fe1c046"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/verification.rs","sha256":"6a6b5834c5dae10af1ba8939b2deae43b85db71544dc8f077ff63b7fe68ac8a8"},{"path":"product/qualification/auths-recipe-qualification/src/verify.rs","sha256":"edd33589c54fb79bcfccc4cf4e6ccf95bbca088318bb7f8dfc27da684b4fa671"},{"path":"product/receipts/auths-receipts/Cargo.toml","sha256":"6001fa1375899953aafcb07c23a6da0c8f57ea7ec08bb9c950b12a60a8cc6f0f"},{"path":"product/receipts/auths-receipts/src/disclosure.rs","sha256":"ba9ed439be0a320c8a01f5b6e9b51361c1a37e076947490d8e4a484ba6bb119c"},{"path":"product/receipts/auths-receipts/src/lib.rs","sha256":"547a57c4160256719cafb7d0ab972d9fc80b0da14fbbce4148c70c414070ff36"},{"path":"product/runtime/auths-connections/Cargo.toml","sha256":"babeb6e1dda3dfb66291713ce1e43dce5c349833d0b50ea4dccbf986030026b2"},{"path":"product/runtime/auths-connections/src/credential.rs","sha256":"82921413bb053f0f6c7931fbd4e6a86c8cc1d8c6b51debd9c2cef33a8d5b1c51"},{"path":"product/runtime/auths-connections/src/kernel.rs","sha256":"a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8"},{"path":"product/runtime/auths-connections/src/lib.rs","sha256":"79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22"},{"path":"product/runtime/auths-connections/src/model.rs","sha256":"de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77"},{"path":"product/runtime/auths-connections/src/registry.rs","sha256":"e57640e003e72ad3235c567c2bb944a262bd64e673f023b62ea091094cc7e946"},{"path":"product/runtime/auths-gateway-kernel/Cargo.toml","sha256":"34f864e67656af4ac7e5c7a347a23f01fc8ab31365b8e23c0ef474483b14a183"},{"path":"product/runtime/auths-gateway-kernel/src/construct.rs","sha256":"e9d65744bae273d65face4285e5d2da75c06a92ab48f7b8333d496604e31c63c"},{"path":"product/runtime/auths-gateway-kernel/src/lib.rs","sha256":"cfda6f8453426564c085475f183b6f790b438768a19668f1b65d33ba59dc8632"},{"path":"product/runtime/auths-gateway-kernel/src/order.rs","sha256":"e0045f877c4b7fe3860c291039853885064ddcdebba7c9b345ab65e81e646dda"},{"path":"product/runtime/auths-gateway-kernel/src/outcome.rs","sha256":"e9785b1afe70788c89b51b18655bcd5acff7b0c8e3d12fb79c6f05a202e67e6b"},{"path":"product/runtime/auths-gateway-kernel/src/ratio.rs","sha256":"7ace22264812e6fc1ef3a62afee402cf43494bb71ae0d3de219ad1b39d690bcb"},{"path":"product/runtime/auths-gateway-kernel/src/recovery.rs","sha256":"9f46dcd1685ab6e4d1ba04a3fc286a9f3afee8fb47829be1fbc670a7926a2dc6"},{"path":"product/runtime/auths-gateway-kernel/src/transition.rs","sha256":"cefb8f01d915880f6921f2501ff881ad94b9de61072c34d9cd19220992f97374"},{"path":"product/runtime/auths-gateway/Cargo.toml","sha256":"00b28be86921dcdc0ad90cce0c62c2961cafefe96ea6c2edf0e926c3d405ccad"},{"path":"product/runtime/auths-gateway/src/admin.rs","sha256":"2d5cc67afac42fbd15f36e2d1693cd1b20cedacf775040dce6ffe04ccc94c9ea"},{"path":"product/runtime/auths-gateway/src/app.rs","sha256":"6f80f63833ea0815bb44fbf3b0cc54624a08e9fb578b035819f2980dc04e8256"},{"path":"product/runtime/auths-gateway/src/audit.rs","sha256":"0edb2037eb7b5d6f13acfce85c54f62a82bf7fdd31bc7e626c4fec183cef61dd"},{"path":"product/runtime/auths-gateway/src/audit_tests.rs","sha256":"990969384a52d75bc2489d9d412a9e7dd814bca1c8f65c701d6205fae62a15d5"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway-harness.rs","sha256":"12b0c24d36b2e6a3be392d3c081a783b355fdd67dc5b54bacc0410e803116b8c"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway.rs","sha256":"b1dab74ec9a0c301fc9896de15d4676274461928f8b09f5346c561d731d123b0"},{"path":"product/runtime/auths-gateway/src/binding.rs","sha256":"663b0ce878319511aa7d05722ab4ab2fa9be18817884ffb2ee9f131ff1e382d1"},{"path":"product/runtime/auths-gateway/src/bounds.rs","sha256":"9cfa0eae4973e5e047a198360b22f041708fa20276b0b90c2ec440f06915d64b"},{"path":"product/runtime/auths-gateway/src/bounds_aggregate_tests.rs","sha256":"ab34f227b7c8692ba1da88ccb32bb3687a66adf8353d8282fae905d4a88eb612"},{"path":"product/runtime/auths-gateway/src/bounds_tests.rs","sha256":"74136bc570da7b9338b5a1a1ed9d3fd892c55135160964f9d3ac0e2cf5741375"},{"path":"product/runtime/auths-gateway/src/connection.rs","sha256":"7b5d049c258a26ed1c93ecf860f51d051a8a65f9b93554af0b1ea93862398ec9"},{"path":"product/runtime/auths-gateway/src/credential_journal.rs","sha256":"8e2b0733038d93ca5df770d27a870237e3b65664fa48da017d964a65bbbe25b8"},{"path":"product/runtime/auths-gateway/src/echo_verify.rs","sha256":"6d453051665f823abd7354d5c50031d9524cf47d6092d2f09080ae814e3b9575"},{"path":"product/runtime/auths-gateway/src/engine.rs","sha256":"5c04a836112d02677de66a1b79d7487fc95fcaac4a9dfc9e1044a6c19ea1282d"},{"path":"product/runtime/auths-gateway/src/fuzzing.rs","sha256":"ed3b0028487eb546a3b0a91d115aa8f18bcea324b61620bfe8e35a9e6ab18758"},{"path":"product/runtime/auths-gateway/src/generation_floor.rs","sha256":"999ec17cd6f0c11ab144d971e75dcf824b8b71fbffa355cde0dff9555dd7db78"},{"path":"product/runtime/auths-gateway/src/harness.rs","sha256":"c87e479f3eb281960f6c9c80d43c7560d7ccb654b0154ec823d3fcec4884ac05"},{"path":"product/runtime/auths-gateway/src/lib.rs","sha256":"b182052835a2cd631d1f801a74788d6ac1ef9cae21ade9ab4ffc270cd6f667ed"},{"path":"product/runtime/auths-gateway/src/listener.rs","sha256":"aa08239bcbc1fcb55e8a212fbdf6a84f12985b0d436dcb51dc58b06e59e435f2"},{"path":"product/runtime/auths-gateway/src/observed_tests.rs","sha256":"a22be071695f89ca2578a4d82fd80d9cb82289213c9bdb8f0470f6b2dc3d9201"},{"path":"product/runtime/auths-gateway/src/observer.rs","sha256":"562ffcaea071c3856e0708dc2fe33516917e145d2438aabb75af0a2b6ba01046"},{"path":"product/runtime/auths-gateway/src/onboarding.rs","sha256":"0dfd7d67e7f02f18a28d1c86ca1b7751d7463f5efcdbe3825de0ad8cbccb3891"},{"path":"product/runtime/auths-gateway/src/operator.rs","sha256":"c3c36954a3e86723df035b47f43b85fc8ab3a6292983522b6258d5c6b4e6c4e4"},{"path":"product/runtime/auths-gateway/src/pending_vectors/attempts.rs","sha256":"47ef3c8cb1c5504d47ae9a0088705ce6715fe86bac1671a34a56fb38a64d0dd3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/bounds.rs","sha256":"e612217307e1da5b0eb5ee6582a7458bb064b8aa8a529fc6555b1b334127ab68"},{"path":"product/runtime/auths-gateway/src/pending_vectors/codes.rs","sha256":"e00670a5ef24eb856cc2c6dcda8e5a263842f55c76bb939c0c27bd9df37e5522"},{"path":"product/runtime/auths-gateway/src/pending_vectors/keys.rs","sha256":"f84c56f2ea9cb34b2b79c72d13fbf2c6585010ec1ed450af58a78c80c1ea1edd"},{"path":"product/runtime/auths-gateway/src/pending_vectors/mod.rs","sha256":"5de8340f0ef71a0b57a09e323fefe473d3160c6ae952b9ba46f714825fbacafc"},{"path":"product/runtime/auths-gateway/src/pending_vectors/outcomes.rs","sha256":"8ec07b9511b48913af36ac999d2aa0e82924289f6acb23ddaeb9f00f99815166"},{"path":"product/runtime/auths-gateway/src/pending_vectors/production.rs","sha256":"f574cabfa4687a4fc846b8f6a234b68ec53b876aed548b11445729cac1a55ede"},{"path":"product/runtime/auths-gateway/src/pending_vectors/recipes.rs","sha256":"51693208270231c25c3aef2a32151d5962114c71e86b88cb9df83181c7af83d9"},{"path":"product/runtime/auths-gateway/src/pre_entry.rs","sha256":"06ea78ca140468bfaba17d9ab04912ad68673954c3203c98fed28272ff2a00c0"},{"path":"product/runtime/auths-gateway/src/property_tests.rs","sha256":"939c081e2e154aaf10186754044bdd65608932c899b970a04a71d0afaa999a93"},{"path":"product/runtime/auths-gateway/src/qualification.rs","sha256":"a4398512ccb7bb494000fe38f03e0faa7b82d1f80ef5ee2dfa75698ae4f5a9be"},{"path":"product/runtime/auths-gateway/src/qualification_tests.rs","sha256":"4473add5729b97faf04d7be7fd8cf3bbacd7f545e1b61c7d2782563011906b4d"},{"path":"product/runtime/auths-gateway/src/quorum_tests.rs","sha256":"a78380b019104d688c11a4410082c7e08ded3106aab099954c4f8a1b4ae0fd89"},{"path":"product/runtime/auths-gateway/src/readiness.rs","sha256":"911c3f11892f94641574375e2da4c671c802738f71082f12c39832331052d43d"},{"path":"product/runtime/auths-gateway/src/recipe.rs","sha256":"fecf9af67e7afc48d080e9f8f55f8ce28e49d0e08988717a27908bbda461d6b6"},{"path":"product/runtime/auths-gateway/src/recipe/lower.rs","sha256":"8088b8751ed831dbb48247af953c6290ac95e2a438ccd5bd65eff54be06a1fd1"},{"path":"product/runtime/auths-gateway/src/recipe/review.rs","sha256":"c3eb7d9fdd98dacf52750b14b67ad7b7faaecbbdeafff1e0b049f67d0a2d0139"},{"path":"product/runtime/auths-gateway/src/recipe/runtime.rs","sha256":"c286f0d15f974402822c0810d8e97f98411dc1c557755cc23e540d85e2bb42d9"},{"path":"product/runtime/auths-gateway/src/recipe/source.rs","sha256":"1af50298fb1461e1b24cbdf560d43124d6b1c4c529586c911b1c4797214a69ff"},{"path":"product/runtime/auths-gateway/src/recipe/tests.rs","sha256":"aac551a2481bbc60864c64079bc667dcb232e45a0f41a04073ed84ab5dbe1fce"},{"path":"product/runtime/auths-gateway/src/recipe/validate.rs","sha256":"3711b17605cb7b0d639bc1b180449231f5882a306cab20e2c7782155cc63b0d4"},{"path":"product/runtime/auths-gateway/src/scenario_tests.rs","sha256":"d8271761b12597bfe1233f8eb5ad1d4e5498c5d03388e832e24ab818484a1de4"},{"path":"product/runtime/auths-gateway/src/separation.rs","sha256":"be9306848ca5d801767cf6aa14247c8618312ef0e202f00ce0c24c4844491061"},{"path":"product/runtime/auths-gateway/src/store.rs","sha256":"1e5288345c2cb1421aeda277b3158d07607404b0ec46943222ac107b63dcbb46"},{"path":"product/runtime/auths-gateway/src/store_testkit.rs","sha256":"88d82fee42f1b8ef521e8deef0216e938ebeaad822eb2f5020e70b89d145ea70"},{"path":"product/runtime/auths-gateway/src/submit.rs","sha256":"c78dbbba7c45b443febf655056c5edcd635e77be7b21c5b2c318097502415ffe"},{"path":"product/runtime/auths-gateway/src/support.rs","sha256":"9fd979029793a22b15d9776a7fc172476fd7c126a80d4080c65d720845becbcb"},{"path":"product/runtime/auths-gateway/src/transport.rs","sha256":"be2c6dc75b8daec110bf8749fedc3823f6067d40b999aa3eb21126896a97d3ad"},{"path":"product/runtime/auths-kernel-runtime/Cargo.toml","sha256":"926bcd0053e5edd703be8f0027ad009e2982db013c8174c1366edbf38b48087d"},{"path":"product/runtime/auths-kernel-runtime/src/lib.rs","sha256":"7108faae9ca4bc32dc093ddaf885ac8f74f3c9b8d317b7c7d0ed00d1d0ab5972"},{"path":"product/runtime/auths-lifecycle/Cargo.toml","sha256":"c5053c705f8d5554b44e432fe75287a2faf11d644e5a2552e45ad6cd94176af5"},{"path":"product/runtime/auths-lifecycle/src/codec.rs","sha256":"51c4b746749150e8bfcd8ff972b3f6c1ef40bec15583448ec1b471d9ad737dc0"},{"path":"product/runtime/auths-lifecycle/src/digest.rs","sha256":"55282cd7d8aba37713c2dcb5357c9877819edb72a30eadefb860d28d7d3a3eb7"},{"path":"product/runtime/auths-lifecycle/src/identifier.rs","sha256":"31620e8c16de68d3d2d3b84d6353c1a5b9d4151d8247f91fa389b906a8e660f1"},{"path":"product/runtime/auths-lifecycle/src/kernel.rs","sha256":"2abb8c094b36d35b364e74d78091d14c5d6f3d1eb6552cca3b5538dbd017ce23"},{"path":"product/runtime/auths-lifecycle/src/lib.rs","sha256":"afe5a345cd309b5a4f08ffba3170a6d7f16ff914892b3f2006d5208ed24ec736"},{"path":"product/runtime/auths-lifecycle/src/model.rs","sha256":"1af12bbeeeaa65ec02ddcebd7d2c8c92ec1e339fa40ae85b45ab9b01a722a4fa"},{"path":"product/runtime/auths-lifecycle/src/operation.rs","sha256":"78e6d05fcf5d7ea4f148032a3fa26fdfcab77eb346019effe927b08e0d64d732"},{"path":"product/runtime/auths-lifecycle/src/registry.rs","sha256":"53495fe6f7a77422593a41623e28716f1c140dcc1e00f87f6b0ffbfb93a5ef90"},{"path":"product/runtime/auths-lifecycle/src/sealed.rs","sha256":"2e0c03b5813c926c159598bb7890d1523825edbe57cd687d42a5dfb3374a0c19"},{"path":"product/runtime/auths-lifecycle/src/test_support.rs","sha256":"221d9a5c5ef8e1f9f8fd66927484eaf813571d0568470278ecd8fa08a5eec8cd"},{"path":"product/runtime/auths-lifecycle/src/transition.rs","sha256":"011805a28efdd541f44ccea54dd0e34a1e58f4004447ee58013703b4fb6b2822"},{"path":"product/runtime/auths-runtime/Cargo.toml","sha256":"dd29d80a8b4bb56c869f036a6c9998f6e6d1c0383ac5dc03fa42b24abe2a7ff7"},{"path":"product/runtime/auths-runtime/src/lib.rs","sha256":"132ca03d58c14905d3a822a4972f42a22a5ad33a45f2ba9ca44f3a57d810b4b0"},{"path":"product/runtime/auths-runtime/src/production.rs","sha256":"fd4eff4270c571c10fcff6cf27df28961ebf074de8a1a028f500fda1ca376820"},{"path":"product/sdk/auths-approval-quorum/Cargo.toml","sha256":"df904971fca87a24194c5816738a331588fe8f164acb5d70839a35dca5f57114"},{"path":"product/sdk/auths-approval-quorum/src/lib.rs","sha256":"72e4086088a1c0912e4e1a9e980f26a5c280bf5ab16ea39c9f0f58d5096ac2ce"},{"path":"product/sdk/auths-approval-quorum/src/remote.rs","sha256":"9fa029c7c63003adf260f8aec55160c545681c60c1bace0d934e7525862aac7b"},{"path":"product/sdk/auths-approval-quorum/src/remote_tests.rs","sha256":"8a09ce17cfee82a035a74edd535f3ebeb3db0e078784740d3997b17dbdb10197"},{"path":"product/sdk/auths-approval-quorum/src/tests.rs","sha256":"0acbf12be3e497dcc6c2d8f29c9af3b1a7ed8e11b75f6399570d4f217a785060"},{"path":"product/stores/auths-stores/Cargo.toml","sha256":"a32c4b76d17b264be5d40d24497ff237e1ed87822e8bab86229b3db93106dbe3"},{"path":"product/stores/auths-stores/src/gateway_attempt.rs","sha256":"185da8f4a220fba836d5b78a9311f03204681c43a3c53951008084d135bf4d21"},{"path":"product/stores/auths-stores/src/lib.rs","sha256":"e721262edf8a9ab5568ddc27639176312d4a366203b5f73e2d7c11fde2c554e9"},{"path":"product/stores/auths-stores/src/lifecycle.rs","sha256":"94f64d25bc178a9e60ba3c0ee6915d7fb3af7c4468792d76b4e70f43f4de1e2f"}],"schema":"auths.gateway-semantic-closure/1"} \ No newline at end of file +{"files":[{"path":"Cargo.lock","sha256":"c94ed342774d5e2823f01ecf74b8a4812c5f9a6b0cf811d31f2e2cecb671a275"},{"path":"Cargo.toml","sha256":"6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24"},{"path":"core/adapters/auths-did-keri/Cargo.toml","sha256":"86ba3e3f9a0a70d970568bfb3113b7ba7bbdd81c3eebbb52743dd574a0c0ecaa"},{"path":"core/adapters/auths-did-keri/src/lib.rs","sha256":"a75674842f8a7142004369ccd206ab43e476459293f0ff4bed4d4e659031b3e3"},{"path":"core/adapters/auths-did-key/Cargo.toml","sha256":"d5a3ae07ecde83f91eed4c3785051dd0f44eab6c891754f3309b6b40596707d7"},{"path":"core/adapters/auths-did-key/src/lib.rs","sha256":"b76a3f4528a725df53cfa9242e6e414e1d26caa48468aaed497e28b121f4497c"},{"path":"core/adapters/auths-raw-key/Cargo.toml","sha256":"f49616bc18c19e6aaa7e6a02ccebcdb9f5c1422c1278ef9869e0dbf22ceda7be"},{"path":"core/adapters/auths-raw-key/src/lib.rs","sha256":"45eec1b295dac3bed65cd79c942870b926b06b3f5d38eaebaeb6140ac69315fa"},{"path":"core/crates/auths-algebra-kernel/Cargo.toml","sha256":"0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba"},{"path":"core/crates/auths-algebra-kernel/src/generated.rs","sha256":"ae4bcbef42a408c7ffa0c6a74a42f7de177a6f14479e51d205acf830bda05960"},{"path":"core/crates/auths-algebra-kernel/src/lib.rs","sha256":"6654667eeb9b353d6648954c9fd2e8838462a82ce6b2803eb49e1366892c68c6"},{"path":"core/crates/auths-assurance/Cargo.toml","sha256":"afcb12a97ddd09d7a264b9ecd3fcaefc865ff2c9b4539ee85b00883420ba333a"},{"path":"core/crates/auths-assurance/src/lib.rs","sha256":"0fb2ec844d674b25a9e20b1601452c89c2454901fa506adfa9bb38ef9a7fa213"},{"path":"core/crates/auths-author/Cargo.toml","sha256":"1e6f0e3bc079ddb558decf0db26b291c6e72fc47327b6df1b7650d41689b215f"},{"path":"core/crates/auths-author/src/lib.rs","sha256":"e14475f2f49715a1869d5fa6b11ff1fbb72497e39097e09f833b0bae7e5b3f2b"},{"path":"core/crates/auths-author/src/observations.rs","sha256":"dda7d6bfa6f4bd7e95a480ca283c2c0e996f69c5c15cb0c7197af328131a7066"},{"path":"core/crates/auths-authority/Cargo.toml","sha256":"4f68212938029f79ebd857b4f3038494eb85d0163d49f07e51376715cf959815"},{"path":"core/crates/auths-authority/src/lib.rs","sha256":"da88d5194de4e17449e69972c0fb042afa3c39798a8f570f30771e77c384f1eb"},{"path":"core/crates/auths-codec/Cargo.toml","sha256":"e20e51826e17814effd9d8925d18d5fbdd6c0d37bf50231e743ec2611314722c"},{"path":"core/crates/auths-codec/src/approval.rs","sha256":"fbff43bf4d57f69f8b7738a8647751cde75c5a932dee65d924a1fe9c7202f91f"},{"path":"core/crates/auths-codec/src/bounded_policy.rs","sha256":"d21f6728be2d8a04b6d94921f2b683f7e61cbb42e0ac6866f1c88a49caa534c3"},{"path":"core/crates/auths-codec/src/decode.rs","sha256":"ba2999584cdf53b1b517ecb9c7ea50d39efee17c666a9a38e2ad1ac94379f778"},{"path":"core/crates/auths-codec/src/encode.rs","sha256":"8491192053e2e15d62b4d2a491de22405b7487ead69ab6f6bca40669ce7ca5f7"},{"path":"core/crates/auths-codec/src/error.rs","sha256":"fecb0737c16deb42d859f1dc7727c698438d9ac12064fd99e0024629642c390c"},{"path":"core/crates/auths-codec/src/hash.rs","sha256":"f88e111f1dbb2cef6b7b5e9c948cb45ff92e366710c8a5f5c636138aa748479e"},{"path":"core/crates/auths-codec/src/lib.rs","sha256":"3b0e5c94c6f34f750b88a9333e1d5c8145746d845d3a23e0d2f61807cf592ea7"},{"path":"core/crates/auths-codec/src/observation.rs","sha256":"38328b0c71ff97a4196eeade8b4faa889527ff1f80bb168468bcd49082a3987e"},{"path":"core/crates/auths-composition/Cargo.toml","sha256":"331e13025eb82588b5269ed3975929eb41c823d588c49e4c296273d85c6fe80e"},{"path":"core/crates/auths-composition/src/lib.rs","sha256":"e42e3b0b6a9985b73c533aeb23799c638979aa27a9ce7d0f10a8d60340570fb1"},{"path":"core/crates/auths-model/Cargo.toml","sha256":"565c15302b0cc9270db1e28efa3862804846850ba933cc17aea8abcec4a65987"},{"path":"core/crates/auths-model/src/approval.rs","sha256":"54cf44a9ef747ec21546a4086aecfb130bc7803b0d646430e6082df51e6e305f"},{"path":"core/crates/auths-model/src/bounded.rs","sha256":"f90496abc0a06c028b4d850af6ddab7d850bfafeaa3d042f1b1246a41d8bbbc9"},{"path":"core/crates/auths-model/src/bounded_policy.rs","sha256":"306a8f049cc7cfc7635fe0e4de47eb7813eed63d3c14c3be2b51586aa4eea450"},{"path":"core/crates/auths-model/src/lib.rs","sha256":"e7cfe6bb9574c6b016aa63e70658c31e0b90903ec6479a49f4a2ceb64f5bad97"},{"path":"core/crates/auths-model/src/observation.rs","sha256":"b3ed3e3cc090afca2896a7d3de7988afccc1ee1ea0ebd91b51a8bc0f20ad8dbb"},{"path":"core/crates/auths-multikey/Cargo.toml","sha256":"858756c1197befcada06134742bffe8d58cf674cadd6c046bf710570e96efaf2"},{"path":"core/crates/auths-multikey/src/lib.rs","sha256":"f5177fffb11e40eeaaa665ba886c541fc1f24d5eacdd6983fb03dc20148733f0"},{"path":"core/crates/auths-ports/Cargo.toml","sha256":"596a9b0f5af3717c16a6d13f7054d8a106bcd9f01f5f72c2235dd2afcf0ab16c"},{"path":"core/crates/auths-ports/src/binding.rs","sha256":"a16c012d40aa4249e3ec54372b9611006d0bfe8c7dc3c741911c2194ad17736d"},{"path":"core/crates/auths-ports/src/diagnostics.rs","sha256":"aa596572503b5a65a918bb2ff38281c144ff53821ee914e9325c852828d852df"},{"path":"core/crates/auths-ports/src/lib.rs","sha256":"8da1debf86f9532df0660155d04298beb1ba3a1204508f8586e2e67cd2fb3449"},{"path":"core/crates/auths-ports/src/path.rs","sha256":"b68fc547b4e4d97a60cbbc1cc1939fc6b34a8233b81f840bd396914a707e3ea1"},{"path":"core/crates/auths-raw-key-core/Cargo.toml","sha256":"98c0bc8527a537512e43a74dd6ba9658c6f0cdc16610cf938e3f9b43785d836d"},{"path":"core/crates/auths-raw-key-core/src/lib.rs","sha256":"98c0500c41697aae28708ad0bf970b9a97583d96a3d2c18d23e7fa351e0f7d12"},{"path":"core/crates/auths-registries/Cargo.toml","sha256":"590e49e58b0622d9d6274fea46796dcdb07dec9550eff295cce6a6427ffa51e2"},{"path":"core/crates/auths-registries/src/lib.rs","sha256":"450d3886d85ee333b7e046317fb5b47cde62483d5f3e41d46265e2caf4c373ec"},{"path":"core/crates/auths-registries/src/template.rs","sha256":"1224039dd2b3ce6fa8357613d8cafbae40400493da7176da202b9ade62fa05e4"},{"path":"core/crates/auths-signature-core/Cargo.toml","sha256":"6bee2230eb30af1be0bd5c2d57bd3e1903497a70028d47290d4ac6e9e0e8bca0"},{"path":"core/crates/auths-signature-core/src/lib.rs","sha256":"6e3f9311ded5e49ea50d445eb21e6d8fa12442aa4362a73e0cb6fda15b7cd865"},{"path":"core/crates/auths-signature/Cargo.toml","sha256":"7f7b5682466ba439d8c59579022cb61068cad9fb4bd2d73e1cc21327c902b450"},{"path":"core/crates/auths-signature/src/lib.rs","sha256":"b3d9ac4cc3ba0797b9e1c09f2d6ac05089b25dac4e285a5af28c0165b33d925b"},{"path":"core/crates/auths-verifier/Cargo.toml","sha256":"c43358e06a33324b41a8b93e5cc7279c55f7d21f1f6cfaa539a3fc7b4c27a38f"},{"path":"core/crates/auths-verifier/src/approval.rs","sha256":"c3cae6a49e169051eb555bb092b1069a4d422516d6a2114623a89e5f31ff923f"},{"path":"core/crates/auths-verifier/src/causal.rs","sha256":"9635230f33b13a263573d319ac8a1976addbcc07677514a43e3c7bf28dc04587"},{"path":"core/crates/auths-verifier/src/lib.rs","sha256":"f22dec38dfa47ced8da4f605390da8453273bee1da010f57fd1fdfcb10e0b389"},{"path":"core/crates/auths-verifier/src/observation.rs","sha256":"0bb07f06a0f9524c88427df1c972b1de8ba038a9eeeb15d3134c25125ae84b1e"},{"path":"core/crates/auths-verifier/src/trace.rs","sha256":"2213d72023a1d9e0413a2cf2c51c3dad9e04775d86033a0caaa9d29a8f0036f8"},{"path":"exchange/crates/auths-proof-exchange-model/Cargo.toml","sha256":"34b2db64f93a288e942b5a3918d28cdcbef906e0dc9074ce848018d3d5f7a1fa"},{"path":"exchange/crates/auths-proof-exchange-model/src/lib.rs","sha256":"49fac5aff2339d3a57c41cb8bb2a82852538e8f77ecc4b157c88e264ff31fb55"},{"path":"exchange/crates/auths-proof-exchange-port/Cargo.toml","sha256":"7ff660f1b7579dc570c791090aeb450404fbbf44c92781e289f5ccdde746d739"},{"path":"exchange/crates/auths-proof-exchange-port/src/lib.rs","sha256":"b408fb40c6432edc1facb3d8b3e9433a033f8dc73fe2e0ba5a88c972ca675021"},{"path":"product/config/auths-config/Cargo.toml","sha256":"e4b568ab9f6d84f7d7e6d66443fe825f360db9c27bc7c31d6ddc0647ba3ab304"},{"path":"product/config/auths-config/src/lib.rs","sha256":"fecf00ea65cef9018fda9af2063326d7065b869266d0d9e73a4f06816f1102cc"},{"path":"product/errors/auths-errors/Cargo.toml","sha256":"3b3a199b6460ba75bda84475bb5accd35e1485448a3981038db85bf4772dd350"},{"path":"product/errors/auths-errors/src/lib.rs","sha256":"7feeb9069fa4003f94f1f07c1c94619cf1c883e0dbaaf2187f04d0f742264bdd"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/Cargo.toml","sha256":"716f1f2a117d6d69d8effe9ee9057e24ba3502f20af6a602b06facb638cdabed"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/api.rs","sha256":"9ea61dd7ddd93282b073b98e453e6b75b26dc49689c04e9782435d06a3a09e48"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/clock.rs","sha256":"73f0a6e0f5903883329fa6683f5888288f759512ac69e5c87efd2b6b87f7d79f"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/http.rs","sha256":"14c1fce14e24c984b2a275563a29b6326fb08367922b6e8d37ba38b9cb81aa2b"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/identity.rs","sha256":"186de11230c8b33375951c4368609f8976bf9795f171af3fd7fac26207a94361"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs","sha256":"0b4617d044f5254a5ab22f5a2578f91cc025206a8c1845be39c1c56dcdf7a5df"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/names.rs","sha256":"41bb23572d6002e23ee103d6fe70ecd68764861c6f2e48a1c53af998270a4afa"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs","sha256":"39fed883f4802e68d3b41a68fea0aba0737810996b33d13577de70faba004c29"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/store.rs","sha256":"fc60ee9c49b2f4f063c449b4c78100c5c4872779e94ca168f796603b380ef6e4"},{"path":"product/integrations/auths-custody/Cargo.toml","sha256":"1e14034185ad1ec24a977fd5f41d0abee219606245c046ce2a82287fadef448b"},{"path":"product/integrations/auths-custody/src/conformance.rs","sha256":"8ed1afd58f18fc6becc268908aa6419c9aa404c79da0197963eb2599df44acf6"},{"path":"product/integrations/auths-custody/src/key.rs","sha256":"70cbb0fd21b6f5652157845a22c35be2d0f6c05b3d138fc4b9bb6dbdc3d81c40"},{"path":"product/integrations/auths-custody/src/lib.rs","sha256":"8ee593c1f59b0fd2126bdda9138026f5bc531beb64d4489a99785842e7b98b43"},{"path":"product/operations/auths-operations/Cargo.toml","sha256":"73dde1e914ba5e1386f8d49c0d730423cc72ae77ec44c6554a6a75cc8e8922b1"},{"path":"product/operations/auths-operations/src/explanation.rs","sha256":"b4a39bcbd5712cb9e735ee7deeb281f3fa6af5ddca973735bf3d87dce427ef11"},{"path":"product/operations/auths-operations/src/lib.rs","sha256":"3f401a56555113b98f57bca172a2660eaecedf76247b83a3fdbb089c133a29cd"},{"path":"product/operations/auths-operations/src/render/json.rs","sha256":"2ae042639960afee123730e945d373bc5dda1d2b3af20ae16c939a7e99b9e418"},{"path":"product/operations/auths-operations/src/render/mod.rs","sha256":"b3b7f6fe473f49227ace5a68bfc3d8dc14b5db8dd9888fd9e207070337b1b8bf"},{"path":"product/operations/auths-operations/src/render/text.rs","sha256":"f216cf3bdb00e264523271b16e7059535ac6b1aabf271cebd7935af155e4bfec"},{"path":"product/policy/auths-bounded-policy/Cargo.toml","sha256":"babd5d200923137ead71d8c2528f847cea323ce98da942a1320b054436612c47"},{"path":"product/policy/auths-bounded-policy/src/arithmetic.rs","sha256":"75e43c5d4eab8d1f71c1daf53839f5f9fe45a400afc1f63a30c6f55ce3632627"},{"path":"product/policy/auths-bounded-policy/src/commitment.rs","sha256":"c5706f2d583454e1a7f570f7ada138d4d864bef0205dfae7c1296774f396bb3f"},{"path":"product/policy/auths-bounded-policy/src/eligibility.rs","sha256":"c9acdfb793074e687fc36efad506be27dbd99ffbf40387bc66c8de39ef238432"},{"path":"product/policy/auths-bounded-policy/src/identifier.rs","sha256":"0006a32bae9eb16c4178cf797df418d2b0a781f2bc6474b741dc1a908141831c"},{"path":"product/policy/auths-bounded-policy/src/kernel.rs","sha256":"99187c28b161ac70bee1afed60711f7f645adb4d1671a01863f9849b369811d5"},{"path":"product/policy/auths-bounded-policy/src/lib.rs","sha256":"76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c"},{"path":"product/policy/auths-bounded-policy/src/receipt.rs","sha256":"3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad"},{"path":"product/policy/auths-bounded-policy/src/registry.rs","sha256":"4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0"},{"path":"product/profiles/auths-profile-api/Cargo.toml","sha256":"7ae85761f58625b5d678f961fd052eebf3e000ef565c7312e3ac857763c0017f"},{"path":"product/profiles/auths-profile-api/src/lib.rs","sha256":"a194b82b20bf8aa864c2334ef6c6aec30b2154ded972862252d5dcefa488ab95"},{"path":"product/profiles/auths-profile-mcp/Cargo.toml","sha256":"db264fc25242f7b7e4133cbe5782545b3107b406c87168ae072683cfb59eac66"},{"path":"product/profiles/auths-profile-mcp/src/arguments.rs","sha256":"a5de696586d507e2aee4a49fee99ef1ef4c51a2e46603f8838f1af6d9009833f"},{"path":"product/profiles/auths-profile-mcp/src/lib.rs","sha256":"d0f8b733a09ef8408336cdebc8948d6a5861012ce6878598b11be7084dfd4280"},{"path":"product/profiles/auths-profile-mcp/src/session.rs","sha256":"166c281fa66333388e4760d6098dad02d3359e1d5de4b8f93312c014f97abb03"},{"path":"product/qualification/auths-recipe-qualification/Cargo.toml","sha256":"b7b15b30b9a3d96d4f089d514266d3a892de6608d30707aa44be31cca89ca9fe"},{"path":"product/qualification/auths-recipe-qualification/src/canonical.rs","sha256":"30a9b50777f0dcb4b606abfee2467d5a975d9f6ad941ab6c13ca3df5b359f667"},{"path":"product/qualification/auths-recipe-qualification/src/closure.rs","sha256":"0ad6aee9bd981e2863fa725f209ec84031db2ff12f4c7ac3aaf5120f0bb86039"},{"path":"product/qualification/auths-recipe-qualification/src/error.rs","sha256":"52d5cf720a1e4579008fdda90a3ac2c31f0b8db57985f121f65e54b4da2b7dd1"},{"path":"product/qualification/auths-recipe-qualification/src/evidence.rs","sha256":"1a4cb862f725b02f9efd827db99637ea8178a5236aa020ec271a363edbe7b362"},{"path":"product/qualification/auths-recipe-qualification/src/ids.rs","sha256":"e81a906d571497ab2da753e1532d4443706410e0b75fdd59a7d2d788c7aec403"},{"path":"product/qualification/auths-recipe-qualification/src/lib.rs","sha256":"195b19f46e1e94a0f3594ad5958e5715bc5e3ad415bdfe6428dfc1b6dd3f4631"},{"path":"product/qualification/auths-recipe-qualification/src/model.rs","sha256":"3484eb0ec287b23d4682ade7b1b0f8d1335985b3fb180f06fc28716076957d5f"},{"path":"product/qualification/auths-recipe-qualification/src/release.rs","sha256":"d816b53e2275e902c750ad03803061844e259e28560ab2d1c77e8a43981a4d6a"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/mod.rs","sha256":"7f15b68e05a04f202bcb1fb80de1d9a9a4fda8bfd6af2cd4e5c660fc75d96fe5"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/schemas.rs","sha256":"c59feec2805621f341a90f81fc005e2c12f7a70f9d264fdeacccb2be4fe1c046"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/verification.rs","sha256":"6a6b5834c5dae10af1ba8939b2deae43b85db71544dc8f077ff63b7fe68ac8a8"},{"path":"product/qualification/auths-recipe-qualification/src/verify.rs","sha256":"edd33589c54fb79bcfccc4cf4e6ccf95bbca088318bb7f8dfc27da684b4fa671"},{"path":"product/receipts/auths-receipts/Cargo.toml","sha256":"6001fa1375899953aafcb07c23a6da0c8f57ea7ec08bb9c950b12a60a8cc6f0f"},{"path":"product/receipts/auths-receipts/src/disclosure.rs","sha256":"ba9ed439be0a320c8a01f5b6e9b51361c1a37e076947490d8e4a484ba6bb119c"},{"path":"product/receipts/auths-receipts/src/lib.rs","sha256":"547a57c4160256719cafb7d0ab972d9fc80b0da14fbbce4148c70c414070ff36"},{"path":"product/runtime/auths-connections/Cargo.toml","sha256":"babeb6e1dda3dfb66291713ce1e43dce5c349833d0b50ea4dccbf986030026b2"},{"path":"product/runtime/auths-connections/src/credential.rs","sha256":"82921413bb053f0f6c7931fbd4e6a86c8cc1d8c6b51debd9c2cef33a8d5b1c51"},{"path":"product/runtime/auths-connections/src/kernel.rs","sha256":"a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8"},{"path":"product/runtime/auths-connections/src/lib.rs","sha256":"79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22"},{"path":"product/runtime/auths-connections/src/model.rs","sha256":"de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77"},{"path":"product/runtime/auths-connections/src/registry.rs","sha256":"e57640e003e72ad3235c567c2bb944a262bd64e673f023b62ea091094cc7e946"},{"path":"product/runtime/auths-gateway-kernel/Cargo.toml","sha256":"34f864e67656af4ac7e5c7a347a23f01fc8ab31365b8e23c0ef474483b14a183"},{"path":"product/runtime/auths-gateway-kernel/src/construct.rs","sha256":"e9d65744bae273d65face4285e5d2da75c06a92ab48f7b8333d496604e31c63c"},{"path":"product/runtime/auths-gateway-kernel/src/lib.rs","sha256":"cfda6f8453426564c085475f183b6f790b438768a19668f1b65d33ba59dc8632"},{"path":"product/runtime/auths-gateway-kernel/src/order.rs","sha256":"e0045f877c4b7fe3860c291039853885064ddcdebba7c9b345ab65e81e646dda"},{"path":"product/runtime/auths-gateway-kernel/src/outcome.rs","sha256":"e9785b1afe70788c89b51b18655bcd5acff7b0c8e3d12fb79c6f05a202e67e6b"},{"path":"product/runtime/auths-gateway-kernel/src/ratio.rs","sha256":"7ace22264812e6fc1ef3a62afee402cf43494bb71ae0d3de219ad1b39d690bcb"},{"path":"product/runtime/auths-gateway-kernel/src/recovery.rs","sha256":"9f46dcd1685ab6e4d1ba04a3fc286a9f3afee8fb47829be1fbc670a7926a2dc6"},{"path":"product/runtime/auths-gateway-kernel/src/transition.rs","sha256":"cefb8f01d915880f6921f2501ff881ad94b9de61072c34d9cd19220992f97374"},{"path":"product/runtime/auths-gateway/Cargo.toml","sha256":"00b28be86921dcdc0ad90cce0c62c2961cafefe96ea6c2edf0e926c3d405ccad"},{"path":"product/runtime/auths-gateway/src/admin.rs","sha256":"2d5cc67afac42fbd15f36e2d1693cd1b20cedacf775040dce6ffe04ccc94c9ea"},{"path":"product/runtime/auths-gateway/src/app.rs","sha256":"6f80f63833ea0815bb44fbf3b0cc54624a08e9fb578b035819f2980dc04e8256"},{"path":"product/runtime/auths-gateway/src/audit.rs","sha256":"0edb2037eb7b5d6f13acfce85c54f62a82bf7fdd31bc7e626c4fec183cef61dd"},{"path":"product/runtime/auths-gateway/src/audit_tests.rs","sha256":"990969384a52d75bc2489d9d412a9e7dd814bca1c8f65c701d6205fae62a15d5"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway-harness.rs","sha256":"12b0c24d36b2e6a3be392d3c081a783b355fdd67dc5b54bacc0410e803116b8c"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway.rs","sha256":"b1dab74ec9a0c301fc9896de15d4676274461928f8b09f5346c561d731d123b0"},{"path":"product/runtime/auths-gateway/src/binding.rs","sha256":"663b0ce878319511aa7d05722ab4ab2fa9be18817884ffb2ee9f131ff1e382d1"},{"path":"product/runtime/auths-gateway/src/bounds.rs","sha256":"9cfa0eae4973e5e047a198360b22f041708fa20276b0b90c2ec440f06915d64b"},{"path":"product/runtime/auths-gateway/src/bounds_aggregate_tests.rs","sha256":"ab34f227b7c8692ba1da88ccb32bb3687a66adf8353d8282fae905d4a88eb612"},{"path":"product/runtime/auths-gateway/src/bounds_tests.rs","sha256":"74136bc570da7b9338b5a1a1ed9d3fd892c55135160964f9d3ac0e2cf5741375"},{"path":"product/runtime/auths-gateway/src/connection.rs","sha256":"7b5d049c258a26ed1c93ecf860f51d051a8a65f9b93554af0b1ea93862398ec9"},{"path":"product/runtime/auths-gateway/src/credential_journal.rs","sha256":"8e2b0733038d93ca5df770d27a870237e3b65664fa48da017d964a65bbbe25b8"},{"path":"product/runtime/auths-gateway/src/echo_verify.rs","sha256":"6d453051665f823abd7354d5c50031d9524cf47d6092d2f09080ae814e3b9575"},{"path":"product/runtime/auths-gateway/src/engine.rs","sha256":"5c04a836112d02677de66a1b79d7487fc95fcaac4a9dfc9e1044a6c19ea1282d"},{"path":"product/runtime/auths-gateway/src/fuzzing.rs","sha256":"ed3b0028487eb546a3b0a91d115aa8f18bcea324b61620bfe8e35a9e6ab18758"},{"path":"product/runtime/auths-gateway/src/generation_floor.rs","sha256":"999ec17cd6f0c11ab144d971e75dcf824b8b71fbffa355cde0dff9555dd7db78"},{"path":"product/runtime/auths-gateway/src/harness.rs","sha256":"c87e479f3eb281960f6c9c80d43c7560d7ccb654b0154ec823d3fcec4884ac05"},{"path":"product/runtime/auths-gateway/src/lib.rs","sha256":"b182052835a2cd631d1f801a74788d6ac1ef9cae21ade9ab4ffc270cd6f667ed"},{"path":"product/runtime/auths-gateway/src/listener.rs","sha256":"aa08239bcbc1fcb55e8a212fbdf6a84f12985b0d436dcb51dc58b06e59e435f2"},{"path":"product/runtime/auths-gateway/src/observed_tests.rs","sha256":"a22be071695f89ca2578a4d82fd80d9cb82289213c9bdb8f0470f6b2dc3d9201"},{"path":"product/runtime/auths-gateway/src/observer.rs","sha256":"562ffcaea071c3856e0708dc2fe33516917e145d2438aabb75af0a2b6ba01046"},{"path":"product/runtime/auths-gateway/src/onboarding.rs","sha256":"0dfd7d67e7f02f18a28d1c86ca1b7751d7463f5efcdbe3825de0ad8cbccb3891"},{"path":"product/runtime/auths-gateway/src/operator.rs","sha256":"c3c36954a3e86723df035b47f43b85fc8ab3a6292983522b6258d5c6b4e6c4e4"},{"path":"product/runtime/auths-gateway/src/pending_vectors/attempts.rs","sha256":"47ef3c8cb1c5504d47ae9a0088705ce6715fe86bac1671a34a56fb38a64d0dd3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/bounds.rs","sha256":"e612217307e1da5b0eb5ee6582a7458bb064b8aa8a529fc6555b1b334127ab68"},{"path":"product/runtime/auths-gateway/src/pending_vectors/codes.rs","sha256":"e00670a5ef24eb856cc2c6dcda8e5a263842f55c76bb939c0c27bd9df37e5522"},{"path":"product/runtime/auths-gateway/src/pending_vectors/keys.rs","sha256":"f84c56f2ea9cb34b2b79c72d13fbf2c6585010ec1ed450af58a78c80c1ea1edd"},{"path":"product/runtime/auths-gateway/src/pending_vectors/mod.rs","sha256":"5de8340f0ef71a0b57a09e323fefe473d3160c6ae952b9ba46f714825fbacafc"},{"path":"product/runtime/auths-gateway/src/pending_vectors/outcomes.rs","sha256":"8ec07b9511b48913af36ac999d2aa0e82924289f6acb23ddaeb9f00f99815166"},{"path":"product/runtime/auths-gateway/src/pending_vectors/production.rs","sha256":"f574cabfa4687a4fc846b8f6a234b68ec53b876aed548b11445729cac1a55ede"},{"path":"product/runtime/auths-gateway/src/pending_vectors/recipes.rs","sha256":"51693208270231c25c3aef2a32151d5962114c71e86b88cb9df83181c7af83d9"},{"path":"product/runtime/auths-gateway/src/pre_entry.rs","sha256":"06ea78ca140468bfaba17d9ab04912ad68673954c3203c98fed28272ff2a00c0"},{"path":"product/runtime/auths-gateway/src/property_tests.rs","sha256":"939c081e2e154aaf10186754044bdd65608932c899b970a04a71d0afaa999a93"},{"path":"product/runtime/auths-gateway/src/qualification.rs","sha256":"fd79f80c6cce2342a0ccfc8d271cb69d310179b7e93a2472c83e0e4a38d21735"},{"path":"product/runtime/auths-gateway/src/qualification_tests.rs","sha256":"4473add5729b97faf04d7be7fd8cf3bbacd7f545e1b61c7d2782563011906b4d"},{"path":"product/runtime/auths-gateway/src/quorum_tests.rs","sha256":"a78380b019104d688c11a4410082c7e08ded3106aab099954c4f8a1b4ae0fd89"},{"path":"product/runtime/auths-gateway/src/readiness.rs","sha256":"911c3f11892f94641574375e2da4c671c802738f71082f12c39832331052d43d"},{"path":"product/runtime/auths-gateway/src/recipe.rs","sha256":"fecf9af67e7afc48d080e9f8f55f8ce28e49d0e08988717a27908bbda461d6b6"},{"path":"product/runtime/auths-gateway/src/recipe/lower.rs","sha256":"8088b8751ed831dbb48247af953c6290ac95e2a438ccd5bd65eff54be06a1fd1"},{"path":"product/runtime/auths-gateway/src/recipe/review.rs","sha256":"c3eb7d9fdd98dacf52750b14b67ad7b7faaecbbdeafff1e0b049f67d0a2d0139"},{"path":"product/runtime/auths-gateway/src/recipe/runtime.rs","sha256":"c286f0d15f974402822c0810d8e97f98411dc1c557755cc23e540d85e2bb42d9"},{"path":"product/runtime/auths-gateway/src/recipe/source.rs","sha256":"1af50298fb1461e1b24cbdf560d43124d6b1c4c529586c911b1c4797214a69ff"},{"path":"product/runtime/auths-gateway/src/recipe/tests.rs","sha256":"aac551a2481bbc60864c64079bc667dcb232e45a0f41a04073ed84ab5dbe1fce"},{"path":"product/runtime/auths-gateway/src/recipe/validate.rs","sha256":"3711b17605cb7b0d639bc1b180449231f5882a306cab20e2c7782155cc63b0d4"},{"path":"product/runtime/auths-gateway/src/scenario_tests.rs","sha256":"d8271761b12597bfe1233f8eb5ad1d4e5498c5d03388e832e24ab818484a1de4"},{"path":"product/runtime/auths-gateway/src/separation.rs","sha256":"be9306848ca5d801767cf6aa14247c8618312ef0e202f00ce0c24c4844491061"},{"path":"product/runtime/auths-gateway/src/store.rs","sha256":"1e5288345c2cb1421aeda277b3158d07607404b0ec46943222ac107b63dcbb46"},{"path":"product/runtime/auths-gateway/src/store_testkit.rs","sha256":"88d82fee42f1b8ef521e8deef0216e938ebeaad822eb2f5020e70b89d145ea70"},{"path":"product/runtime/auths-gateway/src/submit.rs","sha256":"c78dbbba7c45b443febf655056c5edcd635e77be7b21c5b2c318097502415ffe"},{"path":"product/runtime/auths-gateway/src/support.rs","sha256":"9fd979029793a22b15d9776a7fc172476fd7c126a80d4080c65d720845becbcb"},{"path":"product/runtime/auths-gateway/src/transport.rs","sha256":"be2c6dc75b8daec110bf8749fedc3823f6067d40b999aa3eb21126896a97d3ad"},{"path":"product/runtime/auths-kernel-runtime/Cargo.toml","sha256":"926bcd0053e5edd703be8f0027ad009e2982db013c8174c1366edbf38b48087d"},{"path":"product/runtime/auths-kernel-runtime/src/lib.rs","sha256":"7108faae9ca4bc32dc093ddaf885ac8f74f3c9b8d317b7c7d0ed00d1d0ab5972"},{"path":"product/runtime/auths-lifecycle/Cargo.toml","sha256":"c5053c705f8d5554b44e432fe75287a2faf11d644e5a2552e45ad6cd94176af5"},{"path":"product/runtime/auths-lifecycle/src/codec.rs","sha256":"51c4b746749150e8bfcd8ff972b3f6c1ef40bec15583448ec1b471d9ad737dc0"},{"path":"product/runtime/auths-lifecycle/src/digest.rs","sha256":"55282cd7d8aba37713c2dcb5357c9877819edb72a30eadefb860d28d7d3a3eb7"},{"path":"product/runtime/auths-lifecycle/src/identifier.rs","sha256":"31620e8c16de68d3d2d3b84d6353c1a5b9d4151d8247f91fa389b906a8e660f1"},{"path":"product/runtime/auths-lifecycle/src/kernel.rs","sha256":"2abb8c094b36d35b364e74d78091d14c5d6f3d1eb6552cca3b5538dbd017ce23"},{"path":"product/runtime/auths-lifecycle/src/lib.rs","sha256":"afe5a345cd309b5a4f08ffba3170a6d7f16ff914892b3f2006d5208ed24ec736"},{"path":"product/runtime/auths-lifecycle/src/model.rs","sha256":"1af12bbeeeaa65ec02ddcebd7d2c8c92ec1e339fa40ae85b45ab9b01a722a4fa"},{"path":"product/runtime/auths-lifecycle/src/operation.rs","sha256":"78e6d05fcf5d7ea4f148032a3fa26fdfcab77eb346019effe927b08e0d64d732"},{"path":"product/runtime/auths-lifecycle/src/registry.rs","sha256":"53495fe6f7a77422593a41623e28716f1c140dcc1e00f87f6b0ffbfb93a5ef90"},{"path":"product/runtime/auths-lifecycle/src/sealed.rs","sha256":"2e0c03b5813c926c159598bb7890d1523825edbe57cd687d42a5dfb3374a0c19"},{"path":"product/runtime/auths-lifecycle/src/test_support.rs","sha256":"221d9a5c5ef8e1f9f8fd66927484eaf813571d0568470278ecd8fa08a5eec8cd"},{"path":"product/runtime/auths-lifecycle/src/transition.rs","sha256":"011805a28efdd541f44ccea54dd0e34a1e58f4004447ee58013703b4fb6b2822"},{"path":"product/runtime/auths-runtime/Cargo.toml","sha256":"dd29d80a8b4bb56c869f036a6c9998f6e6d1c0383ac5dc03fa42b24abe2a7ff7"},{"path":"product/runtime/auths-runtime/src/lib.rs","sha256":"132ca03d58c14905d3a822a4972f42a22a5ad33a45f2ba9ca44f3a57d810b4b0"},{"path":"product/runtime/auths-runtime/src/production.rs","sha256":"fd4eff4270c571c10fcff6cf27df28961ebf074de8a1a028f500fda1ca376820"},{"path":"product/sdk/auths-approval-quorum/Cargo.toml","sha256":"df904971fca87a24194c5816738a331588fe8f164acb5d70839a35dca5f57114"},{"path":"product/sdk/auths-approval-quorum/src/lib.rs","sha256":"72e4086088a1c0912e4e1a9e980f26a5c280bf5ab16ea39c9f0f58d5096ac2ce"},{"path":"product/sdk/auths-approval-quorum/src/remote.rs","sha256":"9fa029c7c63003adf260f8aec55160c545681c60c1bace0d934e7525862aac7b"},{"path":"product/sdk/auths-approval-quorum/src/remote_tests.rs","sha256":"8a09ce17cfee82a035a74edd535f3ebeb3db0e078784740d3997b17dbdb10197"},{"path":"product/sdk/auths-approval-quorum/src/tests.rs","sha256":"0acbf12be3e497dcc6c2d8f29c9af3b1a7ed8e11b75f6399570d4f217a785060"},{"path":"product/stores/auths-stores/Cargo.toml","sha256":"a32c4b76d17b264be5d40d24497ff237e1ed87822e8bab86229b3db93106dbe3"},{"path":"product/stores/auths-stores/src/gateway_attempt.rs","sha256":"185da8f4a220fba836d5b78a9311f03204681c43a3c53951008084d135bf4d21"},{"path":"product/stores/auths-stores/src/lib.rs","sha256":"e721262edf8a9ab5568ddc27639176312d4a366203b5f73e2d7c11fde2c554e9"},{"path":"product/stores/auths-stores/src/lifecycle.rs","sha256":"94f64d25bc178a9e60ba3c0ee6915d7fb3af7c4468792d76b4e70f43f4de1e2f"}],"schema":"auths.gateway-semantic-closure/1"} \ No newline at end of file diff --git a/product/runtime/auths-gateway/src/qualification.rs b/product/runtime/auths-gateway/src/qualification.rs index 2c22fb7a7..f96641d4a 100644 --- a/product/runtime/auths-gateway/src/qualification.rs +++ b/product/runtime/auths-gateway/src/qualification.rs @@ -16,7 +16,7 @@ use auths_recipe_qualification::{ }; use sha2::{Digest as _, Sha256}; use std::sync::{Arc, Mutex, PoisonError, RwLock}; -use std::time::{SystemTime, UNIX_EPOCH}; +use std::time::{Duration, SystemTime, UNIX_EPOCH}; /// The install-time refusal of a qualification policy that is unknown or /// that production does not permit. @@ -106,11 +106,13 @@ fn system_seconds() -> Option { .map(|elapsed| elapsed.as_secs()) } -/// The production clock adapter: trusted exactly while the host's time -/// synchronization service has recorded a synchronization. +/// The production clock adapter: trusted while the host's synchronization +/// marker records a sample no more than fifteen minutes old. /// -/// The service records one by creating a fixed marker file. The path is a -/// constant of this adapter and no configuration names another. +/// Missing, future-dated, stale, symlinked or nonregular markers refuse. On +/// Unix, group/world-writable markers also refuse. The service updates the +/// fixed file after each synchronization; mere existence cannot establish +/// freshness. Neither the path nor the age bound is configurable. #[derive(Clone, Copy, Debug, Default)] pub struct SynchronizedHostClock; @@ -122,17 +124,40 @@ impl SynchronizedHostClock { impl sealed::Sealed for SynchronizedHostClock {} +const MAX_SYNCHRONIZATION_AGE: Duration = Duration::from_secs(15 * 60); + +fn synchronization_marker_trust(path: &std::path::Path, now: SystemTime) -> ClockTrustState { + let Ok(marker) = std::fs::symlink_metadata(path) else { + return ClockTrustState::Untrusted; + }; + if !marker.is_file() { + return ClockTrustState::Untrusted; + } + #[cfg(unix)] + { + use std::os::unix::fs::PermissionsExt as _; + if marker.permissions().mode() & 0o022 != 0 { + return ClockTrustState::Untrusted; + } + } + let age = marker + .modified() + .ok() + .and_then(|sample| now.duration_since(sample).ok()); + if age.is_some_and(|age| age <= MAX_SYNCHRONIZATION_AGE) { + ClockTrustState::Trusted + } else { + ClockTrustState::Untrusted + } +} + impl DeploymentClock for SynchronizedHostClock { fn now(&self) -> Option { system_seconds() } fn trust(&self) -> ClockTrustState { - if std::fs::metadata(Self::MARKER).is_ok_and(|marker| marker.is_file()) { - ClockTrustState::Trusted - } else { - ClockTrustState::Untrusted - } + synchronization_marker_trust(std::path::Path::new(Self::MARKER), SystemTime::now()) } } @@ -539,3 +564,79 @@ pub fn deployment_tuple(facts: &DeploymentFacts<'_>) -> Option Date: Tue, 6 Oct 2026 04:27:33 +0100 Subject: [PATCH 014/108] docs(gateway): order reconciliation around enabled leases --- docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md b/docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md index a3a90276c..de1310ade 100644 --- a/docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md +++ b/docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md @@ -138,7 +138,12 @@ database is current; recover its floors before starting it. For each response-recorded or unknown operation, use `reobserve --state-dir ... --operation-id ...` once. It uses the stored plan and a fresh read-only -check under the declared capability. Confirmed evidence may advance the +check under the declared capability. Reobserve requires an enabled connection +because it leases a credential; a disabled or revoked connection refuses even +this read. Only when the restored state passes the continuity and retained-floor +checks, keep app ingress blocked on both hosts, require every other readiness +check to pass, enable and rerun full doctor before reconciling. Do not enable +a quarantined restore to work around a refusal. Confirmed evidence may advance the record; missing or delayed evidence stays unknown. Reobserve again after visibility returns; never issue a new provider write as recovery. Keep the opaque operation digest and stage only in support evidence. @@ -151,9 +156,13 @@ support bundles and floors, and upgrade one host. It must derive the same recipe and connection generations; the old host must refuse a changed binding rather than choosing a stale credential. A binary without a current exact tuple attestation stays disabled. Validate doctor and read-only reconciliation -before replacing the second host and enabling. Do not mix obsolete store -schemas or interpret restore as replay continuity. Keep expiry and revocation -updates running during the upgrade. +with app ingress blocked on both hosts: while disabled, the connection check +must fail and every other required check must pass. Enable within that isolated +window, rerun full doctor and reconcile without submitting a new operation. +Disable again before replacing the second host. Check its candidate the same +way, then enable, require full doctor on both hosts and only then admit app +traffic. Do not mix obsolete store schemas or interpret restore as replay +continuity. Keep expiry and revocation updates running during the upgrade. ## Independent operator trial From 631f44c136c0c8fc507cb8ab11deaa2fa6e5b232 Mon Sep 17 00:00:00 2001 From: bordumb Date: Tue, 6 Oct 2026 04:30:41 +0100 Subject: [PATCH 015/108] docs(program): record GitHub SDK candidate handoff --- docs/PROGRAM_BOARD.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/PROGRAM_BOARD.md b/docs/PROGRAM_BOARD.md index 46cb8af06..5953074b4 100644 --- a/docs/PROGRAM_BOARD.md +++ b/docs/PROGRAM_BOARD.md @@ -356,3 +356,9 @@ neither live recipe environment exists; the offline owner root ceremony and live-provider qualification remain unclaimed. Python packaging must normalize the requested semver to PEP 440 `0.0.1rc1`, preserving `0.0.1-rc1` as the release/tag identifier. No publication or qualified launch is claimed yet. + +Owner clarification (2026-10-06): publish the RC as a GitHub prerelease with +downloadable Python wheel assets; PyPI publication is not required. Download +those published assets, verify their checksums and install them in clean +environments for the simulated onboarding pilot. Local checkout installs do +not demonstrate that release handoff. From 4ab303b16a2371fafef47e945687b741d4f4ef0f Mon Sep 17 00:00:00 2001 From: bordumb Date: Tue, 6 Oct 2026 04:41:56 +0100 Subject: [PATCH 016/108] fix(gateway): satisfy operator preflight lint checks --- .../auths-gateway/semantic-closure.json | 2 +- .../auths-gateway/src/bin/auths-gateway.rs | 78 +++++++++++-------- .../auths-gateway/src/generation_floor.rs | 4 +- .../auths-gateway/src/qualification.rs | 2 +- .../auths-gateway/src/semantic_closure.rs | 2 +- 5 files changed, 52 insertions(+), 36 deletions(-) diff --git a/product/runtime/auths-gateway/semantic-closure.json b/product/runtime/auths-gateway/semantic-closure.json index 3207c3e82..e9af3dbcf 100644 --- a/product/runtime/auths-gateway/semantic-closure.json +++ b/product/runtime/auths-gateway/semantic-closure.json @@ -1 +1 @@ -{"files":[{"path":"Cargo.lock","sha256":"c94ed342774d5e2823f01ecf74b8a4812c5f9a6b0cf811d31f2e2cecb671a275"},{"path":"Cargo.toml","sha256":"6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24"},{"path":"core/adapters/auths-did-keri/Cargo.toml","sha256":"86ba3e3f9a0a70d970568bfb3113b7ba7bbdd81c3eebbb52743dd574a0c0ecaa"},{"path":"core/adapters/auths-did-keri/src/lib.rs","sha256":"a75674842f8a7142004369ccd206ab43e476459293f0ff4bed4d4e659031b3e3"},{"path":"core/adapters/auths-did-key/Cargo.toml","sha256":"d5a3ae07ecde83f91eed4c3785051dd0f44eab6c891754f3309b6b40596707d7"},{"path":"core/adapters/auths-did-key/src/lib.rs","sha256":"b76a3f4528a725df53cfa9242e6e414e1d26caa48468aaed497e28b121f4497c"},{"path":"core/adapters/auths-raw-key/Cargo.toml","sha256":"f49616bc18c19e6aaa7e6a02ccebcdb9f5c1422c1278ef9869e0dbf22ceda7be"},{"path":"core/adapters/auths-raw-key/src/lib.rs","sha256":"45eec1b295dac3bed65cd79c942870b926b06b3f5d38eaebaeb6140ac69315fa"},{"path":"core/crates/auths-algebra-kernel/Cargo.toml","sha256":"0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba"},{"path":"core/crates/auths-algebra-kernel/src/generated.rs","sha256":"ae4bcbef42a408c7ffa0c6a74a42f7de177a6f14479e51d205acf830bda05960"},{"path":"core/crates/auths-algebra-kernel/src/lib.rs","sha256":"6654667eeb9b353d6648954c9fd2e8838462a82ce6b2803eb49e1366892c68c6"},{"path":"core/crates/auths-assurance/Cargo.toml","sha256":"afcb12a97ddd09d7a264b9ecd3fcaefc865ff2c9b4539ee85b00883420ba333a"},{"path":"core/crates/auths-assurance/src/lib.rs","sha256":"0fb2ec844d674b25a9e20b1601452c89c2454901fa506adfa9bb38ef9a7fa213"},{"path":"core/crates/auths-author/Cargo.toml","sha256":"1e6f0e3bc079ddb558decf0db26b291c6e72fc47327b6df1b7650d41689b215f"},{"path":"core/crates/auths-author/src/lib.rs","sha256":"e14475f2f49715a1869d5fa6b11ff1fbb72497e39097e09f833b0bae7e5b3f2b"},{"path":"core/crates/auths-author/src/observations.rs","sha256":"dda7d6bfa6f4bd7e95a480ca283c2c0e996f69c5c15cb0c7197af328131a7066"},{"path":"core/crates/auths-authority/Cargo.toml","sha256":"4f68212938029f79ebd857b4f3038494eb85d0163d49f07e51376715cf959815"},{"path":"core/crates/auths-authority/src/lib.rs","sha256":"da88d5194de4e17449e69972c0fb042afa3c39798a8f570f30771e77c384f1eb"},{"path":"core/crates/auths-codec/Cargo.toml","sha256":"e20e51826e17814effd9d8925d18d5fbdd6c0d37bf50231e743ec2611314722c"},{"path":"core/crates/auths-codec/src/approval.rs","sha256":"fbff43bf4d57f69f8b7738a8647751cde75c5a932dee65d924a1fe9c7202f91f"},{"path":"core/crates/auths-codec/src/bounded_policy.rs","sha256":"d21f6728be2d8a04b6d94921f2b683f7e61cbb42e0ac6866f1c88a49caa534c3"},{"path":"core/crates/auths-codec/src/decode.rs","sha256":"ba2999584cdf53b1b517ecb9c7ea50d39efee17c666a9a38e2ad1ac94379f778"},{"path":"core/crates/auths-codec/src/encode.rs","sha256":"8491192053e2e15d62b4d2a491de22405b7487ead69ab6f6bca40669ce7ca5f7"},{"path":"core/crates/auths-codec/src/error.rs","sha256":"fecb0737c16deb42d859f1dc7727c698438d9ac12064fd99e0024629642c390c"},{"path":"core/crates/auths-codec/src/hash.rs","sha256":"f88e111f1dbb2cef6b7b5e9c948cb45ff92e366710c8a5f5c636138aa748479e"},{"path":"core/crates/auths-codec/src/lib.rs","sha256":"3b0e5c94c6f34f750b88a9333e1d5c8145746d845d3a23e0d2f61807cf592ea7"},{"path":"core/crates/auths-codec/src/observation.rs","sha256":"38328b0c71ff97a4196eeade8b4faa889527ff1f80bb168468bcd49082a3987e"},{"path":"core/crates/auths-composition/Cargo.toml","sha256":"331e13025eb82588b5269ed3975929eb41c823d588c49e4c296273d85c6fe80e"},{"path":"core/crates/auths-composition/src/lib.rs","sha256":"e42e3b0b6a9985b73c533aeb23799c638979aa27a9ce7d0f10a8d60340570fb1"},{"path":"core/crates/auths-model/Cargo.toml","sha256":"565c15302b0cc9270db1e28efa3862804846850ba933cc17aea8abcec4a65987"},{"path":"core/crates/auths-model/src/approval.rs","sha256":"54cf44a9ef747ec21546a4086aecfb130bc7803b0d646430e6082df51e6e305f"},{"path":"core/crates/auths-model/src/bounded.rs","sha256":"f90496abc0a06c028b4d850af6ddab7d850bfafeaa3d042f1b1246a41d8bbbc9"},{"path":"core/crates/auths-model/src/bounded_policy.rs","sha256":"306a8f049cc7cfc7635fe0e4de47eb7813eed63d3c14c3be2b51586aa4eea450"},{"path":"core/crates/auths-model/src/lib.rs","sha256":"e7cfe6bb9574c6b016aa63e70658c31e0b90903ec6479a49f4a2ceb64f5bad97"},{"path":"core/crates/auths-model/src/observation.rs","sha256":"b3ed3e3cc090afca2896a7d3de7988afccc1ee1ea0ebd91b51a8bc0f20ad8dbb"},{"path":"core/crates/auths-multikey/Cargo.toml","sha256":"858756c1197befcada06134742bffe8d58cf674cadd6c046bf710570e96efaf2"},{"path":"core/crates/auths-multikey/src/lib.rs","sha256":"f5177fffb11e40eeaaa665ba886c541fc1f24d5eacdd6983fb03dc20148733f0"},{"path":"core/crates/auths-ports/Cargo.toml","sha256":"596a9b0f5af3717c16a6d13f7054d8a106bcd9f01f5f72c2235dd2afcf0ab16c"},{"path":"core/crates/auths-ports/src/binding.rs","sha256":"a16c012d40aa4249e3ec54372b9611006d0bfe8c7dc3c741911c2194ad17736d"},{"path":"core/crates/auths-ports/src/diagnostics.rs","sha256":"aa596572503b5a65a918bb2ff38281c144ff53821ee914e9325c852828d852df"},{"path":"core/crates/auths-ports/src/lib.rs","sha256":"8da1debf86f9532df0660155d04298beb1ba3a1204508f8586e2e67cd2fb3449"},{"path":"core/crates/auths-ports/src/path.rs","sha256":"b68fc547b4e4d97a60cbbc1cc1939fc6b34a8233b81f840bd396914a707e3ea1"},{"path":"core/crates/auths-raw-key-core/Cargo.toml","sha256":"98c0bc8527a537512e43a74dd6ba9658c6f0cdc16610cf938e3f9b43785d836d"},{"path":"core/crates/auths-raw-key-core/src/lib.rs","sha256":"98c0500c41697aae28708ad0bf970b9a97583d96a3d2c18d23e7fa351e0f7d12"},{"path":"core/crates/auths-registries/Cargo.toml","sha256":"590e49e58b0622d9d6274fea46796dcdb07dec9550eff295cce6a6427ffa51e2"},{"path":"core/crates/auths-registries/src/lib.rs","sha256":"450d3886d85ee333b7e046317fb5b47cde62483d5f3e41d46265e2caf4c373ec"},{"path":"core/crates/auths-registries/src/template.rs","sha256":"1224039dd2b3ce6fa8357613d8cafbae40400493da7176da202b9ade62fa05e4"},{"path":"core/crates/auths-signature-core/Cargo.toml","sha256":"6bee2230eb30af1be0bd5c2d57bd3e1903497a70028d47290d4ac6e9e0e8bca0"},{"path":"core/crates/auths-signature-core/src/lib.rs","sha256":"6e3f9311ded5e49ea50d445eb21e6d8fa12442aa4362a73e0cb6fda15b7cd865"},{"path":"core/crates/auths-signature/Cargo.toml","sha256":"7f7b5682466ba439d8c59579022cb61068cad9fb4bd2d73e1cc21327c902b450"},{"path":"core/crates/auths-signature/src/lib.rs","sha256":"b3d9ac4cc3ba0797b9e1c09f2d6ac05089b25dac4e285a5af28c0165b33d925b"},{"path":"core/crates/auths-verifier/Cargo.toml","sha256":"c43358e06a33324b41a8b93e5cc7279c55f7d21f1f6cfaa539a3fc7b4c27a38f"},{"path":"core/crates/auths-verifier/src/approval.rs","sha256":"c3cae6a49e169051eb555bb092b1069a4d422516d6a2114623a89e5f31ff923f"},{"path":"core/crates/auths-verifier/src/causal.rs","sha256":"9635230f33b13a263573d319ac8a1976addbcc07677514a43e3c7bf28dc04587"},{"path":"core/crates/auths-verifier/src/lib.rs","sha256":"f22dec38dfa47ced8da4f605390da8453273bee1da010f57fd1fdfcb10e0b389"},{"path":"core/crates/auths-verifier/src/observation.rs","sha256":"0bb07f06a0f9524c88427df1c972b1de8ba038a9eeeb15d3134c25125ae84b1e"},{"path":"core/crates/auths-verifier/src/trace.rs","sha256":"2213d72023a1d9e0413a2cf2c51c3dad9e04775d86033a0caaa9d29a8f0036f8"},{"path":"exchange/crates/auths-proof-exchange-model/Cargo.toml","sha256":"34b2db64f93a288e942b5a3918d28cdcbef906e0dc9074ce848018d3d5f7a1fa"},{"path":"exchange/crates/auths-proof-exchange-model/src/lib.rs","sha256":"49fac5aff2339d3a57c41cb8bb2a82852538e8f77ecc4b157c88e264ff31fb55"},{"path":"exchange/crates/auths-proof-exchange-port/Cargo.toml","sha256":"7ff660f1b7579dc570c791090aeb450404fbbf44c92781e289f5ccdde746d739"},{"path":"exchange/crates/auths-proof-exchange-port/src/lib.rs","sha256":"b408fb40c6432edc1facb3d8b3e9433a033f8dc73fe2e0ba5a88c972ca675021"},{"path":"product/config/auths-config/Cargo.toml","sha256":"e4b568ab9f6d84f7d7e6d66443fe825f360db9c27bc7c31d6ddc0647ba3ab304"},{"path":"product/config/auths-config/src/lib.rs","sha256":"fecf00ea65cef9018fda9af2063326d7065b869266d0d9e73a4f06816f1102cc"},{"path":"product/errors/auths-errors/Cargo.toml","sha256":"3b3a199b6460ba75bda84475bb5accd35e1485448a3981038db85bf4772dd350"},{"path":"product/errors/auths-errors/src/lib.rs","sha256":"7feeb9069fa4003f94f1f07c1c94619cf1c883e0dbaaf2187f04d0f742264bdd"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/Cargo.toml","sha256":"716f1f2a117d6d69d8effe9ee9057e24ba3502f20af6a602b06facb638cdabed"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/api.rs","sha256":"9ea61dd7ddd93282b073b98e453e6b75b26dc49689c04e9782435d06a3a09e48"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/clock.rs","sha256":"73f0a6e0f5903883329fa6683f5888288f759512ac69e5c87efd2b6b87f7d79f"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/http.rs","sha256":"14c1fce14e24c984b2a275563a29b6326fb08367922b6e8d37ba38b9cb81aa2b"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/identity.rs","sha256":"186de11230c8b33375951c4368609f8976bf9795f171af3fd7fac26207a94361"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs","sha256":"0b4617d044f5254a5ab22f5a2578f91cc025206a8c1845be39c1c56dcdf7a5df"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/names.rs","sha256":"41bb23572d6002e23ee103d6fe70ecd68764861c6f2e48a1c53af998270a4afa"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs","sha256":"39fed883f4802e68d3b41a68fea0aba0737810996b33d13577de70faba004c29"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/store.rs","sha256":"fc60ee9c49b2f4f063c449b4c78100c5c4872779e94ca168f796603b380ef6e4"},{"path":"product/integrations/auths-custody/Cargo.toml","sha256":"1e14034185ad1ec24a977fd5f41d0abee219606245c046ce2a82287fadef448b"},{"path":"product/integrations/auths-custody/src/conformance.rs","sha256":"8ed1afd58f18fc6becc268908aa6419c9aa404c79da0197963eb2599df44acf6"},{"path":"product/integrations/auths-custody/src/key.rs","sha256":"70cbb0fd21b6f5652157845a22c35be2d0f6c05b3d138fc4b9bb6dbdc3d81c40"},{"path":"product/integrations/auths-custody/src/lib.rs","sha256":"8ee593c1f59b0fd2126bdda9138026f5bc531beb64d4489a99785842e7b98b43"},{"path":"product/operations/auths-operations/Cargo.toml","sha256":"73dde1e914ba5e1386f8d49c0d730423cc72ae77ec44c6554a6a75cc8e8922b1"},{"path":"product/operations/auths-operations/src/explanation.rs","sha256":"b4a39bcbd5712cb9e735ee7deeb281f3fa6af5ddca973735bf3d87dce427ef11"},{"path":"product/operations/auths-operations/src/lib.rs","sha256":"3f401a56555113b98f57bca172a2660eaecedf76247b83a3fdbb089c133a29cd"},{"path":"product/operations/auths-operations/src/render/json.rs","sha256":"2ae042639960afee123730e945d373bc5dda1d2b3af20ae16c939a7e99b9e418"},{"path":"product/operations/auths-operations/src/render/mod.rs","sha256":"b3b7f6fe473f49227ace5a68bfc3d8dc14b5db8dd9888fd9e207070337b1b8bf"},{"path":"product/operations/auths-operations/src/render/text.rs","sha256":"f216cf3bdb00e264523271b16e7059535ac6b1aabf271cebd7935af155e4bfec"},{"path":"product/policy/auths-bounded-policy/Cargo.toml","sha256":"babd5d200923137ead71d8c2528f847cea323ce98da942a1320b054436612c47"},{"path":"product/policy/auths-bounded-policy/src/arithmetic.rs","sha256":"75e43c5d4eab8d1f71c1daf53839f5f9fe45a400afc1f63a30c6f55ce3632627"},{"path":"product/policy/auths-bounded-policy/src/commitment.rs","sha256":"c5706f2d583454e1a7f570f7ada138d4d864bef0205dfae7c1296774f396bb3f"},{"path":"product/policy/auths-bounded-policy/src/eligibility.rs","sha256":"c9acdfb793074e687fc36efad506be27dbd99ffbf40387bc66c8de39ef238432"},{"path":"product/policy/auths-bounded-policy/src/identifier.rs","sha256":"0006a32bae9eb16c4178cf797df418d2b0a781f2bc6474b741dc1a908141831c"},{"path":"product/policy/auths-bounded-policy/src/kernel.rs","sha256":"99187c28b161ac70bee1afed60711f7f645adb4d1671a01863f9849b369811d5"},{"path":"product/policy/auths-bounded-policy/src/lib.rs","sha256":"76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c"},{"path":"product/policy/auths-bounded-policy/src/receipt.rs","sha256":"3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad"},{"path":"product/policy/auths-bounded-policy/src/registry.rs","sha256":"4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0"},{"path":"product/profiles/auths-profile-api/Cargo.toml","sha256":"7ae85761f58625b5d678f961fd052eebf3e000ef565c7312e3ac857763c0017f"},{"path":"product/profiles/auths-profile-api/src/lib.rs","sha256":"a194b82b20bf8aa864c2334ef6c6aec30b2154ded972862252d5dcefa488ab95"},{"path":"product/profiles/auths-profile-mcp/Cargo.toml","sha256":"db264fc25242f7b7e4133cbe5782545b3107b406c87168ae072683cfb59eac66"},{"path":"product/profiles/auths-profile-mcp/src/arguments.rs","sha256":"a5de696586d507e2aee4a49fee99ef1ef4c51a2e46603f8838f1af6d9009833f"},{"path":"product/profiles/auths-profile-mcp/src/lib.rs","sha256":"d0f8b733a09ef8408336cdebc8948d6a5861012ce6878598b11be7084dfd4280"},{"path":"product/profiles/auths-profile-mcp/src/session.rs","sha256":"166c281fa66333388e4760d6098dad02d3359e1d5de4b8f93312c014f97abb03"},{"path":"product/qualification/auths-recipe-qualification/Cargo.toml","sha256":"b7b15b30b9a3d96d4f089d514266d3a892de6608d30707aa44be31cca89ca9fe"},{"path":"product/qualification/auths-recipe-qualification/src/canonical.rs","sha256":"30a9b50777f0dcb4b606abfee2467d5a975d9f6ad941ab6c13ca3df5b359f667"},{"path":"product/qualification/auths-recipe-qualification/src/closure.rs","sha256":"0ad6aee9bd981e2863fa725f209ec84031db2ff12f4c7ac3aaf5120f0bb86039"},{"path":"product/qualification/auths-recipe-qualification/src/error.rs","sha256":"52d5cf720a1e4579008fdda90a3ac2c31f0b8db57985f121f65e54b4da2b7dd1"},{"path":"product/qualification/auths-recipe-qualification/src/evidence.rs","sha256":"1a4cb862f725b02f9efd827db99637ea8178a5236aa020ec271a363edbe7b362"},{"path":"product/qualification/auths-recipe-qualification/src/ids.rs","sha256":"e81a906d571497ab2da753e1532d4443706410e0b75fdd59a7d2d788c7aec403"},{"path":"product/qualification/auths-recipe-qualification/src/lib.rs","sha256":"195b19f46e1e94a0f3594ad5958e5715bc5e3ad415bdfe6428dfc1b6dd3f4631"},{"path":"product/qualification/auths-recipe-qualification/src/model.rs","sha256":"3484eb0ec287b23d4682ade7b1b0f8d1335985b3fb180f06fc28716076957d5f"},{"path":"product/qualification/auths-recipe-qualification/src/release.rs","sha256":"d816b53e2275e902c750ad03803061844e259e28560ab2d1c77e8a43981a4d6a"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/mod.rs","sha256":"7f15b68e05a04f202bcb1fb80de1d9a9a4fda8bfd6af2cd4e5c660fc75d96fe5"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/schemas.rs","sha256":"c59feec2805621f341a90f81fc005e2c12f7a70f9d264fdeacccb2be4fe1c046"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/verification.rs","sha256":"6a6b5834c5dae10af1ba8939b2deae43b85db71544dc8f077ff63b7fe68ac8a8"},{"path":"product/qualification/auths-recipe-qualification/src/verify.rs","sha256":"edd33589c54fb79bcfccc4cf4e6ccf95bbca088318bb7f8dfc27da684b4fa671"},{"path":"product/receipts/auths-receipts/Cargo.toml","sha256":"6001fa1375899953aafcb07c23a6da0c8f57ea7ec08bb9c950b12a60a8cc6f0f"},{"path":"product/receipts/auths-receipts/src/disclosure.rs","sha256":"ba9ed439be0a320c8a01f5b6e9b51361c1a37e076947490d8e4a484ba6bb119c"},{"path":"product/receipts/auths-receipts/src/lib.rs","sha256":"547a57c4160256719cafb7d0ab972d9fc80b0da14fbbce4148c70c414070ff36"},{"path":"product/runtime/auths-connections/Cargo.toml","sha256":"babeb6e1dda3dfb66291713ce1e43dce5c349833d0b50ea4dccbf986030026b2"},{"path":"product/runtime/auths-connections/src/credential.rs","sha256":"82921413bb053f0f6c7931fbd4e6a86c8cc1d8c6b51debd9c2cef33a8d5b1c51"},{"path":"product/runtime/auths-connections/src/kernel.rs","sha256":"a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8"},{"path":"product/runtime/auths-connections/src/lib.rs","sha256":"79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22"},{"path":"product/runtime/auths-connections/src/model.rs","sha256":"de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77"},{"path":"product/runtime/auths-connections/src/registry.rs","sha256":"e57640e003e72ad3235c567c2bb944a262bd64e673f023b62ea091094cc7e946"},{"path":"product/runtime/auths-gateway-kernel/Cargo.toml","sha256":"34f864e67656af4ac7e5c7a347a23f01fc8ab31365b8e23c0ef474483b14a183"},{"path":"product/runtime/auths-gateway-kernel/src/construct.rs","sha256":"e9d65744bae273d65face4285e5d2da75c06a92ab48f7b8333d496604e31c63c"},{"path":"product/runtime/auths-gateway-kernel/src/lib.rs","sha256":"cfda6f8453426564c085475f183b6f790b438768a19668f1b65d33ba59dc8632"},{"path":"product/runtime/auths-gateway-kernel/src/order.rs","sha256":"e0045f877c4b7fe3860c291039853885064ddcdebba7c9b345ab65e81e646dda"},{"path":"product/runtime/auths-gateway-kernel/src/outcome.rs","sha256":"e9785b1afe70788c89b51b18655bcd5acff7b0c8e3d12fb79c6f05a202e67e6b"},{"path":"product/runtime/auths-gateway-kernel/src/ratio.rs","sha256":"7ace22264812e6fc1ef3a62afee402cf43494bb71ae0d3de219ad1b39d690bcb"},{"path":"product/runtime/auths-gateway-kernel/src/recovery.rs","sha256":"9f46dcd1685ab6e4d1ba04a3fc286a9f3afee8fb47829be1fbc670a7926a2dc6"},{"path":"product/runtime/auths-gateway-kernel/src/transition.rs","sha256":"cefb8f01d915880f6921f2501ff881ad94b9de61072c34d9cd19220992f97374"},{"path":"product/runtime/auths-gateway/Cargo.toml","sha256":"00b28be86921dcdc0ad90cce0c62c2961cafefe96ea6c2edf0e926c3d405ccad"},{"path":"product/runtime/auths-gateway/src/admin.rs","sha256":"2d5cc67afac42fbd15f36e2d1693cd1b20cedacf775040dce6ffe04ccc94c9ea"},{"path":"product/runtime/auths-gateway/src/app.rs","sha256":"6f80f63833ea0815bb44fbf3b0cc54624a08e9fb578b035819f2980dc04e8256"},{"path":"product/runtime/auths-gateway/src/audit.rs","sha256":"0edb2037eb7b5d6f13acfce85c54f62a82bf7fdd31bc7e626c4fec183cef61dd"},{"path":"product/runtime/auths-gateway/src/audit_tests.rs","sha256":"990969384a52d75bc2489d9d412a9e7dd814bca1c8f65c701d6205fae62a15d5"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway-harness.rs","sha256":"12b0c24d36b2e6a3be392d3c081a783b355fdd67dc5b54bacc0410e803116b8c"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway.rs","sha256":"b1dab74ec9a0c301fc9896de15d4676274461928f8b09f5346c561d731d123b0"},{"path":"product/runtime/auths-gateway/src/binding.rs","sha256":"663b0ce878319511aa7d05722ab4ab2fa9be18817884ffb2ee9f131ff1e382d1"},{"path":"product/runtime/auths-gateway/src/bounds.rs","sha256":"9cfa0eae4973e5e047a198360b22f041708fa20276b0b90c2ec440f06915d64b"},{"path":"product/runtime/auths-gateway/src/bounds_aggregate_tests.rs","sha256":"ab34f227b7c8692ba1da88ccb32bb3687a66adf8353d8282fae905d4a88eb612"},{"path":"product/runtime/auths-gateway/src/bounds_tests.rs","sha256":"74136bc570da7b9338b5a1a1ed9d3fd892c55135160964f9d3ac0e2cf5741375"},{"path":"product/runtime/auths-gateway/src/connection.rs","sha256":"7b5d049c258a26ed1c93ecf860f51d051a8a65f9b93554af0b1ea93862398ec9"},{"path":"product/runtime/auths-gateway/src/credential_journal.rs","sha256":"8e2b0733038d93ca5df770d27a870237e3b65664fa48da017d964a65bbbe25b8"},{"path":"product/runtime/auths-gateway/src/echo_verify.rs","sha256":"6d453051665f823abd7354d5c50031d9524cf47d6092d2f09080ae814e3b9575"},{"path":"product/runtime/auths-gateway/src/engine.rs","sha256":"5c04a836112d02677de66a1b79d7487fc95fcaac4a9dfc9e1044a6c19ea1282d"},{"path":"product/runtime/auths-gateway/src/fuzzing.rs","sha256":"ed3b0028487eb546a3b0a91d115aa8f18bcea324b61620bfe8e35a9e6ab18758"},{"path":"product/runtime/auths-gateway/src/generation_floor.rs","sha256":"999ec17cd6f0c11ab144d971e75dcf824b8b71fbffa355cde0dff9555dd7db78"},{"path":"product/runtime/auths-gateway/src/harness.rs","sha256":"c87e479f3eb281960f6c9c80d43c7560d7ccb654b0154ec823d3fcec4884ac05"},{"path":"product/runtime/auths-gateway/src/lib.rs","sha256":"b182052835a2cd631d1f801a74788d6ac1ef9cae21ade9ab4ffc270cd6f667ed"},{"path":"product/runtime/auths-gateway/src/listener.rs","sha256":"aa08239bcbc1fcb55e8a212fbdf6a84f12985b0d436dcb51dc58b06e59e435f2"},{"path":"product/runtime/auths-gateway/src/observed_tests.rs","sha256":"a22be071695f89ca2578a4d82fd80d9cb82289213c9bdb8f0470f6b2dc3d9201"},{"path":"product/runtime/auths-gateway/src/observer.rs","sha256":"562ffcaea071c3856e0708dc2fe33516917e145d2438aabb75af0a2b6ba01046"},{"path":"product/runtime/auths-gateway/src/onboarding.rs","sha256":"0dfd7d67e7f02f18a28d1c86ca1b7751d7463f5efcdbe3825de0ad8cbccb3891"},{"path":"product/runtime/auths-gateway/src/operator.rs","sha256":"c3c36954a3e86723df035b47f43b85fc8ab3a6292983522b6258d5c6b4e6c4e4"},{"path":"product/runtime/auths-gateway/src/pending_vectors/attempts.rs","sha256":"47ef3c8cb1c5504d47ae9a0088705ce6715fe86bac1671a34a56fb38a64d0dd3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/bounds.rs","sha256":"e612217307e1da5b0eb5ee6582a7458bb064b8aa8a529fc6555b1b334127ab68"},{"path":"product/runtime/auths-gateway/src/pending_vectors/codes.rs","sha256":"e00670a5ef24eb856cc2c6dcda8e5a263842f55c76bb939c0c27bd9df37e5522"},{"path":"product/runtime/auths-gateway/src/pending_vectors/keys.rs","sha256":"f84c56f2ea9cb34b2b79c72d13fbf2c6585010ec1ed450af58a78c80c1ea1edd"},{"path":"product/runtime/auths-gateway/src/pending_vectors/mod.rs","sha256":"5de8340f0ef71a0b57a09e323fefe473d3160c6ae952b9ba46f714825fbacafc"},{"path":"product/runtime/auths-gateway/src/pending_vectors/outcomes.rs","sha256":"8ec07b9511b48913af36ac999d2aa0e82924289f6acb23ddaeb9f00f99815166"},{"path":"product/runtime/auths-gateway/src/pending_vectors/production.rs","sha256":"f574cabfa4687a4fc846b8f6a234b68ec53b876aed548b11445729cac1a55ede"},{"path":"product/runtime/auths-gateway/src/pending_vectors/recipes.rs","sha256":"51693208270231c25c3aef2a32151d5962114c71e86b88cb9df83181c7af83d9"},{"path":"product/runtime/auths-gateway/src/pre_entry.rs","sha256":"06ea78ca140468bfaba17d9ab04912ad68673954c3203c98fed28272ff2a00c0"},{"path":"product/runtime/auths-gateway/src/property_tests.rs","sha256":"939c081e2e154aaf10186754044bdd65608932c899b970a04a71d0afaa999a93"},{"path":"product/runtime/auths-gateway/src/qualification.rs","sha256":"fd79f80c6cce2342a0ccfc8d271cb69d310179b7e93a2472c83e0e4a38d21735"},{"path":"product/runtime/auths-gateway/src/qualification_tests.rs","sha256":"4473add5729b97faf04d7be7fd8cf3bbacd7f545e1b61c7d2782563011906b4d"},{"path":"product/runtime/auths-gateway/src/quorum_tests.rs","sha256":"a78380b019104d688c11a4410082c7e08ded3106aab099954c4f8a1b4ae0fd89"},{"path":"product/runtime/auths-gateway/src/readiness.rs","sha256":"911c3f11892f94641574375e2da4c671c802738f71082f12c39832331052d43d"},{"path":"product/runtime/auths-gateway/src/recipe.rs","sha256":"fecf9af67e7afc48d080e9f8f55f8ce28e49d0e08988717a27908bbda461d6b6"},{"path":"product/runtime/auths-gateway/src/recipe/lower.rs","sha256":"8088b8751ed831dbb48247af953c6290ac95e2a438ccd5bd65eff54be06a1fd1"},{"path":"product/runtime/auths-gateway/src/recipe/review.rs","sha256":"c3eb7d9fdd98dacf52750b14b67ad7b7faaecbbdeafff1e0b049f67d0a2d0139"},{"path":"product/runtime/auths-gateway/src/recipe/runtime.rs","sha256":"c286f0d15f974402822c0810d8e97f98411dc1c557755cc23e540d85e2bb42d9"},{"path":"product/runtime/auths-gateway/src/recipe/source.rs","sha256":"1af50298fb1461e1b24cbdf560d43124d6b1c4c529586c911b1c4797214a69ff"},{"path":"product/runtime/auths-gateway/src/recipe/tests.rs","sha256":"aac551a2481bbc60864c64079bc667dcb232e45a0f41a04073ed84ab5dbe1fce"},{"path":"product/runtime/auths-gateway/src/recipe/validate.rs","sha256":"3711b17605cb7b0d639bc1b180449231f5882a306cab20e2c7782155cc63b0d4"},{"path":"product/runtime/auths-gateway/src/scenario_tests.rs","sha256":"d8271761b12597bfe1233f8eb5ad1d4e5498c5d03388e832e24ab818484a1de4"},{"path":"product/runtime/auths-gateway/src/separation.rs","sha256":"be9306848ca5d801767cf6aa14247c8618312ef0e202f00ce0c24c4844491061"},{"path":"product/runtime/auths-gateway/src/store.rs","sha256":"1e5288345c2cb1421aeda277b3158d07607404b0ec46943222ac107b63dcbb46"},{"path":"product/runtime/auths-gateway/src/store_testkit.rs","sha256":"88d82fee42f1b8ef521e8deef0216e938ebeaad822eb2f5020e70b89d145ea70"},{"path":"product/runtime/auths-gateway/src/submit.rs","sha256":"c78dbbba7c45b443febf655056c5edcd635e77be7b21c5b2c318097502415ffe"},{"path":"product/runtime/auths-gateway/src/support.rs","sha256":"9fd979029793a22b15d9776a7fc172476fd7c126a80d4080c65d720845becbcb"},{"path":"product/runtime/auths-gateway/src/transport.rs","sha256":"be2c6dc75b8daec110bf8749fedc3823f6067d40b999aa3eb21126896a97d3ad"},{"path":"product/runtime/auths-kernel-runtime/Cargo.toml","sha256":"926bcd0053e5edd703be8f0027ad009e2982db013c8174c1366edbf38b48087d"},{"path":"product/runtime/auths-kernel-runtime/src/lib.rs","sha256":"7108faae9ca4bc32dc093ddaf885ac8f74f3c9b8d317b7c7d0ed00d1d0ab5972"},{"path":"product/runtime/auths-lifecycle/Cargo.toml","sha256":"c5053c705f8d5554b44e432fe75287a2faf11d644e5a2552e45ad6cd94176af5"},{"path":"product/runtime/auths-lifecycle/src/codec.rs","sha256":"51c4b746749150e8bfcd8ff972b3f6c1ef40bec15583448ec1b471d9ad737dc0"},{"path":"product/runtime/auths-lifecycle/src/digest.rs","sha256":"55282cd7d8aba37713c2dcb5357c9877819edb72a30eadefb860d28d7d3a3eb7"},{"path":"product/runtime/auths-lifecycle/src/identifier.rs","sha256":"31620e8c16de68d3d2d3b84d6353c1a5b9d4151d8247f91fa389b906a8e660f1"},{"path":"product/runtime/auths-lifecycle/src/kernel.rs","sha256":"2abb8c094b36d35b364e74d78091d14c5d6f3d1eb6552cca3b5538dbd017ce23"},{"path":"product/runtime/auths-lifecycle/src/lib.rs","sha256":"afe5a345cd309b5a4f08ffba3170a6d7f16ff914892b3f2006d5208ed24ec736"},{"path":"product/runtime/auths-lifecycle/src/model.rs","sha256":"1af12bbeeeaa65ec02ddcebd7d2c8c92ec1e339fa40ae85b45ab9b01a722a4fa"},{"path":"product/runtime/auths-lifecycle/src/operation.rs","sha256":"78e6d05fcf5d7ea4f148032a3fa26fdfcab77eb346019effe927b08e0d64d732"},{"path":"product/runtime/auths-lifecycle/src/registry.rs","sha256":"53495fe6f7a77422593a41623e28716f1c140dcc1e00f87f6b0ffbfb93a5ef90"},{"path":"product/runtime/auths-lifecycle/src/sealed.rs","sha256":"2e0c03b5813c926c159598bb7890d1523825edbe57cd687d42a5dfb3374a0c19"},{"path":"product/runtime/auths-lifecycle/src/test_support.rs","sha256":"221d9a5c5ef8e1f9f8fd66927484eaf813571d0568470278ecd8fa08a5eec8cd"},{"path":"product/runtime/auths-lifecycle/src/transition.rs","sha256":"011805a28efdd541f44ccea54dd0e34a1e58f4004447ee58013703b4fb6b2822"},{"path":"product/runtime/auths-runtime/Cargo.toml","sha256":"dd29d80a8b4bb56c869f036a6c9998f6e6d1c0383ac5dc03fa42b24abe2a7ff7"},{"path":"product/runtime/auths-runtime/src/lib.rs","sha256":"132ca03d58c14905d3a822a4972f42a22a5ad33a45f2ba9ca44f3a57d810b4b0"},{"path":"product/runtime/auths-runtime/src/production.rs","sha256":"fd4eff4270c571c10fcff6cf27df28961ebf074de8a1a028f500fda1ca376820"},{"path":"product/sdk/auths-approval-quorum/Cargo.toml","sha256":"df904971fca87a24194c5816738a331588fe8f164acb5d70839a35dca5f57114"},{"path":"product/sdk/auths-approval-quorum/src/lib.rs","sha256":"72e4086088a1c0912e4e1a9e980f26a5c280bf5ab16ea39c9f0f58d5096ac2ce"},{"path":"product/sdk/auths-approval-quorum/src/remote.rs","sha256":"9fa029c7c63003adf260f8aec55160c545681c60c1bace0d934e7525862aac7b"},{"path":"product/sdk/auths-approval-quorum/src/remote_tests.rs","sha256":"8a09ce17cfee82a035a74edd535f3ebeb3db0e078784740d3997b17dbdb10197"},{"path":"product/sdk/auths-approval-quorum/src/tests.rs","sha256":"0acbf12be3e497dcc6c2d8f29c9af3b1a7ed8e11b75f6399570d4f217a785060"},{"path":"product/stores/auths-stores/Cargo.toml","sha256":"a32c4b76d17b264be5d40d24497ff237e1ed87822e8bab86229b3db93106dbe3"},{"path":"product/stores/auths-stores/src/gateway_attempt.rs","sha256":"185da8f4a220fba836d5b78a9311f03204681c43a3c53951008084d135bf4d21"},{"path":"product/stores/auths-stores/src/lib.rs","sha256":"e721262edf8a9ab5568ddc27639176312d4a366203b5f73e2d7c11fde2c554e9"},{"path":"product/stores/auths-stores/src/lifecycle.rs","sha256":"94f64d25bc178a9e60ba3c0ee6915d7fb3af7c4468792d76b4e70f43f4de1e2f"}],"schema":"auths.gateway-semantic-closure/1"} \ No newline at end of file +{"files":[{"path":"Cargo.lock","sha256":"c94ed342774d5e2823f01ecf74b8a4812c5f9a6b0cf811d31f2e2cecb671a275"},{"path":"Cargo.toml","sha256":"6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24"},{"path":"core/adapters/auths-did-keri/Cargo.toml","sha256":"86ba3e3f9a0a70d970568bfb3113b7ba7bbdd81c3eebbb52743dd574a0c0ecaa"},{"path":"core/adapters/auths-did-keri/src/lib.rs","sha256":"a75674842f8a7142004369ccd206ab43e476459293f0ff4bed4d4e659031b3e3"},{"path":"core/adapters/auths-did-key/Cargo.toml","sha256":"d5a3ae07ecde83f91eed4c3785051dd0f44eab6c891754f3309b6b40596707d7"},{"path":"core/adapters/auths-did-key/src/lib.rs","sha256":"b76a3f4528a725df53cfa9242e6e414e1d26caa48468aaed497e28b121f4497c"},{"path":"core/adapters/auths-raw-key/Cargo.toml","sha256":"f49616bc18c19e6aaa7e6a02ccebcdb9f5c1422c1278ef9869e0dbf22ceda7be"},{"path":"core/adapters/auths-raw-key/src/lib.rs","sha256":"45eec1b295dac3bed65cd79c942870b926b06b3f5d38eaebaeb6140ac69315fa"},{"path":"core/crates/auths-algebra-kernel/Cargo.toml","sha256":"0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba"},{"path":"core/crates/auths-algebra-kernel/src/generated.rs","sha256":"ae4bcbef42a408c7ffa0c6a74a42f7de177a6f14479e51d205acf830bda05960"},{"path":"core/crates/auths-algebra-kernel/src/lib.rs","sha256":"6654667eeb9b353d6648954c9fd2e8838462a82ce6b2803eb49e1366892c68c6"},{"path":"core/crates/auths-assurance/Cargo.toml","sha256":"afcb12a97ddd09d7a264b9ecd3fcaefc865ff2c9b4539ee85b00883420ba333a"},{"path":"core/crates/auths-assurance/src/lib.rs","sha256":"0fb2ec844d674b25a9e20b1601452c89c2454901fa506adfa9bb38ef9a7fa213"},{"path":"core/crates/auths-author/Cargo.toml","sha256":"1e6f0e3bc079ddb558decf0db26b291c6e72fc47327b6df1b7650d41689b215f"},{"path":"core/crates/auths-author/src/lib.rs","sha256":"e14475f2f49715a1869d5fa6b11ff1fbb72497e39097e09f833b0bae7e5b3f2b"},{"path":"core/crates/auths-author/src/observations.rs","sha256":"dda7d6bfa6f4bd7e95a480ca283c2c0e996f69c5c15cb0c7197af328131a7066"},{"path":"core/crates/auths-authority/Cargo.toml","sha256":"4f68212938029f79ebd857b4f3038494eb85d0163d49f07e51376715cf959815"},{"path":"core/crates/auths-authority/src/lib.rs","sha256":"da88d5194de4e17449e69972c0fb042afa3c39798a8f570f30771e77c384f1eb"},{"path":"core/crates/auths-codec/Cargo.toml","sha256":"e20e51826e17814effd9d8925d18d5fbdd6c0d37bf50231e743ec2611314722c"},{"path":"core/crates/auths-codec/src/approval.rs","sha256":"fbff43bf4d57f69f8b7738a8647751cde75c5a932dee65d924a1fe9c7202f91f"},{"path":"core/crates/auths-codec/src/bounded_policy.rs","sha256":"d21f6728be2d8a04b6d94921f2b683f7e61cbb42e0ac6866f1c88a49caa534c3"},{"path":"core/crates/auths-codec/src/decode.rs","sha256":"ba2999584cdf53b1b517ecb9c7ea50d39efee17c666a9a38e2ad1ac94379f778"},{"path":"core/crates/auths-codec/src/encode.rs","sha256":"8491192053e2e15d62b4d2a491de22405b7487ead69ab6f6bca40669ce7ca5f7"},{"path":"core/crates/auths-codec/src/error.rs","sha256":"fecb0737c16deb42d859f1dc7727c698438d9ac12064fd99e0024629642c390c"},{"path":"core/crates/auths-codec/src/hash.rs","sha256":"f88e111f1dbb2cef6b7b5e9c948cb45ff92e366710c8a5f5c636138aa748479e"},{"path":"core/crates/auths-codec/src/lib.rs","sha256":"3b0e5c94c6f34f750b88a9333e1d5c8145746d845d3a23e0d2f61807cf592ea7"},{"path":"core/crates/auths-codec/src/observation.rs","sha256":"38328b0c71ff97a4196eeade8b4faa889527ff1f80bb168468bcd49082a3987e"},{"path":"core/crates/auths-composition/Cargo.toml","sha256":"331e13025eb82588b5269ed3975929eb41c823d588c49e4c296273d85c6fe80e"},{"path":"core/crates/auths-composition/src/lib.rs","sha256":"e42e3b0b6a9985b73c533aeb23799c638979aa27a9ce7d0f10a8d60340570fb1"},{"path":"core/crates/auths-model/Cargo.toml","sha256":"565c15302b0cc9270db1e28efa3862804846850ba933cc17aea8abcec4a65987"},{"path":"core/crates/auths-model/src/approval.rs","sha256":"54cf44a9ef747ec21546a4086aecfb130bc7803b0d646430e6082df51e6e305f"},{"path":"core/crates/auths-model/src/bounded.rs","sha256":"f90496abc0a06c028b4d850af6ddab7d850bfafeaa3d042f1b1246a41d8bbbc9"},{"path":"core/crates/auths-model/src/bounded_policy.rs","sha256":"306a8f049cc7cfc7635fe0e4de47eb7813eed63d3c14c3be2b51586aa4eea450"},{"path":"core/crates/auths-model/src/lib.rs","sha256":"e7cfe6bb9574c6b016aa63e70658c31e0b90903ec6479a49f4a2ceb64f5bad97"},{"path":"core/crates/auths-model/src/observation.rs","sha256":"b3ed3e3cc090afca2896a7d3de7988afccc1ee1ea0ebd91b51a8bc0f20ad8dbb"},{"path":"core/crates/auths-multikey/Cargo.toml","sha256":"858756c1197befcada06134742bffe8d58cf674cadd6c046bf710570e96efaf2"},{"path":"core/crates/auths-multikey/src/lib.rs","sha256":"f5177fffb11e40eeaaa665ba886c541fc1f24d5eacdd6983fb03dc20148733f0"},{"path":"core/crates/auths-ports/Cargo.toml","sha256":"596a9b0f5af3717c16a6d13f7054d8a106bcd9f01f5f72c2235dd2afcf0ab16c"},{"path":"core/crates/auths-ports/src/binding.rs","sha256":"a16c012d40aa4249e3ec54372b9611006d0bfe8c7dc3c741911c2194ad17736d"},{"path":"core/crates/auths-ports/src/diagnostics.rs","sha256":"aa596572503b5a65a918bb2ff38281c144ff53821ee914e9325c852828d852df"},{"path":"core/crates/auths-ports/src/lib.rs","sha256":"8da1debf86f9532df0660155d04298beb1ba3a1204508f8586e2e67cd2fb3449"},{"path":"core/crates/auths-ports/src/path.rs","sha256":"b68fc547b4e4d97a60cbbc1cc1939fc6b34a8233b81f840bd396914a707e3ea1"},{"path":"core/crates/auths-raw-key-core/Cargo.toml","sha256":"98c0bc8527a537512e43a74dd6ba9658c6f0cdc16610cf938e3f9b43785d836d"},{"path":"core/crates/auths-raw-key-core/src/lib.rs","sha256":"98c0500c41697aae28708ad0bf970b9a97583d96a3d2c18d23e7fa351e0f7d12"},{"path":"core/crates/auths-registries/Cargo.toml","sha256":"590e49e58b0622d9d6274fea46796dcdb07dec9550eff295cce6a6427ffa51e2"},{"path":"core/crates/auths-registries/src/lib.rs","sha256":"450d3886d85ee333b7e046317fb5b47cde62483d5f3e41d46265e2caf4c373ec"},{"path":"core/crates/auths-registries/src/template.rs","sha256":"1224039dd2b3ce6fa8357613d8cafbae40400493da7176da202b9ade62fa05e4"},{"path":"core/crates/auths-signature-core/Cargo.toml","sha256":"6bee2230eb30af1be0bd5c2d57bd3e1903497a70028d47290d4ac6e9e0e8bca0"},{"path":"core/crates/auths-signature-core/src/lib.rs","sha256":"6e3f9311ded5e49ea50d445eb21e6d8fa12442aa4362a73e0cb6fda15b7cd865"},{"path":"core/crates/auths-signature/Cargo.toml","sha256":"7f7b5682466ba439d8c59579022cb61068cad9fb4bd2d73e1cc21327c902b450"},{"path":"core/crates/auths-signature/src/lib.rs","sha256":"b3d9ac4cc3ba0797b9e1c09f2d6ac05089b25dac4e285a5af28c0165b33d925b"},{"path":"core/crates/auths-verifier/Cargo.toml","sha256":"c43358e06a33324b41a8b93e5cc7279c55f7d21f1f6cfaa539a3fc7b4c27a38f"},{"path":"core/crates/auths-verifier/src/approval.rs","sha256":"c3cae6a49e169051eb555bb092b1069a4d422516d6a2114623a89e5f31ff923f"},{"path":"core/crates/auths-verifier/src/causal.rs","sha256":"9635230f33b13a263573d319ac8a1976addbcc07677514a43e3c7bf28dc04587"},{"path":"core/crates/auths-verifier/src/lib.rs","sha256":"f22dec38dfa47ced8da4f605390da8453273bee1da010f57fd1fdfcb10e0b389"},{"path":"core/crates/auths-verifier/src/observation.rs","sha256":"0bb07f06a0f9524c88427df1c972b1de8ba038a9eeeb15d3134c25125ae84b1e"},{"path":"core/crates/auths-verifier/src/trace.rs","sha256":"2213d72023a1d9e0413a2cf2c51c3dad9e04775d86033a0caaa9d29a8f0036f8"},{"path":"exchange/crates/auths-proof-exchange-model/Cargo.toml","sha256":"34b2db64f93a288e942b5a3918d28cdcbef906e0dc9074ce848018d3d5f7a1fa"},{"path":"exchange/crates/auths-proof-exchange-model/src/lib.rs","sha256":"49fac5aff2339d3a57c41cb8bb2a82852538e8f77ecc4b157c88e264ff31fb55"},{"path":"exchange/crates/auths-proof-exchange-port/Cargo.toml","sha256":"7ff660f1b7579dc570c791090aeb450404fbbf44c92781e289f5ccdde746d739"},{"path":"exchange/crates/auths-proof-exchange-port/src/lib.rs","sha256":"b408fb40c6432edc1facb3d8b3e9433a033f8dc73fe2e0ba5a88c972ca675021"},{"path":"product/config/auths-config/Cargo.toml","sha256":"e4b568ab9f6d84f7d7e6d66443fe825f360db9c27bc7c31d6ddc0647ba3ab304"},{"path":"product/config/auths-config/src/lib.rs","sha256":"fecf00ea65cef9018fda9af2063326d7065b869266d0d9e73a4f06816f1102cc"},{"path":"product/errors/auths-errors/Cargo.toml","sha256":"3b3a199b6460ba75bda84475bb5accd35e1485448a3981038db85bf4772dd350"},{"path":"product/errors/auths-errors/src/lib.rs","sha256":"7feeb9069fa4003f94f1f07c1c94619cf1c883e0dbaaf2187f04d0f742264bdd"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/Cargo.toml","sha256":"716f1f2a117d6d69d8effe9ee9057e24ba3502f20af6a602b06facb638cdabed"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/api.rs","sha256":"9ea61dd7ddd93282b073b98e453e6b75b26dc49689c04e9782435d06a3a09e48"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/clock.rs","sha256":"73f0a6e0f5903883329fa6683f5888288f759512ac69e5c87efd2b6b87f7d79f"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/http.rs","sha256":"14c1fce14e24c984b2a275563a29b6326fb08367922b6e8d37ba38b9cb81aa2b"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/identity.rs","sha256":"186de11230c8b33375951c4368609f8976bf9795f171af3fd7fac26207a94361"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs","sha256":"0b4617d044f5254a5ab22f5a2578f91cc025206a8c1845be39c1c56dcdf7a5df"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/names.rs","sha256":"41bb23572d6002e23ee103d6fe70ecd68764861c6f2e48a1c53af998270a4afa"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs","sha256":"39fed883f4802e68d3b41a68fea0aba0737810996b33d13577de70faba004c29"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/store.rs","sha256":"fc60ee9c49b2f4f063c449b4c78100c5c4872779e94ca168f796603b380ef6e4"},{"path":"product/integrations/auths-custody/Cargo.toml","sha256":"1e14034185ad1ec24a977fd5f41d0abee219606245c046ce2a82287fadef448b"},{"path":"product/integrations/auths-custody/src/conformance.rs","sha256":"8ed1afd58f18fc6becc268908aa6419c9aa404c79da0197963eb2599df44acf6"},{"path":"product/integrations/auths-custody/src/key.rs","sha256":"70cbb0fd21b6f5652157845a22c35be2d0f6c05b3d138fc4b9bb6dbdc3d81c40"},{"path":"product/integrations/auths-custody/src/lib.rs","sha256":"8ee593c1f59b0fd2126bdda9138026f5bc531beb64d4489a99785842e7b98b43"},{"path":"product/operations/auths-operations/Cargo.toml","sha256":"73dde1e914ba5e1386f8d49c0d730423cc72ae77ec44c6554a6a75cc8e8922b1"},{"path":"product/operations/auths-operations/src/explanation.rs","sha256":"b4a39bcbd5712cb9e735ee7deeb281f3fa6af5ddca973735bf3d87dce427ef11"},{"path":"product/operations/auths-operations/src/lib.rs","sha256":"3f401a56555113b98f57bca172a2660eaecedf76247b83a3fdbb089c133a29cd"},{"path":"product/operations/auths-operations/src/render/json.rs","sha256":"2ae042639960afee123730e945d373bc5dda1d2b3af20ae16c939a7e99b9e418"},{"path":"product/operations/auths-operations/src/render/mod.rs","sha256":"b3b7f6fe473f49227ace5a68bfc3d8dc14b5db8dd9888fd9e207070337b1b8bf"},{"path":"product/operations/auths-operations/src/render/text.rs","sha256":"f216cf3bdb00e264523271b16e7059535ac6b1aabf271cebd7935af155e4bfec"},{"path":"product/policy/auths-bounded-policy/Cargo.toml","sha256":"babd5d200923137ead71d8c2528f847cea323ce98da942a1320b054436612c47"},{"path":"product/policy/auths-bounded-policy/src/arithmetic.rs","sha256":"75e43c5d4eab8d1f71c1daf53839f5f9fe45a400afc1f63a30c6f55ce3632627"},{"path":"product/policy/auths-bounded-policy/src/commitment.rs","sha256":"c5706f2d583454e1a7f570f7ada138d4d864bef0205dfae7c1296774f396bb3f"},{"path":"product/policy/auths-bounded-policy/src/eligibility.rs","sha256":"c9acdfb793074e687fc36efad506be27dbd99ffbf40387bc66c8de39ef238432"},{"path":"product/policy/auths-bounded-policy/src/identifier.rs","sha256":"0006a32bae9eb16c4178cf797df418d2b0a781f2bc6474b741dc1a908141831c"},{"path":"product/policy/auths-bounded-policy/src/kernel.rs","sha256":"99187c28b161ac70bee1afed60711f7f645adb4d1671a01863f9849b369811d5"},{"path":"product/policy/auths-bounded-policy/src/lib.rs","sha256":"76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c"},{"path":"product/policy/auths-bounded-policy/src/receipt.rs","sha256":"3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad"},{"path":"product/policy/auths-bounded-policy/src/registry.rs","sha256":"4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0"},{"path":"product/profiles/auths-profile-api/Cargo.toml","sha256":"7ae85761f58625b5d678f961fd052eebf3e000ef565c7312e3ac857763c0017f"},{"path":"product/profiles/auths-profile-api/src/lib.rs","sha256":"a194b82b20bf8aa864c2334ef6c6aec30b2154ded972862252d5dcefa488ab95"},{"path":"product/profiles/auths-profile-mcp/Cargo.toml","sha256":"db264fc25242f7b7e4133cbe5782545b3107b406c87168ae072683cfb59eac66"},{"path":"product/profiles/auths-profile-mcp/src/arguments.rs","sha256":"a5de696586d507e2aee4a49fee99ef1ef4c51a2e46603f8838f1af6d9009833f"},{"path":"product/profiles/auths-profile-mcp/src/lib.rs","sha256":"d0f8b733a09ef8408336cdebc8948d6a5861012ce6878598b11be7084dfd4280"},{"path":"product/profiles/auths-profile-mcp/src/session.rs","sha256":"166c281fa66333388e4760d6098dad02d3359e1d5de4b8f93312c014f97abb03"},{"path":"product/qualification/auths-recipe-qualification/Cargo.toml","sha256":"b7b15b30b9a3d96d4f089d514266d3a892de6608d30707aa44be31cca89ca9fe"},{"path":"product/qualification/auths-recipe-qualification/src/canonical.rs","sha256":"30a9b50777f0dcb4b606abfee2467d5a975d9f6ad941ab6c13ca3df5b359f667"},{"path":"product/qualification/auths-recipe-qualification/src/closure.rs","sha256":"0ad6aee9bd981e2863fa725f209ec84031db2ff12f4c7ac3aaf5120f0bb86039"},{"path":"product/qualification/auths-recipe-qualification/src/error.rs","sha256":"52d5cf720a1e4579008fdda90a3ac2c31f0b8db57985f121f65e54b4da2b7dd1"},{"path":"product/qualification/auths-recipe-qualification/src/evidence.rs","sha256":"1a4cb862f725b02f9efd827db99637ea8178a5236aa020ec271a363edbe7b362"},{"path":"product/qualification/auths-recipe-qualification/src/ids.rs","sha256":"e81a906d571497ab2da753e1532d4443706410e0b75fdd59a7d2d788c7aec403"},{"path":"product/qualification/auths-recipe-qualification/src/lib.rs","sha256":"195b19f46e1e94a0f3594ad5958e5715bc5e3ad415bdfe6428dfc1b6dd3f4631"},{"path":"product/qualification/auths-recipe-qualification/src/model.rs","sha256":"3484eb0ec287b23d4682ade7b1b0f8d1335985b3fb180f06fc28716076957d5f"},{"path":"product/qualification/auths-recipe-qualification/src/release.rs","sha256":"d816b53e2275e902c750ad03803061844e259e28560ab2d1c77e8a43981a4d6a"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/mod.rs","sha256":"7f15b68e05a04f202bcb1fb80de1d9a9a4fda8bfd6af2cd4e5c660fc75d96fe5"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/schemas.rs","sha256":"c59feec2805621f341a90f81fc005e2c12f7a70f9d264fdeacccb2be4fe1c046"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/verification.rs","sha256":"6a6b5834c5dae10af1ba8939b2deae43b85db71544dc8f077ff63b7fe68ac8a8"},{"path":"product/qualification/auths-recipe-qualification/src/verify.rs","sha256":"edd33589c54fb79bcfccc4cf4e6ccf95bbca088318bb7f8dfc27da684b4fa671"},{"path":"product/receipts/auths-receipts/Cargo.toml","sha256":"6001fa1375899953aafcb07c23a6da0c8f57ea7ec08bb9c950b12a60a8cc6f0f"},{"path":"product/receipts/auths-receipts/src/disclosure.rs","sha256":"ba9ed439be0a320c8a01f5b6e9b51361c1a37e076947490d8e4a484ba6bb119c"},{"path":"product/receipts/auths-receipts/src/lib.rs","sha256":"547a57c4160256719cafb7d0ab972d9fc80b0da14fbbce4148c70c414070ff36"},{"path":"product/runtime/auths-connections/Cargo.toml","sha256":"babeb6e1dda3dfb66291713ce1e43dce5c349833d0b50ea4dccbf986030026b2"},{"path":"product/runtime/auths-connections/src/credential.rs","sha256":"82921413bb053f0f6c7931fbd4e6a86c8cc1d8c6b51debd9c2cef33a8d5b1c51"},{"path":"product/runtime/auths-connections/src/kernel.rs","sha256":"a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8"},{"path":"product/runtime/auths-connections/src/lib.rs","sha256":"79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22"},{"path":"product/runtime/auths-connections/src/model.rs","sha256":"de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77"},{"path":"product/runtime/auths-connections/src/registry.rs","sha256":"e57640e003e72ad3235c567c2bb944a262bd64e673f023b62ea091094cc7e946"},{"path":"product/runtime/auths-gateway-kernel/Cargo.toml","sha256":"34f864e67656af4ac7e5c7a347a23f01fc8ab31365b8e23c0ef474483b14a183"},{"path":"product/runtime/auths-gateway-kernel/src/construct.rs","sha256":"e9d65744bae273d65face4285e5d2da75c06a92ab48f7b8333d496604e31c63c"},{"path":"product/runtime/auths-gateway-kernel/src/lib.rs","sha256":"cfda6f8453426564c085475f183b6f790b438768a19668f1b65d33ba59dc8632"},{"path":"product/runtime/auths-gateway-kernel/src/order.rs","sha256":"e0045f877c4b7fe3860c291039853885064ddcdebba7c9b345ab65e81e646dda"},{"path":"product/runtime/auths-gateway-kernel/src/outcome.rs","sha256":"e9785b1afe70788c89b51b18655bcd5acff7b0c8e3d12fb79c6f05a202e67e6b"},{"path":"product/runtime/auths-gateway-kernel/src/ratio.rs","sha256":"7ace22264812e6fc1ef3a62afee402cf43494bb71ae0d3de219ad1b39d690bcb"},{"path":"product/runtime/auths-gateway-kernel/src/recovery.rs","sha256":"9f46dcd1685ab6e4d1ba04a3fc286a9f3afee8fb47829be1fbc670a7926a2dc6"},{"path":"product/runtime/auths-gateway-kernel/src/transition.rs","sha256":"cefb8f01d915880f6921f2501ff881ad94b9de61072c34d9cd19220992f97374"},{"path":"product/runtime/auths-gateway/Cargo.toml","sha256":"00b28be86921dcdc0ad90cce0c62c2961cafefe96ea6c2edf0e926c3d405ccad"},{"path":"product/runtime/auths-gateway/src/admin.rs","sha256":"2d5cc67afac42fbd15f36e2d1693cd1b20cedacf775040dce6ffe04ccc94c9ea"},{"path":"product/runtime/auths-gateway/src/app.rs","sha256":"6f80f63833ea0815bb44fbf3b0cc54624a08e9fb578b035819f2980dc04e8256"},{"path":"product/runtime/auths-gateway/src/audit.rs","sha256":"0edb2037eb7b5d6f13acfce85c54f62a82bf7fdd31bc7e626c4fec183cef61dd"},{"path":"product/runtime/auths-gateway/src/audit_tests.rs","sha256":"990969384a52d75bc2489d9d412a9e7dd814bca1c8f65c701d6205fae62a15d5"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway-harness.rs","sha256":"12b0c24d36b2e6a3be392d3c081a783b355fdd67dc5b54bacc0410e803116b8c"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway.rs","sha256":"8851f5e95b70540f64c1965f6f240e7d90968817c6396d59cda49a75e46f85fc"},{"path":"product/runtime/auths-gateway/src/binding.rs","sha256":"663b0ce878319511aa7d05722ab4ab2fa9be18817884ffb2ee9f131ff1e382d1"},{"path":"product/runtime/auths-gateway/src/bounds.rs","sha256":"9cfa0eae4973e5e047a198360b22f041708fa20276b0b90c2ec440f06915d64b"},{"path":"product/runtime/auths-gateway/src/bounds_aggregate_tests.rs","sha256":"ab34f227b7c8692ba1da88ccb32bb3687a66adf8353d8282fae905d4a88eb612"},{"path":"product/runtime/auths-gateway/src/bounds_tests.rs","sha256":"74136bc570da7b9338b5a1a1ed9d3fd892c55135160964f9d3ac0e2cf5741375"},{"path":"product/runtime/auths-gateway/src/connection.rs","sha256":"7b5d049c258a26ed1c93ecf860f51d051a8a65f9b93554af0b1ea93862398ec9"},{"path":"product/runtime/auths-gateway/src/credential_journal.rs","sha256":"8e2b0733038d93ca5df770d27a870237e3b65664fa48da017d964a65bbbe25b8"},{"path":"product/runtime/auths-gateway/src/echo_verify.rs","sha256":"6d453051665f823abd7354d5c50031d9524cf47d6092d2f09080ae814e3b9575"},{"path":"product/runtime/auths-gateway/src/engine.rs","sha256":"5c04a836112d02677de66a1b79d7487fc95fcaac4a9dfc9e1044a6c19ea1282d"},{"path":"product/runtime/auths-gateway/src/fuzzing.rs","sha256":"ed3b0028487eb546a3b0a91d115aa8f18bcea324b61620bfe8e35a9e6ab18758"},{"path":"product/runtime/auths-gateway/src/generation_floor.rs","sha256":"fe1510ec96ce0f67e9a78edbfa94b33eb7df64c0ac4d0a67901124dcd0164777"},{"path":"product/runtime/auths-gateway/src/harness.rs","sha256":"c87e479f3eb281960f6c9c80d43c7560d7ccb654b0154ec823d3fcec4884ac05"},{"path":"product/runtime/auths-gateway/src/lib.rs","sha256":"b182052835a2cd631d1f801a74788d6ac1ef9cae21ade9ab4ffc270cd6f667ed"},{"path":"product/runtime/auths-gateway/src/listener.rs","sha256":"aa08239bcbc1fcb55e8a212fbdf6a84f12985b0d436dcb51dc58b06e59e435f2"},{"path":"product/runtime/auths-gateway/src/observed_tests.rs","sha256":"a22be071695f89ca2578a4d82fd80d9cb82289213c9bdb8f0470f6b2dc3d9201"},{"path":"product/runtime/auths-gateway/src/observer.rs","sha256":"562ffcaea071c3856e0708dc2fe33516917e145d2438aabb75af0a2b6ba01046"},{"path":"product/runtime/auths-gateway/src/onboarding.rs","sha256":"0dfd7d67e7f02f18a28d1c86ca1b7751d7463f5efcdbe3825de0ad8cbccb3891"},{"path":"product/runtime/auths-gateway/src/operator.rs","sha256":"c3c36954a3e86723df035b47f43b85fc8ab3a6292983522b6258d5c6b4e6c4e4"},{"path":"product/runtime/auths-gateway/src/pending_vectors/attempts.rs","sha256":"47ef3c8cb1c5504d47ae9a0088705ce6715fe86bac1671a34a56fb38a64d0dd3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/bounds.rs","sha256":"e612217307e1da5b0eb5ee6582a7458bb064b8aa8a529fc6555b1b334127ab68"},{"path":"product/runtime/auths-gateway/src/pending_vectors/codes.rs","sha256":"e00670a5ef24eb856cc2c6dcda8e5a263842f55c76bb939c0c27bd9df37e5522"},{"path":"product/runtime/auths-gateway/src/pending_vectors/keys.rs","sha256":"f84c56f2ea9cb34b2b79c72d13fbf2c6585010ec1ed450af58a78c80c1ea1edd"},{"path":"product/runtime/auths-gateway/src/pending_vectors/mod.rs","sha256":"5de8340f0ef71a0b57a09e323fefe473d3160c6ae952b9ba46f714825fbacafc"},{"path":"product/runtime/auths-gateway/src/pending_vectors/outcomes.rs","sha256":"8ec07b9511b48913af36ac999d2aa0e82924289f6acb23ddaeb9f00f99815166"},{"path":"product/runtime/auths-gateway/src/pending_vectors/production.rs","sha256":"f574cabfa4687a4fc846b8f6a234b68ec53b876aed548b11445729cac1a55ede"},{"path":"product/runtime/auths-gateway/src/pending_vectors/recipes.rs","sha256":"51693208270231c25c3aef2a32151d5962114c71e86b88cb9df83181c7af83d9"},{"path":"product/runtime/auths-gateway/src/pre_entry.rs","sha256":"06ea78ca140468bfaba17d9ab04912ad68673954c3203c98fed28272ff2a00c0"},{"path":"product/runtime/auths-gateway/src/property_tests.rs","sha256":"939c081e2e154aaf10186754044bdd65608932c899b970a04a71d0afaa999a93"},{"path":"product/runtime/auths-gateway/src/qualification.rs","sha256":"d5078a81dc89f30958a7d8fdabfe164c3411c441dd7d9015002681a58883b63a"},{"path":"product/runtime/auths-gateway/src/qualification_tests.rs","sha256":"4473add5729b97faf04d7be7fd8cf3bbacd7f545e1b61c7d2782563011906b4d"},{"path":"product/runtime/auths-gateway/src/quorum_tests.rs","sha256":"a78380b019104d688c11a4410082c7e08ded3106aab099954c4f8a1b4ae0fd89"},{"path":"product/runtime/auths-gateway/src/readiness.rs","sha256":"911c3f11892f94641574375e2da4c671c802738f71082f12c39832331052d43d"},{"path":"product/runtime/auths-gateway/src/recipe.rs","sha256":"fecf9af67e7afc48d080e9f8f55f8ce28e49d0e08988717a27908bbda461d6b6"},{"path":"product/runtime/auths-gateway/src/recipe/lower.rs","sha256":"8088b8751ed831dbb48247af953c6290ac95e2a438ccd5bd65eff54be06a1fd1"},{"path":"product/runtime/auths-gateway/src/recipe/review.rs","sha256":"c3eb7d9fdd98dacf52750b14b67ad7b7faaecbbdeafff1e0b049f67d0a2d0139"},{"path":"product/runtime/auths-gateway/src/recipe/runtime.rs","sha256":"c286f0d15f974402822c0810d8e97f98411dc1c557755cc23e540d85e2bb42d9"},{"path":"product/runtime/auths-gateway/src/recipe/source.rs","sha256":"1af50298fb1461e1b24cbdf560d43124d6b1c4c529586c911b1c4797214a69ff"},{"path":"product/runtime/auths-gateway/src/recipe/tests.rs","sha256":"aac551a2481bbc60864c64079bc667dcb232e45a0f41a04073ed84ab5dbe1fce"},{"path":"product/runtime/auths-gateway/src/recipe/validate.rs","sha256":"3711b17605cb7b0d639bc1b180449231f5882a306cab20e2c7782155cc63b0d4"},{"path":"product/runtime/auths-gateway/src/scenario_tests.rs","sha256":"d8271761b12597bfe1233f8eb5ad1d4e5498c5d03388e832e24ab818484a1de4"},{"path":"product/runtime/auths-gateway/src/separation.rs","sha256":"be9306848ca5d801767cf6aa14247c8618312ef0e202f00ce0c24c4844491061"},{"path":"product/runtime/auths-gateway/src/store.rs","sha256":"1e5288345c2cb1421aeda277b3158d07607404b0ec46943222ac107b63dcbb46"},{"path":"product/runtime/auths-gateway/src/store_testkit.rs","sha256":"88d82fee42f1b8ef521e8deef0216e938ebeaad822eb2f5020e70b89d145ea70"},{"path":"product/runtime/auths-gateway/src/submit.rs","sha256":"c78dbbba7c45b443febf655056c5edcd635e77be7b21c5b2c318097502415ffe"},{"path":"product/runtime/auths-gateway/src/support.rs","sha256":"9fd979029793a22b15d9776a7fc172476fd7c126a80d4080c65d720845becbcb"},{"path":"product/runtime/auths-gateway/src/transport.rs","sha256":"be2c6dc75b8daec110bf8749fedc3823f6067d40b999aa3eb21126896a97d3ad"},{"path":"product/runtime/auths-kernel-runtime/Cargo.toml","sha256":"926bcd0053e5edd703be8f0027ad009e2982db013c8174c1366edbf38b48087d"},{"path":"product/runtime/auths-kernel-runtime/src/lib.rs","sha256":"7108faae9ca4bc32dc093ddaf885ac8f74f3c9b8d317b7c7d0ed00d1d0ab5972"},{"path":"product/runtime/auths-lifecycle/Cargo.toml","sha256":"c5053c705f8d5554b44e432fe75287a2faf11d644e5a2552e45ad6cd94176af5"},{"path":"product/runtime/auths-lifecycle/src/codec.rs","sha256":"51c4b746749150e8bfcd8ff972b3f6c1ef40bec15583448ec1b471d9ad737dc0"},{"path":"product/runtime/auths-lifecycle/src/digest.rs","sha256":"55282cd7d8aba37713c2dcb5357c9877819edb72a30eadefb860d28d7d3a3eb7"},{"path":"product/runtime/auths-lifecycle/src/identifier.rs","sha256":"31620e8c16de68d3d2d3b84d6353c1a5b9d4151d8247f91fa389b906a8e660f1"},{"path":"product/runtime/auths-lifecycle/src/kernel.rs","sha256":"2abb8c094b36d35b364e74d78091d14c5d6f3d1eb6552cca3b5538dbd017ce23"},{"path":"product/runtime/auths-lifecycle/src/lib.rs","sha256":"afe5a345cd309b5a4f08ffba3170a6d7f16ff914892b3f2006d5208ed24ec736"},{"path":"product/runtime/auths-lifecycle/src/model.rs","sha256":"1af12bbeeeaa65ec02ddcebd7d2c8c92ec1e339fa40ae85b45ab9b01a722a4fa"},{"path":"product/runtime/auths-lifecycle/src/operation.rs","sha256":"78e6d05fcf5d7ea4f148032a3fa26fdfcab77eb346019effe927b08e0d64d732"},{"path":"product/runtime/auths-lifecycle/src/registry.rs","sha256":"53495fe6f7a77422593a41623e28716f1c140dcc1e00f87f6b0ffbfb93a5ef90"},{"path":"product/runtime/auths-lifecycle/src/sealed.rs","sha256":"2e0c03b5813c926c159598bb7890d1523825edbe57cd687d42a5dfb3374a0c19"},{"path":"product/runtime/auths-lifecycle/src/test_support.rs","sha256":"221d9a5c5ef8e1f9f8fd66927484eaf813571d0568470278ecd8fa08a5eec8cd"},{"path":"product/runtime/auths-lifecycle/src/transition.rs","sha256":"011805a28efdd541f44ccea54dd0e34a1e58f4004447ee58013703b4fb6b2822"},{"path":"product/runtime/auths-runtime/Cargo.toml","sha256":"dd29d80a8b4bb56c869f036a6c9998f6e6d1c0383ac5dc03fa42b24abe2a7ff7"},{"path":"product/runtime/auths-runtime/src/lib.rs","sha256":"132ca03d58c14905d3a822a4972f42a22a5ad33a45f2ba9ca44f3a57d810b4b0"},{"path":"product/runtime/auths-runtime/src/production.rs","sha256":"fd4eff4270c571c10fcff6cf27df28961ebf074de8a1a028f500fda1ca376820"},{"path":"product/sdk/auths-approval-quorum/Cargo.toml","sha256":"df904971fca87a24194c5816738a331588fe8f164acb5d70839a35dca5f57114"},{"path":"product/sdk/auths-approval-quorum/src/lib.rs","sha256":"72e4086088a1c0912e4e1a9e980f26a5c280bf5ab16ea39c9f0f58d5096ac2ce"},{"path":"product/sdk/auths-approval-quorum/src/remote.rs","sha256":"9fa029c7c63003adf260f8aec55160c545681c60c1bace0d934e7525862aac7b"},{"path":"product/sdk/auths-approval-quorum/src/remote_tests.rs","sha256":"8a09ce17cfee82a035a74edd535f3ebeb3db0e078784740d3997b17dbdb10197"},{"path":"product/sdk/auths-approval-quorum/src/tests.rs","sha256":"0acbf12be3e497dcc6c2d8f29c9af3b1a7ed8e11b75f6399570d4f217a785060"},{"path":"product/stores/auths-stores/Cargo.toml","sha256":"a32c4b76d17b264be5d40d24497ff237e1ed87822e8bab86229b3db93106dbe3"},{"path":"product/stores/auths-stores/src/gateway_attempt.rs","sha256":"185da8f4a220fba836d5b78a9311f03204681c43a3c53951008084d135bf4d21"},{"path":"product/stores/auths-stores/src/lib.rs","sha256":"e721262edf8a9ab5568ddc27639176312d4a366203b5f73e2d7c11fde2c554e9"},{"path":"product/stores/auths-stores/src/lifecycle.rs","sha256":"94f64d25bc178a9e60ba3c0ee6915d7fb3af7c4468792d76b4e70f43f4de1e2f"}],"schema":"auths.gateway-semantic-closure/1"} \ No newline at end of file diff --git a/product/runtime/auths-gateway/src/bin/auths-gateway.rs b/product/runtime/auths-gateway/src/bin/auths-gateway.rs index 2e2424fed..2f49a1685 100644 --- a/product/runtime/auths-gateway/src/bin/auths-gateway.rs +++ b/product/runtime/auths-gateway/src/bin/auths-gateway.rs @@ -2286,17 +2286,7 @@ mod unix { } }, ); - let sweeper = async move { - let mut tick = tokio::time::interval(std::time::Duration::from_secs( - auths_gateway::SLOT_SWEEP_INTERVAL_SECONDS, - )); - loop { - tick.tick().await; - if let Err(code) = sweep_engine.sweep_expired_slots().await { - eprintln!("{code}"); - } - } - }; + let sweeper = sweep_periodically(sweep_engine.as_ref()); let mut terminate = tokio::signal::unix::signal(tokio::signal::unix::SignalKind::terminate()) .map_err(|_| "gateway.serve.signal-unavailable")?; @@ -2310,6 +2300,29 @@ mod unix { // The listeners have been dropped: no new session can be admitted. // Waiting for permits includes pre-entry and admin sessions, not // just transports already counted by the engine. + let drained = drain_sessions(&app_permits, &admin_permits, app_capacity).await; + let _ = fs::remove_file(&app_socket); + let _ = fs::remove_file(admin_path); + drained + } + + async fn sweep_periodically(engine: &GatewayEngine) -> ! { + let mut tick = tokio::time::interval(Duration::from_secs( + auths_gateway::SLOT_SWEEP_INTERVAL_SECONDS, + )); + loop { + tick.tick().await; + if let Err(code) = engine.sweep_expired_slots().await { + eprintln!("{code}"); + } + } + } + + async fn drain_sessions( + app_permits: &Semaphore, + admin_permits: &Semaphore, + app_capacity: usize, + ) -> Result<(), Failure> { let drained = tokio::time::timeout(Duration::from_secs(25), async { let _app = app_permits .acquire_many(u32::try_from(app_capacity).map_err(|_| "gateway.serve.capacity")?) @@ -2322,8 +2335,6 @@ mod unix { Ok::<_, &'static str>(()) }) .await; - let _ = fs::remove_file(&app_socket); - let _ = fs::remove_file(admin_path); match drained { Ok(result) => Ok(result?), Err(_) => Err("gateway.serve.shutdown-incomplete".into()), @@ -2755,10 +2766,10 @@ mod unix { .map_err(|_| "gateway.admin.load-failed")? } - fn print_admin_response(response: AdminResponse) -> Result<(), Failure> { + fn print_admin_response(response: &AdminResponse) -> Result<(), Failure> { println!( "{}", - serde_json::to_string(&response).map_err(|_| "gateway.output")? + serde_json::to_string(response).map_err(|_| "gateway.output")? ); if response.ok { Ok(()) @@ -2807,7 +2818,7 @@ mod unix { } else { AdminResponse::of(engine.rotate_connection(bytes).await) }; - return print_admin_response(response); + return print_admin_response(&response); } admin_command( state_dir, @@ -3087,10 +3098,26 @@ mod unix { } // Runtime checks run as the actual gateway owner, so root does not // accidentally bypass file ownership checks or mutate its custody. + let mut checked = runtime_doctor_as_owner(state_dir, state.uid(), state.gid()).await?; + checked.required.operator_plane_isolation = auths_gateway::PreconditionState::Ready; + let readiness = auths_gateway::ProductionReadiness::new(checked.required, checked.observer); + println!( + "{}", + readiness.report(checked.qualification_code.map(|code| code.0)) + ); + if !readiness.is_ready() { + return Err("gateway.doctor.not-ready"); + } + Ok(()) + } + + async fn runtime_doctor_as_owner( + state_dir: &Path, + uid: u32, + gid: u32, + ) -> Result { let binary = std::env::current_exe().map_err(|_| "gateway.doctor.binary-unavailable")?; let directory = state_dir.to_path_buf(); - let uid = state.uid(); - let gid = state.gid(); let output = tokio::task::spawn_blocking(move || { std::process::Command::new(binary) .arg("readiness-probe") @@ -3106,18 +3133,7 @@ mod unix { if !output.status.success() || output.stdout.len() > 64 * 1024 { return Err("gateway.doctor.runtime-check-unavailable"); } - let mut checked: DoctorRuntime = serde_json::from_slice(&output.stdout) - .map_err(|_| "gateway.doctor.invalid-runtime-report")?; - checked.required.operator_plane_isolation = auths_gateway::PreconditionState::Ready; - let readiness = auths_gateway::ProductionReadiness::new(checked.required, checked.observer); - println!( - "{}", - readiness.report(checked.qualification_code.map(|code| code.0)) - ); - if !readiness.is_ready() { - return Err("gateway.doctor.not-ready"); - } - Ok(()) + serde_json::from_slice(&output.stdout).map_err(|_| "gateway.doctor.invalid-runtime-report") } fn probe(state_dir: &Path, admin_socket: &Path, app_socket: &Path) -> Result<(), &'static str> { @@ -3442,7 +3458,7 @@ mod unix { hex::decode_to_slice(&commitment, &mut fixed) .map_err(|_| "gateway.admin.invalid-frame")?; let response = AdminResponse::of(engine.commit_rotation(fixed).await); - return print_admin_response(response); + return print_admin_response(&response); } let admin_socket = admin_socket_path(&state_dir, admin_socket); admin_command( diff --git a/product/runtime/auths-gateway/src/generation_floor.rs b/product/runtime/auths-gateway/src/generation_floor.rs index 4673a397f..67c0260ec 100644 --- a/product/runtime/auths-gateway/src/generation_floor.rs +++ b/product/runtime/auths-gateway/src/generation_floor.rs @@ -44,7 +44,7 @@ impl GenerationFloor { /// Returns the restore-rollback code if the floor cannot be persisted. pub fn initialize(&self, record: &ConnectionRecord) -> Result<(), &'static str> { self.persist(record, true) - .map_err(|_| "gateway.connection.restore-rollback") + .map_err(|()| "gateway.connection.restore-rollback") } /// Accepts an equal or newer exact record, durably recording a newer one @@ -55,7 +55,7 @@ impl GenerationFloor { /// Returns `gateway.connection.restore-rollback`; no secret is leased. pub fn accept(&self, record: &ConnectionRecord) -> Result<(), &'static str> { self.persist(record, false) - .map_err(|_| "gateway.connection.restore-rollback") + .map_err(|()| "gateway.connection.restore-rollback") } #[cfg(unix)] diff --git a/product/runtime/auths-gateway/src/qualification.rs b/product/runtime/auths-gateway/src/qualification.rs index f96641d4a..b5be98dcf 100644 --- a/product/runtime/auths-gateway/src/qualification.rs +++ b/product/runtime/auths-gateway/src/qualification.rs @@ -124,7 +124,7 @@ impl SynchronizedHostClock { impl sealed::Sealed for SynchronizedHostClock {} -const MAX_SYNCHRONIZATION_AGE: Duration = Duration::from_secs(15 * 60); +const MAX_SYNCHRONIZATION_AGE: Duration = Duration::from_mins(15); fn synchronization_marker_trust(path: &std::path::Path, now: SystemTime) -> ClockTrustState { let Ok(marker) = std::fs::symlink_metadata(path) else { diff --git a/product/runtime/auths-gateway/src/semantic_closure.rs b/product/runtime/auths-gateway/src/semantic_closure.rs index 17b4e92d0..e4ed4f8ba 100644 --- a/product/runtime/auths-gateway/src/semantic_closure.rs +++ b/product/runtime/auths-gateway/src/semantic_closure.rs @@ -10,7 +10,7 @@ /// SHA-256 of the schema, a NUL byte, and `semantic-closure.json`. /// Regenerate through `semantic_closure_is_current` with `AUTHS_UPDATE_FIXTURES=1`. pub const GATEWAY_SEMANTIC_CLOSURE_SHA256: &str = - "5bd6f6bf1cc166e7dfc8c2ee365e49b43310bf6e3e06f2a3c1b4379cebf65ce3"; + "ec4a2b94844f90e3b2e3b30cb8c3e18a33f14242221e7765ff0f1877ab1c286e"; #[cfg(test)] mod tests { From d24db30b2bcc173ee670c49c5d4d4070df5cde44 Mon Sep 17 00:00:00 2001 From: bordumb Date: Tue, 6 Oct 2026 05:01:31 +0100 Subject: [PATCH 017/108] fix(formal): refresh credential-store proof coverage measurement --- docs/assurance/PROOF_COVERAGE.md | 4 +- formal/proof-coverage-functions-v1.tsv | 86 +++++++++++++------------- formal/proof-coverage-v1.json | 14 ++--- 3 files changed, 52 insertions(+), 52 deletions(-) diff --git a/docs/assurance/PROOF_COVERAGE.md b/docs/assurance/PROOF_COVERAGE.md index 9ef778ee9..5b207aeb5 100644 --- a/docs/assurance/PROOF_COVERAGE.md +++ b/docs/assurance/PROOF_COVERAGE.md @@ -7,7 +7,7 @@ At the commit that contains this document, 110 of 1,031 decision-scope functions (10.7%) and 1,289 of 11,353 code lines (11.4%) are translated to Lean and reached from audited theorem statements, and 15 of 82 kernel check sites map only to such functions. The rest of the decision path, including the staged verifier control flow, the composition evaluator, the registry handlers, the codec, and the signature suites, is tested, not proved. - Revision: the commit that contains this document and `formal/proof-coverage-v1.json`; a release binds it in its assurance evidence. -- Measurement inputs: sha256 `aa2ed884c2a3f36b66103057966c4d6ec0610647696c4f8b163225bba4026b76` over the 89 files listed in `formal/proof-coverage-v1.json`. +- Measurement inputs: sha256 `56f5f8df74c31a2554725ec967451d36bfa6e7c4a49004b3c83bb5cd32c35f52` over the 89 files listed in `formal/proof-coverage-v1.json`. - Tool: `cargo xtask formal coverage`, version 1. - Toolchain pins: `formal/lean-toolchain` = `leanprover/lean4:v4.31.0`; `formal/translation-toolchain.lock` sha256 `0c45a8a08ac06e313d775e669749097bd3a0abfb8e3395c69416ba0238770d53`. - Role table: `formal/coverage-scope-v1.toml`, sha256 `053f0be216b0003768d422d9ccc92a692726488874284fa80615657b30a495b5`. Figures computed under a different role table are not comparable. @@ -52,7 +52,7 @@ Files in scoped crates with a non-decision role (every other scoped file is deci | --- | ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: | | decision | 1,031 | 110 (10.7%) | 56 (5.4%) | 110 (10.7%) | 11,353 | 1,289 (11.4%) | 856 (7.5%) | 1,289 (11.4%) | | verifier-core | 785 | 86 (11.0%) | 41 (5.2%) | 86 (11.0%) | 8,802 | 907 (10.3%) | 558 (6.3%) | 907 (10.3%) | -| translated-crates | 1,138 | 210 (18.5%) | 70 (6.2%) | 210 (18.5%) | 10,666 | 2,508 (23.5%) | 1,024 (9.6%) | 2,508 (23.5%) | +| translated-crates | 1,138 | 210 (18.5%) | 70 (6.2%) | 210 (18.5%) | 10,662 | 2,508 (23.5%) | 1,024 (9.6%) | 2,508 (23.5%) | | verifier-closure | 1,083 | 86 (7.9%) | 41 (3.8%) | 86 (7.9%) | 13,762 | 907 (6.6%) | 558 (4.1%) | 907 (6.6%) | | decision-nontrivial | 443 | 81 (18.3%) | 44 (9.9%) | 81 (18.3%) | 9,589 | 1,202 (12.5%) | 820 (8.6%) | 1,202 (12.5%) | diff --git a/formal/proof-coverage-functions-v1.tsv b/formal/proof-coverage-functions-v1.tsv index bddcfc0aa..9e3656230 100644 --- a/formal/proof-coverage-functions-v1.tsv +++ b/formal/proof-coverage-functions-v1.tsv @@ -1205,49 +1205,49 @@ product/runtime/auths-connections/src/credential.rs 145 147 3 StoredSecretLease: product/runtime/auths-connections/src/credential.rs 182 187 6 CredentialStoreKind::parse product/runtime/auths-connections decision 0 0 0 0 0 0 product/runtime/auths-connections/src/credential.rs 191 196 6 CredentialStoreKind::as_str product/runtime/auths-connections decision 0 0 0 0 0 0 product/runtime/auths-connections/src/credential.rs 201 206 6 CredentialStoreKind::is_production product/runtime/auths-connections decision 0 0 0 0 0 0 -product/runtime/auths-connections/src/credential.rs 319 324 6 StoredSecret::holds product/runtime/auths-connections decision 0 0 0 0 0 0 -product/runtime/auths-connections/src/credential.rs 333 342 10 InMemoryCredentialStore::new product/runtime/auths-connections decision 0 0 0 0 0 0 -product/runtime/auths-connections/src/credential.rs 344 346 3 InMemoryCredentialStore::total_bytes product/runtime/auths-connections decision 0 0 0 0 0 0 -product/runtime/auths-connections/src/credential.rs 351 381 31 InMemoryCredentialStore::install product/runtime/auths-connections decision 0 0 0 0 0 0 -product/runtime/auths-connections/src/credential.rs 383 397 15 InMemoryCredentialStore::lease_secret product/runtime/auths-connections decision 0 0 0 0 0 0 -product/runtime/auths-connections/src/credential.rs 399 440 42 InMemoryCredentialStore::replace product/runtime/auths-connections decision 0 0 0 0 0 0 -product/runtime/auths-connections/src/credential.rs 442 456 15 InMemoryCredentialStore::revoke product/runtime/auths-connections decision 0 0 0 0 0 0 -product/runtime/auths-connections/src/credential.rs 458 464 7 InMemoryCredentialStore::holds product/runtime/auths-connections decision 0 0 0 0 0 0 -product/runtime/auths-connections/src/credential.rs 466 504 39 InMemoryCredentialStore::confirm product/runtime/auths-connections decision 0 0 0 0 0 0 -product/runtime/auths-connections/src/credential.rs 506 521 16 InMemoryCredentialStore::retire_superseded product/runtime/auths-connections decision 0 0 0 0 0 0 -product/runtime/auths-connections/src/credential.rs 523 535 13 InMemoryCredentialStore::delete_connection product/runtime/auths-connections decision 0 0 0 0 0 0 -product/runtime/auths-connections/src/credential.rs 561 567 7 PersistentCredentialStore::open product/runtime/auths-connections decision 0 0 0 0 0 0 -product/runtime/auths-connections/src/credential.rs 575 604 30 PersistentCredentialStore::open_with_limits product/runtime/auths-connections decision 0 0 0 0 0 0 -product/runtime/auths-connections/src/credential.rs 606 621 16 PersistentCredentialStore::mutate product/runtime/auths-connections decision 0 0 0 0 0 0 -product/runtime/auths-connections/src/credential.rs 623 625 3 PersistentCredentialStore::total_bytes product/runtime/auths-connections decision 0 0 0 0 0 0 -product/runtime/auths-connections/src/credential.rs 640 652 13 PersistentCredentialStore::retained_commitment product/runtime/auths-connections decision 0 0 0 0 0 0 -product/runtime/auths-connections/src/credential.rs 661 672 12 PersistentCredentialStore::stored_generations product/runtime/auths-connections decision 0 0 0 0 0 0 -product/runtime/auths-connections/src/credential.rs 688 702 15 PersistentCredentialStore::lease_for_record product/runtime/auths-connections decision 0 0 0 0 0 0 -product/runtime/auths-connections/src/credential.rs 710 719 10 PersistentCredentialStore::holds_record_credential product/runtime/auths-connections decision 0 0 0 0 0 0 -product/runtime/auths-connections/src/credential.rs 739 775 37 PersistentCredentialStore::store_confirmed product/runtime/auths-connections decision 0 0 0 0 0 0 -product/runtime/auths-connections/src/credential.rs 791 796 6 PersistentCredentialStore::revoke_connection product/runtime/auths-connections decision 0 0 0 0 0 0 -product/runtime/auths-connections/src/credential.rs 813 838 26 PersistentCredentialStore::retain_generations product/runtime/auths-connections decision 0 0 0 0 0 0 -product/runtime/auths-connections/src/credential.rs 840 861 22 PersistentCredentialStore::delete_generations product/runtime/auths-connections decision 0 0 0 0 0 0 -product/runtime/auths-connections/src/credential.rs 866 876 11 retained_entry product/runtime/auths-connections decision 0 0 0 0 0 0 -product/runtime/auths-connections/src/credential.rs 884 904 21 binding_entry product/runtime/auths-connections decision 0 0 0 0 0 0 -product/runtime/auths-connections/src/credential.rs 908 931 24 record_entry product/runtime/auths-connections decision 0 0 0 0 0 0 -product/runtime/auths-connections/src/credential.rs 933 941 9 connection_generations product/runtime/auths-connections decision 0 0 0 0 0 0 -product/runtime/auths-connections/src/credential.rs 945 973 29 PersistentCredentialStore::install product/runtime/auths-connections decision 0 0 0 0 0 0 -product/runtime/auths-connections/src/credential.rs 975 989 15 PersistentCredentialStore::lease_secret product/runtime/auths-connections decision 0 0 0 0 0 0 -product/runtime/auths-connections/src/credential.rs 991 1035 45 PersistentCredentialStore::replace product/runtime/auths-connections decision 0 0 0 0 0 0 -product/runtime/auths-connections/src/credential.rs 1037 1050 13 PersistentCredentialStore::revoke product/runtime/auths-connections decision 0 0 0 0 0 0 -product/runtime/auths-connections/src/credential.rs 1052 1058 7 PersistentCredentialStore::holds product/runtime/auths-connections decision 0 0 0 0 0 0 -product/runtime/auths-connections/src/credential.rs 1060 1072 13 PersistentCredentialStore::confirm product/runtime/auths-connections decision 0 0 0 0 0 0 -product/runtime/auths-connections/src/credential.rs 1074 1087 14 PersistentCredentialStore::retire_superseded product/runtime/auths-connections decision 0 0 0 0 0 0 -product/runtime/auths-connections/src/credential.rs 1089 1095 7 PersistentCredentialStore::delete_connection product/runtime/auths-connections decision 0 0 0 0 0 0 -product/runtime/auths-connections/src/credential.rs 1098 1111 14 validate_parent product/runtime/auths-connections decision 0 0 0 0 0 0 -product/runtime/auths-connections/src/credential.rs 1113 1128 16 validate_secret_file product/runtime/auths-connections decision 0 0 0 0 0 0 -product/runtime/auths-connections/src/credential.rs 1130 1161 32 persist_entries product/runtime/auths-connections decision 0 0 0 0 0 0 -product/runtime/auths-connections/src/credential.rs 1166 1177 12 encode_persistent_entries product/runtime/auths-connections decision 0 0 0 0 0 0 -product/runtime/auths-connections/src/credential.rs 1179 1201 23 write_persistent_entries product/runtime/auths-connections decision 0 0 0 0 0 0 -product/runtime/auths-connections/src/credential.rs 1209 1212 4 EncodedLength::write_all product/runtime/auths-connections decision 0 0 0 0 0 0 -product/runtime/auths-connections/src/credential.rs 1215 1309 95 decode_persistent_entries product/runtime/auths-connections decision 0 0 0 0 0 0 -product/runtime/auths-connections/src/credential.rs 1340 1351 12 credential_commitment product/runtime/auths-connections decision 0 0 0 0 0 0 +product/runtime/auths-connections/src/credential.rs 320 325 6 StoredSecret::holds product/runtime/auths-connections decision 0 0 0 0 0 0 +product/runtime/auths-connections/src/credential.rs 334 343 10 InMemoryCredentialStore::new product/runtime/auths-connections decision 0 0 0 0 0 0 +product/runtime/auths-connections/src/credential.rs 345 347 3 InMemoryCredentialStore::total_bytes product/runtime/auths-connections decision 0 0 0 0 0 0 +product/runtime/auths-connections/src/credential.rs 352 382 31 InMemoryCredentialStore::install product/runtime/auths-connections decision 0 0 0 0 0 0 +product/runtime/auths-connections/src/credential.rs 384 398 15 InMemoryCredentialStore::lease_secret product/runtime/auths-connections decision 0 0 0 0 0 0 +product/runtime/auths-connections/src/credential.rs 400 441 42 InMemoryCredentialStore::replace product/runtime/auths-connections decision 0 0 0 0 0 0 +product/runtime/auths-connections/src/credential.rs 443 455 13 InMemoryCredentialStore::revoke product/runtime/auths-connections decision 0 0 0 0 0 0 +product/runtime/auths-connections/src/credential.rs 457 463 7 InMemoryCredentialStore::holds product/runtime/auths-connections decision 0 0 0 0 0 0 +product/runtime/auths-connections/src/credential.rs 465 503 39 InMemoryCredentialStore::confirm product/runtime/auths-connections decision 0 0 0 0 0 0 +product/runtime/auths-connections/src/credential.rs 505 520 16 InMemoryCredentialStore::retire_superseded product/runtime/auths-connections decision 0 0 0 0 0 0 +product/runtime/auths-connections/src/credential.rs 522 534 13 InMemoryCredentialStore::delete_connection product/runtime/auths-connections decision 0 0 0 0 0 0 +product/runtime/auths-connections/src/credential.rs 560 566 7 PersistentCredentialStore::open product/runtime/auths-connections decision 0 0 0 0 0 0 +product/runtime/auths-connections/src/credential.rs 574 603 30 PersistentCredentialStore::open_with_limits product/runtime/auths-connections decision 0 0 0 0 0 0 +product/runtime/auths-connections/src/credential.rs 605 620 16 PersistentCredentialStore::mutate product/runtime/auths-connections decision 0 0 0 0 0 0 +product/runtime/auths-connections/src/credential.rs 622 624 3 PersistentCredentialStore::total_bytes product/runtime/auths-connections decision 0 0 0 0 0 0 +product/runtime/auths-connections/src/credential.rs 639 651 13 PersistentCredentialStore::retained_commitment product/runtime/auths-connections decision 0 0 0 0 0 0 +product/runtime/auths-connections/src/credential.rs 660 671 12 PersistentCredentialStore::stored_generations product/runtime/auths-connections decision 0 0 0 0 0 0 +product/runtime/auths-connections/src/credential.rs 687 701 15 PersistentCredentialStore::lease_for_record product/runtime/auths-connections decision 0 0 0 0 0 0 +product/runtime/auths-connections/src/credential.rs 709 718 10 PersistentCredentialStore::holds_record_credential product/runtime/auths-connections decision 0 0 0 0 0 0 +product/runtime/auths-connections/src/credential.rs 738 774 37 PersistentCredentialStore::store_confirmed product/runtime/auths-connections decision 0 0 0 0 0 0 +product/runtime/auths-connections/src/credential.rs 790 795 6 PersistentCredentialStore::revoke_connection product/runtime/auths-connections decision 0 0 0 0 0 0 +product/runtime/auths-connections/src/credential.rs 812 837 26 PersistentCredentialStore::retain_generations product/runtime/auths-connections decision 0 0 0 0 0 0 +product/runtime/auths-connections/src/credential.rs 839 860 22 PersistentCredentialStore::delete_generations product/runtime/auths-connections decision 0 0 0 0 0 0 +product/runtime/auths-connections/src/credential.rs 865 875 11 retained_entry product/runtime/auths-connections decision 0 0 0 0 0 0 +product/runtime/auths-connections/src/credential.rs 883 903 21 binding_entry product/runtime/auths-connections decision 0 0 0 0 0 0 +product/runtime/auths-connections/src/credential.rs 907 930 24 record_entry product/runtime/auths-connections decision 0 0 0 0 0 0 +product/runtime/auths-connections/src/credential.rs 932 940 9 connection_generations product/runtime/auths-connections decision 0 0 0 0 0 0 +product/runtime/auths-connections/src/credential.rs 944 972 29 PersistentCredentialStore::install product/runtime/auths-connections decision 0 0 0 0 0 0 +product/runtime/auths-connections/src/credential.rs 974 988 15 PersistentCredentialStore::lease_secret product/runtime/auths-connections decision 0 0 0 0 0 0 +product/runtime/auths-connections/src/credential.rs 990 1034 45 PersistentCredentialStore::replace product/runtime/auths-connections decision 0 0 0 0 0 0 +product/runtime/auths-connections/src/credential.rs 1036 1047 11 PersistentCredentialStore::revoke product/runtime/auths-connections decision 0 0 0 0 0 0 +product/runtime/auths-connections/src/credential.rs 1049 1055 7 PersistentCredentialStore::holds product/runtime/auths-connections decision 0 0 0 0 0 0 +product/runtime/auths-connections/src/credential.rs 1057 1069 13 PersistentCredentialStore::confirm product/runtime/auths-connections decision 0 0 0 0 0 0 +product/runtime/auths-connections/src/credential.rs 1071 1084 14 PersistentCredentialStore::retire_superseded product/runtime/auths-connections decision 0 0 0 0 0 0 +product/runtime/auths-connections/src/credential.rs 1086 1092 7 PersistentCredentialStore::delete_connection product/runtime/auths-connections decision 0 0 0 0 0 0 +product/runtime/auths-connections/src/credential.rs 1095 1108 14 validate_parent product/runtime/auths-connections decision 0 0 0 0 0 0 +product/runtime/auths-connections/src/credential.rs 1110 1125 16 validate_secret_file product/runtime/auths-connections decision 0 0 0 0 0 0 +product/runtime/auths-connections/src/credential.rs 1127 1158 32 persist_entries product/runtime/auths-connections decision 0 0 0 0 0 0 +product/runtime/auths-connections/src/credential.rs 1163 1174 12 encode_persistent_entries product/runtime/auths-connections decision 0 0 0 0 0 0 +product/runtime/auths-connections/src/credential.rs 1176 1198 23 write_persistent_entries product/runtime/auths-connections decision 0 0 0 0 0 0 +product/runtime/auths-connections/src/credential.rs 1206 1209 4 EncodedLength::write_all product/runtime/auths-connections decision 0 0 0 0 0 0 +product/runtime/auths-connections/src/credential.rs 1212 1306 95 decode_persistent_entries product/runtime/auths-connections decision 0 0 0 0 0 0 +product/runtime/auths-connections/src/credential.rs 1337 1348 12 credential_commitment product/runtime/auths-connections decision 0 0 0 0 0 0 product/runtime/auths-connections/src/kernel.rs 29 31 3 next_generation product/runtime/auths-connections decision 0 0 1 1 1 1 product/runtime/auths-connections/src/kernel.rs 36 44 9 state_change product/runtime/auths-connections decision 0 0 1 1 1 1 product/runtime/auths-connections/src/kernel.rs 49 57 9 rotation product/runtime/auths-connections decision 0 0 1 1 1 1 diff --git a/formal/proof-coverage-v1.json b/formal/proof-coverage-v1.json index cb9799148..49af70735 100644 --- a/formal/proof-coverage-v1.json +++ b/formal/proof-coverage-v1.json @@ -16,7 +16,7 @@ "translation_toolchain_lock_sha256": "0c45a8a08ac06e313d775e669749097bd3a0abfb8e3395c69416ba0238770d53" }, "scope_definition_sha256": "053f0be216b0003768d422d9ccc92a692726488874284fa80615657b30a495b5", - "inputs_sha256": "aa2ed884c2a3f36b66103057966c4d6ec0610647696c4f8b163225bba4026b76", + "inputs_sha256": "56f5f8df74c31a2554725ec967451d36bfa6e7c4a49004b3c83bb5cd32c35f52", "inputs": { "Cargo.toml": "sha256:6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24", "core/crates/auths-algebra-kernel/Cargo.toml": "sha256:0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba", @@ -84,7 +84,7 @@ "product/policy/auths-bounded-policy/src/lib.rs": "sha256:76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c", "product/policy/auths-bounded-policy/src/receipt.rs": "sha256:3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad", "product/policy/auths-bounded-policy/src/registry.rs": "sha256:4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0", - "product/runtime/auths-connections/src/credential.rs": "sha256:4d532c221d2fe7a2b47c8720be94c26d0c86a0448c3f66f479ce3b12adf44f25", + "product/runtime/auths-connections/src/credential.rs": "sha256:82921413bb053f0f6c7931fbd4e6a86c8cc1d8c6b51debd9c2cef33a8d5b1c51", "product/runtime/auths-connections/src/kernel.rs": "sha256:a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8", "product/runtime/auths-connections/src/lib.rs": "sha256:79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22", "product/runtime/auths-connections/src/model.rs": "sha256:de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77", @@ -246,8 +246,8 @@ "scope": "translated-crates", "minimum_code_lines": 0, "functions": 1138, - "span_lines": 10685, - "code_lines": 10666, + "span_lines": 10681, + "code_lines": 10662, "by_level": { "translated": { "functions": 210, @@ -255,7 +255,7 @@ "span_lines": 2519, "span_line_share": 0.2358, "code_lines": 2508, - "code_line_share": 0.2351 + "code_line_share": 0.2352 }, "direct": { "functions": 70, @@ -271,7 +271,7 @@ "span_lines": 2519, "span_line_share": 0.2358, "code_lines": 2508, - "code_line_share": 0.2351 + "code_line_share": 0.2352 } } }, @@ -549,7 +549,7 @@ }, "product/runtime/auths-connections": { "decision_functions": 153, - "decision_code_lines": 1891, + "decision_code_lines": 1887, "translated": 5, "refined_closure": 5, "refined_closure_code_lines": 51 From 8c98ecf7e9cb0f1ccac7413bf510bb35a394c859 Mon Sep 17 00:00:00 2001 From: bordumb Date: Tue, 6 Oct 2026 05:23:02 +0100 Subject: [PATCH 018/108] test(gateway): follow durable emergency-stop cleanup contract --- .../auths-gateway/semantic-closure.json | 2 +- .../auths-gateway/src/credential_journal.rs | 2 +- product/runtime/auths-gateway/src/engine.rs | 49 ++++++++++++++++--- .../auths-gateway/src/semantic_closure.rs | 2 +- 4 files changed, 44 insertions(+), 11 deletions(-) diff --git a/product/runtime/auths-gateway/semantic-closure.json b/product/runtime/auths-gateway/semantic-closure.json index e9af3dbcf..aa9637645 100644 --- a/product/runtime/auths-gateway/semantic-closure.json +++ b/product/runtime/auths-gateway/semantic-closure.json @@ -1 +1 @@ -{"files":[{"path":"Cargo.lock","sha256":"c94ed342774d5e2823f01ecf74b8a4812c5f9a6b0cf811d31f2e2cecb671a275"},{"path":"Cargo.toml","sha256":"6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24"},{"path":"core/adapters/auths-did-keri/Cargo.toml","sha256":"86ba3e3f9a0a70d970568bfb3113b7ba7bbdd81c3eebbb52743dd574a0c0ecaa"},{"path":"core/adapters/auths-did-keri/src/lib.rs","sha256":"a75674842f8a7142004369ccd206ab43e476459293f0ff4bed4d4e659031b3e3"},{"path":"core/adapters/auths-did-key/Cargo.toml","sha256":"d5a3ae07ecde83f91eed4c3785051dd0f44eab6c891754f3309b6b40596707d7"},{"path":"core/adapters/auths-did-key/src/lib.rs","sha256":"b76a3f4528a725df53cfa9242e6e414e1d26caa48468aaed497e28b121f4497c"},{"path":"core/adapters/auths-raw-key/Cargo.toml","sha256":"f49616bc18c19e6aaa7e6a02ccebcdb9f5c1422c1278ef9869e0dbf22ceda7be"},{"path":"core/adapters/auths-raw-key/src/lib.rs","sha256":"45eec1b295dac3bed65cd79c942870b926b06b3f5d38eaebaeb6140ac69315fa"},{"path":"core/crates/auths-algebra-kernel/Cargo.toml","sha256":"0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba"},{"path":"core/crates/auths-algebra-kernel/src/generated.rs","sha256":"ae4bcbef42a408c7ffa0c6a74a42f7de177a6f14479e51d205acf830bda05960"},{"path":"core/crates/auths-algebra-kernel/src/lib.rs","sha256":"6654667eeb9b353d6648954c9fd2e8838462a82ce6b2803eb49e1366892c68c6"},{"path":"core/crates/auths-assurance/Cargo.toml","sha256":"afcb12a97ddd09d7a264b9ecd3fcaefc865ff2c9b4539ee85b00883420ba333a"},{"path":"core/crates/auths-assurance/src/lib.rs","sha256":"0fb2ec844d674b25a9e20b1601452c89c2454901fa506adfa9bb38ef9a7fa213"},{"path":"core/crates/auths-author/Cargo.toml","sha256":"1e6f0e3bc079ddb558decf0db26b291c6e72fc47327b6df1b7650d41689b215f"},{"path":"core/crates/auths-author/src/lib.rs","sha256":"e14475f2f49715a1869d5fa6b11ff1fbb72497e39097e09f833b0bae7e5b3f2b"},{"path":"core/crates/auths-author/src/observations.rs","sha256":"dda7d6bfa6f4bd7e95a480ca283c2c0e996f69c5c15cb0c7197af328131a7066"},{"path":"core/crates/auths-authority/Cargo.toml","sha256":"4f68212938029f79ebd857b4f3038494eb85d0163d49f07e51376715cf959815"},{"path":"core/crates/auths-authority/src/lib.rs","sha256":"da88d5194de4e17449e69972c0fb042afa3c39798a8f570f30771e77c384f1eb"},{"path":"core/crates/auths-codec/Cargo.toml","sha256":"e20e51826e17814effd9d8925d18d5fbdd6c0d37bf50231e743ec2611314722c"},{"path":"core/crates/auths-codec/src/approval.rs","sha256":"fbff43bf4d57f69f8b7738a8647751cde75c5a932dee65d924a1fe9c7202f91f"},{"path":"core/crates/auths-codec/src/bounded_policy.rs","sha256":"d21f6728be2d8a04b6d94921f2b683f7e61cbb42e0ac6866f1c88a49caa534c3"},{"path":"core/crates/auths-codec/src/decode.rs","sha256":"ba2999584cdf53b1b517ecb9c7ea50d39efee17c666a9a38e2ad1ac94379f778"},{"path":"core/crates/auths-codec/src/encode.rs","sha256":"8491192053e2e15d62b4d2a491de22405b7487ead69ab6f6bca40669ce7ca5f7"},{"path":"core/crates/auths-codec/src/error.rs","sha256":"fecb0737c16deb42d859f1dc7727c698438d9ac12064fd99e0024629642c390c"},{"path":"core/crates/auths-codec/src/hash.rs","sha256":"f88e111f1dbb2cef6b7b5e9c948cb45ff92e366710c8a5f5c636138aa748479e"},{"path":"core/crates/auths-codec/src/lib.rs","sha256":"3b0e5c94c6f34f750b88a9333e1d5c8145746d845d3a23e0d2f61807cf592ea7"},{"path":"core/crates/auths-codec/src/observation.rs","sha256":"38328b0c71ff97a4196eeade8b4faa889527ff1f80bb168468bcd49082a3987e"},{"path":"core/crates/auths-composition/Cargo.toml","sha256":"331e13025eb82588b5269ed3975929eb41c823d588c49e4c296273d85c6fe80e"},{"path":"core/crates/auths-composition/src/lib.rs","sha256":"e42e3b0b6a9985b73c533aeb23799c638979aa27a9ce7d0f10a8d60340570fb1"},{"path":"core/crates/auths-model/Cargo.toml","sha256":"565c15302b0cc9270db1e28efa3862804846850ba933cc17aea8abcec4a65987"},{"path":"core/crates/auths-model/src/approval.rs","sha256":"54cf44a9ef747ec21546a4086aecfb130bc7803b0d646430e6082df51e6e305f"},{"path":"core/crates/auths-model/src/bounded.rs","sha256":"f90496abc0a06c028b4d850af6ddab7d850bfafeaa3d042f1b1246a41d8bbbc9"},{"path":"core/crates/auths-model/src/bounded_policy.rs","sha256":"306a8f049cc7cfc7635fe0e4de47eb7813eed63d3c14c3be2b51586aa4eea450"},{"path":"core/crates/auths-model/src/lib.rs","sha256":"e7cfe6bb9574c6b016aa63e70658c31e0b90903ec6479a49f4a2ceb64f5bad97"},{"path":"core/crates/auths-model/src/observation.rs","sha256":"b3ed3e3cc090afca2896a7d3de7988afccc1ee1ea0ebd91b51a8bc0f20ad8dbb"},{"path":"core/crates/auths-multikey/Cargo.toml","sha256":"858756c1197befcada06134742bffe8d58cf674cadd6c046bf710570e96efaf2"},{"path":"core/crates/auths-multikey/src/lib.rs","sha256":"f5177fffb11e40eeaaa665ba886c541fc1f24d5eacdd6983fb03dc20148733f0"},{"path":"core/crates/auths-ports/Cargo.toml","sha256":"596a9b0f5af3717c16a6d13f7054d8a106bcd9f01f5f72c2235dd2afcf0ab16c"},{"path":"core/crates/auths-ports/src/binding.rs","sha256":"a16c012d40aa4249e3ec54372b9611006d0bfe8c7dc3c741911c2194ad17736d"},{"path":"core/crates/auths-ports/src/diagnostics.rs","sha256":"aa596572503b5a65a918bb2ff38281c144ff53821ee914e9325c852828d852df"},{"path":"core/crates/auths-ports/src/lib.rs","sha256":"8da1debf86f9532df0660155d04298beb1ba3a1204508f8586e2e67cd2fb3449"},{"path":"core/crates/auths-ports/src/path.rs","sha256":"b68fc547b4e4d97a60cbbc1cc1939fc6b34a8233b81f840bd396914a707e3ea1"},{"path":"core/crates/auths-raw-key-core/Cargo.toml","sha256":"98c0bc8527a537512e43a74dd6ba9658c6f0cdc16610cf938e3f9b43785d836d"},{"path":"core/crates/auths-raw-key-core/src/lib.rs","sha256":"98c0500c41697aae28708ad0bf970b9a97583d96a3d2c18d23e7fa351e0f7d12"},{"path":"core/crates/auths-registries/Cargo.toml","sha256":"590e49e58b0622d9d6274fea46796dcdb07dec9550eff295cce6a6427ffa51e2"},{"path":"core/crates/auths-registries/src/lib.rs","sha256":"450d3886d85ee333b7e046317fb5b47cde62483d5f3e41d46265e2caf4c373ec"},{"path":"core/crates/auths-registries/src/template.rs","sha256":"1224039dd2b3ce6fa8357613d8cafbae40400493da7176da202b9ade62fa05e4"},{"path":"core/crates/auths-signature-core/Cargo.toml","sha256":"6bee2230eb30af1be0bd5c2d57bd3e1903497a70028d47290d4ac6e9e0e8bca0"},{"path":"core/crates/auths-signature-core/src/lib.rs","sha256":"6e3f9311ded5e49ea50d445eb21e6d8fa12442aa4362a73e0cb6fda15b7cd865"},{"path":"core/crates/auths-signature/Cargo.toml","sha256":"7f7b5682466ba439d8c59579022cb61068cad9fb4bd2d73e1cc21327c902b450"},{"path":"core/crates/auths-signature/src/lib.rs","sha256":"b3d9ac4cc3ba0797b9e1c09f2d6ac05089b25dac4e285a5af28c0165b33d925b"},{"path":"core/crates/auths-verifier/Cargo.toml","sha256":"c43358e06a33324b41a8b93e5cc7279c55f7d21f1f6cfaa539a3fc7b4c27a38f"},{"path":"core/crates/auths-verifier/src/approval.rs","sha256":"c3cae6a49e169051eb555bb092b1069a4d422516d6a2114623a89e5f31ff923f"},{"path":"core/crates/auths-verifier/src/causal.rs","sha256":"9635230f33b13a263573d319ac8a1976addbcc07677514a43e3c7bf28dc04587"},{"path":"core/crates/auths-verifier/src/lib.rs","sha256":"f22dec38dfa47ced8da4f605390da8453273bee1da010f57fd1fdfcb10e0b389"},{"path":"core/crates/auths-verifier/src/observation.rs","sha256":"0bb07f06a0f9524c88427df1c972b1de8ba038a9eeeb15d3134c25125ae84b1e"},{"path":"core/crates/auths-verifier/src/trace.rs","sha256":"2213d72023a1d9e0413a2cf2c51c3dad9e04775d86033a0caaa9d29a8f0036f8"},{"path":"exchange/crates/auths-proof-exchange-model/Cargo.toml","sha256":"34b2db64f93a288e942b5a3918d28cdcbef906e0dc9074ce848018d3d5f7a1fa"},{"path":"exchange/crates/auths-proof-exchange-model/src/lib.rs","sha256":"49fac5aff2339d3a57c41cb8bb2a82852538e8f77ecc4b157c88e264ff31fb55"},{"path":"exchange/crates/auths-proof-exchange-port/Cargo.toml","sha256":"7ff660f1b7579dc570c791090aeb450404fbbf44c92781e289f5ccdde746d739"},{"path":"exchange/crates/auths-proof-exchange-port/src/lib.rs","sha256":"b408fb40c6432edc1facb3d8b3e9433a033f8dc73fe2e0ba5a88c972ca675021"},{"path":"product/config/auths-config/Cargo.toml","sha256":"e4b568ab9f6d84f7d7e6d66443fe825f360db9c27bc7c31d6ddc0647ba3ab304"},{"path":"product/config/auths-config/src/lib.rs","sha256":"fecf00ea65cef9018fda9af2063326d7065b869266d0d9e73a4f06816f1102cc"},{"path":"product/errors/auths-errors/Cargo.toml","sha256":"3b3a199b6460ba75bda84475bb5accd35e1485448a3981038db85bf4772dd350"},{"path":"product/errors/auths-errors/src/lib.rs","sha256":"7feeb9069fa4003f94f1f07c1c94619cf1c883e0dbaaf2187f04d0f742264bdd"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/Cargo.toml","sha256":"716f1f2a117d6d69d8effe9ee9057e24ba3502f20af6a602b06facb638cdabed"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/api.rs","sha256":"9ea61dd7ddd93282b073b98e453e6b75b26dc49689c04e9782435d06a3a09e48"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/clock.rs","sha256":"73f0a6e0f5903883329fa6683f5888288f759512ac69e5c87efd2b6b87f7d79f"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/http.rs","sha256":"14c1fce14e24c984b2a275563a29b6326fb08367922b6e8d37ba38b9cb81aa2b"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/identity.rs","sha256":"186de11230c8b33375951c4368609f8976bf9795f171af3fd7fac26207a94361"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs","sha256":"0b4617d044f5254a5ab22f5a2578f91cc025206a8c1845be39c1c56dcdf7a5df"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/names.rs","sha256":"41bb23572d6002e23ee103d6fe70ecd68764861c6f2e48a1c53af998270a4afa"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs","sha256":"39fed883f4802e68d3b41a68fea0aba0737810996b33d13577de70faba004c29"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/store.rs","sha256":"fc60ee9c49b2f4f063c449b4c78100c5c4872779e94ca168f796603b380ef6e4"},{"path":"product/integrations/auths-custody/Cargo.toml","sha256":"1e14034185ad1ec24a977fd5f41d0abee219606245c046ce2a82287fadef448b"},{"path":"product/integrations/auths-custody/src/conformance.rs","sha256":"8ed1afd58f18fc6becc268908aa6419c9aa404c79da0197963eb2599df44acf6"},{"path":"product/integrations/auths-custody/src/key.rs","sha256":"70cbb0fd21b6f5652157845a22c35be2d0f6c05b3d138fc4b9bb6dbdc3d81c40"},{"path":"product/integrations/auths-custody/src/lib.rs","sha256":"8ee593c1f59b0fd2126bdda9138026f5bc531beb64d4489a99785842e7b98b43"},{"path":"product/operations/auths-operations/Cargo.toml","sha256":"73dde1e914ba5e1386f8d49c0d730423cc72ae77ec44c6554a6a75cc8e8922b1"},{"path":"product/operations/auths-operations/src/explanation.rs","sha256":"b4a39bcbd5712cb9e735ee7deeb281f3fa6af5ddca973735bf3d87dce427ef11"},{"path":"product/operations/auths-operations/src/lib.rs","sha256":"3f401a56555113b98f57bca172a2660eaecedf76247b83a3fdbb089c133a29cd"},{"path":"product/operations/auths-operations/src/render/json.rs","sha256":"2ae042639960afee123730e945d373bc5dda1d2b3af20ae16c939a7e99b9e418"},{"path":"product/operations/auths-operations/src/render/mod.rs","sha256":"b3b7f6fe473f49227ace5a68bfc3d8dc14b5db8dd9888fd9e207070337b1b8bf"},{"path":"product/operations/auths-operations/src/render/text.rs","sha256":"f216cf3bdb00e264523271b16e7059535ac6b1aabf271cebd7935af155e4bfec"},{"path":"product/policy/auths-bounded-policy/Cargo.toml","sha256":"babd5d200923137ead71d8c2528f847cea323ce98da942a1320b054436612c47"},{"path":"product/policy/auths-bounded-policy/src/arithmetic.rs","sha256":"75e43c5d4eab8d1f71c1daf53839f5f9fe45a400afc1f63a30c6f55ce3632627"},{"path":"product/policy/auths-bounded-policy/src/commitment.rs","sha256":"c5706f2d583454e1a7f570f7ada138d4d864bef0205dfae7c1296774f396bb3f"},{"path":"product/policy/auths-bounded-policy/src/eligibility.rs","sha256":"c9acdfb793074e687fc36efad506be27dbd99ffbf40387bc66c8de39ef238432"},{"path":"product/policy/auths-bounded-policy/src/identifier.rs","sha256":"0006a32bae9eb16c4178cf797df418d2b0a781f2bc6474b741dc1a908141831c"},{"path":"product/policy/auths-bounded-policy/src/kernel.rs","sha256":"99187c28b161ac70bee1afed60711f7f645adb4d1671a01863f9849b369811d5"},{"path":"product/policy/auths-bounded-policy/src/lib.rs","sha256":"76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c"},{"path":"product/policy/auths-bounded-policy/src/receipt.rs","sha256":"3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad"},{"path":"product/policy/auths-bounded-policy/src/registry.rs","sha256":"4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0"},{"path":"product/profiles/auths-profile-api/Cargo.toml","sha256":"7ae85761f58625b5d678f961fd052eebf3e000ef565c7312e3ac857763c0017f"},{"path":"product/profiles/auths-profile-api/src/lib.rs","sha256":"a194b82b20bf8aa864c2334ef6c6aec30b2154ded972862252d5dcefa488ab95"},{"path":"product/profiles/auths-profile-mcp/Cargo.toml","sha256":"db264fc25242f7b7e4133cbe5782545b3107b406c87168ae072683cfb59eac66"},{"path":"product/profiles/auths-profile-mcp/src/arguments.rs","sha256":"a5de696586d507e2aee4a49fee99ef1ef4c51a2e46603f8838f1af6d9009833f"},{"path":"product/profiles/auths-profile-mcp/src/lib.rs","sha256":"d0f8b733a09ef8408336cdebc8948d6a5861012ce6878598b11be7084dfd4280"},{"path":"product/profiles/auths-profile-mcp/src/session.rs","sha256":"166c281fa66333388e4760d6098dad02d3359e1d5de4b8f93312c014f97abb03"},{"path":"product/qualification/auths-recipe-qualification/Cargo.toml","sha256":"b7b15b30b9a3d96d4f089d514266d3a892de6608d30707aa44be31cca89ca9fe"},{"path":"product/qualification/auths-recipe-qualification/src/canonical.rs","sha256":"30a9b50777f0dcb4b606abfee2467d5a975d9f6ad941ab6c13ca3df5b359f667"},{"path":"product/qualification/auths-recipe-qualification/src/closure.rs","sha256":"0ad6aee9bd981e2863fa725f209ec84031db2ff12f4c7ac3aaf5120f0bb86039"},{"path":"product/qualification/auths-recipe-qualification/src/error.rs","sha256":"52d5cf720a1e4579008fdda90a3ac2c31f0b8db57985f121f65e54b4da2b7dd1"},{"path":"product/qualification/auths-recipe-qualification/src/evidence.rs","sha256":"1a4cb862f725b02f9efd827db99637ea8178a5236aa020ec271a363edbe7b362"},{"path":"product/qualification/auths-recipe-qualification/src/ids.rs","sha256":"e81a906d571497ab2da753e1532d4443706410e0b75fdd59a7d2d788c7aec403"},{"path":"product/qualification/auths-recipe-qualification/src/lib.rs","sha256":"195b19f46e1e94a0f3594ad5958e5715bc5e3ad415bdfe6428dfc1b6dd3f4631"},{"path":"product/qualification/auths-recipe-qualification/src/model.rs","sha256":"3484eb0ec287b23d4682ade7b1b0f8d1335985b3fb180f06fc28716076957d5f"},{"path":"product/qualification/auths-recipe-qualification/src/release.rs","sha256":"d816b53e2275e902c750ad03803061844e259e28560ab2d1c77e8a43981a4d6a"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/mod.rs","sha256":"7f15b68e05a04f202bcb1fb80de1d9a9a4fda8bfd6af2cd4e5c660fc75d96fe5"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/schemas.rs","sha256":"c59feec2805621f341a90f81fc005e2c12f7a70f9d264fdeacccb2be4fe1c046"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/verification.rs","sha256":"6a6b5834c5dae10af1ba8939b2deae43b85db71544dc8f077ff63b7fe68ac8a8"},{"path":"product/qualification/auths-recipe-qualification/src/verify.rs","sha256":"edd33589c54fb79bcfccc4cf4e6ccf95bbca088318bb7f8dfc27da684b4fa671"},{"path":"product/receipts/auths-receipts/Cargo.toml","sha256":"6001fa1375899953aafcb07c23a6da0c8f57ea7ec08bb9c950b12a60a8cc6f0f"},{"path":"product/receipts/auths-receipts/src/disclosure.rs","sha256":"ba9ed439be0a320c8a01f5b6e9b51361c1a37e076947490d8e4a484ba6bb119c"},{"path":"product/receipts/auths-receipts/src/lib.rs","sha256":"547a57c4160256719cafb7d0ab972d9fc80b0da14fbbce4148c70c414070ff36"},{"path":"product/runtime/auths-connections/Cargo.toml","sha256":"babeb6e1dda3dfb66291713ce1e43dce5c349833d0b50ea4dccbf986030026b2"},{"path":"product/runtime/auths-connections/src/credential.rs","sha256":"82921413bb053f0f6c7931fbd4e6a86c8cc1d8c6b51debd9c2cef33a8d5b1c51"},{"path":"product/runtime/auths-connections/src/kernel.rs","sha256":"a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8"},{"path":"product/runtime/auths-connections/src/lib.rs","sha256":"79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22"},{"path":"product/runtime/auths-connections/src/model.rs","sha256":"de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77"},{"path":"product/runtime/auths-connections/src/registry.rs","sha256":"e57640e003e72ad3235c567c2bb944a262bd64e673f023b62ea091094cc7e946"},{"path":"product/runtime/auths-gateway-kernel/Cargo.toml","sha256":"34f864e67656af4ac7e5c7a347a23f01fc8ab31365b8e23c0ef474483b14a183"},{"path":"product/runtime/auths-gateway-kernel/src/construct.rs","sha256":"e9d65744bae273d65face4285e5d2da75c06a92ab48f7b8333d496604e31c63c"},{"path":"product/runtime/auths-gateway-kernel/src/lib.rs","sha256":"cfda6f8453426564c085475f183b6f790b438768a19668f1b65d33ba59dc8632"},{"path":"product/runtime/auths-gateway-kernel/src/order.rs","sha256":"e0045f877c4b7fe3860c291039853885064ddcdebba7c9b345ab65e81e646dda"},{"path":"product/runtime/auths-gateway-kernel/src/outcome.rs","sha256":"e9785b1afe70788c89b51b18655bcd5acff7b0c8e3d12fb79c6f05a202e67e6b"},{"path":"product/runtime/auths-gateway-kernel/src/ratio.rs","sha256":"7ace22264812e6fc1ef3a62afee402cf43494bb71ae0d3de219ad1b39d690bcb"},{"path":"product/runtime/auths-gateway-kernel/src/recovery.rs","sha256":"9f46dcd1685ab6e4d1ba04a3fc286a9f3afee8fb47829be1fbc670a7926a2dc6"},{"path":"product/runtime/auths-gateway-kernel/src/transition.rs","sha256":"cefb8f01d915880f6921f2501ff881ad94b9de61072c34d9cd19220992f97374"},{"path":"product/runtime/auths-gateway/Cargo.toml","sha256":"00b28be86921dcdc0ad90cce0c62c2961cafefe96ea6c2edf0e926c3d405ccad"},{"path":"product/runtime/auths-gateway/src/admin.rs","sha256":"2d5cc67afac42fbd15f36e2d1693cd1b20cedacf775040dce6ffe04ccc94c9ea"},{"path":"product/runtime/auths-gateway/src/app.rs","sha256":"6f80f63833ea0815bb44fbf3b0cc54624a08e9fb578b035819f2980dc04e8256"},{"path":"product/runtime/auths-gateway/src/audit.rs","sha256":"0edb2037eb7b5d6f13acfce85c54f62a82bf7fdd31bc7e626c4fec183cef61dd"},{"path":"product/runtime/auths-gateway/src/audit_tests.rs","sha256":"990969384a52d75bc2489d9d412a9e7dd814bca1c8f65c701d6205fae62a15d5"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway-harness.rs","sha256":"12b0c24d36b2e6a3be392d3c081a783b355fdd67dc5b54bacc0410e803116b8c"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway.rs","sha256":"8851f5e95b70540f64c1965f6f240e7d90968817c6396d59cda49a75e46f85fc"},{"path":"product/runtime/auths-gateway/src/binding.rs","sha256":"663b0ce878319511aa7d05722ab4ab2fa9be18817884ffb2ee9f131ff1e382d1"},{"path":"product/runtime/auths-gateway/src/bounds.rs","sha256":"9cfa0eae4973e5e047a198360b22f041708fa20276b0b90c2ec440f06915d64b"},{"path":"product/runtime/auths-gateway/src/bounds_aggregate_tests.rs","sha256":"ab34f227b7c8692ba1da88ccb32bb3687a66adf8353d8282fae905d4a88eb612"},{"path":"product/runtime/auths-gateway/src/bounds_tests.rs","sha256":"74136bc570da7b9338b5a1a1ed9d3fd892c55135160964f9d3ac0e2cf5741375"},{"path":"product/runtime/auths-gateway/src/connection.rs","sha256":"7b5d049c258a26ed1c93ecf860f51d051a8a65f9b93554af0b1ea93862398ec9"},{"path":"product/runtime/auths-gateway/src/credential_journal.rs","sha256":"8e2b0733038d93ca5df770d27a870237e3b65664fa48da017d964a65bbbe25b8"},{"path":"product/runtime/auths-gateway/src/echo_verify.rs","sha256":"6d453051665f823abd7354d5c50031d9524cf47d6092d2f09080ae814e3b9575"},{"path":"product/runtime/auths-gateway/src/engine.rs","sha256":"5c04a836112d02677de66a1b79d7487fc95fcaac4a9dfc9e1044a6c19ea1282d"},{"path":"product/runtime/auths-gateway/src/fuzzing.rs","sha256":"ed3b0028487eb546a3b0a91d115aa8f18bcea324b61620bfe8e35a9e6ab18758"},{"path":"product/runtime/auths-gateway/src/generation_floor.rs","sha256":"fe1510ec96ce0f67e9a78edbfa94b33eb7df64c0ac4d0a67901124dcd0164777"},{"path":"product/runtime/auths-gateway/src/harness.rs","sha256":"c87e479f3eb281960f6c9c80d43c7560d7ccb654b0154ec823d3fcec4884ac05"},{"path":"product/runtime/auths-gateway/src/lib.rs","sha256":"b182052835a2cd631d1f801a74788d6ac1ef9cae21ade9ab4ffc270cd6f667ed"},{"path":"product/runtime/auths-gateway/src/listener.rs","sha256":"aa08239bcbc1fcb55e8a212fbdf6a84f12985b0d436dcb51dc58b06e59e435f2"},{"path":"product/runtime/auths-gateway/src/observed_tests.rs","sha256":"a22be071695f89ca2578a4d82fd80d9cb82289213c9bdb8f0470f6b2dc3d9201"},{"path":"product/runtime/auths-gateway/src/observer.rs","sha256":"562ffcaea071c3856e0708dc2fe33516917e145d2438aabb75af0a2b6ba01046"},{"path":"product/runtime/auths-gateway/src/onboarding.rs","sha256":"0dfd7d67e7f02f18a28d1c86ca1b7751d7463f5efcdbe3825de0ad8cbccb3891"},{"path":"product/runtime/auths-gateway/src/operator.rs","sha256":"c3c36954a3e86723df035b47f43b85fc8ab3a6292983522b6258d5c6b4e6c4e4"},{"path":"product/runtime/auths-gateway/src/pending_vectors/attempts.rs","sha256":"47ef3c8cb1c5504d47ae9a0088705ce6715fe86bac1671a34a56fb38a64d0dd3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/bounds.rs","sha256":"e612217307e1da5b0eb5ee6582a7458bb064b8aa8a529fc6555b1b334127ab68"},{"path":"product/runtime/auths-gateway/src/pending_vectors/codes.rs","sha256":"e00670a5ef24eb856cc2c6dcda8e5a263842f55c76bb939c0c27bd9df37e5522"},{"path":"product/runtime/auths-gateway/src/pending_vectors/keys.rs","sha256":"f84c56f2ea9cb34b2b79c72d13fbf2c6585010ec1ed450af58a78c80c1ea1edd"},{"path":"product/runtime/auths-gateway/src/pending_vectors/mod.rs","sha256":"5de8340f0ef71a0b57a09e323fefe473d3160c6ae952b9ba46f714825fbacafc"},{"path":"product/runtime/auths-gateway/src/pending_vectors/outcomes.rs","sha256":"8ec07b9511b48913af36ac999d2aa0e82924289f6acb23ddaeb9f00f99815166"},{"path":"product/runtime/auths-gateway/src/pending_vectors/production.rs","sha256":"f574cabfa4687a4fc846b8f6a234b68ec53b876aed548b11445729cac1a55ede"},{"path":"product/runtime/auths-gateway/src/pending_vectors/recipes.rs","sha256":"51693208270231c25c3aef2a32151d5962114c71e86b88cb9df83181c7af83d9"},{"path":"product/runtime/auths-gateway/src/pre_entry.rs","sha256":"06ea78ca140468bfaba17d9ab04912ad68673954c3203c98fed28272ff2a00c0"},{"path":"product/runtime/auths-gateway/src/property_tests.rs","sha256":"939c081e2e154aaf10186754044bdd65608932c899b970a04a71d0afaa999a93"},{"path":"product/runtime/auths-gateway/src/qualification.rs","sha256":"d5078a81dc89f30958a7d8fdabfe164c3411c441dd7d9015002681a58883b63a"},{"path":"product/runtime/auths-gateway/src/qualification_tests.rs","sha256":"4473add5729b97faf04d7be7fd8cf3bbacd7f545e1b61c7d2782563011906b4d"},{"path":"product/runtime/auths-gateway/src/quorum_tests.rs","sha256":"a78380b019104d688c11a4410082c7e08ded3106aab099954c4f8a1b4ae0fd89"},{"path":"product/runtime/auths-gateway/src/readiness.rs","sha256":"911c3f11892f94641574375e2da4c671c802738f71082f12c39832331052d43d"},{"path":"product/runtime/auths-gateway/src/recipe.rs","sha256":"fecf9af67e7afc48d080e9f8f55f8ce28e49d0e08988717a27908bbda461d6b6"},{"path":"product/runtime/auths-gateway/src/recipe/lower.rs","sha256":"8088b8751ed831dbb48247af953c6290ac95e2a438ccd5bd65eff54be06a1fd1"},{"path":"product/runtime/auths-gateway/src/recipe/review.rs","sha256":"c3eb7d9fdd98dacf52750b14b67ad7b7faaecbbdeafff1e0b049f67d0a2d0139"},{"path":"product/runtime/auths-gateway/src/recipe/runtime.rs","sha256":"c286f0d15f974402822c0810d8e97f98411dc1c557755cc23e540d85e2bb42d9"},{"path":"product/runtime/auths-gateway/src/recipe/source.rs","sha256":"1af50298fb1461e1b24cbdf560d43124d6b1c4c529586c911b1c4797214a69ff"},{"path":"product/runtime/auths-gateway/src/recipe/tests.rs","sha256":"aac551a2481bbc60864c64079bc667dcb232e45a0f41a04073ed84ab5dbe1fce"},{"path":"product/runtime/auths-gateway/src/recipe/validate.rs","sha256":"3711b17605cb7b0d639bc1b180449231f5882a306cab20e2c7782155cc63b0d4"},{"path":"product/runtime/auths-gateway/src/scenario_tests.rs","sha256":"d8271761b12597bfe1233f8eb5ad1d4e5498c5d03388e832e24ab818484a1de4"},{"path":"product/runtime/auths-gateway/src/separation.rs","sha256":"be9306848ca5d801767cf6aa14247c8618312ef0e202f00ce0c24c4844491061"},{"path":"product/runtime/auths-gateway/src/store.rs","sha256":"1e5288345c2cb1421aeda277b3158d07607404b0ec46943222ac107b63dcbb46"},{"path":"product/runtime/auths-gateway/src/store_testkit.rs","sha256":"88d82fee42f1b8ef521e8deef0216e938ebeaad822eb2f5020e70b89d145ea70"},{"path":"product/runtime/auths-gateway/src/submit.rs","sha256":"c78dbbba7c45b443febf655056c5edcd635e77be7b21c5b2c318097502415ffe"},{"path":"product/runtime/auths-gateway/src/support.rs","sha256":"9fd979029793a22b15d9776a7fc172476fd7c126a80d4080c65d720845becbcb"},{"path":"product/runtime/auths-gateway/src/transport.rs","sha256":"be2c6dc75b8daec110bf8749fedc3823f6067d40b999aa3eb21126896a97d3ad"},{"path":"product/runtime/auths-kernel-runtime/Cargo.toml","sha256":"926bcd0053e5edd703be8f0027ad009e2982db013c8174c1366edbf38b48087d"},{"path":"product/runtime/auths-kernel-runtime/src/lib.rs","sha256":"7108faae9ca4bc32dc093ddaf885ac8f74f3c9b8d317b7c7d0ed00d1d0ab5972"},{"path":"product/runtime/auths-lifecycle/Cargo.toml","sha256":"c5053c705f8d5554b44e432fe75287a2faf11d644e5a2552e45ad6cd94176af5"},{"path":"product/runtime/auths-lifecycle/src/codec.rs","sha256":"51c4b746749150e8bfcd8ff972b3f6c1ef40bec15583448ec1b471d9ad737dc0"},{"path":"product/runtime/auths-lifecycle/src/digest.rs","sha256":"55282cd7d8aba37713c2dcb5357c9877819edb72a30eadefb860d28d7d3a3eb7"},{"path":"product/runtime/auths-lifecycle/src/identifier.rs","sha256":"31620e8c16de68d3d2d3b84d6353c1a5b9d4151d8247f91fa389b906a8e660f1"},{"path":"product/runtime/auths-lifecycle/src/kernel.rs","sha256":"2abb8c094b36d35b364e74d78091d14c5d6f3d1eb6552cca3b5538dbd017ce23"},{"path":"product/runtime/auths-lifecycle/src/lib.rs","sha256":"afe5a345cd309b5a4f08ffba3170a6d7f16ff914892b3f2006d5208ed24ec736"},{"path":"product/runtime/auths-lifecycle/src/model.rs","sha256":"1af12bbeeeaa65ec02ddcebd7d2c8c92ec1e339fa40ae85b45ab9b01a722a4fa"},{"path":"product/runtime/auths-lifecycle/src/operation.rs","sha256":"78e6d05fcf5d7ea4f148032a3fa26fdfcab77eb346019effe927b08e0d64d732"},{"path":"product/runtime/auths-lifecycle/src/registry.rs","sha256":"53495fe6f7a77422593a41623e28716f1c140dcc1e00f87f6b0ffbfb93a5ef90"},{"path":"product/runtime/auths-lifecycle/src/sealed.rs","sha256":"2e0c03b5813c926c159598bb7890d1523825edbe57cd687d42a5dfb3374a0c19"},{"path":"product/runtime/auths-lifecycle/src/test_support.rs","sha256":"221d9a5c5ef8e1f9f8fd66927484eaf813571d0568470278ecd8fa08a5eec8cd"},{"path":"product/runtime/auths-lifecycle/src/transition.rs","sha256":"011805a28efdd541f44ccea54dd0e34a1e58f4004447ee58013703b4fb6b2822"},{"path":"product/runtime/auths-runtime/Cargo.toml","sha256":"dd29d80a8b4bb56c869f036a6c9998f6e6d1c0383ac5dc03fa42b24abe2a7ff7"},{"path":"product/runtime/auths-runtime/src/lib.rs","sha256":"132ca03d58c14905d3a822a4972f42a22a5ad33a45f2ba9ca44f3a57d810b4b0"},{"path":"product/runtime/auths-runtime/src/production.rs","sha256":"fd4eff4270c571c10fcff6cf27df28961ebf074de8a1a028f500fda1ca376820"},{"path":"product/sdk/auths-approval-quorum/Cargo.toml","sha256":"df904971fca87a24194c5816738a331588fe8f164acb5d70839a35dca5f57114"},{"path":"product/sdk/auths-approval-quorum/src/lib.rs","sha256":"72e4086088a1c0912e4e1a9e980f26a5c280bf5ab16ea39c9f0f58d5096ac2ce"},{"path":"product/sdk/auths-approval-quorum/src/remote.rs","sha256":"9fa029c7c63003adf260f8aec55160c545681c60c1bace0d934e7525862aac7b"},{"path":"product/sdk/auths-approval-quorum/src/remote_tests.rs","sha256":"8a09ce17cfee82a035a74edd535f3ebeb3db0e078784740d3997b17dbdb10197"},{"path":"product/sdk/auths-approval-quorum/src/tests.rs","sha256":"0acbf12be3e497dcc6c2d8f29c9af3b1a7ed8e11b75f6399570d4f217a785060"},{"path":"product/stores/auths-stores/Cargo.toml","sha256":"a32c4b76d17b264be5d40d24497ff237e1ed87822e8bab86229b3db93106dbe3"},{"path":"product/stores/auths-stores/src/gateway_attempt.rs","sha256":"185da8f4a220fba836d5b78a9311f03204681c43a3c53951008084d135bf4d21"},{"path":"product/stores/auths-stores/src/lib.rs","sha256":"e721262edf8a9ab5568ddc27639176312d4a366203b5f73e2d7c11fde2c554e9"},{"path":"product/stores/auths-stores/src/lifecycle.rs","sha256":"94f64d25bc178a9e60ba3c0ee6915d7fb3af7c4468792d76b4e70f43f4de1e2f"}],"schema":"auths.gateway-semantic-closure/1"} \ No newline at end of file +{"files":[{"path":"Cargo.lock","sha256":"c94ed342774d5e2823f01ecf74b8a4812c5f9a6b0cf811d31f2e2cecb671a275"},{"path":"Cargo.toml","sha256":"6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24"},{"path":"core/adapters/auths-did-keri/Cargo.toml","sha256":"86ba3e3f9a0a70d970568bfb3113b7ba7bbdd81c3eebbb52743dd574a0c0ecaa"},{"path":"core/adapters/auths-did-keri/src/lib.rs","sha256":"a75674842f8a7142004369ccd206ab43e476459293f0ff4bed4d4e659031b3e3"},{"path":"core/adapters/auths-did-key/Cargo.toml","sha256":"d5a3ae07ecde83f91eed4c3785051dd0f44eab6c891754f3309b6b40596707d7"},{"path":"core/adapters/auths-did-key/src/lib.rs","sha256":"b76a3f4528a725df53cfa9242e6e414e1d26caa48468aaed497e28b121f4497c"},{"path":"core/adapters/auths-raw-key/Cargo.toml","sha256":"f49616bc18c19e6aaa7e6a02ccebcdb9f5c1422c1278ef9869e0dbf22ceda7be"},{"path":"core/adapters/auths-raw-key/src/lib.rs","sha256":"45eec1b295dac3bed65cd79c942870b926b06b3f5d38eaebaeb6140ac69315fa"},{"path":"core/crates/auths-algebra-kernel/Cargo.toml","sha256":"0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba"},{"path":"core/crates/auths-algebra-kernel/src/generated.rs","sha256":"ae4bcbef42a408c7ffa0c6a74a42f7de177a6f14479e51d205acf830bda05960"},{"path":"core/crates/auths-algebra-kernel/src/lib.rs","sha256":"6654667eeb9b353d6648954c9fd2e8838462a82ce6b2803eb49e1366892c68c6"},{"path":"core/crates/auths-assurance/Cargo.toml","sha256":"afcb12a97ddd09d7a264b9ecd3fcaefc865ff2c9b4539ee85b00883420ba333a"},{"path":"core/crates/auths-assurance/src/lib.rs","sha256":"0fb2ec844d674b25a9e20b1601452c89c2454901fa506adfa9bb38ef9a7fa213"},{"path":"core/crates/auths-author/Cargo.toml","sha256":"1e6f0e3bc079ddb558decf0db26b291c6e72fc47327b6df1b7650d41689b215f"},{"path":"core/crates/auths-author/src/lib.rs","sha256":"e14475f2f49715a1869d5fa6b11ff1fbb72497e39097e09f833b0bae7e5b3f2b"},{"path":"core/crates/auths-author/src/observations.rs","sha256":"dda7d6bfa6f4bd7e95a480ca283c2c0e996f69c5c15cb0c7197af328131a7066"},{"path":"core/crates/auths-authority/Cargo.toml","sha256":"4f68212938029f79ebd857b4f3038494eb85d0163d49f07e51376715cf959815"},{"path":"core/crates/auths-authority/src/lib.rs","sha256":"da88d5194de4e17449e69972c0fb042afa3c39798a8f570f30771e77c384f1eb"},{"path":"core/crates/auths-codec/Cargo.toml","sha256":"e20e51826e17814effd9d8925d18d5fbdd6c0d37bf50231e743ec2611314722c"},{"path":"core/crates/auths-codec/src/approval.rs","sha256":"fbff43bf4d57f69f8b7738a8647751cde75c5a932dee65d924a1fe9c7202f91f"},{"path":"core/crates/auths-codec/src/bounded_policy.rs","sha256":"d21f6728be2d8a04b6d94921f2b683f7e61cbb42e0ac6866f1c88a49caa534c3"},{"path":"core/crates/auths-codec/src/decode.rs","sha256":"ba2999584cdf53b1b517ecb9c7ea50d39efee17c666a9a38e2ad1ac94379f778"},{"path":"core/crates/auths-codec/src/encode.rs","sha256":"8491192053e2e15d62b4d2a491de22405b7487ead69ab6f6bca40669ce7ca5f7"},{"path":"core/crates/auths-codec/src/error.rs","sha256":"fecb0737c16deb42d859f1dc7727c698438d9ac12064fd99e0024629642c390c"},{"path":"core/crates/auths-codec/src/hash.rs","sha256":"f88e111f1dbb2cef6b7b5e9c948cb45ff92e366710c8a5f5c636138aa748479e"},{"path":"core/crates/auths-codec/src/lib.rs","sha256":"3b0e5c94c6f34f750b88a9333e1d5c8145746d845d3a23e0d2f61807cf592ea7"},{"path":"core/crates/auths-codec/src/observation.rs","sha256":"38328b0c71ff97a4196eeade8b4faa889527ff1f80bb168468bcd49082a3987e"},{"path":"core/crates/auths-composition/Cargo.toml","sha256":"331e13025eb82588b5269ed3975929eb41c823d588c49e4c296273d85c6fe80e"},{"path":"core/crates/auths-composition/src/lib.rs","sha256":"e42e3b0b6a9985b73c533aeb23799c638979aa27a9ce7d0f10a8d60340570fb1"},{"path":"core/crates/auths-model/Cargo.toml","sha256":"565c15302b0cc9270db1e28efa3862804846850ba933cc17aea8abcec4a65987"},{"path":"core/crates/auths-model/src/approval.rs","sha256":"54cf44a9ef747ec21546a4086aecfb130bc7803b0d646430e6082df51e6e305f"},{"path":"core/crates/auths-model/src/bounded.rs","sha256":"f90496abc0a06c028b4d850af6ddab7d850bfafeaa3d042f1b1246a41d8bbbc9"},{"path":"core/crates/auths-model/src/bounded_policy.rs","sha256":"306a8f049cc7cfc7635fe0e4de47eb7813eed63d3c14c3be2b51586aa4eea450"},{"path":"core/crates/auths-model/src/lib.rs","sha256":"e7cfe6bb9574c6b016aa63e70658c31e0b90903ec6479a49f4a2ceb64f5bad97"},{"path":"core/crates/auths-model/src/observation.rs","sha256":"b3ed3e3cc090afca2896a7d3de7988afccc1ee1ea0ebd91b51a8bc0f20ad8dbb"},{"path":"core/crates/auths-multikey/Cargo.toml","sha256":"858756c1197befcada06134742bffe8d58cf674cadd6c046bf710570e96efaf2"},{"path":"core/crates/auths-multikey/src/lib.rs","sha256":"f5177fffb11e40eeaaa665ba886c541fc1f24d5eacdd6983fb03dc20148733f0"},{"path":"core/crates/auths-ports/Cargo.toml","sha256":"596a9b0f5af3717c16a6d13f7054d8a106bcd9f01f5f72c2235dd2afcf0ab16c"},{"path":"core/crates/auths-ports/src/binding.rs","sha256":"a16c012d40aa4249e3ec54372b9611006d0bfe8c7dc3c741911c2194ad17736d"},{"path":"core/crates/auths-ports/src/diagnostics.rs","sha256":"aa596572503b5a65a918bb2ff38281c144ff53821ee914e9325c852828d852df"},{"path":"core/crates/auths-ports/src/lib.rs","sha256":"8da1debf86f9532df0660155d04298beb1ba3a1204508f8586e2e67cd2fb3449"},{"path":"core/crates/auths-ports/src/path.rs","sha256":"b68fc547b4e4d97a60cbbc1cc1939fc6b34a8233b81f840bd396914a707e3ea1"},{"path":"core/crates/auths-raw-key-core/Cargo.toml","sha256":"98c0bc8527a537512e43a74dd6ba9658c6f0cdc16610cf938e3f9b43785d836d"},{"path":"core/crates/auths-raw-key-core/src/lib.rs","sha256":"98c0500c41697aae28708ad0bf970b9a97583d96a3d2c18d23e7fa351e0f7d12"},{"path":"core/crates/auths-registries/Cargo.toml","sha256":"590e49e58b0622d9d6274fea46796dcdb07dec9550eff295cce6a6427ffa51e2"},{"path":"core/crates/auths-registries/src/lib.rs","sha256":"450d3886d85ee333b7e046317fb5b47cde62483d5f3e41d46265e2caf4c373ec"},{"path":"core/crates/auths-registries/src/template.rs","sha256":"1224039dd2b3ce6fa8357613d8cafbae40400493da7176da202b9ade62fa05e4"},{"path":"core/crates/auths-signature-core/Cargo.toml","sha256":"6bee2230eb30af1be0bd5c2d57bd3e1903497a70028d47290d4ac6e9e0e8bca0"},{"path":"core/crates/auths-signature-core/src/lib.rs","sha256":"6e3f9311ded5e49ea50d445eb21e6d8fa12442aa4362a73e0cb6fda15b7cd865"},{"path":"core/crates/auths-signature/Cargo.toml","sha256":"7f7b5682466ba439d8c59579022cb61068cad9fb4bd2d73e1cc21327c902b450"},{"path":"core/crates/auths-signature/src/lib.rs","sha256":"b3d9ac4cc3ba0797b9e1c09f2d6ac05089b25dac4e285a5af28c0165b33d925b"},{"path":"core/crates/auths-verifier/Cargo.toml","sha256":"c43358e06a33324b41a8b93e5cc7279c55f7d21f1f6cfaa539a3fc7b4c27a38f"},{"path":"core/crates/auths-verifier/src/approval.rs","sha256":"c3cae6a49e169051eb555bb092b1069a4d422516d6a2114623a89e5f31ff923f"},{"path":"core/crates/auths-verifier/src/causal.rs","sha256":"9635230f33b13a263573d319ac8a1976addbcc07677514a43e3c7bf28dc04587"},{"path":"core/crates/auths-verifier/src/lib.rs","sha256":"f22dec38dfa47ced8da4f605390da8453273bee1da010f57fd1fdfcb10e0b389"},{"path":"core/crates/auths-verifier/src/observation.rs","sha256":"0bb07f06a0f9524c88427df1c972b1de8ba038a9eeeb15d3134c25125ae84b1e"},{"path":"core/crates/auths-verifier/src/trace.rs","sha256":"2213d72023a1d9e0413a2cf2c51c3dad9e04775d86033a0caaa9d29a8f0036f8"},{"path":"exchange/crates/auths-proof-exchange-model/Cargo.toml","sha256":"34b2db64f93a288e942b5a3918d28cdcbef906e0dc9074ce848018d3d5f7a1fa"},{"path":"exchange/crates/auths-proof-exchange-model/src/lib.rs","sha256":"49fac5aff2339d3a57c41cb8bb2a82852538e8f77ecc4b157c88e264ff31fb55"},{"path":"exchange/crates/auths-proof-exchange-port/Cargo.toml","sha256":"7ff660f1b7579dc570c791090aeb450404fbbf44c92781e289f5ccdde746d739"},{"path":"exchange/crates/auths-proof-exchange-port/src/lib.rs","sha256":"b408fb40c6432edc1facb3d8b3e9433a033f8dc73fe2e0ba5a88c972ca675021"},{"path":"product/config/auths-config/Cargo.toml","sha256":"e4b568ab9f6d84f7d7e6d66443fe825f360db9c27bc7c31d6ddc0647ba3ab304"},{"path":"product/config/auths-config/src/lib.rs","sha256":"fecf00ea65cef9018fda9af2063326d7065b869266d0d9e73a4f06816f1102cc"},{"path":"product/errors/auths-errors/Cargo.toml","sha256":"3b3a199b6460ba75bda84475bb5accd35e1485448a3981038db85bf4772dd350"},{"path":"product/errors/auths-errors/src/lib.rs","sha256":"7feeb9069fa4003f94f1f07c1c94619cf1c883e0dbaaf2187f04d0f742264bdd"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/Cargo.toml","sha256":"716f1f2a117d6d69d8effe9ee9057e24ba3502f20af6a602b06facb638cdabed"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/api.rs","sha256":"9ea61dd7ddd93282b073b98e453e6b75b26dc49689c04e9782435d06a3a09e48"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/clock.rs","sha256":"73f0a6e0f5903883329fa6683f5888288f759512ac69e5c87efd2b6b87f7d79f"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/http.rs","sha256":"14c1fce14e24c984b2a275563a29b6326fb08367922b6e8d37ba38b9cb81aa2b"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/identity.rs","sha256":"186de11230c8b33375951c4368609f8976bf9795f171af3fd7fac26207a94361"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs","sha256":"0b4617d044f5254a5ab22f5a2578f91cc025206a8c1845be39c1c56dcdf7a5df"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/names.rs","sha256":"41bb23572d6002e23ee103d6fe70ecd68764861c6f2e48a1c53af998270a4afa"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs","sha256":"39fed883f4802e68d3b41a68fea0aba0737810996b33d13577de70faba004c29"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/store.rs","sha256":"fc60ee9c49b2f4f063c449b4c78100c5c4872779e94ca168f796603b380ef6e4"},{"path":"product/integrations/auths-custody/Cargo.toml","sha256":"1e14034185ad1ec24a977fd5f41d0abee219606245c046ce2a82287fadef448b"},{"path":"product/integrations/auths-custody/src/conformance.rs","sha256":"8ed1afd58f18fc6becc268908aa6419c9aa404c79da0197963eb2599df44acf6"},{"path":"product/integrations/auths-custody/src/key.rs","sha256":"70cbb0fd21b6f5652157845a22c35be2d0f6c05b3d138fc4b9bb6dbdc3d81c40"},{"path":"product/integrations/auths-custody/src/lib.rs","sha256":"8ee593c1f59b0fd2126bdda9138026f5bc531beb64d4489a99785842e7b98b43"},{"path":"product/operations/auths-operations/Cargo.toml","sha256":"73dde1e914ba5e1386f8d49c0d730423cc72ae77ec44c6554a6a75cc8e8922b1"},{"path":"product/operations/auths-operations/src/explanation.rs","sha256":"b4a39bcbd5712cb9e735ee7deeb281f3fa6af5ddca973735bf3d87dce427ef11"},{"path":"product/operations/auths-operations/src/lib.rs","sha256":"3f401a56555113b98f57bca172a2660eaecedf76247b83a3fdbb089c133a29cd"},{"path":"product/operations/auths-operations/src/render/json.rs","sha256":"2ae042639960afee123730e945d373bc5dda1d2b3af20ae16c939a7e99b9e418"},{"path":"product/operations/auths-operations/src/render/mod.rs","sha256":"b3b7f6fe473f49227ace5a68bfc3d8dc14b5db8dd9888fd9e207070337b1b8bf"},{"path":"product/operations/auths-operations/src/render/text.rs","sha256":"f216cf3bdb00e264523271b16e7059535ac6b1aabf271cebd7935af155e4bfec"},{"path":"product/policy/auths-bounded-policy/Cargo.toml","sha256":"babd5d200923137ead71d8c2528f847cea323ce98da942a1320b054436612c47"},{"path":"product/policy/auths-bounded-policy/src/arithmetic.rs","sha256":"75e43c5d4eab8d1f71c1daf53839f5f9fe45a400afc1f63a30c6f55ce3632627"},{"path":"product/policy/auths-bounded-policy/src/commitment.rs","sha256":"c5706f2d583454e1a7f570f7ada138d4d864bef0205dfae7c1296774f396bb3f"},{"path":"product/policy/auths-bounded-policy/src/eligibility.rs","sha256":"c9acdfb793074e687fc36efad506be27dbd99ffbf40387bc66c8de39ef238432"},{"path":"product/policy/auths-bounded-policy/src/identifier.rs","sha256":"0006a32bae9eb16c4178cf797df418d2b0a781f2bc6474b741dc1a908141831c"},{"path":"product/policy/auths-bounded-policy/src/kernel.rs","sha256":"99187c28b161ac70bee1afed60711f7f645adb4d1671a01863f9849b369811d5"},{"path":"product/policy/auths-bounded-policy/src/lib.rs","sha256":"76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c"},{"path":"product/policy/auths-bounded-policy/src/receipt.rs","sha256":"3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad"},{"path":"product/policy/auths-bounded-policy/src/registry.rs","sha256":"4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0"},{"path":"product/profiles/auths-profile-api/Cargo.toml","sha256":"7ae85761f58625b5d678f961fd052eebf3e000ef565c7312e3ac857763c0017f"},{"path":"product/profiles/auths-profile-api/src/lib.rs","sha256":"a194b82b20bf8aa864c2334ef6c6aec30b2154ded972862252d5dcefa488ab95"},{"path":"product/profiles/auths-profile-mcp/Cargo.toml","sha256":"db264fc25242f7b7e4133cbe5782545b3107b406c87168ae072683cfb59eac66"},{"path":"product/profiles/auths-profile-mcp/src/arguments.rs","sha256":"a5de696586d507e2aee4a49fee99ef1ef4c51a2e46603f8838f1af6d9009833f"},{"path":"product/profiles/auths-profile-mcp/src/lib.rs","sha256":"d0f8b733a09ef8408336cdebc8948d6a5861012ce6878598b11be7084dfd4280"},{"path":"product/profiles/auths-profile-mcp/src/session.rs","sha256":"166c281fa66333388e4760d6098dad02d3359e1d5de4b8f93312c014f97abb03"},{"path":"product/qualification/auths-recipe-qualification/Cargo.toml","sha256":"b7b15b30b9a3d96d4f089d514266d3a892de6608d30707aa44be31cca89ca9fe"},{"path":"product/qualification/auths-recipe-qualification/src/canonical.rs","sha256":"30a9b50777f0dcb4b606abfee2467d5a975d9f6ad941ab6c13ca3df5b359f667"},{"path":"product/qualification/auths-recipe-qualification/src/closure.rs","sha256":"0ad6aee9bd981e2863fa725f209ec84031db2ff12f4c7ac3aaf5120f0bb86039"},{"path":"product/qualification/auths-recipe-qualification/src/error.rs","sha256":"52d5cf720a1e4579008fdda90a3ac2c31f0b8db57985f121f65e54b4da2b7dd1"},{"path":"product/qualification/auths-recipe-qualification/src/evidence.rs","sha256":"1a4cb862f725b02f9efd827db99637ea8178a5236aa020ec271a363edbe7b362"},{"path":"product/qualification/auths-recipe-qualification/src/ids.rs","sha256":"e81a906d571497ab2da753e1532d4443706410e0b75fdd59a7d2d788c7aec403"},{"path":"product/qualification/auths-recipe-qualification/src/lib.rs","sha256":"195b19f46e1e94a0f3594ad5958e5715bc5e3ad415bdfe6428dfc1b6dd3f4631"},{"path":"product/qualification/auths-recipe-qualification/src/model.rs","sha256":"3484eb0ec287b23d4682ade7b1b0f8d1335985b3fb180f06fc28716076957d5f"},{"path":"product/qualification/auths-recipe-qualification/src/release.rs","sha256":"d816b53e2275e902c750ad03803061844e259e28560ab2d1c77e8a43981a4d6a"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/mod.rs","sha256":"7f15b68e05a04f202bcb1fb80de1d9a9a4fda8bfd6af2cd4e5c660fc75d96fe5"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/schemas.rs","sha256":"c59feec2805621f341a90f81fc005e2c12f7a70f9d264fdeacccb2be4fe1c046"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/verification.rs","sha256":"6a6b5834c5dae10af1ba8939b2deae43b85db71544dc8f077ff63b7fe68ac8a8"},{"path":"product/qualification/auths-recipe-qualification/src/verify.rs","sha256":"edd33589c54fb79bcfccc4cf4e6ccf95bbca088318bb7f8dfc27da684b4fa671"},{"path":"product/receipts/auths-receipts/Cargo.toml","sha256":"6001fa1375899953aafcb07c23a6da0c8f57ea7ec08bb9c950b12a60a8cc6f0f"},{"path":"product/receipts/auths-receipts/src/disclosure.rs","sha256":"ba9ed439be0a320c8a01f5b6e9b51361c1a37e076947490d8e4a484ba6bb119c"},{"path":"product/receipts/auths-receipts/src/lib.rs","sha256":"547a57c4160256719cafb7d0ab972d9fc80b0da14fbbce4148c70c414070ff36"},{"path":"product/runtime/auths-connections/Cargo.toml","sha256":"babeb6e1dda3dfb66291713ce1e43dce5c349833d0b50ea4dccbf986030026b2"},{"path":"product/runtime/auths-connections/src/credential.rs","sha256":"82921413bb053f0f6c7931fbd4e6a86c8cc1d8c6b51debd9c2cef33a8d5b1c51"},{"path":"product/runtime/auths-connections/src/kernel.rs","sha256":"a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8"},{"path":"product/runtime/auths-connections/src/lib.rs","sha256":"79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22"},{"path":"product/runtime/auths-connections/src/model.rs","sha256":"de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77"},{"path":"product/runtime/auths-connections/src/registry.rs","sha256":"e57640e003e72ad3235c567c2bb944a262bd64e673f023b62ea091094cc7e946"},{"path":"product/runtime/auths-gateway-kernel/Cargo.toml","sha256":"34f864e67656af4ac7e5c7a347a23f01fc8ab31365b8e23c0ef474483b14a183"},{"path":"product/runtime/auths-gateway-kernel/src/construct.rs","sha256":"e9d65744bae273d65face4285e5d2da75c06a92ab48f7b8333d496604e31c63c"},{"path":"product/runtime/auths-gateway-kernel/src/lib.rs","sha256":"cfda6f8453426564c085475f183b6f790b438768a19668f1b65d33ba59dc8632"},{"path":"product/runtime/auths-gateway-kernel/src/order.rs","sha256":"e0045f877c4b7fe3860c291039853885064ddcdebba7c9b345ab65e81e646dda"},{"path":"product/runtime/auths-gateway-kernel/src/outcome.rs","sha256":"e9785b1afe70788c89b51b18655bcd5acff7b0c8e3d12fb79c6f05a202e67e6b"},{"path":"product/runtime/auths-gateway-kernel/src/ratio.rs","sha256":"7ace22264812e6fc1ef3a62afee402cf43494bb71ae0d3de219ad1b39d690bcb"},{"path":"product/runtime/auths-gateway-kernel/src/recovery.rs","sha256":"9f46dcd1685ab6e4d1ba04a3fc286a9f3afee8fb47829be1fbc670a7926a2dc6"},{"path":"product/runtime/auths-gateway-kernel/src/transition.rs","sha256":"cefb8f01d915880f6921f2501ff881ad94b9de61072c34d9cd19220992f97374"},{"path":"product/runtime/auths-gateway/Cargo.toml","sha256":"00b28be86921dcdc0ad90cce0c62c2961cafefe96ea6c2edf0e926c3d405ccad"},{"path":"product/runtime/auths-gateway/src/admin.rs","sha256":"2d5cc67afac42fbd15f36e2d1693cd1b20cedacf775040dce6ffe04ccc94c9ea"},{"path":"product/runtime/auths-gateway/src/app.rs","sha256":"6f80f63833ea0815bb44fbf3b0cc54624a08e9fb578b035819f2980dc04e8256"},{"path":"product/runtime/auths-gateway/src/audit.rs","sha256":"0edb2037eb7b5d6f13acfce85c54f62a82bf7fdd31bc7e626c4fec183cef61dd"},{"path":"product/runtime/auths-gateway/src/audit_tests.rs","sha256":"990969384a52d75bc2489d9d412a9e7dd814bca1c8f65c701d6205fae62a15d5"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway-harness.rs","sha256":"12b0c24d36b2e6a3be392d3c081a783b355fdd67dc5b54bacc0410e803116b8c"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway.rs","sha256":"8851f5e95b70540f64c1965f6f240e7d90968817c6396d59cda49a75e46f85fc"},{"path":"product/runtime/auths-gateway/src/binding.rs","sha256":"663b0ce878319511aa7d05722ab4ab2fa9be18817884ffb2ee9f131ff1e382d1"},{"path":"product/runtime/auths-gateway/src/bounds.rs","sha256":"9cfa0eae4973e5e047a198360b22f041708fa20276b0b90c2ec440f06915d64b"},{"path":"product/runtime/auths-gateway/src/bounds_aggregate_tests.rs","sha256":"ab34f227b7c8692ba1da88ccb32bb3687a66adf8353d8282fae905d4a88eb612"},{"path":"product/runtime/auths-gateway/src/bounds_tests.rs","sha256":"74136bc570da7b9338b5a1a1ed9d3fd892c55135160964f9d3ac0e2cf5741375"},{"path":"product/runtime/auths-gateway/src/connection.rs","sha256":"7b5d049c258a26ed1c93ecf860f51d051a8a65f9b93554af0b1ea93862398ec9"},{"path":"product/runtime/auths-gateway/src/credential_journal.rs","sha256":"7297fccaee5cd8622928e8e0a42bba50da7941970a6f682ecd300c41ee6509da"},{"path":"product/runtime/auths-gateway/src/echo_verify.rs","sha256":"6d453051665f823abd7354d5c50031d9524cf47d6092d2f09080ae814e3b9575"},{"path":"product/runtime/auths-gateway/src/engine.rs","sha256":"900dead51861e63c3cbb38e365a5152055e058489ddf18b06fb30cc21b1ffe19"},{"path":"product/runtime/auths-gateway/src/fuzzing.rs","sha256":"ed3b0028487eb546a3b0a91d115aa8f18bcea324b61620bfe8e35a9e6ab18758"},{"path":"product/runtime/auths-gateway/src/generation_floor.rs","sha256":"fe1510ec96ce0f67e9a78edbfa94b33eb7df64c0ac4d0a67901124dcd0164777"},{"path":"product/runtime/auths-gateway/src/harness.rs","sha256":"c87e479f3eb281960f6c9c80d43c7560d7ccb654b0154ec823d3fcec4884ac05"},{"path":"product/runtime/auths-gateway/src/lib.rs","sha256":"b182052835a2cd631d1f801a74788d6ac1ef9cae21ade9ab4ffc270cd6f667ed"},{"path":"product/runtime/auths-gateway/src/listener.rs","sha256":"aa08239bcbc1fcb55e8a212fbdf6a84f12985b0d436dcb51dc58b06e59e435f2"},{"path":"product/runtime/auths-gateway/src/observed_tests.rs","sha256":"a22be071695f89ca2578a4d82fd80d9cb82289213c9bdb8f0470f6b2dc3d9201"},{"path":"product/runtime/auths-gateway/src/observer.rs","sha256":"562ffcaea071c3856e0708dc2fe33516917e145d2438aabb75af0a2b6ba01046"},{"path":"product/runtime/auths-gateway/src/onboarding.rs","sha256":"0dfd7d67e7f02f18a28d1c86ca1b7751d7463f5efcdbe3825de0ad8cbccb3891"},{"path":"product/runtime/auths-gateway/src/operator.rs","sha256":"c3c36954a3e86723df035b47f43b85fc8ab3a6292983522b6258d5c6b4e6c4e4"},{"path":"product/runtime/auths-gateway/src/pending_vectors/attempts.rs","sha256":"47ef3c8cb1c5504d47ae9a0088705ce6715fe86bac1671a34a56fb38a64d0dd3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/bounds.rs","sha256":"e612217307e1da5b0eb5ee6582a7458bb064b8aa8a529fc6555b1b334127ab68"},{"path":"product/runtime/auths-gateway/src/pending_vectors/codes.rs","sha256":"e00670a5ef24eb856cc2c6dcda8e5a263842f55c76bb939c0c27bd9df37e5522"},{"path":"product/runtime/auths-gateway/src/pending_vectors/keys.rs","sha256":"f84c56f2ea9cb34b2b79c72d13fbf2c6585010ec1ed450af58a78c80c1ea1edd"},{"path":"product/runtime/auths-gateway/src/pending_vectors/mod.rs","sha256":"5de8340f0ef71a0b57a09e323fefe473d3160c6ae952b9ba46f714825fbacafc"},{"path":"product/runtime/auths-gateway/src/pending_vectors/outcomes.rs","sha256":"8ec07b9511b48913af36ac999d2aa0e82924289f6acb23ddaeb9f00f99815166"},{"path":"product/runtime/auths-gateway/src/pending_vectors/production.rs","sha256":"f574cabfa4687a4fc846b8f6a234b68ec53b876aed548b11445729cac1a55ede"},{"path":"product/runtime/auths-gateway/src/pending_vectors/recipes.rs","sha256":"51693208270231c25c3aef2a32151d5962114c71e86b88cb9df83181c7af83d9"},{"path":"product/runtime/auths-gateway/src/pre_entry.rs","sha256":"06ea78ca140468bfaba17d9ab04912ad68673954c3203c98fed28272ff2a00c0"},{"path":"product/runtime/auths-gateway/src/property_tests.rs","sha256":"939c081e2e154aaf10186754044bdd65608932c899b970a04a71d0afaa999a93"},{"path":"product/runtime/auths-gateway/src/qualification.rs","sha256":"d5078a81dc89f30958a7d8fdabfe164c3411c441dd7d9015002681a58883b63a"},{"path":"product/runtime/auths-gateway/src/qualification_tests.rs","sha256":"4473add5729b97faf04d7be7fd8cf3bbacd7f545e1b61c7d2782563011906b4d"},{"path":"product/runtime/auths-gateway/src/quorum_tests.rs","sha256":"a78380b019104d688c11a4410082c7e08ded3106aab099954c4f8a1b4ae0fd89"},{"path":"product/runtime/auths-gateway/src/readiness.rs","sha256":"911c3f11892f94641574375e2da4c671c802738f71082f12c39832331052d43d"},{"path":"product/runtime/auths-gateway/src/recipe.rs","sha256":"fecf9af67e7afc48d080e9f8f55f8ce28e49d0e08988717a27908bbda461d6b6"},{"path":"product/runtime/auths-gateway/src/recipe/lower.rs","sha256":"8088b8751ed831dbb48247af953c6290ac95e2a438ccd5bd65eff54be06a1fd1"},{"path":"product/runtime/auths-gateway/src/recipe/review.rs","sha256":"c3eb7d9fdd98dacf52750b14b67ad7b7faaecbbdeafff1e0b049f67d0a2d0139"},{"path":"product/runtime/auths-gateway/src/recipe/runtime.rs","sha256":"c286f0d15f974402822c0810d8e97f98411dc1c557755cc23e540d85e2bb42d9"},{"path":"product/runtime/auths-gateway/src/recipe/source.rs","sha256":"1af50298fb1461e1b24cbdf560d43124d6b1c4c529586c911b1c4797214a69ff"},{"path":"product/runtime/auths-gateway/src/recipe/tests.rs","sha256":"aac551a2481bbc60864c64079bc667dcb232e45a0f41a04073ed84ab5dbe1fce"},{"path":"product/runtime/auths-gateway/src/recipe/validate.rs","sha256":"3711b17605cb7b0d639bc1b180449231f5882a306cab20e2c7782155cc63b0d4"},{"path":"product/runtime/auths-gateway/src/scenario_tests.rs","sha256":"d8271761b12597bfe1233f8eb5ad1d4e5498c5d03388e832e24ab818484a1de4"},{"path":"product/runtime/auths-gateway/src/separation.rs","sha256":"be9306848ca5d801767cf6aa14247c8618312ef0e202f00ce0c24c4844491061"},{"path":"product/runtime/auths-gateway/src/store.rs","sha256":"1e5288345c2cb1421aeda277b3158d07607404b0ec46943222ac107b63dcbb46"},{"path":"product/runtime/auths-gateway/src/store_testkit.rs","sha256":"88d82fee42f1b8ef521e8deef0216e938ebeaad822eb2f5020e70b89d145ea70"},{"path":"product/runtime/auths-gateway/src/submit.rs","sha256":"c78dbbba7c45b443febf655056c5edcd635e77be7b21c5b2c318097502415ffe"},{"path":"product/runtime/auths-gateway/src/support.rs","sha256":"9fd979029793a22b15d9776a7fc172476fd7c126a80d4080c65d720845becbcb"},{"path":"product/runtime/auths-gateway/src/transport.rs","sha256":"be2c6dc75b8daec110bf8749fedc3823f6067d40b999aa3eb21126896a97d3ad"},{"path":"product/runtime/auths-kernel-runtime/Cargo.toml","sha256":"926bcd0053e5edd703be8f0027ad009e2982db013c8174c1366edbf38b48087d"},{"path":"product/runtime/auths-kernel-runtime/src/lib.rs","sha256":"7108faae9ca4bc32dc093ddaf885ac8f74f3c9b8d317b7c7d0ed00d1d0ab5972"},{"path":"product/runtime/auths-lifecycle/Cargo.toml","sha256":"c5053c705f8d5554b44e432fe75287a2faf11d644e5a2552e45ad6cd94176af5"},{"path":"product/runtime/auths-lifecycle/src/codec.rs","sha256":"51c4b746749150e8bfcd8ff972b3f6c1ef40bec15583448ec1b471d9ad737dc0"},{"path":"product/runtime/auths-lifecycle/src/digest.rs","sha256":"55282cd7d8aba37713c2dcb5357c9877819edb72a30eadefb860d28d7d3a3eb7"},{"path":"product/runtime/auths-lifecycle/src/identifier.rs","sha256":"31620e8c16de68d3d2d3b84d6353c1a5b9d4151d8247f91fa389b906a8e660f1"},{"path":"product/runtime/auths-lifecycle/src/kernel.rs","sha256":"2abb8c094b36d35b364e74d78091d14c5d6f3d1eb6552cca3b5538dbd017ce23"},{"path":"product/runtime/auths-lifecycle/src/lib.rs","sha256":"afe5a345cd309b5a4f08ffba3170a6d7f16ff914892b3f2006d5208ed24ec736"},{"path":"product/runtime/auths-lifecycle/src/model.rs","sha256":"1af12bbeeeaa65ec02ddcebd7d2c8c92ec1e339fa40ae85b45ab9b01a722a4fa"},{"path":"product/runtime/auths-lifecycle/src/operation.rs","sha256":"78e6d05fcf5d7ea4f148032a3fa26fdfcab77eb346019effe927b08e0d64d732"},{"path":"product/runtime/auths-lifecycle/src/registry.rs","sha256":"53495fe6f7a77422593a41623e28716f1c140dcc1e00f87f6b0ffbfb93a5ef90"},{"path":"product/runtime/auths-lifecycle/src/sealed.rs","sha256":"2e0c03b5813c926c159598bb7890d1523825edbe57cd687d42a5dfb3374a0c19"},{"path":"product/runtime/auths-lifecycle/src/test_support.rs","sha256":"221d9a5c5ef8e1f9f8fd66927484eaf813571d0568470278ecd8fa08a5eec8cd"},{"path":"product/runtime/auths-lifecycle/src/transition.rs","sha256":"011805a28efdd541f44ccea54dd0e34a1e58f4004447ee58013703b4fb6b2822"},{"path":"product/runtime/auths-runtime/Cargo.toml","sha256":"dd29d80a8b4bb56c869f036a6c9998f6e6d1c0383ac5dc03fa42b24abe2a7ff7"},{"path":"product/runtime/auths-runtime/src/lib.rs","sha256":"132ca03d58c14905d3a822a4972f42a22a5ad33a45f2ba9ca44f3a57d810b4b0"},{"path":"product/runtime/auths-runtime/src/production.rs","sha256":"fd4eff4270c571c10fcff6cf27df28961ebf074de8a1a028f500fda1ca376820"},{"path":"product/sdk/auths-approval-quorum/Cargo.toml","sha256":"df904971fca87a24194c5816738a331588fe8f164acb5d70839a35dca5f57114"},{"path":"product/sdk/auths-approval-quorum/src/lib.rs","sha256":"72e4086088a1c0912e4e1a9e980f26a5c280bf5ab16ea39c9f0f58d5096ac2ce"},{"path":"product/sdk/auths-approval-quorum/src/remote.rs","sha256":"9fa029c7c63003adf260f8aec55160c545681c60c1bace0d934e7525862aac7b"},{"path":"product/sdk/auths-approval-quorum/src/remote_tests.rs","sha256":"8a09ce17cfee82a035a74edd535f3ebeb3db0e078784740d3997b17dbdb10197"},{"path":"product/sdk/auths-approval-quorum/src/tests.rs","sha256":"0acbf12be3e497dcc6c2d8f29c9af3b1a7ed8e11b75f6399570d4f217a785060"},{"path":"product/stores/auths-stores/Cargo.toml","sha256":"a32c4b76d17b264be5d40d24497ff237e1ed87822e8bab86229b3db93106dbe3"},{"path":"product/stores/auths-stores/src/gateway_attempt.rs","sha256":"185da8f4a220fba836d5b78a9311f03204681c43a3c53951008084d135bf4d21"},{"path":"product/stores/auths-stores/src/lib.rs","sha256":"e721262edf8a9ab5568ddc27639176312d4a366203b5f73e2d7c11fde2c554e9"},{"path":"product/stores/auths-stores/src/lifecycle.rs","sha256":"94f64d25bc178a9e60ba3c0ee6915d7fb3af7c4468792d76b4e70f43f4de1e2f"}],"schema":"auths.gateway-semantic-closure/1"} \ No newline at end of file diff --git a/product/runtime/auths-gateway/src/credential_journal.rs b/product/runtime/auths-gateway/src/credential_journal.rs index 4d04e40b2..ed1e44571 100644 --- a/product/runtime/auths-gateway/src/credential_journal.rs +++ b/product/runtime/auths-gateway/src/credential_journal.rs @@ -188,7 +188,7 @@ mod tests { ); let reopened = CredentialJournal::new(directory.path().to_path_buf()); assert_eq!(reopened.generations(&id).expect("notes").len(), 64); - let foreign = ConnectionId::parse("conn_BBBBBBBBBBBBBBBBBBBBBB").expect("id"); + let foreign = ConnectionId::parse("conn_AAAAAAAAAAAAAAAAAAAAAQ").expect("foreign id"); assert_eq!(reopened.generations(&foreign), Err(CODE)); reopened .forget(&id, NonZeroU64::MIN) diff --git a/product/runtime/auths-gateway/src/engine.rs b/product/runtime/auths-gateway/src/engine.rs index a7691274c..6049cdba3 100644 --- a/product/runtime/auths-gateway/src/engine.rs +++ b/product/runtime/auths-gateway/src/engine.rs @@ -2222,8 +2222,14 @@ pub(crate) mod tests { #[tokio::test] async fn a_record_that_changed_since_the_prepare_is_not_committed() { - let installation = installation(8).await; - let host = &installation.first; + let mut installation = installation(8).await; + let host = &mut installation.first; + let journal = crate::CredentialJournal::new(host._state.path().to_path_buf()); + journal + .initialize(&installation.connection_id) + .expect("journal"); + host.engine.credential_journal = Some(journal); + let leases = host.leases.load(Ordering::SeqCst); let commitment = host .engine .prepare_rotation(candidate("prepared-secret")) @@ -2235,7 +2241,22 @@ pub(crate) mod tests { "gateway.admin.rotation-not-prepared", "the successor was stored for the generation before the disable" ); - // The emergency flow: rotate while disabled, then enable. + assert_eq!( + host.engine + .prepare_rotation(candidate("prepared-secret")) + .await, + Err("gateway.admin.credential-unavailable"), + "the abandoned successor blocks the current generation until collected" + ); + assert_eq!( + host.engine + .collect_credentials() + .await + .expect("collect abandoned"), + 1 + ); + // The emergency flow collects the abandoned successor before + // preparing another rotation while the connection remains disabled. let again = host .engine .prepare_rotation(candidate("prepared-secret")) @@ -2245,9 +2266,15 @@ pub(crate) mod tests { .commit_rotation(again) .await .expect("commit while disabled"); + assert_eq!(host.record().await.state(), ConnectionState::Disabled); + assert_eq!( + host.entry_refusal().await.as_deref(), + Some("gateway.connection.unavailable") + ); + assert_eq!(host.leases.load(Ordering::SeqCst), leases); host.engine.enable_connection().await.expect("enable"); assert!(host.engine.status().await.expect("status").credential_held); - assert!(host.entry_refusal().await.is_none()); + assert_eq!(host.entry_refusal().await, None); } #[tokio::test] @@ -2374,10 +2401,16 @@ pub(crate) mod tests { .await .expect("repeated revoke"); assert!(host.stored(&installation.connection_id).is_empty()); - assert_eq!( - host.engine.disable_connection().await, - Err("gateway.admin.connection-not-active") - ); + let generation = host.record().await.generation(); + let stopped = host + .engine + .disable_connection() + .await + .expect("stop revoked"); + assert_eq!(stopped.code, "gateway.admin.disabled"); + assert_eq!(host.record().await.state(), ConnectionState::Revoked); + assert_eq!(host.record().await.generation(), generation); + assert!(host.stored(&installation.connection_id).is_empty()); } async fn a_second_host_joins_only_with_the_matching_secret_after_state_changes( diff --git a/product/runtime/auths-gateway/src/semantic_closure.rs b/product/runtime/auths-gateway/src/semantic_closure.rs index e4ed4f8ba..9d91c39f3 100644 --- a/product/runtime/auths-gateway/src/semantic_closure.rs +++ b/product/runtime/auths-gateway/src/semantic_closure.rs @@ -10,7 +10,7 @@ /// SHA-256 of the schema, a NUL byte, and `semantic-closure.json`. /// Regenerate through `semantic_closure_is_current` with `AUTHS_UPDATE_FIXTURES=1`. pub const GATEWAY_SEMANTIC_CLOSURE_SHA256: &str = - "ec4a2b94844f90e3b2e3b30cb8c3e18a33f14242221e7765ff0f1877ab1c286e"; + "0177bfec3c76f1c296bcafbd71d242a717aedd90f9765ec1954c7208a98659b4"; #[cfg(test)] mod tests { From 71a85bf4b0ab6b05a41b271722bcab5ace2899b6 Mon Sep 17 00:00:00 2001 From: bordumb Date: Tue, 6 Oct 2026 05:40:55 +0100 Subject: [PATCH 019/108] fix(gateway): use the test host directory without underscore access --- product/runtime/auths-gateway/semantic-closure.json | 2 +- product/runtime/auths-gateway/src/engine.rs | 7 ++++++- product/runtime/auths-gateway/src/semantic_closure.rs | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/product/runtime/auths-gateway/semantic-closure.json b/product/runtime/auths-gateway/semantic-closure.json index aa9637645..560b8240e 100644 --- a/product/runtime/auths-gateway/semantic-closure.json +++ b/product/runtime/auths-gateway/semantic-closure.json @@ -1 +1 @@ -{"files":[{"path":"Cargo.lock","sha256":"c94ed342774d5e2823f01ecf74b8a4812c5f9a6b0cf811d31f2e2cecb671a275"},{"path":"Cargo.toml","sha256":"6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24"},{"path":"core/adapters/auths-did-keri/Cargo.toml","sha256":"86ba3e3f9a0a70d970568bfb3113b7ba7bbdd81c3eebbb52743dd574a0c0ecaa"},{"path":"core/adapters/auths-did-keri/src/lib.rs","sha256":"a75674842f8a7142004369ccd206ab43e476459293f0ff4bed4d4e659031b3e3"},{"path":"core/adapters/auths-did-key/Cargo.toml","sha256":"d5a3ae07ecde83f91eed4c3785051dd0f44eab6c891754f3309b6b40596707d7"},{"path":"core/adapters/auths-did-key/src/lib.rs","sha256":"b76a3f4528a725df53cfa9242e6e414e1d26caa48468aaed497e28b121f4497c"},{"path":"core/adapters/auths-raw-key/Cargo.toml","sha256":"f49616bc18c19e6aaa7e6a02ccebcdb9f5c1422c1278ef9869e0dbf22ceda7be"},{"path":"core/adapters/auths-raw-key/src/lib.rs","sha256":"45eec1b295dac3bed65cd79c942870b926b06b3f5d38eaebaeb6140ac69315fa"},{"path":"core/crates/auths-algebra-kernel/Cargo.toml","sha256":"0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba"},{"path":"core/crates/auths-algebra-kernel/src/generated.rs","sha256":"ae4bcbef42a408c7ffa0c6a74a42f7de177a6f14479e51d205acf830bda05960"},{"path":"core/crates/auths-algebra-kernel/src/lib.rs","sha256":"6654667eeb9b353d6648954c9fd2e8838462a82ce6b2803eb49e1366892c68c6"},{"path":"core/crates/auths-assurance/Cargo.toml","sha256":"afcb12a97ddd09d7a264b9ecd3fcaefc865ff2c9b4539ee85b00883420ba333a"},{"path":"core/crates/auths-assurance/src/lib.rs","sha256":"0fb2ec844d674b25a9e20b1601452c89c2454901fa506adfa9bb38ef9a7fa213"},{"path":"core/crates/auths-author/Cargo.toml","sha256":"1e6f0e3bc079ddb558decf0db26b291c6e72fc47327b6df1b7650d41689b215f"},{"path":"core/crates/auths-author/src/lib.rs","sha256":"e14475f2f49715a1869d5fa6b11ff1fbb72497e39097e09f833b0bae7e5b3f2b"},{"path":"core/crates/auths-author/src/observations.rs","sha256":"dda7d6bfa6f4bd7e95a480ca283c2c0e996f69c5c15cb0c7197af328131a7066"},{"path":"core/crates/auths-authority/Cargo.toml","sha256":"4f68212938029f79ebd857b4f3038494eb85d0163d49f07e51376715cf959815"},{"path":"core/crates/auths-authority/src/lib.rs","sha256":"da88d5194de4e17449e69972c0fb042afa3c39798a8f570f30771e77c384f1eb"},{"path":"core/crates/auths-codec/Cargo.toml","sha256":"e20e51826e17814effd9d8925d18d5fbdd6c0d37bf50231e743ec2611314722c"},{"path":"core/crates/auths-codec/src/approval.rs","sha256":"fbff43bf4d57f69f8b7738a8647751cde75c5a932dee65d924a1fe9c7202f91f"},{"path":"core/crates/auths-codec/src/bounded_policy.rs","sha256":"d21f6728be2d8a04b6d94921f2b683f7e61cbb42e0ac6866f1c88a49caa534c3"},{"path":"core/crates/auths-codec/src/decode.rs","sha256":"ba2999584cdf53b1b517ecb9c7ea50d39efee17c666a9a38e2ad1ac94379f778"},{"path":"core/crates/auths-codec/src/encode.rs","sha256":"8491192053e2e15d62b4d2a491de22405b7487ead69ab6f6bca40669ce7ca5f7"},{"path":"core/crates/auths-codec/src/error.rs","sha256":"fecb0737c16deb42d859f1dc7727c698438d9ac12064fd99e0024629642c390c"},{"path":"core/crates/auths-codec/src/hash.rs","sha256":"f88e111f1dbb2cef6b7b5e9c948cb45ff92e366710c8a5f5c636138aa748479e"},{"path":"core/crates/auths-codec/src/lib.rs","sha256":"3b0e5c94c6f34f750b88a9333e1d5c8145746d845d3a23e0d2f61807cf592ea7"},{"path":"core/crates/auths-codec/src/observation.rs","sha256":"38328b0c71ff97a4196eeade8b4faa889527ff1f80bb168468bcd49082a3987e"},{"path":"core/crates/auths-composition/Cargo.toml","sha256":"331e13025eb82588b5269ed3975929eb41c823d588c49e4c296273d85c6fe80e"},{"path":"core/crates/auths-composition/src/lib.rs","sha256":"e42e3b0b6a9985b73c533aeb23799c638979aa27a9ce7d0f10a8d60340570fb1"},{"path":"core/crates/auths-model/Cargo.toml","sha256":"565c15302b0cc9270db1e28efa3862804846850ba933cc17aea8abcec4a65987"},{"path":"core/crates/auths-model/src/approval.rs","sha256":"54cf44a9ef747ec21546a4086aecfb130bc7803b0d646430e6082df51e6e305f"},{"path":"core/crates/auths-model/src/bounded.rs","sha256":"f90496abc0a06c028b4d850af6ddab7d850bfafeaa3d042f1b1246a41d8bbbc9"},{"path":"core/crates/auths-model/src/bounded_policy.rs","sha256":"306a8f049cc7cfc7635fe0e4de47eb7813eed63d3c14c3be2b51586aa4eea450"},{"path":"core/crates/auths-model/src/lib.rs","sha256":"e7cfe6bb9574c6b016aa63e70658c31e0b90903ec6479a49f4a2ceb64f5bad97"},{"path":"core/crates/auths-model/src/observation.rs","sha256":"b3ed3e3cc090afca2896a7d3de7988afccc1ee1ea0ebd91b51a8bc0f20ad8dbb"},{"path":"core/crates/auths-multikey/Cargo.toml","sha256":"858756c1197befcada06134742bffe8d58cf674cadd6c046bf710570e96efaf2"},{"path":"core/crates/auths-multikey/src/lib.rs","sha256":"f5177fffb11e40eeaaa665ba886c541fc1f24d5eacdd6983fb03dc20148733f0"},{"path":"core/crates/auths-ports/Cargo.toml","sha256":"596a9b0f5af3717c16a6d13f7054d8a106bcd9f01f5f72c2235dd2afcf0ab16c"},{"path":"core/crates/auths-ports/src/binding.rs","sha256":"a16c012d40aa4249e3ec54372b9611006d0bfe8c7dc3c741911c2194ad17736d"},{"path":"core/crates/auths-ports/src/diagnostics.rs","sha256":"aa596572503b5a65a918bb2ff38281c144ff53821ee914e9325c852828d852df"},{"path":"core/crates/auths-ports/src/lib.rs","sha256":"8da1debf86f9532df0660155d04298beb1ba3a1204508f8586e2e67cd2fb3449"},{"path":"core/crates/auths-ports/src/path.rs","sha256":"b68fc547b4e4d97a60cbbc1cc1939fc6b34a8233b81f840bd396914a707e3ea1"},{"path":"core/crates/auths-raw-key-core/Cargo.toml","sha256":"98c0bc8527a537512e43a74dd6ba9658c6f0cdc16610cf938e3f9b43785d836d"},{"path":"core/crates/auths-raw-key-core/src/lib.rs","sha256":"98c0500c41697aae28708ad0bf970b9a97583d96a3d2c18d23e7fa351e0f7d12"},{"path":"core/crates/auths-registries/Cargo.toml","sha256":"590e49e58b0622d9d6274fea46796dcdb07dec9550eff295cce6a6427ffa51e2"},{"path":"core/crates/auths-registries/src/lib.rs","sha256":"450d3886d85ee333b7e046317fb5b47cde62483d5f3e41d46265e2caf4c373ec"},{"path":"core/crates/auths-registries/src/template.rs","sha256":"1224039dd2b3ce6fa8357613d8cafbae40400493da7176da202b9ade62fa05e4"},{"path":"core/crates/auths-signature-core/Cargo.toml","sha256":"6bee2230eb30af1be0bd5c2d57bd3e1903497a70028d47290d4ac6e9e0e8bca0"},{"path":"core/crates/auths-signature-core/src/lib.rs","sha256":"6e3f9311ded5e49ea50d445eb21e6d8fa12442aa4362a73e0cb6fda15b7cd865"},{"path":"core/crates/auths-signature/Cargo.toml","sha256":"7f7b5682466ba439d8c59579022cb61068cad9fb4bd2d73e1cc21327c902b450"},{"path":"core/crates/auths-signature/src/lib.rs","sha256":"b3d9ac4cc3ba0797b9e1c09f2d6ac05089b25dac4e285a5af28c0165b33d925b"},{"path":"core/crates/auths-verifier/Cargo.toml","sha256":"c43358e06a33324b41a8b93e5cc7279c55f7d21f1f6cfaa539a3fc7b4c27a38f"},{"path":"core/crates/auths-verifier/src/approval.rs","sha256":"c3cae6a49e169051eb555bb092b1069a4d422516d6a2114623a89e5f31ff923f"},{"path":"core/crates/auths-verifier/src/causal.rs","sha256":"9635230f33b13a263573d319ac8a1976addbcc07677514a43e3c7bf28dc04587"},{"path":"core/crates/auths-verifier/src/lib.rs","sha256":"f22dec38dfa47ced8da4f605390da8453273bee1da010f57fd1fdfcb10e0b389"},{"path":"core/crates/auths-verifier/src/observation.rs","sha256":"0bb07f06a0f9524c88427df1c972b1de8ba038a9eeeb15d3134c25125ae84b1e"},{"path":"core/crates/auths-verifier/src/trace.rs","sha256":"2213d72023a1d9e0413a2cf2c51c3dad9e04775d86033a0caaa9d29a8f0036f8"},{"path":"exchange/crates/auths-proof-exchange-model/Cargo.toml","sha256":"34b2db64f93a288e942b5a3918d28cdcbef906e0dc9074ce848018d3d5f7a1fa"},{"path":"exchange/crates/auths-proof-exchange-model/src/lib.rs","sha256":"49fac5aff2339d3a57c41cb8bb2a82852538e8f77ecc4b157c88e264ff31fb55"},{"path":"exchange/crates/auths-proof-exchange-port/Cargo.toml","sha256":"7ff660f1b7579dc570c791090aeb450404fbbf44c92781e289f5ccdde746d739"},{"path":"exchange/crates/auths-proof-exchange-port/src/lib.rs","sha256":"b408fb40c6432edc1facb3d8b3e9433a033f8dc73fe2e0ba5a88c972ca675021"},{"path":"product/config/auths-config/Cargo.toml","sha256":"e4b568ab9f6d84f7d7e6d66443fe825f360db9c27bc7c31d6ddc0647ba3ab304"},{"path":"product/config/auths-config/src/lib.rs","sha256":"fecf00ea65cef9018fda9af2063326d7065b869266d0d9e73a4f06816f1102cc"},{"path":"product/errors/auths-errors/Cargo.toml","sha256":"3b3a199b6460ba75bda84475bb5accd35e1485448a3981038db85bf4772dd350"},{"path":"product/errors/auths-errors/src/lib.rs","sha256":"7feeb9069fa4003f94f1f07c1c94619cf1c883e0dbaaf2187f04d0f742264bdd"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/Cargo.toml","sha256":"716f1f2a117d6d69d8effe9ee9057e24ba3502f20af6a602b06facb638cdabed"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/api.rs","sha256":"9ea61dd7ddd93282b073b98e453e6b75b26dc49689c04e9782435d06a3a09e48"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/clock.rs","sha256":"73f0a6e0f5903883329fa6683f5888288f759512ac69e5c87efd2b6b87f7d79f"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/http.rs","sha256":"14c1fce14e24c984b2a275563a29b6326fb08367922b6e8d37ba38b9cb81aa2b"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/identity.rs","sha256":"186de11230c8b33375951c4368609f8976bf9795f171af3fd7fac26207a94361"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs","sha256":"0b4617d044f5254a5ab22f5a2578f91cc025206a8c1845be39c1c56dcdf7a5df"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/names.rs","sha256":"41bb23572d6002e23ee103d6fe70ecd68764861c6f2e48a1c53af998270a4afa"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs","sha256":"39fed883f4802e68d3b41a68fea0aba0737810996b33d13577de70faba004c29"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/store.rs","sha256":"fc60ee9c49b2f4f063c449b4c78100c5c4872779e94ca168f796603b380ef6e4"},{"path":"product/integrations/auths-custody/Cargo.toml","sha256":"1e14034185ad1ec24a977fd5f41d0abee219606245c046ce2a82287fadef448b"},{"path":"product/integrations/auths-custody/src/conformance.rs","sha256":"8ed1afd58f18fc6becc268908aa6419c9aa404c79da0197963eb2599df44acf6"},{"path":"product/integrations/auths-custody/src/key.rs","sha256":"70cbb0fd21b6f5652157845a22c35be2d0f6c05b3d138fc4b9bb6dbdc3d81c40"},{"path":"product/integrations/auths-custody/src/lib.rs","sha256":"8ee593c1f59b0fd2126bdda9138026f5bc531beb64d4489a99785842e7b98b43"},{"path":"product/operations/auths-operations/Cargo.toml","sha256":"73dde1e914ba5e1386f8d49c0d730423cc72ae77ec44c6554a6a75cc8e8922b1"},{"path":"product/operations/auths-operations/src/explanation.rs","sha256":"b4a39bcbd5712cb9e735ee7deeb281f3fa6af5ddca973735bf3d87dce427ef11"},{"path":"product/operations/auths-operations/src/lib.rs","sha256":"3f401a56555113b98f57bca172a2660eaecedf76247b83a3fdbb089c133a29cd"},{"path":"product/operations/auths-operations/src/render/json.rs","sha256":"2ae042639960afee123730e945d373bc5dda1d2b3af20ae16c939a7e99b9e418"},{"path":"product/operations/auths-operations/src/render/mod.rs","sha256":"b3b7f6fe473f49227ace5a68bfc3d8dc14b5db8dd9888fd9e207070337b1b8bf"},{"path":"product/operations/auths-operations/src/render/text.rs","sha256":"f216cf3bdb00e264523271b16e7059535ac6b1aabf271cebd7935af155e4bfec"},{"path":"product/policy/auths-bounded-policy/Cargo.toml","sha256":"babd5d200923137ead71d8c2528f847cea323ce98da942a1320b054436612c47"},{"path":"product/policy/auths-bounded-policy/src/arithmetic.rs","sha256":"75e43c5d4eab8d1f71c1daf53839f5f9fe45a400afc1f63a30c6f55ce3632627"},{"path":"product/policy/auths-bounded-policy/src/commitment.rs","sha256":"c5706f2d583454e1a7f570f7ada138d4d864bef0205dfae7c1296774f396bb3f"},{"path":"product/policy/auths-bounded-policy/src/eligibility.rs","sha256":"c9acdfb793074e687fc36efad506be27dbd99ffbf40387bc66c8de39ef238432"},{"path":"product/policy/auths-bounded-policy/src/identifier.rs","sha256":"0006a32bae9eb16c4178cf797df418d2b0a781f2bc6474b741dc1a908141831c"},{"path":"product/policy/auths-bounded-policy/src/kernel.rs","sha256":"99187c28b161ac70bee1afed60711f7f645adb4d1671a01863f9849b369811d5"},{"path":"product/policy/auths-bounded-policy/src/lib.rs","sha256":"76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c"},{"path":"product/policy/auths-bounded-policy/src/receipt.rs","sha256":"3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad"},{"path":"product/policy/auths-bounded-policy/src/registry.rs","sha256":"4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0"},{"path":"product/profiles/auths-profile-api/Cargo.toml","sha256":"7ae85761f58625b5d678f961fd052eebf3e000ef565c7312e3ac857763c0017f"},{"path":"product/profiles/auths-profile-api/src/lib.rs","sha256":"a194b82b20bf8aa864c2334ef6c6aec30b2154ded972862252d5dcefa488ab95"},{"path":"product/profiles/auths-profile-mcp/Cargo.toml","sha256":"db264fc25242f7b7e4133cbe5782545b3107b406c87168ae072683cfb59eac66"},{"path":"product/profiles/auths-profile-mcp/src/arguments.rs","sha256":"a5de696586d507e2aee4a49fee99ef1ef4c51a2e46603f8838f1af6d9009833f"},{"path":"product/profiles/auths-profile-mcp/src/lib.rs","sha256":"d0f8b733a09ef8408336cdebc8948d6a5861012ce6878598b11be7084dfd4280"},{"path":"product/profiles/auths-profile-mcp/src/session.rs","sha256":"166c281fa66333388e4760d6098dad02d3359e1d5de4b8f93312c014f97abb03"},{"path":"product/qualification/auths-recipe-qualification/Cargo.toml","sha256":"b7b15b30b9a3d96d4f089d514266d3a892de6608d30707aa44be31cca89ca9fe"},{"path":"product/qualification/auths-recipe-qualification/src/canonical.rs","sha256":"30a9b50777f0dcb4b606abfee2467d5a975d9f6ad941ab6c13ca3df5b359f667"},{"path":"product/qualification/auths-recipe-qualification/src/closure.rs","sha256":"0ad6aee9bd981e2863fa725f209ec84031db2ff12f4c7ac3aaf5120f0bb86039"},{"path":"product/qualification/auths-recipe-qualification/src/error.rs","sha256":"52d5cf720a1e4579008fdda90a3ac2c31f0b8db57985f121f65e54b4da2b7dd1"},{"path":"product/qualification/auths-recipe-qualification/src/evidence.rs","sha256":"1a4cb862f725b02f9efd827db99637ea8178a5236aa020ec271a363edbe7b362"},{"path":"product/qualification/auths-recipe-qualification/src/ids.rs","sha256":"e81a906d571497ab2da753e1532d4443706410e0b75fdd59a7d2d788c7aec403"},{"path":"product/qualification/auths-recipe-qualification/src/lib.rs","sha256":"195b19f46e1e94a0f3594ad5958e5715bc5e3ad415bdfe6428dfc1b6dd3f4631"},{"path":"product/qualification/auths-recipe-qualification/src/model.rs","sha256":"3484eb0ec287b23d4682ade7b1b0f8d1335985b3fb180f06fc28716076957d5f"},{"path":"product/qualification/auths-recipe-qualification/src/release.rs","sha256":"d816b53e2275e902c750ad03803061844e259e28560ab2d1c77e8a43981a4d6a"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/mod.rs","sha256":"7f15b68e05a04f202bcb1fb80de1d9a9a4fda8bfd6af2cd4e5c660fc75d96fe5"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/schemas.rs","sha256":"c59feec2805621f341a90f81fc005e2c12f7a70f9d264fdeacccb2be4fe1c046"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/verification.rs","sha256":"6a6b5834c5dae10af1ba8939b2deae43b85db71544dc8f077ff63b7fe68ac8a8"},{"path":"product/qualification/auths-recipe-qualification/src/verify.rs","sha256":"edd33589c54fb79bcfccc4cf4e6ccf95bbca088318bb7f8dfc27da684b4fa671"},{"path":"product/receipts/auths-receipts/Cargo.toml","sha256":"6001fa1375899953aafcb07c23a6da0c8f57ea7ec08bb9c950b12a60a8cc6f0f"},{"path":"product/receipts/auths-receipts/src/disclosure.rs","sha256":"ba9ed439be0a320c8a01f5b6e9b51361c1a37e076947490d8e4a484ba6bb119c"},{"path":"product/receipts/auths-receipts/src/lib.rs","sha256":"547a57c4160256719cafb7d0ab972d9fc80b0da14fbbce4148c70c414070ff36"},{"path":"product/runtime/auths-connections/Cargo.toml","sha256":"babeb6e1dda3dfb66291713ce1e43dce5c349833d0b50ea4dccbf986030026b2"},{"path":"product/runtime/auths-connections/src/credential.rs","sha256":"82921413bb053f0f6c7931fbd4e6a86c8cc1d8c6b51debd9c2cef33a8d5b1c51"},{"path":"product/runtime/auths-connections/src/kernel.rs","sha256":"a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8"},{"path":"product/runtime/auths-connections/src/lib.rs","sha256":"79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22"},{"path":"product/runtime/auths-connections/src/model.rs","sha256":"de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77"},{"path":"product/runtime/auths-connections/src/registry.rs","sha256":"e57640e003e72ad3235c567c2bb944a262bd64e673f023b62ea091094cc7e946"},{"path":"product/runtime/auths-gateway-kernel/Cargo.toml","sha256":"34f864e67656af4ac7e5c7a347a23f01fc8ab31365b8e23c0ef474483b14a183"},{"path":"product/runtime/auths-gateway-kernel/src/construct.rs","sha256":"e9d65744bae273d65face4285e5d2da75c06a92ab48f7b8333d496604e31c63c"},{"path":"product/runtime/auths-gateway-kernel/src/lib.rs","sha256":"cfda6f8453426564c085475f183b6f790b438768a19668f1b65d33ba59dc8632"},{"path":"product/runtime/auths-gateway-kernel/src/order.rs","sha256":"e0045f877c4b7fe3860c291039853885064ddcdebba7c9b345ab65e81e646dda"},{"path":"product/runtime/auths-gateway-kernel/src/outcome.rs","sha256":"e9785b1afe70788c89b51b18655bcd5acff7b0c8e3d12fb79c6f05a202e67e6b"},{"path":"product/runtime/auths-gateway-kernel/src/ratio.rs","sha256":"7ace22264812e6fc1ef3a62afee402cf43494bb71ae0d3de219ad1b39d690bcb"},{"path":"product/runtime/auths-gateway-kernel/src/recovery.rs","sha256":"9f46dcd1685ab6e4d1ba04a3fc286a9f3afee8fb47829be1fbc670a7926a2dc6"},{"path":"product/runtime/auths-gateway-kernel/src/transition.rs","sha256":"cefb8f01d915880f6921f2501ff881ad94b9de61072c34d9cd19220992f97374"},{"path":"product/runtime/auths-gateway/Cargo.toml","sha256":"00b28be86921dcdc0ad90cce0c62c2961cafefe96ea6c2edf0e926c3d405ccad"},{"path":"product/runtime/auths-gateway/src/admin.rs","sha256":"2d5cc67afac42fbd15f36e2d1693cd1b20cedacf775040dce6ffe04ccc94c9ea"},{"path":"product/runtime/auths-gateway/src/app.rs","sha256":"6f80f63833ea0815bb44fbf3b0cc54624a08e9fb578b035819f2980dc04e8256"},{"path":"product/runtime/auths-gateway/src/audit.rs","sha256":"0edb2037eb7b5d6f13acfce85c54f62a82bf7fdd31bc7e626c4fec183cef61dd"},{"path":"product/runtime/auths-gateway/src/audit_tests.rs","sha256":"990969384a52d75bc2489d9d412a9e7dd814bca1c8f65c701d6205fae62a15d5"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway-harness.rs","sha256":"12b0c24d36b2e6a3be392d3c081a783b355fdd67dc5b54bacc0410e803116b8c"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway.rs","sha256":"8851f5e95b70540f64c1965f6f240e7d90968817c6396d59cda49a75e46f85fc"},{"path":"product/runtime/auths-gateway/src/binding.rs","sha256":"663b0ce878319511aa7d05722ab4ab2fa9be18817884ffb2ee9f131ff1e382d1"},{"path":"product/runtime/auths-gateway/src/bounds.rs","sha256":"9cfa0eae4973e5e047a198360b22f041708fa20276b0b90c2ec440f06915d64b"},{"path":"product/runtime/auths-gateway/src/bounds_aggregate_tests.rs","sha256":"ab34f227b7c8692ba1da88ccb32bb3687a66adf8353d8282fae905d4a88eb612"},{"path":"product/runtime/auths-gateway/src/bounds_tests.rs","sha256":"74136bc570da7b9338b5a1a1ed9d3fd892c55135160964f9d3ac0e2cf5741375"},{"path":"product/runtime/auths-gateway/src/connection.rs","sha256":"7b5d049c258a26ed1c93ecf860f51d051a8a65f9b93554af0b1ea93862398ec9"},{"path":"product/runtime/auths-gateway/src/credential_journal.rs","sha256":"7297fccaee5cd8622928e8e0a42bba50da7941970a6f682ecd300c41ee6509da"},{"path":"product/runtime/auths-gateway/src/echo_verify.rs","sha256":"6d453051665f823abd7354d5c50031d9524cf47d6092d2f09080ae814e3b9575"},{"path":"product/runtime/auths-gateway/src/engine.rs","sha256":"900dead51861e63c3cbb38e365a5152055e058489ddf18b06fb30cc21b1ffe19"},{"path":"product/runtime/auths-gateway/src/fuzzing.rs","sha256":"ed3b0028487eb546a3b0a91d115aa8f18bcea324b61620bfe8e35a9e6ab18758"},{"path":"product/runtime/auths-gateway/src/generation_floor.rs","sha256":"fe1510ec96ce0f67e9a78edbfa94b33eb7df64c0ac4d0a67901124dcd0164777"},{"path":"product/runtime/auths-gateway/src/harness.rs","sha256":"c87e479f3eb281960f6c9c80d43c7560d7ccb654b0154ec823d3fcec4884ac05"},{"path":"product/runtime/auths-gateway/src/lib.rs","sha256":"b182052835a2cd631d1f801a74788d6ac1ef9cae21ade9ab4ffc270cd6f667ed"},{"path":"product/runtime/auths-gateway/src/listener.rs","sha256":"aa08239bcbc1fcb55e8a212fbdf6a84f12985b0d436dcb51dc58b06e59e435f2"},{"path":"product/runtime/auths-gateway/src/observed_tests.rs","sha256":"a22be071695f89ca2578a4d82fd80d9cb82289213c9bdb8f0470f6b2dc3d9201"},{"path":"product/runtime/auths-gateway/src/observer.rs","sha256":"562ffcaea071c3856e0708dc2fe33516917e145d2438aabb75af0a2b6ba01046"},{"path":"product/runtime/auths-gateway/src/onboarding.rs","sha256":"0dfd7d67e7f02f18a28d1c86ca1b7751d7463f5efcdbe3825de0ad8cbccb3891"},{"path":"product/runtime/auths-gateway/src/operator.rs","sha256":"c3c36954a3e86723df035b47f43b85fc8ab3a6292983522b6258d5c6b4e6c4e4"},{"path":"product/runtime/auths-gateway/src/pending_vectors/attempts.rs","sha256":"47ef3c8cb1c5504d47ae9a0088705ce6715fe86bac1671a34a56fb38a64d0dd3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/bounds.rs","sha256":"e612217307e1da5b0eb5ee6582a7458bb064b8aa8a529fc6555b1b334127ab68"},{"path":"product/runtime/auths-gateway/src/pending_vectors/codes.rs","sha256":"e00670a5ef24eb856cc2c6dcda8e5a263842f55c76bb939c0c27bd9df37e5522"},{"path":"product/runtime/auths-gateway/src/pending_vectors/keys.rs","sha256":"f84c56f2ea9cb34b2b79c72d13fbf2c6585010ec1ed450af58a78c80c1ea1edd"},{"path":"product/runtime/auths-gateway/src/pending_vectors/mod.rs","sha256":"5de8340f0ef71a0b57a09e323fefe473d3160c6ae952b9ba46f714825fbacafc"},{"path":"product/runtime/auths-gateway/src/pending_vectors/outcomes.rs","sha256":"8ec07b9511b48913af36ac999d2aa0e82924289f6acb23ddaeb9f00f99815166"},{"path":"product/runtime/auths-gateway/src/pending_vectors/production.rs","sha256":"f574cabfa4687a4fc846b8f6a234b68ec53b876aed548b11445729cac1a55ede"},{"path":"product/runtime/auths-gateway/src/pending_vectors/recipes.rs","sha256":"51693208270231c25c3aef2a32151d5962114c71e86b88cb9df83181c7af83d9"},{"path":"product/runtime/auths-gateway/src/pre_entry.rs","sha256":"06ea78ca140468bfaba17d9ab04912ad68673954c3203c98fed28272ff2a00c0"},{"path":"product/runtime/auths-gateway/src/property_tests.rs","sha256":"939c081e2e154aaf10186754044bdd65608932c899b970a04a71d0afaa999a93"},{"path":"product/runtime/auths-gateway/src/qualification.rs","sha256":"d5078a81dc89f30958a7d8fdabfe164c3411c441dd7d9015002681a58883b63a"},{"path":"product/runtime/auths-gateway/src/qualification_tests.rs","sha256":"4473add5729b97faf04d7be7fd8cf3bbacd7f545e1b61c7d2782563011906b4d"},{"path":"product/runtime/auths-gateway/src/quorum_tests.rs","sha256":"a78380b019104d688c11a4410082c7e08ded3106aab099954c4f8a1b4ae0fd89"},{"path":"product/runtime/auths-gateway/src/readiness.rs","sha256":"911c3f11892f94641574375e2da4c671c802738f71082f12c39832331052d43d"},{"path":"product/runtime/auths-gateway/src/recipe.rs","sha256":"fecf9af67e7afc48d080e9f8f55f8ce28e49d0e08988717a27908bbda461d6b6"},{"path":"product/runtime/auths-gateway/src/recipe/lower.rs","sha256":"8088b8751ed831dbb48247af953c6290ac95e2a438ccd5bd65eff54be06a1fd1"},{"path":"product/runtime/auths-gateway/src/recipe/review.rs","sha256":"c3eb7d9fdd98dacf52750b14b67ad7b7faaecbbdeafff1e0b049f67d0a2d0139"},{"path":"product/runtime/auths-gateway/src/recipe/runtime.rs","sha256":"c286f0d15f974402822c0810d8e97f98411dc1c557755cc23e540d85e2bb42d9"},{"path":"product/runtime/auths-gateway/src/recipe/source.rs","sha256":"1af50298fb1461e1b24cbdf560d43124d6b1c4c529586c911b1c4797214a69ff"},{"path":"product/runtime/auths-gateway/src/recipe/tests.rs","sha256":"aac551a2481bbc60864c64079bc667dcb232e45a0f41a04073ed84ab5dbe1fce"},{"path":"product/runtime/auths-gateway/src/recipe/validate.rs","sha256":"3711b17605cb7b0d639bc1b180449231f5882a306cab20e2c7782155cc63b0d4"},{"path":"product/runtime/auths-gateway/src/scenario_tests.rs","sha256":"d8271761b12597bfe1233f8eb5ad1d4e5498c5d03388e832e24ab818484a1de4"},{"path":"product/runtime/auths-gateway/src/separation.rs","sha256":"be9306848ca5d801767cf6aa14247c8618312ef0e202f00ce0c24c4844491061"},{"path":"product/runtime/auths-gateway/src/store.rs","sha256":"1e5288345c2cb1421aeda277b3158d07607404b0ec46943222ac107b63dcbb46"},{"path":"product/runtime/auths-gateway/src/store_testkit.rs","sha256":"88d82fee42f1b8ef521e8deef0216e938ebeaad822eb2f5020e70b89d145ea70"},{"path":"product/runtime/auths-gateway/src/submit.rs","sha256":"c78dbbba7c45b443febf655056c5edcd635e77be7b21c5b2c318097502415ffe"},{"path":"product/runtime/auths-gateway/src/support.rs","sha256":"9fd979029793a22b15d9776a7fc172476fd7c126a80d4080c65d720845becbcb"},{"path":"product/runtime/auths-gateway/src/transport.rs","sha256":"be2c6dc75b8daec110bf8749fedc3823f6067d40b999aa3eb21126896a97d3ad"},{"path":"product/runtime/auths-kernel-runtime/Cargo.toml","sha256":"926bcd0053e5edd703be8f0027ad009e2982db013c8174c1366edbf38b48087d"},{"path":"product/runtime/auths-kernel-runtime/src/lib.rs","sha256":"7108faae9ca4bc32dc093ddaf885ac8f74f3c9b8d317b7c7d0ed00d1d0ab5972"},{"path":"product/runtime/auths-lifecycle/Cargo.toml","sha256":"c5053c705f8d5554b44e432fe75287a2faf11d644e5a2552e45ad6cd94176af5"},{"path":"product/runtime/auths-lifecycle/src/codec.rs","sha256":"51c4b746749150e8bfcd8ff972b3f6c1ef40bec15583448ec1b471d9ad737dc0"},{"path":"product/runtime/auths-lifecycle/src/digest.rs","sha256":"55282cd7d8aba37713c2dcb5357c9877819edb72a30eadefb860d28d7d3a3eb7"},{"path":"product/runtime/auths-lifecycle/src/identifier.rs","sha256":"31620e8c16de68d3d2d3b84d6353c1a5b9d4151d8247f91fa389b906a8e660f1"},{"path":"product/runtime/auths-lifecycle/src/kernel.rs","sha256":"2abb8c094b36d35b364e74d78091d14c5d6f3d1eb6552cca3b5538dbd017ce23"},{"path":"product/runtime/auths-lifecycle/src/lib.rs","sha256":"afe5a345cd309b5a4f08ffba3170a6d7f16ff914892b3f2006d5208ed24ec736"},{"path":"product/runtime/auths-lifecycle/src/model.rs","sha256":"1af12bbeeeaa65ec02ddcebd7d2c8c92ec1e339fa40ae85b45ab9b01a722a4fa"},{"path":"product/runtime/auths-lifecycle/src/operation.rs","sha256":"78e6d05fcf5d7ea4f148032a3fa26fdfcab77eb346019effe927b08e0d64d732"},{"path":"product/runtime/auths-lifecycle/src/registry.rs","sha256":"53495fe6f7a77422593a41623e28716f1c140dcc1e00f87f6b0ffbfb93a5ef90"},{"path":"product/runtime/auths-lifecycle/src/sealed.rs","sha256":"2e0c03b5813c926c159598bb7890d1523825edbe57cd687d42a5dfb3374a0c19"},{"path":"product/runtime/auths-lifecycle/src/test_support.rs","sha256":"221d9a5c5ef8e1f9f8fd66927484eaf813571d0568470278ecd8fa08a5eec8cd"},{"path":"product/runtime/auths-lifecycle/src/transition.rs","sha256":"011805a28efdd541f44ccea54dd0e34a1e58f4004447ee58013703b4fb6b2822"},{"path":"product/runtime/auths-runtime/Cargo.toml","sha256":"dd29d80a8b4bb56c869f036a6c9998f6e6d1c0383ac5dc03fa42b24abe2a7ff7"},{"path":"product/runtime/auths-runtime/src/lib.rs","sha256":"132ca03d58c14905d3a822a4972f42a22a5ad33a45f2ba9ca44f3a57d810b4b0"},{"path":"product/runtime/auths-runtime/src/production.rs","sha256":"fd4eff4270c571c10fcff6cf27df28961ebf074de8a1a028f500fda1ca376820"},{"path":"product/sdk/auths-approval-quorum/Cargo.toml","sha256":"df904971fca87a24194c5816738a331588fe8f164acb5d70839a35dca5f57114"},{"path":"product/sdk/auths-approval-quorum/src/lib.rs","sha256":"72e4086088a1c0912e4e1a9e980f26a5c280bf5ab16ea39c9f0f58d5096ac2ce"},{"path":"product/sdk/auths-approval-quorum/src/remote.rs","sha256":"9fa029c7c63003adf260f8aec55160c545681c60c1bace0d934e7525862aac7b"},{"path":"product/sdk/auths-approval-quorum/src/remote_tests.rs","sha256":"8a09ce17cfee82a035a74edd535f3ebeb3db0e078784740d3997b17dbdb10197"},{"path":"product/sdk/auths-approval-quorum/src/tests.rs","sha256":"0acbf12be3e497dcc6c2d8f29c9af3b1a7ed8e11b75f6399570d4f217a785060"},{"path":"product/stores/auths-stores/Cargo.toml","sha256":"a32c4b76d17b264be5d40d24497ff237e1ed87822e8bab86229b3db93106dbe3"},{"path":"product/stores/auths-stores/src/gateway_attempt.rs","sha256":"185da8f4a220fba836d5b78a9311f03204681c43a3c53951008084d135bf4d21"},{"path":"product/stores/auths-stores/src/lib.rs","sha256":"e721262edf8a9ab5568ddc27639176312d4a366203b5f73e2d7c11fde2c554e9"},{"path":"product/stores/auths-stores/src/lifecycle.rs","sha256":"94f64d25bc178a9e60ba3c0ee6915d7fb3af7c4468792d76b4e70f43f4de1e2f"}],"schema":"auths.gateway-semantic-closure/1"} \ No newline at end of file +{"files":[{"path":"Cargo.lock","sha256":"c94ed342774d5e2823f01ecf74b8a4812c5f9a6b0cf811d31f2e2cecb671a275"},{"path":"Cargo.toml","sha256":"6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24"},{"path":"core/adapters/auths-did-keri/Cargo.toml","sha256":"86ba3e3f9a0a70d970568bfb3113b7ba7bbdd81c3eebbb52743dd574a0c0ecaa"},{"path":"core/adapters/auths-did-keri/src/lib.rs","sha256":"a75674842f8a7142004369ccd206ab43e476459293f0ff4bed4d4e659031b3e3"},{"path":"core/adapters/auths-did-key/Cargo.toml","sha256":"d5a3ae07ecde83f91eed4c3785051dd0f44eab6c891754f3309b6b40596707d7"},{"path":"core/adapters/auths-did-key/src/lib.rs","sha256":"b76a3f4528a725df53cfa9242e6e414e1d26caa48468aaed497e28b121f4497c"},{"path":"core/adapters/auths-raw-key/Cargo.toml","sha256":"f49616bc18c19e6aaa7e6a02ccebcdb9f5c1422c1278ef9869e0dbf22ceda7be"},{"path":"core/adapters/auths-raw-key/src/lib.rs","sha256":"45eec1b295dac3bed65cd79c942870b926b06b3f5d38eaebaeb6140ac69315fa"},{"path":"core/crates/auths-algebra-kernel/Cargo.toml","sha256":"0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba"},{"path":"core/crates/auths-algebra-kernel/src/generated.rs","sha256":"ae4bcbef42a408c7ffa0c6a74a42f7de177a6f14479e51d205acf830bda05960"},{"path":"core/crates/auths-algebra-kernel/src/lib.rs","sha256":"6654667eeb9b353d6648954c9fd2e8838462a82ce6b2803eb49e1366892c68c6"},{"path":"core/crates/auths-assurance/Cargo.toml","sha256":"afcb12a97ddd09d7a264b9ecd3fcaefc865ff2c9b4539ee85b00883420ba333a"},{"path":"core/crates/auths-assurance/src/lib.rs","sha256":"0fb2ec844d674b25a9e20b1601452c89c2454901fa506adfa9bb38ef9a7fa213"},{"path":"core/crates/auths-author/Cargo.toml","sha256":"1e6f0e3bc079ddb558decf0db26b291c6e72fc47327b6df1b7650d41689b215f"},{"path":"core/crates/auths-author/src/lib.rs","sha256":"e14475f2f49715a1869d5fa6b11ff1fbb72497e39097e09f833b0bae7e5b3f2b"},{"path":"core/crates/auths-author/src/observations.rs","sha256":"dda7d6bfa6f4bd7e95a480ca283c2c0e996f69c5c15cb0c7197af328131a7066"},{"path":"core/crates/auths-authority/Cargo.toml","sha256":"4f68212938029f79ebd857b4f3038494eb85d0163d49f07e51376715cf959815"},{"path":"core/crates/auths-authority/src/lib.rs","sha256":"da88d5194de4e17449e69972c0fb042afa3c39798a8f570f30771e77c384f1eb"},{"path":"core/crates/auths-codec/Cargo.toml","sha256":"e20e51826e17814effd9d8925d18d5fbdd6c0d37bf50231e743ec2611314722c"},{"path":"core/crates/auths-codec/src/approval.rs","sha256":"fbff43bf4d57f69f8b7738a8647751cde75c5a932dee65d924a1fe9c7202f91f"},{"path":"core/crates/auths-codec/src/bounded_policy.rs","sha256":"d21f6728be2d8a04b6d94921f2b683f7e61cbb42e0ac6866f1c88a49caa534c3"},{"path":"core/crates/auths-codec/src/decode.rs","sha256":"ba2999584cdf53b1b517ecb9c7ea50d39efee17c666a9a38e2ad1ac94379f778"},{"path":"core/crates/auths-codec/src/encode.rs","sha256":"8491192053e2e15d62b4d2a491de22405b7487ead69ab6f6bca40669ce7ca5f7"},{"path":"core/crates/auths-codec/src/error.rs","sha256":"fecb0737c16deb42d859f1dc7727c698438d9ac12064fd99e0024629642c390c"},{"path":"core/crates/auths-codec/src/hash.rs","sha256":"f88e111f1dbb2cef6b7b5e9c948cb45ff92e366710c8a5f5c636138aa748479e"},{"path":"core/crates/auths-codec/src/lib.rs","sha256":"3b0e5c94c6f34f750b88a9333e1d5c8145746d845d3a23e0d2f61807cf592ea7"},{"path":"core/crates/auths-codec/src/observation.rs","sha256":"38328b0c71ff97a4196eeade8b4faa889527ff1f80bb168468bcd49082a3987e"},{"path":"core/crates/auths-composition/Cargo.toml","sha256":"331e13025eb82588b5269ed3975929eb41c823d588c49e4c296273d85c6fe80e"},{"path":"core/crates/auths-composition/src/lib.rs","sha256":"e42e3b0b6a9985b73c533aeb23799c638979aa27a9ce7d0f10a8d60340570fb1"},{"path":"core/crates/auths-model/Cargo.toml","sha256":"565c15302b0cc9270db1e28efa3862804846850ba933cc17aea8abcec4a65987"},{"path":"core/crates/auths-model/src/approval.rs","sha256":"54cf44a9ef747ec21546a4086aecfb130bc7803b0d646430e6082df51e6e305f"},{"path":"core/crates/auths-model/src/bounded.rs","sha256":"f90496abc0a06c028b4d850af6ddab7d850bfafeaa3d042f1b1246a41d8bbbc9"},{"path":"core/crates/auths-model/src/bounded_policy.rs","sha256":"306a8f049cc7cfc7635fe0e4de47eb7813eed63d3c14c3be2b51586aa4eea450"},{"path":"core/crates/auths-model/src/lib.rs","sha256":"e7cfe6bb9574c6b016aa63e70658c31e0b90903ec6479a49f4a2ceb64f5bad97"},{"path":"core/crates/auths-model/src/observation.rs","sha256":"b3ed3e3cc090afca2896a7d3de7988afccc1ee1ea0ebd91b51a8bc0f20ad8dbb"},{"path":"core/crates/auths-multikey/Cargo.toml","sha256":"858756c1197befcada06134742bffe8d58cf674cadd6c046bf710570e96efaf2"},{"path":"core/crates/auths-multikey/src/lib.rs","sha256":"f5177fffb11e40eeaaa665ba886c541fc1f24d5eacdd6983fb03dc20148733f0"},{"path":"core/crates/auths-ports/Cargo.toml","sha256":"596a9b0f5af3717c16a6d13f7054d8a106bcd9f01f5f72c2235dd2afcf0ab16c"},{"path":"core/crates/auths-ports/src/binding.rs","sha256":"a16c012d40aa4249e3ec54372b9611006d0bfe8c7dc3c741911c2194ad17736d"},{"path":"core/crates/auths-ports/src/diagnostics.rs","sha256":"aa596572503b5a65a918bb2ff38281c144ff53821ee914e9325c852828d852df"},{"path":"core/crates/auths-ports/src/lib.rs","sha256":"8da1debf86f9532df0660155d04298beb1ba3a1204508f8586e2e67cd2fb3449"},{"path":"core/crates/auths-ports/src/path.rs","sha256":"b68fc547b4e4d97a60cbbc1cc1939fc6b34a8233b81f840bd396914a707e3ea1"},{"path":"core/crates/auths-raw-key-core/Cargo.toml","sha256":"98c0bc8527a537512e43a74dd6ba9658c6f0cdc16610cf938e3f9b43785d836d"},{"path":"core/crates/auths-raw-key-core/src/lib.rs","sha256":"98c0500c41697aae28708ad0bf970b9a97583d96a3d2c18d23e7fa351e0f7d12"},{"path":"core/crates/auths-registries/Cargo.toml","sha256":"590e49e58b0622d9d6274fea46796dcdb07dec9550eff295cce6a6427ffa51e2"},{"path":"core/crates/auths-registries/src/lib.rs","sha256":"450d3886d85ee333b7e046317fb5b47cde62483d5f3e41d46265e2caf4c373ec"},{"path":"core/crates/auths-registries/src/template.rs","sha256":"1224039dd2b3ce6fa8357613d8cafbae40400493da7176da202b9ade62fa05e4"},{"path":"core/crates/auths-signature-core/Cargo.toml","sha256":"6bee2230eb30af1be0bd5c2d57bd3e1903497a70028d47290d4ac6e9e0e8bca0"},{"path":"core/crates/auths-signature-core/src/lib.rs","sha256":"6e3f9311ded5e49ea50d445eb21e6d8fa12442aa4362a73e0cb6fda15b7cd865"},{"path":"core/crates/auths-signature/Cargo.toml","sha256":"7f7b5682466ba439d8c59579022cb61068cad9fb4bd2d73e1cc21327c902b450"},{"path":"core/crates/auths-signature/src/lib.rs","sha256":"b3d9ac4cc3ba0797b9e1c09f2d6ac05089b25dac4e285a5af28c0165b33d925b"},{"path":"core/crates/auths-verifier/Cargo.toml","sha256":"c43358e06a33324b41a8b93e5cc7279c55f7d21f1f6cfaa539a3fc7b4c27a38f"},{"path":"core/crates/auths-verifier/src/approval.rs","sha256":"c3cae6a49e169051eb555bb092b1069a4d422516d6a2114623a89e5f31ff923f"},{"path":"core/crates/auths-verifier/src/causal.rs","sha256":"9635230f33b13a263573d319ac8a1976addbcc07677514a43e3c7bf28dc04587"},{"path":"core/crates/auths-verifier/src/lib.rs","sha256":"f22dec38dfa47ced8da4f605390da8453273bee1da010f57fd1fdfcb10e0b389"},{"path":"core/crates/auths-verifier/src/observation.rs","sha256":"0bb07f06a0f9524c88427df1c972b1de8ba038a9eeeb15d3134c25125ae84b1e"},{"path":"core/crates/auths-verifier/src/trace.rs","sha256":"2213d72023a1d9e0413a2cf2c51c3dad9e04775d86033a0caaa9d29a8f0036f8"},{"path":"exchange/crates/auths-proof-exchange-model/Cargo.toml","sha256":"34b2db64f93a288e942b5a3918d28cdcbef906e0dc9074ce848018d3d5f7a1fa"},{"path":"exchange/crates/auths-proof-exchange-model/src/lib.rs","sha256":"49fac5aff2339d3a57c41cb8bb2a82852538e8f77ecc4b157c88e264ff31fb55"},{"path":"exchange/crates/auths-proof-exchange-port/Cargo.toml","sha256":"7ff660f1b7579dc570c791090aeb450404fbbf44c92781e289f5ccdde746d739"},{"path":"exchange/crates/auths-proof-exchange-port/src/lib.rs","sha256":"b408fb40c6432edc1facb3d8b3e9433a033f8dc73fe2e0ba5a88c972ca675021"},{"path":"product/config/auths-config/Cargo.toml","sha256":"e4b568ab9f6d84f7d7e6d66443fe825f360db9c27bc7c31d6ddc0647ba3ab304"},{"path":"product/config/auths-config/src/lib.rs","sha256":"fecf00ea65cef9018fda9af2063326d7065b869266d0d9e73a4f06816f1102cc"},{"path":"product/errors/auths-errors/Cargo.toml","sha256":"3b3a199b6460ba75bda84475bb5accd35e1485448a3981038db85bf4772dd350"},{"path":"product/errors/auths-errors/src/lib.rs","sha256":"7feeb9069fa4003f94f1f07c1c94619cf1c883e0dbaaf2187f04d0f742264bdd"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/Cargo.toml","sha256":"716f1f2a117d6d69d8effe9ee9057e24ba3502f20af6a602b06facb638cdabed"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/api.rs","sha256":"9ea61dd7ddd93282b073b98e453e6b75b26dc49689c04e9782435d06a3a09e48"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/clock.rs","sha256":"73f0a6e0f5903883329fa6683f5888288f759512ac69e5c87efd2b6b87f7d79f"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/http.rs","sha256":"14c1fce14e24c984b2a275563a29b6326fb08367922b6e8d37ba38b9cb81aa2b"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/identity.rs","sha256":"186de11230c8b33375951c4368609f8976bf9795f171af3fd7fac26207a94361"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs","sha256":"0b4617d044f5254a5ab22f5a2578f91cc025206a8c1845be39c1c56dcdf7a5df"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/names.rs","sha256":"41bb23572d6002e23ee103d6fe70ecd68764861c6f2e48a1c53af998270a4afa"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs","sha256":"39fed883f4802e68d3b41a68fea0aba0737810996b33d13577de70faba004c29"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/store.rs","sha256":"fc60ee9c49b2f4f063c449b4c78100c5c4872779e94ca168f796603b380ef6e4"},{"path":"product/integrations/auths-custody/Cargo.toml","sha256":"1e14034185ad1ec24a977fd5f41d0abee219606245c046ce2a82287fadef448b"},{"path":"product/integrations/auths-custody/src/conformance.rs","sha256":"8ed1afd58f18fc6becc268908aa6419c9aa404c79da0197963eb2599df44acf6"},{"path":"product/integrations/auths-custody/src/key.rs","sha256":"70cbb0fd21b6f5652157845a22c35be2d0f6c05b3d138fc4b9bb6dbdc3d81c40"},{"path":"product/integrations/auths-custody/src/lib.rs","sha256":"8ee593c1f59b0fd2126bdda9138026f5bc531beb64d4489a99785842e7b98b43"},{"path":"product/operations/auths-operations/Cargo.toml","sha256":"73dde1e914ba5e1386f8d49c0d730423cc72ae77ec44c6554a6a75cc8e8922b1"},{"path":"product/operations/auths-operations/src/explanation.rs","sha256":"b4a39bcbd5712cb9e735ee7deeb281f3fa6af5ddca973735bf3d87dce427ef11"},{"path":"product/operations/auths-operations/src/lib.rs","sha256":"3f401a56555113b98f57bca172a2660eaecedf76247b83a3fdbb089c133a29cd"},{"path":"product/operations/auths-operations/src/render/json.rs","sha256":"2ae042639960afee123730e945d373bc5dda1d2b3af20ae16c939a7e99b9e418"},{"path":"product/operations/auths-operations/src/render/mod.rs","sha256":"b3b7f6fe473f49227ace5a68bfc3d8dc14b5db8dd9888fd9e207070337b1b8bf"},{"path":"product/operations/auths-operations/src/render/text.rs","sha256":"f216cf3bdb00e264523271b16e7059535ac6b1aabf271cebd7935af155e4bfec"},{"path":"product/policy/auths-bounded-policy/Cargo.toml","sha256":"babd5d200923137ead71d8c2528f847cea323ce98da942a1320b054436612c47"},{"path":"product/policy/auths-bounded-policy/src/arithmetic.rs","sha256":"75e43c5d4eab8d1f71c1daf53839f5f9fe45a400afc1f63a30c6f55ce3632627"},{"path":"product/policy/auths-bounded-policy/src/commitment.rs","sha256":"c5706f2d583454e1a7f570f7ada138d4d864bef0205dfae7c1296774f396bb3f"},{"path":"product/policy/auths-bounded-policy/src/eligibility.rs","sha256":"c9acdfb793074e687fc36efad506be27dbd99ffbf40387bc66c8de39ef238432"},{"path":"product/policy/auths-bounded-policy/src/identifier.rs","sha256":"0006a32bae9eb16c4178cf797df418d2b0a781f2bc6474b741dc1a908141831c"},{"path":"product/policy/auths-bounded-policy/src/kernel.rs","sha256":"99187c28b161ac70bee1afed60711f7f645adb4d1671a01863f9849b369811d5"},{"path":"product/policy/auths-bounded-policy/src/lib.rs","sha256":"76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c"},{"path":"product/policy/auths-bounded-policy/src/receipt.rs","sha256":"3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad"},{"path":"product/policy/auths-bounded-policy/src/registry.rs","sha256":"4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0"},{"path":"product/profiles/auths-profile-api/Cargo.toml","sha256":"7ae85761f58625b5d678f961fd052eebf3e000ef565c7312e3ac857763c0017f"},{"path":"product/profiles/auths-profile-api/src/lib.rs","sha256":"a194b82b20bf8aa864c2334ef6c6aec30b2154ded972862252d5dcefa488ab95"},{"path":"product/profiles/auths-profile-mcp/Cargo.toml","sha256":"db264fc25242f7b7e4133cbe5782545b3107b406c87168ae072683cfb59eac66"},{"path":"product/profiles/auths-profile-mcp/src/arguments.rs","sha256":"a5de696586d507e2aee4a49fee99ef1ef4c51a2e46603f8838f1af6d9009833f"},{"path":"product/profiles/auths-profile-mcp/src/lib.rs","sha256":"d0f8b733a09ef8408336cdebc8948d6a5861012ce6878598b11be7084dfd4280"},{"path":"product/profiles/auths-profile-mcp/src/session.rs","sha256":"166c281fa66333388e4760d6098dad02d3359e1d5de4b8f93312c014f97abb03"},{"path":"product/qualification/auths-recipe-qualification/Cargo.toml","sha256":"b7b15b30b9a3d96d4f089d514266d3a892de6608d30707aa44be31cca89ca9fe"},{"path":"product/qualification/auths-recipe-qualification/src/canonical.rs","sha256":"30a9b50777f0dcb4b606abfee2467d5a975d9f6ad941ab6c13ca3df5b359f667"},{"path":"product/qualification/auths-recipe-qualification/src/closure.rs","sha256":"0ad6aee9bd981e2863fa725f209ec84031db2ff12f4c7ac3aaf5120f0bb86039"},{"path":"product/qualification/auths-recipe-qualification/src/error.rs","sha256":"52d5cf720a1e4579008fdda90a3ac2c31f0b8db57985f121f65e54b4da2b7dd1"},{"path":"product/qualification/auths-recipe-qualification/src/evidence.rs","sha256":"1a4cb862f725b02f9efd827db99637ea8178a5236aa020ec271a363edbe7b362"},{"path":"product/qualification/auths-recipe-qualification/src/ids.rs","sha256":"e81a906d571497ab2da753e1532d4443706410e0b75fdd59a7d2d788c7aec403"},{"path":"product/qualification/auths-recipe-qualification/src/lib.rs","sha256":"195b19f46e1e94a0f3594ad5958e5715bc5e3ad415bdfe6428dfc1b6dd3f4631"},{"path":"product/qualification/auths-recipe-qualification/src/model.rs","sha256":"3484eb0ec287b23d4682ade7b1b0f8d1335985b3fb180f06fc28716076957d5f"},{"path":"product/qualification/auths-recipe-qualification/src/release.rs","sha256":"d816b53e2275e902c750ad03803061844e259e28560ab2d1c77e8a43981a4d6a"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/mod.rs","sha256":"7f15b68e05a04f202bcb1fb80de1d9a9a4fda8bfd6af2cd4e5c660fc75d96fe5"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/schemas.rs","sha256":"c59feec2805621f341a90f81fc005e2c12f7a70f9d264fdeacccb2be4fe1c046"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/verification.rs","sha256":"6a6b5834c5dae10af1ba8939b2deae43b85db71544dc8f077ff63b7fe68ac8a8"},{"path":"product/qualification/auths-recipe-qualification/src/verify.rs","sha256":"edd33589c54fb79bcfccc4cf4e6ccf95bbca088318bb7f8dfc27da684b4fa671"},{"path":"product/receipts/auths-receipts/Cargo.toml","sha256":"6001fa1375899953aafcb07c23a6da0c8f57ea7ec08bb9c950b12a60a8cc6f0f"},{"path":"product/receipts/auths-receipts/src/disclosure.rs","sha256":"ba9ed439be0a320c8a01f5b6e9b51361c1a37e076947490d8e4a484ba6bb119c"},{"path":"product/receipts/auths-receipts/src/lib.rs","sha256":"547a57c4160256719cafb7d0ab972d9fc80b0da14fbbce4148c70c414070ff36"},{"path":"product/runtime/auths-connections/Cargo.toml","sha256":"babeb6e1dda3dfb66291713ce1e43dce5c349833d0b50ea4dccbf986030026b2"},{"path":"product/runtime/auths-connections/src/credential.rs","sha256":"82921413bb053f0f6c7931fbd4e6a86c8cc1d8c6b51debd9c2cef33a8d5b1c51"},{"path":"product/runtime/auths-connections/src/kernel.rs","sha256":"a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8"},{"path":"product/runtime/auths-connections/src/lib.rs","sha256":"79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22"},{"path":"product/runtime/auths-connections/src/model.rs","sha256":"de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77"},{"path":"product/runtime/auths-connections/src/registry.rs","sha256":"e57640e003e72ad3235c567c2bb944a262bd64e673f023b62ea091094cc7e946"},{"path":"product/runtime/auths-gateway-kernel/Cargo.toml","sha256":"34f864e67656af4ac7e5c7a347a23f01fc8ab31365b8e23c0ef474483b14a183"},{"path":"product/runtime/auths-gateway-kernel/src/construct.rs","sha256":"e9d65744bae273d65face4285e5d2da75c06a92ab48f7b8333d496604e31c63c"},{"path":"product/runtime/auths-gateway-kernel/src/lib.rs","sha256":"cfda6f8453426564c085475f183b6f790b438768a19668f1b65d33ba59dc8632"},{"path":"product/runtime/auths-gateway-kernel/src/order.rs","sha256":"e0045f877c4b7fe3860c291039853885064ddcdebba7c9b345ab65e81e646dda"},{"path":"product/runtime/auths-gateway-kernel/src/outcome.rs","sha256":"e9785b1afe70788c89b51b18655bcd5acff7b0c8e3d12fb79c6f05a202e67e6b"},{"path":"product/runtime/auths-gateway-kernel/src/ratio.rs","sha256":"7ace22264812e6fc1ef3a62afee402cf43494bb71ae0d3de219ad1b39d690bcb"},{"path":"product/runtime/auths-gateway-kernel/src/recovery.rs","sha256":"9f46dcd1685ab6e4d1ba04a3fc286a9f3afee8fb47829be1fbc670a7926a2dc6"},{"path":"product/runtime/auths-gateway-kernel/src/transition.rs","sha256":"cefb8f01d915880f6921f2501ff881ad94b9de61072c34d9cd19220992f97374"},{"path":"product/runtime/auths-gateway/Cargo.toml","sha256":"00b28be86921dcdc0ad90cce0c62c2961cafefe96ea6c2edf0e926c3d405ccad"},{"path":"product/runtime/auths-gateway/src/admin.rs","sha256":"2d5cc67afac42fbd15f36e2d1693cd1b20cedacf775040dce6ffe04ccc94c9ea"},{"path":"product/runtime/auths-gateway/src/app.rs","sha256":"6f80f63833ea0815bb44fbf3b0cc54624a08e9fb578b035819f2980dc04e8256"},{"path":"product/runtime/auths-gateway/src/audit.rs","sha256":"0edb2037eb7b5d6f13acfce85c54f62a82bf7fdd31bc7e626c4fec183cef61dd"},{"path":"product/runtime/auths-gateway/src/audit_tests.rs","sha256":"990969384a52d75bc2489d9d412a9e7dd814bca1c8f65c701d6205fae62a15d5"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway-harness.rs","sha256":"12b0c24d36b2e6a3be392d3c081a783b355fdd67dc5b54bacc0410e803116b8c"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway.rs","sha256":"8851f5e95b70540f64c1965f6f240e7d90968817c6396d59cda49a75e46f85fc"},{"path":"product/runtime/auths-gateway/src/binding.rs","sha256":"663b0ce878319511aa7d05722ab4ab2fa9be18817884ffb2ee9f131ff1e382d1"},{"path":"product/runtime/auths-gateway/src/bounds.rs","sha256":"9cfa0eae4973e5e047a198360b22f041708fa20276b0b90c2ec440f06915d64b"},{"path":"product/runtime/auths-gateway/src/bounds_aggregate_tests.rs","sha256":"ab34f227b7c8692ba1da88ccb32bb3687a66adf8353d8282fae905d4a88eb612"},{"path":"product/runtime/auths-gateway/src/bounds_tests.rs","sha256":"74136bc570da7b9338b5a1a1ed9d3fd892c55135160964f9d3ac0e2cf5741375"},{"path":"product/runtime/auths-gateway/src/connection.rs","sha256":"7b5d049c258a26ed1c93ecf860f51d051a8a65f9b93554af0b1ea93862398ec9"},{"path":"product/runtime/auths-gateway/src/credential_journal.rs","sha256":"7297fccaee5cd8622928e8e0a42bba50da7941970a6f682ecd300c41ee6509da"},{"path":"product/runtime/auths-gateway/src/echo_verify.rs","sha256":"6d453051665f823abd7354d5c50031d9524cf47d6092d2f09080ae814e3b9575"},{"path":"product/runtime/auths-gateway/src/engine.rs","sha256":"f1052aaef43e441b9e0befa3f8ad1e2fd5279a27cb9d63aac0cf9dfdbe85a052"},{"path":"product/runtime/auths-gateway/src/fuzzing.rs","sha256":"ed3b0028487eb546a3b0a91d115aa8f18bcea324b61620bfe8e35a9e6ab18758"},{"path":"product/runtime/auths-gateway/src/generation_floor.rs","sha256":"fe1510ec96ce0f67e9a78edbfa94b33eb7df64c0ac4d0a67901124dcd0164777"},{"path":"product/runtime/auths-gateway/src/harness.rs","sha256":"c87e479f3eb281960f6c9c80d43c7560d7ccb654b0154ec823d3fcec4884ac05"},{"path":"product/runtime/auths-gateway/src/lib.rs","sha256":"b182052835a2cd631d1f801a74788d6ac1ef9cae21ade9ab4ffc270cd6f667ed"},{"path":"product/runtime/auths-gateway/src/listener.rs","sha256":"aa08239bcbc1fcb55e8a212fbdf6a84f12985b0d436dcb51dc58b06e59e435f2"},{"path":"product/runtime/auths-gateway/src/observed_tests.rs","sha256":"a22be071695f89ca2578a4d82fd80d9cb82289213c9bdb8f0470f6b2dc3d9201"},{"path":"product/runtime/auths-gateway/src/observer.rs","sha256":"562ffcaea071c3856e0708dc2fe33516917e145d2438aabb75af0a2b6ba01046"},{"path":"product/runtime/auths-gateway/src/onboarding.rs","sha256":"0dfd7d67e7f02f18a28d1c86ca1b7751d7463f5efcdbe3825de0ad8cbccb3891"},{"path":"product/runtime/auths-gateway/src/operator.rs","sha256":"c3c36954a3e86723df035b47f43b85fc8ab3a6292983522b6258d5c6b4e6c4e4"},{"path":"product/runtime/auths-gateway/src/pending_vectors/attempts.rs","sha256":"47ef3c8cb1c5504d47ae9a0088705ce6715fe86bac1671a34a56fb38a64d0dd3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/bounds.rs","sha256":"e612217307e1da5b0eb5ee6582a7458bb064b8aa8a529fc6555b1b334127ab68"},{"path":"product/runtime/auths-gateway/src/pending_vectors/codes.rs","sha256":"e00670a5ef24eb856cc2c6dcda8e5a263842f55c76bb939c0c27bd9df37e5522"},{"path":"product/runtime/auths-gateway/src/pending_vectors/keys.rs","sha256":"f84c56f2ea9cb34b2b79c72d13fbf2c6585010ec1ed450af58a78c80c1ea1edd"},{"path":"product/runtime/auths-gateway/src/pending_vectors/mod.rs","sha256":"5de8340f0ef71a0b57a09e323fefe473d3160c6ae952b9ba46f714825fbacafc"},{"path":"product/runtime/auths-gateway/src/pending_vectors/outcomes.rs","sha256":"8ec07b9511b48913af36ac999d2aa0e82924289f6acb23ddaeb9f00f99815166"},{"path":"product/runtime/auths-gateway/src/pending_vectors/production.rs","sha256":"f574cabfa4687a4fc846b8f6a234b68ec53b876aed548b11445729cac1a55ede"},{"path":"product/runtime/auths-gateway/src/pending_vectors/recipes.rs","sha256":"51693208270231c25c3aef2a32151d5962114c71e86b88cb9df83181c7af83d9"},{"path":"product/runtime/auths-gateway/src/pre_entry.rs","sha256":"06ea78ca140468bfaba17d9ab04912ad68673954c3203c98fed28272ff2a00c0"},{"path":"product/runtime/auths-gateway/src/property_tests.rs","sha256":"939c081e2e154aaf10186754044bdd65608932c899b970a04a71d0afaa999a93"},{"path":"product/runtime/auths-gateway/src/qualification.rs","sha256":"d5078a81dc89f30958a7d8fdabfe164c3411c441dd7d9015002681a58883b63a"},{"path":"product/runtime/auths-gateway/src/qualification_tests.rs","sha256":"4473add5729b97faf04d7be7fd8cf3bbacd7f545e1b61c7d2782563011906b4d"},{"path":"product/runtime/auths-gateway/src/quorum_tests.rs","sha256":"a78380b019104d688c11a4410082c7e08ded3106aab099954c4f8a1b4ae0fd89"},{"path":"product/runtime/auths-gateway/src/readiness.rs","sha256":"911c3f11892f94641574375e2da4c671c802738f71082f12c39832331052d43d"},{"path":"product/runtime/auths-gateway/src/recipe.rs","sha256":"fecf9af67e7afc48d080e9f8f55f8ce28e49d0e08988717a27908bbda461d6b6"},{"path":"product/runtime/auths-gateway/src/recipe/lower.rs","sha256":"8088b8751ed831dbb48247af953c6290ac95e2a438ccd5bd65eff54be06a1fd1"},{"path":"product/runtime/auths-gateway/src/recipe/review.rs","sha256":"c3eb7d9fdd98dacf52750b14b67ad7b7faaecbbdeafff1e0b049f67d0a2d0139"},{"path":"product/runtime/auths-gateway/src/recipe/runtime.rs","sha256":"c286f0d15f974402822c0810d8e97f98411dc1c557755cc23e540d85e2bb42d9"},{"path":"product/runtime/auths-gateway/src/recipe/source.rs","sha256":"1af50298fb1461e1b24cbdf560d43124d6b1c4c529586c911b1c4797214a69ff"},{"path":"product/runtime/auths-gateway/src/recipe/tests.rs","sha256":"aac551a2481bbc60864c64079bc667dcb232e45a0f41a04073ed84ab5dbe1fce"},{"path":"product/runtime/auths-gateway/src/recipe/validate.rs","sha256":"3711b17605cb7b0d639bc1b180449231f5882a306cab20e2c7782155cc63b0d4"},{"path":"product/runtime/auths-gateway/src/scenario_tests.rs","sha256":"d8271761b12597bfe1233f8eb5ad1d4e5498c5d03388e832e24ab818484a1de4"},{"path":"product/runtime/auths-gateway/src/separation.rs","sha256":"be9306848ca5d801767cf6aa14247c8618312ef0e202f00ce0c24c4844491061"},{"path":"product/runtime/auths-gateway/src/store.rs","sha256":"1e5288345c2cb1421aeda277b3158d07607404b0ec46943222ac107b63dcbb46"},{"path":"product/runtime/auths-gateway/src/store_testkit.rs","sha256":"88d82fee42f1b8ef521e8deef0216e938ebeaad822eb2f5020e70b89d145ea70"},{"path":"product/runtime/auths-gateway/src/submit.rs","sha256":"c78dbbba7c45b443febf655056c5edcd635e77be7b21c5b2c318097502415ffe"},{"path":"product/runtime/auths-gateway/src/support.rs","sha256":"9fd979029793a22b15d9776a7fc172476fd7c126a80d4080c65d720845becbcb"},{"path":"product/runtime/auths-gateway/src/transport.rs","sha256":"be2c6dc75b8daec110bf8749fedc3823f6067d40b999aa3eb21126896a97d3ad"},{"path":"product/runtime/auths-kernel-runtime/Cargo.toml","sha256":"926bcd0053e5edd703be8f0027ad009e2982db013c8174c1366edbf38b48087d"},{"path":"product/runtime/auths-kernel-runtime/src/lib.rs","sha256":"7108faae9ca4bc32dc093ddaf885ac8f74f3c9b8d317b7c7d0ed00d1d0ab5972"},{"path":"product/runtime/auths-lifecycle/Cargo.toml","sha256":"c5053c705f8d5554b44e432fe75287a2faf11d644e5a2552e45ad6cd94176af5"},{"path":"product/runtime/auths-lifecycle/src/codec.rs","sha256":"51c4b746749150e8bfcd8ff972b3f6c1ef40bec15583448ec1b471d9ad737dc0"},{"path":"product/runtime/auths-lifecycle/src/digest.rs","sha256":"55282cd7d8aba37713c2dcb5357c9877819edb72a30eadefb860d28d7d3a3eb7"},{"path":"product/runtime/auths-lifecycle/src/identifier.rs","sha256":"31620e8c16de68d3d2d3b84d6353c1a5b9d4151d8247f91fa389b906a8e660f1"},{"path":"product/runtime/auths-lifecycle/src/kernel.rs","sha256":"2abb8c094b36d35b364e74d78091d14c5d6f3d1eb6552cca3b5538dbd017ce23"},{"path":"product/runtime/auths-lifecycle/src/lib.rs","sha256":"afe5a345cd309b5a4f08ffba3170a6d7f16ff914892b3f2006d5208ed24ec736"},{"path":"product/runtime/auths-lifecycle/src/model.rs","sha256":"1af12bbeeeaa65ec02ddcebd7d2c8c92ec1e339fa40ae85b45ab9b01a722a4fa"},{"path":"product/runtime/auths-lifecycle/src/operation.rs","sha256":"78e6d05fcf5d7ea4f148032a3fa26fdfcab77eb346019effe927b08e0d64d732"},{"path":"product/runtime/auths-lifecycle/src/registry.rs","sha256":"53495fe6f7a77422593a41623e28716f1c140dcc1e00f87f6b0ffbfb93a5ef90"},{"path":"product/runtime/auths-lifecycle/src/sealed.rs","sha256":"2e0c03b5813c926c159598bb7890d1523825edbe57cd687d42a5dfb3374a0c19"},{"path":"product/runtime/auths-lifecycle/src/test_support.rs","sha256":"221d9a5c5ef8e1f9f8fd66927484eaf813571d0568470278ecd8fa08a5eec8cd"},{"path":"product/runtime/auths-lifecycle/src/transition.rs","sha256":"011805a28efdd541f44ccea54dd0e34a1e58f4004447ee58013703b4fb6b2822"},{"path":"product/runtime/auths-runtime/Cargo.toml","sha256":"dd29d80a8b4bb56c869f036a6c9998f6e6d1c0383ac5dc03fa42b24abe2a7ff7"},{"path":"product/runtime/auths-runtime/src/lib.rs","sha256":"132ca03d58c14905d3a822a4972f42a22a5ad33a45f2ba9ca44f3a57d810b4b0"},{"path":"product/runtime/auths-runtime/src/production.rs","sha256":"fd4eff4270c571c10fcff6cf27df28961ebf074de8a1a028f500fda1ca376820"},{"path":"product/sdk/auths-approval-quorum/Cargo.toml","sha256":"df904971fca87a24194c5816738a331588fe8f164acb5d70839a35dca5f57114"},{"path":"product/sdk/auths-approval-quorum/src/lib.rs","sha256":"72e4086088a1c0912e4e1a9e980f26a5c280bf5ab16ea39c9f0f58d5096ac2ce"},{"path":"product/sdk/auths-approval-quorum/src/remote.rs","sha256":"9fa029c7c63003adf260f8aec55160c545681c60c1bace0d934e7525862aac7b"},{"path":"product/sdk/auths-approval-quorum/src/remote_tests.rs","sha256":"8a09ce17cfee82a035a74edd535f3ebeb3db0e078784740d3997b17dbdb10197"},{"path":"product/sdk/auths-approval-quorum/src/tests.rs","sha256":"0acbf12be3e497dcc6c2d8f29c9af3b1a7ed8e11b75f6399570d4f217a785060"},{"path":"product/stores/auths-stores/Cargo.toml","sha256":"a32c4b76d17b264be5d40d24497ff237e1ed87822e8bab86229b3db93106dbe3"},{"path":"product/stores/auths-stores/src/gateway_attempt.rs","sha256":"185da8f4a220fba836d5b78a9311f03204681c43a3c53951008084d135bf4d21"},{"path":"product/stores/auths-stores/src/lib.rs","sha256":"e721262edf8a9ab5568ddc27639176312d4a366203b5f73e2d7c11fde2c554e9"},{"path":"product/stores/auths-stores/src/lifecycle.rs","sha256":"94f64d25bc178a9e60ba3c0ee6915d7fb3af7c4468792d76b4e70f43f4de1e2f"}],"schema":"auths.gateway-semantic-closure/1"} \ No newline at end of file diff --git a/product/runtime/auths-gateway/src/engine.rs b/product/runtime/auths-gateway/src/engine.rs index 6049cdba3..f4e546bfa 100644 --- a/product/runtime/auths-gateway/src/engine.rs +++ b/product/runtime/auths-gateway/src/engine.rs @@ -2224,7 +2224,12 @@ pub(crate) mod tests { async fn a_record_that_changed_since_the_prepare_is_not_committed() { let mut installation = installation(8).await; let host = &mut installation.first; - let journal = crate::CredentialJournal::new(host._state.path().to_path_buf()); + let journal = crate::CredentialJournal::new( + host.credentials_directory + .parent() + .expect("private root") + .to_path_buf(), + ); journal .initialize(&installation.connection_id) .expect("journal"); diff --git a/product/runtime/auths-gateway/src/semantic_closure.rs b/product/runtime/auths-gateway/src/semantic_closure.rs index 9d91c39f3..94260912d 100644 --- a/product/runtime/auths-gateway/src/semantic_closure.rs +++ b/product/runtime/auths-gateway/src/semantic_closure.rs @@ -10,7 +10,7 @@ /// SHA-256 of the schema, a NUL byte, and `semantic-closure.json`. /// Regenerate through `semantic_closure_is_current` with `AUTHS_UPDATE_FIXTURES=1`. pub const GATEWAY_SEMANTIC_CLOSURE_SHA256: &str = - "0177bfec3c76f1c296bcafbd71d242a717aedd90f9765ec1954c7208a98659b4"; + "464c6c17b8b6f969da548b4df9bdebf8bfe58066727a5a2fe5f150b443854c52"; #[cfg(test)] mod tests { From 5aa0916b33a403a3b4cbd1e48f7cc1b724832cd8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 6 Oct 2026 05:38:59 +0000 Subject: [PATCH 020/108] chore(formal): regenerate qualification artifacts Source-SHA: 71a85bf4b0ab6b05a41b271722bcab5ace2899b6 Workflow-Run: 37414864276 --- formal/assurance-manifest-v1.toml | 118 +++++++++++++++--------------- 1 file changed, 59 insertions(+), 59 deletions(-) diff --git a/formal/assurance-manifest-v1.toml b/formal/assurance-manifest-v1.toml index b9583c6c9..f1195d0ed 100644 --- a/formal/assurance-manifest-v1.toml +++ b/formal/assurance-manifest-v1.toml @@ -8733,7 +8733,7 @@ sha256 = "2bb401ffca0136622cd79bb14a5a38852061649a06cc46100503870c22d300c7" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "01aea09dd874fe1aab4088257f031dbc33702b554c7021184cae74f924c33348" +sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" [[claims]] claim_id = "AP-FORMAL-RICH-055" @@ -8854,7 +8854,7 @@ sha256 = "2bb401ffca0136622cd79bb14a5a38852061649a06cc46100503870c22d300c7" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "01aea09dd874fe1aab4088257f031dbc33702b554c7021184cae74f924c33348" +sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" [[claims]] claim_id = "AP-FORMAL-RICH-056" @@ -8989,7 +8989,7 @@ sha256 = "2bb401ffca0136622cd79bb14a5a38852061649a06cc46100503870c22d300c7" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "01aea09dd874fe1aab4088257f031dbc33702b554c7021184cae74f924c33348" +sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" [[claims]] claim_id = "AP-FORMAL-RICH-104" @@ -10463,7 +10463,7 @@ sha256 = "ba7aea214063b8a698fbd2c9c8cd95a717bf0ec0eaef70a92844444bf7e9f22e" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "01aea09dd874fe1aab4088257f031dbc33702b554c7021184cae74f924c33348" +sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" [[claims]] claim_id = "AP-FORMAL-RICH-263" @@ -10559,7 +10559,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "01aea09dd874fe1aab4088257f031dbc33702b554c7021184cae74f924c33348" +sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" [[claims]] claim_id = "AP-FORMAL-RICH-264" @@ -10658,7 +10658,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "01aea09dd874fe1aab4088257f031dbc33702b554c7021184cae74f924c33348" +sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" [[claims]] claim_id = "AP-FORMAL-RICH-186" @@ -10918,7 +10918,7 @@ sha256 = "ba7aea214063b8a698fbd2c9c8cd95a717bf0ec0eaef70a92844444bf7e9f22e" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "01aea09dd874fe1aab4088257f031dbc33702b554c7021184cae74f924c33348" +sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" [[claims]] claim_id = "AP-FORMAL-RICH-237" @@ -11014,7 +11014,7 @@ sha256 = "ba7aea214063b8a698fbd2c9c8cd95a717bf0ec0eaef70a92844444bf7e9f22e" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "01aea09dd874fe1aab4088257f031dbc33702b554c7021184cae74f924c33348" +sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" [[claims]] claim_id = "AP-FORMAL-RICH-238" @@ -11113,7 +11113,7 @@ sha256 = "ba7aea214063b8a698fbd2c9c8cd95a717bf0ec0eaef70a92844444bf7e9f22e" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "01aea09dd874fe1aab4088257f031dbc33702b554c7021184cae74f924c33348" +sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" [[claims]] claim_id = "AP-FORMAL-RICH-175" @@ -15048,7 +15048,7 @@ sha256 = "c8c86db058f313ab46ee86370d79ee70130c1ead3860dd7dabd49f2a89af1636" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "01aea09dd874fe1aab4088257f031dbc33702b554c7021184cae74f924c33348" +sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" [[claims]] claim_id = "AP-FORMAL-RICH-211" @@ -15143,7 +15143,7 @@ sha256 = "c8c86db058f313ab46ee86370d79ee70130c1ead3860dd7dabd49f2a89af1636" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "01aea09dd874fe1aab4088257f031dbc33702b554c7021184cae74f924c33348" +sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" [[claims]] claim_id = "AP-FORMAL-RICH-212" @@ -15239,7 +15239,7 @@ sha256 = "c8c86db058f313ab46ee86370d79ee70130c1ead3860dd7dabd49f2a89af1636" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "01aea09dd874fe1aab4088257f031dbc33702b554c7021184cae74f924c33348" +sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" [[claims]] claim_id = "AP-FORMAL-RICH-213" @@ -15335,7 +15335,7 @@ sha256 = "c8c86db058f313ab46ee86370d79ee70130c1ead3860dd7dabd49f2a89af1636" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "01aea09dd874fe1aab4088257f031dbc33702b554c7021184cae74f924c33348" +sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" [[claims]] claim_id = "AP-FORMAL-RICH-214" @@ -15431,7 +15431,7 @@ sha256 = "c8c86db058f313ab46ee86370d79ee70130c1ead3860dd7dabd49f2a89af1636" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "01aea09dd874fe1aab4088257f031dbc33702b554c7021184cae74f924c33348" +sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" [[claims]] claim_id = "AP-FORMAL-RICH-232" @@ -15530,7 +15530,7 @@ sha256 = "c8c86db058f313ab46ee86370d79ee70130c1ead3860dd7dabd49f2a89af1636" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "01aea09dd874fe1aab4088257f031dbc33702b554c7021184cae74f924c33348" +sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" [[claims]] claim_id = "AP-FORMAL-RICH-233" @@ -15626,7 +15626,7 @@ sha256 = "c8c86db058f313ab46ee86370d79ee70130c1ead3860dd7dabd49f2a89af1636" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "01aea09dd874fe1aab4088257f031dbc33702b554c7021184cae74f924c33348" +sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" [[claims]] claim_id = "AP-FORMAL-RICH-234" @@ -15722,7 +15722,7 @@ sha256 = "c8c86db058f313ab46ee86370d79ee70130c1ead3860dd7dabd49f2a89af1636" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "01aea09dd874fe1aab4088257f031dbc33702b554c7021184cae74f924c33348" +sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" [[claims]] claim_id = "AP-FORMAL-RICH-235" @@ -15818,7 +15818,7 @@ sha256 = "c8c86db058f313ab46ee86370d79ee70130c1ead3860dd7dabd49f2a89af1636" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "01aea09dd874fe1aab4088257f031dbc33702b554c7021184cae74f924c33348" +sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" [[claims]] claim_id = "AP-FORMAL-RICH-249" @@ -16485,7 +16485,7 @@ sha256 = "dfa1998e3506f06dce142222dc383116d0952155517edc399f5d94e688e22912" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "01aea09dd874fe1aab4088257f031dbc33702b554c7021184cae74f924c33348" +sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" [[claims]] claim_id = "AP-FORMAL-RICH-257" @@ -16584,7 +16584,7 @@ sha256 = "dfa1998e3506f06dce142222dc383116d0952155517edc399f5d94e688e22912" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "01aea09dd874fe1aab4088257f031dbc33702b554c7021184cae74f924c33348" +sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" [[claims]] claim_id = "AP-FORMAL-RICH-258" @@ -16683,7 +16683,7 @@ sha256 = "dfa1998e3506f06dce142222dc383116d0952155517edc399f5d94e688e22912" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "01aea09dd874fe1aab4088257f031dbc33702b554c7021184cae74f924c33348" +sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" [[claims]] claim_id = "AP-FORMAL-RICH-259" @@ -16779,7 +16779,7 @@ sha256 = "dfa1998e3506f06dce142222dc383116d0952155517edc399f5d94e688e22912" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "01aea09dd874fe1aab4088257f031dbc33702b554c7021184cae74f924c33348" +sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" [[claims]] claim_id = "AP-FORMAL-RICH-260" @@ -16878,7 +16878,7 @@ sha256 = "dfa1998e3506f06dce142222dc383116d0952155517edc399f5d94e688e22912" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "01aea09dd874fe1aab4088257f031dbc33702b554c7021184cae74f924c33348" +sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" [[claims]] claim_id = "AP-FORMAL-RICH-070" @@ -23876,7 +23876,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "01aea09dd874fe1aab4088257f031dbc33702b554c7021184cae74f924c33348" +sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" [[claims]] claim_id = "AP-FORMAL-RICH-189" @@ -23972,7 +23972,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "01aea09dd874fe1aab4088257f031dbc33702b554c7021184cae74f924c33348" +sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" [[claims]] claim_id = "AP-FORMAL-RICH-190" @@ -24068,7 +24068,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "01aea09dd874fe1aab4088257f031dbc33702b554c7021184cae74f924c33348" +sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" [[claims]] claim_id = "AP-FORMAL-RICH-191" @@ -24164,7 +24164,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "01aea09dd874fe1aab4088257f031dbc33702b554c7021184cae74f924c33348" +sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" [[claims]] claim_id = "AP-FORMAL-RICH-192" @@ -24259,7 +24259,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "01aea09dd874fe1aab4088257f031dbc33702b554c7021184cae74f924c33348" +sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" [[claims]] claim_id = "AP-FORMAL-RICH-193" @@ -24358,7 +24358,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "01aea09dd874fe1aab4088257f031dbc33702b554c7021184cae74f924c33348" +sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" [[claims]] claim_id = "AP-FORMAL-RICH-194" @@ -24457,7 +24457,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "01aea09dd874fe1aab4088257f031dbc33702b554c7021184cae74f924c33348" +sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" [[claims]] claim_id = "AP-FORMAL-RICH-195" @@ -24558,7 +24558,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "01aea09dd874fe1aab4088257f031dbc33702b554c7021184cae74f924c33348" +sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" [[claims]] claim_id = "AP-FORMAL-RICH-196" @@ -24662,7 +24662,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "01aea09dd874fe1aab4088257f031dbc33702b554c7021184cae74f924c33348" +sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" [[claims]] claim_id = "AP-FORMAL-RICH-197" @@ -24767,7 +24767,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "01aea09dd874fe1aab4088257f031dbc33702b554c7021184cae74f924c33348" +sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" [[claims]] claim_id = "AP-FORMAL-RICH-198" @@ -24863,7 +24863,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "01aea09dd874fe1aab4088257f031dbc33702b554c7021184cae74f924c33348" +sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" [[claims]] claim_id = "AP-FORMAL-RICH-199" @@ -24968,7 +24968,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "01aea09dd874fe1aab4088257f031dbc33702b554c7021184cae74f924c33348" +sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" [[claims]] claim_id = "AP-FORMAL-RICH-200" @@ -25063,7 +25063,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "01aea09dd874fe1aab4088257f031dbc33702b554c7021184cae74f924c33348" +sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" [[claims]] claim_id = "AP-FORMAL-RICH-201" @@ -25158,7 +25158,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "01aea09dd874fe1aab4088257f031dbc33702b554c7021184cae74f924c33348" +sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" [[claims]] claim_id = "AP-FORMAL-RICH-271" @@ -25254,7 +25254,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "01aea09dd874fe1aab4088257f031dbc33702b554c7021184cae74f924c33348" +sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" [[claims]] claim_id = "AP-FORMAL-RICH-272" @@ -25350,7 +25350,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "01aea09dd874fe1aab4088257f031dbc33702b554c7021184cae74f924c33348" +sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" [[claims]] claim_id = "AP-FORMAL-RICH-273" @@ -25449,7 +25449,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "01aea09dd874fe1aab4088257f031dbc33702b554c7021184cae74f924c33348" +sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" [[claims]] claim_id = "AP-FORMAL-RICH-274" @@ -25548,7 +25548,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "01aea09dd874fe1aab4088257f031dbc33702b554c7021184cae74f924c33348" +sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" [[claims]] claim_id = "AP-FORMAL-RICH-275" @@ -25649,7 +25649,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "01aea09dd874fe1aab4088257f031dbc33702b554c7021184cae74f924c33348" +sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" [[claims]] claim_id = "AP-FORMAL-RICH-276" @@ -25749,7 +25749,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "01aea09dd874fe1aab4088257f031dbc33702b554c7021184cae74f924c33348" +sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" [[claims]] claim_id = "AP-FORMAL-RICH-277" @@ -25848,7 +25848,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "01aea09dd874fe1aab4088257f031dbc33702b554c7021184cae74f924c33348" +sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" [[claims]] claim_id = "AP-FORMAL-RICH-278" @@ -25948,7 +25948,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "01aea09dd874fe1aab4088257f031dbc33702b554c7021184cae74f924c33348" +sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" [[claims]] claim_id = "AP-FORMAL-RICH-279" @@ -26047,7 +26047,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "01aea09dd874fe1aab4088257f031dbc33702b554c7021184cae74f924c33348" +sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" [[claims]] claim_id = "AP-FORMAL-RICH-280" @@ -26148,7 +26148,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "01aea09dd874fe1aab4088257f031dbc33702b554c7021184cae74f924c33348" +sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" [[claims]] claim_id = "AP-FORMAL-RICH-281" @@ -26248,7 +26248,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "01aea09dd874fe1aab4088257f031dbc33702b554c7021184cae74f924c33348" +sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" [[claims]] claim_id = "AP-FORMAL-RICH-282" @@ -26348,7 +26348,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "01aea09dd874fe1aab4088257f031dbc33702b554c7021184cae74f924c33348" +sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" [[claims]] claim_id = "AP-FORMAL-RICH-283" @@ -26448,7 +26448,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "01aea09dd874fe1aab4088257f031dbc33702b554c7021184cae74f924c33348" +sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" [[claims]] claim_id = "AP-FORMAL-RICH-284" @@ -26547,7 +26547,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "01aea09dd874fe1aab4088257f031dbc33702b554c7021184cae74f924c33348" +sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" [[claims]] claim_id = "AP-FORMAL-RICH-285" @@ -26649,7 +26649,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "01aea09dd874fe1aab4088257f031dbc33702b554c7021184cae74f924c33348" +sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" [[claims]] claim_id = "AP-FORMAL-RICH-306" @@ -26745,7 +26745,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "01aea09dd874fe1aab4088257f031dbc33702b554c7021184cae74f924c33348" +sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" [[claims]] claim_id = "AP-FORMAL-RICH-307" @@ -26844,7 +26844,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "01aea09dd874fe1aab4088257f031dbc33702b554c7021184cae74f924c33348" +sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" [[claims]] claim_id = "AP-FORMAL-RICH-308" @@ -26940,7 +26940,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "01aea09dd874fe1aab4088257f031dbc33702b554c7021184cae74f924c33348" +sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" [[claims]] claim_id = "AP-FORMAL-RICH-309" @@ -27039,7 +27039,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "01aea09dd874fe1aab4088257f031dbc33702b554c7021184cae74f924c33348" +sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" [[claims]] claim_id = "AP-FORMAL-RICH-310" @@ -27139,7 +27139,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "01aea09dd874fe1aab4088257f031dbc33702b554c7021184cae74f924c33348" +sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" [[claims]] claim_id = "AP-FORMAL-RICH-311" @@ -27238,7 +27238,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "01aea09dd874fe1aab4088257f031dbc33702b554c7021184cae74f924c33348" +sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" [[claims]] claim_id = "AP-FORMAL-RICH-312" @@ -27339,4 +27339,4 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "01aea09dd874fe1aab4088257f031dbc33702b554c7021184cae74f924c33348" +sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" From f1f92c3fb2d3d6f30f86547e69fa3958a9426a8a Mon Sep 17 00:00:00 2001 From: bordumb Date: Tue, 6 Oct 2026 07:02:46 +0100 Subject: [PATCH 021/108] chore(release): synchronize frozen assurance evidence --- docs/PROGRAM_BOARD.md | 9 +++++++++ release/semantic-freeze-versions.toml | 6 +++--- release/semantic-freeze.json | 10 +++++----- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/docs/PROGRAM_BOARD.md b/docs/PROGRAM_BOARD.md index 5953074b4..bdda21797 100644 --- a/docs/PROGRAM_BOARD.md +++ b/docs/PROGRAM_BOARD.md @@ -362,3 +362,12 @@ downloadable Python wheel assets; PyPI publication is not required. Download those published assets, verify their checksums and install them in clean environments for the simulated onboarding pilot. Local checkout installs do not demonstrate that release handoff. + +Epic 4's hosted Lean build, 322 compiled-claim audit and Aeneas qualification +passed in [run 37414864276](https://github.com/auths-dev/auths-proof/actions/runs/37414864276). +Its bounded updater committed the assurance-manifest digest refresh as +`5aa0916b`; the subsequent preflight exposed the matching frozen-byte inventory +as stale. That inventory is regenerated with freeze version 369, manifest-byte +version 58 and release-metadata version 369. Protocol identities and proof +statements are unchanged. Full hosted CI qualification and the live/human +acceptance gates remain open. diff --git a/release/semantic-freeze-versions.toml b/release/semantic-freeze-versions.toml index 76d8b0e44..e7c30e343 100644 --- a/release/semantic-freeze-versions.toml +++ b/release/semantic-freeze-versions.toml @@ -1,4 +1,4 @@ -freeze_version = 368 +freeze_version = 369 # Semantic identity counters live outside the xtask source tree deliberately. # The formal source closure binds xtask's executable code, while the semantic @@ -16,7 +16,7 @@ freeze_version = 368 "auths.frozen-bytes/core/fixtures/v1/manifest.json" = 15 "auths.frozen-bytes/core/formal-vectors/v1/manifest.json" = 1 "auths.frozen-bytes/demos/benchmarks/profiles/release.toml" = 1 -"auths.frozen-bytes/formal/assurance-manifest-v1.toml" = 57 +"auths.frozen-bytes/formal/assurance-manifest-v1.toml" = 58 "auths.frozen-bytes/formal/qualification/aeneas/generated" = 19 "auths.frozen-bytes/formal/qualification/aeneas/qualification.toml" = 16 "auths.frozen-bytes/formal/qualification/aeneas/source-closure.json" = 97 @@ -67,4 +67,4 @@ freeze_version = 368 "auths.product.vocabulary" = 24 "auths.release.benchmark-contract" = 1 "auths.release.evolution-contract" = 79 -"auths.release.public-surface" = 368 +"auths.release.public-surface" = 369 diff --git a/release/semantic-freeze.json b/release/semantic-freeze.json index 19df57502..ac0a07006 100644 --- a/release/semantic-freeze.json +++ b/release/semantic-freeze.json @@ -1,6 +1,6 @@ { "schema": "auths.semantic-freeze/1", - "freezeVersion": 368, + "freezeVersion": 369, "publicSurface": { "rustRoots": [ "auths", @@ -202,7 +202,7 @@ }, { "id": "auths.frozen-bytes/formal/assurance-manifest-v1.toml", - "version": 57, + "version": 58, "classification": "frozen-bytes", "categories": [ "canonical-generated-evidence" @@ -210,7 +210,7 @@ "owners": [ "formal/assurance-manifest-v1.toml" ], - "sha256": "c6f930fe3c8aa5e174e140fa92a801b1737f81b27a3fa926065151db51bd2248" + "sha256": "cc87f4480cc9eb559c810eba8534b844d05616e7e74c8732b39b5315616c65c3" }, { "id": "auths.frozen-bytes/formal/qualification/aeneas/generated", @@ -1011,7 +1011,7 @@ }, { "id": "auths.release.public-surface", - "version": 368, + "version": 369, "classification": "release-metadata", "categories": [ "package-names", @@ -1103,7 +1103,7 @@ "xtask/src/release_control.rs", "xtask/src/semantic_freeze.rs" ], - "sha256": "7bb135477e8944a99519690a5aa96d4a8b2c3991b7d121ae267a79bd7f5bb67f" + "sha256": "2ec62100d0f39cb3cd4c6786286d1de77c279aefbb34bdce730867e764708039" } ] } From 7bb3dcb131904d2795dcacdeff4768e293da499a Mon Sep 17 00:00:00 2001 From: bordumb Date: Tue, 6 Oct 2026 10:53:33 +0100 Subject: [PATCH 022/108] docs(gateway): record hosted evidence and diagnostic limits --- docs/PROGRAM_BOARD.md | 25 +++++++++++++------ docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md | 7 ++++-- ...gateway-polish-and-recipe-qualification.md | 8 +++++- 3 files changed, 29 insertions(+), 11 deletions(-) diff --git a/docs/PROGRAM_BOARD.md b/docs/PROGRAM_BOARD.md index bdda21797..15ef73371 100644 --- a/docs/PROGRAM_BOARD.md +++ b/docs/PROGRAM_BOARD.md @@ -363,11 +363,20 @@ those published assets, verify their checksums and install them in clean environments for the simulated onboarding pilot. Local checkout installs do not demonstrate that release handoff. -Epic 4's hosted Lean build, 322 compiled-claim audit and Aeneas qualification -passed in [run 37414864276](https://github.com/auths-dev/auths-proof/actions/runs/37414864276). -Its bounded updater committed the assurance-manifest digest refresh as -`5aa0916b`; the subsequent preflight exposed the matching frozen-byte inventory -as stale. That inventory is regenerated with freeze version 369, manifest-byte -version 58 and release-metadata version 369. Protocol identities and proof -statements are unchanged. Full hosted CI qualification and the live/human -acceptance gates remain open. +Epic 4 code at `f1f92c3f` passed every job in +[main CI](https://github.com/auths-dev/auths-proof/actions/runs/37421643170), +including authoritative tests, Lean, Kani, formal evidence and CI qualification. +The six operator-package, isolation, PostgreSQL, recipe and SDK-package +workflows also passed. The +[operator package](https://github.com/auths-dev/auths-proof/actions/runs/37421643189) +was downloaded and verified: archive SHA-256 +`70b585794b4883a9f85897446bf13ccc334d711570b0dee3148413788f577cd4` +and all eleven payload digests match. Frozen evidence uses freeze version 369, +manifest-byte version 58 and release-metadata version 369. Protocol identities +and proof statements are unchanged. This is engineering evidence; +[protected live custody](https://github.com/auths-dev/auths-proof/actions/runs/37421643146) +still awaits environment approval, and live/human acceptance remains open. + +Owner clarification (2026-10-06): merge each epic PR when that epic is complete +and CI is green. This authorizes those merges without another confirmation; +it does not waive the spec's live or independent-human acceptance gates. diff --git a/docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md b/docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md index de1310ade..631d05e5f 100644 --- a/docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md +++ b/docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md @@ -8,8 +8,11 @@ privilege-drop test. Application processes receive neither identity nor state. ## Diagnose and stop -`doctor --state-dir ... --app-socket ... --app-uid ... --app-gid ...` prints all -nine required typed checks and the optional observer state. It checks the +For a loadable installation whose isolation probes complete, +`doctor --state-dir ... --app-socket ... --app-uid ... --app-gid ...` prints +all nine required typed checks and the optional observer state. If installation +loading or isolation checks cannot complete, it refuses with a stable top-level +code before emitting that report; retain the code for diagnosis. It checks the actual lifecycle record, recipe binding, current credential-store confirmation, qualification, clock and process isolation. Any failed or unmade check yields nonzero status. Keep the JSON report. A missing observer explicitly means diff --git a/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md b/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md index 912e230ea..7463dc03a 100644 --- a/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md +++ b/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md @@ -1612,7 +1612,13 @@ shutdown and a durable host generation floor. The floor rejects an older restored connection or changed bytes at an accepted generation before lease. The maintained systemd deployment reference is `deployment/gateway/`; the operations and independent trial protocol are in -`docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md`. Hosted verification is pending. +`docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md`. Code at `f1f92c3f` passed +[all main CI jobs](https://github.com/auths-dev/auths-proof/actions/runs/37421643170) +and the six operator-package, isolation, PostgreSQL, recipe and SDK-package +workflows. The downloaded operator archive and all eleven payload digests +were verified against that commit. Protected live custody is still awaiting +environment approval; these automated checks do not close the live or human +acceptance gates below. The production clock adapter now rejects a synchronization marker older than fifteen minutes, a future timestamp, a symlink/nonregular file or an unsafe From 8900553ee13898f710f8043a20dcc56859ec6825 Mon Sep 17 00:00:00 2001 From: bordumb Date: Tue, 6 Oct 2026 20:27:05 +0100 Subject: [PATCH 023/108] feat(gateway): rehearse packaged operator commands without source checkout --- .../workflows/gateway-operator-package.yml | 51 +++ .../gateway/tools/operator-simulation.py | 345 ++++++++++++++++++ docs/PROGRAM_BOARD.md | 12 + docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md | 12 + ...gateway-polish-and-recipe-qualification.md | 13 +- 5 files changed, 430 insertions(+), 3 deletions(-) create mode 100644 deployment/gateway/tools/operator-simulation.py diff --git a/.github/workflows/gateway-operator-package.yml b/.github/workflows/gateway-operator-package.yml index 9c3edd133..d866b672c 100644 --- a/.github/workflows/gateway-operator-package.yml +++ b/.github/workflows/gateway-operator-package.yml @@ -65,6 +65,22 @@ jobs: run: | cargo test --locked -p auths-gateway --test operator_plane --test support_bundle cargo test --locked -p auths-gateway --test isolated_process -- --ignored + - name: Prepare public inputs for the operator simulation + run: | + mkdir -p target/operator-simulation-kit + cp deployment/gateway/tools/operator-simulation.py target/operator-simulation-kit/ + cp bindings/fixtures/gateway/airtable/recipe.json target/operator-simulation-kit/ + cp bindings/fixtures/gateway/airtable/profile.lock.json target/operator-simulation-kit/ + cp core/fixtures/v1/denied/untrusted-root.context.cbor target/operator-simulation-kit/trusted.context.cbor + cp bindings/fixtures/gateway/custody-hostile.json target/operator-simulation-kit/ + cd target/operator-simulation-kit + sha256sum operator-simulation.py recipe.json profile.lock.json trusted.context.cbor custody-hostile.json > SHA256SUMS + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 + with: + name: gateway-operator-simulation-kit + path: target/operator-simulation-kit/ + if-no-files-found: error + retention-days: 30 - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: name: gateway-operator-package @@ -73,3 +89,38 @@ jobs: target/gateway-operator-package.tgz.sha256 if-no-files-found: error retention-days: 30 + + operator-simulation: + name: source-free operator simulation + needs: package + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + # No checkout, source build, repository import, or provider secret in this job. + - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 + with: + name: gateway-operator-package + path: package + - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 + with: + name: gateway-operator-simulation-kit + path: kit + - name: Verify the simulation kit + working-directory: kit + run: sha256sum -c SHA256SUMS + - name: Rehearse the documented operator commands and measure friction + env: + AUTHS_SIMULATION_COMMIT: ${{ github.event.pull_request.head.sha || github.sha }} + run: | + sudo python3 kit/operator-simulation.py \ + --archive "$GITHUB_WORKSPACE/package/gateway-operator-package.tgz" \ + --inputs "$GITHUB_WORKSPACE/kit" \ + --expected-commit "$AUTHS_SIMULATION_COMMIT" \ + --report "$GITHUB_WORKSPACE/reports/operator-simulation.json" + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 + if: always() + with: + name: gateway-operator-simulation-report + path: reports/operator-simulation.json + if-no-files-found: warn + retention-days: 30 diff --git a/deployment/gateway/tools/operator-simulation.py b/deployment/gateway/tools/operator-simulation.py new file mode 100644 index 000000000..0976ee2ee --- /dev/null +++ b/deployment/gateway/tools/operator-simulation.py @@ -0,0 +1,345 @@ +#!/usr/bin/env python3 +"""A labeled operator rehearsal using downloaded binaries, never a source build.""" +import argparse +import base64 +import hashlib +import json +import os +from pathlib import Path, PurePosixPath +import selectors +import shutil +import signal +import subprocess +import tarfile +import tempfile +import time + + +class Refusal(Exception): + """Only a bounded, non-secret diagnostic reaches the public report.""" + + +def require(condition, code): + if not condition: + raise Refusal(code) + + +def private_tree(path, uid, gid): + for item in [path, *path.rglob("*")]: + require(not item.is_symlink(), "simulation.unexpected-symlink") + os.chown(item, uid, gid) + + +class Operator: + def __init__(self, package, inputs, work, sockets): + self.binary = package / "bin/auths-gateway" + self.qualification = package / "bin/auths-qualification" + self.inputs, self.work, self.sockets = inputs, work, sockets + self.steps, self.servers = [], {} + self.uid, self.gid, self.app_uid = 62001, 62000, 62002 + fixture = json.loads((inputs / "custody-hostile.json").read_text()) + self.sources = [{"source": entry["source"], + "canary": "synthetic-simulation-" + os.urandom(16).hex()} + for entry in fixture["redaction"]["canaries"]["sources"]] + require(len(self.sources) == 11, "simulation.canary-inventory") + self.canaries = [entry["canary"].encode() for entry in self.sources] + self.secret = next(e["canary"].encode() for e in self.sources if e["source"] == "credential") + self.account = next(e["canary"] for e in self.sources if e["source"] == "provider-account-id") + self.rotated = ("synthetic-simulation-rotation-" + os.urandom(16).hex()).encode() + self.canaries.append(self.rotated) + + def scan(self, data): + for canary in self.canaries: + needles = [canary, canary.hex().encode(), canary.hex().upper().encode()] + for padding in range(3): + # Exclude sextets containing padding bytes or trailing partial bits. + start = (padding * 8 + 5) // 6 + end = ((padding + len(canary)) * 8) // 6 + for encode in (base64.b64encode, base64.urlsafe_b64encode): + needles.append(encode(b"\0" * padding + canary)[start:end]) + require(not any(needle in data for needle in needles), "simulation.canary-exposure") + + def run(self, label, args, stdin=b"", success=True, code=None, root=False, env=None, binary=None): + started = time.monotonic() + record = {"step": label, "command": args[0], "seconds": None, "passed": False} + self.steps.append(record) + options = {} if root else {"user": self.uid, "group": self.gid, "extra_groups": []} + result = subprocess.run( + [str(binary or self.binary), *map(str, args)], input=stdin, + capture_output=True, timeout=65, cwd=self.work, + env={"PATH": "/usr/bin:/bin", **(env or {})}, **options, + ) + record["seconds"] = round(time.monotonic() - started, 3) + record["exit_code"] = result.returncode + self.scan(result.stdout + result.stderr) + require(len(result.stdout) + len(result.stderr) <= 1024 * 1024, "simulation.output-bound") + require((result.returncode == 0) == success, "simulation.command-exit") + if code: + require(code.encode() in result.stderr or code.encode() in result.stdout, "simulation.expected-code") + record["code"] = code + record["passed"] = True + return result.stdout + + def json(self, label, args, **kwargs): + return json.loads(self.run(label, args, **kwargs)) + + def install(self, state, store=None, join=False, secret=None, extra=(), label="install"): + args = ["install", "--state-dir", state, "--recipe", self.inputs / "recipe.json", + "--profile-lock", self.inputs / "profile.lock.json", + "--trusted-context", self.inputs / "trusted.context.cbor", + "--approve-digest", self.digest, "--provider", "airtable", + "--alias", "simulation", "--credential-stdin"] + args += ["--join"] if join else ["--account-label", self.account] + if store: + args += ["--attempt-store", store] + return self.run(label, [*args, *extra], stdin=(secret or self.secret) + b"\n") + + def start(self, state): + started = time.monotonic() + record = {"step": "start-" + state.name, "command": "serve", "passed": False} + self.steps.append(record) + app = self.sockets / (state.name + ".sock") + log = tempfile.TemporaryFile() + process = subprocess.Popen( + [str(self.binary), "serve", "--state-dir", str(state), "--app-socket", str(app)], + stdout=subprocess.PIPE, stderr=log, cwd=self.work, + env={"PATH": "/usr/bin:/bin"}, user=self.uid, group=self.gid, extra_groups=[], + ) + self.servers[state] = (process, log, app) + with selectors.DefaultSelector() as selector: + selector.register(process.stdout, selectors.EVENT_READ) + require(bool(selector.select(15)), "simulation.start-timeout") + ready = process.stdout.readline(65537) + self.scan(ready) + require(ready.startswith(b"app socket ready"), "simulation.start-refused") + record.update(passed=True, seconds=round(time.monotonic() - started, 3)) + + def stop(self, state): + started = time.monotonic() + record = {"step": "drain-" + state.name, "command": "SIGTERM", "passed": False} + self.steps.append(record) + process, log, app = self.servers.pop(state) + process.send_signal(signal.SIGTERM) + try: + process.wait(timeout=30) + except subprocess.TimeoutExpired: + process.kill() + process.wait() + raise Refusal("simulation.shutdown-timeout") + self.scan(process.stdout.read(65537)) + log.seek(0) + self.scan(log.read(65537)) + log.close() + process.stdout.close() + require(process.returncode == 0, "simulation.shutdown-refused") + require(not app.exists() and not (state / "admin.sock").exists(), "simulation.socket-not-removed") + record.update(passed=True, seconds=round(time.monotonic() - started, 3)) + + def admin(self, state, command, label=None, extra=(), stdin=b"", success=True, code=None): + result = self.json(label or command + "-" + state.name, + [command, "--state-dir", state, *extra], + stdin=stdin, success=success, code=code) + require(result["ok"] == success, "simulation.admin-verdict") + return result + + def status(self, state): + return self.admin(state, "status")["status"] + + def doctor(self, state): + app = self.servers[state][2] + report = self.json("diagnose-development-" + state.name, + ["doctor", "--state-dir", state, "--app-socket", app, + "--app-uid", str(self.app_uid), "--app-gid", str(self.gid)], + root=True, success=False, code="gateway.doctor.not-ready") + require(report["schema"] == "auths.gateway-readiness/1" and not report["ready"], + "simulation.false-production-readiness") + checks = {row["check"]: row for row in report["checks"]} + require(len(checks) == 10, "simulation.diagnostic-inventory") + require(checks["operator-plane-isolation"]["ready"], "simulation.isolation-refused") + require(not checks["provider-secret-custody"]["ready"], "simulation.plaintext-ready") + require(checks["observer-custody"]["state"] == "not-configured", "simulation.optional-observer") + return report + + def exercise(self): + review = self.json("review-recipe", ["review", "--recipe", self.inputs / "recipe.json", + "--profile-lock", self.inputs / "profile.lock.json"]) + self.digest = review["recipe_digest"] + first, second, store = self.work / "first", self.work / "second", self.work / "store" + self.install(first, store) + self.install(second, store, join=True, label="join-second-host") + for source in self.sources: + (first / (source["source"] + ".captured")).write_text(source["canary"]) + private_tree(first, self.uid, self.gid) + self.json("offline-support", ["support-bundle", "--state-dir", first]) + # These are shipped builds: neither test transport nor plaintext production is allowed. + args = ["install", "--state-dir", self.work / "production", "--recipe", + self.inputs / "recipe.json", "--profile-lock", self.inputs / "profile.lock.json", + "--trusted-context", self.inputs / "trusted.context.cbor", "--approve-digest", + self.digest, "--provider", "airtable", "--alias", "simulation", + "--account-label", self.account, "--credential-stdin", "--deployment", "production"] + self.run("refuse-production-plaintext", args, stdin=self.secret + b"\n", success=False, + code="gateway.credential.production-plaintext-refused") + self.start(first) + self.start(second) + require(self.status(first)["credential_held"] and self.status(second)["credential_held"], + "simulation.joined-custody") + self.doctor(first) + self.admin(first, "disable") + require(self.status(second)["state"] == "disabled", "simulation.shared-disable") + self.admin(second, "enable") + require(self.status(first)["state"] == "active", "simulation.shared-enable") + self.stop(first) + self.stop(second) + snapshot = self.work / "old-store" + shutil.copytree(store, snapshot) + self.start(first) + self.start(second) + self.admin(first, "disable") + self.admin(second, "enable") + self.status(first) + self.status(second) + self.stop(first) + self.stop(second) + current = self.work / "current-store" + shutil.copytree(store, current) + floor = (first / "connection-floor.json").read_bytes() + shutil.rmtree(store) + shutil.copytree(snapshot, store) + private_tree(store, self.uid, self.gid) + self.run("refuse-stale-restore", + ["rotate-prepare", "--state-dir", first, "--operator-process", "--credential-stdin"], + stdin=self.rotated + b"\n", success=False, code="gateway.admin.connection-unavailable") + require((first / "connection-floor.json").read_bytes() == floor, "simulation.floor-replaced") + shutil.rmtree(store) + shutil.copytree(current, store) + private_tree(store, self.uid, self.gid) + self.start(first) + self.start(second) + prepared = self.admin(first, "rotate-prepare", extra=["--operator-process", "--credential-stdin"], + stdin=self.rotated + b"\n") + self.admin(first, "rotate-commit", extra=["--operator-process", "--commitment", prepared["commitment"]]) + # The development stores are host-local: the second host must adopt the same secret. + self.admin(second, "rotate", extra=["--operator-process", "--credential-stdin"], + stdin=self.rotated + b"\n") + one, two = self.status(first), self.status(second) + require(one["credential_generation"] == two["credential_generation"] + and one["credential_held"] and two["credential_held"], "simulation.rotation-diverged") + self.json("redacted-support", ["support-bundle", "--state-dir", first], + env={"AUTHS_SIMULATION_CANARY": self.secret.decode()}) + self.admin(first, "reobserve", extra=["--operation-id", "simulation-no-such-operation"], + success=False, code="gateway.reobserve.not-observable") + tuple_bytes = self.run("deployment-tuple", ["qualification-status", "--state-dir", first, "--tuple"]) + tuple_path = self.work / "tuple.json" + tuple_path.write_bytes(tuple_bytes) + os.chown(tuple_path, self.uid, self.gid) + self.run("disposable-signer-rotation-and-freshness", + ["stage-trust", "--tuple", tuple_path, "--out", self.work / "trust-stage"], + binary=self.qualification) + # Rolling restart retains the shared binding; there is no new candidate or live attestation. + self.stop(first) + self.start(first) + require(self.status(first)["credential_generation"] == self.status(second)["credential_generation"], + "simulation.restart-diverged") + self.stop(first) + self.stop(second) + emergency = self.work / "emergency" + self.install(emergency, label="install-outage-fixture") + (emergency / "credentials.cbor").unlink() + (emergency / "qualification-state.json").write_bytes(b"unavailable") + for command, state in [("disable", "disabled"), ("disable", "disabled"), + ("revoke", "revoked"), ("disable", "revoked")]: + result = self.json("outage-" + command, + [command, "--state-dir", emergency, "--store-only"]) + require(result["state"] == state and result["drainage"] == "not-checked" + and result["credential_deletion"] == "not-attempted", "simulation.false-outage-claim") + + def cleanup(self): + for state in list(self.servers): + process, log, _ = self.servers.pop(state) + if process.poll() is None: + process.kill() + process.wait(timeout=10) + process.stdout.close() + log.close() + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("--archive", type=Path, required=True) + parser.add_argument("--inputs", type=Path, required=True) + parser.add_argument("--expected-commit", required=True) + parser.add_argument("--report", type=Path, required=True) + args = parser.parse_args() + report = {"schema": "auths.operator-simulation/1", "participant": "agent-simulation", + "independent_human_trial": False, "production_qualification": False, + "source_commit": args.expected_commit, "passed": False, "steps": [], + "not_exercised": ["live AWS workload identity", "live provider writes and unknown recovery", + "production qualification import", "production PostgreSQL PITR", + "upgrade to a distinct attested candidate"], + "friction": [{"code": "operator.platform-linux-only", "resolution": "rehearse on Ubuntu CI"}, + {"code": "operator.production-inputs-unprovisioned", + "resolution": "owner supplies offline public root and protected live inputs"}]} + started, operator = time.monotonic(), None + try: + require(os.geteuid() == 0, "simulation.root-required") + expected = Path(str(args.archive) + ".sha256").read_text().split() + require(len(expected) == 2 and expected[1] == args.archive.name, "simulation.checksum-format") + with args.archive.open("rb") as stream: + digest = hashlib.file_digest(stream, "sha256").hexdigest() + require(digest == expected[0], "simulation.archive-digest") + report["archive_sha256"] = digest + with tempfile.TemporaryDirectory(prefix="auths-op-", dir="/var/tmp") as temporary: + root = Path(temporary) + os.chmod(root, 0o755) + with tarfile.open(args.archive, "r:gz") as archive: + members = archive.getmembers() + names = [member.name for member in members] + require(len(names) == len(set(names)) <= 64, "simulation.archive-members") + for member in members: + path = PurePosixPath(member.name) + require(member.isfile() and not path.is_absolute() and ".." not in path.parts + and path.parts[0] == "auths-gateway-operator" and path.suffix != ".rs", + "simulation.archive-path") + archive.extractall(root, filter="data") + package = root / "auths-gateway-operator" + manifest = json.loads((package / "manifest.json").read_text()) + require(manifest["schema"] == "auths.gateway-operator-package/1" + and manifest["source_commit"] == args.expected_commit, "simulation.package-identity") + require(set(names) == {"auths-gateway-operator/" + item["path"] for item in manifest["files"]} + | {"auths-gateway-operator/manifest.json"}, "simulation.package-inventory") + for item in manifest["files"]: + require(hashlib.sha256((package / item["path"]).read_bytes()).hexdigest() == item["sha256"], + "simulation.payload-digest") + work, sockets, inputs = root / "work", root / "sockets", root / "inputs" + work.mkdir(mode=0o700) + sockets.mkdir(mode=0o750) + shutil.copytree(args.inputs, inputs) + os.chmod(inputs, 0o700) + os.chown(work, 62001, 62000) + os.chown(sockets, 62001, 62000) + private_tree(inputs, 62001, 62000) + operator = Operator(package, inputs, work, sockets) + operator.exercise() + report["passed"] = True + except Exception as error: + report["failure_code"] = str(error) if isinstance(error, Refusal) else "simulation." + type(error).__name__ + if operator and operator.steps: + operator.steps[-1].update(passed=False, failure_code=report["failure_code"]) + finally: + if operator: + try: + operator.cleanup() + except Exception: + report.update(passed=False, failure_code="simulation.cleanup-failed") + report["steps"] = operator.steps + report["elapsed_seconds"] = round(time.monotonic() - started, 3) + report["command_count"] = len(report["steps"]) + args.report.parent.mkdir(parents=True, exist_ok=True) + args.report.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n") + print(json.dumps({"passed": report["passed"], "commands": report["command_count"], + "seconds": report["elapsed_seconds"], "failure_code": report.get("failure_code")})) + return 0 if report["passed"] else 1 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/docs/PROGRAM_BOARD.md b/docs/PROGRAM_BOARD.md index 15ef73371..f5365743d 100644 --- a/docs/PROGRAM_BOARD.md +++ b/docs/PROGRAM_BOARD.md @@ -380,3 +380,15 @@ still awaits environment approval, and live/human acceptance remains open. Owner clarification (2026-10-06): merge each epic PR when that epic is complete and CI is green. This authorizes those merges without another confirmation; it does not waive the spec's live or independent-human acceptance gates. + +Owner correction (2026-10-06): the agent simulates being an operator, fixes +the observed friction and reruns the packaged rehearsal; the owner handles +real users offline. This supersedes the earlier requirement for the agent to +wait for an independent participant before continuing engineering. The +simulation is labeled as such and cannot qualify live providers or establish +independent human adoption. A separate source-free Ubuntu job downloads the +operator archive and simulation kit, runs the documented CLI against +disposable development installations, and records command timing and friction. +Its hosted result is pending. Continue with Epic 5 engineering after this +rehearsal; protected live inputs and release-signing keys remain explicit +external prerequisites for signed qualification. diff --git a/docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md b/docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md index 631d05e5f..82f5e4e62 100644 --- a/docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md +++ b/docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md @@ -169,6 +169,18 @@ continuity. Keep expiry and revocation updates running during the upgrade. ## Independent operator trial +The owner directed the agent on 2026-10-06 to simulate an operator and will +handle real users offline. The `Gateway operator package` workflow therefore +also runs a labeled rehearsal in a separate Ubuntu job with no source checkout, +compiler invocation or repository imports. It downloads the archive and public +simulation kit, checks the exact commit and all payload digests, and records +actual command counts, timings, stable refusals and friction in +`operator-simulation.json`. Shipped binaries retain their production guards. +The rehearsal uses disposable development custody and a shared file store; +its report explicitly lists unexercised production/live operations. It is +agent simulation evidence, not an independent person's result or a production +qualification. Any failing command must be corrected and the rehearsal rerun. + Give a person unfamiliar with this implementation only the verified packaged binaries, packages, public configuration and this runbook. Record participant identity/role, artifact digests, dates, timings, attempted commands, redacted diff --git a/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md b/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md index 7463dc03a..4056fae59 100644 --- a/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md +++ b/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md @@ -887,7 +887,12 @@ Tasks: Done when a clean operator can deploy, diagnose, rotate, disable, restore and reconcile without source checkout or secret exposure; every diagnostic phrase corresponds to an actual typed check; and the trial's defects are fixed and -rerun. The implementer MUST NOT simulate the unfamiliar-operator trial. +rerun. The implementer MUST NOT represent a simulated trial as an independent +human result. Owner clarification (2026-10-06): the agent's deliverable is a +labeled operator simulation from packaged artifacts; the owner handles real +users offline. The simulation must fix and rerun its defects and explicitly +report which production/live operations its inputs do not exercise. Human +adoption and production qualification claims still require their own evidence. ### Epic 5 — Qualify two recipes and close the launch gate @@ -1629,8 +1634,10 @@ a claim that a compromised time source is trustworthy. This is not Epic 4 acceptance yet. A live two-host reference exercise of workload identity, firewall, PostgreSQL point-in-time restore and the runbooks -remains, as does the independently performed unfamiliar-operator trial and -its defect rerun. The implementer has not simulated that participant. Epic 5 +remains. The owner now assigns the agent a labeled operator simulation and +handles real users offline; no independent human result is claimed. The +source-free packaged simulation and its defect reruns are being implemented. +Epic 5 also lacks the owner's offline root ceremony, protected signer secret, two protected provider environments and human release review. On 2026-10-06, GitHub environment/secret metadata confirmed no qualification signer secret From 6667cedb1370b753959dd2ab2d866ab72dca9c31 Mon Sep 17 00:00:00 2001 From: bordumb Date: Tue, 6 Oct 2026 20:35:04 +0100 Subject: [PATCH 024/108] fix(gateway): drain development hosts for operator file rotation --- deployment/gateway/tools/operator-simulation.py | 9 +++++++-- docs/PROGRAM_BOARD.md | 7 +++++++ docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md | 7 +++++++ 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/deployment/gateway/tools/operator-simulation.py b/deployment/gateway/tools/operator-simulation.py index 0976ee2ee..a6017afc0 100644 --- a/deployment/gateway/tools/operator-simulation.py +++ b/deployment/gateway/tools/operator-simulation.py @@ -213,14 +213,17 @@ def exercise(self): shutil.rmtree(store) shutil.copytree(current, store) private_tree(store, self.uid, self.gid) - self.start(first) - self.start(second) + # Development file custody is a process-local snapshot. Keep both hosts + # drained while separate operator processes update those files; + # production AWS readers resolve the published exact version instead. prepared = self.admin(first, "rotate-prepare", extra=["--operator-process", "--credential-stdin"], stdin=self.rotated + b"\n") self.admin(first, "rotate-commit", extra=["--operator-process", "--commitment", prepared["commitment"]]) # The development stores are host-local: the second host must adopt the same secret. self.admin(second, "rotate", extra=["--operator-process", "--credential-stdin"], stdin=self.rotated + b"\n") + self.start(first) + self.start(second) one, two = self.status(first), self.status(second) require(one["credential_generation"] == two["credential_generation"] and one["credential_held"] and two["credential_held"], "simulation.rotation-diverged") @@ -277,6 +280,8 @@ def main(): "production qualification import", "production PostgreSQL PITR", "upgrade to a distinct attested candidate"], "friction": [{"code": "operator.platform-linux-only", "resolution": "rehearse on Ubuntu CI"}, + {"code": "operator.development-custody-snapshot", + "resolution": "drain development hosts before separate-process file rotation; restart both afterward"}, {"code": "operator.production-inputs-unprovisioned", "resolution": "owner supplies offline public root and protected live inputs"}]} started, operator = time.monotonic(), None diff --git a/docs/PROGRAM_BOARD.md b/docs/PROGRAM_BOARD.md index f5365743d..2cca88cbc 100644 --- a/docs/PROGRAM_BOARD.md +++ b/docs/PROGRAM_BOARD.md @@ -392,3 +392,10 @@ disposable development installations, and records command timing and friction. Its hosted result is pending. Continue with Epic 5 engineering after this rehearsal; protected live inputs and release-signing keys remain explicit external prerequisites for signed qualification. + +The first local Docker rehearsal used the verified `f1f92c3f` archive without +a source mount or network. It passed 31 steps, then found that separate-process +rotation does not reload development file custody in running hosts. The +rehearsal and runbook now keep those hosts drained during file rotation and +restart both before checking the committed generation. The defect rerun is +pending; no production AWS rotation result is inferred from this procedure. diff --git a/docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md b/docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md index 82f5e4e62..6c88061b0 100644 --- a/docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md +++ b/docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md @@ -181,6 +181,13 @@ its report explicitly lists unexercised production/live operations. It is agent simulation evidence, not an independent person's result or a production qualification. Any failing command must be corrected and the rehearsal rerun. +Development file custody is loaded into each serving process at startup. For +this rehearsal, drain both hosts before rotating their host-local files with +`--operator-process`, then restart both and require the same credential +generation with `credential_held: true`. Updating a file beside a running +process does not reload that process's custody snapshot. This development +procedure does not demonstrate the production AWS reader's live rotation. + Give a person unfamiliar with this implementation only the verified packaged binaries, packages, public configuration and this runbook. Record participant identity/role, artifact digests, dates, timings, attempted commands, redacted From 0f91af2b69fa39e873ed2b2ed22b627da55dfd63 Mon Sep 17 00:00:00 2001 From: bordumb Date: Tue, 6 Oct 2026 20:36:14 +0100 Subject: [PATCH 025/108] fix(gateway): declare synthetic qualification tuple in rehearsal --- deployment/gateway/tools/operator-simulation.py | 4 +++- docs/PROGRAM_BOARD.md | 4 ++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/deployment/gateway/tools/operator-simulation.py b/deployment/gateway/tools/operator-simulation.py index a6017afc0..590a156bf 100644 --- a/deployment/gateway/tools/operator-simulation.py +++ b/deployment/gateway/tools/operator-simulation.py @@ -88,7 +88,9 @@ def install(self, state, store=None, join=False, secret=None, extra=(), label="i "--profile-lock", self.inputs / "profile.lock.json", "--trusted-context", self.inputs / "trusted.context.cbor", "--approve-digest", self.digest, "--provider", "airtable", - "--alias", "simulation", "--credential-stdin"] + "--alias", "simulation", "--credential-stdin", + "--recipe-family", "operator-simulation-v1", + "--provider-contract-id", "3" * 64] args += ["--join"] if join else ["--account-label", self.account] if store: args += ["--attempt-store", store] diff --git a/docs/PROGRAM_BOARD.md b/docs/PROGRAM_BOARD.md index 2cca88cbc..364970c3b 100644 --- a/docs/PROGRAM_BOARD.md +++ b/docs/PROGRAM_BOARD.md @@ -399,3 +399,7 @@ rotation does not reload development file custody in running hosts. The rehearsal and runbook now keep those hosts drained during file rotation and restart both before checking the committed generation. The defect rerun is pending; no production AWS rotation result is inferred from this procedure. +The next run passed rotation on both restarted hosts, then refused tuple +export because the development install omitted a family and contract. The +rehearsal now declares an explicitly synthetic family/contract at install; +those identifiers carry no production qualification claim. From 393edc5213128e0572493a86c942ef910e25117b Mon Sep 17 00:00:00 2001 From: bordumb Date: Tue, 6 Oct 2026 20:37:33 +0100 Subject: [PATCH 026/108] docs(gateway): record passing Docker operator rehearsal --- .../operator-simulation-2026-10-06.json | 353 ++++++++++++++++++ docs/PROGRAM_BOARD.md | 11 + ...gateway-polish-and-recipe-qualification.md | 7 +- 3 files changed, 370 insertions(+), 1 deletion(-) create mode 100644 deployment/gateway/evidence/operator-simulation-2026-10-06.json diff --git a/deployment/gateway/evidence/operator-simulation-2026-10-06.json b/deployment/gateway/evidence/operator-simulation-2026-10-06.json new file mode 100644 index 000000000..ffc77fb99 --- /dev/null +++ b/deployment/gateway/evidence/operator-simulation-2026-10-06.json @@ -0,0 +1,353 @@ +{ + "archive_sha256": "70b585794b4883a9f85897446bf13ccc334d711570b0dee3148413788f577cd4", + "command_count": 47, + "elapsed_seconds": 5.848, + "friction": [ + { + "code": "operator.platform-linux-only", + "resolution": "rehearse on Ubuntu CI" + }, + { + "code": "operator.development-custody-snapshot", + "resolution": "drain development hosts before separate-process file rotation; restart both afterward" + }, + { + "code": "operator.production-inputs-unprovisioned", + "resolution": "owner supplies offline public root and protected live inputs" + } + ], + "independent_human_trial": false, + "not_exercised": [ + "live AWS workload identity", + "live provider writes and unknown recovery", + "production qualification import", + "production PostgreSQL PITR", + "upgrade to a distinct attested candidate" + ], + "participant": "agent-simulation", + "passed": true, + "production_qualification": false, + "schema": "auths.operator-simulation/1", + "source_commit": "f1f92c3fb2d3d6f30f86547e69fa3958a9426a8a", + "steps": [ + { + "command": "review", + "exit_code": 0, + "passed": true, + "seconds": 0.114, + "step": "review-recipe" + }, + { + "command": "install", + "exit_code": 0, + "passed": true, + "seconds": 0.138, + "step": "install" + }, + { + "command": "install", + "exit_code": 0, + "passed": true, + "seconds": 0.142, + "step": "join-second-host" + }, + { + "command": "support-bundle", + "exit_code": 0, + "passed": true, + "seconds": 0.234, + "step": "offline-support" + }, + { + "code": "gateway.credential.production-plaintext-refused", + "command": "install", + "exit_code": 1, + "passed": true, + "seconds": 0.076, + "step": "refuse-production-plaintext" + }, + { + "command": "serve", + "passed": true, + "seconds": 0.17, + "step": "start-first" + }, + { + "command": "serve", + "passed": true, + "seconds": 0.17, + "step": "start-second" + }, + { + "command": "status", + "exit_code": 0, + "passed": true, + "seconds": 0.105, + "step": "status-first" + }, + { + "command": "status", + "exit_code": 0, + "passed": true, + "seconds": 0.102, + "step": "status-second" + }, + { + "code": "gateway.doctor.not-ready", + "command": "doctor", + "exit_code": 1, + "passed": true, + "seconds": 0.379, + "step": "diagnose-development-first" + }, + { + "command": "disable", + "exit_code": 0, + "passed": true, + "seconds": 0.099, + "step": "disable-first" + }, + { + "command": "status", + "exit_code": 0, + "passed": true, + "seconds": 0.093, + "step": "status-second" + }, + { + "command": "enable", + "exit_code": 0, + "passed": true, + "seconds": 0.096, + "step": "enable-second" + }, + { + "command": "status", + "exit_code": 0, + "passed": true, + "seconds": 0.093, + "step": "status-first" + }, + { + "command": "SIGTERM", + "passed": true, + "seconds": 0.021, + "step": "drain-first" + }, + { + "command": "SIGTERM", + "passed": true, + "seconds": 0.018, + "step": "drain-second" + }, + { + "command": "serve", + "passed": true, + "seconds": 0.164, + "step": "start-first" + }, + { + "command": "serve", + "passed": true, + "seconds": 0.164, + "step": "start-second" + }, + { + "command": "disable", + "exit_code": 0, + "passed": true, + "seconds": 0.107, + "step": "disable-first" + }, + { + "command": "enable", + "exit_code": 0, + "passed": true, + "seconds": 0.105, + "step": "enable-second" + }, + { + "command": "status", + "exit_code": 0, + "passed": true, + "seconds": 0.096, + "step": "status-first" + }, + { + "command": "status", + "exit_code": 0, + "passed": true, + "seconds": 0.093, + "step": "status-second" + }, + { + "command": "SIGTERM", + "passed": true, + "seconds": 0.02, + "step": "drain-first" + }, + { + "command": "SIGTERM", + "passed": true, + "seconds": 0.021, + "step": "drain-second" + }, + { + "code": "gateway.admin.connection-unavailable", + "command": "rotate-prepare", + "exit_code": 1, + "passed": true, + "seconds": 0.175, + "step": "refuse-stale-restore" + }, + { + "command": "rotate-prepare", + "exit_code": 0, + "passed": true, + "seconds": 0.2, + "step": "rotate-prepare-first" + }, + { + "command": "rotate-commit", + "exit_code": 0, + "passed": true, + "seconds": 0.19, + "step": "rotate-commit-first" + }, + { + "command": "rotate", + "exit_code": 0, + "passed": true, + "seconds": 0.196, + "step": "rotate-second" + }, + { + "command": "serve", + "passed": true, + "seconds": 0.166, + "step": "start-first" + }, + { + "command": "serve", + "passed": true, + "seconds": 0.169, + "step": "start-second" + }, + { + "command": "status", + "exit_code": 0, + "passed": true, + "seconds": 0.101, + "step": "status-first" + }, + { + "command": "status", + "exit_code": 0, + "passed": true, + "seconds": 0.1, + "step": "status-second" + }, + { + "command": "support-bundle", + "exit_code": 0, + "passed": true, + "seconds": 0.226, + "step": "redacted-support" + }, + { + "code": "gateway.reobserve.not-observable", + "command": "reobserve", + "exit_code": 1, + "passed": true, + "seconds": 0.077, + "step": "reobserve-first" + }, + { + "command": "qualification-status", + "exit_code": 0, + "passed": true, + "seconds": 0.168, + "step": "deployment-tuple" + }, + { + "command": "stage-trust", + "exit_code": 0, + "passed": true, + "seconds": 0.096, + "step": "disposable-signer-rotation-and-freshness" + }, + { + "command": "SIGTERM", + "passed": true, + "seconds": 0.019, + "step": "drain-first" + }, + { + "command": "serve", + "passed": true, + "seconds": 0.162, + "step": "start-first" + }, + { + "command": "status", + "exit_code": 0, + "passed": true, + "seconds": 0.1, + "step": "status-first" + }, + { + "command": "status", + "exit_code": 0, + "passed": true, + "seconds": 0.091, + "step": "status-second" + }, + { + "command": "SIGTERM", + "passed": true, + "seconds": 0.019, + "step": "drain-first" + }, + { + "command": "SIGTERM", + "passed": true, + "seconds": 0.019, + "step": "drain-second" + }, + { + "command": "install", + "exit_code": 0, + "passed": true, + "seconds": 0.14, + "step": "install-outage-fixture" + }, + { + "command": "disable", + "exit_code": 0, + "passed": true, + "seconds": 0.101, + "step": "outage-disable" + }, + { + "command": "disable", + "exit_code": 0, + "passed": true, + "seconds": 0.096, + "step": "outage-disable" + }, + { + "command": "revoke", + "exit_code": 0, + "passed": true, + "seconds": 0.101, + "step": "outage-revoke" + }, + { + "command": "disable", + "exit_code": 0, + "passed": true, + "seconds": 0.098, + "step": "outage-disable" + } + ] +} diff --git a/docs/PROGRAM_BOARD.md b/docs/PROGRAM_BOARD.md index 364970c3b..f3d647fac 100644 --- a/docs/PROGRAM_BOARD.md +++ b/docs/PROGRAM_BOARD.md @@ -403,3 +403,14 @@ The next run passed rotation on both restarted hosts, then refused tuple export because the development install omitted a family and contract. The rehearsal now declares an explicitly synthetic family/contract at install; those identifiers carry no production qualification claim. + +The corrected Docker rehearsal passed all 47 steps in 5.848 seconds against +the downloaded `f1f92c3f` archive. The container mounted only that archive, +public inputs and the report directory; networking was disabled, with a +synthetic public-address DNS entry solely for transport construction. No +provider request or TLS session was exercised. The sanitized result is +`deployment/gateway/evidence/operator-simulation-2026-10-06.json`. It covers +shared controls, retained-floor restore refusal, drained file rotation, +privilege-dropped diagnostics, support redaction, disposable trust stages, +restart and store-only outage controls. Exact-current-commit hosted rehearsal +and CI remain pending. Live production and human adoption claims remain open. diff --git a/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md b/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md index 4056fae59..05f0911f0 100644 --- a/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md +++ b/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md @@ -1636,7 +1636,12 @@ This is not Epic 4 acceptance yet. A live two-host reference exercise of workload identity, firewall, PostgreSQL point-in-time restore and the runbooks remains. The owner now assigns the agent a labeled operator simulation and handles real users offline; no independent human result is claimed. The -source-free packaged simulation and its defect reruns are being implemented. +source-free packaged simulation passed 47 steps in Docker against the verified +`f1f92c3f` package after fixing development file-rotation and tuple-declaration +friction. The sanitized report is +`deployment/gateway/evidence/operator-simulation-2026-10-06.json`. +Exact-current-commit hosted verification remains pending; no live provider, +production AWS rotation or production PostgreSQL PITR is claimed by this run. Epic 5 also lacks the owner's offline root ceremony, protected signer secret, two protected provider environments and human release review. On 2026-10-06, From 9d25e306536045440083ba93856317ddf18b2bbc Mon Sep 17 00:00:00 2001 From: bordumb Date: Tue, 6 Oct 2026 20:58:11 +0100 Subject: [PATCH 027/108] feat(release): derive stable launch readiness from signed evidence --- Cargo.lock | 2 + docs/PROGRAM_BOARD.md | 14 + .../src/bin/auths-qualification.rs | 13 + .../src/execution.rs | 21 ++ .../tests/execution.rs | 45 +++ .../src/evidence.rs | 20 +- .../auths-recipe-qualification/src/launch.rs | 352 ++++++++++++++++++ .../auths-recipe-qualification/src/lib.rs | 2 + .../auths-recipe-qualification/src/verify.rs | 123 +++++- .../auths-gateway/src/bin/auths-gateway.rs | 6 +- product/runtime/auths-gateway/src/lib.rs | 8 +- .../auths-gateway/src/qualification.rs | 5 + qualification/README.md | 26 ++ xtask/Cargo.toml | 2 + xtask/src/main.rs | 1 + xtask/src/release.rs | 6 + xtask/src/release_launch.rs | 194 ++++++++++ 17 files changed, 822 insertions(+), 18 deletions(-) create mode 100644 product/qualification/auths-recipe-qualification/src/launch.rs create mode 100644 xtask/src/release_launch.rs diff --git a/Cargo.lock b/Cargo.lock index 1ad02cb1b..aca959af0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7405,6 +7405,7 @@ dependencies = [ "auths-did-key", "auths-did-web", "auths-errors", + "auths-gateway", "auths-github", "auths-hsm-attested", "auths-kubernetes", @@ -7419,6 +7420,7 @@ dependencies = [ "auths-radicle", "auths-raw-key", "auths-receipts", + "auths-recipe-qualification", "auths-records-api", "auths-registries", "auths-signature", diff --git a/docs/PROGRAM_BOARD.md b/docs/PROGRAM_BOARD.md index f3d647fac..b07ccf0aa 100644 --- a/docs/PROGRAM_BOARD.md +++ b/docs/PROGRAM_BOARD.md @@ -414,3 +414,17 @@ shared controls, retained-floor restore refusal, drained file rotation, privilege-dropped diagnostics, support redaction, disposable trust stages, restart and store-only outage controls. Exact-current-commit hosted rehearsal and CI remain pending. Live production and human adoption claims remain open. + +Epic 5 engineering is underway on `codex/recipe-qualification`, based on the +operator-polish candidate. The exact `393edc52` source-free hosted rehearsal +passed 47 steps in 0.553 seconds; its downloaded archive passed the same 47 +steps in local Docker in 6.162 seconds, including manifest and payload checks. +Main CI remains pending. The initial Epic 5 change derives stable launch +readiness from every signed index entry, exact candidate/production target, +freshness and revocation, three independence dimensions and complete +digest-bound evidence. Each launch claim additionally needs protected +production readiness evidence. The signing output retains those artifacts; +`release-check` emits the projection. No production root is pinned, so the +current projection remains false. Hosted verification of this implementation +is pending. Provider ADRs/corpora/harnesses, live qualification, signed release +publication and the installed SDK pilot remain outstanding. diff --git a/product/qualification/auths-recipe-qualification-issuance/src/bin/auths-qualification.rs b/product/qualification/auths-recipe-qualification-issuance/src/bin/auths-qualification.rs index 9d47232e9..540ce5bdf 100644 --- a/product/qualification/auths-recipe-qualification-issuance/src/bin/auths-qualification.rs +++ b/product/qualification/auths-recipe-qualification-issuance/src/bin/auths-qualification.rs @@ -428,6 +428,19 @@ fn sign( .zip(&attestations) .collect(); let index = signer.index(issued_at, &listed)?; + // Publish the exact evidence already reverified at signing. The launch + // projection checks these bytes against the signed record's digests; + // counters or a case label alone cannot substitute for artifact closure. + for proposal in &proposals { + for artifact in proposal.evidence() { + write( + &out_dir + .join(EVIDENCE_DIRECTORY) + .join(format!("{}.json", artifact.digest().to_hex())), + artifact.canonical_bytes(), + )?; + } + } for (record, attestation) in &listed { let name = format!("{}.json", record.body().qualification_id.as_str()); write( diff --git a/product/qualification/auths-recipe-qualification-issuance/src/execution.rs b/product/qualification/auths-recipe-qualification-issuance/src/execution.rs index 87cca3aef..3f843e669 100644 --- a/product/qualification/auths-recipe-qualification-issuance/src/execution.rs +++ b/product/qualification/auths-recipe-qualification-issuance/src/execution.rs @@ -229,6 +229,19 @@ impl RunCase { has(Op::InstalledConsumer) } S::DeclaredCapability => has(Op::Submit) || has(Op::Probe), + S::ProductionReadiness => { + has(Op::Probe) + && self.steps.iter().all(|step| { + step.operation == Op::Probe + && step.expected.verdict.outcome == RunOutcome::Complete + && step.expected.verdict.code.as_str() == "production-readiness-passed" + && step.expected.verdict.request_sha256.is_none() + && step.expected.verdict.evidence_sha256.is_some() + && step.expected.credential_leases == 0 + && step.expected.provider_entries == 0 + && step.expected.confirmed_by_read_back == 0 + }) + } _ => has(Op::Probe), }; let live_only = matches!( @@ -240,6 +253,7 @@ impl RunCase { | S::InstalledJourney | S::NoRepositoryImport | S::NoProviderToken + | S::ProductionReadiness ); if !harness_scenario(self.scenario) || !required @@ -280,6 +294,13 @@ impl RunCase { mut observe: impl FnMut(usize, &RunStep) -> Result, ) -> Result<(CaseReport, LiveEffects), IssuanceError> { self.validate()?; + if self.scenario == Scenario::ProductionReadiness + && (tuple.target.store_kind + != auths_recipe_qualification::LifecycleStoreKind::PostgresqlV1 + || !tuple.target.credential_store_kind.is_production()) + { + return Err(IssuanceError::CaseFailed); + } let tuple_digest = tuple.digest()?; let mut observations = Vec::with_capacity(self.steps.len()); let mut effects = LiveEffects { diff --git a/product/qualification/auths-recipe-qualification-issuance/tests/execution.rs b/product/qualification/auths-recipe-qualification-issuance/tests/execution.rs index fa3644693..38a5a63dc 100644 --- a/product/qualification/auths-recipe-qualification-issuance/tests/execution.rs +++ b/product/qualification/auths-recipe-qualification-issuance/tests/execution.rs @@ -29,6 +29,51 @@ fn run( .map(|(_, effects)| effects) } +#[test] +fn production_readiness_requires_a_read_only_live_probe_on_a_production_target() { + use auths_recipe_qualification::{BoundedText, LifecycleStoreKind}; + use auths_recipe_qualification_issuance::execution::{Operation, RunPhase}; + let mut case = executable_corpus() + .cases + .into_iter() + .find(|case| case.scenario == Scenario::ApplicationCannotReadSecret) + .expect("probe"); + case.scenario = Scenario::ProductionReadiness; + case.phase = RunPhase::Live; + case.steps.truncate(1); + case.steps[0].operation = Operation::Probe; + let expected = &mut case.steps[0].expected; + expected.verdict.outcome = RunOutcome::Complete; + expected.verdict.code = BoundedText::parse("production-readiness-passed").expect("code"); + expected.verdict.request_sha256 = None; + expected.verdict.evidence_sha256 = Some(tuple().profile_lock_sha256); + expected.credential_leases = 0; + expected.provider_entries = 0; + expected.confirmed_by_read_back = 0; + assert!(run(&case, |_, _| {}).is_ok()); + for index in 0..4 { + let mut changed = case.clone(); + match index { + 0 => changed.phase = RunPhase::Offline, + 1 => changed.steps[0].expected.credential_leases = 1, + 2 => changed.steps[0].expected.provider_entries = 1, + _ => changed.steps[0].expected.verdict.evidence_sha256 = None, + } + assert_eq!(run(&changed, |_, _| {}), Err(IssuanceError::CaseFailed)); + } + let mut development = tuple(); + development.target.store_kind = LifecycleStoreKind::SharedFileV1; + let mut invoked = false; + assert_eq!( + case.execute(&development, |_, _| { + invoked = true; + Err(IssuanceError::CaseFailed) + }), + Err(IssuanceError::CaseFailed) + ); + assert!(!invoked); +} + #[test] fn every_stage_executes_its_operations_and_a_missing_runner_refuses() { let corpus = executable_corpus(); diff --git a/product/qualification/auths-recipe-qualification/src/evidence.rs b/product/qualification/auths-recipe-qualification/src/evidence.rs index 35179a77b..6412aa971 100644 --- a/product/qualification/auths-recipe-qualification/src/evidence.rs +++ b/product/qualification/auths-recipe-qualification/src/evidence.rs @@ -107,6 +107,9 @@ pub enum Scenario { /// An application process without a credential cannot read secret /// material. ApplicationCannotReadSecret, + /// All required typed production doctor checks pass. Required for the + /// stable launch projection, never inferred from development readiness. + ProductionReadiness, /// A forged proof enters no provider. ForgedProof, /// An action altered after approval enters no provider. @@ -174,7 +177,7 @@ pub enum Scenario { impl Scenario { /// Every scenario, in the wall's order. - pub const ALL: [Self; 36] = [ + pub const ALL: [Self; 37] = [ Self::CleanSource, Self::RecipeDigestRederives, Self::RecipeVectors, @@ -182,6 +185,7 @@ impl Scenario { Self::OracleAccepts, Self::OracleRejects, Self::ApplicationCannotReadSecret, + Self::ProductionReadiness, Self::ForgedProof, Self::AlteredAction, Self::ProofReplay, @@ -220,7 +224,9 @@ impl Scenario { Self::CleanSource | Self::RecipeDigestRederives => WallRow::CleanSource, Self::RecipeVectors | Self::ClosedEnumerationHostile => WallRow::RecipeVectors, Self::OracleAccepts | Self::OracleRejects => WallRow::OracleAgreement, - Self::ApplicationCannotReadSecret => WallRow::SecretIsolation, + Self::ApplicationCannotReadSecret | Self::ProductionReadiness => { + WallRow::SecretIsolation + } Self::ForgedProof | Self::AlteredAction | Self::ProofReplay @@ -272,11 +278,15 @@ impl Scenario { } } - /// Whether every record needs a case for this scenario. The two that do - /// not are required exactly when a capability they show is exercised. + /// Whether every record needs a case for this scenario. Capability cases + /// are required when declared; production readiness is additionally + /// required by the stable launch projection. #[must_use] pub const fn always_required(self) -> bool { - !matches!(self, Self::ObserverRotation | Self::DeclaredCapability) + !matches!( + self, + Self::ObserverRotation | Self::DeclaredCapability | Self::ProductionReadiness + ) } /// Whether a case for this scenario may show `capability` exercised. diff --git a/product/qualification/auths-recipe-qualification/src/launch.rs b/product/qualification/auths-recipe-qualification/src/launch.rs new file mode 100644 index 000000000..fc70adaf8 --- /dev/null +++ b/product/qualification/auths-recipe-qualification/src/launch.rs @@ -0,0 +1,352 @@ +//! Inputs the release builder derives for the stable launch projection. + +use crate::{GitCommit, QualificationTarget, Sha256Digest}; + +/// Exact candidate identity, derived by the release builder rather than a +/// qualification record. A caller must read the candidate's executable and +/// maintained semantic closure to supply these facts. This value contains no +/// readiness flag and cannot authorize a gateway credential lease. +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct LaunchCandidate { + /// The clean candidate source commit. + pub commit: GitCommit, + /// The candidate's maintained gateway semantic closure. + pub gateway_semantic_closure_sha256: Sha256Digest, + /// The exact production deployment and candidate executable digest. + pub target: QualificationTarget, +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::vectors::{ + Keys, NOW, attestation, attestation_statement, bounded, certificate, certificate_statement, + digest_of, index, index_entry, index_statement, record, revocation, revocation_statement, + text, trust_root, tuple, + }; + use crate::{ + Canonical, CapabilityResult, EVIDENCE_SCHEMA, EvidenceBody, EvidenceCase, EvidenceMember, + EvidenceMemberKind, EvidenceResult, QualificationEvidence, QualificationInputs, + QualificationTrustRoot, RecipeFamilyId, RecipeQualificationRecord, RecordBody, Scenario, + VerifiedQualifications, VerifierState, + }; + use auths_connections::{CredentialStoreKind, ProviderKind}; + + struct Fixture { + records: Vec, + evidence: Vec, + expired: Option, + revoked: Option, + } + + impl Fixture { + fn new(claims: &[(&str, &str, &str)], readiness: bool) -> Self { + let mut records = Vec::new(); + let mut evidence = Vec::new(); + for (index, (family, provider, contract)) in claims.iter().enumerate() { + let mut deployment = tuple(); + deployment.recipe_family = RecipeFamilyId::parse(family).expect("family"); + let mut declared = crate::vectors::contract(); + declared.api_release = bounded(contract); + deployment.provider_contract_id = + crate::vectors::decoded_contract(&declared).contract_id(); + let mut body = record( + u8::try_from(index + 1).expect("bounded fixture"), + deployment, + ); + body.provider_kind = ProviderKind::parse(provider).expect("provider"); + body.provenance.environment = + bounded(&format!("recipe-qualification-live-{family}")); + let artifacts = artifacts(&body, readiness); + body.evidence = artifacts + .iter() + .map(|artifact| EvidenceMember { + member: artifact.body().member, + result: EvidenceResult::Passed, + evidence_sha256: artifact.digest(), + cases: u32::try_from(artifact.body().cases.len()).expect("bounded cases"), + unauthorized_provider_entries: 0, + }) + .collect(); + records.push(body); + evidence.extend(artifacts); + } + Self { + records, + evidence, + expired: None, + revoked: None, + } + } + + fn two() -> Self { + Self::new( + &[ + ("refund-v1", "stripe", "stripe contract"), + ("record-update-v1", "airtable", "airtable contract"), + ], + true, + ) + } + + fn candidate(&self) -> LaunchCandidate { + let record = &self.records[0]; + LaunchCandidate { + commit: record.provenance.commit.clone(), + gateway_semantic_closure_sha256: record.tuple.gateway_semantic_closure_sha256, + target: record.tuple.target.clone(), + } + } + + fn verified(&self, omit_record: bool) -> VerifiedQualifications { + let keys = Keys::fixed(); + let root = QualificationTrustRoot::from_body(&trust_root(&keys)).expect("root"); + let certificate = text(&certificate(certificate_statement(&keys), &keys.root)); + let mut revoked = revocation_statement(NOW); + if let Some(index) = self.revoked { + revoked + .revoked_qualifications + .push(self.records[index].qualification_id.clone()); + } + let revocations = text(&revocation(revoked, &keys.root)); + let records: Vec = self.records.iter().map(text).collect(); + let attestations: Vec = records + .iter() + .enumerate() + .map(|(index, record)| { + let mut statement = + attestation_statement(record, u8::try_from(index + 1).expect("id")); + if self.expired == Some(index) { + statement.not_after = NOW - 1; + } + text(&attestation(statement, &keys.signer)) + }) + .collect(); + let entries = records + .iter() + .zip(&attestations) + .enumerate() + .map(|(index, (record, attestation))| { + index_entry(u8::try_from(index + 1).expect("id"), record, attestation) + }) + .collect(); + let index = text(&index(index_statement(entries), &keys.signer)); + let records: Vec<&[u8]> = records + .iter() + .take(if omit_record { 1 } else { records.len() }) + .map(|record| record.as_bytes()) + .collect(); + let attestations: Vec<&[u8]> = attestations + .iter() + .map(|attestation| attestation.as_bytes()) + .collect(); + VerifiedQualifications::verify( + &root, + &QualificationInputs { + signer_certificate: certificate.as_bytes(), + revocation_list: revocations.as_bytes(), + release_index: index.as_bytes(), + records: &records, + attestations: &attestations, + }, + ) + } + + fn ready(&self) -> bool { + self.verified(false).stable_launch_ready( + &self.candidate(), + &self.evidence, + NOW, + true, + &VerifierState::default(), + ) + } + } + + fn artifacts(record: &RecordBody, readiness: bool) -> Vec { + EvidenceMemberKind::ALL + .into_iter() + .map(|member| { + let mut cases: Vec = Scenario::ALL + .into_iter() + .filter(|scenario| { + scenario.member() == member + && (scenario.always_required() + || (readiness && *scenario == Scenario::ProductionReadiness)) + }) + .map(|scenario| EvidenceCase { + id: bounded(&format!("{scenario:?}")), + scenario, + capabilities: Vec::new(), + unauthorized_provider_entries: 0, + }) + .collect(); + for capability in &record.capabilities { + if capability.result == CapabilityResult::Exercised + && capability.capability.member() == member + { + let scenario = match capability.capability { + crate::CapabilityKind::Recovery => Scenario::ResponseLoss, + crate::CapabilityKind::ObserverRotation => Scenario::ObserverRotation, + _ => Scenario::DeclaredCapability, + }; + cases.push(EvidenceCase { + id: bounded(&format!("capability-{:?}", capability.capability)), + scenario, + capabilities: vec![capability.capability], + unauthorized_provider_entries: 0, + }); + } + } + cases.sort_by(|left, right| left.id.cmp(&right.id)); + Canonical::from_body(&EvidenceBody { + schema: EVIDENCE_SCHEMA.to_owned(), + member, + commit: record.provenance.commit.clone(), + tuple_sha256: record.tuple.digest().expect("tuple"), + cases, + live_effects: (member == EvidenceMemberKind::Live) + .then_some(record.live_effects), + }) + .expect("evidence") + }) + .collect() + } + + #[test] + fn two_signed_independent_production_claims_with_closed_evidence_are_ready() { + let fixture = Fixture::two(); + for record in &fixture.records { + RecipeQualificationRecord::from_body(record).expect("closed record"); + } + assert!(fixture.ready()); + } + + #[test] + fn each_independence_dimension_is_required() { + for claims in [ + [ + ("refund-v1", "stripe", "stripe contract"), + ("refund-v1", "airtable", "airtable contract"), + ], + [ + ("refund-v1", "stripe", "shared contract"), + ("record-update-v1", "airtable", "shared contract"), + ], + [ + ("refund-v1", "stripe", "one contract"), + ("record-update-v1", "stripe", "another contract"), + ], + ] { + assert!(!Fixture::new(&claims, true).ready()); + } + } + + #[test] + fn missing_or_tampered_evidence_and_missing_index_members_refuse() { + let fixture = Fixture::two(); + let verified = fixture.verified(false); + let candidate = fixture.candidate(); + let state = VerifierState::default(); + assert!(!verified.stable_launch_ready( + &candidate, + &fixture.evidence[1..], + NOW, + true, + &state + )); + let mut changed = fixture.evidence.clone(); + let mut body = changed[0].body().clone(); + body.cases[0].id = bounded("substituted-case"); + body.cases.sort_by(|left, right| left.id.cmp(&right.id)); + changed[0] = QualificationEvidence::from_body(&body).expect("changed evidence"); + assert!(!verified.stable_launch_ready(&candidate, &changed, NOW, true, &state)); + assert!(!fixture.verified(true).stable_launch_ready( + &candidate, + &fixture.evidence, + NOW, + true, + &state + )); + assert!( + !Fixture::new( + &[ + ("refund-v1", "stripe", "one"), + ("update-v1", "airtable", "two") + ], + false + ) + .ready() + ); + } + + #[test] + fn candidate_drift_development_custody_and_untrusted_time_refuse() { + let fixture = Fixture::two(); + let verified = fixture.verified(false); + let candidate = fixture.candidate(); + let state = VerifierState::default(); + for changed in [ + LaunchCandidate { + commit: GitCommit::parse("abcdef0123456789abcdef0123456789abcdef01") + .expect("commit"), + ..candidate.clone() + }, + LaunchCandidate { + gateway_semantic_closure_sha256: digest_of("changed closure"), + ..candidate.clone() + }, + LaunchCandidate { + target: crate::QualificationTarget { + gateway_build_sha256: digest_of("changed binary"), + ..candidate.target.clone() + }, + ..candidate.clone() + }, + LaunchCandidate { + target: crate::QualificationTarget { + store_kind: crate::LifecycleStoreKind::SharedFileV1, + ..candidate.target.clone() + }, + ..candidate.clone() + }, + LaunchCandidate { + target: crate::QualificationTarget { + credential_store_kind: CredentialStoreKind::LocalFileV1, + ..candidate.target.clone() + }, + ..candidate.clone() + }, + ] { + assert!(!verified.stable_launch_ready(&changed, &fixture.evidence, NOW, true, &state)); + } + assert!(!verified.stable_launch_ready(&candidate, &fixture.evidence, NOW, false, &state)); + assert!(!verified.stable_launch_ready( + &candidate, + &fixture.evidence, + NOW + crate::MAX_REVOCATION_SECONDS + 1, + true, + &state + )); + } + + #[test] + fn a_valid_family_entry_cannot_hide_an_expired_or_revoked_duplicate() { + for revoked in [false, true] { + let mut fixture = Fixture::new( + &[ + ("refund-v1", "stripe", "stripe contract"), + ("record-update-v1", "airtable", "airtable contract"), + ("refund-v1", "stripe", "stripe contract"), + ], + true, + ); + if revoked { + fixture.revoked = Some(2); + } else { + fixture.expired = Some(2); + } + assert!(!fixture.ready()); + } + } +} diff --git a/product/qualification/auths-recipe-qualification/src/lib.rs b/product/qualification/auths-recipe-qualification/src/lib.rs index 1e6e09a64..b3f54a3f3 100644 --- a/product/qualification/auths-recipe-qualification/src/lib.rs +++ b/product/qualification/auths-recipe-qualification/src/lib.rs @@ -21,6 +21,7 @@ mod closure; mod error; mod evidence; mod ids; +mod launch; mod model; mod release; mod verify; @@ -56,6 +57,7 @@ pub use ids::{ BoundedText, GitCommit, InvalidIdentifier, PublicKeyB64, QualificationId, QualificationRootId, QualificationSignerId, RecipeFamilyId, Sha256Digest, SignatureB64, }; +pub use launch::LaunchCandidate; pub use model::{ CapabilityKind, CapabilityResult, ContractDeclarations, EvidenceMember, EvidenceMemberKind, EvidenceResult, ExercisedCapability, InstalledPackage, LifecycleStoreKind, LiveEffects, diff --git a/product/qualification/auths-recipe-qualification/src/verify.rs b/product/qualification/auths-recipe-qualification/src/verify.rs index 9b376cb5f..dca324b87 100644 --- a/product/qualification/auths-recipe-qualification/src/verify.rs +++ b/product/qualification/auths-recipe-qualification/src/verify.rs @@ -12,10 +12,11 @@ //! compared as a digest. use crate::{ - Canonical, QualificationArtifactKind, QualificationId, QualificationReleaseIndex, - QualificationRevocationList, QualificationSignerCertificate, QualificationSignerId, - QualificationTrustRoot, QualificationTuple, RecipeQualificationAttestation, - RecipeQualificationRecord, RecipeQualificationState, Sha256Digest, + Canonical, LaunchCandidate, LifecycleStoreKind, QualificationArtifactKind, + QualificationEvidence, QualificationId, QualificationReleaseIndex, QualificationRevocationList, + QualificationSignerCertificate, QualificationSignerId, QualificationTrustRoot, + QualificationTuple, RecipeQualificationAttestation, RecipeQualificationRecord, + RecipeQualificationState, Scenario, Sha256Digest, verify_evidence_closure, }; use ed25519_dalek::{Signature, VerifyingKey}; use std::collections::BTreeSet; @@ -157,6 +158,120 @@ pub struct VerifiedQualifications { } impl VerifiedQualifications { + /// Computes AP-SPEC-066's technical stable launch gate for `candidate`. + /// + /// Every index entry must have its own usable attestation, match the clean + /// candidate's exact build, target and semantic closure, remain qualified + /// at the supplied trusted time, and close over the presented protected + /// evidence, including production readiness. At least two distinct recipe + /// families, contracts and provider kinds must be covered. Missing or + /// excess evidence, a development target, an unusable extra index entry, + /// or any failed condition returns false. This does not represent the + /// separate human release judgment or independent operator adoption. + #[must_use] + pub fn stable_launch_ready( + &self, + candidate: &LaunchCandidate, + evidence: &[QualificationEvidence], + now: u64, + clock_trusted: bool, + state: &VerifierState, + ) -> bool { + let Some(index) = self.current_index(state) else { + return false; + }; + if candidate.target.store_kind != LifecycleStoreKind::PostgresqlV1 + || !candidate.target.credential_store_kind.is_production() + || self.listed.len() != index.body().statement.entries.len() + || self.listed.len() < 2 + || evidence.len() != self.listed.len() * crate::EvidenceMemberKind::ALL.len() + { + return false; + } + let mut families = BTreeSet::new(); + let mut contracts = BTreeSet::new(); + let mut providers = BTreeSet::new(); + let mut used_evidence = BTreeSet::new(); + for listed in &self.listed { + let record = listed.record.body(); + if !self.launch_record_matches(listed, candidate, now, state) + || !self + .evaluate(&record.tuple, now, clock_trusted, state) + .permits_lease() + { + return false; + } + let artifacts: Option> = record + .evidence + .iter() + .map(|member| { + let artifact = evidence + .iter() + .find(|artifact| artifact.digest() == member.evidence_sha256)?; + used_evidence.insert(artifact.digest()); + Some(artifact.clone()) + }) + .collect(); + let Some(artifacts) = artifacts else { + return false; + }; + if verify_evidence_closure(&listed.record, &artifacts).is_err() + || !artifacts.iter().any(|artifact| { + artifact + .body() + .cases + .iter() + .any(|case| case.scenario == Scenario::ProductionReadiness) + }) + { + return false; + } + families.insert(record.tuple.recipe_family.clone()); + contracts.insert(record.tuple.provider_contract_id); + providers.insert(record.provider_kind.as_str()); + } + used_evidence.len() == evidence.len() + && families.len() >= 2 + && contracts.len() >= 2 + && providers.len() >= 2 + } + + fn launch_record_matches( + &self, + listed: &Listed, + candidate: &LaunchCandidate, + now: u64, + state: &VerifierState, + ) -> bool { + let record = listed.record.body(); + // Family evaluation selects its best attestation. Inspect this entry's + // own signed window and revocation too; an extra claim cannot hide + // behind a fresh unrevoked entry for the same family. + listed.attestation.as_ref().is_some_and(|attestation| { + let statement = &attestation.body().statement; + now >= statement.issued_at && now >= statement.not_before && now <= statement.not_after + }) && record.provenance.commit == candidate.commit + && record.tuple.target == candidate.target + && record.tuple.gateway_semantic_closure_sha256 + == candidate.gateway_semantic_closure_sha256 + && !state + .revoked_qualifications + .contains(&record.qualification_id) + && !self.revocations.as_ref().is_some_and(|list| { + list.body() + .statement + .revoked_qualifications + .contains(&record.qualification_id) + }) + && record.provenance.repository.as_str() == "github.com/auths-dev/auths-proof" + && record.provenance.workflow.as_str() == ".github/workflows/recipe-qualification.yml" + && record.provenance.environment.as_str() + == format!( + "recipe-qualification-live-{}", + record.tuple.recipe_family.as_str() + ) + } + /// Checks every signature under the pinned `root`. An input that does /// not decode or verify is kept as absent; nothing is trusted from it. #[must_use] diff --git a/product/runtime/auths-gateway/src/bin/auths-gateway.rs b/product/runtime/auths-gateway/src/bin/auths-gateway.rs index 2f49a1685..51300180d 100644 --- a/product/runtime/auths-gateway/src/bin/auths-gateway.rs +++ b/product/runtime/auths-gateway/src/bin/auths-gateway.rs @@ -85,10 +85,6 @@ mod unix { const QUALIFICATION_STATE_FILE: &str = "qualification-state.json"; /// A development installation's own trust root. const QUALIFICATION_ROOT_FILE: &str = "qualification-trust-root.json"; - /// The qualification trust root this build pins. It is `None` until a - /// reviewed release pins the root the offline ceremony created; until - /// then a production gateway finds every recipe unqualified. - const PINNED_QUALIFICATION_ROOT: Option<&[u8]> = None; const OBSERVER_SEED: &str = "observer.seed"; const OPERATOR_ATTESTATION_FILE: &str = "operator-attestation.json"; use auths_gateway::admin::{ @@ -1489,7 +1485,7 @@ mod unix { Some(bytes) } (Some(_), Deployment::Production) => return Err("gateway.serve.invalid-installation"), - (None, _) => PINNED_QUALIFICATION_ROOT.map(<[u8]>::to_vec), + (None, _) => auths_gateway::PINNED_QUALIFICATION_ROOT.map(<[u8]>::to_vec), }; bytes .map(|bytes| { diff --git a/product/runtime/auths-gateway/src/lib.rs b/product/runtime/auths-gateway/src/lib.rs index 094e32937..279af6ee3 100644 --- a/product/runtime/auths-gateway/src/lib.rs +++ b/product/runtime/auths-gateway/src/lib.rs @@ -99,10 +99,10 @@ pub use operator::{ #[cfg(any(test, feature = "testkit-harness"))] pub use qualification::FixedClock; pub use qualification::{ - DeploymentClock, DeploymentFacts, DevelopmentClock, FILE_STORE_SCHEMA, POSTGRES_STORE_SCHEMA, - QUALIFICATION_POLICY_REFUSED, QualificationBundle, QualificationGate, QualificationPolicy, - QualificationStatus, SynchronizedHostClock, deployment_tuple, qualification_code, - qualification_policy, + DeploymentClock, DeploymentFacts, DevelopmentClock, FILE_STORE_SCHEMA, + PINNED_QUALIFICATION_ROOT, POSTGRES_STORE_SCHEMA, QUALIFICATION_POLICY_REFUSED, + QualificationBundle, QualificationGate, QualificationPolicy, QualificationStatus, + SynchronizedHostClock, deployment_tuple, qualification_code, qualification_policy, }; pub use readiness::{ ClockTrustState, CredentialRetirementDelay, ObserverCustodyState, PreconditionState, diff --git a/product/runtime/auths-gateway/src/qualification.rs b/product/runtime/auths-gateway/src/qualification.rs index b5be98dcf..826cfef71 100644 --- a/product/runtime/auths-gateway/src/qualification.rs +++ b/product/runtime/auths-gateway/src/qualification.rs @@ -27,6 +27,11 @@ pub const POSTGRES_STORE_SCHEMA: &str = "auths.lifecycle.postgresql/5"; /// The schema identifier of the development file store. pub const FILE_STORE_SCHEMA: &str = "auths.gateway-attempt/3"; +/// The public qualification root this gateway build pins. A reviewed release +/// supplies only the offline ceremony's public artifact here. Until then both +/// the runtime and release projection authenticate no qualification. +pub const PINNED_QUALIFICATION_ROOT: Option<&[u8]> = None; + /// The stable code of one refusal. #[must_use] pub const fn qualification_code(refusal: QualificationRefusal) -> &'static str { diff --git a/qualification/README.md b/qualification/README.md index 64e9eab4a..19c392476 100644 --- a/qualification/README.md +++ b/qualification/README.md @@ -9,6 +9,32 @@ The specification is No family is qualified and none is present here yet. The two launch families arrive with their decision records. +`cargo xtask release-check` generates `target/release-evidence/launch-readiness.json`. +Its `stable_launch_ready` value comes from the gateway build's pinned public +root, current signed inputs and their actual evidence; no checked-in flag can +set it. The current build pins no root and therefore derives false. Missing +qualification permits a prerelease while preventing a stable launch claim. + +The release builder reads public signed inputs from +`target/qualification-release//`. These downloaded +public artifacts are build inputs, not a source commit containing a reference +to itself. The signing tool includes +the canonical evidence at `evidence/.json`, alongside the +index, records, attestations, certificate and revocation list. The projection +verifies every referenced artifact and requires two distinct families, +contracts and provider kinds on the same production candidate. Its clock +must pass the maintained synchronization check. Human release review remains +a separate requirement. + +A `production-readiness` case is additionally required for each stable launch +claim. It runs only in the protected live phase against PostgreSQL and +production custody, without a lease or provider entry. The reviewed harness +must run the candidate's doctor and check every required typed row, including +qualification, then return `production-readiness-passed` and the digest of its +actual report. Development `not-ready` reports cannot satisfy it. This case +is optional for intermediate qualification records; its absence always makes +the stable launch projection false. + ## `families//` One directory per recipe family, named by its `RecipeFamilyId`. diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml index a90b553f4..911bd2ce3 100644 --- a/xtask/Cargo.toml +++ b/xtask/Cargo.toml @@ -30,12 +30,14 @@ auths-ci-plan = { path = "ci-plan", version = "1.0.0-rc.1" } auths-lab-matrix.workspace = true auths-lifecycle.workspace = true auths-github = { workspace = true, features = ["fixture-support"] } +auths-gateway.workspace = true auths-kubernetes.workspace = true auths-opentofu.workspace = true auths-postgresql.workspace = true auths-proof-exchange-testkit.workspace = true auths-radicle = { workspace = true, features = ["fixture-support"] } auths-records-api.workspace = true +auths-recipe-qualification.workspace = true auths-stripe = { workspace = true, features = ["fixture-support"] } base64ct.workspace = true ed25519-dalek.workspace = true diff --git a/xtask/src/main.rs b/xtask/src/main.rs index e6c26a436..5a4b0d94d 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -26,6 +26,7 @@ mod product_waist; mod public_naming; mod release; mod release_control; +mod release_launch; mod sdk_experience; mod sdk_vocabulary; mod semantic_freeze; diff --git a/xtask/src/release.rs b/xtask/src/release.rs index fb702b627..2f4d4f4be 100644 --- a/xtask/src/release.rs +++ b/xtask/src/release.rs @@ -297,7 +297,13 @@ pub(crate) fn release_evidence() -> Result<(), String> { let platform_path = evidence.join("platform.json"); platform_artifact(&platform_path)?; let mut evidence_checksums = BTreeMap::new(); + let launch_path = evidence.join("launch-readiness.json"); + let launch = release_launch::projection(&root(), &commit)?; + fs::write(&launch_path, pretty_json(&launch, "launch readiness")?) + .map_err(|error| format!("could not write launch projection: {error}"))?; + println!("stable_launch_ready: {}", launch["stable_launch_ready"]); for relative in [ + "target/release-evidence/launch-readiness.json", "target/release-evidence/platform.json", "target/release-evidence/platform.sha256", "target/compliance/inventory.json", diff --git a/xtask/src/release_launch.rs b/xtask/src/release_launch.rs new file mode 100644 index 000000000..d85d789fe --- /dev/null +++ b/xtask/src/release_launch.rs @@ -0,0 +1,194 @@ +//! The release projection reads only the gateway build's pinned root and +//! clean candidate inputs. Missing qualification does not prevent an RC; +//! it computes false and never promotes a human or production claim. + +use auths_gateway::{ClockTrustState, DeploymentClock as _}; +use auths_recipe_qualification::{ + Artifact, GatewaySemanticClosure, GitCommit, LaunchCandidate, QualificationEvidence, + QualificationInputs, QualificationReleaseIndex, QualificationTarget, QualificationTrustRoot, + RecipeQualificationRecord, VerifiedQualifications, VerifierState, +}; +use serde_json::{Value, json}; +use sha2::{Digest as _, Sha256}; +use std::{fs, io::Read as _, path::Path, process::Command}; + +fn bounded(path: &Path, maximum: usize) -> Result, String> { + let metadata = fs::symlink_metadata(path).map_err(|_| "qualification input unavailable")?; + if !metadata.file_type().is_file() || metadata.len() > maximum as u64 { + return Err("qualification input invalid or oversized".to_owned()); + } + let mut bytes = Vec::new(); + fs::File::open(path) + .map_err(|_| "qualification input unavailable")? + .take(maximum as u64 + 1) + .read_to_end(&mut bytes) + .map_err(|_| "qualification input unavailable")?; + if bytes.len() > maximum { + return Err("qualification input oversized".to_owned()); + } + Ok(bytes) +} + +fn candidate(repository: &Path, commit: &str) -> Result { + let status = Command::new("cargo") + .args([ + "build", + "--locked", + "--release", + "-p", + "auths-gateway", + "--bin", + "auths-gateway", + ]) + .current_dir(repository) + .status() + .map_err(|_| "candidate build unavailable")?; + if !status.success() { + return Err("candidate build failed".to_owned()); + } + let executable = bounded( + &repository.join("target/release/auths-gateway"), + 128 * 1024 * 1024, + )?; + let closure = GatewaySemanticClosure::from_canonical_json(&bounded( + &repository.join("product/runtime/auths-gateway/semantic-closure.json"), + GatewaySemanticClosure::MAX_BYTES, + )?) + .map_err(|_| "candidate closure invalid")?; + if closure.digest().to_hex() != auths_gateway::GATEWAY_SEMANTIC_CLOSURE_SHA256 { + return Err("candidate closure differs from compiled gateway".to_owned()); + } + let os = match std::env::consts::OS { + "linux" => "linux", + "macos" => "macos", + _ => return Err("candidate OS unsupported".to_owned()), + }; + let arch = match std::env::consts::ARCH { + "x86_64" => "x86_64", + "aarch64" => "aarch64", + _ => return Err("candidate architecture unsupported".to_owned()), + }; + let target: QualificationTarget = serde_json::from_value(json!({ + "os": os, "arch": arch, "gateway_package": "auths-gateway", + "gateway_version": env!("CARGO_PKG_VERSION"), + "gateway_build_sha256": hex::encode(Sha256::digest(&executable)), + "store_kind": "postgresql-v1", "store_schema": auths_gateway::POSTGRES_STORE_SCHEMA, + "credential_store_kind": "aws-secrets-manager-v1", + })) + .map_err(|_| "candidate target invalid")?; + Ok(LaunchCandidate { + commit: GitCommit::parse(commit).map_err(|_| "candidate commit invalid")?, + gateway_semantic_closure_sha256: closure.digest(), + target, + }) +} + +fn evaluate( + repository: &Path, + candidate: &LaunchCandidate, + root: &QualificationTrustRoot, + now: u64, +) -> Result { + let directory = repository + .join("target/qualification-release") + .join(candidate.commit.as_str()); + let index = bounded( + &directory.join(auths_recipe_qualification::RELEASE_INDEX_FILE), + auths_recipe_qualification::MAX_RELEASE_INDEX_BYTES, + )?; + let parsed_index = QualificationReleaseIndex::from_canonical_json(&index) + .map_err(|_| "qualification index invalid")?; + let certificate = bounded( + &directory.join(auths_recipe_qualification::RELEASE_SIGNER_CERTIFICATE_FILE), + auths_recipe_qualification::MAX_SIGNER_CERTIFICATE_BYTES, + )?; + let revocations = bounded( + &directory.join(auths_recipe_qualification::RELEASE_REVOCATION_LIST_FILE), + auths_recipe_qualification::MAX_REVOCATION_LIST_BYTES, + )?; + let mut records = Vec::new(); + let mut attestations = Vec::new(); + let mut evidence = Vec::new(); + for entry in &parsed_index.body().statement.entries { + let name = format!("{}.json", entry.qualification_id.as_str()); + let bytes = bounded( + &directory + .join(auths_recipe_qualification::RELEASE_RECORDS_DIRECTORY) + .join(&name), + auths_recipe_qualification::MAX_RECORD_BYTES, + )?; + let record = RecipeQualificationRecord::from_canonical_json(&bytes) + .map_err(|_| "qualification record invalid")?; + for member in &record.body().evidence { + let path = directory + .join("evidence") + .join(format!("{}.json", member.evidence_sha256.to_hex())); + evidence.push( + QualificationEvidence::from_canonical_json(&bounded( + &path, + auths_recipe_qualification::MAX_EVIDENCE_BYTES, + )?) + .map_err(|_| "qualification evidence invalid")?, + ); + } + records.push(bytes); + attestations.push(bounded( + &directory + .join(auths_recipe_qualification::RELEASE_ATTESTATIONS_DIRECTORY) + .join(name), + auths_recipe_qualification::MAX_ATTESTATION_BYTES, + )?); + } + let record_refs: Vec<&[u8]> = records.iter().map(Vec::as_slice).collect(); + let attestation_refs: Vec<&[u8]> = attestations.iter().map(Vec::as_slice).collect(); + let verified = VerifiedQualifications::verify( + root, + &QualificationInputs { + signer_certificate: &certificate, + revocation_list: &revocations, + release_index: &index, + records: &record_refs, + attestations: &attestation_refs, + }, + ); + Ok(verified.stable_launch_ready(candidate, &evidence, now, true, &VerifierState::default())) +} + +pub(crate) fn projection(repository: &Path, commit: &str) -> Result { + let mut report = json!({"schema": "auths.launch-readiness/1", "source_commit": commit, + "gateway_semantic_closure_sha256": auths_gateway::GATEWAY_SEMANTIC_CLOSURE_SHA256, + "stable_launch_ready": false, "reason": "pinned-root-unavailable", + "human_release_review": "separate-required-gate"}); + let Some(root_bytes) = auths_gateway::PINNED_QUALIFICATION_ROOT else { + return Ok(report); + }; + let Ok(root) = QualificationTrustRoot::from_canonical_json(root_bytes) else { + report["reason"] = json!("pinned-root-invalid"); + return Ok(report); + }; + let clock = auths_gateway::SynchronizedHostClock; + let Some(now) = clock + .now() + .filter(|_| clock.trust() == ClockTrustState::Trusted) + else { + report["reason"] = json!("release-clock-untrusted"); + return Ok(report); + }; + let candidate = candidate(repository, commit)?; + report["target"] = + serde_json::to_value(&candidate.target).map_err(|_| "candidate target unencodable")?; + match evaluate(repository, &candidate, &root, now) { + Ok(ready) => { + report["stable_launch_ready"] = json!(ready); + report["reason"] = json!(if ready { + "technical-gates-passed" + } else { + "qualification-gates-not-satisfied" + }); + } + Err(_) => { + report["reason"] = json!("qualification-inputs-unavailable-or-invalid"); + } + } + Ok(report) +} From 88dad6b29df812ddaec060c8bb7c57938eabdc42 Mon Sep 17 00:00:00 2001 From: bordumb Date: Tue, 6 Oct 2026 20:59:37 +0100 Subject: [PATCH 028/108] fix(release): use the semantic closure decoder bound --- xtask/src/release_launch.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/xtask/src/release_launch.rs b/xtask/src/release_launch.rs index d85d789fe..94e750f2b 100644 --- a/xtask/src/release_launch.rs +++ b/xtask/src/release_launch.rs @@ -4,8 +4,8 @@ use auths_gateway::{ClockTrustState, DeploymentClock as _}; use auths_recipe_qualification::{ - Artifact, GatewaySemanticClosure, GitCommit, LaunchCandidate, QualificationEvidence, - QualificationInputs, QualificationReleaseIndex, QualificationTarget, QualificationTrustRoot, + GatewaySemanticClosure, GitCommit, LaunchCandidate, QualificationEvidence, QualificationInputs, + QualificationReleaseIndex, QualificationTarget, QualificationTrustRoot, RecipeQualificationRecord, VerifiedQualifications, VerifierState, }; use serde_json::{Value, json}; @@ -52,7 +52,7 @@ fn candidate(repository: &Path, commit: &str) -> Result )?; let closure = GatewaySemanticClosure::from_canonical_json(&bounded( &repository.join("product/runtime/auths-gateway/semantic-closure.json"), - GatewaySemanticClosure::MAX_BYTES, + auths_recipe_qualification::MAX_SEMANTIC_CLOSURE_BYTES, )?) .map_err(|_| "candidate closure invalid")?; if closure.digest().to_hex() != auths_gateway::GATEWAY_SEMANTIC_CLOSURE_SHA256 { From 00206fb82a76fcc41932a20e25e9f7c073620d72 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 6 Oct 2026 20:09:01 +0000 Subject: [PATCH 029/108] chore(formal): regenerate qualification artifacts Source-SHA: 88dad6b29df812ddaec060c8bb7c57938eabdc42 Workflow-Run: 37523066656 --- formal/qualification/aeneas/source-closure.json | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/formal/qualification/aeneas/source-closure.json b/formal/qualification/aeneas/source-closure.json index 029640dd5..58a2c5483 100644 --- a/formal/qualification/aeneas/source-closure.json +++ b/formal/qualification/aeneas/source-closure.json @@ -1,6 +1,6 @@ { "schema": "auths-proof-translation-source-closure/v2", - "digest": "f3b8cc9336cc95cfabab6629e583f58717601435d678375a62416160a2efb461", + "digest": "4a475e2a52afaf2fd47cd8bc6426750db2b65ee6cac4acb892f13b69699d12d9", "files": [ { "path": ".cargo/config.toml", @@ -8,7 +8,7 @@ }, { "path": "Cargo.lock", - "sha256": "e11d08de053ca87e33f265c6ff0bc55d4cca51777cf9b54f5c2fa39b4d032a24", + "sha256": "f84825e2ac0d4af57a406ab4b49ae5ce4e9360caf0a23e092906257743509b04", "normalization": "translated-cargo-closure-v1" }, { @@ -261,7 +261,7 @@ }, { "path": "xtask/Cargo.toml", - "sha256": "ec016a7130a9a604c146f56458e30fef96c9dedc82790f07047dabeac1142e2d" + "sha256": "66b2989994cb878392e352a3c1a632b6cc64074aa4e37e8e77361a191a60a0c5" }, { "path": "xtask/ci-plan/Cargo.toml", @@ -353,7 +353,7 @@ }, { "path": "xtask/src/main.rs", - "sha256": "dd5c06c25f6404e2647e8132e038cefd78fd1f239dda2149a3d8cd58a5522d38" + "sha256": "e897303e906ad3eab43badd52a60142ee1350a6f53e8e7ad8b2e505ac88240fe" }, { "path": "xtask/src/mcp_session_contract.rs", @@ -381,12 +381,16 @@ }, { "path": "xtask/src/release.rs", - "sha256": "46b7f15530d8cda42636f585381f00c9e952d0d4048a0e536e7fa23f0a0f659e" + "sha256": "99c02765423b941effcd818c1fbd216b0a843d34762ef65e2585f6d5537b7e05" }, { "path": "xtask/src/release_control.rs", "sha256": "6027e030cd2db03818a23d816e3011f2b504c18599d100322d994387207db090" }, + { + "path": "xtask/src/release_launch.rs", + "sha256": "52441d8220e9318b591abd4d39494d7df367351f613bb33603ee3ba0c68781ce" + }, { "path": "xtask/src/sdk_experience.rs", "sha256": "ab58c932bf68bf48273ccd28811a10fb09d9705268d9d257221bb4c194c4d517" From 4f26b325ed828ca1839eb9bdc9df91ebd6a34f77 Mon Sep 17 00:00:00 2001 From: bordumb Date: Tue, 6 Oct 2026 21:09:55 +0100 Subject: [PATCH 030/108] fix(release): bind the launch projection into the final manifest --- xtask/src/release_control.rs | 1 + xtask/src/release_launch.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/xtask/src/release_control.rs b/xtask/src/release_control.rs index 4d474d28b..240377712 100644 --- a/xtask/src/release_control.rs +++ b/xtask/src/release_control.rs @@ -178,6 +178,7 @@ fn finalize_preparation( "conformance": [ digest_reference("target/release-evidence/platform.json")?, digest_reference("target/compliance/report.json")?, + digest_reference("target/release-evidence/launch-readiness.json")?, ], "benchmarks": [ digest_reference("demos/benchmarks/profiles/release.toml")?, diff --git a/xtask/src/release_launch.rs b/xtask/src/release_launch.rs index 94e750f2b..f1a5053b6 100644 --- a/xtask/src/release_launch.rs +++ b/xtask/src/release_launch.rs @@ -175,6 +175,7 @@ pub(crate) fn projection(repository: &Path, commit: &str) -> Result Date: Tue, 6 Oct 2026 21:22:43 +0100 Subject: [PATCH 031/108] fix(release): require and revalidate the computed launch projection --- architecture/dependency-graph.dot | 2 + architecture/dependency-graph.json | 24 ++++++ .../qualification/aeneas/source-closure.json | 10 +-- .../auths-gateway/semantic-closure.json | 2 +- .../auths-gateway/src/semantic_closure.rs | 2 +- .../release-manifest.contract-fixture.json | 4 + release/release-manifest.schema.json | 11 ++- release/semantic-freeze-versions.toml | 8 +- release/semantic-freeze.json | 15 ++-- xtask/src/release.rs | 31 +++++++- xtask/src/release_control.rs | 3 +- xtask/src/release_launch.rs | 75 +++++++++++++++++++ xtask/src/semantic_freeze.rs | 1 + 13 files changed, 167 insertions(+), 21 deletions(-) diff --git a/architecture/dependency-graph.dot b/architecture/dependency-graph.dot index b866cf197..0ff3ff544 100644 --- a/architecture/dependency-graph.dot +++ b/architecture/dependency-graph.dot @@ -763,6 +763,7 @@ digraph auths_architecture { "xtask" -> "auths-did-key" [label="normal"]; "xtask" -> "auths-did-web" [label="normal"]; "xtask" -> "auths-errors" [label="normal"]; + "xtask" -> "auths-gateway" [label="normal"]; "xtask" -> "auths-github" [label="normal"]; "xtask" -> "auths-hsm-attested" [label="normal"]; "xtask" -> "auths-kubernetes" [label="normal"]; @@ -777,6 +778,7 @@ digraph auths_architecture { "xtask" -> "auths-radicle" [label="normal"]; "xtask" -> "auths-raw-key" [label="normal"]; "xtask" -> "auths-receipts" [label="normal"]; + "xtask" -> "auths-recipe-qualification" [label="normal"]; "xtask" -> "auths-records-api" [label="normal"]; "xtask" -> "auths-registries" [label="normal"]; "xtask" -> "auths-signature" [label="normal"]; diff --git a/architecture/dependency-graph.json b/architecture/dependency-graph.json index 3dfcf370d..6ee389cb2 100644 --- a/architecture/dependency-graph.json +++ b/architecture/dependency-graph.json @@ -16991,6 +16991,18 @@ "std" ] }, + { + "source": "xtask", + "source_layer": "tooling", + "target": "auths-gateway", + "target_layer": "product", + "scope": "internal", + "kind": "normal", + "target_condition": null, + "optional": false, + "default_features": true, + "features": [] + }, { "source": "xtask", "source_layer": "tooling", @@ -17169,6 +17181,18 @@ "default_features": true, "features": [] }, + { + "source": "xtask", + "source_layer": "tooling", + "target": "auths-recipe-qualification", + "target_layer": "product", + "scope": "internal", + "kind": "normal", + "target_condition": null, + "optional": false, + "default_features": true, + "features": [] + }, { "source": "xtask", "source_layer": "tooling", diff --git a/formal/qualification/aeneas/source-closure.json b/formal/qualification/aeneas/source-closure.json index 58a2c5483..57aeafb20 100644 --- a/formal/qualification/aeneas/source-closure.json +++ b/formal/qualification/aeneas/source-closure.json @@ -1,6 +1,6 @@ { "schema": "auths-proof-translation-source-closure/v2", - "digest": "4a475e2a52afaf2fd47cd8bc6426750db2b65ee6cac4acb892f13b69699d12d9", + "digest": "df1985f8750732aa8896f5d25e48387f42281b05da244bc1d3b3c22ad3599fba", "files": [ { "path": ".cargo/config.toml", @@ -381,15 +381,15 @@ }, { "path": "xtask/src/release.rs", - "sha256": "99c02765423b941effcd818c1fbd216b0a843d34762ef65e2585f6d5537b7e05" + "sha256": "777158590253b03652d94d988ad7a96b5a750481e4f2eaf5f1e0edc6d48f2e8f" }, { "path": "xtask/src/release_control.rs", - "sha256": "6027e030cd2db03818a23d816e3011f2b504c18599d100322d994387207db090" + "sha256": "0e3727745909381939280674d53309c0ef3d7c52dc58add091f860ba79ab2893" }, { "path": "xtask/src/release_launch.rs", - "sha256": "52441d8220e9318b591abd4d39494d7df367351f613bb33603ee3ba0c68781ce" + "sha256": "1ace0de9a642e0e408997ce52c8244b628b2fb340b4cb354d9ffcddd44f357ce" }, { "path": "xtask/src/sdk_experience.rs", @@ -401,7 +401,7 @@ }, { "path": "xtask/src/semantic_freeze.rs", - "sha256": "3227a3dc0a2edc827e2408545063f142b3f89bb7277799fb6a9608669729d5f6" + "sha256": "52b36fa91c618677addf4d8ba157783b119b6a64e797047112f0e652281e846a" }, { "path": "xtask/src/stripe.rs", diff --git a/product/runtime/auths-gateway/semantic-closure.json b/product/runtime/auths-gateway/semantic-closure.json index 560b8240e..4b833f367 100644 --- a/product/runtime/auths-gateway/semantic-closure.json +++ b/product/runtime/auths-gateway/semantic-closure.json @@ -1 +1 @@ -{"files":[{"path":"Cargo.lock","sha256":"c94ed342774d5e2823f01ecf74b8a4812c5f9a6b0cf811d31f2e2cecb671a275"},{"path":"Cargo.toml","sha256":"6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24"},{"path":"core/adapters/auths-did-keri/Cargo.toml","sha256":"86ba3e3f9a0a70d970568bfb3113b7ba7bbdd81c3eebbb52743dd574a0c0ecaa"},{"path":"core/adapters/auths-did-keri/src/lib.rs","sha256":"a75674842f8a7142004369ccd206ab43e476459293f0ff4bed4d4e659031b3e3"},{"path":"core/adapters/auths-did-key/Cargo.toml","sha256":"d5a3ae07ecde83f91eed4c3785051dd0f44eab6c891754f3309b6b40596707d7"},{"path":"core/adapters/auths-did-key/src/lib.rs","sha256":"b76a3f4528a725df53cfa9242e6e414e1d26caa48468aaed497e28b121f4497c"},{"path":"core/adapters/auths-raw-key/Cargo.toml","sha256":"f49616bc18c19e6aaa7e6a02ccebcdb9f5c1422c1278ef9869e0dbf22ceda7be"},{"path":"core/adapters/auths-raw-key/src/lib.rs","sha256":"45eec1b295dac3bed65cd79c942870b926b06b3f5d38eaebaeb6140ac69315fa"},{"path":"core/crates/auths-algebra-kernel/Cargo.toml","sha256":"0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba"},{"path":"core/crates/auths-algebra-kernel/src/generated.rs","sha256":"ae4bcbef42a408c7ffa0c6a74a42f7de177a6f14479e51d205acf830bda05960"},{"path":"core/crates/auths-algebra-kernel/src/lib.rs","sha256":"6654667eeb9b353d6648954c9fd2e8838462a82ce6b2803eb49e1366892c68c6"},{"path":"core/crates/auths-assurance/Cargo.toml","sha256":"afcb12a97ddd09d7a264b9ecd3fcaefc865ff2c9b4539ee85b00883420ba333a"},{"path":"core/crates/auths-assurance/src/lib.rs","sha256":"0fb2ec844d674b25a9e20b1601452c89c2454901fa506adfa9bb38ef9a7fa213"},{"path":"core/crates/auths-author/Cargo.toml","sha256":"1e6f0e3bc079ddb558decf0db26b291c6e72fc47327b6df1b7650d41689b215f"},{"path":"core/crates/auths-author/src/lib.rs","sha256":"e14475f2f49715a1869d5fa6b11ff1fbb72497e39097e09f833b0bae7e5b3f2b"},{"path":"core/crates/auths-author/src/observations.rs","sha256":"dda7d6bfa6f4bd7e95a480ca283c2c0e996f69c5c15cb0c7197af328131a7066"},{"path":"core/crates/auths-authority/Cargo.toml","sha256":"4f68212938029f79ebd857b4f3038494eb85d0163d49f07e51376715cf959815"},{"path":"core/crates/auths-authority/src/lib.rs","sha256":"da88d5194de4e17449e69972c0fb042afa3c39798a8f570f30771e77c384f1eb"},{"path":"core/crates/auths-codec/Cargo.toml","sha256":"e20e51826e17814effd9d8925d18d5fbdd6c0d37bf50231e743ec2611314722c"},{"path":"core/crates/auths-codec/src/approval.rs","sha256":"fbff43bf4d57f69f8b7738a8647751cde75c5a932dee65d924a1fe9c7202f91f"},{"path":"core/crates/auths-codec/src/bounded_policy.rs","sha256":"d21f6728be2d8a04b6d94921f2b683f7e61cbb42e0ac6866f1c88a49caa534c3"},{"path":"core/crates/auths-codec/src/decode.rs","sha256":"ba2999584cdf53b1b517ecb9c7ea50d39efee17c666a9a38e2ad1ac94379f778"},{"path":"core/crates/auths-codec/src/encode.rs","sha256":"8491192053e2e15d62b4d2a491de22405b7487ead69ab6f6bca40669ce7ca5f7"},{"path":"core/crates/auths-codec/src/error.rs","sha256":"fecb0737c16deb42d859f1dc7727c698438d9ac12064fd99e0024629642c390c"},{"path":"core/crates/auths-codec/src/hash.rs","sha256":"f88e111f1dbb2cef6b7b5e9c948cb45ff92e366710c8a5f5c636138aa748479e"},{"path":"core/crates/auths-codec/src/lib.rs","sha256":"3b0e5c94c6f34f750b88a9333e1d5c8145746d845d3a23e0d2f61807cf592ea7"},{"path":"core/crates/auths-codec/src/observation.rs","sha256":"38328b0c71ff97a4196eeade8b4faa889527ff1f80bb168468bcd49082a3987e"},{"path":"core/crates/auths-composition/Cargo.toml","sha256":"331e13025eb82588b5269ed3975929eb41c823d588c49e4c296273d85c6fe80e"},{"path":"core/crates/auths-composition/src/lib.rs","sha256":"e42e3b0b6a9985b73c533aeb23799c638979aa27a9ce7d0f10a8d60340570fb1"},{"path":"core/crates/auths-model/Cargo.toml","sha256":"565c15302b0cc9270db1e28efa3862804846850ba933cc17aea8abcec4a65987"},{"path":"core/crates/auths-model/src/approval.rs","sha256":"54cf44a9ef747ec21546a4086aecfb130bc7803b0d646430e6082df51e6e305f"},{"path":"core/crates/auths-model/src/bounded.rs","sha256":"f90496abc0a06c028b4d850af6ddab7d850bfafeaa3d042f1b1246a41d8bbbc9"},{"path":"core/crates/auths-model/src/bounded_policy.rs","sha256":"306a8f049cc7cfc7635fe0e4de47eb7813eed63d3c14c3be2b51586aa4eea450"},{"path":"core/crates/auths-model/src/lib.rs","sha256":"e7cfe6bb9574c6b016aa63e70658c31e0b90903ec6479a49f4a2ceb64f5bad97"},{"path":"core/crates/auths-model/src/observation.rs","sha256":"b3ed3e3cc090afca2896a7d3de7988afccc1ee1ea0ebd91b51a8bc0f20ad8dbb"},{"path":"core/crates/auths-multikey/Cargo.toml","sha256":"858756c1197befcada06134742bffe8d58cf674cadd6c046bf710570e96efaf2"},{"path":"core/crates/auths-multikey/src/lib.rs","sha256":"f5177fffb11e40eeaaa665ba886c541fc1f24d5eacdd6983fb03dc20148733f0"},{"path":"core/crates/auths-ports/Cargo.toml","sha256":"596a9b0f5af3717c16a6d13f7054d8a106bcd9f01f5f72c2235dd2afcf0ab16c"},{"path":"core/crates/auths-ports/src/binding.rs","sha256":"a16c012d40aa4249e3ec54372b9611006d0bfe8c7dc3c741911c2194ad17736d"},{"path":"core/crates/auths-ports/src/diagnostics.rs","sha256":"aa596572503b5a65a918bb2ff38281c144ff53821ee914e9325c852828d852df"},{"path":"core/crates/auths-ports/src/lib.rs","sha256":"8da1debf86f9532df0660155d04298beb1ba3a1204508f8586e2e67cd2fb3449"},{"path":"core/crates/auths-ports/src/path.rs","sha256":"b68fc547b4e4d97a60cbbc1cc1939fc6b34a8233b81f840bd396914a707e3ea1"},{"path":"core/crates/auths-raw-key-core/Cargo.toml","sha256":"98c0bc8527a537512e43a74dd6ba9658c6f0cdc16610cf938e3f9b43785d836d"},{"path":"core/crates/auths-raw-key-core/src/lib.rs","sha256":"98c0500c41697aae28708ad0bf970b9a97583d96a3d2c18d23e7fa351e0f7d12"},{"path":"core/crates/auths-registries/Cargo.toml","sha256":"590e49e58b0622d9d6274fea46796dcdb07dec9550eff295cce6a6427ffa51e2"},{"path":"core/crates/auths-registries/src/lib.rs","sha256":"450d3886d85ee333b7e046317fb5b47cde62483d5f3e41d46265e2caf4c373ec"},{"path":"core/crates/auths-registries/src/template.rs","sha256":"1224039dd2b3ce6fa8357613d8cafbae40400493da7176da202b9ade62fa05e4"},{"path":"core/crates/auths-signature-core/Cargo.toml","sha256":"6bee2230eb30af1be0bd5c2d57bd3e1903497a70028d47290d4ac6e9e0e8bca0"},{"path":"core/crates/auths-signature-core/src/lib.rs","sha256":"6e3f9311ded5e49ea50d445eb21e6d8fa12442aa4362a73e0cb6fda15b7cd865"},{"path":"core/crates/auths-signature/Cargo.toml","sha256":"7f7b5682466ba439d8c59579022cb61068cad9fb4bd2d73e1cc21327c902b450"},{"path":"core/crates/auths-signature/src/lib.rs","sha256":"b3d9ac4cc3ba0797b9e1c09f2d6ac05089b25dac4e285a5af28c0165b33d925b"},{"path":"core/crates/auths-verifier/Cargo.toml","sha256":"c43358e06a33324b41a8b93e5cc7279c55f7d21f1f6cfaa539a3fc7b4c27a38f"},{"path":"core/crates/auths-verifier/src/approval.rs","sha256":"c3cae6a49e169051eb555bb092b1069a4d422516d6a2114623a89e5f31ff923f"},{"path":"core/crates/auths-verifier/src/causal.rs","sha256":"9635230f33b13a263573d319ac8a1976addbcc07677514a43e3c7bf28dc04587"},{"path":"core/crates/auths-verifier/src/lib.rs","sha256":"f22dec38dfa47ced8da4f605390da8453273bee1da010f57fd1fdfcb10e0b389"},{"path":"core/crates/auths-verifier/src/observation.rs","sha256":"0bb07f06a0f9524c88427df1c972b1de8ba038a9eeeb15d3134c25125ae84b1e"},{"path":"core/crates/auths-verifier/src/trace.rs","sha256":"2213d72023a1d9e0413a2cf2c51c3dad9e04775d86033a0caaa9d29a8f0036f8"},{"path":"exchange/crates/auths-proof-exchange-model/Cargo.toml","sha256":"34b2db64f93a288e942b5a3918d28cdcbef906e0dc9074ce848018d3d5f7a1fa"},{"path":"exchange/crates/auths-proof-exchange-model/src/lib.rs","sha256":"49fac5aff2339d3a57c41cb8bb2a82852538e8f77ecc4b157c88e264ff31fb55"},{"path":"exchange/crates/auths-proof-exchange-port/Cargo.toml","sha256":"7ff660f1b7579dc570c791090aeb450404fbbf44c92781e289f5ccdde746d739"},{"path":"exchange/crates/auths-proof-exchange-port/src/lib.rs","sha256":"b408fb40c6432edc1facb3d8b3e9433a033f8dc73fe2e0ba5a88c972ca675021"},{"path":"product/config/auths-config/Cargo.toml","sha256":"e4b568ab9f6d84f7d7e6d66443fe825f360db9c27bc7c31d6ddc0647ba3ab304"},{"path":"product/config/auths-config/src/lib.rs","sha256":"fecf00ea65cef9018fda9af2063326d7065b869266d0d9e73a4f06816f1102cc"},{"path":"product/errors/auths-errors/Cargo.toml","sha256":"3b3a199b6460ba75bda84475bb5accd35e1485448a3981038db85bf4772dd350"},{"path":"product/errors/auths-errors/src/lib.rs","sha256":"7feeb9069fa4003f94f1f07c1c94619cf1c883e0dbaaf2187f04d0f742264bdd"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/Cargo.toml","sha256":"716f1f2a117d6d69d8effe9ee9057e24ba3502f20af6a602b06facb638cdabed"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/api.rs","sha256":"9ea61dd7ddd93282b073b98e453e6b75b26dc49689c04e9782435d06a3a09e48"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/clock.rs","sha256":"73f0a6e0f5903883329fa6683f5888288f759512ac69e5c87efd2b6b87f7d79f"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/http.rs","sha256":"14c1fce14e24c984b2a275563a29b6326fb08367922b6e8d37ba38b9cb81aa2b"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/identity.rs","sha256":"186de11230c8b33375951c4368609f8976bf9795f171af3fd7fac26207a94361"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs","sha256":"0b4617d044f5254a5ab22f5a2578f91cc025206a8c1845be39c1c56dcdf7a5df"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/names.rs","sha256":"41bb23572d6002e23ee103d6fe70ecd68764861c6f2e48a1c53af998270a4afa"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs","sha256":"39fed883f4802e68d3b41a68fea0aba0737810996b33d13577de70faba004c29"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/store.rs","sha256":"fc60ee9c49b2f4f063c449b4c78100c5c4872779e94ca168f796603b380ef6e4"},{"path":"product/integrations/auths-custody/Cargo.toml","sha256":"1e14034185ad1ec24a977fd5f41d0abee219606245c046ce2a82287fadef448b"},{"path":"product/integrations/auths-custody/src/conformance.rs","sha256":"8ed1afd58f18fc6becc268908aa6419c9aa404c79da0197963eb2599df44acf6"},{"path":"product/integrations/auths-custody/src/key.rs","sha256":"70cbb0fd21b6f5652157845a22c35be2d0f6c05b3d138fc4b9bb6dbdc3d81c40"},{"path":"product/integrations/auths-custody/src/lib.rs","sha256":"8ee593c1f59b0fd2126bdda9138026f5bc531beb64d4489a99785842e7b98b43"},{"path":"product/operations/auths-operations/Cargo.toml","sha256":"73dde1e914ba5e1386f8d49c0d730423cc72ae77ec44c6554a6a75cc8e8922b1"},{"path":"product/operations/auths-operations/src/explanation.rs","sha256":"b4a39bcbd5712cb9e735ee7deeb281f3fa6af5ddca973735bf3d87dce427ef11"},{"path":"product/operations/auths-operations/src/lib.rs","sha256":"3f401a56555113b98f57bca172a2660eaecedf76247b83a3fdbb089c133a29cd"},{"path":"product/operations/auths-operations/src/render/json.rs","sha256":"2ae042639960afee123730e945d373bc5dda1d2b3af20ae16c939a7e99b9e418"},{"path":"product/operations/auths-operations/src/render/mod.rs","sha256":"b3b7f6fe473f49227ace5a68bfc3d8dc14b5db8dd9888fd9e207070337b1b8bf"},{"path":"product/operations/auths-operations/src/render/text.rs","sha256":"f216cf3bdb00e264523271b16e7059535ac6b1aabf271cebd7935af155e4bfec"},{"path":"product/policy/auths-bounded-policy/Cargo.toml","sha256":"babd5d200923137ead71d8c2528f847cea323ce98da942a1320b054436612c47"},{"path":"product/policy/auths-bounded-policy/src/arithmetic.rs","sha256":"75e43c5d4eab8d1f71c1daf53839f5f9fe45a400afc1f63a30c6f55ce3632627"},{"path":"product/policy/auths-bounded-policy/src/commitment.rs","sha256":"c5706f2d583454e1a7f570f7ada138d4d864bef0205dfae7c1296774f396bb3f"},{"path":"product/policy/auths-bounded-policy/src/eligibility.rs","sha256":"c9acdfb793074e687fc36efad506be27dbd99ffbf40387bc66c8de39ef238432"},{"path":"product/policy/auths-bounded-policy/src/identifier.rs","sha256":"0006a32bae9eb16c4178cf797df418d2b0a781f2bc6474b741dc1a908141831c"},{"path":"product/policy/auths-bounded-policy/src/kernel.rs","sha256":"99187c28b161ac70bee1afed60711f7f645adb4d1671a01863f9849b369811d5"},{"path":"product/policy/auths-bounded-policy/src/lib.rs","sha256":"76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c"},{"path":"product/policy/auths-bounded-policy/src/receipt.rs","sha256":"3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad"},{"path":"product/policy/auths-bounded-policy/src/registry.rs","sha256":"4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0"},{"path":"product/profiles/auths-profile-api/Cargo.toml","sha256":"7ae85761f58625b5d678f961fd052eebf3e000ef565c7312e3ac857763c0017f"},{"path":"product/profiles/auths-profile-api/src/lib.rs","sha256":"a194b82b20bf8aa864c2334ef6c6aec30b2154ded972862252d5dcefa488ab95"},{"path":"product/profiles/auths-profile-mcp/Cargo.toml","sha256":"db264fc25242f7b7e4133cbe5782545b3107b406c87168ae072683cfb59eac66"},{"path":"product/profiles/auths-profile-mcp/src/arguments.rs","sha256":"a5de696586d507e2aee4a49fee99ef1ef4c51a2e46603f8838f1af6d9009833f"},{"path":"product/profiles/auths-profile-mcp/src/lib.rs","sha256":"d0f8b733a09ef8408336cdebc8948d6a5861012ce6878598b11be7084dfd4280"},{"path":"product/profiles/auths-profile-mcp/src/session.rs","sha256":"166c281fa66333388e4760d6098dad02d3359e1d5de4b8f93312c014f97abb03"},{"path":"product/qualification/auths-recipe-qualification/Cargo.toml","sha256":"b7b15b30b9a3d96d4f089d514266d3a892de6608d30707aa44be31cca89ca9fe"},{"path":"product/qualification/auths-recipe-qualification/src/canonical.rs","sha256":"30a9b50777f0dcb4b606abfee2467d5a975d9f6ad941ab6c13ca3df5b359f667"},{"path":"product/qualification/auths-recipe-qualification/src/closure.rs","sha256":"0ad6aee9bd981e2863fa725f209ec84031db2ff12f4c7ac3aaf5120f0bb86039"},{"path":"product/qualification/auths-recipe-qualification/src/error.rs","sha256":"52d5cf720a1e4579008fdda90a3ac2c31f0b8db57985f121f65e54b4da2b7dd1"},{"path":"product/qualification/auths-recipe-qualification/src/evidence.rs","sha256":"1a4cb862f725b02f9efd827db99637ea8178a5236aa020ec271a363edbe7b362"},{"path":"product/qualification/auths-recipe-qualification/src/ids.rs","sha256":"e81a906d571497ab2da753e1532d4443706410e0b75fdd59a7d2d788c7aec403"},{"path":"product/qualification/auths-recipe-qualification/src/lib.rs","sha256":"195b19f46e1e94a0f3594ad5958e5715bc5e3ad415bdfe6428dfc1b6dd3f4631"},{"path":"product/qualification/auths-recipe-qualification/src/model.rs","sha256":"3484eb0ec287b23d4682ade7b1b0f8d1335985b3fb180f06fc28716076957d5f"},{"path":"product/qualification/auths-recipe-qualification/src/release.rs","sha256":"d816b53e2275e902c750ad03803061844e259e28560ab2d1c77e8a43981a4d6a"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/mod.rs","sha256":"7f15b68e05a04f202bcb1fb80de1d9a9a4fda8bfd6af2cd4e5c660fc75d96fe5"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/schemas.rs","sha256":"c59feec2805621f341a90f81fc005e2c12f7a70f9d264fdeacccb2be4fe1c046"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/verification.rs","sha256":"6a6b5834c5dae10af1ba8939b2deae43b85db71544dc8f077ff63b7fe68ac8a8"},{"path":"product/qualification/auths-recipe-qualification/src/verify.rs","sha256":"edd33589c54fb79bcfccc4cf4e6ccf95bbca088318bb7f8dfc27da684b4fa671"},{"path":"product/receipts/auths-receipts/Cargo.toml","sha256":"6001fa1375899953aafcb07c23a6da0c8f57ea7ec08bb9c950b12a60a8cc6f0f"},{"path":"product/receipts/auths-receipts/src/disclosure.rs","sha256":"ba9ed439be0a320c8a01f5b6e9b51361c1a37e076947490d8e4a484ba6bb119c"},{"path":"product/receipts/auths-receipts/src/lib.rs","sha256":"547a57c4160256719cafb7d0ab972d9fc80b0da14fbbce4148c70c414070ff36"},{"path":"product/runtime/auths-connections/Cargo.toml","sha256":"babeb6e1dda3dfb66291713ce1e43dce5c349833d0b50ea4dccbf986030026b2"},{"path":"product/runtime/auths-connections/src/credential.rs","sha256":"82921413bb053f0f6c7931fbd4e6a86c8cc1d8c6b51debd9c2cef33a8d5b1c51"},{"path":"product/runtime/auths-connections/src/kernel.rs","sha256":"a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8"},{"path":"product/runtime/auths-connections/src/lib.rs","sha256":"79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22"},{"path":"product/runtime/auths-connections/src/model.rs","sha256":"de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77"},{"path":"product/runtime/auths-connections/src/registry.rs","sha256":"e57640e003e72ad3235c567c2bb944a262bd64e673f023b62ea091094cc7e946"},{"path":"product/runtime/auths-gateway-kernel/Cargo.toml","sha256":"34f864e67656af4ac7e5c7a347a23f01fc8ab31365b8e23c0ef474483b14a183"},{"path":"product/runtime/auths-gateway-kernel/src/construct.rs","sha256":"e9d65744bae273d65face4285e5d2da75c06a92ab48f7b8333d496604e31c63c"},{"path":"product/runtime/auths-gateway-kernel/src/lib.rs","sha256":"cfda6f8453426564c085475f183b6f790b438768a19668f1b65d33ba59dc8632"},{"path":"product/runtime/auths-gateway-kernel/src/order.rs","sha256":"e0045f877c4b7fe3860c291039853885064ddcdebba7c9b345ab65e81e646dda"},{"path":"product/runtime/auths-gateway-kernel/src/outcome.rs","sha256":"e9785b1afe70788c89b51b18655bcd5acff7b0c8e3d12fb79c6f05a202e67e6b"},{"path":"product/runtime/auths-gateway-kernel/src/ratio.rs","sha256":"7ace22264812e6fc1ef3a62afee402cf43494bb71ae0d3de219ad1b39d690bcb"},{"path":"product/runtime/auths-gateway-kernel/src/recovery.rs","sha256":"9f46dcd1685ab6e4d1ba04a3fc286a9f3afee8fb47829be1fbc670a7926a2dc6"},{"path":"product/runtime/auths-gateway-kernel/src/transition.rs","sha256":"cefb8f01d915880f6921f2501ff881ad94b9de61072c34d9cd19220992f97374"},{"path":"product/runtime/auths-gateway/Cargo.toml","sha256":"00b28be86921dcdc0ad90cce0c62c2961cafefe96ea6c2edf0e926c3d405ccad"},{"path":"product/runtime/auths-gateway/src/admin.rs","sha256":"2d5cc67afac42fbd15f36e2d1693cd1b20cedacf775040dce6ffe04ccc94c9ea"},{"path":"product/runtime/auths-gateway/src/app.rs","sha256":"6f80f63833ea0815bb44fbf3b0cc54624a08e9fb578b035819f2980dc04e8256"},{"path":"product/runtime/auths-gateway/src/audit.rs","sha256":"0edb2037eb7b5d6f13acfce85c54f62a82bf7fdd31bc7e626c4fec183cef61dd"},{"path":"product/runtime/auths-gateway/src/audit_tests.rs","sha256":"990969384a52d75bc2489d9d412a9e7dd814bca1c8f65c701d6205fae62a15d5"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway-harness.rs","sha256":"12b0c24d36b2e6a3be392d3c081a783b355fdd67dc5b54bacc0410e803116b8c"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway.rs","sha256":"8851f5e95b70540f64c1965f6f240e7d90968817c6396d59cda49a75e46f85fc"},{"path":"product/runtime/auths-gateway/src/binding.rs","sha256":"663b0ce878319511aa7d05722ab4ab2fa9be18817884ffb2ee9f131ff1e382d1"},{"path":"product/runtime/auths-gateway/src/bounds.rs","sha256":"9cfa0eae4973e5e047a198360b22f041708fa20276b0b90c2ec440f06915d64b"},{"path":"product/runtime/auths-gateway/src/bounds_aggregate_tests.rs","sha256":"ab34f227b7c8692ba1da88ccb32bb3687a66adf8353d8282fae905d4a88eb612"},{"path":"product/runtime/auths-gateway/src/bounds_tests.rs","sha256":"74136bc570da7b9338b5a1a1ed9d3fd892c55135160964f9d3ac0e2cf5741375"},{"path":"product/runtime/auths-gateway/src/connection.rs","sha256":"7b5d049c258a26ed1c93ecf860f51d051a8a65f9b93554af0b1ea93862398ec9"},{"path":"product/runtime/auths-gateway/src/credential_journal.rs","sha256":"7297fccaee5cd8622928e8e0a42bba50da7941970a6f682ecd300c41ee6509da"},{"path":"product/runtime/auths-gateway/src/echo_verify.rs","sha256":"6d453051665f823abd7354d5c50031d9524cf47d6092d2f09080ae814e3b9575"},{"path":"product/runtime/auths-gateway/src/engine.rs","sha256":"f1052aaef43e441b9e0befa3f8ad1e2fd5279a27cb9d63aac0cf9dfdbe85a052"},{"path":"product/runtime/auths-gateway/src/fuzzing.rs","sha256":"ed3b0028487eb546a3b0a91d115aa8f18bcea324b61620bfe8e35a9e6ab18758"},{"path":"product/runtime/auths-gateway/src/generation_floor.rs","sha256":"fe1510ec96ce0f67e9a78edbfa94b33eb7df64c0ac4d0a67901124dcd0164777"},{"path":"product/runtime/auths-gateway/src/harness.rs","sha256":"c87e479f3eb281960f6c9c80d43c7560d7ccb654b0154ec823d3fcec4884ac05"},{"path":"product/runtime/auths-gateway/src/lib.rs","sha256":"b182052835a2cd631d1f801a74788d6ac1ef9cae21ade9ab4ffc270cd6f667ed"},{"path":"product/runtime/auths-gateway/src/listener.rs","sha256":"aa08239bcbc1fcb55e8a212fbdf6a84f12985b0d436dcb51dc58b06e59e435f2"},{"path":"product/runtime/auths-gateway/src/observed_tests.rs","sha256":"a22be071695f89ca2578a4d82fd80d9cb82289213c9bdb8f0470f6b2dc3d9201"},{"path":"product/runtime/auths-gateway/src/observer.rs","sha256":"562ffcaea071c3856e0708dc2fe33516917e145d2438aabb75af0a2b6ba01046"},{"path":"product/runtime/auths-gateway/src/onboarding.rs","sha256":"0dfd7d67e7f02f18a28d1c86ca1b7751d7463f5efcdbe3825de0ad8cbccb3891"},{"path":"product/runtime/auths-gateway/src/operator.rs","sha256":"c3c36954a3e86723df035b47f43b85fc8ab3a6292983522b6258d5c6b4e6c4e4"},{"path":"product/runtime/auths-gateway/src/pending_vectors/attempts.rs","sha256":"47ef3c8cb1c5504d47ae9a0088705ce6715fe86bac1671a34a56fb38a64d0dd3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/bounds.rs","sha256":"e612217307e1da5b0eb5ee6582a7458bb064b8aa8a529fc6555b1b334127ab68"},{"path":"product/runtime/auths-gateway/src/pending_vectors/codes.rs","sha256":"e00670a5ef24eb856cc2c6dcda8e5a263842f55c76bb939c0c27bd9df37e5522"},{"path":"product/runtime/auths-gateway/src/pending_vectors/keys.rs","sha256":"f84c56f2ea9cb34b2b79c72d13fbf2c6585010ec1ed450af58a78c80c1ea1edd"},{"path":"product/runtime/auths-gateway/src/pending_vectors/mod.rs","sha256":"5de8340f0ef71a0b57a09e323fefe473d3160c6ae952b9ba46f714825fbacafc"},{"path":"product/runtime/auths-gateway/src/pending_vectors/outcomes.rs","sha256":"8ec07b9511b48913af36ac999d2aa0e82924289f6acb23ddaeb9f00f99815166"},{"path":"product/runtime/auths-gateway/src/pending_vectors/production.rs","sha256":"f574cabfa4687a4fc846b8f6a234b68ec53b876aed548b11445729cac1a55ede"},{"path":"product/runtime/auths-gateway/src/pending_vectors/recipes.rs","sha256":"51693208270231c25c3aef2a32151d5962114c71e86b88cb9df83181c7af83d9"},{"path":"product/runtime/auths-gateway/src/pre_entry.rs","sha256":"06ea78ca140468bfaba17d9ab04912ad68673954c3203c98fed28272ff2a00c0"},{"path":"product/runtime/auths-gateway/src/property_tests.rs","sha256":"939c081e2e154aaf10186754044bdd65608932c899b970a04a71d0afaa999a93"},{"path":"product/runtime/auths-gateway/src/qualification.rs","sha256":"d5078a81dc89f30958a7d8fdabfe164c3411c441dd7d9015002681a58883b63a"},{"path":"product/runtime/auths-gateway/src/qualification_tests.rs","sha256":"4473add5729b97faf04d7be7fd8cf3bbacd7f545e1b61c7d2782563011906b4d"},{"path":"product/runtime/auths-gateway/src/quorum_tests.rs","sha256":"a78380b019104d688c11a4410082c7e08ded3106aab099954c4f8a1b4ae0fd89"},{"path":"product/runtime/auths-gateway/src/readiness.rs","sha256":"911c3f11892f94641574375e2da4c671c802738f71082f12c39832331052d43d"},{"path":"product/runtime/auths-gateway/src/recipe.rs","sha256":"fecf9af67e7afc48d080e9f8f55f8ce28e49d0e08988717a27908bbda461d6b6"},{"path":"product/runtime/auths-gateway/src/recipe/lower.rs","sha256":"8088b8751ed831dbb48247af953c6290ac95e2a438ccd5bd65eff54be06a1fd1"},{"path":"product/runtime/auths-gateway/src/recipe/review.rs","sha256":"c3eb7d9fdd98dacf52750b14b67ad7b7faaecbbdeafff1e0b049f67d0a2d0139"},{"path":"product/runtime/auths-gateway/src/recipe/runtime.rs","sha256":"c286f0d15f974402822c0810d8e97f98411dc1c557755cc23e540d85e2bb42d9"},{"path":"product/runtime/auths-gateway/src/recipe/source.rs","sha256":"1af50298fb1461e1b24cbdf560d43124d6b1c4c529586c911b1c4797214a69ff"},{"path":"product/runtime/auths-gateway/src/recipe/tests.rs","sha256":"aac551a2481bbc60864c64079bc667dcb232e45a0f41a04073ed84ab5dbe1fce"},{"path":"product/runtime/auths-gateway/src/recipe/validate.rs","sha256":"3711b17605cb7b0d639bc1b180449231f5882a306cab20e2c7782155cc63b0d4"},{"path":"product/runtime/auths-gateway/src/scenario_tests.rs","sha256":"d8271761b12597bfe1233f8eb5ad1d4e5498c5d03388e832e24ab818484a1de4"},{"path":"product/runtime/auths-gateway/src/separation.rs","sha256":"be9306848ca5d801767cf6aa14247c8618312ef0e202f00ce0c24c4844491061"},{"path":"product/runtime/auths-gateway/src/store.rs","sha256":"1e5288345c2cb1421aeda277b3158d07607404b0ec46943222ac107b63dcbb46"},{"path":"product/runtime/auths-gateway/src/store_testkit.rs","sha256":"88d82fee42f1b8ef521e8deef0216e938ebeaad822eb2f5020e70b89d145ea70"},{"path":"product/runtime/auths-gateway/src/submit.rs","sha256":"c78dbbba7c45b443febf655056c5edcd635e77be7b21c5b2c318097502415ffe"},{"path":"product/runtime/auths-gateway/src/support.rs","sha256":"9fd979029793a22b15d9776a7fc172476fd7c126a80d4080c65d720845becbcb"},{"path":"product/runtime/auths-gateway/src/transport.rs","sha256":"be2c6dc75b8daec110bf8749fedc3823f6067d40b999aa3eb21126896a97d3ad"},{"path":"product/runtime/auths-kernel-runtime/Cargo.toml","sha256":"926bcd0053e5edd703be8f0027ad009e2982db013c8174c1366edbf38b48087d"},{"path":"product/runtime/auths-kernel-runtime/src/lib.rs","sha256":"7108faae9ca4bc32dc093ddaf885ac8f74f3c9b8d317b7c7d0ed00d1d0ab5972"},{"path":"product/runtime/auths-lifecycle/Cargo.toml","sha256":"c5053c705f8d5554b44e432fe75287a2faf11d644e5a2552e45ad6cd94176af5"},{"path":"product/runtime/auths-lifecycle/src/codec.rs","sha256":"51c4b746749150e8bfcd8ff972b3f6c1ef40bec15583448ec1b471d9ad737dc0"},{"path":"product/runtime/auths-lifecycle/src/digest.rs","sha256":"55282cd7d8aba37713c2dcb5357c9877819edb72a30eadefb860d28d7d3a3eb7"},{"path":"product/runtime/auths-lifecycle/src/identifier.rs","sha256":"31620e8c16de68d3d2d3b84d6353c1a5b9d4151d8247f91fa389b906a8e660f1"},{"path":"product/runtime/auths-lifecycle/src/kernel.rs","sha256":"2abb8c094b36d35b364e74d78091d14c5d6f3d1eb6552cca3b5538dbd017ce23"},{"path":"product/runtime/auths-lifecycle/src/lib.rs","sha256":"afe5a345cd309b5a4f08ffba3170a6d7f16ff914892b3f2006d5208ed24ec736"},{"path":"product/runtime/auths-lifecycle/src/model.rs","sha256":"1af12bbeeeaa65ec02ddcebd7d2c8c92ec1e339fa40ae85b45ab9b01a722a4fa"},{"path":"product/runtime/auths-lifecycle/src/operation.rs","sha256":"78e6d05fcf5d7ea4f148032a3fa26fdfcab77eb346019effe927b08e0d64d732"},{"path":"product/runtime/auths-lifecycle/src/registry.rs","sha256":"53495fe6f7a77422593a41623e28716f1c140dcc1e00f87f6b0ffbfb93a5ef90"},{"path":"product/runtime/auths-lifecycle/src/sealed.rs","sha256":"2e0c03b5813c926c159598bb7890d1523825edbe57cd687d42a5dfb3374a0c19"},{"path":"product/runtime/auths-lifecycle/src/test_support.rs","sha256":"221d9a5c5ef8e1f9f8fd66927484eaf813571d0568470278ecd8fa08a5eec8cd"},{"path":"product/runtime/auths-lifecycle/src/transition.rs","sha256":"011805a28efdd541f44ccea54dd0e34a1e58f4004447ee58013703b4fb6b2822"},{"path":"product/runtime/auths-runtime/Cargo.toml","sha256":"dd29d80a8b4bb56c869f036a6c9998f6e6d1c0383ac5dc03fa42b24abe2a7ff7"},{"path":"product/runtime/auths-runtime/src/lib.rs","sha256":"132ca03d58c14905d3a822a4972f42a22a5ad33a45f2ba9ca44f3a57d810b4b0"},{"path":"product/runtime/auths-runtime/src/production.rs","sha256":"fd4eff4270c571c10fcff6cf27df28961ebf074de8a1a028f500fda1ca376820"},{"path":"product/sdk/auths-approval-quorum/Cargo.toml","sha256":"df904971fca87a24194c5816738a331588fe8f164acb5d70839a35dca5f57114"},{"path":"product/sdk/auths-approval-quorum/src/lib.rs","sha256":"72e4086088a1c0912e4e1a9e980f26a5c280bf5ab16ea39c9f0f58d5096ac2ce"},{"path":"product/sdk/auths-approval-quorum/src/remote.rs","sha256":"9fa029c7c63003adf260f8aec55160c545681c60c1bace0d934e7525862aac7b"},{"path":"product/sdk/auths-approval-quorum/src/remote_tests.rs","sha256":"8a09ce17cfee82a035a74edd535f3ebeb3db0e078784740d3997b17dbdb10197"},{"path":"product/sdk/auths-approval-quorum/src/tests.rs","sha256":"0acbf12be3e497dcc6c2d8f29c9af3b1a7ed8e11b75f6399570d4f217a785060"},{"path":"product/stores/auths-stores/Cargo.toml","sha256":"a32c4b76d17b264be5d40d24497ff237e1ed87822e8bab86229b3db93106dbe3"},{"path":"product/stores/auths-stores/src/gateway_attempt.rs","sha256":"185da8f4a220fba836d5b78a9311f03204681c43a3c53951008084d135bf4d21"},{"path":"product/stores/auths-stores/src/lib.rs","sha256":"e721262edf8a9ab5568ddc27639176312d4a366203b5f73e2d7c11fde2c554e9"},{"path":"product/stores/auths-stores/src/lifecycle.rs","sha256":"94f64d25bc178a9e60ba3c0ee6915d7fb3af7c4468792d76b4e70f43f4de1e2f"}],"schema":"auths.gateway-semantic-closure/1"} \ No newline at end of file +{"files":[{"path":"Cargo.lock","sha256":"0e75e2fdef44e79e57797ac6661295ae58ddb8de4a1990a6fd22ce6c54f78604"},{"path":"Cargo.toml","sha256":"6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24"},{"path":"core/adapters/auths-did-keri/Cargo.toml","sha256":"86ba3e3f9a0a70d970568bfb3113b7ba7bbdd81c3eebbb52743dd574a0c0ecaa"},{"path":"core/adapters/auths-did-keri/src/lib.rs","sha256":"a75674842f8a7142004369ccd206ab43e476459293f0ff4bed4d4e659031b3e3"},{"path":"core/adapters/auths-did-key/Cargo.toml","sha256":"d5a3ae07ecde83f91eed4c3785051dd0f44eab6c891754f3309b6b40596707d7"},{"path":"core/adapters/auths-did-key/src/lib.rs","sha256":"b76a3f4528a725df53cfa9242e6e414e1d26caa48468aaed497e28b121f4497c"},{"path":"core/adapters/auths-raw-key/Cargo.toml","sha256":"f49616bc18c19e6aaa7e6a02ccebcdb9f5c1422c1278ef9869e0dbf22ceda7be"},{"path":"core/adapters/auths-raw-key/src/lib.rs","sha256":"45eec1b295dac3bed65cd79c942870b926b06b3f5d38eaebaeb6140ac69315fa"},{"path":"core/crates/auths-algebra-kernel/Cargo.toml","sha256":"0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba"},{"path":"core/crates/auths-algebra-kernel/src/generated.rs","sha256":"ae4bcbef42a408c7ffa0c6a74a42f7de177a6f14479e51d205acf830bda05960"},{"path":"core/crates/auths-algebra-kernel/src/lib.rs","sha256":"6654667eeb9b353d6648954c9fd2e8838462a82ce6b2803eb49e1366892c68c6"},{"path":"core/crates/auths-assurance/Cargo.toml","sha256":"afcb12a97ddd09d7a264b9ecd3fcaefc865ff2c9b4539ee85b00883420ba333a"},{"path":"core/crates/auths-assurance/src/lib.rs","sha256":"0fb2ec844d674b25a9e20b1601452c89c2454901fa506adfa9bb38ef9a7fa213"},{"path":"core/crates/auths-author/Cargo.toml","sha256":"1e6f0e3bc079ddb558decf0db26b291c6e72fc47327b6df1b7650d41689b215f"},{"path":"core/crates/auths-author/src/lib.rs","sha256":"e14475f2f49715a1869d5fa6b11ff1fbb72497e39097e09f833b0bae7e5b3f2b"},{"path":"core/crates/auths-author/src/observations.rs","sha256":"dda7d6bfa6f4bd7e95a480ca283c2c0e996f69c5c15cb0c7197af328131a7066"},{"path":"core/crates/auths-authority/Cargo.toml","sha256":"4f68212938029f79ebd857b4f3038494eb85d0163d49f07e51376715cf959815"},{"path":"core/crates/auths-authority/src/lib.rs","sha256":"da88d5194de4e17449e69972c0fb042afa3c39798a8f570f30771e77c384f1eb"},{"path":"core/crates/auths-codec/Cargo.toml","sha256":"e20e51826e17814effd9d8925d18d5fbdd6c0d37bf50231e743ec2611314722c"},{"path":"core/crates/auths-codec/src/approval.rs","sha256":"fbff43bf4d57f69f8b7738a8647751cde75c5a932dee65d924a1fe9c7202f91f"},{"path":"core/crates/auths-codec/src/bounded_policy.rs","sha256":"d21f6728be2d8a04b6d94921f2b683f7e61cbb42e0ac6866f1c88a49caa534c3"},{"path":"core/crates/auths-codec/src/decode.rs","sha256":"ba2999584cdf53b1b517ecb9c7ea50d39efee17c666a9a38e2ad1ac94379f778"},{"path":"core/crates/auths-codec/src/encode.rs","sha256":"8491192053e2e15d62b4d2a491de22405b7487ead69ab6f6bca40669ce7ca5f7"},{"path":"core/crates/auths-codec/src/error.rs","sha256":"fecb0737c16deb42d859f1dc7727c698438d9ac12064fd99e0024629642c390c"},{"path":"core/crates/auths-codec/src/hash.rs","sha256":"f88e111f1dbb2cef6b7b5e9c948cb45ff92e366710c8a5f5c636138aa748479e"},{"path":"core/crates/auths-codec/src/lib.rs","sha256":"3b0e5c94c6f34f750b88a9333e1d5c8145746d845d3a23e0d2f61807cf592ea7"},{"path":"core/crates/auths-codec/src/observation.rs","sha256":"38328b0c71ff97a4196eeade8b4faa889527ff1f80bb168468bcd49082a3987e"},{"path":"core/crates/auths-composition/Cargo.toml","sha256":"331e13025eb82588b5269ed3975929eb41c823d588c49e4c296273d85c6fe80e"},{"path":"core/crates/auths-composition/src/lib.rs","sha256":"e42e3b0b6a9985b73c533aeb23799c638979aa27a9ce7d0f10a8d60340570fb1"},{"path":"core/crates/auths-model/Cargo.toml","sha256":"565c15302b0cc9270db1e28efa3862804846850ba933cc17aea8abcec4a65987"},{"path":"core/crates/auths-model/src/approval.rs","sha256":"54cf44a9ef747ec21546a4086aecfb130bc7803b0d646430e6082df51e6e305f"},{"path":"core/crates/auths-model/src/bounded.rs","sha256":"f90496abc0a06c028b4d850af6ddab7d850bfafeaa3d042f1b1246a41d8bbbc9"},{"path":"core/crates/auths-model/src/bounded_policy.rs","sha256":"306a8f049cc7cfc7635fe0e4de47eb7813eed63d3c14c3be2b51586aa4eea450"},{"path":"core/crates/auths-model/src/lib.rs","sha256":"e7cfe6bb9574c6b016aa63e70658c31e0b90903ec6479a49f4a2ceb64f5bad97"},{"path":"core/crates/auths-model/src/observation.rs","sha256":"b3ed3e3cc090afca2896a7d3de7988afccc1ee1ea0ebd91b51a8bc0f20ad8dbb"},{"path":"core/crates/auths-multikey/Cargo.toml","sha256":"858756c1197befcada06134742bffe8d58cf674cadd6c046bf710570e96efaf2"},{"path":"core/crates/auths-multikey/src/lib.rs","sha256":"f5177fffb11e40eeaaa665ba886c541fc1f24d5eacdd6983fb03dc20148733f0"},{"path":"core/crates/auths-ports/Cargo.toml","sha256":"596a9b0f5af3717c16a6d13f7054d8a106bcd9f01f5f72c2235dd2afcf0ab16c"},{"path":"core/crates/auths-ports/src/binding.rs","sha256":"a16c012d40aa4249e3ec54372b9611006d0bfe8c7dc3c741911c2194ad17736d"},{"path":"core/crates/auths-ports/src/diagnostics.rs","sha256":"aa596572503b5a65a918bb2ff38281c144ff53821ee914e9325c852828d852df"},{"path":"core/crates/auths-ports/src/lib.rs","sha256":"8da1debf86f9532df0660155d04298beb1ba3a1204508f8586e2e67cd2fb3449"},{"path":"core/crates/auths-ports/src/path.rs","sha256":"b68fc547b4e4d97a60cbbc1cc1939fc6b34a8233b81f840bd396914a707e3ea1"},{"path":"core/crates/auths-raw-key-core/Cargo.toml","sha256":"98c0bc8527a537512e43a74dd6ba9658c6f0cdc16610cf938e3f9b43785d836d"},{"path":"core/crates/auths-raw-key-core/src/lib.rs","sha256":"98c0500c41697aae28708ad0bf970b9a97583d96a3d2c18d23e7fa351e0f7d12"},{"path":"core/crates/auths-registries/Cargo.toml","sha256":"590e49e58b0622d9d6274fea46796dcdb07dec9550eff295cce6a6427ffa51e2"},{"path":"core/crates/auths-registries/src/lib.rs","sha256":"450d3886d85ee333b7e046317fb5b47cde62483d5f3e41d46265e2caf4c373ec"},{"path":"core/crates/auths-registries/src/template.rs","sha256":"1224039dd2b3ce6fa8357613d8cafbae40400493da7176da202b9ade62fa05e4"},{"path":"core/crates/auths-signature-core/Cargo.toml","sha256":"6bee2230eb30af1be0bd5c2d57bd3e1903497a70028d47290d4ac6e9e0e8bca0"},{"path":"core/crates/auths-signature-core/src/lib.rs","sha256":"6e3f9311ded5e49ea50d445eb21e6d8fa12442aa4362a73e0cb6fda15b7cd865"},{"path":"core/crates/auths-signature/Cargo.toml","sha256":"7f7b5682466ba439d8c59579022cb61068cad9fb4bd2d73e1cc21327c902b450"},{"path":"core/crates/auths-signature/src/lib.rs","sha256":"b3d9ac4cc3ba0797b9e1c09f2d6ac05089b25dac4e285a5af28c0165b33d925b"},{"path":"core/crates/auths-verifier/Cargo.toml","sha256":"c43358e06a33324b41a8b93e5cc7279c55f7d21f1f6cfaa539a3fc7b4c27a38f"},{"path":"core/crates/auths-verifier/src/approval.rs","sha256":"c3cae6a49e169051eb555bb092b1069a4d422516d6a2114623a89e5f31ff923f"},{"path":"core/crates/auths-verifier/src/causal.rs","sha256":"9635230f33b13a263573d319ac8a1976addbcc07677514a43e3c7bf28dc04587"},{"path":"core/crates/auths-verifier/src/lib.rs","sha256":"f22dec38dfa47ced8da4f605390da8453273bee1da010f57fd1fdfcb10e0b389"},{"path":"core/crates/auths-verifier/src/observation.rs","sha256":"0bb07f06a0f9524c88427df1c972b1de8ba038a9eeeb15d3134c25125ae84b1e"},{"path":"core/crates/auths-verifier/src/trace.rs","sha256":"2213d72023a1d9e0413a2cf2c51c3dad9e04775d86033a0caaa9d29a8f0036f8"},{"path":"exchange/crates/auths-proof-exchange-model/Cargo.toml","sha256":"34b2db64f93a288e942b5a3918d28cdcbef906e0dc9074ce848018d3d5f7a1fa"},{"path":"exchange/crates/auths-proof-exchange-model/src/lib.rs","sha256":"49fac5aff2339d3a57c41cb8bb2a82852538e8f77ecc4b157c88e264ff31fb55"},{"path":"exchange/crates/auths-proof-exchange-port/Cargo.toml","sha256":"7ff660f1b7579dc570c791090aeb450404fbbf44c92781e289f5ccdde746d739"},{"path":"exchange/crates/auths-proof-exchange-port/src/lib.rs","sha256":"b408fb40c6432edc1facb3d8b3e9433a033f8dc73fe2e0ba5a88c972ca675021"},{"path":"product/config/auths-config/Cargo.toml","sha256":"e4b568ab9f6d84f7d7e6d66443fe825f360db9c27bc7c31d6ddc0647ba3ab304"},{"path":"product/config/auths-config/src/lib.rs","sha256":"fecf00ea65cef9018fda9af2063326d7065b869266d0d9e73a4f06816f1102cc"},{"path":"product/errors/auths-errors/Cargo.toml","sha256":"3b3a199b6460ba75bda84475bb5accd35e1485448a3981038db85bf4772dd350"},{"path":"product/errors/auths-errors/src/lib.rs","sha256":"7feeb9069fa4003f94f1f07c1c94619cf1c883e0dbaaf2187f04d0f742264bdd"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/Cargo.toml","sha256":"716f1f2a117d6d69d8effe9ee9057e24ba3502f20af6a602b06facb638cdabed"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/api.rs","sha256":"9ea61dd7ddd93282b073b98e453e6b75b26dc49689c04e9782435d06a3a09e48"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/clock.rs","sha256":"73f0a6e0f5903883329fa6683f5888288f759512ac69e5c87efd2b6b87f7d79f"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/http.rs","sha256":"14c1fce14e24c984b2a275563a29b6326fb08367922b6e8d37ba38b9cb81aa2b"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/identity.rs","sha256":"186de11230c8b33375951c4368609f8976bf9795f171af3fd7fac26207a94361"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs","sha256":"0b4617d044f5254a5ab22f5a2578f91cc025206a8c1845be39c1c56dcdf7a5df"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/names.rs","sha256":"41bb23572d6002e23ee103d6fe70ecd68764861c6f2e48a1c53af998270a4afa"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs","sha256":"39fed883f4802e68d3b41a68fea0aba0737810996b33d13577de70faba004c29"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/store.rs","sha256":"fc60ee9c49b2f4f063c449b4c78100c5c4872779e94ca168f796603b380ef6e4"},{"path":"product/integrations/auths-custody/Cargo.toml","sha256":"1e14034185ad1ec24a977fd5f41d0abee219606245c046ce2a82287fadef448b"},{"path":"product/integrations/auths-custody/src/conformance.rs","sha256":"8ed1afd58f18fc6becc268908aa6419c9aa404c79da0197963eb2599df44acf6"},{"path":"product/integrations/auths-custody/src/key.rs","sha256":"70cbb0fd21b6f5652157845a22c35be2d0f6c05b3d138fc4b9bb6dbdc3d81c40"},{"path":"product/integrations/auths-custody/src/lib.rs","sha256":"8ee593c1f59b0fd2126bdda9138026f5bc531beb64d4489a99785842e7b98b43"},{"path":"product/operations/auths-operations/Cargo.toml","sha256":"73dde1e914ba5e1386f8d49c0d730423cc72ae77ec44c6554a6a75cc8e8922b1"},{"path":"product/operations/auths-operations/src/explanation.rs","sha256":"b4a39bcbd5712cb9e735ee7deeb281f3fa6af5ddca973735bf3d87dce427ef11"},{"path":"product/operations/auths-operations/src/lib.rs","sha256":"3f401a56555113b98f57bca172a2660eaecedf76247b83a3fdbb089c133a29cd"},{"path":"product/operations/auths-operations/src/render/json.rs","sha256":"2ae042639960afee123730e945d373bc5dda1d2b3af20ae16c939a7e99b9e418"},{"path":"product/operations/auths-operations/src/render/mod.rs","sha256":"b3b7f6fe473f49227ace5a68bfc3d8dc14b5db8dd9888fd9e207070337b1b8bf"},{"path":"product/operations/auths-operations/src/render/text.rs","sha256":"f216cf3bdb00e264523271b16e7059535ac6b1aabf271cebd7935af155e4bfec"},{"path":"product/policy/auths-bounded-policy/Cargo.toml","sha256":"babd5d200923137ead71d8c2528f847cea323ce98da942a1320b054436612c47"},{"path":"product/policy/auths-bounded-policy/src/arithmetic.rs","sha256":"75e43c5d4eab8d1f71c1daf53839f5f9fe45a400afc1f63a30c6f55ce3632627"},{"path":"product/policy/auths-bounded-policy/src/commitment.rs","sha256":"c5706f2d583454e1a7f570f7ada138d4d864bef0205dfae7c1296774f396bb3f"},{"path":"product/policy/auths-bounded-policy/src/eligibility.rs","sha256":"c9acdfb793074e687fc36efad506be27dbd99ffbf40387bc66c8de39ef238432"},{"path":"product/policy/auths-bounded-policy/src/identifier.rs","sha256":"0006a32bae9eb16c4178cf797df418d2b0a781f2bc6474b741dc1a908141831c"},{"path":"product/policy/auths-bounded-policy/src/kernel.rs","sha256":"99187c28b161ac70bee1afed60711f7f645adb4d1671a01863f9849b369811d5"},{"path":"product/policy/auths-bounded-policy/src/lib.rs","sha256":"76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c"},{"path":"product/policy/auths-bounded-policy/src/receipt.rs","sha256":"3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad"},{"path":"product/policy/auths-bounded-policy/src/registry.rs","sha256":"4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0"},{"path":"product/profiles/auths-profile-api/Cargo.toml","sha256":"7ae85761f58625b5d678f961fd052eebf3e000ef565c7312e3ac857763c0017f"},{"path":"product/profiles/auths-profile-api/src/lib.rs","sha256":"a194b82b20bf8aa864c2334ef6c6aec30b2154ded972862252d5dcefa488ab95"},{"path":"product/profiles/auths-profile-mcp/Cargo.toml","sha256":"db264fc25242f7b7e4133cbe5782545b3107b406c87168ae072683cfb59eac66"},{"path":"product/profiles/auths-profile-mcp/src/arguments.rs","sha256":"a5de696586d507e2aee4a49fee99ef1ef4c51a2e46603f8838f1af6d9009833f"},{"path":"product/profiles/auths-profile-mcp/src/lib.rs","sha256":"d0f8b733a09ef8408336cdebc8948d6a5861012ce6878598b11be7084dfd4280"},{"path":"product/profiles/auths-profile-mcp/src/session.rs","sha256":"166c281fa66333388e4760d6098dad02d3359e1d5de4b8f93312c014f97abb03"},{"path":"product/qualification/auths-recipe-qualification/Cargo.toml","sha256":"b7b15b30b9a3d96d4f089d514266d3a892de6608d30707aa44be31cca89ca9fe"},{"path":"product/qualification/auths-recipe-qualification/src/canonical.rs","sha256":"30a9b50777f0dcb4b606abfee2467d5a975d9f6ad941ab6c13ca3df5b359f667"},{"path":"product/qualification/auths-recipe-qualification/src/closure.rs","sha256":"0ad6aee9bd981e2863fa725f209ec84031db2ff12f4c7ac3aaf5120f0bb86039"},{"path":"product/qualification/auths-recipe-qualification/src/error.rs","sha256":"52d5cf720a1e4579008fdda90a3ac2c31f0b8db57985f121f65e54b4da2b7dd1"},{"path":"product/qualification/auths-recipe-qualification/src/evidence.rs","sha256":"ba45a7409d67a8af26ab811af306412014557477a101ab2a8eb0faf8f2bd4b91"},{"path":"product/qualification/auths-recipe-qualification/src/ids.rs","sha256":"e81a906d571497ab2da753e1532d4443706410e0b75fdd59a7d2d788c7aec403"},{"path":"product/qualification/auths-recipe-qualification/src/launch.rs","sha256":"05b73fabb40d663466026b2bae5a9fd2681e1a3deaefa0f91811e6acfdd467fd"},{"path":"product/qualification/auths-recipe-qualification/src/lib.rs","sha256":"5c9cff04c8960df805a2f7656cf5e74932798e0db7648341e96ae7073a592404"},{"path":"product/qualification/auths-recipe-qualification/src/model.rs","sha256":"3484eb0ec287b23d4682ade7b1b0f8d1335985b3fb180f06fc28716076957d5f"},{"path":"product/qualification/auths-recipe-qualification/src/release.rs","sha256":"d816b53e2275e902c750ad03803061844e259e28560ab2d1c77e8a43981a4d6a"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/mod.rs","sha256":"7f15b68e05a04f202bcb1fb80de1d9a9a4fda8bfd6af2cd4e5c660fc75d96fe5"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/schemas.rs","sha256":"c59feec2805621f341a90f81fc005e2c12f7a70f9d264fdeacccb2be4fe1c046"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/verification.rs","sha256":"6a6b5834c5dae10af1ba8939b2deae43b85db71544dc8f077ff63b7fe68ac8a8"},{"path":"product/qualification/auths-recipe-qualification/src/verify.rs","sha256":"a470a9b98c04dc8d5dabe4d3dc8ed4e7a3ceb1cde035944a0714462bbf37d56d"},{"path":"product/receipts/auths-receipts/Cargo.toml","sha256":"6001fa1375899953aafcb07c23a6da0c8f57ea7ec08bb9c950b12a60a8cc6f0f"},{"path":"product/receipts/auths-receipts/src/disclosure.rs","sha256":"ba9ed439be0a320c8a01f5b6e9b51361c1a37e076947490d8e4a484ba6bb119c"},{"path":"product/receipts/auths-receipts/src/lib.rs","sha256":"547a57c4160256719cafb7d0ab972d9fc80b0da14fbbce4148c70c414070ff36"},{"path":"product/runtime/auths-connections/Cargo.toml","sha256":"babeb6e1dda3dfb66291713ce1e43dce5c349833d0b50ea4dccbf986030026b2"},{"path":"product/runtime/auths-connections/src/credential.rs","sha256":"82921413bb053f0f6c7931fbd4e6a86c8cc1d8c6b51debd9c2cef33a8d5b1c51"},{"path":"product/runtime/auths-connections/src/kernel.rs","sha256":"a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8"},{"path":"product/runtime/auths-connections/src/lib.rs","sha256":"79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22"},{"path":"product/runtime/auths-connections/src/model.rs","sha256":"de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77"},{"path":"product/runtime/auths-connections/src/registry.rs","sha256":"e57640e003e72ad3235c567c2bb944a262bd64e673f023b62ea091094cc7e946"},{"path":"product/runtime/auths-gateway-kernel/Cargo.toml","sha256":"34f864e67656af4ac7e5c7a347a23f01fc8ab31365b8e23c0ef474483b14a183"},{"path":"product/runtime/auths-gateway-kernel/src/construct.rs","sha256":"e9d65744bae273d65face4285e5d2da75c06a92ab48f7b8333d496604e31c63c"},{"path":"product/runtime/auths-gateway-kernel/src/lib.rs","sha256":"cfda6f8453426564c085475f183b6f790b438768a19668f1b65d33ba59dc8632"},{"path":"product/runtime/auths-gateway-kernel/src/order.rs","sha256":"e0045f877c4b7fe3860c291039853885064ddcdebba7c9b345ab65e81e646dda"},{"path":"product/runtime/auths-gateway-kernel/src/outcome.rs","sha256":"e9785b1afe70788c89b51b18655bcd5acff7b0c8e3d12fb79c6f05a202e67e6b"},{"path":"product/runtime/auths-gateway-kernel/src/ratio.rs","sha256":"7ace22264812e6fc1ef3a62afee402cf43494bb71ae0d3de219ad1b39d690bcb"},{"path":"product/runtime/auths-gateway-kernel/src/recovery.rs","sha256":"9f46dcd1685ab6e4d1ba04a3fc286a9f3afee8fb47829be1fbc670a7926a2dc6"},{"path":"product/runtime/auths-gateway-kernel/src/transition.rs","sha256":"cefb8f01d915880f6921f2501ff881ad94b9de61072c34d9cd19220992f97374"},{"path":"product/runtime/auths-gateway/Cargo.toml","sha256":"00b28be86921dcdc0ad90cce0c62c2961cafefe96ea6c2edf0e926c3d405ccad"},{"path":"product/runtime/auths-gateway/src/admin.rs","sha256":"2d5cc67afac42fbd15f36e2d1693cd1b20cedacf775040dce6ffe04ccc94c9ea"},{"path":"product/runtime/auths-gateway/src/app.rs","sha256":"6f80f63833ea0815bb44fbf3b0cc54624a08e9fb578b035819f2980dc04e8256"},{"path":"product/runtime/auths-gateway/src/audit.rs","sha256":"0edb2037eb7b5d6f13acfce85c54f62a82bf7fdd31bc7e626c4fec183cef61dd"},{"path":"product/runtime/auths-gateway/src/audit_tests.rs","sha256":"990969384a52d75bc2489d9d412a9e7dd814bca1c8f65c701d6205fae62a15d5"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway-harness.rs","sha256":"12b0c24d36b2e6a3be392d3c081a783b355fdd67dc5b54bacc0410e803116b8c"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway.rs","sha256":"2f33a1da5dd54947ee1664795f90b3f07a11bb9ee184774bf470b78b03600f0c"},{"path":"product/runtime/auths-gateway/src/binding.rs","sha256":"663b0ce878319511aa7d05722ab4ab2fa9be18817884ffb2ee9f131ff1e382d1"},{"path":"product/runtime/auths-gateway/src/bounds.rs","sha256":"9cfa0eae4973e5e047a198360b22f041708fa20276b0b90c2ec440f06915d64b"},{"path":"product/runtime/auths-gateway/src/bounds_aggregate_tests.rs","sha256":"ab34f227b7c8692ba1da88ccb32bb3687a66adf8353d8282fae905d4a88eb612"},{"path":"product/runtime/auths-gateway/src/bounds_tests.rs","sha256":"74136bc570da7b9338b5a1a1ed9d3fd892c55135160964f9d3ac0e2cf5741375"},{"path":"product/runtime/auths-gateway/src/connection.rs","sha256":"7b5d049c258a26ed1c93ecf860f51d051a8a65f9b93554af0b1ea93862398ec9"},{"path":"product/runtime/auths-gateway/src/credential_journal.rs","sha256":"7297fccaee5cd8622928e8e0a42bba50da7941970a6f682ecd300c41ee6509da"},{"path":"product/runtime/auths-gateway/src/echo_verify.rs","sha256":"6d453051665f823abd7354d5c50031d9524cf47d6092d2f09080ae814e3b9575"},{"path":"product/runtime/auths-gateway/src/engine.rs","sha256":"f1052aaef43e441b9e0befa3f8ad1e2fd5279a27cb9d63aac0cf9dfdbe85a052"},{"path":"product/runtime/auths-gateway/src/fuzzing.rs","sha256":"ed3b0028487eb546a3b0a91d115aa8f18bcea324b61620bfe8e35a9e6ab18758"},{"path":"product/runtime/auths-gateway/src/generation_floor.rs","sha256":"fe1510ec96ce0f67e9a78edbfa94b33eb7df64c0ac4d0a67901124dcd0164777"},{"path":"product/runtime/auths-gateway/src/harness.rs","sha256":"c87e479f3eb281960f6c9c80d43c7560d7ccb654b0154ec823d3fcec4884ac05"},{"path":"product/runtime/auths-gateway/src/lib.rs","sha256":"4674c497940ab339d9b755b71a3e1fe5feeba28bfecc025b7d148dc804a508bf"},{"path":"product/runtime/auths-gateway/src/listener.rs","sha256":"aa08239bcbc1fcb55e8a212fbdf6a84f12985b0d436dcb51dc58b06e59e435f2"},{"path":"product/runtime/auths-gateway/src/observed_tests.rs","sha256":"a22be071695f89ca2578a4d82fd80d9cb82289213c9bdb8f0470f6b2dc3d9201"},{"path":"product/runtime/auths-gateway/src/observer.rs","sha256":"562ffcaea071c3856e0708dc2fe33516917e145d2438aabb75af0a2b6ba01046"},{"path":"product/runtime/auths-gateway/src/onboarding.rs","sha256":"0dfd7d67e7f02f18a28d1c86ca1b7751d7463f5efcdbe3825de0ad8cbccb3891"},{"path":"product/runtime/auths-gateway/src/operator.rs","sha256":"c3c36954a3e86723df035b47f43b85fc8ab3a6292983522b6258d5c6b4e6c4e4"},{"path":"product/runtime/auths-gateway/src/pending_vectors/attempts.rs","sha256":"47ef3c8cb1c5504d47ae9a0088705ce6715fe86bac1671a34a56fb38a64d0dd3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/bounds.rs","sha256":"e612217307e1da5b0eb5ee6582a7458bb064b8aa8a529fc6555b1b334127ab68"},{"path":"product/runtime/auths-gateway/src/pending_vectors/codes.rs","sha256":"e00670a5ef24eb856cc2c6dcda8e5a263842f55c76bb939c0c27bd9df37e5522"},{"path":"product/runtime/auths-gateway/src/pending_vectors/keys.rs","sha256":"f84c56f2ea9cb34b2b79c72d13fbf2c6585010ec1ed450af58a78c80c1ea1edd"},{"path":"product/runtime/auths-gateway/src/pending_vectors/mod.rs","sha256":"5de8340f0ef71a0b57a09e323fefe473d3160c6ae952b9ba46f714825fbacafc"},{"path":"product/runtime/auths-gateway/src/pending_vectors/outcomes.rs","sha256":"8ec07b9511b48913af36ac999d2aa0e82924289f6acb23ddaeb9f00f99815166"},{"path":"product/runtime/auths-gateway/src/pending_vectors/production.rs","sha256":"f574cabfa4687a4fc846b8f6a234b68ec53b876aed548b11445729cac1a55ede"},{"path":"product/runtime/auths-gateway/src/pending_vectors/recipes.rs","sha256":"51693208270231c25c3aef2a32151d5962114c71e86b88cb9df83181c7af83d9"},{"path":"product/runtime/auths-gateway/src/pre_entry.rs","sha256":"06ea78ca140468bfaba17d9ab04912ad68673954c3203c98fed28272ff2a00c0"},{"path":"product/runtime/auths-gateway/src/property_tests.rs","sha256":"939c081e2e154aaf10186754044bdd65608932c899b970a04a71d0afaa999a93"},{"path":"product/runtime/auths-gateway/src/qualification.rs","sha256":"06b49d3fc2ad4383f9e23beefa96033f1fd6e415e043878327583451a53086cc"},{"path":"product/runtime/auths-gateway/src/qualification_tests.rs","sha256":"4473add5729b97faf04d7be7fd8cf3bbacd7f545e1b61c7d2782563011906b4d"},{"path":"product/runtime/auths-gateway/src/quorum_tests.rs","sha256":"a78380b019104d688c11a4410082c7e08ded3106aab099954c4f8a1b4ae0fd89"},{"path":"product/runtime/auths-gateway/src/readiness.rs","sha256":"911c3f11892f94641574375e2da4c671c802738f71082f12c39832331052d43d"},{"path":"product/runtime/auths-gateway/src/recipe.rs","sha256":"fecf9af67e7afc48d080e9f8f55f8ce28e49d0e08988717a27908bbda461d6b6"},{"path":"product/runtime/auths-gateway/src/recipe/lower.rs","sha256":"8088b8751ed831dbb48247af953c6290ac95e2a438ccd5bd65eff54be06a1fd1"},{"path":"product/runtime/auths-gateway/src/recipe/review.rs","sha256":"c3eb7d9fdd98dacf52750b14b67ad7b7faaecbbdeafff1e0b049f67d0a2d0139"},{"path":"product/runtime/auths-gateway/src/recipe/runtime.rs","sha256":"c286f0d15f974402822c0810d8e97f98411dc1c557755cc23e540d85e2bb42d9"},{"path":"product/runtime/auths-gateway/src/recipe/source.rs","sha256":"1af50298fb1461e1b24cbdf560d43124d6b1c4c529586c911b1c4797214a69ff"},{"path":"product/runtime/auths-gateway/src/recipe/tests.rs","sha256":"aac551a2481bbc60864c64079bc667dcb232e45a0f41a04073ed84ab5dbe1fce"},{"path":"product/runtime/auths-gateway/src/recipe/validate.rs","sha256":"3711b17605cb7b0d639bc1b180449231f5882a306cab20e2c7782155cc63b0d4"},{"path":"product/runtime/auths-gateway/src/scenario_tests.rs","sha256":"d8271761b12597bfe1233f8eb5ad1d4e5498c5d03388e832e24ab818484a1de4"},{"path":"product/runtime/auths-gateway/src/separation.rs","sha256":"be9306848ca5d801767cf6aa14247c8618312ef0e202f00ce0c24c4844491061"},{"path":"product/runtime/auths-gateway/src/store.rs","sha256":"1e5288345c2cb1421aeda277b3158d07607404b0ec46943222ac107b63dcbb46"},{"path":"product/runtime/auths-gateway/src/store_testkit.rs","sha256":"88d82fee42f1b8ef521e8deef0216e938ebeaad822eb2f5020e70b89d145ea70"},{"path":"product/runtime/auths-gateway/src/submit.rs","sha256":"c78dbbba7c45b443febf655056c5edcd635e77be7b21c5b2c318097502415ffe"},{"path":"product/runtime/auths-gateway/src/support.rs","sha256":"9fd979029793a22b15d9776a7fc172476fd7c126a80d4080c65d720845becbcb"},{"path":"product/runtime/auths-gateway/src/transport.rs","sha256":"be2c6dc75b8daec110bf8749fedc3823f6067d40b999aa3eb21126896a97d3ad"},{"path":"product/runtime/auths-kernel-runtime/Cargo.toml","sha256":"926bcd0053e5edd703be8f0027ad009e2982db013c8174c1366edbf38b48087d"},{"path":"product/runtime/auths-kernel-runtime/src/lib.rs","sha256":"7108faae9ca4bc32dc093ddaf885ac8f74f3c9b8d317b7c7d0ed00d1d0ab5972"},{"path":"product/runtime/auths-lifecycle/Cargo.toml","sha256":"c5053c705f8d5554b44e432fe75287a2faf11d644e5a2552e45ad6cd94176af5"},{"path":"product/runtime/auths-lifecycle/src/codec.rs","sha256":"51c4b746749150e8bfcd8ff972b3f6c1ef40bec15583448ec1b471d9ad737dc0"},{"path":"product/runtime/auths-lifecycle/src/digest.rs","sha256":"55282cd7d8aba37713c2dcb5357c9877819edb72a30eadefb860d28d7d3a3eb7"},{"path":"product/runtime/auths-lifecycle/src/identifier.rs","sha256":"31620e8c16de68d3d2d3b84d6353c1a5b9d4151d8247f91fa389b906a8e660f1"},{"path":"product/runtime/auths-lifecycle/src/kernel.rs","sha256":"2abb8c094b36d35b364e74d78091d14c5d6f3d1eb6552cca3b5538dbd017ce23"},{"path":"product/runtime/auths-lifecycle/src/lib.rs","sha256":"afe5a345cd309b5a4f08ffba3170a6d7f16ff914892b3f2006d5208ed24ec736"},{"path":"product/runtime/auths-lifecycle/src/model.rs","sha256":"1af12bbeeeaa65ec02ddcebd7d2c8c92ec1e339fa40ae85b45ab9b01a722a4fa"},{"path":"product/runtime/auths-lifecycle/src/operation.rs","sha256":"78e6d05fcf5d7ea4f148032a3fa26fdfcab77eb346019effe927b08e0d64d732"},{"path":"product/runtime/auths-lifecycle/src/registry.rs","sha256":"53495fe6f7a77422593a41623e28716f1c140dcc1e00f87f6b0ffbfb93a5ef90"},{"path":"product/runtime/auths-lifecycle/src/sealed.rs","sha256":"2e0c03b5813c926c159598bb7890d1523825edbe57cd687d42a5dfb3374a0c19"},{"path":"product/runtime/auths-lifecycle/src/test_support.rs","sha256":"221d9a5c5ef8e1f9f8fd66927484eaf813571d0568470278ecd8fa08a5eec8cd"},{"path":"product/runtime/auths-lifecycle/src/transition.rs","sha256":"011805a28efdd541f44ccea54dd0e34a1e58f4004447ee58013703b4fb6b2822"},{"path":"product/runtime/auths-runtime/Cargo.toml","sha256":"dd29d80a8b4bb56c869f036a6c9998f6e6d1c0383ac5dc03fa42b24abe2a7ff7"},{"path":"product/runtime/auths-runtime/src/lib.rs","sha256":"132ca03d58c14905d3a822a4972f42a22a5ad33a45f2ba9ca44f3a57d810b4b0"},{"path":"product/runtime/auths-runtime/src/production.rs","sha256":"fd4eff4270c571c10fcff6cf27df28961ebf074de8a1a028f500fda1ca376820"},{"path":"product/sdk/auths-approval-quorum/Cargo.toml","sha256":"df904971fca87a24194c5816738a331588fe8f164acb5d70839a35dca5f57114"},{"path":"product/sdk/auths-approval-quorum/src/lib.rs","sha256":"72e4086088a1c0912e4e1a9e980f26a5c280bf5ab16ea39c9f0f58d5096ac2ce"},{"path":"product/sdk/auths-approval-quorum/src/remote.rs","sha256":"9fa029c7c63003adf260f8aec55160c545681c60c1bace0d934e7525862aac7b"},{"path":"product/sdk/auths-approval-quorum/src/remote_tests.rs","sha256":"8a09ce17cfee82a035a74edd535f3ebeb3db0e078784740d3997b17dbdb10197"},{"path":"product/sdk/auths-approval-quorum/src/tests.rs","sha256":"0acbf12be3e497dcc6c2d8f29c9af3b1a7ed8e11b75f6399570d4f217a785060"},{"path":"product/stores/auths-stores/Cargo.toml","sha256":"a32c4b76d17b264be5d40d24497ff237e1ed87822e8bab86229b3db93106dbe3"},{"path":"product/stores/auths-stores/src/gateway_attempt.rs","sha256":"185da8f4a220fba836d5b78a9311f03204681c43a3c53951008084d135bf4d21"},{"path":"product/stores/auths-stores/src/lib.rs","sha256":"e721262edf8a9ab5568ddc27639176312d4a366203b5f73e2d7c11fde2c554e9"},{"path":"product/stores/auths-stores/src/lifecycle.rs","sha256":"94f64d25bc178a9e60ba3c0ee6915d7fb3af7c4468792d76b4e70f43f4de1e2f"}],"schema":"auths.gateway-semantic-closure/1"} \ No newline at end of file diff --git a/product/runtime/auths-gateway/src/semantic_closure.rs b/product/runtime/auths-gateway/src/semantic_closure.rs index 94260912d..0d1f554df 100644 --- a/product/runtime/auths-gateway/src/semantic_closure.rs +++ b/product/runtime/auths-gateway/src/semantic_closure.rs @@ -10,7 +10,7 @@ /// SHA-256 of the schema, a NUL byte, and `semantic-closure.json`. /// Regenerate through `semantic_closure_is_current` with `AUTHS_UPDATE_FIXTURES=1`. pub const GATEWAY_SEMANTIC_CLOSURE_SHA256: &str = - "464c6c17b8b6f969da548b4df9bdebf8bfe58066727a5a2fe5f150b443854c52"; + "7cc768345590accc1d7e4b7de14e976148d11b37bb5445034171235388d19685"; #[cfg(test)] mod tests { diff --git a/release/release-manifest.contract-fixture.json b/release/release-manifest.contract-fixture.json index 843389df2..3d0ab2643 100644 --- a/release/release-manifest.contract-fixture.json +++ b/release/release-manifest.contract-fixture.json @@ -59,6 +59,10 @@ { "path": "evidence/conformance.json", "sha256": "1111111111111111111111111111111111111111111111111111111111111111" + }, + { + "path": "target/release-evidence/launch-readiness.json", + "sha256": "6666666666666666666666666666666666666666666666666666666666666666" } ], "benchmarks": [ diff --git a/release/release-manifest.schema.json b/release/release-manifest.schema.json index 00ea02223..c8d4dadca 100644 --- a/release/release-manifest.schema.json +++ b/release/release-manifest.schema.json @@ -66,7 +66,16 @@ "spdx": { "$ref": "#/$defs/nonEmptyDigestReferences" }, "provenance": { "$ref": "#/$defs/nonEmptyDigestReferences" }, "formalManifest": { "$ref": "#/$defs/digestReference" }, - "conformance": { "$ref": "#/$defs/nonEmptyDigestReferences" }, + "conformance": { + "allOf": [{ "$ref": "#/$defs/nonEmptyDigestReferences" }], + "contains": { + "type": "object", + "required": ["path", "sha256"], + "properties": { "path": { "const": "target/release-evidence/launch-readiness.json" } } + }, + "minContains": 1, + "maxContains": 1 + }, "benchmarks": { "$ref": "#/$defs/nonEmptyDigestReferences" }, "releaseNotes": { "$ref": "#/$defs/digestReference" } }, diff --git a/release/semantic-freeze-versions.toml b/release/semantic-freeze-versions.toml index e7c30e343..34c6fbb9d 100644 --- a/release/semantic-freeze-versions.toml +++ b/release/semantic-freeze-versions.toml @@ -1,4 +1,4 @@ -freeze_version = 369 +freeze_version = 370 # Semantic identity counters live outside the xtask source tree deliberately. # The formal source closure binds xtask's executable code, while the semantic @@ -7,7 +7,7 @@ freeze_version = 369 # converge. This file is a reviewed release input, never an automatic output. [entries] "auths.core.protocol" = 36 -"auths.frozen-bytes/architecture/dependency-graph.json" = 78 +"auths.frozen-bytes/architecture/dependency-graph.json" = 79 "auths.frozen-bytes/bindings/wasm/auths-proof-wasm/identity-abi-v1.json" = 4 "auths.frozen-bytes/bounded-domains.toml" = 2 "auths.frozen-bytes/core/conformance/v1/manifest.json" = 2 @@ -19,7 +19,7 @@ freeze_version = 369 "auths.frozen-bytes/formal/assurance-manifest-v1.toml" = 58 "auths.frozen-bytes/formal/qualification/aeneas/generated" = 19 "auths.frozen-bytes/formal/qualification/aeneas/qualification.toml" = 16 -"auths.frozen-bytes/formal/qualification/aeneas/source-closure.json" = 97 +"auths.frozen-bytes/formal/qualification/aeneas/source-closure.json" = 98 "auths.frozen-bytes/product/conformance/v1/mechanism-profile-conformance.json" = 1 "auths.frozen-bytes/product/conformance/v1/simplified-product-waist.json" = 4 "auths.frozen-bytes/product/fixtures/v1/bounded-policy/manifest.json" = 3 @@ -67,4 +67,4 @@ freeze_version = 369 "auths.product.vocabulary" = 24 "auths.release.benchmark-contract" = 1 "auths.release.evolution-contract" = 79 -"auths.release.public-surface" = 369 +"auths.release.public-surface" = 370 diff --git a/release/semantic-freeze.json b/release/semantic-freeze.json index ac0a07006..59d4441ba 100644 --- a/release/semantic-freeze.json +++ b/release/semantic-freeze.json @@ -1,6 +1,6 @@ { "schema": "auths.semantic-freeze/1", - "freezeVersion": 369, + "freezeVersion": 370, "publicSurface": { "rustRoots": [ "auths", @@ -94,7 +94,7 @@ }, { "id": "auths.frozen-bytes/architecture/dependency-graph.json", - "version": 78, + "version": 79, "classification": "frozen-bytes", "categories": [ "canonical-generated-evidence" @@ -102,7 +102,7 @@ "owners": [ "architecture/dependency-graph.json" ], - "sha256": "9f16afa44d9d1220fdc7d7d219ec114b444978b8bb9288242ddd62b376f2f6c4" + "sha256": "83fed3f0d16736b93df13412e43e500f91840effd660aa17fb07ad79974c3d8f" }, { "id": "auths.frozen-bytes/bindings/wasm/auths-proof-wasm/identity-abi-v1.json", @@ -238,7 +238,7 @@ }, { "id": "auths.frozen-bytes/formal/qualification/aeneas/source-closure.json", - "version": 97, + "version": 98, "classification": "frozen-bytes", "categories": [ "canonical-generated-evidence" @@ -246,7 +246,7 @@ "owners": [ "formal/qualification/aeneas/source-closure.json" ], - "sha256": "32b4ba2c0a643b402d2109abc0b4dbe125827a20d4760911654e078dcfe02d29" + "sha256": "31b4053a1e61e4195ff2bcc0495f1014bd1b1a8970da970282dec29fe4aa500d" }, { "id": "auths.frozen-bytes/product/conformance/v1/mechanism-profile-conformance.json", @@ -1011,7 +1011,7 @@ }, { "id": "auths.release.public-surface", - "version": 369, + "version": 370, "classification": "release-metadata", "categories": [ "package-names", @@ -1101,9 +1101,10 @@ "xtask/src/public_naming.rs", "xtask/src/release.rs", "xtask/src/release_control.rs", + "xtask/src/release_launch.rs", "xtask/src/semantic_freeze.rs" ], - "sha256": "2ec62100d0f39cb3cd4c6786286d1de77c279aefbb34bdce730867e764708039" + "sha256": "6546b04c364ef8ba03022a369388bc15b90c2cd5afef4733216fa1fbd7561527" } ] } diff --git a/xtask/src/release.rs b/xtask/src/release.rs index 2f4d4f4be..72d18b381 100644 --- a/xtask/src/release.rs +++ b/xtask/src/release.rs @@ -1533,6 +1533,16 @@ pub(crate) fn validate_release_manifest_value(manifest: &Value) -> Result<(), St validate_digest_reference(reference)?; } } + if evidence["conformance"] + .as_array() + .ok_or("release manifest evidence has no conformance array")? + .iter() + .filter(|reference| reference["path"] == release_launch::REPORT_PATH) + .count() + != 1 + { + return Err("release manifest must bind exactly one launch projection".to_owned()); + } validate_digest_reference(&evidence["formalManifest"])?; validate_digest_reference(&evidence["releaseNotes"]) } @@ -1666,7 +1676,10 @@ mod tests { "spdx": [digest_reference("evidence/sbom.spdx.json")], "provenance": [digest_reference("evidence/provenance.sigstore.json")], "formalManifest": digest_reference("formal/assurance-manifest-v1.toml"), - "conformance": [digest_reference("evidence/conformance.json")], + "conformance": [ + digest_reference("evidence/conformance.json"), + digest_reference(release_launch::REPORT_PATH), + ], "benchmarks": [digest_reference("evidence/benchmarks.json")], "releaseNotes": digest_reference("evidence/RELEASE_CANDIDATE_NOTES.md"), }, @@ -1742,6 +1755,22 @@ mod tests { .expect("complete exact release manifest should pass"); } + #[test] + fn final_release_manifest_requires_one_launch_projection() { + for duplicate in [false, true] { + let mut manifest = valid_manifest(); + let references = manifest["evidence"]["conformance"] + .as_array_mut() + .expect("references"); + if duplicate { + references.push(digest_reference(release_launch::REPORT_PATH)); + } else { + references.retain(|reference| reference["path"] != release_launch::REPORT_PATH); + } + assert!(validate_release_manifest_value(&manifest).is_err()); + } + } + #[test] fn final_release_manifest_rejects_unknown_schema() { let mut manifest = valid_manifest(); diff --git a/xtask/src/release_control.rs b/xtask/src/release_control.rs index 240377712..e55483b10 100644 --- a/xtask/src/release_control.rs +++ b/xtask/src/release_control.rs @@ -110,6 +110,7 @@ fn finalize_preparation( if subjects.is_empty() { return Err("release-manifest input has no subjects".to_owned()); } + release_launch::verify_projection(&root(), commit)?; let provenance_path = copy_evidence_file( provenance_source, @@ -178,7 +179,7 @@ fn finalize_preparation( "conformance": [ digest_reference("target/release-evidence/platform.json")?, digest_reference("target/compliance/report.json")?, - digest_reference("target/release-evidence/launch-readiness.json")?, + digest_reference(release_launch::REPORT_PATH)?, ], "benchmarks": [ digest_reference("demos/benchmarks/profiles/release.toml")?, diff --git a/xtask/src/release_launch.rs b/xtask/src/release_launch.rs index f1a5053b6..e72bff1d7 100644 --- a/xtask/src/release_launch.rs +++ b/xtask/src/release_launch.rs @@ -12,6 +12,8 @@ use serde_json::{Value, json}; use sha2::{Digest as _, Sha256}; use std::{fs, io::Read as _, path::Path, process::Command}; +pub(crate) const REPORT_PATH: &str = "target/release-evidence/launch-readiness.json"; + fn bounded(path: &Path, maximum: usize) -> Result, String> { let metadata = fs::symlink_metadata(path).map_err(|_| "qualification input unavailable")?; if !metadata.file_type().is_file() || metadata.len() > maximum as u64 { @@ -193,3 +195,76 @@ pub(crate) fn projection(repository: &Path, commit: &str) -> Result Result<(), String> { + let report: Value = serde_json::from_slice(&bounded(&repository.join(REPORT_PATH), 16 * 1024)?) + .map_err(|_| "launch projection invalid")?; + let current = projection(repository, commit)?; + compare_projection(&report, ¤t) +} + +fn compare_projection(report: &Value, current: &Value) -> Result<(), String> { + for field in [ + "schema", + "source_commit", + "gateway_semantic_closure_sha256", + "stable_launch_ready", + "reason", + "human_release_review", + "target", + ] { + if report[field] != current[field] { + return Err("launch projection differs from current candidate inputs".to_owned()); + } + } + if let Some(now) = current["evaluated_at"].as_u64() + && report["evaluated_at"] + .as_u64() + .is_none_or(|evaluated| evaluated > now) + { + return Err("launch projection evaluation time invalid".to_owned()); + } + Ok(()) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn finalization_refuses_a_manual_readiness_flag_or_another_candidate() { + // Explicit test observation of a candidate with unavailable inputs. + // This test remains valid when a production root is eventually pinned. + let report = json!({"schema": "auths.launch-readiness/1", + "source_commit": "a".repeat(40), + "gateway_semantic_closure_sha256": "d".repeat(64), + "stable_launch_ready": false, "reason": "pinned-root-unavailable", + "human_release_review": "separate-required-gate"}); + compare_projection(&report, &report).expect("actual derived report"); + for (field, value) in [ + ("stable_launch_ready", json!(true)), + ("source_commit", json!("b".repeat(40))), + ("gateway_semantic_closure_sha256", json!("c".repeat(64))), + ] { + let mut changed = report.clone(); + changed[field] = value; + assert!(compare_projection(&changed, &report).is_err()); + } + assert!(compare_projection(&json!({}), &report).is_err()); + let mut ready = report; + ready["stable_launch_ready"] = json!(true); + ready["evaluated_at"] = json!(100); + let mut future = ready.clone(); + future["evaluated_at"] = json!(101); + assert!(compare_projection(&future, &ready).is_err()); + let mut missing_time = ready.clone(); + missing_time + .as_object_mut() + .expect("report") + .remove("evaluated_at"); + assert!(compare_projection(&missing_time, &ready).is_err()); + } +} diff --git a/xtask/src/semantic_freeze.rs b/xtask/src/semantic_freeze.rs index 5cf768a65..e939530c5 100644 --- a/xtask/src/semantic_freeze.rs +++ b/xtask/src/semantic_freeze.rs @@ -705,6 +705,7 @@ fn generate_inventory() -> Result { "xtask/src/public_naming.rs".to_owned(), "xtask/src/release.rs".to_owned(), "xtask/src/release_control.rs".to_owned(), + "xtask/src/release_launch.rs".to_owned(), "xtask/src/semantic_freeze.rs".to_owned(), ]); entries.push(freeze_entry( From 338453d9d3324ed383755e75429c93a57a16c924 Mon Sep 17 00:00:00 2001 From: bordumb Date: Tue, 6 Oct 2026 21:27:42 +0100 Subject: [PATCH 032/108] docs(qualification): define the proposed provider claims and bootstrap gaps --- ...0014-stripe-refund-recipe-qualification.md | 82 +++++++++++++++++++ ...able-record-update-recipe-qualification.md | 81 ++++++++++++++++++ qualification/README.md | 32 +++++++- 3 files changed, 193 insertions(+), 2 deletions(-) create mode 100644 docs/adr/0014-stripe-refund-recipe-qualification.md create mode 100644 docs/adr/0015-airtable-record-update-recipe-qualification.md diff --git a/docs/adr/0014-stripe-refund-recipe-qualification.md b/docs/adr/0014-stripe-refund-recipe-qualification.md new file mode 100644 index 000000000..c17203b5a --- /dev/null +++ b/docs/adr/0014-stripe-refund-recipe-qualification.md @@ -0,0 +1,82 @@ +# ADR 0014: Qualify the Stripe refund recipe against a disposable Connect account + +**Status:** Proposed. No family is a candidate or qualified. Acceptance requires +the executable family corpus, independent oracle and protected evidence below. + +**Date:** 6 October 2026 + +## Scope and identity + +The proposed family is `stripe-refund-v1`, starting from +[`examples/stripe-refund-approval/recipe.json`](../../examples/stripe-refund-approval/recipe.json) +and its profile lock. Qualification binds the compiled recipe, profile lock, +reviewed provider contract, candidate executable and semantic closure, Linux +x86_64 target, PostgreSQL schema and `aws-secrets-manager-v1` custody. A source +file or provider name alone identifies none of these claims. + +The contract is Stripe API `2025-03-31.basil` in `provider-test-mode`. A test-mode +Connect account must differ from the platform account. Only disposable test +payments may be refunded; no customer data or real-money claim is in scope. +The gateway continues to interpret recipe data. Provider semantics and the +qualification oracle remain in the release harness, outside the runtime build. + +## Oracle and provider assumptions + +The test-only oracle must independently derive the POST URL, ordered form body, +version and account-scope headers, payment-intent basis read, refund locator and +fresh observation from the reviewed action and evidence. It must compare both +accepted and refused cases with the candidate, including request/evidence +commitments. It may reuse canonical encoding and cryptographic primitives; +calling the gateway's evaluator to produce the expected result is not an oracle. +The old Stripe vertical's bounded-refund evaluator is a reference for arithmetic, +not proof that the current recipe shares every budget or recovery meaning. + +| Assumption | Required protected observation | +| --- | --- | +| The credential addresses test mode | The `rk_test_` prefix and `/v1/balance` `livemode=false` guard both hold. | +| Credential identity stays bound | The unscoped `/v1/account` result agrees with the installed platform commitment on every lease. | +| Restricted reads are refused | Unscoped customers and payouts reads return the recipe's declared 403 statuses. | +| The selected account is distinct | Record sanitized platform and connected identifiers; action reads, write and refund read-back carry the exact verified `Stripe-Account`. Credential reads do not. | +| The ceiling uses the selected payment | Fresh amount and currency evidence passes at 50%, and refuses at boundary plus one or with a changed currency. | +| The exact request is entered once | Provider and credential witnesses count replay, fresh-challenge replay, race, restart and crash cases separately from the corpus's expected counters. | +| A recorded refund is observed | Fresh GET of the returned refund identifier matches amount and echo under the selected account. | +| The idempotency declaration held in this run | Inspect a deliberate duplicate request inside the declared 86,400-second window; do not infer indefinite retention. | + +Stripe documents refund amounts in minor units and a remaining-refundable +constraint ([refund API](https://docs.stripe.com/api/refunds/create)); the recipe's +50% basis is not an atomic reservation of that provider balance. Stripe documents +server-side connected-account selection by header +([Connect authentication](https://docs.stripe.com/connect/authentication)). That +does not establish that the platform token is restricted to one connected account. + +## Corpus, recovery and publication gates + +The maintained offline seeds are the recipe/profile lock, gateway +`attempt-scenarios-v3.json`, `bounds-aggregate.json`, `outcome-v2.json` and +`hostile-recipes-v2.json`. They must be expanded into the family-owned +`auths.qualification-corpus/1` with executable coverage of every mandatory wall +scenario; they are not the missing protected family corpus. + +The live corpus must additionally exercise every declared capability, provider +secret rotation, production doctor, two-host restart, redaction of actual support +bundles and installed Python/TypeScript clients with no token or source import. +The current recipe declares no lost-response recovery capability. Response loss +must remain `unknown`; delayed read-back may resolve only when the gateway has +retained the recipe's required response locator. `recovery` is not applicable +because this recipe cannot locate an unrecorded refund response. Observer +rotation is not applicable unless the qualified installation declares one. + +Before a candidate run, resolve the production qualification bootstrap described +in [`qualification/README.md`](../../qualification/README.md): no optional policy, +test-feature executable or fabricated intermediate attestation can stand in for +the exact shipped target. Resource bindings and expected digests must also be +fixed by a reviewed corpus expansion before execution, rather than copied from +the candidate's answers. + +Use a maximum 30-day attestation and rerun before renewal or any tuple change. +Revoke on evidence/custody compromise, unauthorized entry, broken account binding, +changed provider behavior or a materially false published assumption. Publish +only sanitized disposable identifiers, bounded evidence, signed artifacts and +explicit exclusions. Provider availability, settlement, indefinite idempotency, +global exactly-once behavior and prevention of writes by other actors remain +provider-owned. No live evidence is claimed by this decision record. diff --git a/docs/adr/0015-airtable-record-update-recipe-qualification.md b/docs/adr/0015-airtable-record-update-recipe-qualification.md new file mode 100644 index 000000000..f73d151fa --- /dev/null +++ b/docs/adr/0015-airtable-record-update-recipe-qualification.md @@ -0,0 +1,81 @@ +# ADR 0015: Independently qualify one Airtable field update + +**Status:** Proposed. No family is a candidate or qualified. Acceptance requires +the executable family corpus, independent oracle and protected evidence below. + +**Date:** 6 October 2026 + +## Scope and identity + +The proposed family is `airtable-record-update-v1`. Start with the independently +authored field-lab recipe and profile under +[`bindings/fixtures/gateway/airtable/`](../../bindings/fixtures/gateway/airtable/). +The existing `appTEST...` and `tblTEST...` fixture values are synthetic and cannot +be used as live evidence. Substitute one dedicated disposable base and table +through a reviewed recipe construction, then approve and attest its actual +compiled digest. Changing either fixed identifier changes qualification. + +The provider contract is an explicitly reviewed Airtable Web API v0 slice in +`disposable-live-resources`; the recipe has no API version header. Bind the +contract to reviewed documentation and assumptions rather than treating `v0` as +an immutable provider implementation. The candidate target is the same shipped +Linux x86_64 gateway, PostgreSQL schema and production AWS custody used by the +Stripe family. The shared runtime gains no Airtable operation or provider branch. + +## Independent oracle and provider assumptions + +The test-only oracle derives exactly PATCH `/v0///` with +`fields.DemoStatus` and the declared echo, and GET of the same record with the +declared status/echo pointers. It must independently validate allowed replacement +values, field bounds, segment encoding and request/evidence commitments. +It must not call the candidate to generate expected decisions or requests. + +| Assumption | Required protected observation | +| --- | --- | +| The operator's token reaches only disposable resources | Configure the personal access token with the necessary record read/write scopes and one base; inspect refusal against an excluded base. | +| The fixed table and record belong to that base | Retain sanitized base/table/record identifiers; inspect a fresh record read before and after each successful action. | +| The write changes the intended field | Compare the exact PATCH body with the independent oracle; fresh GET must return the declared replacement and echo. | +| Invalid actions enter nothing | Forge, alter, unknown-field, replacement-enum, path-injection and wrong-recipe cases show zero credential leases and provider entries. | +| Persisted admission survives process changes | Replay, fresh challenge, race, crash and restart witnesses show no second authorized entry for the logical operation. | +| Uncertain delivery stays uncertain | Lose the response after entry and delay visibility; absence of declared recovery cannot become observed success. | + +Airtable's token permissions depend on both scopes and selected resources +([personal access tokens](https://support.airtable.com/articles/9934989703-creating-personal-access-tokens)). +This family must observe its configured restrictions; possession of a token is +not evidence that they were configured. The current recipe has no credential +guard or account-binding probe, so the ADR cannot claim the gateway enforces +those capabilities on every lease. + +## Corpus, exclusions and publication gates + +The maintained offline seeds are `airtable/vectors.json`, the profile lock and +gateway hostile, attempt and outcome corpora. Publish a family-owned executable +`auths.qualification-corpus/1` covering the complete evidence wall, including +an oracle-accepted update, all refused mappings, real application isolation and +credential drift. These seeds alone are not the missing protected family corpus. + +The protected live corpus must exercise a fresh confirmed update, echo, +production doctor, provider-secret rotation, two hosts, restart/recovery, +actual support/log/trace/metric scans and installed Python/TypeScript journeys. +Create records with no personal data; cleanup removes only resources whose +identifiers were recorded by this run and must also execute after partial setup. + +The recipe declares no provider idempotency or recovery capability. Both are +not applicable because a field overwrite and echo are not a provider deduplication +or lost-response reconciliation contract. Version pin, credential guard, account +binding, denied reads, relative ceiling, sum budget, response locator and +pre-entry read are also not applicable because they are absent from this recipe. +Observer rotation is required only if the installed target declares one. + +The production qualification bootstrap and reviewed dynamic resource bindings +in [`qualification/README.md`](../../qualification/README.md) must be resolved +before a candidate can run. Do not qualify a development file-store tuple and +rename it as the production target. + +Use a maximum 14-day attestation, reflecting the absence of a fixed API release +header, and rerun before renewal or any tuple change. Revoke on unexpected +provider entries, secret/evidence compromise, changed response behavior, token +scope widening or invalid observation assumptions. Publish signed artifacts, +bounded evidence and sanitized resource identifiers. Atomic compare-and-swap, +isolation from another writer, provider idempotency, lost-response recovery and +generic account-binding guarantees are excluded. No live evidence is claimed. diff --git a/qualification/README.md b/qualification/README.md index 19c392476..db04b6ff0 100644 --- a/qualification/README.md +++ b/qualification/README.md @@ -6,8 +6,11 @@ The specification is §7 and §8; the run is described in [the protected-run plan](../docs/plans/RECIPE_QUALIFICATION_PROTECTED_RUN_PLAN.md). -No family is qualified and none is present here yet. The two launch families -arrive with their decision records. +No family is qualified and none is present here yet. Proposed provider decisions +are [ADR 0014](../docs/adr/0014-stripe-refund-recipe-qualification.md) and +[ADR 0015](../docs/adr/0015-airtable-record-update-recipe-qualification.md). +They explicitly remain proposed until their executable corpora and protected +evidence exist. `cargo xtask release-check` generates `target/release-evidence/launch-readiness.json`. Its `stable_launch_ready` value comes from the gateway build's pinned public @@ -26,6 +29,31 @@ contracts and provider kinds on the same production candidate. Its clock must pass the maintained synchronization check. Human release review remains a separate requirement. +Finalization re-evaluates the projection against current candidate inputs before +binding it into the final manifest. An edited readiness value, another commit, +drifted target or missing projection cannot become a signed launch claim. The +manifest contract requires exactly one digest-bound projection. + +## First-run prerequisites still unresolved + +The current production gateway refuses every lease without a current exact-tuple +attestation. The protected workflow gathers live effects before it can sign that +attestation. Therefore its first qualification cannot bootstrap itself. A +development installation or `testkit-production-unqualified` executable changes +the target or shipped bytes and cannot establish the required production claim. +An owner-reviewed authority design must resolve this cycle while preserving the +production lease gate; no bypass has been implemented. + +The current executable corpus also fixes exact request/evidence digests before +running, while disposable live resource identifiers may be created during setup. +Family harnesses need a reviewed, bounded resource-binding and oracle expansion +before executing their cases. Copying the candidate's observed digest into an +expected result would invalidate the differential evidence. + +The offline trust-root ceremony, protected release signer and two provider +credentials remain external prerequisites. Docker supports the labeled local +operator simulation; it supplies none of these live qualification inputs. + A `production-readiness` case is additionally required for each stable launch claim. It runs only in the protected live phase against PostgreSQL and production custody, without a lease or provider entry. The reviewed harness From fa9ca49ba8914fb37b6abc710df4b06ea6b2d3fb Mon Sep 17 00:00:00 2001 From: bordumb Date: Tue, 6 Oct 2026 21:28:37 +0100 Subject: [PATCH 033/108] test(qualification): verify the published evidence closure --- .../tests/cli.rs | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/product/qualification/auths-recipe-qualification-issuance/tests/cli.rs b/product/qualification/auths-recipe-qualification-issuance/tests/cli.rs index 22a8e1e45..3fcff1f87 100644 --- a/product/qualification/auths-recipe-qualification-issuance/tests/cli.rs +++ b/product/qualification/auths-recipe-qualification-issuance/tests/cli.rs @@ -290,6 +290,38 @@ fn a_release_is_built_signed_and_verified_and_a_proposal_alone_is_not() { ); succeed(&borrowed(&sign("proposal", "signer.key"))); + // A consumer must be able to verify the signed record's closure using + // only the published release, after the unsigned proposal is unavailable. + let record = auths_recipe_qualification::RecipeQualificationRecord::from_canonical_json( + &fs::read(at("proposal/record.json")).expect("proposal record"), + ) + .expect("record"); + let artifacts: Vec = record + .body() + .evidence + .iter() + .map(|member| { + let artifact = auths_recipe_qualification::QualificationEvidence::from_canonical_json( + &fs::read(at(&format!( + "release/evidence/{}.json", + member.evidence_sha256.to_hex() + ))) + .expect("published evidence"), + ) + .expect("canonical evidence"); + assert_eq!(artifact.digest(), member.evidence_sha256); + artifact + }) + .collect(); + auths_recipe_qualification::verify_evidence_closure(&record, &artifacts) + .expect("published evidence closes over the signed record"); + assert_eq!( + fs::read_dir(at("release/evidence")) + .expect("published evidence directory") + .count(), + EvidenceMemberKind::ALL.len(), + "release includes exactly its evidence members" + ); fs::copy( at("unsigned/revocation-list.json"), at("release/revocation-list.json"), From 35d69959f36963cf6f8f2eacb861eed9b192c64c Mon Sep 17 00:00:00 2001 From: bordumb Date: Tue, 6 Oct 2026 21:30:06 +0100 Subject: [PATCH 034/108] docs(spec): align the launch evidence scenario and remaining gates --- docs/PROGRAM_BOARD.md | 9 ++++++ ...RECIPE_QUALIFICATION_PROTECTED_RUN_PLAN.md | 7 +++-- ...gateway-polish-and-recipe-qualification.md | 30 +++++++++++++++++-- 3 files changed, 42 insertions(+), 4 deletions(-) diff --git a/docs/PROGRAM_BOARD.md b/docs/PROGRAM_BOARD.md index b07ccf0aa..ccbea4d07 100644 --- a/docs/PROGRAM_BOARD.md +++ b/docs/PROGRAM_BOARD.md @@ -428,3 +428,12 @@ production readiness evidence. The signing output retains those artifacts; current projection remains false. Hosted verification of this implementation is pending. Provider ADRs/corpora/harnesses, live qualification, signed release publication and the installed SDK pilot remain outstanding. + +The Epic 5 finalizer now re-evaluates launch readiness before binding the +projection, and the manifest contract refuses a missing or duplicate reference. +ADR 0014 (Stripe Connect refund) and ADR 0015 (Airtable field update) remain +proposed; neither has an executable protected family corpus or a qualification. +The documented first-attestation bootstrap cycle and reviewed dynamic resource +binding must be resolved before live qualification. The production lease gate +has not been relaxed. GitHub verification and Epic 4's current main CI are still +pending; the passing Docker simulation does not close these live gates. diff --git a/docs/plans/RECIPE_QUALIFICATION_PROTECTED_RUN_PLAN.md b/docs/plans/RECIPE_QUALIFICATION_PROTECTED_RUN_PLAN.md index 42edc6e5c..7437da32f 100644 --- a/docs/plans/RECIPE_QUALIFICATION_PROTECTED_RUN_PLAN.md +++ b/docs/plans/RECIPE_QUALIFICATION_PROTECTED_RUN_PLAN.md @@ -82,9 +82,12 @@ reason its decision record fixes; nothing is omitted. | 11 secret and provider-data scans | `redaction` | | | 12 installed consumer journey | `installed-consumer` | | -Within a row, the cases are tagged with one of 36 scenarios, and a record +Within a row, the cases are tagged with one of 37 scenarios, and a record closes only when every scenario the wall always requires has a case; -AP-SPEC-066 §20.3 reading 3 lists them. The release tooling runs the +AP-SPEC-066 §20.3 reading 3 lists them. The additional `production-readiness` +scenario is a protected live doctor probe required for stable launch, with zero +leases and provider entries; intermediate records may omit it without becoming +launch-ready. The release tooling runs the differential comparison, the redaction scan, and the freshness and signer-rotation stages itself. The executable corpus runner sequences the remaining operations through a reviewed family's harness and derives reports from measured observations. See `qualification/README.md` for the bounded subprocess contract. diff --git a/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md b/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md index 05f0911f0..be4a0c86e 100644 --- a/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md +++ b/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md @@ -1428,7 +1428,7 @@ Each was taken unattended as the narrower or fail-closed reading. | 1 | `clean-source`, `recipe-digest-rederives` | conformance | | 2 | `recipe-vectors`, `closed-enumeration-hostile` | conformance | | 3 | `oracle-accepts`, `oracle-rejects` | differential | - | 4 | `application-cannot-read-secret` | hostile | + | 4 | `application-cannot-read-secret`, `production-readiness` (launch gate) | hostile | | 5 | `forged-proof`, `altered-action`, `proof-replay`, `fresh-challenge-replay`, `direct-provider-attempt`, `ambiguous-response` | hostile | | 5 | `two-instance-race` | multi-instance | | 5 | `restart`, `crash` | restart | @@ -1440,7 +1440,13 @@ Each was taken unattended as the narrower or fail-closed reading. | 11 | `log-scan`, `trace-scan`, `metric-scan`, `support-bundle-scan`, `evidence-scan` | redaction | | 12 | `installed-journey`, `no-repository-import`, `no-provider-token` | installed-consumer | - Thirty-four are required of every record. `observer-rotation` and + The closed set has thirty-seven scenarios. Thirty-four are required of every + record. `production-readiness` is additionally required for the stable launch + projection: a protected live, read-only doctor probe on the exact PostgreSQL + and production-custody target, with all required typed rows ready and zero + leases or provider entries. Its evidence commits to the actual doctor report. + Intermediate records may omit it but cannot close the stable launch gate. + `observer-rotation` and `declared-capability` are required exactly when a capability they show is exercised. `freshness` is placed in row 7 because the signed time bounds are part of the trust transitions. @@ -1647,3 +1653,23 @@ also lacks the owner's offline root ceremony, protected signer secret, two protected provider environments and human release review. On 2026-10-06, GitHub environment/secret metadata confirmed no qualification signer secret and neither family live environment. No production recipe is qualified. + +## 22. Epic 5 engineering and unresolved qualification inputs (2026-10-06) + +The release projection now verifies every signed index entry, exact candidate +identity, production target, time/revocation, evidence closure and production +readiness, requiring independent families, contracts and provider kinds. +Finalization re-evaluates the result and the manifest binds exactly one +projection. Signing publishes the canonical evidence needed to inspect closure. +The current build pins no root and derives false; hosted verification is pending. + +[ADR 0014](../adr/0014-stripe-refund-recipe-qualification.md) and +[ADR 0015](../adr/0015-airtable-record-update-recipe-qualification.md) are proposed +provider decisions, not candidate or qualified families. Executable corpora and +harnesses remain missing. The protected run also has a first-attestation cycle: +production leases require qualification before the live effects needed to issue +it. A reviewed authority design must resolve this without bypassing the shipped +lease gate. Dynamically created provider identifiers need reviewed oracle/corpus +binding before execution, not expected digests copied from candidate output. +Docker rehearsal establishes neither prerequisite and supplies no protected key +or live provider credential. No Epic 5 completion or release is claimed. From aff7e62a27d6049ceabb04ec34c483738c3f0aac Mon Sep 17 00:00:00 2001 From: bordumb Date: Tue, 6 Oct 2026 21:32:06 +0100 Subject: [PATCH 035/108] test(qualification): discard proposals before release consumption --- .../tests/cli.rs | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/product/qualification/auths-recipe-qualification-issuance/tests/cli.rs b/product/qualification/auths-recipe-qualification-issuance/tests/cli.rs index 3fcff1f87..b08af012e 100644 --- a/product/qualification/auths-recipe-qualification-issuance/tests/cli.rs +++ b/product/qualification/auths-recipe-qualification-issuance/tests/cli.rs @@ -292,10 +292,21 @@ fn a_release_is_built_signed_and_verified_and_a_proposal_alone_is_not() { succeed(&borrowed(&sign("proposal", "signer.key"))); // A consumer must be able to verify the signed record's closure using // only the published release, after the unsigned proposal is unavailable. + let proposal_record = + auths_recipe_qualification::RecipeQualificationRecord::from_canonical_json( + &fs::read(at("proposal/record.json")).expect("proposal record"), + ) + .expect("record"); + let published_record = at(&format!( + "release/records/{}.json", + proposal_record.body().qualification_id.as_str() + )); let record = auths_recipe_qualification::RecipeQualificationRecord::from_canonical_json( - &fs::read(at("proposal/record.json")).expect("proposal record"), + &fs::read(&published_record).expect("published record"), ) - .expect("record"); + .expect("published canonical record"); + assert_eq!(record.digest(), proposal_record.digest()); + fs::remove_dir_all(at("proposal")).expect("discard unsigned proposal"); let artifacts: Vec = record .body() .evidence @@ -378,7 +389,7 @@ fn a_release_is_built_signed_and_verified_and_a_proposal_alone_is_not() { "--source", &format!("log={}", at("gateway.log")), "--source", - &format!("evidence={}", at("proposal/record.json")), + &format!("evidence={published_record}"), "--out", &at("redaction.cases.json"), ]); From de20cccea1c7d9a5a8f9d58dfeb67957d1f848c4 Mon Sep 17 00:00:00 2001 From: bordumb Date: Tue, 6 Oct 2026 21:35:11 +0100 Subject: [PATCH 036/108] docs(program): close the simulated Epic 4 operator deliverable --- docs/PROGRAM_BOARD.md | 7 +++++-- ...6-production-gateway-polish-and-recipe-qualification.md | 6 +++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/docs/PROGRAM_BOARD.md b/docs/PROGRAM_BOARD.md index ccbea4d07..cb2c582ee 100644 --- a/docs/PROGRAM_BOARD.md +++ b/docs/PROGRAM_BOARD.md @@ -435,5 +435,8 @@ ADR 0014 (Stripe Connect refund) and ADR 0015 (Airtable field update) remain proposed; neither has an executable protected family corpus or a qualification. The documented first-attestation bootstrap cycle and reviewed dynamic resource binding must be resolved before live qualification. The production lease gate -has not been relaxed. GitHub verification and Epic 4's current main CI are still -pending; the passing Docker simulation does not close these live gates. +has not been relaxed. Epic 4's exact `393edc52` candidate passed all 26 main CI +jobs plus the six package/isolation/PostgreSQL/recipe/SDK workflows and the +47-step Docker rehearsal. PR #205 merged on 2026-10-06 as `4623d635` under the +owner's labeled-simulation deliverable. Production live and human claims remain +explicitly unexercised. Epic 5's current GitHub verification remains pending. diff --git a/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md b/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md index be4a0c86e..11ac408c3 100644 --- a/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md +++ b/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md @@ -1646,7 +1646,11 @@ source-free packaged simulation passed 47 steps in Docker against the verified `f1f92c3f` package after fixing development file-rotation and tuple-declaration friction. The sanitized report is `deployment/gateway/evidence/operator-simulation-2026-10-06.json`. -Exact-current-commit hosted verification remains pending; no live provider, +The exact `393edc52` candidate subsequently passed all 26 main CI jobs and the +six package/isolation/PostgreSQL/recipe/SDK workflows. Its source-free hosted +rehearsal passed all 47 steps in 0.553 seconds, and the downloaded archive passed +the same 47 steps in Docker in 6.162 seconds. PR #205 merged as `4623d635` on +2026-10-06 under the owner's labeled-simulation deliverable. No live provider, production AWS rotation or production PostgreSQL PITR is claimed by this run. Epic 5 also lacks the owner's offline root ceremony, protected signer secret, From 6806dcd8459a4bf2492acdfcbbd139262c2039b3 Mon Sep 17 00:00:00 2001 From: bordumb Date: Tue, 6 Oct 2026 23:47:57 +0100 Subject: [PATCH 037/108] Fix launch fixture identifier references reported by CI --- .../qualification/auths-recipe-qualification/src/launch.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/product/qualification/auths-recipe-qualification/src/launch.rs b/product/qualification/auths-recipe-qualification/src/launch.rs index fc70adaf8..0cb27efec 100644 --- a/product/qualification/auths-recipe-qualification/src/launch.rs +++ b/product/qualification/auths-recipe-qualification/src/launch.rs @@ -45,7 +45,7 @@ mod tests { let mut evidence = Vec::new(); for (index, (family, provider, contract)) in claims.iter().enumerate() { let mut deployment = tuple(); - deployment.recipe_family = RecipeFamilyId::parse(family).expect("family"); + deployment.recipe_family = RecipeFamilyId::parse(*family).expect("family"); let mut declared = crate::vectors::contract(); declared.api_release = bounded(contract); deployment.provider_contract_id = @@ -54,7 +54,7 @@ mod tests { u8::try_from(index + 1).expect("bounded fixture"), deployment, ); - body.provider_kind = ProviderKind::parse(provider).expect("provider"); + body.provider_kind = ProviderKind::parse(*provider).expect("provider"); body.provenance.environment = bounded(&format!("recipe-qualification-live-{family}")); let artifacts = artifacts(&body, readiness); From 3ab35fcf912a0151e86fb8e1b143829ebb399e88 Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 00:01:24 +0100 Subject: [PATCH 038/108] Rehearse disposable qualification bootstrap and two provider lifecycles --- .github/workflows/recipe-qualification.yml | 27 + docs/PROGRAM_BOARD.md | 11 + ...0014-stripe-refund-recipe-qualification.md | 5 +- ...able-record-update-recipe-qualification.md | 21 +- ...gateway-polish-and-recipe-qualification.md | 19 +- .../src/qualification_simulation.rs | 500 ++++++++++++++++++ .../auths-gateway/src/qualification_tests.rs | 161 ++++++ .../auths-gateway/src/scenario_tests.rs | 3 + qualification/README.md | 25 +- qualification/simulation/README.md | 34 ++ qualification/simulation/run.py | 101 ++++ 11 files changed, 886 insertions(+), 21 deletions(-) create mode 100644 product/runtime/auths-gateway/src/qualification_simulation.rs create mode 100644 qualification/simulation/README.md create mode 100644 qualification/simulation/run.py diff --git a/.github/workflows/recipe-qualification.yml b/.github/workflows/recipe-qualification.yml index 6ed670176..8e4eb8a3f 100644 --- a/.github/workflows/recipe-qualification.yml +++ b/.github/workflows/recipe-qualification.yml @@ -14,6 +14,11 @@ on: pull_request: paths: - "qualification/**" + - "product/runtime/auths-gateway/**" + - "product/qualification/**" + - "examples/stripe-refund-approval/recipe.json" + - "examples/stripe-refund-approval/profile.lock.json" + - "bindings/fixtures/gateway/**" - ".github/workflows/recipe-qualification.yml" permissions: @@ -24,6 +29,28 @@ concurrency: cancel-in-progress: false jobs: + simulation: + name: disposable bootstrap and two provider simulations + runs-on: ubuntu-latest + timeout-minutes: 45 + steps: + - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 + with: + persist-credentials: false + - uses: ./.github/actions/setup-rust-cache + with: + toolchain: 1.97.1 + - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 + with: + python-version: "3.12" + - run: python qualification/simulation/run.py --out target/qualification-simulation + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 + with: + name: qualification-simulation-${{ github.run_id }}-${{ github.run_attempt }} + path: target/qualification-simulation + if-no-files-found: error + retention-days: 30 + families: name: list the families runs-on: ubuntu-latest diff --git a/docs/PROGRAM_BOARD.md b/docs/PROGRAM_BOARD.md index cb2c582ee..751f0bd2c 100644 --- a/docs/PROGRAM_BOARD.md +++ b/docs/PROGRAM_BOARD.md @@ -440,3 +440,14 @@ jobs plus the six package/isolation/PostgreSQL/recipe/SDK workflows and the 47-step Docker rehearsal. PR #205 merged on 2026-10-06 as `4623d635` under the owner's labeled-simulation deliverable. Production live and human claims remain explicitly unexercised. Epic 5's current GitHub verification remains pending. + +The owner explicitly assigned first bootstrap and Stripe/Airtable qualification +to the agent as simulations. `qualification/simulation/run.py` now executes the +disposable ceremony and native provider harnesses without external credentials. +The required gate measures zero leases for unsigned fixtures and permits an +entry after verified import under disposable test trust. Separate provider +reports measure exact requests, replay, restart, response loss, crash, race and +hostile input behavior. The Airtable ADR now correctly names its derived linked +read-back recovery; Stripe cannot recover a response-provided locator that was +lost. Signing fixtures explicitly exclude provider-run claims. Production trust +and readiness remain unchanged; real users remain the owner's offline work. diff --git a/docs/adr/0014-stripe-refund-recipe-qualification.md b/docs/adr/0014-stripe-refund-recipe-qualification.md index c17203b5a..0a0f42ced 100644 --- a/docs/adr/0014-stripe-refund-recipe-qualification.md +++ b/docs/adr/0014-stripe-refund-recipe-qualification.md @@ -66,7 +66,10 @@ retained the recipe's required response locator. `recovery` is not applicable because this recipe cannot locate an unrecorded refund response. Observer rotation is not applicable unless the qualified installation declares one. -Before a candidate run, resolve the production qualification bootstrap described +The owner-directed [simulation](../../qualification/simulation/README.md) runs +this recipe through an independent wire oracle and mutable provider double, +with fixed synthetic resources and disposable signing trust. Before a protected +production candidate run, resolve the qualification bootstrap described in [`qualification/README.md`](../../qualification/README.md): no optional policy, test-feature executable or fabricated intermediate attestation can stand in for the exact shipped target. Resource bindings and expected digests must also be diff --git a/docs/adr/0015-airtable-record-update-recipe-qualification.md b/docs/adr/0015-airtable-record-update-recipe-qualification.md index f73d151fa..489400ee6 100644 --- a/docs/adr/0015-airtable-record-update-recipe-qualification.md +++ b/docs/adr/0015-airtable-record-update-recipe-qualification.md @@ -37,7 +37,7 @@ It must not call the candidate to generate expected decisions or requests. | The write changes the intended field | Compare the exact PATCH body with the independent oracle; fresh GET must return the declared replacement and echo. | | Invalid actions enter nothing | Forge, alter, unknown-field, replacement-enum, path-injection and wrong-recipe cases show zero credential leases and provider entries. | | Persisted admission survives process changes | Replay, fresh challenge, race, crash and restart witnesses show no second authorized entry for the logical operation. | -| Uncertain delivery stays uncertain | Lose the response after entry and delay visibility; absence of declared recovery cannot become observed success. | +| Reconciliation needs fresh matching evidence | Lose the response after entry and delay visibility; the verified record locator permits read-back, but only matching value and echo can establish observed success. No retry sends another PATCH. | Airtable's token permissions depend on both scopes and selected resources ([personal access tokens](https://support.airtable.com/articles/9934989703-creating-personal-access-tokens)). @@ -60,22 +60,25 @@ actual support/log/trace/metric scans and installed Python/TypeScript journeys. Create records with no personal data; cleanup removes only resources whose identifiers were recorded by this run and must also execute after partial setup. -The recipe declares no provider idempotency or recovery capability. Both are -not applicable because a field overwrite and echo are not a provider deduplication -or lost-response reconciliation contract. Version pin, credential guard, account +The recipe declares no provider idempotency. Its derived gateway recovery +capability is linked read-back: the fixed record locator and declared echo permit +read-only reconciliation after a lost response. The simulation exercises this +through the native driver and persistent claims; it sends no second PATCH. +This is not provider deduplication or compare-and-swap. Version pin, credential guard, account binding, denied reads, relative ceiling, sum budget, response locator and pre-entry read are also not applicable because they are absent from this recipe. Observer rotation is required only if the installed target declares one. -The production qualification bootstrap and reviewed dynamic resource bindings -in [`qualification/README.md`](../../qualification/README.md) must be resolved -before a candidate can run. Do not qualify a development file-store tuple and -rename it as the production target. +The owner-directed [simulation](../../qualification/simulation/README.md) uses +fixed synthetic resources and disposable signing trust. Production qualification +still requires reviewed live resource bindings and real protected evidence. +Do not rename a development tuple as the production target. Use a maximum 14-day attestation, reflecting the absence of a fixed API release header, and rerun before renewal or any tuple change. Revoke on unexpected provider entries, secret/evidence compromise, changed response behavior, token scope widening or invalid observation assumptions. Publish signed artifacts, bounded evidence and sanitized resource identifiers. Atomic compare-and-swap, -isolation from another writer, provider idempotency, lost-response recovery and +isolation from another writer, provider idempotency, recovery without a fresh +matching value and echo, and generic account-binding guarantees are excluded. No live evidence is claimed. diff --git a/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md b/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md index 11ac408c3..d5f2426ec 100644 --- a/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md +++ b/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md @@ -1669,11 +1669,22 @@ The current build pins no root and derives false; hosted verification is pending [ADR 0014](../adr/0014-stripe-refund-recipe-qualification.md) and [ADR 0015](../adr/0015-airtable-record-update-recipe-qualification.md) are proposed -provider decisions, not candidate or qualified families. Executable corpora and -harnesses remain missing. The protected run also has a first-attestation cycle: +provider decisions, not production-qualified families. The owner has directed +the agent to simulate bootstrap and both provider harnesses independently. +`qualification/simulation/run.py` now runs disposable in-memory root/signer +creation, certification, signing, index/revocation publication and required-gate +import. Unsigned and expired inputs cannot lease; verified test import can. +The signed placeholder records explicitly claim no provider run. Separate +Stripe and Airtable harness reports measure actual native driver leases, entries, +fresh read-back, replay, reopen, response loss and response-record crash against +independent wire oracles and mutable doubles. The production pinned root stays +unchanged and stable launch readiness stays false. The rehearsal is a maintained +CI job and needs no external credentials. + +The protected production run still has a first-attestation cycle: production leases require qualification before the live effects needed to issue it. A reviewed authority design must resolve this without bypassing the shipped lease gate. Dynamically created provider identifiers need reviewed oracle/corpus binding before execution, not expected digests copied from candidate output. -Docker rehearsal establishes neither prerequisite and supplies no protected key -or live provider credential. No Epic 5 completion or release is claimed. +Those real-production prerequisites do not block the owner-directed simulation. +No protected live evidence or production qualification is claimed. diff --git a/product/runtime/auths-gateway/src/qualification_simulation.rs b/product/runtime/auths-gateway/src/qualification_simulation.rs new file mode 100644 index 000000000..39c5155a6 --- /dev/null +++ b/product/runtime/auths-gateway/src/qualification_simulation.rs @@ -0,0 +1,500 @@ +//! Executable, explicitly synthetic provider qualification rehearsals. +//! The independent request oracles below do not read the compiled recipe. +//! Submission enters at the verified-command boundary; native proof/socket +//! journeys are exercised separately by the installed SDK workflows. + +use super::*; +use serde::Serialize; + +const STRIPE_VERSION: &str = "2025-03-31.basil"; +const STRIPE_ACCOUNT: &str = "acct_TESTACCOUNT01"; +const STRIPE_PAYMENT: &str = "pi_TEST0000000001"; + +#[derive(Clone, Copy)] +enum Family { + Stripe, + Airtable, +} + +impl Family { + fn command( + self, + recipe: &CompiledRecipe, + args: &Map, + commitment: [u8; 32], + ) -> VerifiedCommand { + self.admission(recipe, args, commitment).expect("admission") + } + + fn admission( + self, + recipe: &CompiledRecipe, + args: &Map, + commitment: [u8; 32], + ) -> Result { + let links = match self { + Self::Stripe => scenario_links(&corpus(SCENARIOS)["defaults"]["stripe"]), + Self::Airtable => Vec::new(), + }; + admitted(recipe, args, commitment, Vec::new(), 3_600, links, NOW) + } + fn name(self) -> &'static str { + match self { + Self::Stripe => "stripe-refund-v1", + Self::Airtable => "airtable-record-update-v1", + } + } + + fn recipe(self) -> CompiledRecipe { + match self { + Self::Stripe => CompiledRecipe::compile( + include_bytes!("../../../../examples/stripe-refund-approval/recipe.json"), + include_bytes!("../../../../examples/stripe-refund-approval/profile.lock.json"), + ) + .expect("Stripe recipe"), + Self::Airtable => fixture_recipe("airtable"), + } + } + + fn arguments(self, operation: &str) -> Map { + match self { + Self::Stripe => json!({"operation_id": operation, "payment_intent": STRIPE_PAYMENT, + "amount": 500, "currency": "usd", "connect_account": STRIPE_ACCOUNT}), + Self::Airtable => json!({"operation_id": operation, "record_id": RECORD, + "replacement": "Approved"}), + } + .as_object() + .expect("arguments") + .clone() + } + + /// Contract-owned wire oracle. Only admitted shared echo/idempotency + /// primitives are reused; mapping, encoding and resource IDs are fixed + /// by this independent vertical, never projected from candidate bytes. + fn oracle(self, operation: &str, commitment: &[u8; 32]) -> Value { + let namespace = crate::OperatorNamespace::parse(match self { + Self::Stripe => "stripe-refunds", + Self::Airtable => "airtable-demo", + }) + .expect("namespace"); + let operation = LogicalOperationId::parse(operation).expect("operation"); + let echo = echo_token(&namespace, &operation, commitment); + match self { + Self::Stripe => { + let mut form = url::form_urlencoded::Serializer::new(String::new()); + form.append_pair("amount", "500"); + form.append_pair("metadata[auths_echo]", &echo); + form.append_pair("payment_intent", STRIPE_PAYMENT); + json!({"method": "POST", "url": "https://api.stripe.com/v1/refunds", + "content_type": "application/x-www-form-urlencoded", "body": form.finish(), + "headers": [["Stripe-Version", STRIPE_VERSION], ["Stripe-Account", STRIPE_ACCOUNT], + ["Idempotency-Key", crate::idempotency_key(&namespace, &operation)]], + "idempotency_key": crate::idempotency_key(&namespace, &operation)}) + } + Self::Airtable => json!({"method": "PATCH", + "url": format!("https://api.airtable.com/v0/appTEST0000000001/tblTEST0000000001/{RECORD}"), + "content_type": "application/json", + "body": serde_json_canonicalizer::to_string(&json!({"fields": { + "DemoStatus": "Approved", "auths_echo": echo}})).expect("oracle JSON"), + "headers": [], "idempotency_key": null}), + } + } +} + +fn request_facts(request: &ClosedProviderRequest) -> Value { + json!({"method": request.method().as_str(), "url": request.url(), + "content_type": request.content_type(), "body": std::str::from_utf8(request.body()).expect("body"), + "headers": request.headers().iter().map(|header| (header.name(), header.value())).collect::>(), + "idempotency_key": request.idempotency_key()}) +} + +/// The oracle checks the actual outbound request before the mutable provider +/// double applies it. Counting witnesses come from actual driver calls. +struct OracleProvider

{ + inner: P, + expected: Value, + checked: AtomicUsize, +} + +trait SimulationProvider: ProviderPort { + fn entries(&self) -> usize; +} + +impl SimulationProvider for TableProvider { + fn entries(&self) -> usize { + self.writes() + } +} + +impl SimulationProvider for RecordProvider { + fn entries(&self) -> usize { + self.writes() + } +} + +impl ProviderPort for OracleProvider

{ + async fn write( + &self, + request: &ClosedProviderRequest, + ) -> Result { + assert_eq!( + request_facts(request), + self.expected, + "independent wire oracle" + ); + self.checked.fetch_add(1, Ordering::SeqCst); + self.inner.write(request).await + } + + async fn action_read( + &self, + url: &str, + headers: &[RequestHeader], + maximum: usize, + ) -> Option { + self.inner.action_read(url, headers, maximum).await + } + + async fn credential_read(&self, read: &ClosedCredentialRead) -> Option { + self.inner.credential_read(read).await + } +} + +#[derive(Serialize)] +struct Measurement { + case: String, + verdict: String, + credential_leases: usize, + provider_entries: usize, + confirmed_by_read_back: usize, +} + +fn measurement( + case: &str, + result: &GatewaySubmitResult, + leases: usize, + entries: usize, +) -> Measurement { + let verdict = match result { + GatewaySubmitResult::ObservedByProvider { .. } => "observed-by-provider".to_owned(), + GatewaySubmitResult::ResponseRecorded { .. } => "response-recorded".to_owned(), + GatewaySubmitResult::Unknown => "unknown".to_owned(), + GatewaySubmitResult::NotEntered { code } => code.clone(), + other => panic!("unexpected simulation result: {other:?}"), + }; + Measurement { + case: case.to_owned(), + verdict, + credential_leases: leases, + provider_entries: entries, + confirmed_by_read_back: usize::from(matches!( + result, + GatewaySubmitResult::ObservedByProvider { .. } + )), + } +} + +fn publish(family: Family, recipe: &CompiledRecipe, cases: &[Measurement]) { + let report = json!({"schema": "auths.recipe-qualification-simulation/1", + "simulation": true, "family": family.name(), "stable_launch_ready": false, + "compiled_recipe_sha256": recipe.digest_hex(), + "gateway_semantic_closure_sha256": crate::GATEWAY_SEMANTIC_CLOSURE_SHA256, + "store": "shared-file-v1", "custody": "test-only-counting-lease", + "verification_boundary": "native-verified-command projection", + "provider": "in-process mutable double", "cases": cases, + "excluded_claims": ["live provider acceptance", "production qualification", + "production PostgreSQL/custody", "independent human onboarding"]}); + if let Some(directory) = std::env::var_os("AUTHS_QUALIFICATION_SIMULATION_OUTPUT") { + let directory = std::path::PathBuf::from(directory); + std::fs::create_dir_all(&directory).expect("report directory"); + std::fs::write( + directory.join(format!("{}.json", family.name())), + serde_json::to_vec_pretty(&report).expect("report"), + ) + .expect("write report"); + } +} + +/// Runs each lifecycle against real durable claims, with both original and +/// fresh proof commitments. A lost response or response-record crash must +/// use only recovery the recipe's derived capability permits: Airtable's +/// verified locator and echo can re-observe; Stripe needs its response locator. +async fn lifecycle( + family: Family, + provider: &OracleProvider

, + recording: &Arc, + store: &mut TestAttempts, + ambiguous: bool, +) -> Vec { + let recipe = family.recipe(); + let observer = GatewayObserver::from_test_seed(OBSERVER_SEED); + let args = family.arguments("qualification-1"); + let command = family.command(&recipe, &args, ORIGINAL); + let attempts = GatewayAttempts::new(recording.clone()); + let mut first = TestIo::new(provider, command.clone()); + first.recipe = Some(&recipe); + let result = run(&attempts, &recipe, &observer, &first).await; + assert_eq!(provider.checked.load(Ordering::SeqCst), 1); + if ambiguous { + assert!(matches!(result, GatewaySubmitResult::Unknown)); + } else { + assert!( + matches!(result, GatewaySubmitResult::ObservedByProvider { .. }), + "{result:?}" + ); + } + let mut cases = vec![measurement( + if ambiguous { + "ambiguous-write" + } else { + "exact-write-and-read-back" + }, + &result, + first.leases(), + provider.inner.entries(), + )]; + for (name, commitment) in [ + ("proof-replay", ORIGINAL), + ("fresh-challenge-replay", FRESH), + ("restart-replay", FRESH), + ] { + if name == "restart-replay" { + store.restart(); + } + let attempts = if name == "restart-replay" { + store.attempts() + } else { + &attempts + }; + let mut io = TestIo::new(provider, family.command(&recipe, &args, commitment)); + io.recipe = Some(&recipe); + let before = provider.checked.load(Ordering::SeqCst); + let entries_before = provider.inner.entries(); + let result = run(attempts, &recipe, &observer, &io).await; + let recovery = ambiguous && matches!(family, Family::Airtable) && commitment == ORIGINAL; + if recovery { + assert!( + matches!(result, GatewaySubmitResult::ObservedByProvider { .. }), + "{} {name} ambiguous={ambiguous}: {result:?}", + family.name() + ); + } else { + assert!(!matches!( + result, + GatewaySubmitResult::ObservedByProvider { .. } + )); + } + assert_eq!( + io.leases(), + usize::from(recovery), + "{name}: only declared read-back recovery leases" + ); + assert_eq!( + provider.checked.load(Ordering::SeqCst), + before, + "{name}: no second write" + ); + cases.push(measurement( + name, + &result, + io.leases(), + provider.inner.entries() - entries_before, + )); + } + cases +} + +async fn race(family: Family, provider: &OracleProvider

) -> Measurement { + let recipe = family.recipe(); + let observer = GatewayObserver::from_test_seed(OBSERVER_SEED); + let store = TestAttempts::open(Backend::File); + let other_store = store.reopen(); + let args = family.arguments("qualification-1"); + let mut first = TestIo::new(provider, family.command(&recipe, &args, ORIGINAL)); + let mut second = TestIo::new(provider, family.command(&recipe, &args, ORIGINAL)); + first.recipe = Some(&recipe); + second.recipe = Some(&recipe); + let (left, right) = tokio::join!( + run(store.attempts(), &recipe, &observer, &first), + run(&other_store, &recipe, &observer, &second) + ); + assert_eq!( + provider.checked.load(Ordering::SeqCst), + 1, + "two store handles: one write" + ); + let observed = [&left, &right] + .into_iter() + .filter(|result| matches!(result, GatewaySubmitResult::ObservedByProvider { .. })) + .count(); + assert_eq!(observed, 1, "only the winning action is observed"); + let leases = first.leases() + second.leases(); + assert_eq!(leases, 2, "one write lease and one read-back lease"); + Measurement { + case: "two-instance-race".to_owned(), + verdict: "one-authorized-entry".to_owned(), + credential_leases: leases, + provider_entries: provider.inner.entries(), + confirmed_by_read_back: observed, + } +} + +async fn hostile( + family: Family, + provider: &OracleProvider

, +) -> Vec { + let recipe = family.recipe(); + let observer = GatewayObserver::from_test_seed(OBSERVER_SEED); + let store = TestAttempts::open(Backend::File); + let target = match family { + Family::Stripe => "payment_intent", + Family::Airtable => "record_id", + }; + let target_max = match family { + Family::Stripe => 255, + Family::Airtable => 43, + }; + let mut measured = Vec::new(); + for name in [ + "missing-target", + "overlong-target", + "wrong-target-type", + "invalid-value", + "unknown-field", + ] { + let mut args = family.arguments("hostile-1"); + match name { + "missing-target" => { + args.remove(target); + } + "overlong-target" => { + args.insert(target.into(), json!("a".repeat(target_max + 1))); + } + "wrong-target-type" => { + args.insert(target.into(), json!(true)); + } + "invalid-value" => match family { + Family::Stripe => { + args.insert("amount".into(), json!(100_000_000)); + } + Family::Airtable => { + args.insert("replacement".into(), json!("Rejected")); + } + }, + "unknown-field" => { + args.insert("provider_token".into(), json!("synthetic-untrusted-field")); + } + _ => unreachable!(), + } + let mut io = TestIo::answering(provider, family.admission(&recipe, &args, ORIGINAL)); + io.recipe = Some(&recipe); + let result = run(store.attempts(), &recipe, &observer, &io).await; + assert!( + matches!(result, GatewaySubmitResult::NotEntered { .. }), + "{name}: {result:?}" + ); + assert_eq!(io.leases(), 0, "{name}: refused before lease"); + assert_eq!( + provider.checked.load(Ordering::SeqCst), + 0, + "{name}: refused before provider" + ); + assert_eq!(provider.inner.entries(), 0, "{name}: provider witness"); + measured.push(measurement( + name, + &result, + io.leases(), + provider.inner.entries(), + )); + } + measured +} + +#[tokio::test] +async fn stripe_qualification_simulation() { + let family = Family::Stripe; + let recipe = family.recipe(); + let mut cases = Vec::new(); + let mut defaults = corpus(SCENARIOS)["defaults"]["stripe"]["responses"].clone(); + defaults["GET /v1/balance"] = json!({"status": 200, + "headers": {"Stripe-Version": STRIPE_VERSION}, "body": {"livemode": false}}); + for mode in ["respond", "timeout-after-send", "crash-after-write"] { + let mut store = TestAttempts::open(Backend::File); + let recording = RecordingStore::new(store.raw()); + if mode == "crash-after-write" { + recording.lose_response_record.store(true, Ordering::SeqCst); + } + let provider = OracleProvider { + inner: TableProvider::new( + &recipe, + &defaults, + if mode == "timeout-after-send" { + mode + } else { + "respond" + }, + ), + expected: family.oracle("qualification-1", &ORIGINAL), + checked: AtomicUsize::new(0), + }; + let mut measured = + lifecycle(family, &provider, &recording, &mut store, mode != "respond").await; + assert_eq!(provider.inner.writes(), 1); + for case in &mut measured { + case.case = format!("{mode}/{}", case.case); + } + cases.extend(measured); + } + let provider = OracleProvider { + inner: TableProvider::new(&recipe, &defaults, "respond"), + expected: family.oracle("qualification-1", &ORIGINAL), + checked: AtomicUsize::new(0), + }; + cases.extend(hostile(family, &provider).await); + cases.push(race(family, &provider).await); + publish(family, &recipe, &cases); +} + +#[tokio::test] +async fn airtable_qualification_simulation() { + let family = Family::Airtable; + let recipe = family.recipe(); + let mut cases = Vec::new(); + for (label, delivery) in [ + ("respond", Delivery::Respond), + ("timeout-after-send", Delivery::TimeoutAfterApplying), + ("crash-after-write", Delivery::Respond), + ] { + let mut store = TestAttempts::open(Backend::File); + let recording = RecordingStore::new(store.raw()); + if label == "crash-after-write" { + recording.lose_response_record.store(true, Ordering::SeqCst); + } + let provider = OracleProvider { + inner: RecordProvider::new(delivery, Reading::Faithful), + expected: family.oracle("qualification-1", &ORIGINAL), + checked: AtomicUsize::new(0), + }; + let mut measured = lifecycle( + family, + &provider, + &recording, + &mut store, + label != "respond", + ) + .await; + assert_eq!(provider.inner.writes(), 1); + for case in &mut measured { + case.case = format!("{label}/{}", case.case); + } + cases.extend(measured); + } + let provider = OracleProvider { + inner: RecordProvider::new(Delivery::Respond, Reading::Faithful), + expected: family.oracle("qualification-1", &ORIGINAL), + checked: AtomicUsize::new(0), + }; + cases.extend(hostile(family, &provider).await); + cases.push(race(family, &provider).await); + publish(family, &recipe, &cases); +} diff --git a/product/runtime/auths-gateway/src/qualification_tests.rs b/product/runtime/auths-gateway/src/qualification_tests.rs index 09488f61c..1eddc9091 100644 --- a/product/runtime/auths-gateway/src/qualification_tests.rs +++ b/product/runtime/auths-gateway/src/qualification_tests.rs @@ -84,6 +84,10 @@ fn required( async fn host_with(gate: &Arc) -> (Installation, ()) { let mut installation = installation(8).await; + #[cfg(feature = "loopback-provider")] + { + installation.first.engine = installation.first.engine.with_loopback_provider(9); + } installation .first .engine @@ -113,6 +117,163 @@ async fn an_engine_without_a_configured_gate_leases_nothing() { assert_eq!(installation.first.leases.load(Ordering::SeqCst), 0); } +/// Rehearses the first ceremony under fresh ephemeral trust. The signed +/// records are deliberately the issuance testkit's placeholder records; +/// their excluded claim says they stand for no provider run. Family driver +/// measurements are separate artifacts, never substituted for this corpus. +#[tokio::test] +async fn operator_bootstrap_qualification_simulation() { + use auths_recipe_qualification::{QualificationRootId, QualificationSignerId}; + use auths_recipe_qualification_issuance::{ + CertificateRequest, ReleaseSigner, RootSigner, SigningSeed, + }; + + let root_seed = SigningSeed::generate().expect("disposable root"); + let signer_seed = SigningSeed::generate().expect("disposable release signer"); + let root = RootSigner::create( + &root_seed, + QualificationRootId::parse("simulation-root").expect("root ID"), + ) + .expect("root"); + let certificate = root + .certify(CertificateRequest { + signer_id: QualificationSignerId::parse("simulation-signer").expect("signer ID"), + public_key_b64: signer_seed.public_key(), + issued_at: NOW - HOUR, + not_before: NOW - HOUR, + not_after: NOW + 24 * HOUR, + }) + .expect("certificate"); + let signer = ReleaseSigner::open(&signer_seed, certificate).expect("signer"); + let proposals = [ + proposal(1, &tuple_for("simulation-stripe-refund-v1")), + proposal(2, &tuple_for("simulation-airtable-update-v1")), + ]; + let attestations: Vec<_> = proposals + .iter() + .map(|proposal| { + signer + .attest(proposal, NOW, NOW, NOW + 12 * HOUR) + .expect("attestation") + }) + .collect(); + let listed: Vec<_> = proposals + .iter() + .zip(&attestations) + .map(|(proposal, attestation)| (proposal.record(), attestation)) + .collect(); + let index = signer.index(NOW, &listed).expect("signed index"); + let list = root + .revoke(1, NOW - HOUR, NOW + 12 * HOUR, Vec::new(), Vec::new()) + .expect("list"); + let signed = QualificationBundle { + signer_certificate: signer.certificate().canonical_bytes().to_vec(), + revocation_list: list.canonical_bytes().to_vec(), + release_index: index.canonical_bytes().to_vec(), + records: proposals + .iter() + .map(|proposal| proposal.record().canonical_bytes().to_vec()) + .collect(), + attestations: attestations + .iter() + .map(|attestation| attestation.canonical_bytes().to_vec()) + .collect(), + }; + let clock = Arc::new(FixedClock::at(NOW)); + let mut measurements = Vec::new(); + for closed in &proposals { + let deployment = closed.record().body().tuple.clone(); + let gate = required(Some(root.trust_root().clone()), deployment.clone(), &clock); + let (installation, ()) = host_with(&gate).await; + let host = &installation.first; + assert_eq!( + refusal(host).await.as_deref(), + Some("gateway.qualification.unavailable") + ); + let mut unsigned = signed.clone(); + unsigned.attestations.clear(); + assert!(gate.load(&unsigned)); + assert_eq!( + refusal(host).await.as_deref(), + Some("gateway.qualification.missing") + ); + assert_eq!(host.leases.load(Ordering::SeqCst), 0); + let before_signature_leases = host.leases.load(Ordering::SeqCst); + assert!(gate.load(&signed)); + assert_eq!(refusal(host).await, None); + assert_eq!(host.leases.load(Ordering::SeqCst), 1); + let after_verified_import_leases = host.leases.load(Ordering::SeqCst); + let mut forged = signed.clone(); + let position = forged.attestations[0].len() / 2; + forged.attestations[0][position] ^= 1; + assert!(gate.load(&forged)); + // The untouched second record may remain qualified. A corrupt member + // cannot enable the record whose attestation was changed. + if deployment.recipe_family == proposals[0].record().body().tuple.recipe_family { + assert!(refusal(host).await.is_some()); + assert_eq!(host.leases.load(Ordering::SeqCst), 1); + } + assert!(gate.load(&signed)); + clock.set(NOW + 13 * HOUR); + assert!(refusal(host).await.is_some()); + clock.set(NOW); + let no_root = required(None, deployment.clone(), &clock); + assert!(!no_root.load(&signed)); + let (untrusted, ()) = host_with(&no_root).await; + assert_eq!( + refusal(&untrusted.first).await.as_deref(), + Some("gateway.qualification.unavailable") + ); + assert_eq!(untrusted.first.leases.load(Ordering::SeqCst), 0); + measurements.push(json!({"family": deployment.recipe_family, + "before_signature_leases": before_signature_leases, + "after_verified_import_leases": after_verified_import_leases, + "unsigned_refused": true, "expired_refused": true, "missing_root_refused": true})); + } + if let Some(directory) = std::env::var_os("AUTHS_QUALIFICATION_SIMULATION_OUTPUT") { + let directory = std::path::PathBuf::from(directory).join("bootstrap"); + std::fs::create_dir_all(&directory).expect("public output directory"); + std::fs::write( + directory.join("root.json"), + root.trust_root().canonical_bytes(), + ) + .expect("public root"); + for (name, bytes) in [ + ("signer-certificate.json", &signed.signer_certificate), + ("revocation-list.json", &signed.revocation_list), + ("release-index.json", &signed.release_index), + ] { + std::fs::write(directory.join(name), bytes).expect("public artifact"); + } + for (position, closed) in proposals.iter().enumerate() { + std::fs::write( + directory.join(format!("record-{position}.json")), + closed.record().canonical_bytes(), + ) + .expect("record"); + std::fs::write( + directory.join(format!("attestation-{position}.json")), + &signed.attestations[position], + ) + .expect("attestation"); + for (member, evidence) in closed.evidence().iter().enumerate() { + std::fs::write( + directory.join(format!("fixture-evidence-{position}-{member}.json")), + evidence.canonical_bytes(), + ) + .expect("explicit fixture"); + } + } + std::fs::write(directory.join("simulation.json"), serde_json::to_vec_pretty(&json!({ + "schema": "auths.qualification-bootstrap-simulation/1", "simulation": true, + "stable_launch_ready": false, "ephemeral_keys_destroyed_on_return": true, + "evidence_kind": "explicit placeholder fixtures: no provider-run claim", + "measurements": measurements, "production_root_changed": false, + "excluded_claims": ["production qualification", "live provider acceptance", "human review"] + })).expect("report")).expect("write report"); + } +} + #[tokio::test] async fn a_qualified_deployment_leases_and_each_fault_refuses_before_the_lease() { let release = TestRelease::new(NOW); diff --git a/product/runtime/auths-gateway/src/scenario_tests.rs b/product/runtime/auths-gateway/src/scenario_tests.rs index 1bcf85f4b..2101cc401 100644 --- a/product/runtime/auths-gateway/src/scenario_tests.rs +++ b/product/runtime/auths-gateway/src/scenario_tests.rs @@ -46,6 +46,9 @@ const FRESH: [u8; 32] = [0x22; 32]; const RECORD: &str = "recTEST0000000001"; const FOREIGN: &str = "auths-e1-0000000000000000000000000000000000000000000000000000000000000000"; +#[path = "qualification_simulation.rs"] +mod qualification_simulation; + fn corpus(name: &str) -> Value { let path = std::path::Path::new(env!("CARGO_MANIFEST_DIR")) .join("../../../bindings/fixtures/gateway") diff --git a/qualification/README.md b/qualification/README.md index db04b6ff0..d3adbf80a 100644 --- a/qualification/README.md +++ b/qualification/README.md @@ -6,7 +6,9 @@ The specification is §7 and §8; the run is described in [the protected-run plan](../docs/plans/RECIPE_QUALIFICATION_PROTECTED_RUN_PLAN.md). -No family is qualified and none is present here yet. Proposed provider decisions +No production family is qualified. The owner-directed disposable bootstrap and +Stripe/Airtable harnesses are in [simulation/](simulation/README.md); they run +without external credentials and publish explicitly simulated evidence. Proposed provider decisions are [ADR 0014](../docs/adr/0014-stripe-refund-recipe-qualification.md) and [ADR 0015](../docs/adr/0015-airtable-record-update-recipe-qualification.md). They explicitly remain proposed until their executable corpora and protected @@ -34,15 +36,23 @@ binding it into the final manifest. An edited readiness value, another commit, drifted target or missing projection cannot become a signed launch claim. The manifest contract requires exactly one digest-bound projection. -## First-run prerequisites still unresolved +## Bootstrap rehearsal and production evidence + +The owner assigned the agent an independent operator simulation, including the +first signing ceremony and both provider harnesses. `simulation/run.py` performs +that work with fresh in-memory signing keys, explicit placeholder trust-machine +records and measured provider-driver reports. It imports signed fixtures under +required test trust and measures real engine credential-store calls. No private +keys or production trust inputs are written. This work does not wait for a human +ceremony or real provider credentials. The current production gateway refuses every lease without a current exact-tuple attestation. The protected workflow gathers live effects before it can sign that attestation. Therefore its first qualification cannot bootstrap itself. A development installation or `testkit-production-unqualified` executable changes the target or shipped bytes and cannot establish the required production claim. -An owner-reviewed authority design must resolve this cycle while preserving the -production lease gate; no bypass has been implemented. +That real-production authority question remains separate from the requested +simulation; the shipping lease gate has no bypass. The current executable corpus also fixes exact request/evidence digests before running, while disposable live resource identifiers may be created during setup. @@ -50,9 +60,10 @@ Family harnesses need a reviewed, bounded resource-binding and oracle expansion before executing their cases. Copying the candidate's observed digest into an expected result would invalidate the differential evidence. -The offline trust-root ceremony, protected release signer and two provider -credentials remain external prerequisites. Docker supports the labeled local -operator simulation; it supplies none of these live qualification inputs. +The rehearsal fixes synthetic resource IDs before execution, so its independent +oracles do not copy digests observed from candidate output. The offline production +root, protected signer and provider credentials remain prerequisites for real +protected evidence, not for the simulation. A `production-readiness` case is additionally required for each stable launch claim. It runs only in the protected live phase against PostgreSQL and diff --git a/qualification/simulation/README.md b/qualification/simulation/README.md new file mode 100644 index 000000000..b4abcd65b --- /dev/null +++ b/qualification/simulation/README.md @@ -0,0 +1,34 @@ +# Independent operator rehearsal + +The owner requested simulated bootstrap and provider qualification. Run it: + +```sh +python3 qualification/simulation/run.py --out /tmp/auths-qualification-rehearsal +``` + +Use a fresh output directory. No provider credential, signing key file or +production environment is needed. The same run is a required job in recipe +qualification CI, and uploads its public reports and signing artifacts. + +The Stripe refund and Airtable record update harnesses compile the maintained +recipes and drive the native submission driver over durable file claims and +mutable counting providers. Independent vertical wire oracles check the actual +method, URL, headers, body and idempotency commitment before each write. Reports +measure credential leases, write entries and fresh read-back confirmations. +They exercise exact writes, original/fresh proof replay, reopening the store, +lost responses, and crashes before the response record is durable. + +The first ceremony generates an ephemeral root and release signer in memory, +certifies the signer, signs two explicitly placeholder records, constructs the +index and revocation list, and imports them into the native required gate. +Actual engine credential-store counters show zero leases before signing and +one after verified import. Unsigned, expired and missing-root inputs refuse. +The placeholder records explicitly exclude every provider-run claim; they test +the trust transition, while provider measurements are separate artifacts. + +These are simulation artifacts. They cannot enable the shipping gateway: +its pinned root is unchanged, the tuples use development stores, and the +bootstrap records name placeholder provenance. No file is installed under +`qualification/trust` or `qualification/families`, and readiness remains false. +Native proof/socket and installed-package journeys remain separate SDK workflow +checks. This rehearsal does not claim the full protected production corpus. diff --git a/qualification/simulation/run.py b/qualification/simulation/run.py new file mode 100644 index 000000000..e4618476e --- /dev/null +++ b/qualification/simulation/run.py @@ -0,0 +1,101 @@ +#!/usr/bin/env python3 +"""Run native qualification rehearsals; publish public simulation artifacts only.""" + +from __future__ import annotations + +import argparse +import hashlib +import json +import os +from pathlib import Path +import subprocess +import tempfile +import time + +REPOSITORY = Path(__file__).resolve().parents[2] +REPORTS = ( + "stripe-refund-v1.json", + "airtable-record-update-v1.json", + "bootstrap/simulation.json", +) + + +def main() -> None: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--cargo", default="cargo") + parser.add_argument("--out", type=Path, required=True) + args = parser.parse_args() + output = args.out.resolve() + # Public rehearsal outputs must never enter the production trust or family + # directories that the protected signing workflow consumes. + if output == REPOSITORY or any( + output.is_relative_to(REPOSITORY / "qualification" / name) + for name in ("trust", "families") + ): + parser.error("simulation output overlaps production inputs") + output.mkdir(parents=True, exist_ok=True) + if any(output.iterdir()): + parser.error("use a new empty simulation output directory") + source_commit = subprocess.check_output( + ["git", "rev-parse", "HEAD"], cwd=REPOSITORY, text=True + ).strip() + source_dirty = bool(subprocess.check_output( + ["git", "status", "--porcelain", "--untracked-files=no"], cwd=REPOSITORY + )) + # Provider and signing credentials are not needed and do not reach tests. + environment = { + key: value for key, value in os.environ.items() + if key in {"PATH", "HOME", "CARGO_HOME", "RUSTUP_HOME", "CARGO_TARGET_DIR", "TMPDIR"} + } + environment["AUTHS_QUALIFICATION_SIMULATION_OUTPUT"] = str(output) + started = time.monotonic() + with tempfile.TemporaryFile() as log: + result = subprocess.run([ + args.cargo, "test", "--locked", "-p", "auths-gateway", + "--features", "loopback-provider", "--lib", "qualification_simulation", + "--", "--nocapture", + ], cwd=REPOSITORY, env=environment, stdout=log, stderr=subprocess.STDOUT, + timeout=1800, check=False) + if result.returncode: + log.seek(0, os.SEEK_END) + log.seek(max(0, log.tell() - 8192)) + raise SystemExit(log.read().decode("utf-8", errors="replace")) + summaries = [] + for name in REPORTS: + path = output / name + if path.is_symlink() or path.stat().st_size > 1_048_576: + raise SystemExit("invalid simulation report") + report = json.loads(path.read_bytes()) + if report.get("simulation") is not True or report.get("stable_launch_ready") is not False: + raise SystemExit("a rehearsal cannot publish production readiness") + summaries.append(report) + # The bootstrap artifacts are synthetic trust-machine fixtures. Their + # own signed records explicitly exclude every provider-run claim. + for path in sorted((output / "bootstrap").glob("record-*.json")): + record = json.loads(path.read_bytes()) + if record["excluded_claims"] != ["everything: this record stands for no run"]: + raise SystemExit("bootstrap fixture scope changed") + public_members = [] + for path in sorted(output.rglob("*.json")): + if path.is_symlink() or path.stat().st_size > 1_048_576: + raise SystemExit("invalid public artifact") + public_members.append({"path": str(path.relative_to(output)), + "sha256": hashlib.sha256(path.read_bytes()).hexdigest()}) + manifest = { + "schema": "auths.qualification-simulation-run/1", + "simulation": True, "stable_launch_ready": False, + "source_commit": source_commit, "source_dirty": source_dirty, + "seconds": round(time.monotonic() - started, 3), + "families": [summary.get("family") for summary in summaries[:2]], + "provider_case_count": sum(len(summary["cases"]) for summary in summaries[:2]), + "public_artifacts": public_members, + "keys": "generated in memory and zeroized; no private key files", + "excluded_claims": ["protected live evidence", "production qualification", "human acceptance"], + } + (output / "run.json").write_text(json.dumps(manifest, indent=2) + "\n") + print(json.dumps({"simulation": True, "provider_cases": manifest["provider_case_count"], + "families": manifest["families"], "seconds": manifest["seconds"], "out": str(output)})) + + +if __name__ == "__main__": + main() From 90a63ae94c09b43991ae8fa1a4244a4cab2ac183 Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 00:13:01 +0100 Subject: [PATCH 039/108] Package source-free qualification rehearsal and measure recovery races --- .github/workflows/recipe-qualification.yml | 23 +++++++- docs/PROGRAM_BOARD.md | 3 ++ ...gateway-polish-and-recipe-qualification.md | 6 +++ .../auths-gateway/semantic-closure.json | 2 +- .../src/qualification_simulation.rs | 31 +++++++++-- .../auths-gateway/src/qualification_tests.rs | 8 ++- .../auths-gateway/src/semantic_closure.rs | 2 +- qualification/simulation/Dockerfile | 3 ++ qualification/simulation/README.md | 13 +++++ qualification/simulation/pack.py | 51 ++++++++++++++++++ qualification/simulation/run.py | 52 +++++++++++++++---- 11 files changed, 172 insertions(+), 22 deletions(-) create mode 100644 qualification/simulation/Dockerfile create mode 100644 qualification/simulation/pack.py diff --git a/.github/workflows/recipe-qualification.yml b/.github/workflows/recipe-qualification.yml index 8e4eb8a3f..a442a6083 100644 --- a/.github/workflows/recipe-qualification.yml +++ b/.github/workflows/recipe-qualification.yml @@ -43,11 +43,30 @@ jobs: - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 with: python-version: "3.12" - - run: python qualification/simulation/run.py --out target/qualification-simulation + - name: Build the portable simulation harness + run: | + mkdir -p target + cargo test --locked -p auths-gateway --features loopback-provider --lib --no-run --message-format=json > target/qualification-harness-build.jsonl + python qualification/simulation/pack.py --build-report target/qualification-harness-build.jsonl --out target/qualification-candidate-kit + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 + with: + name: qualification-simulation-kit-${{ github.run_id }}-${{ github.run_attempt }} + path: target/qualification-candidate-kit + if-no-files-found: error + retention-days: 30 + - name: Run with no checkout, credentials or network + run: | + docker build -t auths-qualification-simulation qualification/simulation + mkdir -p target/qualification-simulation-reports + docker run --rm --network none \ + --mount type=bind,src="$PWD/target/qualification-candidate-kit",dst=/candidate,readonly \ + --mount type=bind,src="$PWD/target/qualification-simulation-reports",dst=/reports \ + auths-qualification-simulation \ + python3 /candidate/run.py --candidate-kit /candidate --out /reports/run - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: name: qualification-simulation-${{ github.run_id }}-${{ github.run_attempt }} - path: target/qualification-simulation + path: target/qualification-simulation-reports/run if-no-files-found: error retention-days: 30 diff --git a/docs/PROGRAM_BOARD.md b/docs/PROGRAM_BOARD.md index 751f0bd2c..e4d4f0dfd 100644 --- a/docs/PROGRAM_BOARD.md +++ b/docs/PROGRAM_BOARD.md @@ -451,3 +451,6 @@ hostile input behavior. The Airtable ADR now correctly names its derived linked read-back recovery; Stripe cannot recover a response-provided locator that was lost. Signing fixtures explicitly exclude provider-run claims. Production trust and readiness remain unchanged; real users remain the owner's offline work. +The local expanded rehearsal passed 36 provider cases and the two-family +ceremony. Hosted kit verification is pending; the kit is designed to run in +Docker with no checkout or network mounted. diff --git a/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md b/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md index d5f2426ec..28dc47743 100644 --- a/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md +++ b/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md @@ -1681,6 +1681,12 @@ independent wire oracles and mutable doubles. The production pinned root stays unchanged and stable launch readiness stays false. The rehearsal is a maintained CI job and needs no external credentials. +The local rehearsal passed 36 measured provider cases (18 per family), plus +the disposable two-family signing/import ceremony. Each race entered one +write; Airtable additionally used a read-only reconciliation lease. The +candidate kit embeds its fixtures and is run in Docker without checkout, +credentials or network. Hosted verification of that packaged run is pending. + The protected production run still has a first-attestation cycle: production leases require qualification before the live effects needed to issue it. A reviewed authority design must resolve this without bypassing the shipped diff --git a/product/runtime/auths-gateway/semantic-closure.json b/product/runtime/auths-gateway/semantic-closure.json index 4b833f367..c3dbcc3eb 100644 --- a/product/runtime/auths-gateway/semantic-closure.json +++ b/product/runtime/auths-gateway/semantic-closure.json @@ -1 +1 @@ -{"files":[{"path":"Cargo.lock","sha256":"0e75e2fdef44e79e57797ac6661295ae58ddb8de4a1990a6fd22ce6c54f78604"},{"path":"Cargo.toml","sha256":"6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24"},{"path":"core/adapters/auths-did-keri/Cargo.toml","sha256":"86ba3e3f9a0a70d970568bfb3113b7ba7bbdd81c3eebbb52743dd574a0c0ecaa"},{"path":"core/adapters/auths-did-keri/src/lib.rs","sha256":"a75674842f8a7142004369ccd206ab43e476459293f0ff4bed4d4e659031b3e3"},{"path":"core/adapters/auths-did-key/Cargo.toml","sha256":"d5a3ae07ecde83f91eed4c3785051dd0f44eab6c891754f3309b6b40596707d7"},{"path":"core/adapters/auths-did-key/src/lib.rs","sha256":"b76a3f4528a725df53cfa9242e6e414e1d26caa48468aaed497e28b121f4497c"},{"path":"core/adapters/auths-raw-key/Cargo.toml","sha256":"f49616bc18c19e6aaa7e6a02ccebcdb9f5c1422c1278ef9869e0dbf22ceda7be"},{"path":"core/adapters/auths-raw-key/src/lib.rs","sha256":"45eec1b295dac3bed65cd79c942870b926b06b3f5d38eaebaeb6140ac69315fa"},{"path":"core/crates/auths-algebra-kernel/Cargo.toml","sha256":"0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba"},{"path":"core/crates/auths-algebra-kernel/src/generated.rs","sha256":"ae4bcbef42a408c7ffa0c6a74a42f7de177a6f14479e51d205acf830bda05960"},{"path":"core/crates/auths-algebra-kernel/src/lib.rs","sha256":"6654667eeb9b353d6648954c9fd2e8838462a82ce6b2803eb49e1366892c68c6"},{"path":"core/crates/auths-assurance/Cargo.toml","sha256":"afcb12a97ddd09d7a264b9ecd3fcaefc865ff2c9b4539ee85b00883420ba333a"},{"path":"core/crates/auths-assurance/src/lib.rs","sha256":"0fb2ec844d674b25a9e20b1601452c89c2454901fa506adfa9bb38ef9a7fa213"},{"path":"core/crates/auths-author/Cargo.toml","sha256":"1e6f0e3bc079ddb558decf0db26b291c6e72fc47327b6df1b7650d41689b215f"},{"path":"core/crates/auths-author/src/lib.rs","sha256":"e14475f2f49715a1869d5fa6b11ff1fbb72497e39097e09f833b0bae7e5b3f2b"},{"path":"core/crates/auths-author/src/observations.rs","sha256":"dda7d6bfa6f4bd7e95a480ca283c2c0e996f69c5c15cb0c7197af328131a7066"},{"path":"core/crates/auths-authority/Cargo.toml","sha256":"4f68212938029f79ebd857b4f3038494eb85d0163d49f07e51376715cf959815"},{"path":"core/crates/auths-authority/src/lib.rs","sha256":"da88d5194de4e17449e69972c0fb042afa3c39798a8f570f30771e77c384f1eb"},{"path":"core/crates/auths-codec/Cargo.toml","sha256":"e20e51826e17814effd9d8925d18d5fbdd6c0d37bf50231e743ec2611314722c"},{"path":"core/crates/auths-codec/src/approval.rs","sha256":"fbff43bf4d57f69f8b7738a8647751cde75c5a932dee65d924a1fe9c7202f91f"},{"path":"core/crates/auths-codec/src/bounded_policy.rs","sha256":"d21f6728be2d8a04b6d94921f2b683f7e61cbb42e0ac6866f1c88a49caa534c3"},{"path":"core/crates/auths-codec/src/decode.rs","sha256":"ba2999584cdf53b1b517ecb9c7ea50d39efee17c666a9a38e2ad1ac94379f778"},{"path":"core/crates/auths-codec/src/encode.rs","sha256":"8491192053e2e15d62b4d2a491de22405b7487ead69ab6f6bca40669ce7ca5f7"},{"path":"core/crates/auths-codec/src/error.rs","sha256":"fecb0737c16deb42d859f1dc7727c698438d9ac12064fd99e0024629642c390c"},{"path":"core/crates/auths-codec/src/hash.rs","sha256":"f88e111f1dbb2cef6b7b5e9c948cb45ff92e366710c8a5f5c636138aa748479e"},{"path":"core/crates/auths-codec/src/lib.rs","sha256":"3b0e5c94c6f34f750b88a9333e1d5c8145746d845d3a23e0d2f61807cf592ea7"},{"path":"core/crates/auths-codec/src/observation.rs","sha256":"38328b0c71ff97a4196eeade8b4faa889527ff1f80bb168468bcd49082a3987e"},{"path":"core/crates/auths-composition/Cargo.toml","sha256":"331e13025eb82588b5269ed3975929eb41c823d588c49e4c296273d85c6fe80e"},{"path":"core/crates/auths-composition/src/lib.rs","sha256":"e42e3b0b6a9985b73c533aeb23799c638979aa27a9ce7d0f10a8d60340570fb1"},{"path":"core/crates/auths-model/Cargo.toml","sha256":"565c15302b0cc9270db1e28efa3862804846850ba933cc17aea8abcec4a65987"},{"path":"core/crates/auths-model/src/approval.rs","sha256":"54cf44a9ef747ec21546a4086aecfb130bc7803b0d646430e6082df51e6e305f"},{"path":"core/crates/auths-model/src/bounded.rs","sha256":"f90496abc0a06c028b4d850af6ddab7d850bfafeaa3d042f1b1246a41d8bbbc9"},{"path":"core/crates/auths-model/src/bounded_policy.rs","sha256":"306a8f049cc7cfc7635fe0e4de47eb7813eed63d3c14c3be2b51586aa4eea450"},{"path":"core/crates/auths-model/src/lib.rs","sha256":"e7cfe6bb9574c6b016aa63e70658c31e0b90903ec6479a49f4a2ceb64f5bad97"},{"path":"core/crates/auths-model/src/observation.rs","sha256":"b3ed3e3cc090afca2896a7d3de7988afccc1ee1ea0ebd91b51a8bc0f20ad8dbb"},{"path":"core/crates/auths-multikey/Cargo.toml","sha256":"858756c1197befcada06134742bffe8d58cf674cadd6c046bf710570e96efaf2"},{"path":"core/crates/auths-multikey/src/lib.rs","sha256":"f5177fffb11e40eeaaa665ba886c541fc1f24d5eacdd6983fb03dc20148733f0"},{"path":"core/crates/auths-ports/Cargo.toml","sha256":"596a9b0f5af3717c16a6d13f7054d8a106bcd9f01f5f72c2235dd2afcf0ab16c"},{"path":"core/crates/auths-ports/src/binding.rs","sha256":"a16c012d40aa4249e3ec54372b9611006d0bfe8c7dc3c741911c2194ad17736d"},{"path":"core/crates/auths-ports/src/diagnostics.rs","sha256":"aa596572503b5a65a918bb2ff38281c144ff53821ee914e9325c852828d852df"},{"path":"core/crates/auths-ports/src/lib.rs","sha256":"8da1debf86f9532df0660155d04298beb1ba3a1204508f8586e2e67cd2fb3449"},{"path":"core/crates/auths-ports/src/path.rs","sha256":"b68fc547b4e4d97a60cbbc1cc1939fc6b34a8233b81f840bd396914a707e3ea1"},{"path":"core/crates/auths-raw-key-core/Cargo.toml","sha256":"98c0bc8527a537512e43a74dd6ba9658c6f0cdc16610cf938e3f9b43785d836d"},{"path":"core/crates/auths-raw-key-core/src/lib.rs","sha256":"98c0500c41697aae28708ad0bf970b9a97583d96a3d2c18d23e7fa351e0f7d12"},{"path":"core/crates/auths-registries/Cargo.toml","sha256":"590e49e58b0622d9d6274fea46796dcdb07dec9550eff295cce6a6427ffa51e2"},{"path":"core/crates/auths-registries/src/lib.rs","sha256":"450d3886d85ee333b7e046317fb5b47cde62483d5f3e41d46265e2caf4c373ec"},{"path":"core/crates/auths-registries/src/template.rs","sha256":"1224039dd2b3ce6fa8357613d8cafbae40400493da7176da202b9ade62fa05e4"},{"path":"core/crates/auths-signature-core/Cargo.toml","sha256":"6bee2230eb30af1be0bd5c2d57bd3e1903497a70028d47290d4ac6e9e0e8bca0"},{"path":"core/crates/auths-signature-core/src/lib.rs","sha256":"6e3f9311ded5e49ea50d445eb21e6d8fa12442aa4362a73e0cb6fda15b7cd865"},{"path":"core/crates/auths-signature/Cargo.toml","sha256":"7f7b5682466ba439d8c59579022cb61068cad9fb4bd2d73e1cc21327c902b450"},{"path":"core/crates/auths-signature/src/lib.rs","sha256":"b3d9ac4cc3ba0797b9e1c09f2d6ac05089b25dac4e285a5af28c0165b33d925b"},{"path":"core/crates/auths-verifier/Cargo.toml","sha256":"c43358e06a33324b41a8b93e5cc7279c55f7d21f1f6cfaa539a3fc7b4c27a38f"},{"path":"core/crates/auths-verifier/src/approval.rs","sha256":"c3cae6a49e169051eb555bb092b1069a4d422516d6a2114623a89e5f31ff923f"},{"path":"core/crates/auths-verifier/src/causal.rs","sha256":"9635230f33b13a263573d319ac8a1976addbcc07677514a43e3c7bf28dc04587"},{"path":"core/crates/auths-verifier/src/lib.rs","sha256":"f22dec38dfa47ced8da4f605390da8453273bee1da010f57fd1fdfcb10e0b389"},{"path":"core/crates/auths-verifier/src/observation.rs","sha256":"0bb07f06a0f9524c88427df1c972b1de8ba038a9eeeb15d3134c25125ae84b1e"},{"path":"core/crates/auths-verifier/src/trace.rs","sha256":"2213d72023a1d9e0413a2cf2c51c3dad9e04775d86033a0caaa9d29a8f0036f8"},{"path":"exchange/crates/auths-proof-exchange-model/Cargo.toml","sha256":"34b2db64f93a288e942b5a3918d28cdcbef906e0dc9074ce848018d3d5f7a1fa"},{"path":"exchange/crates/auths-proof-exchange-model/src/lib.rs","sha256":"49fac5aff2339d3a57c41cb8bb2a82852538e8f77ecc4b157c88e264ff31fb55"},{"path":"exchange/crates/auths-proof-exchange-port/Cargo.toml","sha256":"7ff660f1b7579dc570c791090aeb450404fbbf44c92781e289f5ccdde746d739"},{"path":"exchange/crates/auths-proof-exchange-port/src/lib.rs","sha256":"b408fb40c6432edc1facb3d8b3e9433a033f8dc73fe2e0ba5a88c972ca675021"},{"path":"product/config/auths-config/Cargo.toml","sha256":"e4b568ab9f6d84f7d7e6d66443fe825f360db9c27bc7c31d6ddc0647ba3ab304"},{"path":"product/config/auths-config/src/lib.rs","sha256":"fecf00ea65cef9018fda9af2063326d7065b869266d0d9e73a4f06816f1102cc"},{"path":"product/errors/auths-errors/Cargo.toml","sha256":"3b3a199b6460ba75bda84475bb5accd35e1485448a3981038db85bf4772dd350"},{"path":"product/errors/auths-errors/src/lib.rs","sha256":"7feeb9069fa4003f94f1f07c1c94619cf1c883e0dbaaf2187f04d0f742264bdd"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/Cargo.toml","sha256":"716f1f2a117d6d69d8effe9ee9057e24ba3502f20af6a602b06facb638cdabed"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/api.rs","sha256":"9ea61dd7ddd93282b073b98e453e6b75b26dc49689c04e9782435d06a3a09e48"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/clock.rs","sha256":"73f0a6e0f5903883329fa6683f5888288f759512ac69e5c87efd2b6b87f7d79f"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/http.rs","sha256":"14c1fce14e24c984b2a275563a29b6326fb08367922b6e8d37ba38b9cb81aa2b"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/identity.rs","sha256":"186de11230c8b33375951c4368609f8976bf9795f171af3fd7fac26207a94361"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs","sha256":"0b4617d044f5254a5ab22f5a2578f91cc025206a8c1845be39c1c56dcdf7a5df"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/names.rs","sha256":"41bb23572d6002e23ee103d6fe70ecd68764861c6f2e48a1c53af998270a4afa"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs","sha256":"39fed883f4802e68d3b41a68fea0aba0737810996b33d13577de70faba004c29"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/store.rs","sha256":"fc60ee9c49b2f4f063c449b4c78100c5c4872779e94ca168f796603b380ef6e4"},{"path":"product/integrations/auths-custody/Cargo.toml","sha256":"1e14034185ad1ec24a977fd5f41d0abee219606245c046ce2a82287fadef448b"},{"path":"product/integrations/auths-custody/src/conformance.rs","sha256":"8ed1afd58f18fc6becc268908aa6419c9aa404c79da0197963eb2599df44acf6"},{"path":"product/integrations/auths-custody/src/key.rs","sha256":"70cbb0fd21b6f5652157845a22c35be2d0f6c05b3d138fc4b9bb6dbdc3d81c40"},{"path":"product/integrations/auths-custody/src/lib.rs","sha256":"8ee593c1f59b0fd2126bdda9138026f5bc531beb64d4489a99785842e7b98b43"},{"path":"product/operations/auths-operations/Cargo.toml","sha256":"73dde1e914ba5e1386f8d49c0d730423cc72ae77ec44c6554a6a75cc8e8922b1"},{"path":"product/operations/auths-operations/src/explanation.rs","sha256":"b4a39bcbd5712cb9e735ee7deeb281f3fa6af5ddca973735bf3d87dce427ef11"},{"path":"product/operations/auths-operations/src/lib.rs","sha256":"3f401a56555113b98f57bca172a2660eaecedf76247b83a3fdbb089c133a29cd"},{"path":"product/operations/auths-operations/src/render/json.rs","sha256":"2ae042639960afee123730e945d373bc5dda1d2b3af20ae16c939a7e99b9e418"},{"path":"product/operations/auths-operations/src/render/mod.rs","sha256":"b3b7f6fe473f49227ace5a68bfc3d8dc14b5db8dd9888fd9e207070337b1b8bf"},{"path":"product/operations/auths-operations/src/render/text.rs","sha256":"f216cf3bdb00e264523271b16e7059535ac6b1aabf271cebd7935af155e4bfec"},{"path":"product/policy/auths-bounded-policy/Cargo.toml","sha256":"babd5d200923137ead71d8c2528f847cea323ce98da942a1320b054436612c47"},{"path":"product/policy/auths-bounded-policy/src/arithmetic.rs","sha256":"75e43c5d4eab8d1f71c1daf53839f5f9fe45a400afc1f63a30c6f55ce3632627"},{"path":"product/policy/auths-bounded-policy/src/commitment.rs","sha256":"c5706f2d583454e1a7f570f7ada138d4d864bef0205dfae7c1296774f396bb3f"},{"path":"product/policy/auths-bounded-policy/src/eligibility.rs","sha256":"c9acdfb793074e687fc36efad506be27dbd99ffbf40387bc66c8de39ef238432"},{"path":"product/policy/auths-bounded-policy/src/identifier.rs","sha256":"0006a32bae9eb16c4178cf797df418d2b0a781f2bc6474b741dc1a908141831c"},{"path":"product/policy/auths-bounded-policy/src/kernel.rs","sha256":"99187c28b161ac70bee1afed60711f7f645adb4d1671a01863f9849b369811d5"},{"path":"product/policy/auths-bounded-policy/src/lib.rs","sha256":"76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c"},{"path":"product/policy/auths-bounded-policy/src/receipt.rs","sha256":"3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad"},{"path":"product/policy/auths-bounded-policy/src/registry.rs","sha256":"4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0"},{"path":"product/profiles/auths-profile-api/Cargo.toml","sha256":"7ae85761f58625b5d678f961fd052eebf3e000ef565c7312e3ac857763c0017f"},{"path":"product/profiles/auths-profile-api/src/lib.rs","sha256":"a194b82b20bf8aa864c2334ef6c6aec30b2154ded972862252d5dcefa488ab95"},{"path":"product/profiles/auths-profile-mcp/Cargo.toml","sha256":"db264fc25242f7b7e4133cbe5782545b3107b406c87168ae072683cfb59eac66"},{"path":"product/profiles/auths-profile-mcp/src/arguments.rs","sha256":"a5de696586d507e2aee4a49fee99ef1ef4c51a2e46603f8838f1af6d9009833f"},{"path":"product/profiles/auths-profile-mcp/src/lib.rs","sha256":"d0f8b733a09ef8408336cdebc8948d6a5861012ce6878598b11be7084dfd4280"},{"path":"product/profiles/auths-profile-mcp/src/session.rs","sha256":"166c281fa66333388e4760d6098dad02d3359e1d5de4b8f93312c014f97abb03"},{"path":"product/qualification/auths-recipe-qualification/Cargo.toml","sha256":"b7b15b30b9a3d96d4f089d514266d3a892de6608d30707aa44be31cca89ca9fe"},{"path":"product/qualification/auths-recipe-qualification/src/canonical.rs","sha256":"30a9b50777f0dcb4b606abfee2467d5a975d9f6ad941ab6c13ca3df5b359f667"},{"path":"product/qualification/auths-recipe-qualification/src/closure.rs","sha256":"0ad6aee9bd981e2863fa725f209ec84031db2ff12f4c7ac3aaf5120f0bb86039"},{"path":"product/qualification/auths-recipe-qualification/src/error.rs","sha256":"52d5cf720a1e4579008fdda90a3ac2c31f0b8db57985f121f65e54b4da2b7dd1"},{"path":"product/qualification/auths-recipe-qualification/src/evidence.rs","sha256":"ba45a7409d67a8af26ab811af306412014557477a101ab2a8eb0faf8f2bd4b91"},{"path":"product/qualification/auths-recipe-qualification/src/ids.rs","sha256":"e81a906d571497ab2da753e1532d4443706410e0b75fdd59a7d2d788c7aec403"},{"path":"product/qualification/auths-recipe-qualification/src/launch.rs","sha256":"05b73fabb40d663466026b2bae5a9fd2681e1a3deaefa0f91811e6acfdd467fd"},{"path":"product/qualification/auths-recipe-qualification/src/lib.rs","sha256":"5c9cff04c8960df805a2f7656cf5e74932798e0db7648341e96ae7073a592404"},{"path":"product/qualification/auths-recipe-qualification/src/model.rs","sha256":"3484eb0ec287b23d4682ade7b1b0f8d1335985b3fb180f06fc28716076957d5f"},{"path":"product/qualification/auths-recipe-qualification/src/release.rs","sha256":"d816b53e2275e902c750ad03803061844e259e28560ab2d1c77e8a43981a4d6a"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/mod.rs","sha256":"7f15b68e05a04f202bcb1fb80de1d9a9a4fda8bfd6af2cd4e5c660fc75d96fe5"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/schemas.rs","sha256":"c59feec2805621f341a90f81fc005e2c12f7a70f9d264fdeacccb2be4fe1c046"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/verification.rs","sha256":"6a6b5834c5dae10af1ba8939b2deae43b85db71544dc8f077ff63b7fe68ac8a8"},{"path":"product/qualification/auths-recipe-qualification/src/verify.rs","sha256":"a470a9b98c04dc8d5dabe4d3dc8ed4e7a3ceb1cde035944a0714462bbf37d56d"},{"path":"product/receipts/auths-receipts/Cargo.toml","sha256":"6001fa1375899953aafcb07c23a6da0c8f57ea7ec08bb9c950b12a60a8cc6f0f"},{"path":"product/receipts/auths-receipts/src/disclosure.rs","sha256":"ba9ed439be0a320c8a01f5b6e9b51361c1a37e076947490d8e4a484ba6bb119c"},{"path":"product/receipts/auths-receipts/src/lib.rs","sha256":"547a57c4160256719cafb7d0ab972d9fc80b0da14fbbce4148c70c414070ff36"},{"path":"product/runtime/auths-connections/Cargo.toml","sha256":"babeb6e1dda3dfb66291713ce1e43dce5c349833d0b50ea4dccbf986030026b2"},{"path":"product/runtime/auths-connections/src/credential.rs","sha256":"82921413bb053f0f6c7931fbd4e6a86c8cc1d8c6b51debd9c2cef33a8d5b1c51"},{"path":"product/runtime/auths-connections/src/kernel.rs","sha256":"a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8"},{"path":"product/runtime/auths-connections/src/lib.rs","sha256":"79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22"},{"path":"product/runtime/auths-connections/src/model.rs","sha256":"de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77"},{"path":"product/runtime/auths-connections/src/registry.rs","sha256":"e57640e003e72ad3235c567c2bb944a262bd64e673f023b62ea091094cc7e946"},{"path":"product/runtime/auths-gateway-kernel/Cargo.toml","sha256":"34f864e67656af4ac7e5c7a347a23f01fc8ab31365b8e23c0ef474483b14a183"},{"path":"product/runtime/auths-gateway-kernel/src/construct.rs","sha256":"e9d65744bae273d65face4285e5d2da75c06a92ab48f7b8333d496604e31c63c"},{"path":"product/runtime/auths-gateway-kernel/src/lib.rs","sha256":"cfda6f8453426564c085475f183b6f790b438768a19668f1b65d33ba59dc8632"},{"path":"product/runtime/auths-gateway-kernel/src/order.rs","sha256":"e0045f877c4b7fe3860c291039853885064ddcdebba7c9b345ab65e81e646dda"},{"path":"product/runtime/auths-gateway-kernel/src/outcome.rs","sha256":"e9785b1afe70788c89b51b18655bcd5acff7b0c8e3d12fb79c6f05a202e67e6b"},{"path":"product/runtime/auths-gateway-kernel/src/ratio.rs","sha256":"7ace22264812e6fc1ef3a62afee402cf43494bb71ae0d3de219ad1b39d690bcb"},{"path":"product/runtime/auths-gateway-kernel/src/recovery.rs","sha256":"9f46dcd1685ab6e4d1ba04a3fc286a9f3afee8fb47829be1fbc670a7926a2dc6"},{"path":"product/runtime/auths-gateway-kernel/src/transition.rs","sha256":"cefb8f01d915880f6921f2501ff881ad94b9de61072c34d9cd19220992f97374"},{"path":"product/runtime/auths-gateway/Cargo.toml","sha256":"00b28be86921dcdc0ad90cce0c62c2961cafefe96ea6c2edf0e926c3d405ccad"},{"path":"product/runtime/auths-gateway/src/admin.rs","sha256":"2d5cc67afac42fbd15f36e2d1693cd1b20cedacf775040dce6ffe04ccc94c9ea"},{"path":"product/runtime/auths-gateway/src/app.rs","sha256":"6f80f63833ea0815bb44fbf3b0cc54624a08e9fb578b035819f2980dc04e8256"},{"path":"product/runtime/auths-gateway/src/audit.rs","sha256":"0edb2037eb7b5d6f13acfce85c54f62a82bf7fdd31bc7e626c4fec183cef61dd"},{"path":"product/runtime/auths-gateway/src/audit_tests.rs","sha256":"990969384a52d75bc2489d9d412a9e7dd814bca1c8f65c701d6205fae62a15d5"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway-harness.rs","sha256":"12b0c24d36b2e6a3be392d3c081a783b355fdd67dc5b54bacc0410e803116b8c"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway.rs","sha256":"2f33a1da5dd54947ee1664795f90b3f07a11bb9ee184774bf470b78b03600f0c"},{"path":"product/runtime/auths-gateway/src/binding.rs","sha256":"663b0ce878319511aa7d05722ab4ab2fa9be18817884ffb2ee9f131ff1e382d1"},{"path":"product/runtime/auths-gateway/src/bounds.rs","sha256":"9cfa0eae4973e5e047a198360b22f041708fa20276b0b90c2ec440f06915d64b"},{"path":"product/runtime/auths-gateway/src/bounds_aggregate_tests.rs","sha256":"ab34f227b7c8692ba1da88ccb32bb3687a66adf8353d8282fae905d4a88eb612"},{"path":"product/runtime/auths-gateway/src/bounds_tests.rs","sha256":"74136bc570da7b9338b5a1a1ed9d3fd892c55135160964f9d3ac0e2cf5741375"},{"path":"product/runtime/auths-gateway/src/connection.rs","sha256":"7b5d049c258a26ed1c93ecf860f51d051a8a65f9b93554af0b1ea93862398ec9"},{"path":"product/runtime/auths-gateway/src/credential_journal.rs","sha256":"7297fccaee5cd8622928e8e0a42bba50da7941970a6f682ecd300c41ee6509da"},{"path":"product/runtime/auths-gateway/src/echo_verify.rs","sha256":"6d453051665f823abd7354d5c50031d9524cf47d6092d2f09080ae814e3b9575"},{"path":"product/runtime/auths-gateway/src/engine.rs","sha256":"f1052aaef43e441b9e0befa3f8ad1e2fd5279a27cb9d63aac0cf9dfdbe85a052"},{"path":"product/runtime/auths-gateway/src/fuzzing.rs","sha256":"ed3b0028487eb546a3b0a91d115aa8f18bcea324b61620bfe8e35a9e6ab18758"},{"path":"product/runtime/auths-gateway/src/generation_floor.rs","sha256":"fe1510ec96ce0f67e9a78edbfa94b33eb7df64c0ac4d0a67901124dcd0164777"},{"path":"product/runtime/auths-gateway/src/harness.rs","sha256":"c87e479f3eb281960f6c9c80d43c7560d7ccb654b0154ec823d3fcec4884ac05"},{"path":"product/runtime/auths-gateway/src/lib.rs","sha256":"4674c497940ab339d9b755b71a3e1fe5feeba28bfecc025b7d148dc804a508bf"},{"path":"product/runtime/auths-gateway/src/listener.rs","sha256":"aa08239bcbc1fcb55e8a212fbdf6a84f12985b0d436dcb51dc58b06e59e435f2"},{"path":"product/runtime/auths-gateway/src/observed_tests.rs","sha256":"a22be071695f89ca2578a4d82fd80d9cb82289213c9bdb8f0470f6b2dc3d9201"},{"path":"product/runtime/auths-gateway/src/observer.rs","sha256":"562ffcaea071c3856e0708dc2fe33516917e145d2438aabb75af0a2b6ba01046"},{"path":"product/runtime/auths-gateway/src/onboarding.rs","sha256":"0dfd7d67e7f02f18a28d1c86ca1b7751d7463f5efcdbe3825de0ad8cbccb3891"},{"path":"product/runtime/auths-gateway/src/operator.rs","sha256":"c3c36954a3e86723df035b47f43b85fc8ab3a6292983522b6258d5c6b4e6c4e4"},{"path":"product/runtime/auths-gateway/src/pending_vectors/attempts.rs","sha256":"47ef3c8cb1c5504d47ae9a0088705ce6715fe86bac1671a34a56fb38a64d0dd3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/bounds.rs","sha256":"e612217307e1da5b0eb5ee6582a7458bb064b8aa8a529fc6555b1b334127ab68"},{"path":"product/runtime/auths-gateway/src/pending_vectors/codes.rs","sha256":"e00670a5ef24eb856cc2c6dcda8e5a263842f55c76bb939c0c27bd9df37e5522"},{"path":"product/runtime/auths-gateway/src/pending_vectors/keys.rs","sha256":"f84c56f2ea9cb34b2b79c72d13fbf2c6585010ec1ed450af58a78c80c1ea1edd"},{"path":"product/runtime/auths-gateway/src/pending_vectors/mod.rs","sha256":"5de8340f0ef71a0b57a09e323fefe473d3160c6ae952b9ba46f714825fbacafc"},{"path":"product/runtime/auths-gateway/src/pending_vectors/outcomes.rs","sha256":"8ec07b9511b48913af36ac999d2aa0e82924289f6acb23ddaeb9f00f99815166"},{"path":"product/runtime/auths-gateway/src/pending_vectors/production.rs","sha256":"f574cabfa4687a4fc846b8f6a234b68ec53b876aed548b11445729cac1a55ede"},{"path":"product/runtime/auths-gateway/src/pending_vectors/recipes.rs","sha256":"51693208270231c25c3aef2a32151d5962114c71e86b88cb9df83181c7af83d9"},{"path":"product/runtime/auths-gateway/src/pre_entry.rs","sha256":"06ea78ca140468bfaba17d9ab04912ad68673954c3203c98fed28272ff2a00c0"},{"path":"product/runtime/auths-gateway/src/property_tests.rs","sha256":"939c081e2e154aaf10186754044bdd65608932c899b970a04a71d0afaa999a93"},{"path":"product/runtime/auths-gateway/src/qualification.rs","sha256":"06b49d3fc2ad4383f9e23beefa96033f1fd6e415e043878327583451a53086cc"},{"path":"product/runtime/auths-gateway/src/qualification_tests.rs","sha256":"4473add5729b97faf04d7be7fd8cf3bbacd7f545e1b61c7d2782563011906b4d"},{"path":"product/runtime/auths-gateway/src/quorum_tests.rs","sha256":"a78380b019104d688c11a4410082c7e08ded3106aab099954c4f8a1b4ae0fd89"},{"path":"product/runtime/auths-gateway/src/readiness.rs","sha256":"911c3f11892f94641574375e2da4c671c802738f71082f12c39832331052d43d"},{"path":"product/runtime/auths-gateway/src/recipe.rs","sha256":"fecf9af67e7afc48d080e9f8f55f8ce28e49d0e08988717a27908bbda461d6b6"},{"path":"product/runtime/auths-gateway/src/recipe/lower.rs","sha256":"8088b8751ed831dbb48247af953c6290ac95e2a438ccd5bd65eff54be06a1fd1"},{"path":"product/runtime/auths-gateway/src/recipe/review.rs","sha256":"c3eb7d9fdd98dacf52750b14b67ad7b7faaecbbdeafff1e0b049f67d0a2d0139"},{"path":"product/runtime/auths-gateway/src/recipe/runtime.rs","sha256":"c286f0d15f974402822c0810d8e97f98411dc1c557755cc23e540d85e2bb42d9"},{"path":"product/runtime/auths-gateway/src/recipe/source.rs","sha256":"1af50298fb1461e1b24cbdf560d43124d6b1c4c529586c911b1c4797214a69ff"},{"path":"product/runtime/auths-gateway/src/recipe/tests.rs","sha256":"aac551a2481bbc60864c64079bc667dcb232e45a0f41a04073ed84ab5dbe1fce"},{"path":"product/runtime/auths-gateway/src/recipe/validate.rs","sha256":"3711b17605cb7b0d639bc1b180449231f5882a306cab20e2c7782155cc63b0d4"},{"path":"product/runtime/auths-gateway/src/scenario_tests.rs","sha256":"d8271761b12597bfe1233f8eb5ad1d4e5498c5d03388e832e24ab818484a1de4"},{"path":"product/runtime/auths-gateway/src/separation.rs","sha256":"be9306848ca5d801767cf6aa14247c8618312ef0e202f00ce0c24c4844491061"},{"path":"product/runtime/auths-gateway/src/store.rs","sha256":"1e5288345c2cb1421aeda277b3158d07607404b0ec46943222ac107b63dcbb46"},{"path":"product/runtime/auths-gateway/src/store_testkit.rs","sha256":"88d82fee42f1b8ef521e8deef0216e938ebeaad822eb2f5020e70b89d145ea70"},{"path":"product/runtime/auths-gateway/src/submit.rs","sha256":"c78dbbba7c45b443febf655056c5edcd635e77be7b21c5b2c318097502415ffe"},{"path":"product/runtime/auths-gateway/src/support.rs","sha256":"9fd979029793a22b15d9776a7fc172476fd7c126a80d4080c65d720845becbcb"},{"path":"product/runtime/auths-gateway/src/transport.rs","sha256":"be2c6dc75b8daec110bf8749fedc3823f6067d40b999aa3eb21126896a97d3ad"},{"path":"product/runtime/auths-kernel-runtime/Cargo.toml","sha256":"926bcd0053e5edd703be8f0027ad009e2982db013c8174c1366edbf38b48087d"},{"path":"product/runtime/auths-kernel-runtime/src/lib.rs","sha256":"7108faae9ca4bc32dc093ddaf885ac8f74f3c9b8d317b7c7d0ed00d1d0ab5972"},{"path":"product/runtime/auths-lifecycle/Cargo.toml","sha256":"c5053c705f8d5554b44e432fe75287a2faf11d644e5a2552e45ad6cd94176af5"},{"path":"product/runtime/auths-lifecycle/src/codec.rs","sha256":"51c4b746749150e8bfcd8ff972b3f6c1ef40bec15583448ec1b471d9ad737dc0"},{"path":"product/runtime/auths-lifecycle/src/digest.rs","sha256":"55282cd7d8aba37713c2dcb5357c9877819edb72a30eadefb860d28d7d3a3eb7"},{"path":"product/runtime/auths-lifecycle/src/identifier.rs","sha256":"31620e8c16de68d3d2d3b84d6353c1a5b9d4151d8247f91fa389b906a8e660f1"},{"path":"product/runtime/auths-lifecycle/src/kernel.rs","sha256":"2abb8c094b36d35b364e74d78091d14c5d6f3d1eb6552cca3b5538dbd017ce23"},{"path":"product/runtime/auths-lifecycle/src/lib.rs","sha256":"afe5a345cd309b5a4f08ffba3170a6d7f16ff914892b3f2006d5208ed24ec736"},{"path":"product/runtime/auths-lifecycle/src/model.rs","sha256":"1af12bbeeeaa65ec02ddcebd7d2c8c92ec1e339fa40ae85b45ab9b01a722a4fa"},{"path":"product/runtime/auths-lifecycle/src/operation.rs","sha256":"78e6d05fcf5d7ea4f148032a3fa26fdfcab77eb346019effe927b08e0d64d732"},{"path":"product/runtime/auths-lifecycle/src/registry.rs","sha256":"53495fe6f7a77422593a41623e28716f1c140dcc1e00f87f6b0ffbfb93a5ef90"},{"path":"product/runtime/auths-lifecycle/src/sealed.rs","sha256":"2e0c03b5813c926c159598bb7890d1523825edbe57cd687d42a5dfb3374a0c19"},{"path":"product/runtime/auths-lifecycle/src/test_support.rs","sha256":"221d9a5c5ef8e1f9f8fd66927484eaf813571d0568470278ecd8fa08a5eec8cd"},{"path":"product/runtime/auths-lifecycle/src/transition.rs","sha256":"011805a28efdd541f44ccea54dd0e34a1e58f4004447ee58013703b4fb6b2822"},{"path":"product/runtime/auths-runtime/Cargo.toml","sha256":"dd29d80a8b4bb56c869f036a6c9998f6e6d1c0383ac5dc03fa42b24abe2a7ff7"},{"path":"product/runtime/auths-runtime/src/lib.rs","sha256":"132ca03d58c14905d3a822a4972f42a22a5ad33a45f2ba9ca44f3a57d810b4b0"},{"path":"product/runtime/auths-runtime/src/production.rs","sha256":"fd4eff4270c571c10fcff6cf27df28961ebf074de8a1a028f500fda1ca376820"},{"path":"product/sdk/auths-approval-quorum/Cargo.toml","sha256":"df904971fca87a24194c5816738a331588fe8f164acb5d70839a35dca5f57114"},{"path":"product/sdk/auths-approval-quorum/src/lib.rs","sha256":"72e4086088a1c0912e4e1a9e980f26a5c280bf5ab16ea39c9f0f58d5096ac2ce"},{"path":"product/sdk/auths-approval-quorum/src/remote.rs","sha256":"9fa029c7c63003adf260f8aec55160c545681c60c1bace0d934e7525862aac7b"},{"path":"product/sdk/auths-approval-quorum/src/remote_tests.rs","sha256":"8a09ce17cfee82a035a74edd535f3ebeb3db0e078784740d3997b17dbdb10197"},{"path":"product/sdk/auths-approval-quorum/src/tests.rs","sha256":"0acbf12be3e497dcc6c2d8f29c9af3b1a7ed8e11b75f6399570d4f217a785060"},{"path":"product/stores/auths-stores/Cargo.toml","sha256":"a32c4b76d17b264be5d40d24497ff237e1ed87822e8bab86229b3db93106dbe3"},{"path":"product/stores/auths-stores/src/gateway_attempt.rs","sha256":"185da8f4a220fba836d5b78a9311f03204681c43a3c53951008084d135bf4d21"},{"path":"product/stores/auths-stores/src/lib.rs","sha256":"e721262edf8a9ab5568ddc27639176312d4a366203b5f73e2d7c11fde2c554e9"},{"path":"product/stores/auths-stores/src/lifecycle.rs","sha256":"94f64d25bc178a9e60ba3c0ee6915d7fb3af7c4468792d76b4e70f43f4de1e2f"}],"schema":"auths.gateway-semantic-closure/1"} \ No newline at end of file +{"files":[{"path":"Cargo.lock","sha256":"0e75e2fdef44e79e57797ac6661295ae58ddb8de4a1990a6fd22ce6c54f78604"},{"path":"Cargo.toml","sha256":"6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24"},{"path":"core/adapters/auths-did-keri/Cargo.toml","sha256":"86ba3e3f9a0a70d970568bfb3113b7ba7bbdd81c3eebbb52743dd574a0c0ecaa"},{"path":"core/adapters/auths-did-keri/src/lib.rs","sha256":"a75674842f8a7142004369ccd206ab43e476459293f0ff4bed4d4e659031b3e3"},{"path":"core/adapters/auths-did-key/Cargo.toml","sha256":"d5a3ae07ecde83f91eed4c3785051dd0f44eab6c891754f3309b6b40596707d7"},{"path":"core/adapters/auths-did-key/src/lib.rs","sha256":"b76a3f4528a725df53cfa9242e6e414e1d26caa48468aaed497e28b121f4497c"},{"path":"core/adapters/auths-raw-key/Cargo.toml","sha256":"f49616bc18c19e6aaa7e6a02ccebcdb9f5c1422c1278ef9869e0dbf22ceda7be"},{"path":"core/adapters/auths-raw-key/src/lib.rs","sha256":"45eec1b295dac3bed65cd79c942870b926b06b3f5d38eaebaeb6140ac69315fa"},{"path":"core/crates/auths-algebra-kernel/Cargo.toml","sha256":"0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba"},{"path":"core/crates/auths-algebra-kernel/src/generated.rs","sha256":"ae4bcbef42a408c7ffa0c6a74a42f7de177a6f14479e51d205acf830bda05960"},{"path":"core/crates/auths-algebra-kernel/src/lib.rs","sha256":"6654667eeb9b353d6648954c9fd2e8838462a82ce6b2803eb49e1366892c68c6"},{"path":"core/crates/auths-assurance/Cargo.toml","sha256":"afcb12a97ddd09d7a264b9ecd3fcaefc865ff2c9b4539ee85b00883420ba333a"},{"path":"core/crates/auths-assurance/src/lib.rs","sha256":"0fb2ec844d674b25a9e20b1601452c89c2454901fa506adfa9bb38ef9a7fa213"},{"path":"core/crates/auths-author/Cargo.toml","sha256":"1e6f0e3bc079ddb558decf0db26b291c6e72fc47327b6df1b7650d41689b215f"},{"path":"core/crates/auths-author/src/lib.rs","sha256":"e14475f2f49715a1869d5fa6b11ff1fbb72497e39097e09f833b0bae7e5b3f2b"},{"path":"core/crates/auths-author/src/observations.rs","sha256":"dda7d6bfa6f4bd7e95a480ca283c2c0e996f69c5c15cb0c7197af328131a7066"},{"path":"core/crates/auths-authority/Cargo.toml","sha256":"4f68212938029f79ebd857b4f3038494eb85d0163d49f07e51376715cf959815"},{"path":"core/crates/auths-authority/src/lib.rs","sha256":"da88d5194de4e17449e69972c0fb042afa3c39798a8f570f30771e77c384f1eb"},{"path":"core/crates/auths-codec/Cargo.toml","sha256":"e20e51826e17814effd9d8925d18d5fbdd6c0d37bf50231e743ec2611314722c"},{"path":"core/crates/auths-codec/src/approval.rs","sha256":"fbff43bf4d57f69f8b7738a8647751cde75c5a932dee65d924a1fe9c7202f91f"},{"path":"core/crates/auths-codec/src/bounded_policy.rs","sha256":"d21f6728be2d8a04b6d94921f2b683f7e61cbb42e0ac6866f1c88a49caa534c3"},{"path":"core/crates/auths-codec/src/decode.rs","sha256":"ba2999584cdf53b1b517ecb9c7ea50d39efee17c666a9a38e2ad1ac94379f778"},{"path":"core/crates/auths-codec/src/encode.rs","sha256":"8491192053e2e15d62b4d2a491de22405b7487ead69ab6f6bca40669ce7ca5f7"},{"path":"core/crates/auths-codec/src/error.rs","sha256":"fecb0737c16deb42d859f1dc7727c698438d9ac12064fd99e0024629642c390c"},{"path":"core/crates/auths-codec/src/hash.rs","sha256":"f88e111f1dbb2cef6b7b5e9c948cb45ff92e366710c8a5f5c636138aa748479e"},{"path":"core/crates/auths-codec/src/lib.rs","sha256":"3b0e5c94c6f34f750b88a9333e1d5c8145746d845d3a23e0d2f61807cf592ea7"},{"path":"core/crates/auths-codec/src/observation.rs","sha256":"38328b0c71ff97a4196eeade8b4faa889527ff1f80bb168468bcd49082a3987e"},{"path":"core/crates/auths-composition/Cargo.toml","sha256":"331e13025eb82588b5269ed3975929eb41c823d588c49e4c296273d85c6fe80e"},{"path":"core/crates/auths-composition/src/lib.rs","sha256":"e42e3b0b6a9985b73c533aeb23799c638979aa27a9ce7d0f10a8d60340570fb1"},{"path":"core/crates/auths-model/Cargo.toml","sha256":"565c15302b0cc9270db1e28efa3862804846850ba933cc17aea8abcec4a65987"},{"path":"core/crates/auths-model/src/approval.rs","sha256":"54cf44a9ef747ec21546a4086aecfb130bc7803b0d646430e6082df51e6e305f"},{"path":"core/crates/auths-model/src/bounded.rs","sha256":"f90496abc0a06c028b4d850af6ddab7d850bfafeaa3d042f1b1246a41d8bbbc9"},{"path":"core/crates/auths-model/src/bounded_policy.rs","sha256":"306a8f049cc7cfc7635fe0e4de47eb7813eed63d3c14c3be2b51586aa4eea450"},{"path":"core/crates/auths-model/src/lib.rs","sha256":"e7cfe6bb9574c6b016aa63e70658c31e0b90903ec6479a49f4a2ceb64f5bad97"},{"path":"core/crates/auths-model/src/observation.rs","sha256":"b3ed3e3cc090afca2896a7d3de7988afccc1ee1ea0ebd91b51a8bc0f20ad8dbb"},{"path":"core/crates/auths-multikey/Cargo.toml","sha256":"858756c1197befcada06134742bffe8d58cf674cadd6c046bf710570e96efaf2"},{"path":"core/crates/auths-multikey/src/lib.rs","sha256":"f5177fffb11e40eeaaa665ba886c541fc1f24d5eacdd6983fb03dc20148733f0"},{"path":"core/crates/auths-ports/Cargo.toml","sha256":"596a9b0f5af3717c16a6d13f7054d8a106bcd9f01f5f72c2235dd2afcf0ab16c"},{"path":"core/crates/auths-ports/src/binding.rs","sha256":"a16c012d40aa4249e3ec54372b9611006d0bfe8c7dc3c741911c2194ad17736d"},{"path":"core/crates/auths-ports/src/diagnostics.rs","sha256":"aa596572503b5a65a918bb2ff38281c144ff53821ee914e9325c852828d852df"},{"path":"core/crates/auths-ports/src/lib.rs","sha256":"8da1debf86f9532df0660155d04298beb1ba3a1204508f8586e2e67cd2fb3449"},{"path":"core/crates/auths-ports/src/path.rs","sha256":"b68fc547b4e4d97a60cbbc1cc1939fc6b34a8233b81f840bd396914a707e3ea1"},{"path":"core/crates/auths-raw-key-core/Cargo.toml","sha256":"98c0bc8527a537512e43a74dd6ba9658c6f0cdc16610cf938e3f9b43785d836d"},{"path":"core/crates/auths-raw-key-core/src/lib.rs","sha256":"98c0500c41697aae28708ad0bf970b9a97583d96a3d2c18d23e7fa351e0f7d12"},{"path":"core/crates/auths-registries/Cargo.toml","sha256":"590e49e58b0622d9d6274fea46796dcdb07dec9550eff295cce6a6427ffa51e2"},{"path":"core/crates/auths-registries/src/lib.rs","sha256":"450d3886d85ee333b7e046317fb5b47cde62483d5f3e41d46265e2caf4c373ec"},{"path":"core/crates/auths-registries/src/template.rs","sha256":"1224039dd2b3ce6fa8357613d8cafbae40400493da7176da202b9ade62fa05e4"},{"path":"core/crates/auths-signature-core/Cargo.toml","sha256":"6bee2230eb30af1be0bd5c2d57bd3e1903497a70028d47290d4ac6e9e0e8bca0"},{"path":"core/crates/auths-signature-core/src/lib.rs","sha256":"6e3f9311ded5e49ea50d445eb21e6d8fa12442aa4362a73e0cb6fda15b7cd865"},{"path":"core/crates/auths-signature/Cargo.toml","sha256":"7f7b5682466ba439d8c59579022cb61068cad9fb4bd2d73e1cc21327c902b450"},{"path":"core/crates/auths-signature/src/lib.rs","sha256":"b3d9ac4cc3ba0797b9e1c09f2d6ac05089b25dac4e285a5af28c0165b33d925b"},{"path":"core/crates/auths-verifier/Cargo.toml","sha256":"c43358e06a33324b41a8b93e5cc7279c55f7d21f1f6cfaa539a3fc7b4c27a38f"},{"path":"core/crates/auths-verifier/src/approval.rs","sha256":"c3cae6a49e169051eb555bb092b1069a4d422516d6a2114623a89e5f31ff923f"},{"path":"core/crates/auths-verifier/src/causal.rs","sha256":"9635230f33b13a263573d319ac8a1976addbcc07677514a43e3c7bf28dc04587"},{"path":"core/crates/auths-verifier/src/lib.rs","sha256":"f22dec38dfa47ced8da4f605390da8453273bee1da010f57fd1fdfcb10e0b389"},{"path":"core/crates/auths-verifier/src/observation.rs","sha256":"0bb07f06a0f9524c88427df1c972b1de8ba038a9eeeb15d3134c25125ae84b1e"},{"path":"core/crates/auths-verifier/src/trace.rs","sha256":"2213d72023a1d9e0413a2cf2c51c3dad9e04775d86033a0caaa9d29a8f0036f8"},{"path":"exchange/crates/auths-proof-exchange-model/Cargo.toml","sha256":"34b2db64f93a288e942b5a3918d28cdcbef906e0dc9074ce848018d3d5f7a1fa"},{"path":"exchange/crates/auths-proof-exchange-model/src/lib.rs","sha256":"49fac5aff2339d3a57c41cb8bb2a82852538e8f77ecc4b157c88e264ff31fb55"},{"path":"exchange/crates/auths-proof-exchange-port/Cargo.toml","sha256":"7ff660f1b7579dc570c791090aeb450404fbbf44c92781e289f5ccdde746d739"},{"path":"exchange/crates/auths-proof-exchange-port/src/lib.rs","sha256":"b408fb40c6432edc1facb3d8b3e9433a033f8dc73fe2e0ba5a88c972ca675021"},{"path":"product/config/auths-config/Cargo.toml","sha256":"e4b568ab9f6d84f7d7e6d66443fe825f360db9c27bc7c31d6ddc0647ba3ab304"},{"path":"product/config/auths-config/src/lib.rs","sha256":"fecf00ea65cef9018fda9af2063326d7065b869266d0d9e73a4f06816f1102cc"},{"path":"product/errors/auths-errors/Cargo.toml","sha256":"3b3a199b6460ba75bda84475bb5accd35e1485448a3981038db85bf4772dd350"},{"path":"product/errors/auths-errors/src/lib.rs","sha256":"7feeb9069fa4003f94f1f07c1c94619cf1c883e0dbaaf2187f04d0f742264bdd"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/Cargo.toml","sha256":"716f1f2a117d6d69d8effe9ee9057e24ba3502f20af6a602b06facb638cdabed"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/api.rs","sha256":"9ea61dd7ddd93282b073b98e453e6b75b26dc49689c04e9782435d06a3a09e48"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/clock.rs","sha256":"73f0a6e0f5903883329fa6683f5888288f759512ac69e5c87efd2b6b87f7d79f"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/http.rs","sha256":"14c1fce14e24c984b2a275563a29b6326fb08367922b6e8d37ba38b9cb81aa2b"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/identity.rs","sha256":"186de11230c8b33375951c4368609f8976bf9795f171af3fd7fac26207a94361"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs","sha256":"0b4617d044f5254a5ab22f5a2578f91cc025206a8c1845be39c1c56dcdf7a5df"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/names.rs","sha256":"41bb23572d6002e23ee103d6fe70ecd68764861c6f2e48a1c53af998270a4afa"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs","sha256":"39fed883f4802e68d3b41a68fea0aba0737810996b33d13577de70faba004c29"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/store.rs","sha256":"fc60ee9c49b2f4f063c449b4c78100c5c4872779e94ca168f796603b380ef6e4"},{"path":"product/integrations/auths-custody/Cargo.toml","sha256":"1e14034185ad1ec24a977fd5f41d0abee219606245c046ce2a82287fadef448b"},{"path":"product/integrations/auths-custody/src/conformance.rs","sha256":"8ed1afd58f18fc6becc268908aa6419c9aa404c79da0197963eb2599df44acf6"},{"path":"product/integrations/auths-custody/src/key.rs","sha256":"70cbb0fd21b6f5652157845a22c35be2d0f6c05b3d138fc4b9bb6dbdc3d81c40"},{"path":"product/integrations/auths-custody/src/lib.rs","sha256":"8ee593c1f59b0fd2126bdda9138026f5bc531beb64d4489a99785842e7b98b43"},{"path":"product/operations/auths-operations/Cargo.toml","sha256":"73dde1e914ba5e1386f8d49c0d730423cc72ae77ec44c6554a6a75cc8e8922b1"},{"path":"product/operations/auths-operations/src/explanation.rs","sha256":"b4a39bcbd5712cb9e735ee7deeb281f3fa6af5ddca973735bf3d87dce427ef11"},{"path":"product/operations/auths-operations/src/lib.rs","sha256":"3f401a56555113b98f57bca172a2660eaecedf76247b83a3fdbb089c133a29cd"},{"path":"product/operations/auths-operations/src/render/json.rs","sha256":"2ae042639960afee123730e945d373bc5dda1d2b3af20ae16c939a7e99b9e418"},{"path":"product/operations/auths-operations/src/render/mod.rs","sha256":"b3b7f6fe473f49227ace5a68bfc3d8dc14b5db8dd9888fd9e207070337b1b8bf"},{"path":"product/operations/auths-operations/src/render/text.rs","sha256":"f216cf3bdb00e264523271b16e7059535ac6b1aabf271cebd7935af155e4bfec"},{"path":"product/policy/auths-bounded-policy/Cargo.toml","sha256":"babd5d200923137ead71d8c2528f847cea323ce98da942a1320b054436612c47"},{"path":"product/policy/auths-bounded-policy/src/arithmetic.rs","sha256":"75e43c5d4eab8d1f71c1daf53839f5f9fe45a400afc1f63a30c6f55ce3632627"},{"path":"product/policy/auths-bounded-policy/src/commitment.rs","sha256":"c5706f2d583454e1a7f570f7ada138d4d864bef0205dfae7c1296774f396bb3f"},{"path":"product/policy/auths-bounded-policy/src/eligibility.rs","sha256":"c9acdfb793074e687fc36efad506be27dbd99ffbf40387bc66c8de39ef238432"},{"path":"product/policy/auths-bounded-policy/src/identifier.rs","sha256":"0006a32bae9eb16c4178cf797df418d2b0a781f2bc6474b741dc1a908141831c"},{"path":"product/policy/auths-bounded-policy/src/kernel.rs","sha256":"99187c28b161ac70bee1afed60711f7f645adb4d1671a01863f9849b369811d5"},{"path":"product/policy/auths-bounded-policy/src/lib.rs","sha256":"76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c"},{"path":"product/policy/auths-bounded-policy/src/receipt.rs","sha256":"3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad"},{"path":"product/policy/auths-bounded-policy/src/registry.rs","sha256":"4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0"},{"path":"product/profiles/auths-profile-api/Cargo.toml","sha256":"7ae85761f58625b5d678f961fd052eebf3e000ef565c7312e3ac857763c0017f"},{"path":"product/profiles/auths-profile-api/src/lib.rs","sha256":"a194b82b20bf8aa864c2334ef6c6aec30b2154ded972862252d5dcefa488ab95"},{"path":"product/profiles/auths-profile-mcp/Cargo.toml","sha256":"db264fc25242f7b7e4133cbe5782545b3107b406c87168ae072683cfb59eac66"},{"path":"product/profiles/auths-profile-mcp/src/arguments.rs","sha256":"a5de696586d507e2aee4a49fee99ef1ef4c51a2e46603f8838f1af6d9009833f"},{"path":"product/profiles/auths-profile-mcp/src/lib.rs","sha256":"d0f8b733a09ef8408336cdebc8948d6a5861012ce6878598b11be7084dfd4280"},{"path":"product/profiles/auths-profile-mcp/src/session.rs","sha256":"166c281fa66333388e4760d6098dad02d3359e1d5de4b8f93312c014f97abb03"},{"path":"product/qualification/auths-recipe-qualification/Cargo.toml","sha256":"b7b15b30b9a3d96d4f089d514266d3a892de6608d30707aa44be31cca89ca9fe"},{"path":"product/qualification/auths-recipe-qualification/src/canonical.rs","sha256":"30a9b50777f0dcb4b606abfee2467d5a975d9f6ad941ab6c13ca3df5b359f667"},{"path":"product/qualification/auths-recipe-qualification/src/closure.rs","sha256":"0ad6aee9bd981e2863fa725f209ec84031db2ff12f4c7ac3aaf5120f0bb86039"},{"path":"product/qualification/auths-recipe-qualification/src/error.rs","sha256":"52d5cf720a1e4579008fdda90a3ac2c31f0b8db57985f121f65e54b4da2b7dd1"},{"path":"product/qualification/auths-recipe-qualification/src/evidence.rs","sha256":"ba45a7409d67a8af26ab811af306412014557477a101ab2a8eb0faf8f2bd4b91"},{"path":"product/qualification/auths-recipe-qualification/src/ids.rs","sha256":"e81a906d571497ab2da753e1532d4443706410e0b75fdd59a7d2d788c7aec403"},{"path":"product/qualification/auths-recipe-qualification/src/launch.rs","sha256":"17ba2534a26b3a2e16a515e783403b1c3b2771a3ed184d4f4ac1dc5684e5582d"},{"path":"product/qualification/auths-recipe-qualification/src/lib.rs","sha256":"5c9cff04c8960df805a2f7656cf5e74932798e0db7648341e96ae7073a592404"},{"path":"product/qualification/auths-recipe-qualification/src/model.rs","sha256":"3484eb0ec287b23d4682ade7b1b0f8d1335985b3fb180f06fc28716076957d5f"},{"path":"product/qualification/auths-recipe-qualification/src/release.rs","sha256":"d816b53e2275e902c750ad03803061844e259e28560ab2d1c77e8a43981a4d6a"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/mod.rs","sha256":"7f15b68e05a04f202bcb1fb80de1d9a9a4fda8bfd6af2cd4e5c660fc75d96fe5"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/schemas.rs","sha256":"c59feec2805621f341a90f81fc005e2c12f7a70f9d264fdeacccb2be4fe1c046"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/verification.rs","sha256":"6a6b5834c5dae10af1ba8939b2deae43b85db71544dc8f077ff63b7fe68ac8a8"},{"path":"product/qualification/auths-recipe-qualification/src/verify.rs","sha256":"a470a9b98c04dc8d5dabe4d3dc8ed4e7a3ceb1cde035944a0714462bbf37d56d"},{"path":"product/receipts/auths-receipts/Cargo.toml","sha256":"6001fa1375899953aafcb07c23a6da0c8f57ea7ec08bb9c950b12a60a8cc6f0f"},{"path":"product/receipts/auths-receipts/src/disclosure.rs","sha256":"ba9ed439be0a320c8a01f5b6e9b51361c1a37e076947490d8e4a484ba6bb119c"},{"path":"product/receipts/auths-receipts/src/lib.rs","sha256":"547a57c4160256719cafb7d0ab972d9fc80b0da14fbbce4148c70c414070ff36"},{"path":"product/runtime/auths-connections/Cargo.toml","sha256":"babeb6e1dda3dfb66291713ce1e43dce5c349833d0b50ea4dccbf986030026b2"},{"path":"product/runtime/auths-connections/src/credential.rs","sha256":"82921413bb053f0f6c7931fbd4e6a86c8cc1d8c6b51debd9c2cef33a8d5b1c51"},{"path":"product/runtime/auths-connections/src/kernel.rs","sha256":"a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8"},{"path":"product/runtime/auths-connections/src/lib.rs","sha256":"79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22"},{"path":"product/runtime/auths-connections/src/model.rs","sha256":"de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77"},{"path":"product/runtime/auths-connections/src/registry.rs","sha256":"e57640e003e72ad3235c567c2bb944a262bd64e673f023b62ea091094cc7e946"},{"path":"product/runtime/auths-gateway-kernel/Cargo.toml","sha256":"34f864e67656af4ac7e5c7a347a23f01fc8ab31365b8e23c0ef474483b14a183"},{"path":"product/runtime/auths-gateway-kernel/src/construct.rs","sha256":"e9d65744bae273d65face4285e5d2da75c06a92ab48f7b8333d496604e31c63c"},{"path":"product/runtime/auths-gateway-kernel/src/lib.rs","sha256":"cfda6f8453426564c085475f183b6f790b438768a19668f1b65d33ba59dc8632"},{"path":"product/runtime/auths-gateway-kernel/src/order.rs","sha256":"e0045f877c4b7fe3860c291039853885064ddcdebba7c9b345ab65e81e646dda"},{"path":"product/runtime/auths-gateway-kernel/src/outcome.rs","sha256":"e9785b1afe70788c89b51b18655bcd5acff7b0c8e3d12fb79c6f05a202e67e6b"},{"path":"product/runtime/auths-gateway-kernel/src/ratio.rs","sha256":"7ace22264812e6fc1ef3a62afee402cf43494bb71ae0d3de219ad1b39d690bcb"},{"path":"product/runtime/auths-gateway-kernel/src/recovery.rs","sha256":"9f46dcd1685ab6e4d1ba04a3fc286a9f3afee8fb47829be1fbc670a7926a2dc6"},{"path":"product/runtime/auths-gateway-kernel/src/transition.rs","sha256":"cefb8f01d915880f6921f2501ff881ad94b9de61072c34d9cd19220992f97374"},{"path":"product/runtime/auths-gateway/Cargo.toml","sha256":"00b28be86921dcdc0ad90cce0c62c2961cafefe96ea6c2edf0e926c3d405ccad"},{"path":"product/runtime/auths-gateway/src/admin.rs","sha256":"2d5cc67afac42fbd15f36e2d1693cd1b20cedacf775040dce6ffe04ccc94c9ea"},{"path":"product/runtime/auths-gateway/src/app.rs","sha256":"6f80f63833ea0815bb44fbf3b0cc54624a08e9fb578b035819f2980dc04e8256"},{"path":"product/runtime/auths-gateway/src/audit.rs","sha256":"0edb2037eb7b5d6f13acfce85c54f62a82bf7fdd31bc7e626c4fec183cef61dd"},{"path":"product/runtime/auths-gateway/src/audit_tests.rs","sha256":"990969384a52d75bc2489d9d412a9e7dd814bca1c8f65c701d6205fae62a15d5"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway-harness.rs","sha256":"12b0c24d36b2e6a3be392d3c081a783b355fdd67dc5b54bacc0410e803116b8c"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway.rs","sha256":"2f33a1da5dd54947ee1664795f90b3f07a11bb9ee184774bf470b78b03600f0c"},{"path":"product/runtime/auths-gateway/src/binding.rs","sha256":"663b0ce878319511aa7d05722ab4ab2fa9be18817884ffb2ee9f131ff1e382d1"},{"path":"product/runtime/auths-gateway/src/bounds.rs","sha256":"9cfa0eae4973e5e047a198360b22f041708fa20276b0b90c2ec440f06915d64b"},{"path":"product/runtime/auths-gateway/src/bounds_aggregate_tests.rs","sha256":"ab34f227b7c8692ba1da88ccb32bb3687a66adf8353d8282fae905d4a88eb612"},{"path":"product/runtime/auths-gateway/src/bounds_tests.rs","sha256":"74136bc570da7b9338b5a1a1ed9d3fd892c55135160964f9d3ac0e2cf5741375"},{"path":"product/runtime/auths-gateway/src/connection.rs","sha256":"7b5d049c258a26ed1c93ecf860f51d051a8a65f9b93554af0b1ea93862398ec9"},{"path":"product/runtime/auths-gateway/src/credential_journal.rs","sha256":"7297fccaee5cd8622928e8e0a42bba50da7941970a6f682ecd300c41ee6509da"},{"path":"product/runtime/auths-gateway/src/echo_verify.rs","sha256":"6d453051665f823abd7354d5c50031d9524cf47d6092d2f09080ae814e3b9575"},{"path":"product/runtime/auths-gateway/src/engine.rs","sha256":"f1052aaef43e441b9e0befa3f8ad1e2fd5279a27cb9d63aac0cf9dfdbe85a052"},{"path":"product/runtime/auths-gateway/src/fuzzing.rs","sha256":"ed3b0028487eb546a3b0a91d115aa8f18bcea324b61620bfe8e35a9e6ab18758"},{"path":"product/runtime/auths-gateway/src/generation_floor.rs","sha256":"fe1510ec96ce0f67e9a78edbfa94b33eb7df64c0ac4d0a67901124dcd0164777"},{"path":"product/runtime/auths-gateway/src/harness.rs","sha256":"c87e479f3eb281960f6c9c80d43c7560d7ccb654b0154ec823d3fcec4884ac05"},{"path":"product/runtime/auths-gateway/src/lib.rs","sha256":"4674c497940ab339d9b755b71a3e1fe5feeba28bfecc025b7d148dc804a508bf"},{"path":"product/runtime/auths-gateway/src/listener.rs","sha256":"aa08239bcbc1fcb55e8a212fbdf6a84f12985b0d436dcb51dc58b06e59e435f2"},{"path":"product/runtime/auths-gateway/src/observed_tests.rs","sha256":"a22be071695f89ca2578a4d82fd80d9cb82289213c9bdb8f0470f6b2dc3d9201"},{"path":"product/runtime/auths-gateway/src/observer.rs","sha256":"562ffcaea071c3856e0708dc2fe33516917e145d2438aabb75af0a2b6ba01046"},{"path":"product/runtime/auths-gateway/src/onboarding.rs","sha256":"0dfd7d67e7f02f18a28d1c86ca1b7751d7463f5efcdbe3825de0ad8cbccb3891"},{"path":"product/runtime/auths-gateway/src/operator.rs","sha256":"c3c36954a3e86723df035b47f43b85fc8ab3a6292983522b6258d5c6b4e6c4e4"},{"path":"product/runtime/auths-gateway/src/pending_vectors/attempts.rs","sha256":"47ef3c8cb1c5504d47ae9a0088705ce6715fe86bac1671a34a56fb38a64d0dd3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/bounds.rs","sha256":"e612217307e1da5b0eb5ee6582a7458bb064b8aa8a529fc6555b1b334127ab68"},{"path":"product/runtime/auths-gateway/src/pending_vectors/codes.rs","sha256":"e00670a5ef24eb856cc2c6dcda8e5a263842f55c76bb939c0c27bd9df37e5522"},{"path":"product/runtime/auths-gateway/src/pending_vectors/keys.rs","sha256":"f84c56f2ea9cb34b2b79c72d13fbf2c6585010ec1ed450af58a78c80c1ea1edd"},{"path":"product/runtime/auths-gateway/src/pending_vectors/mod.rs","sha256":"5de8340f0ef71a0b57a09e323fefe473d3160c6ae952b9ba46f714825fbacafc"},{"path":"product/runtime/auths-gateway/src/pending_vectors/outcomes.rs","sha256":"8ec07b9511b48913af36ac999d2aa0e82924289f6acb23ddaeb9f00f99815166"},{"path":"product/runtime/auths-gateway/src/pending_vectors/production.rs","sha256":"f574cabfa4687a4fc846b8f6a234b68ec53b876aed548b11445729cac1a55ede"},{"path":"product/runtime/auths-gateway/src/pending_vectors/recipes.rs","sha256":"51693208270231c25c3aef2a32151d5962114c71e86b88cb9df83181c7af83d9"},{"path":"product/runtime/auths-gateway/src/pre_entry.rs","sha256":"06ea78ca140468bfaba17d9ab04912ad68673954c3203c98fed28272ff2a00c0"},{"path":"product/runtime/auths-gateway/src/property_tests.rs","sha256":"939c081e2e154aaf10186754044bdd65608932c899b970a04a71d0afaa999a93"},{"path":"product/runtime/auths-gateway/src/qualification.rs","sha256":"06b49d3fc2ad4383f9e23beefa96033f1fd6e415e043878327583451a53086cc"},{"path":"product/runtime/auths-gateway/src/qualification_simulation.rs","sha256":"878bd4a0955c725bdcae9242f731bd4f9f82238fb6a26aadd230134ef8fd2dfe"},{"path":"product/runtime/auths-gateway/src/qualification_tests.rs","sha256":"020c83bb4bc80bcf0ecdc20d95a7aba5842e1e9dde3f2cb2a519e13926ad54eb"},{"path":"product/runtime/auths-gateway/src/quorum_tests.rs","sha256":"a78380b019104d688c11a4410082c7e08ded3106aab099954c4f8a1b4ae0fd89"},{"path":"product/runtime/auths-gateway/src/readiness.rs","sha256":"911c3f11892f94641574375e2da4c671c802738f71082f12c39832331052d43d"},{"path":"product/runtime/auths-gateway/src/recipe.rs","sha256":"fecf9af67e7afc48d080e9f8f55f8ce28e49d0e08988717a27908bbda461d6b6"},{"path":"product/runtime/auths-gateway/src/recipe/lower.rs","sha256":"8088b8751ed831dbb48247af953c6290ac95e2a438ccd5bd65eff54be06a1fd1"},{"path":"product/runtime/auths-gateway/src/recipe/review.rs","sha256":"c3eb7d9fdd98dacf52750b14b67ad7b7faaecbbdeafff1e0b049f67d0a2d0139"},{"path":"product/runtime/auths-gateway/src/recipe/runtime.rs","sha256":"c286f0d15f974402822c0810d8e97f98411dc1c557755cc23e540d85e2bb42d9"},{"path":"product/runtime/auths-gateway/src/recipe/source.rs","sha256":"1af50298fb1461e1b24cbdf560d43124d6b1c4c529586c911b1c4797214a69ff"},{"path":"product/runtime/auths-gateway/src/recipe/tests.rs","sha256":"aac551a2481bbc60864c64079bc667dcb232e45a0f41a04073ed84ab5dbe1fce"},{"path":"product/runtime/auths-gateway/src/recipe/validate.rs","sha256":"3711b17605cb7b0d639bc1b180449231f5882a306cab20e2c7782155cc63b0d4"},{"path":"product/runtime/auths-gateway/src/scenario_tests.rs","sha256":"67915828ecfe2be0afadb5525277ab205f91172edc90852ec7b77c63b2d17fdc"},{"path":"product/runtime/auths-gateway/src/separation.rs","sha256":"be9306848ca5d801767cf6aa14247c8618312ef0e202f00ce0c24c4844491061"},{"path":"product/runtime/auths-gateway/src/store.rs","sha256":"1e5288345c2cb1421aeda277b3158d07607404b0ec46943222ac107b63dcbb46"},{"path":"product/runtime/auths-gateway/src/store_testkit.rs","sha256":"88d82fee42f1b8ef521e8deef0216e938ebeaad822eb2f5020e70b89d145ea70"},{"path":"product/runtime/auths-gateway/src/submit.rs","sha256":"c78dbbba7c45b443febf655056c5edcd635e77be7b21c5b2c318097502415ffe"},{"path":"product/runtime/auths-gateway/src/support.rs","sha256":"9fd979029793a22b15d9776a7fc172476fd7c126a80d4080c65d720845becbcb"},{"path":"product/runtime/auths-gateway/src/transport.rs","sha256":"be2c6dc75b8daec110bf8749fedc3823f6067d40b999aa3eb21126896a97d3ad"},{"path":"product/runtime/auths-kernel-runtime/Cargo.toml","sha256":"926bcd0053e5edd703be8f0027ad009e2982db013c8174c1366edbf38b48087d"},{"path":"product/runtime/auths-kernel-runtime/src/lib.rs","sha256":"7108faae9ca4bc32dc093ddaf885ac8f74f3c9b8d317b7c7d0ed00d1d0ab5972"},{"path":"product/runtime/auths-lifecycle/Cargo.toml","sha256":"c5053c705f8d5554b44e432fe75287a2faf11d644e5a2552e45ad6cd94176af5"},{"path":"product/runtime/auths-lifecycle/src/codec.rs","sha256":"51c4b746749150e8bfcd8ff972b3f6c1ef40bec15583448ec1b471d9ad737dc0"},{"path":"product/runtime/auths-lifecycle/src/digest.rs","sha256":"55282cd7d8aba37713c2dcb5357c9877819edb72a30eadefb860d28d7d3a3eb7"},{"path":"product/runtime/auths-lifecycle/src/identifier.rs","sha256":"31620e8c16de68d3d2d3b84d6353c1a5b9d4151d8247f91fa389b906a8e660f1"},{"path":"product/runtime/auths-lifecycle/src/kernel.rs","sha256":"2abb8c094b36d35b364e74d78091d14c5d6f3d1eb6552cca3b5538dbd017ce23"},{"path":"product/runtime/auths-lifecycle/src/lib.rs","sha256":"afe5a345cd309b5a4f08ffba3170a6d7f16ff914892b3f2006d5208ed24ec736"},{"path":"product/runtime/auths-lifecycle/src/model.rs","sha256":"1af12bbeeeaa65ec02ddcebd7d2c8c92ec1e339fa40ae85b45ab9b01a722a4fa"},{"path":"product/runtime/auths-lifecycle/src/operation.rs","sha256":"78e6d05fcf5d7ea4f148032a3fa26fdfcab77eb346019effe927b08e0d64d732"},{"path":"product/runtime/auths-lifecycle/src/registry.rs","sha256":"53495fe6f7a77422593a41623e28716f1c140dcc1e00f87f6b0ffbfb93a5ef90"},{"path":"product/runtime/auths-lifecycle/src/sealed.rs","sha256":"2e0c03b5813c926c159598bb7890d1523825edbe57cd687d42a5dfb3374a0c19"},{"path":"product/runtime/auths-lifecycle/src/test_support.rs","sha256":"221d9a5c5ef8e1f9f8fd66927484eaf813571d0568470278ecd8fa08a5eec8cd"},{"path":"product/runtime/auths-lifecycle/src/transition.rs","sha256":"011805a28efdd541f44ccea54dd0e34a1e58f4004447ee58013703b4fb6b2822"},{"path":"product/runtime/auths-runtime/Cargo.toml","sha256":"dd29d80a8b4bb56c869f036a6c9998f6e6d1c0383ac5dc03fa42b24abe2a7ff7"},{"path":"product/runtime/auths-runtime/src/lib.rs","sha256":"132ca03d58c14905d3a822a4972f42a22a5ad33a45f2ba9ca44f3a57d810b4b0"},{"path":"product/runtime/auths-runtime/src/production.rs","sha256":"fd4eff4270c571c10fcff6cf27df28961ebf074de8a1a028f500fda1ca376820"},{"path":"product/sdk/auths-approval-quorum/Cargo.toml","sha256":"df904971fca87a24194c5816738a331588fe8f164acb5d70839a35dca5f57114"},{"path":"product/sdk/auths-approval-quorum/src/lib.rs","sha256":"72e4086088a1c0912e4e1a9e980f26a5c280bf5ab16ea39c9f0f58d5096ac2ce"},{"path":"product/sdk/auths-approval-quorum/src/remote.rs","sha256":"9fa029c7c63003adf260f8aec55160c545681c60c1bace0d934e7525862aac7b"},{"path":"product/sdk/auths-approval-quorum/src/remote_tests.rs","sha256":"8a09ce17cfee82a035a74edd535f3ebeb3db0e078784740d3997b17dbdb10197"},{"path":"product/sdk/auths-approval-quorum/src/tests.rs","sha256":"0acbf12be3e497dcc6c2d8f29c9af3b1a7ed8e11b75f6399570d4f217a785060"},{"path":"product/stores/auths-stores/Cargo.toml","sha256":"a32c4b76d17b264be5d40d24497ff237e1ed87822e8bab86229b3db93106dbe3"},{"path":"product/stores/auths-stores/src/gateway_attempt.rs","sha256":"185da8f4a220fba836d5b78a9311f03204681c43a3c53951008084d135bf4d21"},{"path":"product/stores/auths-stores/src/lib.rs","sha256":"e721262edf8a9ab5568ddc27639176312d4a366203b5f73e2d7c11fde2c554e9"},{"path":"product/stores/auths-stores/src/lifecycle.rs","sha256":"94f64d25bc178a9e60ba3c0ee6915d7fb3af7c4468792d76b4e70f43f4de1e2f"}],"schema":"auths.gateway-semantic-closure/1"} \ No newline at end of file diff --git a/product/runtime/auths-gateway/src/qualification_simulation.rs b/product/runtime/auths-gateway/src/qualification_simulation.rs index 39c5155a6..7f948ca40 100644 --- a/product/runtime/auths-gateway/src/qualification_simulation.rs +++ b/product/runtime/auths-gateway/src/qualification_simulation.rs @@ -10,6 +10,14 @@ const STRIPE_VERSION: &str = "2025-03-31.basil"; const STRIPE_ACCOUNT: &str = "acct_TESTACCOUNT01"; const STRIPE_PAYMENT: &str = "pi_TEST0000000001"; +fn stripe_setup() -> Value { + let corpus: Value = serde_json::from_slice(include_bytes!( + "../../../../bindings/fixtures/gateway/attempt-scenarios-v3.json" + )) + .expect("embedded Stripe fixture"); + corpus["defaults"]["stripe"].clone() +} + #[derive(Clone, Copy)] enum Family { Stripe, @@ -33,7 +41,7 @@ impl Family { commitment: [u8; 32], ) -> Result { let links = match self { - Self::Stripe => scenario_links(&corpus(SCENARIOS)["defaults"]["stripe"]), + Self::Stripe => scenario_links(&stripe_setup()), Self::Airtable => Vec::new(), }; admitted(recipe, args, commitment, Vec::new(), 3_600, links, NOW) @@ -200,6 +208,7 @@ fn publish(family: Family, recipe: &CompiledRecipe, cases: &[Measurement]) { "compiled_recipe_sha256": recipe.digest_hex(), "gateway_semantic_closure_sha256": crate::GATEWAY_SEMANTIC_CLOSURE_SHA256, "store": "shared-file-v1", "custody": "test-only-counting-lease", + "clock": {"kind": "fixed-test-clock", "unix_seconds": NOW}, "verification_boundary": "native-verified-command projection", "provider": "in-process mutable double", "cases": cases, "excluded_claims": ["live provider acceptance", "production qualification", @@ -327,15 +336,27 @@ async fn race(family: Family, provider: &OracleProvider

2..=2, + Family::Airtable => 2..=3, + }; + assert!( + allowed_leases.contains(&leases), + "one write lease, only bounded read-back leases: {leases}" + ); Measurement { case: "two-instance-race".to_owned(), verdict: "one-authorized-entry".to_owned(), credential_leases: leases, provider_entries: provider.inner.entries(), - confirmed_by_read_back: observed, + confirmed_by_read_back: usize::from(observed > 0), } } @@ -415,7 +436,7 @@ async fn stripe_qualification_simulation() { let family = Family::Stripe; let recipe = family.recipe(); let mut cases = Vec::new(); - let mut defaults = corpus(SCENARIOS)["defaults"]["stripe"]["responses"].clone(); + let mut defaults = stripe_setup()["responses"].clone(); defaults["GET /v1/balance"] = json!({"status": 200, "headers": {"Stripe-Version": STRIPE_VERSION}, "body": {"livemode": false}}); for mode in ["respond", "timeout-after-send", "crash-after-write"] { diff --git a/product/runtime/auths-gateway/src/qualification_tests.rs b/product/runtime/auths-gateway/src/qualification_tests.rs index 1eddc9091..e5a2e8bc2 100644 --- a/product/runtime/auths-gateway/src/qualification_tests.rs +++ b/product/runtime/auths-gateway/src/qualification_tests.rs @@ -164,7 +164,7 @@ async fn operator_bootstrap_qualification_simulation() { .collect(); let index = signer.index(NOW, &listed).expect("signed index"); let list = root - .revoke(1, NOW - HOUR, NOW + 12 * HOUR, Vec::new(), Vec::new()) + .revoke(1, NOW - HOUR, NOW + 24 * HOUR, Vec::new(), Vec::new()) .expect("list"); let signed = QualificationBundle { signer_certificate: signer.certificate().canonical_bytes().to_vec(), @@ -215,7 +215,10 @@ async fn operator_bootstrap_qualification_simulation() { } assert!(gate.load(&signed)); clock.set(NOW + 13 * HOUR); - assert!(refusal(host).await.is_some()); + assert_eq!( + refusal(host).await.as_deref(), + Some("gateway.qualification.expired") + ); clock.set(NOW); let no_root = required(None, deployment.clone(), &clock); assert!(!no_root.load(&signed)); @@ -267,6 +270,7 @@ async fn operator_bootstrap_qualification_simulation() { std::fs::write(directory.join("simulation.json"), serde_json::to_vec_pretty(&json!({ "schema": "auths.qualification-bootstrap-simulation/1", "simulation": true, "stable_launch_ready": false, "ephemeral_keys_destroyed_on_return": true, + "clock": {"kind": "fixed-test-clock", "unix_seconds": NOW}, "evidence_kind": "explicit placeholder fixtures: no provider-run claim", "measurements": measurements, "production_root_changed": false, "excluded_claims": ["production qualification", "live provider acceptance", "human review"] diff --git a/product/runtime/auths-gateway/src/semantic_closure.rs b/product/runtime/auths-gateway/src/semantic_closure.rs index 0d1f554df..2cc8348b4 100644 --- a/product/runtime/auths-gateway/src/semantic_closure.rs +++ b/product/runtime/auths-gateway/src/semantic_closure.rs @@ -10,7 +10,7 @@ /// SHA-256 of the schema, a NUL byte, and `semantic-closure.json`. /// Regenerate through `semantic_closure_is_current` with `AUTHS_UPDATE_FIXTURES=1`. pub const GATEWAY_SEMANTIC_CLOSURE_SHA256: &str = - "7cc768345590accc1d7e4b7de14e976148d11b37bb5445034171235388d19685"; + "f16f4aa4ec541bff74b6d6e1f35eb390eae3ba256a8fe9c9f87a7c155cc60368"; #[cfg(test)] mod tests { diff --git a/qualification/simulation/Dockerfile b/qualification/simulation/Dockerfile new file mode 100644 index 000000000..b62b1559e --- /dev/null +++ b/qualification/simulation/Dockerfile @@ -0,0 +1,3 @@ +FROM ubuntu:24.04 +RUN apt-get update && apt-get install -y --no-install-recommends python3 ca-certificates \ + && rm -rf /var/lib/apt/lists/* diff --git a/qualification/simulation/README.md b/qualification/simulation/README.md index b4abcd65b..76e6094ea 100644 --- a/qualification/simulation/README.md +++ b/qualification/simulation/README.md @@ -26,6 +26,19 @@ one after verified import. Unsigned, expired and missing-root inputs refuse. The placeholder records explicitly exclude every provider-run claim; they test the trust transition, while provider measurements are separate artifacts. +CI also packages the compiled native harness with its SHA-256 and commit. +It runs that kit in Docker with networking disabled and no source checkout +mounted. Download the `qualification-simulation-kit-*` artifact, make the +`qualification-harness` executable, and run with Python 3.12: + +```sh +chmod +x /path/to/kit/qualification-harness +python3 /path/to/kit/run.py --candidate-kit /path/to/kit --out /tmp/rehearsal +``` + +The kit must match the host OS and architecture. Its request and policy fixtures +are compiled in. No Rust toolchain or repository import is needed for that run. + These are simulation artifacts. They cannot enable the shipping gateway: its pinned root is unchanged, the tuples use development stores, and the bootstrap records name placeholder provenance. No file is installed under diff --git a/qualification/simulation/pack.py b/qualification/simulation/pack.py new file mode 100644 index 000000000..42d5ba0fc --- /dev/null +++ b/qualification/simulation/pack.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python3 +"""Package the native simulation harness selected from Cargo's artifact report.""" + +import argparse +import hashlib +import json +from pathlib import Path +import shutil +import subprocess + + +def main() -> None: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--build-report", type=Path, required=True) + parser.add_argument("--out", type=Path, required=True) + args = parser.parse_args() + executables = [] + with args.build_report.open() as lines: + for line in lines: + if len(line) > 1_048_576: + parser.error("oversized build report line") + artifact = json.loads(line) + if (artifact.get("reason") == "compiler-artifact" + and artifact.get("profile", {}).get("test") is True + and artifact.get("target", {}).get("kind") == ["lib"] + and artifact.get("executable")): + executables.append(Path(artifact["executable"])) + if len(executables) != 1 or not executables[0].is_file(): + parser.error("build report must select exactly one native test harness") + if args.out.exists() and any(args.out.iterdir()): + parser.error("candidate kit directory must be empty") + args.out.mkdir(parents=True, exist_ok=True) + executable = args.out / "qualification-harness" + shutil.copyfile(executables[0], executable) + executable.chmod(0o755) + with executable.open("rb") as stream: + digest = hashlib.file_digest(stream, "sha256").hexdigest() + repository = Path(__file__).resolve().parents[2] + if subprocess.check_output(["git", "status", "--porcelain", "--untracked-files=no"], cwd=repository): + parser.error("candidate kit requires committed source") + commit = subprocess.check_output(["git", "rev-parse", "HEAD"], cwd=repository, text=True).strip() + (args.out / "candidate.json").write_text(json.dumps({ + "schema": "auths.qualification-simulation-candidate/1", "simulation": True, + "source_commit": commit, "harness_sha256": digest, + "features": ["loopback-provider"], "production_gateway": False, + }, indent=2) + "\n") + shutil.copyfile(repository / "qualification/simulation/run.py", args.out / "run.py") + + +if __name__ == "__main__": + main() diff --git a/qualification/simulation/run.py b/qualification/simulation/run.py index e4618476e..b93483a8a 100644 --- a/qualification/simulation/run.py +++ b/qualification/simulation/run.py @@ -8,6 +8,7 @@ import json import os from pathlib import Path +import re import subprocess import tempfile import time @@ -23,6 +24,8 @@ def main() -> None: parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("--cargo", default="cargo") + parser.add_argument("--candidate-kit", type=Path, + help="run the downloaded native harness without a checkout or Rust") parser.add_argument("--out", type=Path, required=True) args = parser.parse_args() output = args.out.resolve() @@ -36,12 +39,41 @@ def main() -> None: output.mkdir(parents=True, exist_ok=True) if any(output.iterdir()): parser.error("use a new empty simulation output directory") - source_commit = subprocess.check_output( - ["git", "rev-parse", "HEAD"], cwd=REPOSITORY, text=True - ).strip() - source_dirty = bool(subprocess.check_output( - ["git", "status", "--porcelain", "--untracked-files=no"], cwd=REPOSITORY - )) + if args.candidate_kit: + kit = args.candidate_kit.resolve() + metadata_file = kit / "candidate.json" + if metadata_file.is_symlink() or metadata_file.stat().st_size > 4096: + parser.error("invalid candidate metadata") + metadata = json.loads(metadata_file.read_bytes()) + source_commit = metadata.get("source_commit") + if (metadata.get("schema") != "auths.qualification-simulation-candidate/1" + or metadata.get("simulation") is not True + or metadata.get("production_gateway") is not False + or metadata.get("features") != ["loopback-provider"] + or not isinstance(source_commit, str) + or not re.fullmatch(r"[0-9a-f]{40}", source_commit)): + parser.error("invalid simulation candidate") + harness = kit / "qualification-harness" + if harness.is_symlink() or not harness.is_file() or harness.stat().st_size > 536_870_912: + parser.error("invalid native harness") + with harness.open("rb") as stream: + harness_sha256 = hashlib.file_digest(stream, "sha256").hexdigest() + if harness_sha256 != metadata.get("harness_sha256"): + parser.error("candidate harness digest mismatch") + source_dirty = False + command = [str(harness), "qualification_simulation", "--nocapture"] + working_directory = output + else: + source_commit = subprocess.check_output( + ["git", "rev-parse", "HEAD"], cwd=REPOSITORY, text=True + ).strip() + source_dirty = bool(subprocess.check_output( + ["git", "status", "--porcelain", "--untracked-files=no"], cwd=REPOSITORY + )) + harness_sha256 = None + command = [args.cargo, "test", "--locked", "-p", "auths-gateway", + "--features", "loopback-provider", "--lib", "qualification_simulation", "--", "--nocapture"] + working_directory = REPOSITORY # Provider and signing credentials are not needed and do not reach tests. environment = { key: value for key, value in os.environ.items() @@ -50,11 +82,7 @@ def main() -> None: environment["AUTHS_QUALIFICATION_SIMULATION_OUTPUT"] = str(output) started = time.monotonic() with tempfile.TemporaryFile() as log: - result = subprocess.run([ - args.cargo, "test", "--locked", "-p", "auths-gateway", - "--features", "loopback-provider", "--lib", "qualification_simulation", - "--", "--nocapture", - ], cwd=REPOSITORY, env=environment, stdout=log, stderr=subprocess.STDOUT, + result = subprocess.run(command, cwd=working_directory, env=environment, stdout=log, stderr=subprocess.STDOUT, timeout=1800, check=False) if result.returncode: log.seek(0, os.SEEK_END) @@ -85,6 +113,8 @@ def main() -> None: "schema": "auths.qualification-simulation-run/1", "simulation": True, "stable_launch_ready": False, "source_commit": source_commit, "source_dirty": source_dirty, + "harness_sha256": harness_sha256, + "source_free": bool(args.candidate_kit), "seconds": round(time.monotonic() - started, 3), "families": [summary.get("family") for summary in summaries[:2]], "provider_case_count": sum(len(summary["cases"]) for summary in summaries[:2]), From 926cecad8a35a68ccdfa17b870635e70fab9b865 Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 00:14:40 +0100 Subject: [PATCH 040/108] Support the operator host Python when hashing rehearsal binaries --- qualification/simulation/README.md | 2 +- qualification/simulation/pack.py | 5 ++++- qualification/simulation/run.py | 5 ++++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/qualification/simulation/README.md b/qualification/simulation/README.md index 76e6094ea..167b6abac 100644 --- a/qualification/simulation/README.md +++ b/qualification/simulation/README.md @@ -29,7 +29,7 @@ the trust transition, while provider measurements are separate artifacts. CI also packages the compiled native harness with its SHA-256 and commit. It runs that kit in Docker with networking disabled and no source checkout mounted. Download the `qualification-simulation-kit-*` artifact, make the -`qualification-harness` executable, and run with Python 3.12: +`qualification-harness` executable, and run with Python 3.9 or later: ```sh chmod +x /path/to/kit/qualification-harness diff --git a/qualification/simulation/pack.py b/qualification/simulation/pack.py index 42d5ba0fc..e59bdf3c4 100644 --- a/qualification/simulation/pack.py +++ b/qualification/simulation/pack.py @@ -34,7 +34,10 @@ def main() -> None: shutil.copyfile(executables[0], executable) executable.chmod(0o755) with executable.open("rb") as stream: - digest = hashlib.file_digest(stream, "sha256").hexdigest() + hasher = hashlib.sha256() + for chunk in iter(lambda: stream.read(131_072), b""): + hasher.update(chunk) + digest = hasher.hexdigest() repository = Path(__file__).resolve().parents[2] if subprocess.check_output(["git", "status", "--porcelain", "--untracked-files=no"], cwd=repository): parser.error("candidate kit requires committed source") diff --git a/qualification/simulation/run.py b/qualification/simulation/run.py index b93483a8a..08454b84a 100644 --- a/qualification/simulation/run.py +++ b/qualification/simulation/run.py @@ -57,7 +57,10 @@ def main() -> None: if harness.is_symlink() or not harness.is_file() or harness.stat().st_size > 536_870_912: parser.error("invalid native harness") with harness.open("rb") as stream: - harness_sha256 = hashlib.file_digest(stream, "sha256").hexdigest() + digest = hashlib.sha256() + for chunk in iter(lambda: stream.read(131_072), b""): + digest.update(chunk) + harness_sha256 = digest.hexdigest() if harness_sha256 != metadata.get("harness_sha256"): parser.error("candidate harness digest mismatch") source_dirty = False From 9a0eb4c9c6dac56c975ce73490d33bbad3f29d2f Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 00:25:45 +0100 Subject: [PATCH 041/108] Resolve checkout paths only for source builds in the portable runner --- qualification/simulation/run.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/qualification/simulation/run.py b/qualification/simulation/run.py index 08454b84a..11527f1cb 100644 --- a/qualification/simulation/run.py +++ b/qualification/simulation/run.py @@ -13,7 +13,6 @@ import tempfile import time -REPOSITORY = Path(__file__).resolve().parents[2] REPORTS = ( "stripe-refund-v1.json", "airtable-record-update-v1.json", @@ -28,13 +27,14 @@ def main() -> None: help="run the downloaded native harness without a checkout or Rust") parser.add_argument("--out", type=Path, required=True) args = parser.parse_args() + repository = None if args.candidate_kit else Path(__file__).resolve().parents[2] output = args.out.resolve() # Public rehearsal outputs must never enter the production trust or family # directories that the protected signing workflow consumes. - if output == REPOSITORY or any( - output.is_relative_to(REPOSITORY / "qualification" / name) + if repository is not None and (output == repository or any( + output.is_relative_to(repository / "qualification" / name) for name in ("trust", "families") - ): + )): parser.error("simulation output overlaps production inputs") output.mkdir(parents=True, exist_ok=True) if any(output.iterdir()): @@ -68,15 +68,15 @@ def main() -> None: working_directory = output else: source_commit = subprocess.check_output( - ["git", "rev-parse", "HEAD"], cwd=REPOSITORY, text=True + ["git", "rev-parse", "HEAD"], cwd=repository, text=True ).strip() source_dirty = bool(subprocess.check_output( - ["git", "status", "--porcelain", "--untracked-files=no"], cwd=REPOSITORY + ["git", "status", "--porcelain", "--untracked-files=no"], cwd=repository )) harness_sha256 = None command = [args.cargo, "test", "--locked", "-p", "auths-gateway", "--features", "loopback-provider", "--lib", "qualification_simulation", "--", "--nocapture"] - working_directory = REPOSITORY + working_directory = repository # Provider and signing credentials are not needed and do not reach tests. environment = { key: value for key, value in os.environ.items() From bc18c3922e44584efd88029479d2c4800cbb7ba6 Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 00:42:03 +0100 Subject: [PATCH 042/108] Measure read-back leases in qualification races and fix preflight lints --- ...gateway-polish-and-recipe-qualification.md | 3 +- .../auths-recipe-qualification/src/launch.rs | 7 +-- .../auths-gateway/semantic-closure.json | 2 +- .../src/qualification_simulation.rs | 51 ++++++++++++++----- .../auths-gateway/src/qualification_tests.rs | 23 +++++---- .../auths-gateway/src/semantic_closure.rs | 2 +- 6 files changed, 58 insertions(+), 30 deletions(-) diff --git a/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md b/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md index 28dc47743..b92a035e5 100644 --- a/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md +++ b/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md @@ -1683,7 +1683,8 @@ CI job and needs no external credentials. The local rehearsal passed 36 measured provider cases (18 per family), plus the disposable two-family signing/import ceremony. Each race entered one -write; Airtable additionally used a read-only reconciliation lease. The +write; a concurrent contender may additionally use a measured read-only +reconciliation lease. The candidate kit embeds its fixtures and is run in Docker without checkout, credentials or network. Hosted verification of that packaged run is pending. diff --git a/product/qualification/auths-recipe-qualification/src/launch.rs b/product/qualification/auths-recipe-qualification/src/launch.rs index 0cb27efec..21e600ecf 100644 --- a/product/qualification/auths-recipe-qualification/src/launch.rs +++ b/product/qualification/auths-recipe-qualification/src/launch.rs @@ -134,12 +134,9 @@ mod tests { let records: Vec<&[u8]> = records .iter() .take(if omit_record { 1 } else { records.len() }) - .map(|record| record.as_bytes()) - .collect(); - let attestations: Vec<&[u8]> = attestations - .iter() - .map(|attestation| attestation.as_bytes()) + .map(String::as_bytes) .collect(); + let attestations: Vec<&[u8]> = attestations.iter().map(String::as_bytes).collect(); VerifiedQualifications::verify( &root, &QualificationInputs { diff --git a/product/runtime/auths-gateway/semantic-closure.json b/product/runtime/auths-gateway/semantic-closure.json index c3dbcc3eb..9b5e10161 100644 --- a/product/runtime/auths-gateway/semantic-closure.json +++ b/product/runtime/auths-gateway/semantic-closure.json @@ -1 +1 @@ -{"files":[{"path":"Cargo.lock","sha256":"0e75e2fdef44e79e57797ac6661295ae58ddb8de4a1990a6fd22ce6c54f78604"},{"path":"Cargo.toml","sha256":"6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24"},{"path":"core/adapters/auths-did-keri/Cargo.toml","sha256":"86ba3e3f9a0a70d970568bfb3113b7ba7bbdd81c3eebbb52743dd574a0c0ecaa"},{"path":"core/adapters/auths-did-keri/src/lib.rs","sha256":"a75674842f8a7142004369ccd206ab43e476459293f0ff4bed4d4e659031b3e3"},{"path":"core/adapters/auths-did-key/Cargo.toml","sha256":"d5a3ae07ecde83f91eed4c3785051dd0f44eab6c891754f3309b6b40596707d7"},{"path":"core/adapters/auths-did-key/src/lib.rs","sha256":"b76a3f4528a725df53cfa9242e6e414e1d26caa48468aaed497e28b121f4497c"},{"path":"core/adapters/auths-raw-key/Cargo.toml","sha256":"f49616bc18c19e6aaa7e6a02ccebcdb9f5c1422c1278ef9869e0dbf22ceda7be"},{"path":"core/adapters/auths-raw-key/src/lib.rs","sha256":"45eec1b295dac3bed65cd79c942870b926b06b3f5d38eaebaeb6140ac69315fa"},{"path":"core/crates/auths-algebra-kernel/Cargo.toml","sha256":"0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba"},{"path":"core/crates/auths-algebra-kernel/src/generated.rs","sha256":"ae4bcbef42a408c7ffa0c6a74a42f7de177a6f14479e51d205acf830bda05960"},{"path":"core/crates/auths-algebra-kernel/src/lib.rs","sha256":"6654667eeb9b353d6648954c9fd2e8838462a82ce6b2803eb49e1366892c68c6"},{"path":"core/crates/auths-assurance/Cargo.toml","sha256":"afcb12a97ddd09d7a264b9ecd3fcaefc865ff2c9b4539ee85b00883420ba333a"},{"path":"core/crates/auths-assurance/src/lib.rs","sha256":"0fb2ec844d674b25a9e20b1601452c89c2454901fa506adfa9bb38ef9a7fa213"},{"path":"core/crates/auths-author/Cargo.toml","sha256":"1e6f0e3bc079ddb558decf0db26b291c6e72fc47327b6df1b7650d41689b215f"},{"path":"core/crates/auths-author/src/lib.rs","sha256":"e14475f2f49715a1869d5fa6b11ff1fbb72497e39097e09f833b0bae7e5b3f2b"},{"path":"core/crates/auths-author/src/observations.rs","sha256":"dda7d6bfa6f4bd7e95a480ca283c2c0e996f69c5c15cb0c7197af328131a7066"},{"path":"core/crates/auths-authority/Cargo.toml","sha256":"4f68212938029f79ebd857b4f3038494eb85d0163d49f07e51376715cf959815"},{"path":"core/crates/auths-authority/src/lib.rs","sha256":"da88d5194de4e17449e69972c0fb042afa3c39798a8f570f30771e77c384f1eb"},{"path":"core/crates/auths-codec/Cargo.toml","sha256":"e20e51826e17814effd9d8925d18d5fbdd6c0d37bf50231e743ec2611314722c"},{"path":"core/crates/auths-codec/src/approval.rs","sha256":"fbff43bf4d57f69f8b7738a8647751cde75c5a932dee65d924a1fe9c7202f91f"},{"path":"core/crates/auths-codec/src/bounded_policy.rs","sha256":"d21f6728be2d8a04b6d94921f2b683f7e61cbb42e0ac6866f1c88a49caa534c3"},{"path":"core/crates/auths-codec/src/decode.rs","sha256":"ba2999584cdf53b1b517ecb9c7ea50d39efee17c666a9a38e2ad1ac94379f778"},{"path":"core/crates/auths-codec/src/encode.rs","sha256":"8491192053e2e15d62b4d2a491de22405b7487ead69ab6f6bca40669ce7ca5f7"},{"path":"core/crates/auths-codec/src/error.rs","sha256":"fecb0737c16deb42d859f1dc7727c698438d9ac12064fd99e0024629642c390c"},{"path":"core/crates/auths-codec/src/hash.rs","sha256":"f88e111f1dbb2cef6b7b5e9c948cb45ff92e366710c8a5f5c636138aa748479e"},{"path":"core/crates/auths-codec/src/lib.rs","sha256":"3b0e5c94c6f34f750b88a9333e1d5c8145746d845d3a23e0d2f61807cf592ea7"},{"path":"core/crates/auths-codec/src/observation.rs","sha256":"38328b0c71ff97a4196eeade8b4faa889527ff1f80bb168468bcd49082a3987e"},{"path":"core/crates/auths-composition/Cargo.toml","sha256":"331e13025eb82588b5269ed3975929eb41c823d588c49e4c296273d85c6fe80e"},{"path":"core/crates/auths-composition/src/lib.rs","sha256":"e42e3b0b6a9985b73c533aeb23799c638979aa27a9ce7d0f10a8d60340570fb1"},{"path":"core/crates/auths-model/Cargo.toml","sha256":"565c15302b0cc9270db1e28efa3862804846850ba933cc17aea8abcec4a65987"},{"path":"core/crates/auths-model/src/approval.rs","sha256":"54cf44a9ef747ec21546a4086aecfb130bc7803b0d646430e6082df51e6e305f"},{"path":"core/crates/auths-model/src/bounded.rs","sha256":"f90496abc0a06c028b4d850af6ddab7d850bfafeaa3d042f1b1246a41d8bbbc9"},{"path":"core/crates/auths-model/src/bounded_policy.rs","sha256":"306a8f049cc7cfc7635fe0e4de47eb7813eed63d3c14c3be2b51586aa4eea450"},{"path":"core/crates/auths-model/src/lib.rs","sha256":"e7cfe6bb9574c6b016aa63e70658c31e0b90903ec6479a49f4a2ceb64f5bad97"},{"path":"core/crates/auths-model/src/observation.rs","sha256":"b3ed3e3cc090afca2896a7d3de7988afccc1ee1ea0ebd91b51a8bc0f20ad8dbb"},{"path":"core/crates/auths-multikey/Cargo.toml","sha256":"858756c1197befcada06134742bffe8d58cf674cadd6c046bf710570e96efaf2"},{"path":"core/crates/auths-multikey/src/lib.rs","sha256":"f5177fffb11e40eeaaa665ba886c541fc1f24d5eacdd6983fb03dc20148733f0"},{"path":"core/crates/auths-ports/Cargo.toml","sha256":"596a9b0f5af3717c16a6d13f7054d8a106bcd9f01f5f72c2235dd2afcf0ab16c"},{"path":"core/crates/auths-ports/src/binding.rs","sha256":"a16c012d40aa4249e3ec54372b9611006d0bfe8c7dc3c741911c2194ad17736d"},{"path":"core/crates/auths-ports/src/diagnostics.rs","sha256":"aa596572503b5a65a918bb2ff38281c144ff53821ee914e9325c852828d852df"},{"path":"core/crates/auths-ports/src/lib.rs","sha256":"8da1debf86f9532df0660155d04298beb1ba3a1204508f8586e2e67cd2fb3449"},{"path":"core/crates/auths-ports/src/path.rs","sha256":"b68fc547b4e4d97a60cbbc1cc1939fc6b34a8233b81f840bd396914a707e3ea1"},{"path":"core/crates/auths-raw-key-core/Cargo.toml","sha256":"98c0bc8527a537512e43a74dd6ba9658c6f0cdc16610cf938e3f9b43785d836d"},{"path":"core/crates/auths-raw-key-core/src/lib.rs","sha256":"98c0500c41697aae28708ad0bf970b9a97583d96a3d2c18d23e7fa351e0f7d12"},{"path":"core/crates/auths-registries/Cargo.toml","sha256":"590e49e58b0622d9d6274fea46796dcdb07dec9550eff295cce6a6427ffa51e2"},{"path":"core/crates/auths-registries/src/lib.rs","sha256":"450d3886d85ee333b7e046317fb5b47cde62483d5f3e41d46265e2caf4c373ec"},{"path":"core/crates/auths-registries/src/template.rs","sha256":"1224039dd2b3ce6fa8357613d8cafbae40400493da7176da202b9ade62fa05e4"},{"path":"core/crates/auths-signature-core/Cargo.toml","sha256":"6bee2230eb30af1be0bd5c2d57bd3e1903497a70028d47290d4ac6e9e0e8bca0"},{"path":"core/crates/auths-signature-core/src/lib.rs","sha256":"6e3f9311ded5e49ea50d445eb21e6d8fa12442aa4362a73e0cb6fda15b7cd865"},{"path":"core/crates/auths-signature/Cargo.toml","sha256":"7f7b5682466ba439d8c59579022cb61068cad9fb4bd2d73e1cc21327c902b450"},{"path":"core/crates/auths-signature/src/lib.rs","sha256":"b3d9ac4cc3ba0797b9e1c09f2d6ac05089b25dac4e285a5af28c0165b33d925b"},{"path":"core/crates/auths-verifier/Cargo.toml","sha256":"c43358e06a33324b41a8b93e5cc7279c55f7d21f1f6cfaa539a3fc7b4c27a38f"},{"path":"core/crates/auths-verifier/src/approval.rs","sha256":"c3cae6a49e169051eb555bb092b1069a4d422516d6a2114623a89e5f31ff923f"},{"path":"core/crates/auths-verifier/src/causal.rs","sha256":"9635230f33b13a263573d319ac8a1976addbcc07677514a43e3c7bf28dc04587"},{"path":"core/crates/auths-verifier/src/lib.rs","sha256":"f22dec38dfa47ced8da4f605390da8453273bee1da010f57fd1fdfcb10e0b389"},{"path":"core/crates/auths-verifier/src/observation.rs","sha256":"0bb07f06a0f9524c88427df1c972b1de8ba038a9eeeb15d3134c25125ae84b1e"},{"path":"core/crates/auths-verifier/src/trace.rs","sha256":"2213d72023a1d9e0413a2cf2c51c3dad9e04775d86033a0caaa9d29a8f0036f8"},{"path":"exchange/crates/auths-proof-exchange-model/Cargo.toml","sha256":"34b2db64f93a288e942b5a3918d28cdcbef906e0dc9074ce848018d3d5f7a1fa"},{"path":"exchange/crates/auths-proof-exchange-model/src/lib.rs","sha256":"49fac5aff2339d3a57c41cb8bb2a82852538e8f77ecc4b157c88e264ff31fb55"},{"path":"exchange/crates/auths-proof-exchange-port/Cargo.toml","sha256":"7ff660f1b7579dc570c791090aeb450404fbbf44c92781e289f5ccdde746d739"},{"path":"exchange/crates/auths-proof-exchange-port/src/lib.rs","sha256":"b408fb40c6432edc1facb3d8b3e9433a033f8dc73fe2e0ba5a88c972ca675021"},{"path":"product/config/auths-config/Cargo.toml","sha256":"e4b568ab9f6d84f7d7e6d66443fe825f360db9c27bc7c31d6ddc0647ba3ab304"},{"path":"product/config/auths-config/src/lib.rs","sha256":"fecf00ea65cef9018fda9af2063326d7065b869266d0d9e73a4f06816f1102cc"},{"path":"product/errors/auths-errors/Cargo.toml","sha256":"3b3a199b6460ba75bda84475bb5accd35e1485448a3981038db85bf4772dd350"},{"path":"product/errors/auths-errors/src/lib.rs","sha256":"7feeb9069fa4003f94f1f07c1c94619cf1c883e0dbaaf2187f04d0f742264bdd"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/Cargo.toml","sha256":"716f1f2a117d6d69d8effe9ee9057e24ba3502f20af6a602b06facb638cdabed"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/api.rs","sha256":"9ea61dd7ddd93282b073b98e453e6b75b26dc49689c04e9782435d06a3a09e48"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/clock.rs","sha256":"73f0a6e0f5903883329fa6683f5888288f759512ac69e5c87efd2b6b87f7d79f"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/http.rs","sha256":"14c1fce14e24c984b2a275563a29b6326fb08367922b6e8d37ba38b9cb81aa2b"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/identity.rs","sha256":"186de11230c8b33375951c4368609f8976bf9795f171af3fd7fac26207a94361"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs","sha256":"0b4617d044f5254a5ab22f5a2578f91cc025206a8c1845be39c1c56dcdf7a5df"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/names.rs","sha256":"41bb23572d6002e23ee103d6fe70ecd68764861c6f2e48a1c53af998270a4afa"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs","sha256":"39fed883f4802e68d3b41a68fea0aba0737810996b33d13577de70faba004c29"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/store.rs","sha256":"fc60ee9c49b2f4f063c449b4c78100c5c4872779e94ca168f796603b380ef6e4"},{"path":"product/integrations/auths-custody/Cargo.toml","sha256":"1e14034185ad1ec24a977fd5f41d0abee219606245c046ce2a82287fadef448b"},{"path":"product/integrations/auths-custody/src/conformance.rs","sha256":"8ed1afd58f18fc6becc268908aa6419c9aa404c79da0197963eb2599df44acf6"},{"path":"product/integrations/auths-custody/src/key.rs","sha256":"70cbb0fd21b6f5652157845a22c35be2d0f6c05b3d138fc4b9bb6dbdc3d81c40"},{"path":"product/integrations/auths-custody/src/lib.rs","sha256":"8ee593c1f59b0fd2126bdda9138026f5bc531beb64d4489a99785842e7b98b43"},{"path":"product/operations/auths-operations/Cargo.toml","sha256":"73dde1e914ba5e1386f8d49c0d730423cc72ae77ec44c6554a6a75cc8e8922b1"},{"path":"product/operations/auths-operations/src/explanation.rs","sha256":"b4a39bcbd5712cb9e735ee7deeb281f3fa6af5ddca973735bf3d87dce427ef11"},{"path":"product/operations/auths-operations/src/lib.rs","sha256":"3f401a56555113b98f57bca172a2660eaecedf76247b83a3fdbb089c133a29cd"},{"path":"product/operations/auths-operations/src/render/json.rs","sha256":"2ae042639960afee123730e945d373bc5dda1d2b3af20ae16c939a7e99b9e418"},{"path":"product/operations/auths-operations/src/render/mod.rs","sha256":"b3b7f6fe473f49227ace5a68bfc3d8dc14b5db8dd9888fd9e207070337b1b8bf"},{"path":"product/operations/auths-operations/src/render/text.rs","sha256":"f216cf3bdb00e264523271b16e7059535ac6b1aabf271cebd7935af155e4bfec"},{"path":"product/policy/auths-bounded-policy/Cargo.toml","sha256":"babd5d200923137ead71d8c2528f847cea323ce98da942a1320b054436612c47"},{"path":"product/policy/auths-bounded-policy/src/arithmetic.rs","sha256":"75e43c5d4eab8d1f71c1daf53839f5f9fe45a400afc1f63a30c6f55ce3632627"},{"path":"product/policy/auths-bounded-policy/src/commitment.rs","sha256":"c5706f2d583454e1a7f570f7ada138d4d864bef0205dfae7c1296774f396bb3f"},{"path":"product/policy/auths-bounded-policy/src/eligibility.rs","sha256":"c9acdfb793074e687fc36efad506be27dbd99ffbf40387bc66c8de39ef238432"},{"path":"product/policy/auths-bounded-policy/src/identifier.rs","sha256":"0006a32bae9eb16c4178cf797df418d2b0a781f2bc6474b741dc1a908141831c"},{"path":"product/policy/auths-bounded-policy/src/kernel.rs","sha256":"99187c28b161ac70bee1afed60711f7f645adb4d1671a01863f9849b369811d5"},{"path":"product/policy/auths-bounded-policy/src/lib.rs","sha256":"76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c"},{"path":"product/policy/auths-bounded-policy/src/receipt.rs","sha256":"3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad"},{"path":"product/policy/auths-bounded-policy/src/registry.rs","sha256":"4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0"},{"path":"product/profiles/auths-profile-api/Cargo.toml","sha256":"7ae85761f58625b5d678f961fd052eebf3e000ef565c7312e3ac857763c0017f"},{"path":"product/profiles/auths-profile-api/src/lib.rs","sha256":"a194b82b20bf8aa864c2334ef6c6aec30b2154ded972862252d5dcefa488ab95"},{"path":"product/profiles/auths-profile-mcp/Cargo.toml","sha256":"db264fc25242f7b7e4133cbe5782545b3107b406c87168ae072683cfb59eac66"},{"path":"product/profiles/auths-profile-mcp/src/arguments.rs","sha256":"a5de696586d507e2aee4a49fee99ef1ef4c51a2e46603f8838f1af6d9009833f"},{"path":"product/profiles/auths-profile-mcp/src/lib.rs","sha256":"d0f8b733a09ef8408336cdebc8948d6a5861012ce6878598b11be7084dfd4280"},{"path":"product/profiles/auths-profile-mcp/src/session.rs","sha256":"166c281fa66333388e4760d6098dad02d3359e1d5de4b8f93312c014f97abb03"},{"path":"product/qualification/auths-recipe-qualification/Cargo.toml","sha256":"b7b15b30b9a3d96d4f089d514266d3a892de6608d30707aa44be31cca89ca9fe"},{"path":"product/qualification/auths-recipe-qualification/src/canonical.rs","sha256":"30a9b50777f0dcb4b606abfee2467d5a975d9f6ad941ab6c13ca3df5b359f667"},{"path":"product/qualification/auths-recipe-qualification/src/closure.rs","sha256":"0ad6aee9bd981e2863fa725f209ec84031db2ff12f4c7ac3aaf5120f0bb86039"},{"path":"product/qualification/auths-recipe-qualification/src/error.rs","sha256":"52d5cf720a1e4579008fdda90a3ac2c31f0b8db57985f121f65e54b4da2b7dd1"},{"path":"product/qualification/auths-recipe-qualification/src/evidence.rs","sha256":"ba45a7409d67a8af26ab811af306412014557477a101ab2a8eb0faf8f2bd4b91"},{"path":"product/qualification/auths-recipe-qualification/src/ids.rs","sha256":"e81a906d571497ab2da753e1532d4443706410e0b75fdd59a7d2d788c7aec403"},{"path":"product/qualification/auths-recipe-qualification/src/launch.rs","sha256":"17ba2534a26b3a2e16a515e783403b1c3b2771a3ed184d4f4ac1dc5684e5582d"},{"path":"product/qualification/auths-recipe-qualification/src/lib.rs","sha256":"5c9cff04c8960df805a2f7656cf5e74932798e0db7648341e96ae7073a592404"},{"path":"product/qualification/auths-recipe-qualification/src/model.rs","sha256":"3484eb0ec287b23d4682ade7b1b0f8d1335985b3fb180f06fc28716076957d5f"},{"path":"product/qualification/auths-recipe-qualification/src/release.rs","sha256":"d816b53e2275e902c750ad03803061844e259e28560ab2d1c77e8a43981a4d6a"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/mod.rs","sha256":"7f15b68e05a04f202bcb1fb80de1d9a9a4fda8bfd6af2cd4e5c660fc75d96fe5"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/schemas.rs","sha256":"c59feec2805621f341a90f81fc005e2c12f7a70f9d264fdeacccb2be4fe1c046"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/verification.rs","sha256":"6a6b5834c5dae10af1ba8939b2deae43b85db71544dc8f077ff63b7fe68ac8a8"},{"path":"product/qualification/auths-recipe-qualification/src/verify.rs","sha256":"a470a9b98c04dc8d5dabe4d3dc8ed4e7a3ceb1cde035944a0714462bbf37d56d"},{"path":"product/receipts/auths-receipts/Cargo.toml","sha256":"6001fa1375899953aafcb07c23a6da0c8f57ea7ec08bb9c950b12a60a8cc6f0f"},{"path":"product/receipts/auths-receipts/src/disclosure.rs","sha256":"ba9ed439be0a320c8a01f5b6e9b51361c1a37e076947490d8e4a484ba6bb119c"},{"path":"product/receipts/auths-receipts/src/lib.rs","sha256":"547a57c4160256719cafb7d0ab972d9fc80b0da14fbbce4148c70c414070ff36"},{"path":"product/runtime/auths-connections/Cargo.toml","sha256":"babeb6e1dda3dfb66291713ce1e43dce5c349833d0b50ea4dccbf986030026b2"},{"path":"product/runtime/auths-connections/src/credential.rs","sha256":"82921413bb053f0f6c7931fbd4e6a86c8cc1d8c6b51debd9c2cef33a8d5b1c51"},{"path":"product/runtime/auths-connections/src/kernel.rs","sha256":"a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8"},{"path":"product/runtime/auths-connections/src/lib.rs","sha256":"79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22"},{"path":"product/runtime/auths-connections/src/model.rs","sha256":"de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77"},{"path":"product/runtime/auths-connections/src/registry.rs","sha256":"e57640e003e72ad3235c567c2bb944a262bd64e673f023b62ea091094cc7e946"},{"path":"product/runtime/auths-gateway-kernel/Cargo.toml","sha256":"34f864e67656af4ac7e5c7a347a23f01fc8ab31365b8e23c0ef474483b14a183"},{"path":"product/runtime/auths-gateway-kernel/src/construct.rs","sha256":"e9d65744bae273d65face4285e5d2da75c06a92ab48f7b8333d496604e31c63c"},{"path":"product/runtime/auths-gateway-kernel/src/lib.rs","sha256":"cfda6f8453426564c085475f183b6f790b438768a19668f1b65d33ba59dc8632"},{"path":"product/runtime/auths-gateway-kernel/src/order.rs","sha256":"e0045f877c4b7fe3860c291039853885064ddcdebba7c9b345ab65e81e646dda"},{"path":"product/runtime/auths-gateway-kernel/src/outcome.rs","sha256":"e9785b1afe70788c89b51b18655bcd5acff7b0c8e3d12fb79c6f05a202e67e6b"},{"path":"product/runtime/auths-gateway-kernel/src/ratio.rs","sha256":"7ace22264812e6fc1ef3a62afee402cf43494bb71ae0d3de219ad1b39d690bcb"},{"path":"product/runtime/auths-gateway-kernel/src/recovery.rs","sha256":"9f46dcd1685ab6e4d1ba04a3fc286a9f3afee8fb47829be1fbc670a7926a2dc6"},{"path":"product/runtime/auths-gateway-kernel/src/transition.rs","sha256":"cefb8f01d915880f6921f2501ff881ad94b9de61072c34d9cd19220992f97374"},{"path":"product/runtime/auths-gateway/Cargo.toml","sha256":"00b28be86921dcdc0ad90cce0c62c2961cafefe96ea6c2edf0e926c3d405ccad"},{"path":"product/runtime/auths-gateway/src/admin.rs","sha256":"2d5cc67afac42fbd15f36e2d1693cd1b20cedacf775040dce6ffe04ccc94c9ea"},{"path":"product/runtime/auths-gateway/src/app.rs","sha256":"6f80f63833ea0815bb44fbf3b0cc54624a08e9fb578b035819f2980dc04e8256"},{"path":"product/runtime/auths-gateway/src/audit.rs","sha256":"0edb2037eb7b5d6f13acfce85c54f62a82bf7fdd31bc7e626c4fec183cef61dd"},{"path":"product/runtime/auths-gateway/src/audit_tests.rs","sha256":"990969384a52d75bc2489d9d412a9e7dd814bca1c8f65c701d6205fae62a15d5"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway-harness.rs","sha256":"12b0c24d36b2e6a3be392d3c081a783b355fdd67dc5b54bacc0410e803116b8c"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway.rs","sha256":"2f33a1da5dd54947ee1664795f90b3f07a11bb9ee184774bf470b78b03600f0c"},{"path":"product/runtime/auths-gateway/src/binding.rs","sha256":"663b0ce878319511aa7d05722ab4ab2fa9be18817884ffb2ee9f131ff1e382d1"},{"path":"product/runtime/auths-gateway/src/bounds.rs","sha256":"9cfa0eae4973e5e047a198360b22f041708fa20276b0b90c2ec440f06915d64b"},{"path":"product/runtime/auths-gateway/src/bounds_aggregate_tests.rs","sha256":"ab34f227b7c8692ba1da88ccb32bb3687a66adf8353d8282fae905d4a88eb612"},{"path":"product/runtime/auths-gateway/src/bounds_tests.rs","sha256":"74136bc570da7b9338b5a1a1ed9d3fd892c55135160964f9d3ac0e2cf5741375"},{"path":"product/runtime/auths-gateway/src/connection.rs","sha256":"7b5d049c258a26ed1c93ecf860f51d051a8a65f9b93554af0b1ea93862398ec9"},{"path":"product/runtime/auths-gateway/src/credential_journal.rs","sha256":"7297fccaee5cd8622928e8e0a42bba50da7941970a6f682ecd300c41ee6509da"},{"path":"product/runtime/auths-gateway/src/echo_verify.rs","sha256":"6d453051665f823abd7354d5c50031d9524cf47d6092d2f09080ae814e3b9575"},{"path":"product/runtime/auths-gateway/src/engine.rs","sha256":"f1052aaef43e441b9e0befa3f8ad1e2fd5279a27cb9d63aac0cf9dfdbe85a052"},{"path":"product/runtime/auths-gateway/src/fuzzing.rs","sha256":"ed3b0028487eb546a3b0a91d115aa8f18bcea324b61620bfe8e35a9e6ab18758"},{"path":"product/runtime/auths-gateway/src/generation_floor.rs","sha256":"fe1510ec96ce0f67e9a78edbfa94b33eb7df64c0ac4d0a67901124dcd0164777"},{"path":"product/runtime/auths-gateway/src/harness.rs","sha256":"c87e479f3eb281960f6c9c80d43c7560d7ccb654b0154ec823d3fcec4884ac05"},{"path":"product/runtime/auths-gateway/src/lib.rs","sha256":"4674c497940ab339d9b755b71a3e1fe5feeba28bfecc025b7d148dc804a508bf"},{"path":"product/runtime/auths-gateway/src/listener.rs","sha256":"aa08239bcbc1fcb55e8a212fbdf6a84f12985b0d436dcb51dc58b06e59e435f2"},{"path":"product/runtime/auths-gateway/src/observed_tests.rs","sha256":"a22be071695f89ca2578a4d82fd80d9cb82289213c9bdb8f0470f6b2dc3d9201"},{"path":"product/runtime/auths-gateway/src/observer.rs","sha256":"562ffcaea071c3856e0708dc2fe33516917e145d2438aabb75af0a2b6ba01046"},{"path":"product/runtime/auths-gateway/src/onboarding.rs","sha256":"0dfd7d67e7f02f18a28d1c86ca1b7751d7463f5efcdbe3825de0ad8cbccb3891"},{"path":"product/runtime/auths-gateway/src/operator.rs","sha256":"c3c36954a3e86723df035b47f43b85fc8ab3a6292983522b6258d5c6b4e6c4e4"},{"path":"product/runtime/auths-gateway/src/pending_vectors/attempts.rs","sha256":"47ef3c8cb1c5504d47ae9a0088705ce6715fe86bac1671a34a56fb38a64d0dd3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/bounds.rs","sha256":"e612217307e1da5b0eb5ee6582a7458bb064b8aa8a529fc6555b1b334127ab68"},{"path":"product/runtime/auths-gateway/src/pending_vectors/codes.rs","sha256":"e00670a5ef24eb856cc2c6dcda8e5a263842f55c76bb939c0c27bd9df37e5522"},{"path":"product/runtime/auths-gateway/src/pending_vectors/keys.rs","sha256":"f84c56f2ea9cb34b2b79c72d13fbf2c6585010ec1ed450af58a78c80c1ea1edd"},{"path":"product/runtime/auths-gateway/src/pending_vectors/mod.rs","sha256":"5de8340f0ef71a0b57a09e323fefe473d3160c6ae952b9ba46f714825fbacafc"},{"path":"product/runtime/auths-gateway/src/pending_vectors/outcomes.rs","sha256":"8ec07b9511b48913af36ac999d2aa0e82924289f6acb23ddaeb9f00f99815166"},{"path":"product/runtime/auths-gateway/src/pending_vectors/production.rs","sha256":"f574cabfa4687a4fc846b8f6a234b68ec53b876aed548b11445729cac1a55ede"},{"path":"product/runtime/auths-gateway/src/pending_vectors/recipes.rs","sha256":"51693208270231c25c3aef2a32151d5962114c71e86b88cb9df83181c7af83d9"},{"path":"product/runtime/auths-gateway/src/pre_entry.rs","sha256":"06ea78ca140468bfaba17d9ab04912ad68673954c3203c98fed28272ff2a00c0"},{"path":"product/runtime/auths-gateway/src/property_tests.rs","sha256":"939c081e2e154aaf10186754044bdd65608932c899b970a04a71d0afaa999a93"},{"path":"product/runtime/auths-gateway/src/qualification.rs","sha256":"06b49d3fc2ad4383f9e23beefa96033f1fd6e415e043878327583451a53086cc"},{"path":"product/runtime/auths-gateway/src/qualification_simulation.rs","sha256":"878bd4a0955c725bdcae9242f731bd4f9f82238fb6a26aadd230134ef8fd2dfe"},{"path":"product/runtime/auths-gateway/src/qualification_tests.rs","sha256":"020c83bb4bc80bcf0ecdc20d95a7aba5842e1e9dde3f2cb2a519e13926ad54eb"},{"path":"product/runtime/auths-gateway/src/quorum_tests.rs","sha256":"a78380b019104d688c11a4410082c7e08ded3106aab099954c4f8a1b4ae0fd89"},{"path":"product/runtime/auths-gateway/src/readiness.rs","sha256":"911c3f11892f94641574375e2da4c671c802738f71082f12c39832331052d43d"},{"path":"product/runtime/auths-gateway/src/recipe.rs","sha256":"fecf9af67e7afc48d080e9f8f55f8ce28e49d0e08988717a27908bbda461d6b6"},{"path":"product/runtime/auths-gateway/src/recipe/lower.rs","sha256":"8088b8751ed831dbb48247af953c6290ac95e2a438ccd5bd65eff54be06a1fd1"},{"path":"product/runtime/auths-gateway/src/recipe/review.rs","sha256":"c3eb7d9fdd98dacf52750b14b67ad7b7faaecbbdeafff1e0b049f67d0a2d0139"},{"path":"product/runtime/auths-gateway/src/recipe/runtime.rs","sha256":"c286f0d15f974402822c0810d8e97f98411dc1c557755cc23e540d85e2bb42d9"},{"path":"product/runtime/auths-gateway/src/recipe/source.rs","sha256":"1af50298fb1461e1b24cbdf560d43124d6b1c4c529586c911b1c4797214a69ff"},{"path":"product/runtime/auths-gateway/src/recipe/tests.rs","sha256":"aac551a2481bbc60864c64079bc667dcb232e45a0f41a04073ed84ab5dbe1fce"},{"path":"product/runtime/auths-gateway/src/recipe/validate.rs","sha256":"3711b17605cb7b0d639bc1b180449231f5882a306cab20e2c7782155cc63b0d4"},{"path":"product/runtime/auths-gateway/src/scenario_tests.rs","sha256":"67915828ecfe2be0afadb5525277ab205f91172edc90852ec7b77c63b2d17fdc"},{"path":"product/runtime/auths-gateway/src/separation.rs","sha256":"be9306848ca5d801767cf6aa14247c8618312ef0e202f00ce0c24c4844491061"},{"path":"product/runtime/auths-gateway/src/store.rs","sha256":"1e5288345c2cb1421aeda277b3158d07607404b0ec46943222ac107b63dcbb46"},{"path":"product/runtime/auths-gateway/src/store_testkit.rs","sha256":"88d82fee42f1b8ef521e8deef0216e938ebeaad822eb2f5020e70b89d145ea70"},{"path":"product/runtime/auths-gateway/src/submit.rs","sha256":"c78dbbba7c45b443febf655056c5edcd635e77be7b21c5b2c318097502415ffe"},{"path":"product/runtime/auths-gateway/src/support.rs","sha256":"9fd979029793a22b15d9776a7fc172476fd7c126a80d4080c65d720845becbcb"},{"path":"product/runtime/auths-gateway/src/transport.rs","sha256":"be2c6dc75b8daec110bf8749fedc3823f6067d40b999aa3eb21126896a97d3ad"},{"path":"product/runtime/auths-kernel-runtime/Cargo.toml","sha256":"926bcd0053e5edd703be8f0027ad009e2982db013c8174c1366edbf38b48087d"},{"path":"product/runtime/auths-kernel-runtime/src/lib.rs","sha256":"7108faae9ca4bc32dc093ddaf885ac8f74f3c9b8d317b7c7d0ed00d1d0ab5972"},{"path":"product/runtime/auths-lifecycle/Cargo.toml","sha256":"c5053c705f8d5554b44e432fe75287a2faf11d644e5a2552e45ad6cd94176af5"},{"path":"product/runtime/auths-lifecycle/src/codec.rs","sha256":"51c4b746749150e8bfcd8ff972b3f6c1ef40bec15583448ec1b471d9ad737dc0"},{"path":"product/runtime/auths-lifecycle/src/digest.rs","sha256":"55282cd7d8aba37713c2dcb5357c9877819edb72a30eadefb860d28d7d3a3eb7"},{"path":"product/runtime/auths-lifecycle/src/identifier.rs","sha256":"31620e8c16de68d3d2d3b84d6353c1a5b9d4151d8247f91fa389b906a8e660f1"},{"path":"product/runtime/auths-lifecycle/src/kernel.rs","sha256":"2abb8c094b36d35b364e74d78091d14c5d6f3d1eb6552cca3b5538dbd017ce23"},{"path":"product/runtime/auths-lifecycle/src/lib.rs","sha256":"afe5a345cd309b5a4f08ffba3170a6d7f16ff914892b3f2006d5208ed24ec736"},{"path":"product/runtime/auths-lifecycle/src/model.rs","sha256":"1af12bbeeeaa65ec02ddcebd7d2c8c92ec1e339fa40ae85b45ab9b01a722a4fa"},{"path":"product/runtime/auths-lifecycle/src/operation.rs","sha256":"78e6d05fcf5d7ea4f148032a3fa26fdfcab77eb346019effe927b08e0d64d732"},{"path":"product/runtime/auths-lifecycle/src/registry.rs","sha256":"53495fe6f7a77422593a41623e28716f1c140dcc1e00f87f6b0ffbfb93a5ef90"},{"path":"product/runtime/auths-lifecycle/src/sealed.rs","sha256":"2e0c03b5813c926c159598bb7890d1523825edbe57cd687d42a5dfb3374a0c19"},{"path":"product/runtime/auths-lifecycle/src/test_support.rs","sha256":"221d9a5c5ef8e1f9f8fd66927484eaf813571d0568470278ecd8fa08a5eec8cd"},{"path":"product/runtime/auths-lifecycle/src/transition.rs","sha256":"011805a28efdd541f44ccea54dd0e34a1e58f4004447ee58013703b4fb6b2822"},{"path":"product/runtime/auths-runtime/Cargo.toml","sha256":"dd29d80a8b4bb56c869f036a6c9998f6e6d1c0383ac5dc03fa42b24abe2a7ff7"},{"path":"product/runtime/auths-runtime/src/lib.rs","sha256":"132ca03d58c14905d3a822a4972f42a22a5ad33a45f2ba9ca44f3a57d810b4b0"},{"path":"product/runtime/auths-runtime/src/production.rs","sha256":"fd4eff4270c571c10fcff6cf27df28961ebf074de8a1a028f500fda1ca376820"},{"path":"product/sdk/auths-approval-quorum/Cargo.toml","sha256":"df904971fca87a24194c5816738a331588fe8f164acb5d70839a35dca5f57114"},{"path":"product/sdk/auths-approval-quorum/src/lib.rs","sha256":"72e4086088a1c0912e4e1a9e980f26a5c280bf5ab16ea39c9f0f58d5096ac2ce"},{"path":"product/sdk/auths-approval-quorum/src/remote.rs","sha256":"9fa029c7c63003adf260f8aec55160c545681c60c1bace0d934e7525862aac7b"},{"path":"product/sdk/auths-approval-quorum/src/remote_tests.rs","sha256":"8a09ce17cfee82a035a74edd535f3ebeb3db0e078784740d3997b17dbdb10197"},{"path":"product/sdk/auths-approval-quorum/src/tests.rs","sha256":"0acbf12be3e497dcc6c2d8f29c9af3b1a7ed8e11b75f6399570d4f217a785060"},{"path":"product/stores/auths-stores/Cargo.toml","sha256":"a32c4b76d17b264be5d40d24497ff237e1ed87822e8bab86229b3db93106dbe3"},{"path":"product/stores/auths-stores/src/gateway_attempt.rs","sha256":"185da8f4a220fba836d5b78a9311f03204681c43a3c53951008084d135bf4d21"},{"path":"product/stores/auths-stores/src/lib.rs","sha256":"e721262edf8a9ab5568ddc27639176312d4a366203b5f73e2d7c11fde2c554e9"},{"path":"product/stores/auths-stores/src/lifecycle.rs","sha256":"94f64d25bc178a9e60ba3c0ee6915d7fb3af7c4468792d76b4e70f43f4de1e2f"}],"schema":"auths.gateway-semantic-closure/1"} \ No newline at end of file +{"files":[{"path":"Cargo.lock","sha256":"0e75e2fdef44e79e57797ac6661295ae58ddb8de4a1990a6fd22ce6c54f78604"},{"path":"Cargo.toml","sha256":"6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24"},{"path":"core/adapters/auths-did-keri/Cargo.toml","sha256":"86ba3e3f9a0a70d970568bfb3113b7ba7bbdd81c3eebbb52743dd574a0c0ecaa"},{"path":"core/adapters/auths-did-keri/src/lib.rs","sha256":"a75674842f8a7142004369ccd206ab43e476459293f0ff4bed4d4e659031b3e3"},{"path":"core/adapters/auths-did-key/Cargo.toml","sha256":"d5a3ae07ecde83f91eed4c3785051dd0f44eab6c891754f3309b6b40596707d7"},{"path":"core/adapters/auths-did-key/src/lib.rs","sha256":"b76a3f4528a725df53cfa9242e6e414e1d26caa48468aaed497e28b121f4497c"},{"path":"core/adapters/auths-raw-key/Cargo.toml","sha256":"f49616bc18c19e6aaa7e6a02ccebcdb9f5c1422c1278ef9869e0dbf22ceda7be"},{"path":"core/adapters/auths-raw-key/src/lib.rs","sha256":"45eec1b295dac3bed65cd79c942870b926b06b3f5d38eaebaeb6140ac69315fa"},{"path":"core/crates/auths-algebra-kernel/Cargo.toml","sha256":"0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba"},{"path":"core/crates/auths-algebra-kernel/src/generated.rs","sha256":"ae4bcbef42a408c7ffa0c6a74a42f7de177a6f14479e51d205acf830bda05960"},{"path":"core/crates/auths-algebra-kernel/src/lib.rs","sha256":"6654667eeb9b353d6648954c9fd2e8838462a82ce6b2803eb49e1366892c68c6"},{"path":"core/crates/auths-assurance/Cargo.toml","sha256":"afcb12a97ddd09d7a264b9ecd3fcaefc865ff2c9b4539ee85b00883420ba333a"},{"path":"core/crates/auths-assurance/src/lib.rs","sha256":"0fb2ec844d674b25a9e20b1601452c89c2454901fa506adfa9bb38ef9a7fa213"},{"path":"core/crates/auths-author/Cargo.toml","sha256":"1e6f0e3bc079ddb558decf0db26b291c6e72fc47327b6df1b7650d41689b215f"},{"path":"core/crates/auths-author/src/lib.rs","sha256":"e14475f2f49715a1869d5fa6b11ff1fbb72497e39097e09f833b0bae7e5b3f2b"},{"path":"core/crates/auths-author/src/observations.rs","sha256":"dda7d6bfa6f4bd7e95a480ca283c2c0e996f69c5c15cb0c7197af328131a7066"},{"path":"core/crates/auths-authority/Cargo.toml","sha256":"4f68212938029f79ebd857b4f3038494eb85d0163d49f07e51376715cf959815"},{"path":"core/crates/auths-authority/src/lib.rs","sha256":"da88d5194de4e17449e69972c0fb042afa3c39798a8f570f30771e77c384f1eb"},{"path":"core/crates/auths-codec/Cargo.toml","sha256":"e20e51826e17814effd9d8925d18d5fbdd6c0d37bf50231e743ec2611314722c"},{"path":"core/crates/auths-codec/src/approval.rs","sha256":"fbff43bf4d57f69f8b7738a8647751cde75c5a932dee65d924a1fe9c7202f91f"},{"path":"core/crates/auths-codec/src/bounded_policy.rs","sha256":"d21f6728be2d8a04b6d94921f2b683f7e61cbb42e0ac6866f1c88a49caa534c3"},{"path":"core/crates/auths-codec/src/decode.rs","sha256":"ba2999584cdf53b1b517ecb9c7ea50d39efee17c666a9a38e2ad1ac94379f778"},{"path":"core/crates/auths-codec/src/encode.rs","sha256":"8491192053e2e15d62b4d2a491de22405b7487ead69ab6f6bca40669ce7ca5f7"},{"path":"core/crates/auths-codec/src/error.rs","sha256":"fecb0737c16deb42d859f1dc7727c698438d9ac12064fd99e0024629642c390c"},{"path":"core/crates/auths-codec/src/hash.rs","sha256":"f88e111f1dbb2cef6b7b5e9c948cb45ff92e366710c8a5f5c636138aa748479e"},{"path":"core/crates/auths-codec/src/lib.rs","sha256":"3b0e5c94c6f34f750b88a9333e1d5c8145746d845d3a23e0d2f61807cf592ea7"},{"path":"core/crates/auths-codec/src/observation.rs","sha256":"38328b0c71ff97a4196eeade8b4faa889527ff1f80bb168468bcd49082a3987e"},{"path":"core/crates/auths-composition/Cargo.toml","sha256":"331e13025eb82588b5269ed3975929eb41c823d588c49e4c296273d85c6fe80e"},{"path":"core/crates/auths-composition/src/lib.rs","sha256":"e42e3b0b6a9985b73c533aeb23799c638979aa27a9ce7d0f10a8d60340570fb1"},{"path":"core/crates/auths-model/Cargo.toml","sha256":"565c15302b0cc9270db1e28efa3862804846850ba933cc17aea8abcec4a65987"},{"path":"core/crates/auths-model/src/approval.rs","sha256":"54cf44a9ef747ec21546a4086aecfb130bc7803b0d646430e6082df51e6e305f"},{"path":"core/crates/auths-model/src/bounded.rs","sha256":"f90496abc0a06c028b4d850af6ddab7d850bfafeaa3d042f1b1246a41d8bbbc9"},{"path":"core/crates/auths-model/src/bounded_policy.rs","sha256":"306a8f049cc7cfc7635fe0e4de47eb7813eed63d3c14c3be2b51586aa4eea450"},{"path":"core/crates/auths-model/src/lib.rs","sha256":"e7cfe6bb9574c6b016aa63e70658c31e0b90903ec6479a49f4a2ceb64f5bad97"},{"path":"core/crates/auths-model/src/observation.rs","sha256":"b3ed3e3cc090afca2896a7d3de7988afccc1ee1ea0ebd91b51a8bc0f20ad8dbb"},{"path":"core/crates/auths-multikey/Cargo.toml","sha256":"858756c1197befcada06134742bffe8d58cf674cadd6c046bf710570e96efaf2"},{"path":"core/crates/auths-multikey/src/lib.rs","sha256":"f5177fffb11e40eeaaa665ba886c541fc1f24d5eacdd6983fb03dc20148733f0"},{"path":"core/crates/auths-ports/Cargo.toml","sha256":"596a9b0f5af3717c16a6d13f7054d8a106bcd9f01f5f72c2235dd2afcf0ab16c"},{"path":"core/crates/auths-ports/src/binding.rs","sha256":"a16c012d40aa4249e3ec54372b9611006d0bfe8c7dc3c741911c2194ad17736d"},{"path":"core/crates/auths-ports/src/diagnostics.rs","sha256":"aa596572503b5a65a918bb2ff38281c144ff53821ee914e9325c852828d852df"},{"path":"core/crates/auths-ports/src/lib.rs","sha256":"8da1debf86f9532df0660155d04298beb1ba3a1204508f8586e2e67cd2fb3449"},{"path":"core/crates/auths-ports/src/path.rs","sha256":"b68fc547b4e4d97a60cbbc1cc1939fc6b34a8233b81f840bd396914a707e3ea1"},{"path":"core/crates/auths-raw-key-core/Cargo.toml","sha256":"98c0bc8527a537512e43a74dd6ba9658c6f0cdc16610cf938e3f9b43785d836d"},{"path":"core/crates/auths-raw-key-core/src/lib.rs","sha256":"98c0500c41697aae28708ad0bf970b9a97583d96a3d2c18d23e7fa351e0f7d12"},{"path":"core/crates/auths-registries/Cargo.toml","sha256":"590e49e58b0622d9d6274fea46796dcdb07dec9550eff295cce6a6427ffa51e2"},{"path":"core/crates/auths-registries/src/lib.rs","sha256":"450d3886d85ee333b7e046317fb5b47cde62483d5f3e41d46265e2caf4c373ec"},{"path":"core/crates/auths-registries/src/template.rs","sha256":"1224039dd2b3ce6fa8357613d8cafbae40400493da7176da202b9ade62fa05e4"},{"path":"core/crates/auths-signature-core/Cargo.toml","sha256":"6bee2230eb30af1be0bd5c2d57bd3e1903497a70028d47290d4ac6e9e0e8bca0"},{"path":"core/crates/auths-signature-core/src/lib.rs","sha256":"6e3f9311ded5e49ea50d445eb21e6d8fa12442aa4362a73e0cb6fda15b7cd865"},{"path":"core/crates/auths-signature/Cargo.toml","sha256":"7f7b5682466ba439d8c59579022cb61068cad9fb4bd2d73e1cc21327c902b450"},{"path":"core/crates/auths-signature/src/lib.rs","sha256":"b3d9ac4cc3ba0797b9e1c09f2d6ac05089b25dac4e285a5af28c0165b33d925b"},{"path":"core/crates/auths-verifier/Cargo.toml","sha256":"c43358e06a33324b41a8b93e5cc7279c55f7d21f1f6cfaa539a3fc7b4c27a38f"},{"path":"core/crates/auths-verifier/src/approval.rs","sha256":"c3cae6a49e169051eb555bb092b1069a4d422516d6a2114623a89e5f31ff923f"},{"path":"core/crates/auths-verifier/src/causal.rs","sha256":"9635230f33b13a263573d319ac8a1976addbcc07677514a43e3c7bf28dc04587"},{"path":"core/crates/auths-verifier/src/lib.rs","sha256":"f22dec38dfa47ced8da4f605390da8453273bee1da010f57fd1fdfcb10e0b389"},{"path":"core/crates/auths-verifier/src/observation.rs","sha256":"0bb07f06a0f9524c88427df1c972b1de8ba038a9eeeb15d3134c25125ae84b1e"},{"path":"core/crates/auths-verifier/src/trace.rs","sha256":"2213d72023a1d9e0413a2cf2c51c3dad9e04775d86033a0caaa9d29a8f0036f8"},{"path":"exchange/crates/auths-proof-exchange-model/Cargo.toml","sha256":"34b2db64f93a288e942b5a3918d28cdcbef906e0dc9074ce848018d3d5f7a1fa"},{"path":"exchange/crates/auths-proof-exchange-model/src/lib.rs","sha256":"49fac5aff2339d3a57c41cb8bb2a82852538e8f77ecc4b157c88e264ff31fb55"},{"path":"exchange/crates/auths-proof-exchange-port/Cargo.toml","sha256":"7ff660f1b7579dc570c791090aeb450404fbbf44c92781e289f5ccdde746d739"},{"path":"exchange/crates/auths-proof-exchange-port/src/lib.rs","sha256":"b408fb40c6432edc1facb3d8b3e9433a033f8dc73fe2e0ba5a88c972ca675021"},{"path":"product/config/auths-config/Cargo.toml","sha256":"e4b568ab9f6d84f7d7e6d66443fe825f360db9c27bc7c31d6ddc0647ba3ab304"},{"path":"product/config/auths-config/src/lib.rs","sha256":"fecf00ea65cef9018fda9af2063326d7065b869266d0d9e73a4f06816f1102cc"},{"path":"product/errors/auths-errors/Cargo.toml","sha256":"3b3a199b6460ba75bda84475bb5accd35e1485448a3981038db85bf4772dd350"},{"path":"product/errors/auths-errors/src/lib.rs","sha256":"7feeb9069fa4003f94f1f07c1c94619cf1c883e0dbaaf2187f04d0f742264bdd"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/Cargo.toml","sha256":"716f1f2a117d6d69d8effe9ee9057e24ba3502f20af6a602b06facb638cdabed"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/api.rs","sha256":"9ea61dd7ddd93282b073b98e453e6b75b26dc49689c04e9782435d06a3a09e48"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/clock.rs","sha256":"73f0a6e0f5903883329fa6683f5888288f759512ac69e5c87efd2b6b87f7d79f"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/http.rs","sha256":"14c1fce14e24c984b2a275563a29b6326fb08367922b6e8d37ba38b9cb81aa2b"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/identity.rs","sha256":"186de11230c8b33375951c4368609f8976bf9795f171af3fd7fac26207a94361"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs","sha256":"0b4617d044f5254a5ab22f5a2578f91cc025206a8c1845be39c1c56dcdf7a5df"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/names.rs","sha256":"41bb23572d6002e23ee103d6fe70ecd68764861c6f2e48a1c53af998270a4afa"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs","sha256":"39fed883f4802e68d3b41a68fea0aba0737810996b33d13577de70faba004c29"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/store.rs","sha256":"fc60ee9c49b2f4f063c449b4c78100c5c4872779e94ca168f796603b380ef6e4"},{"path":"product/integrations/auths-custody/Cargo.toml","sha256":"1e14034185ad1ec24a977fd5f41d0abee219606245c046ce2a82287fadef448b"},{"path":"product/integrations/auths-custody/src/conformance.rs","sha256":"8ed1afd58f18fc6becc268908aa6419c9aa404c79da0197963eb2599df44acf6"},{"path":"product/integrations/auths-custody/src/key.rs","sha256":"70cbb0fd21b6f5652157845a22c35be2d0f6c05b3d138fc4b9bb6dbdc3d81c40"},{"path":"product/integrations/auths-custody/src/lib.rs","sha256":"8ee593c1f59b0fd2126bdda9138026f5bc531beb64d4489a99785842e7b98b43"},{"path":"product/operations/auths-operations/Cargo.toml","sha256":"73dde1e914ba5e1386f8d49c0d730423cc72ae77ec44c6554a6a75cc8e8922b1"},{"path":"product/operations/auths-operations/src/explanation.rs","sha256":"b4a39bcbd5712cb9e735ee7deeb281f3fa6af5ddca973735bf3d87dce427ef11"},{"path":"product/operations/auths-operations/src/lib.rs","sha256":"3f401a56555113b98f57bca172a2660eaecedf76247b83a3fdbb089c133a29cd"},{"path":"product/operations/auths-operations/src/render/json.rs","sha256":"2ae042639960afee123730e945d373bc5dda1d2b3af20ae16c939a7e99b9e418"},{"path":"product/operations/auths-operations/src/render/mod.rs","sha256":"b3b7f6fe473f49227ace5a68bfc3d8dc14b5db8dd9888fd9e207070337b1b8bf"},{"path":"product/operations/auths-operations/src/render/text.rs","sha256":"f216cf3bdb00e264523271b16e7059535ac6b1aabf271cebd7935af155e4bfec"},{"path":"product/policy/auths-bounded-policy/Cargo.toml","sha256":"babd5d200923137ead71d8c2528f847cea323ce98da942a1320b054436612c47"},{"path":"product/policy/auths-bounded-policy/src/arithmetic.rs","sha256":"75e43c5d4eab8d1f71c1daf53839f5f9fe45a400afc1f63a30c6f55ce3632627"},{"path":"product/policy/auths-bounded-policy/src/commitment.rs","sha256":"c5706f2d583454e1a7f570f7ada138d4d864bef0205dfae7c1296774f396bb3f"},{"path":"product/policy/auths-bounded-policy/src/eligibility.rs","sha256":"c9acdfb793074e687fc36efad506be27dbd99ffbf40387bc66c8de39ef238432"},{"path":"product/policy/auths-bounded-policy/src/identifier.rs","sha256":"0006a32bae9eb16c4178cf797df418d2b0a781f2bc6474b741dc1a908141831c"},{"path":"product/policy/auths-bounded-policy/src/kernel.rs","sha256":"99187c28b161ac70bee1afed60711f7f645adb4d1671a01863f9849b369811d5"},{"path":"product/policy/auths-bounded-policy/src/lib.rs","sha256":"76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c"},{"path":"product/policy/auths-bounded-policy/src/receipt.rs","sha256":"3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad"},{"path":"product/policy/auths-bounded-policy/src/registry.rs","sha256":"4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0"},{"path":"product/profiles/auths-profile-api/Cargo.toml","sha256":"7ae85761f58625b5d678f961fd052eebf3e000ef565c7312e3ac857763c0017f"},{"path":"product/profiles/auths-profile-api/src/lib.rs","sha256":"a194b82b20bf8aa864c2334ef6c6aec30b2154ded972862252d5dcefa488ab95"},{"path":"product/profiles/auths-profile-mcp/Cargo.toml","sha256":"db264fc25242f7b7e4133cbe5782545b3107b406c87168ae072683cfb59eac66"},{"path":"product/profiles/auths-profile-mcp/src/arguments.rs","sha256":"a5de696586d507e2aee4a49fee99ef1ef4c51a2e46603f8838f1af6d9009833f"},{"path":"product/profiles/auths-profile-mcp/src/lib.rs","sha256":"d0f8b733a09ef8408336cdebc8948d6a5861012ce6878598b11be7084dfd4280"},{"path":"product/profiles/auths-profile-mcp/src/session.rs","sha256":"166c281fa66333388e4760d6098dad02d3359e1d5de4b8f93312c014f97abb03"},{"path":"product/qualification/auths-recipe-qualification/Cargo.toml","sha256":"b7b15b30b9a3d96d4f089d514266d3a892de6608d30707aa44be31cca89ca9fe"},{"path":"product/qualification/auths-recipe-qualification/src/canonical.rs","sha256":"30a9b50777f0dcb4b606abfee2467d5a975d9f6ad941ab6c13ca3df5b359f667"},{"path":"product/qualification/auths-recipe-qualification/src/closure.rs","sha256":"0ad6aee9bd981e2863fa725f209ec84031db2ff12f4c7ac3aaf5120f0bb86039"},{"path":"product/qualification/auths-recipe-qualification/src/error.rs","sha256":"52d5cf720a1e4579008fdda90a3ac2c31f0b8db57985f121f65e54b4da2b7dd1"},{"path":"product/qualification/auths-recipe-qualification/src/evidence.rs","sha256":"ba45a7409d67a8af26ab811af306412014557477a101ab2a8eb0faf8f2bd4b91"},{"path":"product/qualification/auths-recipe-qualification/src/ids.rs","sha256":"e81a906d571497ab2da753e1532d4443706410e0b75fdd59a7d2d788c7aec403"},{"path":"product/qualification/auths-recipe-qualification/src/launch.rs","sha256":"41f2e2de90e1e7d6440a66eda3eb9bea8d5e0741bc232305a76a363ab5f813c1"},{"path":"product/qualification/auths-recipe-qualification/src/lib.rs","sha256":"5c9cff04c8960df805a2f7656cf5e74932798e0db7648341e96ae7073a592404"},{"path":"product/qualification/auths-recipe-qualification/src/model.rs","sha256":"3484eb0ec287b23d4682ade7b1b0f8d1335985b3fb180f06fc28716076957d5f"},{"path":"product/qualification/auths-recipe-qualification/src/release.rs","sha256":"d816b53e2275e902c750ad03803061844e259e28560ab2d1c77e8a43981a4d6a"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/mod.rs","sha256":"7f15b68e05a04f202bcb1fb80de1d9a9a4fda8bfd6af2cd4e5c660fc75d96fe5"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/schemas.rs","sha256":"c59feec2805621f341a90f81fc005e2c12f7a70f9d264fdeacccb2be4fe1c046"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/verification.rs","sha256":"6a6b5834c5dae10af1ba8939b2deae43b85db71544dc8f077ff63b7fe68ac8a8"},{"path":"product/qualification/auths-recipe-qualification/src/verify.rs","sha256":"a470a9b98c04dc8d5dabe4d3dc8ed4e7a3ceb1cde035944a0714462bbf37d56d"},{"path":"product/receipts/auths-receipts/Cargo.toml","sha256":"6001fa1375899953aafcb07c23a6da0c8f57ea7ec08bb9c950b12a60a8cc6f0f"},{"path":"product/receipts/auths-receipts/src/disclosure.rs","sha256":"ba9ed439be0a320c8a01f5b6e9b51361c1a37e076947490d8e4a484ba6bb119c"},{"path":"product/receipts/auths-receipts/src/lib.rs","sha256":"547a57c4160256719cafb7d0ab972d9fc80b0da14fbbce4148c70c414070ff36"},{"path":"product/runtime/auths-connections/Cargo.toml","sha256":"babeb6e1dda3dfb66291713ce1e43dce5c349833d0b50ea4dccbf986030026b2"},{"path":"product/runtime/auths-connections/src/credential.rs","sha256":"82921413bb053f0f6c7931fbd4e6a86c8cc1d8c6b51debd9c2cef33a8d5b1c51"},{"path":"product/runtime/auths-connections/src/kernel.rs","sha256":"a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8"},{"path":"product/runtime/auths-connections/src/lib.rs","sha256":"79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22"},{"path":"product/runtime/auths-connections/src/model.rs","sha256":"de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77"},{"path":"product/runtime/auths-connections/src/registry.rs","sha256":"e57640e003e72ad3235c567c2bb944a262bd64e673f023b62ea091094cc7e946"},{"path":"product/runtime/auths-gateway-kernel/Cargo.toml","sha256":"34f864e67656af4ac7e5c7a347a23f01fc8ab31365b8e23c0ef474483b14a183"},{"path":"product/runtime/auths-gateway-kernel/src/construct.rs","sha256":"e9d65744bae273d65face4285e5d2da75c06a92ab48f7b8333d496604e31c63c"},{"path":"product/runtime/auths-gateway-kernel/src/lib.rs","sha256":"cfda6f8453426564c085475f183b6f790b438768a19668f1b65d33ba59dc8632"},{"path":"product/runtime/auths-gateway-kernel/src/order.rs","sha256":"e0045f877c4b7fe3860c291039853885064ddcdebba7c9b345ab65e81e646dda"},{"path":"product/runtime/auths-gateway-kernel/src/outcome.rs","sha256":"e9785b1afe70788c89b51b18655bcd5acff7b0c8e3d12fb79c6f05a202e67e6b"},{"path":"product/runtime/auths-gateway-kernel/src/ratio.rs","sha256":"7ace22264812e6fc1ef3a62afee402cf43494bb71ae0d3de219ad1b39d690bcb"},{"path":"product/runtime/auths-gateway-kernel/src/recovery.rs","sha256":"9f46dcd1685ab6e4d1ba04a3fc286a9f3afee8fb47829be1fbc670a7926a2dc6"},{"path":"product/runtime/auths-gateway-kernel/src/transition.rs","sha256":"cefb8f01d915880f6921f2501ff881ad94b9de61072c34d9cd19220992f97374"},{"path":"product/runtime/auths-gateway/Cargo.toml","sha256":"00b28be86921dcdc0ad90cce0c62c2961cafefe96ea6c2edf0e926c3d405ccad"},{"path":"product/runtime/auths-gateway/src/admin.rs","sha256":"2d5cc67afac42fbd15f36e2d1693cd1b20cedacf775040dce6ffe04ccc94c9ea"},{"path":"product/runtime/auths-gateway/src/app.rs","sha256":"6f80f63833ea0815bb44fbf3b0cc54624a08e9fb578b035819f2980dc04e8256"},{"path":"product/runtime/auths-gateway/src/audit.rs","sha256":"0edb2037eb7b5d6f13acfce85c54f62a82bf7fdd31bc7e626c4fec183cef61dd"},{"path":"product/runtime/auths-gateway/src/audit_tests.rs","sha256":"990969384a52d75bc2489d9d412a9e7dd814bca1c8f65c701d6205fae62a15d5"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway-harness.rs","sha256":"12b0c24d36b2e6a3be392d3c081a783b355fdd67dc5b54bacc0410e803116b8c"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway.rs","sha256":"2f33a1da5dd54947ee1664795f90b3f07a11bb9ee184774bf470b78b03600f0c"},{"path":"product/runtime/auths-gateway/src/binding.rs","sha256":"663b0ce878319511aa7d05722ab4ab2fa9be18817884ffb2ee9f131ff1e382d1"},{"path":"product/runtime/auths-gateway/src/bounds.rs","sha256":"9cfa0eae4973e5e047a198360b22f041708fa20276b0b90c2ec440f06915d64b"},{"path":"product/runtime/auths-gateway/src/bounds_aggregate_tests.rs","sha256":"ab34f227b7c8692ba1da88ccb32bb3687a66adf8353d8282fae905d4a88eb612"},{"path":"product/runtime/auths-gateway/src/bounds_tests.rs","sha256":"74136bc570da7b9338b5a1a1ed9d3fd892c55135160964f9d3ac0e2cf5741375"},{"path":"product/runtime/auths-gateway/src/connection.rs","sha256":"7b5d049c258a26ed1c93ecf860f51d051a8a65f9b93554af0b1ea93862398ec9"},{"path":"product/runtime/auths-gateway/src/credential_journal.rs","sha256":"7297fccaee5cd8622928e8e0a42bba50da7941970a6f682ecd300c41ee6509da"},{"path":"product/runtime/auths-gateway/src/echo_verify.rs","sha256":"6d453051665f823abd7354d5c50031d9524cf47d6092d2f09080ae814e3b9575"},{"path":"product/runtime/auths-gateway/src/engine.rs","sha256":"f1052aaef43e441b9e0befa3f8ad1e2fd5279a27cb9d63aac0cf9dfdbe85a052"},{"path":"product/runtime/auths-gateway/src/fuzzing.rs","sha256":"ed3b0028487eb546a3b0a91d115aa8f18bcea324b61620bfe8e35a9e6ab18758"},{"path":"product/runtime/auths-gateway/src/generation_floor.rs","sha256":"fe1510ec96ce0f67e9a78edbfa94b33eb7df64c0ac4d0a67901124dcd0164777"},{"path":"product/runtime/auths-gateway/src/harness.rs","sha256":"c87e479f3eb281960f6c9c80d43c7560d7ccb654b0154ec823d3fcec4884ac05"},{"path":"product/runtime/auths-gateway/src/lib.rs","sha256":"4674c497940ab339d9b755b71a3e1fe5feeba28bfecc025b7d148dc804a508bf"},{"path":"product/runtime/auths-gateway/src/listener.rs","sha256":"aa08239bcbc1fcb55e8a212fbdf6a84f12985b0d436dcb51dc58b06e59e435f2"},{"path":"product/runtime/auths-gateway/src/observed_tests.rs","sha256":"a22be071695f89ca2578a4d82fd80d9cb82289213c9bdb8f0470f6b2dc3d9201"},{"path":"product/runtime/auths-gateway/src/observer.rs","sha256":"562ffcaea071c3856e0708dc2fe33516917e145d2438aabb75af0a2b6ba01046"},{"path":"product/runtime/auths-gateway/src/onboarding.rs","sha256":"0dfd7d67e7f02f18a28d1c86ca1b7751d7463f5efcdbe3825de0ad8cbccb3891"},{"path":"product/runtime/auths-gateway/src/operator.rs","sha256":"c3c36954a3e86723df035b47f43b85fc8ab3a6292983522b6258d5c6b4e6c4e4"},{"path":"product/runtime/auths-gateway/src/pending_vectors/attempts.rs","sha256":"47ef3c8cb1c5504d47ae9a0088705ce6715fe86bac1671a34a56fb38a64d0dd3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/bounds.rs","sha256":"e612217307e1da5b0eb5ee6582a7458bb064b8aa8a529fc6555b1b334127ab68"},{"path":"product/runtime/auths-gateway/src/pending_vectors/codes.rs","sha256":"e00670a5ef24eb856cc2c6dcda8e5a263842f55c76bb939c0c27bd9df37e5522"},{"path":"product/runtime/auths-gateway/src/pending_vectors/keys.rs","sha256":"f84c56f2ea9cb34b2b79c72d13fbf2c6585010ec1ed450af58a78c80c1ea1edd"},{"path":"product/runtime/auths-gateway/src/pending_vectors/mod.rs","sha256":"5de8340f0ef71a0b57a09e323fefe473d3160c6ae952b9ba46f714825fbacafc"},{"path":"product/runtime/auths-gateway/src/pending_vectors/outcomes.rs","sha256":"8ec07b9511b48913af36ac999d2aa0e82924289f6acb23ddaeb9f00f99815166"},{"path":"product/runtime/auths-gateway/src/pending_vectors/production.rs","sha256":"f574cabfa4687a4fc846b8f6a234b68ec53b876aed548b11445729cac1a55ede"},{"path":"product/runtime/auths-gateway/src/pending_vectors/recipes.rs","sha256":"51693208270231c25c3aef2a32151d5962114c71e86b88cb9df83181c7af83d9"},{"path":"product/runtime/auths-gateway/src/pre_entry.rs","sha256":"06ea78ca140468bfaba17d9ab04912ad68673954c3203c98fed28272ff2a00c0"},{"path":"product/runtime/auths-gateway/src/property_tests.rs","sha256":"939c081e2e154aaf10186754044bdd65608932c899b970a04a71d0afaa999a93"},{"path":"product/runtime/auths-gateway/src/qualification.rs","sha256":"06b49d3fc2ad4383f9e23beefa96033f1fd6e415e043878327583451a53086cc"},{"path":"product/runtime/auths-gateway/src/qualification_simulation.rs","sha256":"f5a5b588f4f30aeca1ccc4f4bc0b548de96206d166371ee3554d1e05763db5a7"},{"path":"product/runtime/auths-gateway/src/qualification_tests.rs","sha256":"9f32d3ff014b668652935c16a4ca83b73ed3e0a0e992fb716a881985a0e57567"},{"path":"product/runtime/auths-gateway/src/quorum_tests.rs","sha256":"a78380b019104d688c11a4410082c7e08ded3106aab099954c4f8a1b4ae0fd89"},{"path":"product/runtime/auths-gateway/src/readiness.rs","sha256":"911c3f11892f94641574375e2da4c671c802738f71082f12c39832331052d43d"},{"path":"product/runtime/auths-gateway/src/recipe.rs","sha256":"fecf9af67e7afc48d080e9f8f55f8ce28e49d0e08988717a27908bbda461d6b6"},{"path":"product/runtime/auths-gateway/src/recipe/lower.rs","sha256":"8088b8751ed831dbb48247af953c6290ac95e2a438ccd5bd65eff54be06a1fd1"},{"path":"product/runtime/auths-gateway/src/recipe/review.rs","sha256":"c3eb7d9fdd98dacf52750b14b67ad7b7faaecbbdeafff1e0b049f67d0a2d0139"},{"path":"product/runtime/auths-gateway/src/recipe/runtime.rs","sha256":"c286f0d15f974402822c0810d8e97f98411dc1c557755cc23e540d85e2bb42d9"},{"path":"product/runtime/auths-gateway/src/recipe/source.rs","sha256":"1af50298fb1461e1b24cbdf560d43124d6b1c4c529586c911b1c4797214a69ff"},{"path":"product/runtime/auths-gateway/src/recipe/tests.rs","sha256":"aac551a2481bbc60864c64079bc667dcb232e45a0f41a04073ed84ab5dbe1fce"},{"path":"product/runtime/auths-gateway/src/recipe/validate.rs","sha256":"3711b17605cb7b0d639bc1b180449231f5882a306cab20e2c7782155cc63b0d4"},{"path":"product/runtime/auths-gateway/src/scenario_tests.rs","sha256":"67915828ecfe2be0afadb5525277ab205f91172edc90852ec7b77c63b2d17fdc"},{"path":"product/runtime/auths-gateway/src/separation.rs","sha256":"be9306848ca5d801767cf6aa14247c8618312ef0e202f00ce0c24c4844491061"},{"path":"product/runtime/auths-gateway/src/store.rs","sha256":"1e5288345c2cb1421aeda277b3158d07607404b0ec46943222ac107b63dcbb46"},{"path":"product/runtime/auths-gateway/src/store_testkit.rs","sha256":"88d82fee42f1b8ef521e8deef0216e938ebeaad822eb2f5020e70b89d145ea70"},{"path":"product/runtime/auths-gateway/src/submit.rs","sha256":"c78dbbba7c45b443febf655056c5edcd635e77be7b21c5b2c318097502415ffe"},{"path":"product/runtime/auths-gateway/src/support.rs","sha256":"9fd979029793a22b15d9776a7fc172476fd7c126a80d4080c65d720845becbcb"},{"path":"product/runtime/auths-gateway/src/transport.rs","sha256":"be2c6dc75b8daec110bf8749fedc3823f6067d40b999aa3eb21126896a97d3ad"},{"path":"product/runtime/auths-kernel-runtime/Cargo.toml","sha256":"926bcd0053e5edd703be8f0027ad009e2982db013c8174c1366edbf38b48087d"},{"path":"product/runtime/auths-kernel-runtime/src/lib.rs","sha256":"7108faae9ca4bc32dc093ddaf885ac8f74f3c9b8d317b7c7d0ed00d1d0ab5972"},{"path":"product/runtime/auths-lifecycle/Cargo.toml","sha256":"c5053c705f8d5554b44e432fe75287a2faf11d644e5a2552e45ad6cd94176af5"},{"path":"product/runtime/auths-lifecycle/src/codec.rs","sha256":"51c4b746749150e8bfcd8ff972b3f6c1ef40bec15583448ec1b471d9ad737dc0"},{"path":"product/runtime/auths-lifecycle/src/digest.rs","sha256":"55282cd7d8aba37713c2dcb5357c9877819edb72a30eadefb860d28d7d3a3eb7"},{"path":"product/runtime/auths-lifecycle/src/identifier.rs","sha256":"31620e8c16de68d3d2d3b84d6353c1a5b9d4151d8247f91fa389b906a8e660f1"},{"path":"product/runtime/auths-lifecycle/src/kernel.rs","sha256":"2abb8c094b36d35b364e74d78091d14c5d6f3d1eb6552cca3b5538dbd017ce23"},{"path":"product/runtime/auths-lifecycle/src/lib.rs","sha256":"afe5a345cd309b5a4f08ffba3170a6d7f16ff914892b3f2006d5208ed24ec736"},{"path":"product/runtime/auths-lifecycle/src/model.rs","sha256":"1af12bbeeeaa65ec02ddcebd7d2c8c92ec1e339fa40ae85b45ab9b01a722a4fa"},{"path":"product/runtime/auths-lifecycle/src/operation.rs","sha256":"78e6d05fcf5d7ea4f148032a3fa26fdfcab77eb346019effe927b08e0d64d732"},{"path":"product/runtime/auths-lifecycle/src/registry.rs","sha256":"53495fe6f7a77422593a41623e28716f1c140dcc1e00f87f6b0ffbfb93a5ef90"},{"path":"product/runtime/auths-lifecycle/src/sealed.rs","sha256":"2e0c03b5813c926c159598bb7890d1523825edbe57cd687d42a5dfb3374a0c19"},{"path":"product/runtime/auths-lifecycle/src/test_support.rs","sha256":"221d9a5c5ef8e1f9f8fd66927484eaf813571d0568470278ecd8fa08a5eec8cd"},{"path":"product/runtime/auths-lifecycle/src/transition.rs","sha256":"011805a28efdd541f44ccea54dd0e34a1e58f4004447ee58013703b4fb6b2822"},{"path":"product/runtime/auths-runtime/Cargo.toml","sha256":"dd29d80a8b4bb56c869f036a6c9998f6e6d1c0383ac5dc03fa42b24abe2a7ff7"},{"path":"product/runtime/auths-runtime/src/lib.rs","sha256":"132ca03d58c14905d3a822a4972f42a22a5ad33a45f2ba9ca44f3a57d810b4b0"},{"path":"product/runtime/auths-runtime/src/production.rs","sha256":"fd4eff4270c571c10fcff6cf27df28961ebf074de8a1a028f500fda1ca376820"},{"path":"product/sdk/auths-approval-quorum/Cargo.toml","sha256":"df904971fca87a24194c5816738a331588fe8f164acb5d70839a35dca5f57114"},{"path":"product/sdk/auths-approval-quorum/src/lib.rs","sha256":"72e4086088a1c0912e4e1a9e980f26a5c280bf5ab16ea39c9f0f58d5096ac2ce"},{"path":"product/sdk/auths-approval-quorum/src/remote.rs","sha256":"9fa029c7c63003adf260f8aec55160c545681c60c1bace0d934e7525862aac7b"},{"path":"product/sdk/auths-approval-quorum/src/remote_tests.rs","sha256":"8a09ce17cfee82a035a74edd535f3ebeb3db0e078784740d3997b17dbdb10197"},{"path":"product/sdk/auths-approval-quorum/src/tests.rs","sha256":"0acbf12be3e497dcc6c2d8f29c9af3b1a7ed8e11b75f6399570d4f217a785060"},{"path":"product/stores/auths-stores/Cargo.toml","sha256":"a32c4b76d17b264be5d40d24497ff237e1ed87822e8bab86229b3db93106dbe3"},{"path":"product/stores/auths-stores/src/gateway_attempt.rs","sha256":"185da8f4a220fba836d5b78a9311f03204681c43a3c53951008084d135bf4d21"},{"path":"product/stores/auths-stores/src/lib.rs","sha256":"e721262edf8a9ab5568ddc27639176312d4a366203b5f73e2d7c11fde2c554e9"},{"path":"product/stores/auths-stores/src/lifecycle.rs","sha256":"94f64d25bc178a9e60ba3c0ee6915d7fb3af7c4468792d76b4e70f43f4de1e2f"}],"schema":"auths.gateway-semantic-closure/1"} \ No newline at end of file diff --git a/product/runtime/auths-gateway/src/qualification_simulation.rs b/product/runtime/auths-gateway/src/qualification_simulation.rs index 7f948ca40..942be51b2 100644 --- a/product/runtime/auths-gateway/src/qualification_simulation.rs +++ b/product/runtime/auths-gateway/src/qualification_simulation.rs @@ -53,6 +53,15 @@ impl Family { } } + fn read_back_url(self) -> &'static str { + match self { + Self::Stripe => "https://api.stripe.com/v1/refunds/re_TEST0000000001", + Self::Airtable => { + "https://api.airtable.com/v0/appTEST0000000001/tblTEST0000000001/recTEST0000000001" + } + } + } + fn recipe(self) -> CompiledRecipe { match self { Self::Stripe => CompiledRecipe::compile( @@ -122,6 +131,8 @@ struct OracleProvider

{ inner: P, expected: Value, checked: AtomicUsize, + read_back_url: &'static str, + read_backs: AtomicUsize, } trait SimulationProvider: ProviderPort { @@ -160,6 +171,14 @@ impl ProviderPort for OracleProvider

{ headers: &[RequestHeader], maximum: usize, ) -> Option { + if url == self.read_back_url { + self.read_backs.fetch_add(1, Ordering::SeqCst); + } else { + assert_eq!( + url, "https://api.stripe.com/v1/payment_intents/pi_TEST0000000001", + "only the independent ceiling read is admitted before the write" + ); + } self.inner.action_read(url, headers, maximum).await } @@ -332,31 +351,31 @@ async fn race(family: Family, provider: &OracleProvider

2..=2, - Family::Airtable => 2..=3, - }; - assert!( - allowed_leases.contains(&leases), - "one write lease, only bounded read-back leases: {leases}" + // Either contender can reconcile once a locator is retained; Airtable + // can also recover its fixed locator while the first claim is in flight. + // Count actual read calls so an extra write lease cannot pass as recovery. + let reads = provider.read_backs.load(Ordering::SeqCst); + assert!((1..=2).contains(&reads), "bounded fresh read-back calls"); + assert_eq!( + leases, + 1 + reads, + "one write lease plus measured read leases" ); Measurement { case: "two-instance-race".to_owned(), verdict: "one-authorized-entry".to_owned(), credential_leases: leases, provider_entries: provider.inner.entries(), - confirmed_by_read_back: usize::from(observed > 0), + confirmed_by_read_back: usize::from(confirmations > 0), } } @@ -457,6 +476,8 @@ async fn stripe_qualification_simulation() { ), expected: family.oracle("qualification-1", &ORIGINAL), checked: AtomicUsize::new(0), + read_back_url: family.read_back_url(), + read_backs: AtomicUsize::new(0), }; let mut measured = lifecycle(family, &provider, &recording, &mut store, mode != "respond").await; @@ -470,6 +491,8 @@ async fn stripe_qualification_simulation() { inner: TableProvider::new(&recipe, &defaults, "respond"), expected: family.oracle("qualification-1", &ORIGINAL), checked: AtomicUsize::new(0), + read_back_url: family.read_back_url(), + read_backs: AtomicUsize::new(0), }; cases.extend(hostile(family, &provider).await); cases.push(race(family, &provider).await); @@ -495,6 +518,8 @@ async fn airtable_qualification_simulation() { inner: RecordProvider::new(delivery, Reading::Faithful), expected: family.oracle("qualification-1", &ORIGINAL), checked: AtomicUsize::new(0), + read_back_url: family.read_back_url(), + read_backs: AtomicUsize::new(0), }; let mut measured = lifecycle( family, @@ -514,6 +539,8 @@ async fn airtable_qualification_simulation() { inner: RecordProvider::new(Delivery::Respond, Reading::Faithful), expected: family.oracle("qualification-1", &ORIGINAL), checked: AtomicUsize::new(0), + read_back_url: family.read_back_url(), + read_backs: AtomicUsize::new(0), }; cases.extend(hostile(family, &provider).await); cases.push(race(family, &provider).await); diff --git a/product/runtime/auths-gateway/src/qualification_tests.rs b/product/runtime/auths-gateway/src/qualification_tests.rs index e5a2e8bc2..fb0788e30 100644 --- a/product/runtime/auths-gateway/src/qualification_tests.rs +++ b/product/runtime/auths-gateway/src/qualification_tests.rs @@ -166,7 +166,7 @@ async fn operator_bootstrap_qualification_simulation() { let list = root .revoke(1, NOW - HOUR, NOW + 24 * HOUR, Vec::new(), Vec::new()) .expect("list"); - let signed = QualificationBundle { + let attested_bundle = QualificationBundle { signer_certificate: signer.certificate().canonical_bytes().to_vec(), revocation_list: list.canonical_bytes().to_vec(), release_index: index.canonical_bytes().to_vec(), @@ -190,7 +190,7 @@ async fn operator_bootstrap_qualification_simulation() { refusal(host).await.as_deref(), Some("gateway.qualification.unavailable") ); - let mut unsigned = signed.clone(); + let mut unsigned = attested_bundle.clone(); unsigned.attestations.clear(); assert!(gate.load(&unsigned)); assert_eq!( @@ -199,11 +199,11 @@ async fn operator_bootstrap_qualification_simulation() { ); assert_eq!(host.leases.load(Ordering::SeqCst), 0); let before_signature_leases = host.leases.load(Ordering::SeqCst); - assert!(gate.load(&signed)); + assert!(gate.load(&attested_bundle)); assert_eq!(refusal(host).await, None); assert_eq!(host.leases.load(Ordering::SeqCst), 1); let after_verified_import_leases = host.leases.load(Ordering::SeqCst); - let mut forged = signed.clone(); + let mut forged = attested_bundle.clone(); let position = forged.attestations[0].len() / 2; forged.attestations[0][position] ^= 1; assert!(gate.load(&forged)); @@ -213,7 +213,7 @@ async fn operator_bootstrap_qualification_simulation() { assert!(refusal(host).await.is_some()); assert_eq!(host.leases.load(Ordering::SeqCst), 1); } - assert!(gate.load(&signed)); + assert!(gate.load(&attested_bundle)); clock.set(NOW + 13 * HOUR); assert_eq!( refusal(host).await.as_deref(), @@ -221,7 +221,7 @@ async fn operator_bootstrap_qualification_simulation() { ); clock.set(NOW); let no_root = required(None, deployment.clone(), &clock); - assert!(!no_root.load(&signed)); + assert!(!no_root.load(&attested_bundle)); let (untrusted, ()) = host_with(&no_root).await; assert_eq!( refusal(&untrusted.first).await.as_deref(), @@ -242,9 +242,12 @@ async fn operator_bootstrap_qualification_simulation() { ) .expect("public root"); for (name, bytes) in [ - ("signer-certificate.json", &signed.signer_certificate), - ("revocation-list.json", &signed.revocation_list), - ("release-index.json", &signed.release_index), + ( + "signer-certificate.json", + &attested_bundle.signer_certificate, + ), + ("revocation-list.json", &attested_bundle.revocation_list), + ("release-index.json", &attested_bundle.release_index), ] { std::fs::write(directory.join(name), bytes).expect("public artifact"); } @@ -256,7 +259,7 @@ async fn operator_bootstrap_qualification_simulation() { .expect("record"); std::fs::write( directory.join(format!("attestation-{position}.json")), - &signed.attestations[position], + &attested_bundle.attestations[position], ) .expect("attestation"); for (member, evidence) in closed.evidence().iter().enumerate() { diff --git a/product/runtime/auths-gateway/src/semantic_closure.rs b/product/runtime/auths-gateway/src/semantic_closure.rs index 2cc8348b4..b5cef10d3 100644 --- a/product/runtime/auths-gateway/src/semantic_closure.rs +++ b/product/runtime/auths-gateway/src/semantic_closure.rs @@ -10,7 +10,7 @@ /// SHA-256 of the schema, a NUL byte, and `semantic-closure.json`. /// Regenerate through `semantic_closure_is_current` with `AUTHS_UPDATE_FIXTURES=1`. pub const GATEWAY_SEMANTIC_CLOSURE_SHA256: &str = - "f16f4aa4ec541bff74b6d6e1f35eb390eae3ba256a8fe9c9f87a7c155cc60368"; + "c9414e3a22dce48048dea9e4f8c2b4baa5d8cfd17a2cf8bddb172ca12751193f"; #[cfg(test)] mod tests { From 20837b56a61945d79dedf48a1ff237411dd01185 Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 00:49:18 +0100 Subject: [PATCH 043/108] Sign measured provider simulation reports and verify published bytes --- ...gateway-polish-and-recipe-qualification.md | 6 +- .../auths-gateway/semantic-closure.json | 2 +- product/runtime/auths-gateway/src/lib.rs | 2 + .../src/qualification_simulation.rs | 10 +- .../auths-gateway/src/qualification_tests.rs | 47 +++++++ .../auths-gateway/src/semantic_closure.rs | 2 +- .../src/simulation_attestation.rs | 120 ++++++++++++++++++ qualification/README.md | 4 +- qualification/simulation/README.md | 5 + qualification/simulation/run.py | 25 +++- 10 files changed, 210 insertions(+), 13 deletions(-) create mode 100644 product/runtime/auths-gateway/src/simulation_attestation.rs diff --git a/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md b/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md index b92a035e5..73a45cdea 100644 --- a/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md +++ b/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md @@ -1677,7 +1677,11 @@ import. Unsigned and expired inputs cannot lease; verified test import can. The signed placeholder records explicitly claim no provider run. Separate Stripe and Airtable harness reports measure actual native driver leases, entries, fresh read-back, replay, reopen, response loss and response-record crash against -independent wire oracles and mutable doubles. The production pinned root stays +independent wire oracles and mutable doubles. Each measured provider report +also has a detached signature under a fresh self-signed simulation key; the +runner re-reads and verifies the exact published bytes in a separate native +stage. These signatures have no production or protected-run authority. +The production pinned root stays unchanged and stable launch readiness stays false. The rehearsal is a maintained CI job and needs no external credentials. diff --git a/product/runtime/auths-gateway/semantic-closure.json b/product/runtime/auths-gateway/semantic-closure.json index 9b5e10161..27ee3f7be 100644 --- a/product/runtime/auths-gateway/semantic-closure.json +++ b/product/runtime/auths-gateway/semantic-closure.json @@ -1 +1 @@ -{"files":[{"path":"Cargo.lock","sha256":"0e75e2fdef44e79e57797ac6661295ae58ddb8de4a1990a6fd22ce6c54f78604"},{"path":"Cargo.toml","sha256":"6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24"},{"path":"core/adapters/auths-did-keri/Cargo.toml","sha256":"86ba3e3f9a0a70d970568bfb3113b7ba7bbdd81c3eebbb52743dd574a0c0ecaa"},{"path":"core/adapters/auths-did-keri/src/lib.rs","sha256":"a75674842f8a7142004369ccd206ab43e476459293f0ff4bed4d4e659031b3e3"},{"path":"core/adapters/auths-did-key/Cargo.toml","sha256":"d5a3ae07ecde83f91eed4c3785051dd0f44eab6c891754f3309b6b40596707d7"},{"path":"core/adapters/auths-did-key/src/lib.rs","sha256":"b76a3f4528a725df53cfa9242e6e414e1d26caa48468aaed497e28b121f4497c"},{"path":"core/adapters/auths-raw-key/Cargo.toml","sha256":"f49616bc18c19e6aaa7e6a02ccebcdb9f5c1422c1278ef9869e0dbf22ceda7be"},{"path":"core/adapters/auths-raw-key/src/lib.rs","sha256":"45eec1b295dac3bed65cd79c942870b926b06b3f5d38eaebaeb6140ac69315fa"},{"path":"core/crates/auths-algebra-kernel/Cargo.toml","sha256":"0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba"},{"path":"core/crates/auths-algebra-kernel/src/generated.rs","sha256":"ae4bcbef42a408c7ffa0c6a74a42f7de177a6f14479e51d205acf830bda05960"},{"path":"core/crates/auths-algebra-kernel/src/lib.rs","sha256":"6654667eeb9b353d6648954c9fd2e8838462a82ce6b2803eb49e1366892c68c6"},{"path":"core/crates/auths-assurance/Cargo.toml","sha256":"afcb12a97ddd09d7a264b9ecd3fcaefc865ff2c9b4539ee85b00883420ba333a"},{"path":"core/crates/auths-assurance/src/lib.rs","sha256":"0fb2ec844d674b25a9e20b1601452c89c2454901fa506adfa9bb38ef9a7fa213"},{"path":"core/crates/auths-author/Cargo.toml","sha256":"1e6f0e3bc079ddb558decf0db26b291c6e72fc47327b6df1b7650d41689b215f"},{"path":"core/crates/auths-author/src/lib.rs","sha256":"e14475f2f49715a1869d5fa6b11ff1fbb72497e39097e09f833b0bae7e5b3f2b"},{"path":"core/crates/auths-author/src/observations.rs","sha256":"dda7d6bfa6f4bd7e95a480ca283c2c0e996f69c5c15cb0c7197af328131a7066"},{"path":"core/crates/auths-authority/Cargo.toml","sha256":"4f68212938029f79ebd857b4f3038494eb85d0163d49f07e51376715cf959815"},{"path":"core/crates/auths-authority/src/lib.rs","sha256":"da88d5194de4e17449e69972c0fb042afa3c39798a8f570f30771e77c384f1eb"},{"path":"core/crates/auths-codec/Cargo.toml","sha256":"e20e51826e17814effd9d8925d18d5fbdd6c0d37bf50231e743ec2611314722c"},{"path":"core/crates/auths-codec/src/approval.rs","sha256":"fbff43bf4d57f69f8b7738a8647751cde75c5a932dee65d924a1fe9c7202f91f"},{"path":"core/crates/auths-codec/src/bounded_policy.rs","sha256":"d21f6728be2d8a04b6d94921f2b683f7e61cbb42e0ac6866f1c88a49caa534c3"},{"path":"core/crates/auths-codec/src/decode.rs","sha256":"ba2999584cdf53b1b517ecb9c7ea50d39efee17c666a9a38e2ad1ac94379f778"},{"path":"core/crates/auths-codec/src/encode.rs","sha256":"8491192053e2e15d62b4d2a491de22405b7487ead69ab6f6bca40669ce7ca5f7"},{"path":"core/crates/auths-codec/src/error.rs","sha256":"fecb0737c16deb42d859f1dc7727c698438d9ac12064fd99e0024629642c390c"},{"path":"core/crates/auths-codec/src/hash.rs","sha256":"f88e111f1dbb2cef6b7b5e9c948cb45ff92e366710c8a5f5c636138aa748479e"},{"path":"core/crates/auths-codec/src/lib.rs","sha256":"3b0e5c94c6f34f750b88a9333e1d5c8145746d845d3a23e0d2f61807cf592ea7"},{"path":"core/crates/auths-codec/src/observation.rs","sha256":"38328b0c71ff97a4196eeade8b4faa889527ff1f80bb168468bcd49082a3987e"},{"path":"core/crates/auths-composition/Cargo.toml","sha256":"331e13025eb82588b5269ed3975929eb41c823d588c49e4c296273d85c6fe80e"},{"path":"core/crates/auths-composition/src/lib.rs","sha256":"e42e3b0b6a9985b73c533aeb23799c638979aa27a9ce7d0f10a8d60340570fb1"},{"path":"core/crates/auths-model/Cargo.toml","sha256":"565c15302b0cc9270db1e28efa3862804846850ba933cc17aea8abcec4a65987"},{"path":"core/crates/auths-model/src/approval.rs","sha256":"54cf44a9ef747ec21546a4086aecfb130bc7803b0d646430e6082df51e6e305f"},{"path":"core/crates/auths-model/src/bounded.rs","sha256":"f90496abc0a06c028b4d850af6ddab7d850bfafeaa3d042f1b1246a41d8bbbc9"},{"path":"core/crates/auths-model/src/bounded_policy.rs","sha256":"306a8f049cc7cfc7635fe0e4de47eb7813eed63d3c14c3be2b51586aa4eea450"},{"path":"core/crates/auths-model/src/lib.rs","sha256":"e7cfe6bb9574c6b016aa63e70658c31e0b90903ec6479a49f4a2ceb64f5bad97"},{"path":"core/crates/auths-model/src/observation.rs","sha256":"b3ed3e3cc090afca2896a7d3de7988afccc1ee1ea0ebd91b51a8bc0f20ad8dbb"},{"path":"core/crates/auths-multikey/Cargo.toml","sha256":"858756c1197befcada06134742bffe8d58cf674cadd6c046bf710570e96efaf2"},{"path":"core/crates/auths-multikey/src/lib.rs","sha256":"f5177fffb11e40eeaaa665ba886c541fc1f24d5eacdd6983fb03dc20148733f0"},{"path":"core/crates/auths-ports/Cargo.toml","sha256":"596a9b0f5af3717c16a6d13f7054d8a106bcd9f01f5f72c2235dd2afcf0ab16c"},{"path":"core/crates/auths-ports/src/binding.rs","sha256":"a16c012d40aa4249e3ec54372b9611006d0bfe8c7dc3c741911c2194ad17736d"},{"path":"core/crates/auths-ports/src/diagnostics.rs","sha256":"aa596572503b5a65a918bb2ff38281c144ff53821ee914e9325c852828d852df"},{"path":"core/crates/auths-ports/src/lib.rs","sha256":"8da1debf86f9532df0660155d04298beb1ba3a1204508f8586e2e67cd2fb3449"},{"path":"core/crates/auths-ports/src/path.rs","sha256":"b68fc547b4e4d97a60cbbc1cc1939fc6b34a8233b81f840bd396914a707e3ea1"},{"path":"core/crates/auths-raw-key-core/Cargo.toml","sha256":"98c0bc8527a537512e43a74dd6ba9658c6f0cdc16610cf938e3f9b43785d836d"},{"path":"core/crates/auths-raw-key-core/src/lib.rs","sha256":"98c0500c41697aae28708ad0bf970b9a97583d96a3d2c18d23e7fa351e0f7d12"},{"path":"core/crates/auths-registries/Cargo.toml","sha256":"590e49e58b0622d9d6274fea46796dcdb07dec9550eff295cce6a6427ffa51e2"},{"path":"core/crates/auths-registries/src/lib.rs","sha256":"450d3886d85ee333b7e046317fb5b47cde62483d5f3e41d46265e2caf4c373ec"},{"path":"core/crates/auths-registries/src/template.rs","sha256":"1224039dd2b3ce6fa8357613d8cafbae40400493da7176da202b9ade62fa05e4"},{"path":"core/crates/auths-signature-core/Cargo.toml","sha256":"6bee2230eb30af1be0bd5c2d57bd3e1903497a70028d47290d4ac6e9e0e8bca0"},{"path":"core/crates/auths-signature-core/src/lib.rs","sha256":"6e3f9311ded5e49ea50d445eb21e6d8fa12442aa4362a73e0cb6fda15b7cd865"},{"path":"core/crates/auths-signature/Cargo.toml","sha256":"7f7b5682466ba439d8c59579022cb61068cad9fb4bd2d73e1cc21327c902b450"},{"path":"core/crates/auths-signature/src/lib.rs","sha256":"b3d9ac4cc3ba0797b9e1c09f2d6ac05089b25dac4e285a5af28c0165b33d925b"},{"path":"core/crates/auths-verifier/Cargo.toml","sha256":"c43358e06a33324b41a8b93e5cc7279c55f7d21f1f6cfaa539a3fc7b4c27a38f"},{"path":"core/crates/auths-verifier/src/approval.rs","sha256":"c3cae6a49e169051eb555bb092b1069a4d422516d6a2114623a89e5f31ff923f"},{"path":"core/crates/auths-verifier/src/causal.rs","sha256":"9635230f33b13a263573d319ac8a1976addbcc07677514a43e3c7bf28dc04587"},{"path":"core/crates/auths-verifier/src/lib.rs","sha256":"f22dec38dfa47ced8da4f605390da8453273bee1da010f57fd1fdfcb10e0b389"},{"path":"core/crates/auths-verifier/src/observation.rs","sha256":"0bb07f06a0f9524c88427df1c972b1de8ba038a9eeeb15d3134c25125ae84b1e"},{"path":"core/crates/auths-verifier/src/trace.rs","sha256":"2213d72023a1d9e0413a2cf2c51c3dad9e04775d86033a0caaa9d29a8f0036f8"},{"path":"exchange/crates/auths-proof-exchange-model/Cargo.toml","sha256":"34b2db64f93a288e942b5a3918d28cdcbef906e0dc9074ce848018d3d5f7a1fa"},{"path":"exchange/crates/auths-proof-exchange-model/src/lib.rs","sha256":"49fac5aff2339d3a57c41cb8bb2a82852538e8f77ecc4b157c88e264ff31fb55"},{"path":"exchange/crates/auths-proof-exchange-port/Cargo.toml","sha256":"7ff660f1b7579dc570c791090aeb450404fbbf44c92781e289f5ccdde746d739"},{"path":"exchange/crates/auths-proof-exchange-port/src/lib.rs","sha256":"b408fb40c6432edc1facb3d8b3e9433a033f8dc73fe2e0ba5a88c972ca675021"},{"path":"product/config/auths-config/Cargo.toml","sha256":"e4b568ab9f6d84f7d7e6d66443fe825f360db9c27bc7c31d6ddc0647ba3ab304"},{"path":"product/config/auths-config/src/lib.rs","sha256":"fecf00ea65cef9018fda9af2063326d7065b869266d0d9e73a4f06816f1102cc"},{"path":"product/errors/auths-errors/Cargo.toml","sha256":"3b3a199b6460ba75bda84475bb5accd35e1485448a3981038db85bf4772dd350"},{"path":"product/errors/auths-errors/src/lib.rs","sha256":"7feeb9069fa4003f94f1f07c1c94619cf1c883e0dbaaf2187f04d0f742264bdd"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/Cargo.toml","sha256":"716f1f2a117d6d69d8effe9ee9057e24ba3502f20af6a602b06facb638cdabed"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/api.rs","sha256":"9ea61dd7ddd93282b073b98e453e6b75b26dc49689c04e9782435d06a3a09e48"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/clock.rs","sha256":"73f0a6e0f5903883329fa6683f5888288f759512ac69e5c87efd2b6b87f7d79f"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/http.rs","sha256":"14c1fce14e24c984b2a275563a29b6326fb08367922b6e8d37ba38b9cb81aa2b"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/identity.rs","sha256":"186de11230c8b33375951c4368609f8976bf9795f171af3fd7fac26207a94361"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs","sha256":"0b4617d044f5254a5ab22f5a2578f91cc025206a8c1845be39c1c56dcdf7a5df"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/names.rs","sha256":"41bb23572d6002e23ee103d6fe70ecd68764861c6f2e48a1c53af998270a4afa"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs","sha256":"39fed883f4802e68d3b41a68fea0aba0737810996b33d13577de70faba004c29"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/store.rs","sha256":"fc60ee9c49b2f4f063c449b4c78100c5c4872779e94ca168f796603b380ef6e4"},{"path":"product/integrations/auths-custody/Cargo.toml","sha256":"1e14034185ad1ec24a977fd5f41d0abee219606245c046ce2a82287fadef448b"},{"path":"product/integrations/auths-custody/src/conformance.rs","sha256":"8ed1afd58f18fc6becc268908aa6419c9aa404c79da0197963eb2599df44acf6"},{"path":"product/integrations/auths-custody/src/key.rs","sha256":"70cbb0fd21b6f5652157845a22c35be2d0f6c05b3d138fc4b9bb6dbdc3d81c40"},{"path":"product/integrations/auths-custody/src/lib.rs","sha256":"8ee593c1f59b0fd2126bdda9138026f5bc531beb64d4489a99785842e7b98b43"},{"path":"product/operations/auths-operations/Cargo.toml","sha256":"73dde1e914ba5e1386f8d49c0d730423cc72ae77ec44c6554a6a75cc8e8922b1"},{"path":"product/operations/auths-operations/src/explanation.rs","sha256":"b4a39bcbd5712cb9e735ee7deeb281f3fa6af5ddca973735bf3d87dce427ef11"},{"path":"product/operations/auths-operations/src/lib.rs","sha256":"3f401a56555113b98f57bca172a2660eaecedf76247b83a3fdbb089c133a29cd"},{"path":"product/operations/auths-operations/src/render/json.rs","sha256":"2ae042639960afee123730e945d373bc5dda1d2b3af20ae16c939a7e99b9e418"},{"path":"product/operations/auths-operations/src/render/mod.rs","sha256":"b3b7f6fe473f49227ace5a68bfc3d8dc14b5db8dd9888fd9e207070337b1b8bf"},{"path":"product/operations/auths-operations/src/render/text.rs","sha256":"f216cf3bdb00e264523271b16e7059535ac6b1aabf271cebd7935af155e4bfec"},{"path":"product/policy/auths-bounded-policy/Cargo.toml","sha256":"babd5d200923137ead71d8c2528f847cea323ce98da942a1320b054436612c47"},{"path":"product/policy/auths-bounded-policy/src/arithmetic.rs","sha256":"75e43c5d4eab8d1f71c1daf53839f5f9fe45a400afc1f63a30c6f55ce3632627"},{"path":"product/policy/auths-bounded-policy/src/commitment.rs","sha256":"c5706f2d583454e1a7f570f7ada138d4d864bef0205dfae7c1296774f396bb3f"},{"path":"product/policy/auths-bounded-policy/src/eligibility.rs","sha256":"c9acdfb793074e687fc36efad506be27dbd99ffbf40387bc66c8de39ef238432"},{"path":"product/policy/auths-bounded-policy/src/identifier.rs","sha256":"0006a32bae9eb16c4178cf797df418d2b0a781f2bc6474b741dc1a908141831c"},{"path":"product/policy/auths-bounded-policy/src/kernel.rs","sha256":"99187c28b161ac70bee1afed60711f7f645adb4d1671a01863f9849b369811d5"},{"path":"product/policy/auths-bounded-policy/src/lib.rs","sha256":"76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c"},{"path":"product/policy/auths-bounded-policy/src/receipt.rs","sha256":"3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad"},{"path":"product/policy/auths-bounded-policy/src/registry.rs","sha256":"4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0"},{"path":"product/profiles/auths-profile-api/Cargo.toml","sha256":"7ae85761f58625b5d678f961fd052eebf3e000ef565c7312e3ac857763c0017f"},{"path":"product/profiles/auths-profile-api/src/lib.rs","sha256":"a194b82b20bf8aa864c2334ef6c6aec30b2154ded972862252d5dcefa488ab95"},{"path":"product/profiles/auths-profile-mcp/Cargo.toml","sha256":"db264fc25242f7b7e4133cbe5782545b3107b406c87168ae072683cfb59eac66"},{"path":"product/profiles/auths-profile-mcp/src/arguments.rs","sha256":"a5de696586d507e2aee4a49fee99ef1ef4c51a2e46603f8838f1af6d9009833f"},{"path":"product/profiles/auths-profile-mcp/src/lib.rs","sha256":"d0f8b733a09ef8408336cdebc8948d6a5861012ce6878598b11be7084dfd4280"},{"path":"product/profiles/auths-profile-mcp/src/session.rs","sha256":"166c281fa66333388e4760d6098dad02d3359e1d5de4b8f93312c014f97abb03"},{"path":"product/qualification/auths-recipe-qualification/Cargo.toml","sha256":"b7b15b30b9a3d96d4f089d514266d3a892de6608d30707aa44be31cca89ca9fe"},{"path":"product/qualification/auths-recipe-qualification/src/canonical.rs","sha256":"30a9b50777f0dcb4b606abfee2467d5a975d9f6ad941ab6c13ca3df5b359f667"},{"path":"product/qualification/auths-recipe-qualification/src/closure.rs","sha256":"0ad6aee9bd981e2863fa725f209ec84031db2ff12f4c7ac3aaf5120f0bb86039"},{"path":"product/qualification/auths-recipe-qualification/src/error.rs","sha256":"52d5cf720a1e4579008fdda90a3ac2c31f0b8db57985f121f65e54b4da2b7dd1"},{"path":"product/qualification/auths-recipe-qualification/src/evidence.rs","sha256":"ba45a7409d67a8af26ab811af306412014557477a101ab2a8eb0faf8f2bd4b91"},{"path":"product/qualification/auths-recipe-qualification/src/ids.rs","sha256":"e81a906d571497ab2da753e1532d4443706410e0b75fdd59a7d2d788c7aec403"},{"path":"product/qualification/auths-recipe-qualification/src/launch.rs","sha256":"41f2e2de90e1e7d6440a66eda3eb9bea8d5e0741bc232305a76a363ab5f813c1"},{"path":"product/qualification/auths-recipe-qualification/src/lib.rs","sha256":"5c9cff04c8960df805a2f7656cf5e74932798e0db7648341e96ae7073a592404"},{"path":"product/qualification/auths-recipe-qualification/src/model.rs","sha256":"3484eb0ec287b23d4682ade7b1b0f8d1335985b3fb180f06fc28716076957d5f"},{"path":"product/qualification/auths-recipe-qualification/src/release.rs","sha256":"d816b53e2275e902c750ad03803061844e259e28560ab2d1c77e8a43981a4d6a"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/mod.rs","sha256":"7f15b68e05a04f202bcb1fb80de1d9a9a4fda8bfd6af2cd4e5c660fc75d96fe5"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/schemas.rs","sha256":"c59feec2805621f341a90f81fc005e2c12f7a70f9d264fdeacccb2be4fe1c046"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/verification.rs","sha256":"6a6b5834c5dae10af1ba8939b2deae43b85db71544dc8f077ff63b7fe68ac8a8"},{"path":"product/qualification/auths-recipe-qualification/src/verify.rs","sha256":"a470a9b98c04dc8d5dabe4d3dc8ed4e7a3ceb1cde035944a0714462bbf37d56d"},{"path":"product/receipts/auths-receipts/Cargo.toml","sha256":"6001fa1375899953aafcb07c23a6da0c8f57ea7ec08bb9c950b12a60a8cc6f0f"},{"path":"product/receipts/auths-receipts/src/disclosure.rs","sha256":"ba9ed439be0a320c8a01f5b6e9b51361c1a37e076947490d8e4a484ba6bb119c"},{"path":"product/receipts/auths-receipts/src/lib.rs","sha256":"547a57c4160256719cafb7d0ab972d9fc80b0da14fbbce4148c70c414070ff36"},{"path":"product/runtime/auths-connections/Cargo.toml","sha256":"babeb6e1dda3dfb66291713ce1e43dce5c349833d0b50ea4dccbf986030026b2"},{"path":"product/runtime/auths-connections/src/credential.rs","sha256":"82921413bb053f0f6c7931fbd4e6a86c8cc1d8c6b51debd9c2cef33a8d5b1c51"},{"path":"product/runtime/auths-connections/src/kernel.rs","sha256":"a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8"},{"path":"product/runtime/auths-connections/src/lib.rs","sha256":"79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22"},{"path":"product/runtime/auths-connections/src/model.rs","sha256":"de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77"},{"path":"product/runtime/auths-connections/src/registry.rs","sha256":"e57640e003e72ad3235c567c2bb944a262bd64e673f023b62ea091094cc7e946"},{"path":"product/runtime/auths-gateway-kernel/Cargo.toml","sha256":"34f864e67656af4ac7e5c7a347a23f01fc8ab31365b8e23c0ef474483b14a183"},{"path":"product/runtime/auths-gateway-kernel/src/construct.rs","sha256":"e9d65744bae273d65face4285e5d2da75c06a92ab48f7b8333d496604e31c63c"},{"path":"product/runtime/auths-gateway-kernel/src/lib.rs","sha256":"cfda6f8453426564c085475f183b6f790b438768a19668f1b65d33ba59dc8632"},{"path":"product/runtime/auths-gateway-kernel/src/order.rs","sha256":"e0045f877c4b7fe3860c291039853885064ddcdebba7c9b345ab65e81e646dda"},{"path":"product/runtime/auths-gateway-kernel/src/outcome.rs","sha256":"e9785b1afe70788c89b51b18655bcd5acff7b0c8e3d12fb79c6f05a202e67e6b"},{"path":"product/runtime/auths-gateway-kernel/src/ratio.rs","sha256":"7ace22264812e6fc1ef3a62afee402cf43494bb71ae0d3de219ad1b39d690bcb"},{"path":"product/runtime/auths-gateway-kernel/src/recovery.rs","sha256":"9f46dcd1685ab6e4d1ba04a3fc286a9f3afee8fb47829be1fbc670a7926a2dc6"},{"path":"product/runtime/auths-gateway-kernel/src/transition.rs","sha256":"cefb8f01d915880f6921f2501ff881ad94b9de61072c34d9cd19220992f97374"},{"path":"product/runtime/auths-gateway/Cargo.toml","sha256":"00b28be86921dcdc0ad90cce0c62c2961cafefe96ea6c2edf0e926c3d405ccad"},{"path":"product/runtime/auths-gateway/src/admin.rs","sha256":"2d5cc67afac42fbd15f36e2d1693cd1b20cedacf775040dce6ffe04ccc94c9ea"},{"path":"product/runtime/auths-gateway/src/app.rs","sha256":"6f80f63833ea0815bb44fbf3b0cc54624a08e9fb578b035819f2980dc04e8256"},{"path":"product/runtime/auths-gateway/src/audit.rs","sha256":"0edb2037eb7b5d6f13acfce85c54f62a82bf7fdd31bc7e626c4fec183cef61dd"},{"path":"product/runtime/auths-gateway/src/audit_tests.rs","sha256":"990969384a52d75bc2489d9d412a9e7dd814bca1c8f65c701d6205fae62a15d5"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway-harness.rs","sha256":"12b0c24d36b2e6a3be392d3c081a783b355fdd67dc5b54bacc0410e803116b8c"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway.rs","sha256":"2f33a1da5dd54947ee1664795f90b3f07a11bb9ee184774bf470b78b03600f0c"},{"path":"product/runtime/auths-gateway/src/binding.rs","sha256":"663b0ce878319511aa7d05722ab4ab2fa9be18817884ffb2ee9f131ff1e382d1"},{"path":"product/runtime/auths-gateway/src/bounds.rs","sha256":"9cfa0eae4973e5e047a198360b22f041708fa20276b0b90c2ec440f06915d64b"},{"path":"product/runtime/auths-gateway/src/bounds_aggregate_tests.rs","sha256":"ab34f227b7c8692ba1da88ccb32bb3687a66adf8353d8282fae905d4a88eb612"},{"path":"product/runtime/auths-gateway/src/bounds_tests.rs","sha256":"74136bc570da7b9338b5a1a1ed9d3fd892c55135160964f9d3ac0e2cf5741375"},{"path":"product/runtime/auths-gateway/src/connection.rs","sha256":"7b5d049c258a26ed1c93ecf860f51d051a8a65f9b93554af0b1ea93862398ec9"},{"path":"product/runtime/auths-gateway/src/credential_journal.rs","sha256":"7297fccaee5cd8622928e8e0a42bba50da7941970a6f682ecd300c41ee6509da"},{"path":"product/runtime/auths-gateway/src/echo_verify.rs","sha256":"6d453051665f823abd7354d5c50031d9524cf47d6092d2f09080ae814e3b9575"},{"path":"product/runtime/auths-gateway/src/engine.rs","sha256":"f1052aaef43e441b9e0befa3f8ad1e2fd5279a27cb9d63aac0cf9dfdbe85a052"},{"path":"product/runtime/auths-gateway/src/fuzzing.rs","sha256":"ed3b0028487eb546a3b0a91d115aa8f18bcea324b61620bfe8e35a9e6ab18758"},{"path":"product/runtime/auths-gateway/src/generation_floor.rs","sha256":"fe1510ec96ce0f67e9a78edbfa94b33eb7df64c0ac4d0a67901124dcd0164777"},{"path":"product/runtime/auths-gateway/src/harness.rs","sha256":"c87e479f3eb281960f6c9c80d43c7560d7ccb654b0154ec823d3fcec4884ac05"},{"path":"product/runtime/auths-gateway/src/lib.rs","sha256":"4674c497940ab339d9b755b71a3e1fe5feeba28bfecc025b7d148dc804a508bf"},{"path":"product/runtime/auths-gateway/src/listener.rs","sha256":"aa08239bcbc1fcb55e8a212fbdf6a84f12985b0d436dcb51dc58b06e59e435f2"},{"path":"product/runtime/auths-gateway/src/observed_tests.rs","sha256":"a22be071695f89ca2578a4d82fd80d9cb82289213c9bdb8f0470f6b2dc3d9201"},{"path":"product/runtime/auths-gateway/src/observer.rs","sha256":"562ffcaea071c3856e0708dc2fe33516917e145d2438aabb75af0a2b6ba01046"},{"path":"product/runtime/auths-gateway/src/onboarding.rs","sha256":"0dfd7d67e7f02f18a28d1c86ca1b7751d7463f5efcdbe3825de0ad8cbccb3891"},{"path":"product/runtime/auths-gateway/src/operator.rs","sha256":"c3c36954a3e86723df035b47f43b85fc8ab3a6292983522b6258d5c6b4e6c4e4"},{"path":"product/runtime/auths-gateway/src/pending_vectors/attempts.rs","sha256":"47ef3c8cb1c5504d47ae9a0088705ce6715fe86bac1671a34a56fb38a64d0dd3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/bounds.rs","sha256":"e612217307e1da5b0eb5ee6582a7458bb064b8aa8a529fc6555b1b334127ab68"},{"path":"product/runtime/auths-gateway/src/pending_vectors/codes.rs","sha256":"e00670a5ef24eb856cc2c6dcda8e5a263842f55c76bb939c0c27bd9df37e5522"},{"path":"product/runtime/auths-gateway/src/pending_vectors/keys.rs","sha256":"f84c56f2ea9cb34b2b79c72d13fbf2c6585010ec1ed450af58a78c80c1ea1edd"},{"path":"product/runtime/auths-gateway/src/pending_vectors/mod.rs","sha256":"5de8340f0ef71a0b57a09e323fefe473d3160c6ae952b9ba46f714825fbacafc"},{"path":"product/runtime/auths-gateway/src/pending_vectors/outcomes.rs","sha256":"8ec07b9511b48913af36ac999d2aa0e82924289f6acb23ddaeb9f00f99815166"},{"path":"product/runtime/auths-gateway/src/pending_vectors/production.rs","sha256":"f574cabfa4687a4fc846b8f6a234b68ec53b876aed548b11445729cac1a55ede"},{"path":"product/runtime/auths-gateway/src/pending_vectors/recipes.rs","sha256":"51693208270231c25c3aef2a32151d5962114c71e86b88cb9df83181c7af83d9"},{"path":"product/runtime/auths-gateway/src/pre_entry.rs","sha256":"06ea78ca140468bfaba17d9ab04912ad68673954c3203c98fed28272ff2a00c0"},{"path":"product/runtime/auths-gateway/src/property_tests.rs","sha256":"939c081e2e154aaf10186754044bdd65608932c899b970a04a71d0afaa999a93"},{"path":"product/runtime/auths-gateway/src/qualification.rs","sha256":"06b49d3fc2ad4383f9e23beefa96033f1fd6e415e043878327583451a53086cc"},{"path":"product/runtime/auths-gateway/src/qualification_simulation.rs","sha256":"f5a5b588f4f30aeca1ccc4f4bc0b548de96206d166371ee3554d1e05763db5a7"},{"path":"product/runtime/auths-gateway/src/qualification_tests.rs","sha256":"9f32d3ff014b668652935c16a4ca83b73ed3e0a0e992fb716a881985a0e57567"},{"path":"product/runtime/auths-gateway/src/quorum_tests.rs","sha256":"a78380b019104d688c11a4410082c7e08ded3106aab099954c4f8a1b4ae0fd89"},{"path":"product/runtime/auths-gateway/src/readiness.rs","sha256":"911c3f11892f94641574375e2da4c671c802738f71082f12c39832331052d43d"},{"path":"product/runtime/auths-gateway/src/recipe.rs","sha256":"fecf9af67e7afc48d080e9f8f55f8ce28e49d0e08988717a27908bbda461d6b6"},{"path":"product/runtime/auths-gateway/src/recipe/lower.rs","sha256":"8088b8751ed831dbb48247af953c6290ac95e2a438ccd5bd65eff54be06a1fd1"},{"path":"product/runtime/auths-gateway/src/recipe/review.rs","sha256":"c3eb7d9fdd98dacf52750b14b67ad7b7faaecbbdeafff1e0b049f67d0a2d0139"},{"path":"product/runtime/auths-gateway/src/recipe/runtime.rs","sha256":"c286f0d15f974402822c0810d8e97f98411dc1c557755cc23e540d85e2bb42d9"},{"path":"product/runtime/auths-gateway/src/recipe/source.rs","sha256":"1af50298fb1461e1b24cbdf560d43124d6b1c4c529586c911b1c4797214a69ff"},{"path":"product/runtime/auths-gateway/src/recipe/tests.rs","sha256":"aac551a2481bbc60864c64079bc667dcb232e45a0f41a04073ed84ab5dbe1fce"},{"path":"product/runtime/auths-gateway/src/recipe/validate.rs","sha256":"3711b17605cb7b0d639bc1b180449231f5882a306cab20e2c7782155cc63b0d4"},{"path":"product/runtime/auths-gateway/src/scenario_tests.rs","sha256":"67915828ecfe2be0afadb5525277ab205f91172edc90852ec7b77c63b2d17fdc"},{"path":"product/runtime/auths-gateway/src/separation.rs","sha256":"be9306848ca5d801767cf6aa14247c8618312ef0e202f00ce0c24c4844491061"},{"path":"product/runtime/auths-gateway/src/store.rs","sha256":"1e5288345c2cb1421aeda277b3158d07607404b0ec46943222ac107b63dcbb46"},{"path":"product/runtime/auths-gateway/src/store_testkit.rs","sha256":"88d82fee42f1b8ef521e8deef0216e938ebeaad822eb2f5020e70b89d145ea70"},{"path":"product/runtime/auths-gateway/src/submit.rs","sha256":"c78dbbba7c45b443febf655056c5edcd635e77be7b21c5b2c318097502415ffe"},{"path":"product/runtime/auths-gateway/src/support.rs","sha256":"9fd979029793a22b15d9776a7fc172476fd7c126a80d4080c65d720845becbcb"},{"path":"product/runtime/auths-gateway/src/transport.rs","sha256":"be2c6dc75b8daec110bf8749fedc3823f6067d40b999aa3eb21126896a97d3ad"},{"path":"product/runtime/auths-kernel-runtime/Cargo.toml","sha256":"926bcd0053e5edd703be8f0027ad009e2982db013c8174c1366edbf38b48087d"},{"path":"product/runtime/auths-kernel-runtime/src/lib.rs","sha256":"7108faae9ca4bc32dc093ddaf885ac8f74f3c9b8d317b7c7d0ed00d1d0ab5972"},{"path":"product/runtime/auths-lifecycle/Cargo.toml","sha256":"c5053c705f8d5554b44e432fe75287a2faf11d644e5a2552e45ad6cd94176af5"},{"path":"product/runtime/auths-lifecycle/src/codec.rs","sha256":"51c4b746749150e8bfcd8ff972b3f6c1ef40bec15583448ec1b471d9ad737dc0"},{"path":"product/runtime/auths-lifecycle/src/digest.rs","sha256":"55282cd7d8aba37713c2dcb5357c9877819edb72a30eadefb860d28d7d3a3eb7"},{"path":"product/runtime/auths-lifecycle/src/identifier.rs","sha256":"31620e8c16de68d3d2d3b84d6353c1a5b9d4151d8247f91fa389b906a8e660f1"},{"path":"product/runtime/auths-lifecycle/src/kernel.rs","sha256":"2abb8c094b36d35b364e74d78091d14c5d6f3d1eb6552cca3b5538dbd017ce23"},{"path":"product/runtime/auths-lifecycle/src/lib.rs","sha256":"afe5a345cd309b5a4f08ffba3170a6d7f16ff914892b3f2006d5208ed24ec736"},{"path":"product/runtime/auths-lifecycle/src/model.rs","sha256":"1af12bbeeeaa65ec02ddcebd7d2c8c92ec1e339fa40ae85b45ab9b01a722a4fa"},{"path":"product/runtime/auths-lifecycle/src/operation.rs","sha256":"78e6d05fcf5d7ea4f148032a3fa26fdfcab77eb346019effe927b08e0d64d732"},{"path":"product/runtime/auths-lifecycle/src/registry.rs","sha256":"53495fe6f7a77422593a41623e28716f1c140dcc1e00f87f6b0ffbfb93a5ef90"},{"path":"product/runtime/auths-lifecycle/src/sealed.rs","sha256":"2e0c03b5813c926c159598bb7890d1523825edbe57cd687d42a5dfb3374a0c19"},{"path":"product/runtime/auths-lifecycle/src/test_support.rs","sha256":"221d9a5c5ef8e1f9f8fd66927484eaf813571d0568470278ecd8fa08a5eec8cd"},{"path":"product/runtime/auths-lifecycle/src/transition.rs","sha256":"011805a28efdd541f44ccea54dd0e34a1e58f4004447ee58013703b4fb6b2822"},{"path":"product/runtime/auths-runtime/Cargo.toml","sha256":"dd29d80a8b4bb56c869f036a6c9998f6e6d1c0383ac5dc03fa42b24abe2a7ff7"},{"path":"product/runtime/auths-runtime/src/lib.rs","sha256":"132ca03d58c14905d3a822a4972f42a22a5ad33a45f2ba9ca44f3a57d810b4b0"},{"path":"product/runtime/auths-runtime/src/production.rs","sha256":"fd4eff4270c571c10fcff6cf27df28961ebf074de8a1a028f500fda1ca376820"},{"path":"product/sdk/auths-approval-quorum/Cargo.toml","sha256":"df904971fca87a24194c5816738a331588fe8f164acb5d70839a35dca5f57114"},{"path":"product/sdk/auths-approval-quorum/src/lib.rs","sha256":"72e4086088a1c0912e4e1a9e980f26a5c280bf5ab16ea39c9f0f58d5096ac2ce"},{"path":"product/sdk/auths-approval-quorum/src/remote.rs","sha256":"9fa029c7c63003adf260f8aec55160c545681c60c1bace0d934e7525862aac7b"},{"path":"product/sdk/auths-approval-quorum/src/remote_tests.rs","sha256":"8a09ce17cfee82a035a74edd535f3ebeb3db0e078784740d3997b17dbdb10197"},{"path":"product/sdk/auths-approval-quorum/src/tests.rs","sha256":"0acbf12be3e497dcc6c2d8f29c9af3b1a7ed8e11b75f6399570d4f217a785060"},{"path":"product/stores/auths-stores/Cargo.toml","sha256":"a32c4b76d17b264be5d40d24497ff237e1ed87822e8bab86229b3db93106dbe3"},{"path":"product/stores/auths-stores/src/gateway_attempt.rs","sha256":"185da8f4a220fba836d5b78a9311f03204681c43a3c53951008084d135bf4d21"},{"path":"product/stores/auths-stores/src/lib.rs","sha256":"e721262edf8a9ab5568ddc27639176312d4a366203b5f73e2d7c11fde2c554e9"},{"path":"product/stores/auths-stores/src/lifecycle.rs","sha256":"94f64d25bc178a9e60ba3c0ee6915d7fb3af7c4468792d76b4e70f43f4de1e2f"}],"schema":"auths.gateway-semantic-closure/1"} \ No newline at end of file +{"files":[{"path":"Cargo.lock","sha256":"0e75e2fdef44e79e57797ac6661295ae58ddb8de4a1990a6fd22ce6c54f78604"},{"path":"Cargo.toml","sha256":"6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24"},{"path":"core/adapters/auths-did-keri/Cargo.toml","sha256":"86ba3e3f9a0a70d970568bfb3113b7ba7bbdd81c3eebbb52743dd574a0c0ecaa"},{"path":"core/adapters/auths-did-keri/src/lib.rs","sha256":"a75674842f8a7142004369ccd206ab43e476459293f0ff4bed4d4e659031b3e3"},{"path":"core/adapters/auths-did-key/Cargo.toml","sha256":"d5a3ae07ecde83f91eed4c3785051dd0f44eab6c891754f3309b6b40596707d7"},{"path":"core/adapters/auths-did-key/src/lib.rs","sha256":"b76a3f4528a725df53cfa9242e6e414e1d26caa48468aaed497e28b121f4497c"},{"path":"core/adapters/auths-raw-key/Cargo.toml","sha256":"f49616bc18c19e6aaa7e6a02ccebcdb9f5c1422c1278ef9869e0dbf22ceda7be"},{"path":"core/adapters/auths-raw-key/src/lib.rs","sha256":"45eec1b295dac3bed65cd79c942870b926b06b3f5d38eaebaeb6140ac69315fa"},{"path":"core/crates/auths-algebra-kernel/Cargo.toml","sha256":"0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba"},{"path":"core/crates/auths-algebra-kernel/src/generated.rs","sha256":"ae4bcbef42a408c7ffa0c6a74a42f7de177a6f14479e51d205acf830bda05960"},{"path":"core/crates/auths-algebra-kernel/src/lib.rs","sha256":"6654667eeb9b353d6648954c9fd2e8838462a82ce6b2803eb49e1366892c68c6"},{"path":"core/crates/auths-assurance/Cargo.toml","sha256":"afcb12a97ddd09d7a264b9ecd3fcaefc865ff2c9b4539ee85b00883420ba333a"},{"path":"core/crates/auths-assurance/src/lib.rs","sha256":"0fb2ec844d674b25a9e20b1601452c89c2454901fa506adfa9bb38ef9a7fa213"},{"path":"core/crates/auths-author/Cargo.toml","sha256":"1e6f0e3bc079ddb558decf0db26b291c6e72fc47327b6df1b7650d41689b215f"},{"path":"core/crates/auths-author/src/lib.rs","sha256":"e14475f2f49715a1869d5fa6b11ff1fbb72497e39097e09f833b0bae7e5b3f2b"},{"path":"core/crates/auths-author/src/observations.rs","sha256":"dda7d6bfa6f4bd7e95a480ca283c2c0e996f69c5c15cb0c7197af328131a7066"},{"path":"core/crates/auths-authority/Cargo.toml","sha256":"4f68212938029f79ebd857b4f3038494eb85d0163d49f07e51376715cf959815"},{"path":"core/crates/auths-authority/src/lib.rs","sha256":"da88d5194de4e17449e69972c0fb042afa3c39798a8f570f30771e77c384f1eb"},{"path":"core/crates/auths-codec/Cargo.toml","sha256":"e20e51826e17814effd9d8925d18d5fbdd6c0d37bf50231e743ec2611314722c"},{"path":"core/crates/auths-codec/src/approval.rs","sha256":"fbff43bf4d57f69f8b7738a8647751cde75c5a932dee65d924a1fe9c7202f91f"},{"path":"core/crates/auths-codec/src/bounded_policy.rs","sha256":"d21f6728be2d8a04b6d94921f2b683f7e61cbb42e0ac6866f1c88a49caa534c3"},{"path":"core/crates/auths-codec/src/decode.rs","sha256":"ba2999584cdf53b1b517ecb9c7ea50d39efee17c666a9a38e2ad1ac94379f778"},{"path":"core/crates/auths-codec/src/encode.rs","sha256":"8491192053e2e15d62b4d2a491de22405b7487ead69ab6f6bca40669ce7ca5f7"},{"path":"core/crates/auths-codec/src/error.rs","sha256":"fecb0737c16deb42d859f1dc7727c698438d9ac12064fd99e0024629642c390c"},{"path":"core/crates/auths-codec/src/hash.rs","sha256":"f88e111f1dbb2cef6b7b5e9c948cb45ff92e366710c8a5f5c636138aa748479e"},{"path":"core/crates/auths-codec/src/lib.rs","sha256":"3b0e5c94c6f34f750b88a9333e1d5c8145746d845d3a23e0d2f61807cf592ea7"},{"path":"core/crates/auths-codec/src/observation.rs","sha256":"38328b0c71ff97a4196eeade8b4faa889527ff1f80bb168468bcd49082a3987e"},{"path":"core/crates/auths-composition/Cargo.toml","sha256":"331e13025eb82588b5269ed3975929eb41c823d588c49e4c296273d85c6fe80e"},{"path":"core/crates/auths-composition/src/lib.rs","sha256":"e42e3b0b6a9985b73c533aeb23799c638979aa27a9ce7d0f10a8d60340570fb1"},{"path":"core/crates/auths-model/Cargo.toml","sha256":"565c15302b0cc9270db1e28efa3862804846850ba933cc17aea8abcec4a65987"},{"path":"core/crates/auths-model/src/approval.rs","sha256":"54cf44a9ef747ec21546a4086aecfb130bc7803b0d646430e6082df51e6e305f"},{"path":"core/crates/auths-model/src/bounded.rs","sha256":"f90496abc0a06c028b4d850af6ddab7d850bfafeaa3d042f1b1246a41d8bbbc9"},{"path":"core/crates/auths-model/src/bounded_policy.rs","sha256":"306a8f049cc7cfc7635fe0e4de47eb7813eed63d3c14c3be2b51586aa4eea450"},{"path":"core/crates/auths-model/src/lib.rs","sha256":"e7cfe6bb9574c6b016aa63e70658c31e0b90903ec6479a49f4a2ceb64f5bad97"},{"path":"core/crates/auths-model/src/observation.rs","sha256":"b3ed3e3cc090afca2896a7d3de7988afccc1ee1ea0ebd91b51a8bc0f20ad8dbb"},{"path":"core/crates/auths-multikey/Cargo.toml","sha256":"858756c1197befcada06134742bffe8d58cf674cadd6c046bf710570e96efaf2"},{"path":"core/crates/auths-multikey/src/lib.rs","sha256":"f5177fffb11e40eeaaa665ba886c541fc1f24d5eacdd6983fb03dc20148733f0"},{"path":"core/crates/auths-ports/Cargo.toml","sha256":"596a9b0f5af3717c16a6d13f7054d8a106bcd9f01f5f72c2235dd2afcf0ab16c"},{"path":"core/crates/auths-ports/src/binding.rs","sha256":"a16c012d40aa4249e3ec54372b9611006d0bfe8c7dc3c741911c2194ad17736d"},{"path":"core/crates/auths-ports/src/diagnostics.rs","sha256":"aa596572503b5a65a918bb2ff38281c144ff53821ee914e9325c852828d852df"},{"path":"core/crates/auths-ports/src/lib.rs","sha256":"8da1debf86f9532df0660155d04298beb1ba3a1204508f8586e2e67cd2fb3449"},{"path":"core/crates/auths-ports/src/path.rs","sha256":"b68fc547b4e4d97a60cbbc1cc1939fc6b34a8233b81f840bd396914a707e3ea1"},{"path":"core/crates/auths-raw-key-core/Cargo.toml","sha256":"98c0bc8527a537512e43a74dd6ba9658c6f0cdc16610cf938e3f9b43785d836d"},{"path":"core/crates/auths-raw-key-core/src/lib.rs","sha256":"98c0500c41697aae28708ad0bf970b9a97583d96a3d2c18d23e7fa351e0f7d12"},{"path":"core/crates/auths-registries/Cargo.toml","sha256":"590e49e58b0622d9d6274fea46796dcdb07dec9550eff295cce6a6427ffa51e2"},{"path":"core/crates/auths-registries/src/lib.rs","sha256":"450d3886d85ee333b7e046317fb5b47cde62483d5f3e41d46265e2caf4c373ec"},{"path":"core/crates/auths-registries/src/template.rs","sha256":"1224039dd2b3ce6fa8357613d8cafbae40400493da7176da202b9ade62fa05e4"},{"path":"core/crates/auths-signature-core/Cargo.toml","sha256":"6bee2230eb30af1be0bd5c2d57bd3e1903497a70028d47290d4ac6e9e0e8bca0"},{"path":"core/crates/auths-signature-core/src/lib.rs","sha256":"6e3f9311ded5e49ea50d445eb21e6d8fa12442aa4362a73e0cb6fda15b7cd865"},{"path":"core/crates/auths-signature/Cargo.toml","sha256":"7f7b5682466ba439d8c59579022cb61068cad9fb4bd2d73e1cc21327c902b450"},{"path":"core/crates/auths-signature/src/lib.rs","sha256":"b3d9ac4cc3ba0797b9e1c09f2d6ac05089b25dac4e285a5af28c0165b33d925b"},{"path":"core/crates/auths-verifier/Cargo.toml","sha256":"c43358e06a33324b41a8b93e5cc7279c55f7d21f1f6cfaa539a3fc7b4c27a38f"},{"path":"core/crates/auths-verifier/src/approval.rs","sha256":"c3cae6a49e169051eb555bb092b1069a4d422516d6a2114623a89e5f31ff923f"},{"path":"core/crates/auths-verifier/src/causal.rs","sha256":"9635230f33b13a263573d319ac8a1976addbcc07677514a43e3c7bf28dc04587"},{"path":"core/crates/auths-verifier/src/lib.rs","sha256":"f22dec38dfa47ced8da4f605390da8453273bee1da010f57fd1fdfcb10e0b389"},{"path":"core/crates/auths-verifier/src/observation.rs","sha256":"0bb07f06a0f9524c88427df1c972b1de8ba038a9eeeb15d3134c25125ae84b1e"},{"path":"core/crates/auths-verifier/src/trace.rs","sha256":"2213d72023a1d9e0413a2cf2c51c3dad9e04775d86033a0caaa9d29a8f0036f8"},{"path":"exchange/crates/auths-proof-exchange-model/Cargo.toml","sha256":"34b2db64f93a288e942b5a3918d28cdcbef906e0dc9074ce848018d3d5f7a1fa"},{"path":"exchange/crates/auths-proof-exchange-model/src/lib.rs","sha256":"49fac5aff2339d3a57c41cb8bb2a82852538e8f77ecc4b157c88e264ff31fb55"},{"path":"exchange/crates/auths-proof-exchange-port/Cargo.toml","sha256":"7ff660f1b7579dc570c791090aeb450404fbbf44c92781e289f5ccdde746d739"},{"path":"exchange/crates/auths-proof-exchange-port/src/lib.rs","sha256":"b408fb40c6432edc1facb3d8b3e9433a033f8dc73fe2e0ba5a88c972ca675021"},{"path":"product/config/auths-config/Cargo.toml","sha256":"e4b568ab9f6d84f7d7e6d66443fe825f360db9c27bc7c31d6ddc0647ba3ab304"},{"path":"product/config/auths-config/src/lib.rs","sha256":"fecf00ea65cef9018fda9af2063326d7065b869266d0d9e73a4f06816f1102cc"},{"path":"product/errors/auths-errors/Cargo.toml","sha256":"3b3a199b6460ba75bda84475bb5accd35e1485448a3981038db85bf4772dd350"},{"path":"product/errors/auths-errors/src/lib.rs","sha256":"7feeb9069fa4003f94f1f07c1c94619cf1c883e0dbaaf2187f04d0f742264bdd"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/Cargo.toml","sha256":"716f1f2a117d6d69d8effe9ee9057e24ba3502f20af6a602b06facb638cdabed"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/api.rs","sha256":"9ea61dd7ddd93282b073b98e453e6b75b26dc49689c04e9782435d06a3a09e48"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/clock.rs","sha256":"73f0a6e0f5903883329fa6683f5888288f759512ac69e5c87efd2b6b87f7d79f"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/http.rs","sha256":"14c1fce14e24c984b2a275563a29b6326fb08367922b6e8d37ba38b9cb81aa2b"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/identity.rs","sha256":"186de11230c8b33375951c4368609f8976bf9795f171af3fd7fac26207a94361"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs","sha256":"0b4617d044f5254a5ab22f5a2578f91cc025206a8c1845be39c1c56dcdf7a5df"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/names.rs","sha256":"41bb23572d6002e23ee103d6fe70ecd68764861c6f2e48a1c53af998270a4afa"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs","sha256":"39fed883f4802e68d3b41a68fea0aba0737810996b33d13577de70faba004c29"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/store.rs","sha256":"fc60ee9c49b2f4f063c449b4c78100c5c4872779e94ca168f796603b380ef6e4"},{"path":"product/integrations/auths-custody/Cargo.toml","sha256":"1e14034185ad1ec24a977fd5f41d0abee219606245c046ce2a82287fadef448b"},{"path":"product/integrations/auths-custody/src/conformance.rs","sha256":"8ed1afd58f18fc6becc268908aa6419c9aa404c79da0197963eb2599df44acf6"},{"path":"product/integrations/auths-custody/src/key.rs","sha256":"70cbb0fd21b6f5652157845a22c35be2d0f6c05b3d138fc4b9bb6dbdc3d81c40"},{"path":"product/integrations/auths-custody/src/lib.rs","sha256":"8ee593c1f59b0fd2126bdda9138026f5bc531beb64d4489a99785842e7b98b43"},{"path":"product/operations/auths-operations/Cargo.toml","sha256":"73dde1e914ba5e1386f8d49c0d730423cc72ae77ec44c6554a6a75cc8e8922b1"},{"path":"product/operations/auths-operations/src/explanation.rs","sha256":"b4a39bcbd5712cb9e735ee7deeb281f3fa6af5ddca973735bf3d87dce427ef11"},{"path":"product/operations/auths-operations/src/lib.rs","sha256":"3f401a56555113b98f57bca172a2660eaecedf76247b83a3fdbb089c133a29cd"},{"path":"product/operations/auths-operations/src/render/json.rs","sha256":"2ae042639960afee123730e945d373bc5dda1d2b3af20ae16c939a7e99b9e418"},{"path":"product/operations/auths-operations/src/render/mod.rs","sha256":"b3b7f6fe473f49227ace5a68bfc3d8dc14b5db8dd9888fd9e207070337b1b8bf"},{"path":"product/operations/auths-operations/src/render/text.rs","sha256":"f216cf3bdb00e264523271b16e7059535ac6b1aabf271cebd7935af155e4bfec"},{"path":"product/policy/auths-bounded-policy/Cargo.toml","sha256":"babd5d200923137ead71d8c2528f847cea323ce98da942a1320b054436612c47"},{"path":"product/policy/auths-bounded-policy/src/arithmetic.rs","sha256":"75e43c5d4eab8d1f71c1daf53839f5f9fe45a400afc1f63a30c6f55ce3632627"},{"path":"product/policy/auths-bounded-policy/src/commitment.rs","sha256":"c5706f2d583454e1a7f570f7ada138d4d864bef0205dfae7c1296774f396bb3f"},{"path":"product/policy/auths-bounded-policy/src/eligibility.rs","sha256":"c9acdfb793074e687fc36efad506be27dbd99ffbf40387bc66c8de39ef238432"},{"path":"product/policy/auths-bounded-policy/src/identifier.rs","sha256":"0006a32bae9eb16c4178cf797df418d2b0a781f2bc6474b741dc1a908141831c"},{"path":"product/policy/auths-bounded-policy/src/kernel.rs","sha256":"99187c28b161ac70bee1afed60711f7f645adb4d1671a01863f9849b369811d5"},{"path":"product/policy/auths-bounded-policy/src/lib.rs","sha256":"76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c"},{"path":"product/policy/auths-bounded-policy/src/receipt.rs","sha256":"3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad"},{"path":"product/policy/auths-bounded-policy/src/registry.rs","sha256":"4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0"},{"path":"product/profiles/auths-profile-api/Cargo.toml","sha256":"7ae85761f58625b5d678f961fd052eebf3e000ef565c7312e3ac857763c0017f"},{"path":"product/profiles/auths-profile-api/src/lib.rs","sha256":"a194b82b20bf8aa864c2334ef6c6aec30b2154ded972862252d5dcefa488ab95"},{"path":"product/profiles/auths-profile-mcp/Cargo.toml","sha256":"db264fc25242f7b7e4133cbe5782545b3107b406c87168ae072683cfb59eac66"},{"path":"product/profiles/auths-profile-mcp/src/arguments.rs","sha256":"a5de696586d507e2aee4a49fee99ef1ef4c51a2e46603f8838f1af6d9009833f"},{"path":"product/profiles/auths-profile-mcp/src/lib.rs","sha256":"d0f8b733a09ef8408336cdebc8948d6a5861012ce6878598b11be7084dfd4280"},{"path":"product/profiles/auths-profile-mcp/src/session.rs","sha256":"166c281fa66333388e4760d6098dad02d3359e1d5de4b8f93312c014f97abb03"},{"path":"product/qualification/auths-recipe-qualification/Cargo.toml","sha256":"b7b15b30b9a3d96d4f089d514266d3a892de6608d30707aa44be31cca89ca9fe"},{"path":"product/qualification/auths-recipe-qualification/src/canonical.rs","sha256":"30a9b50777f0dcb4b606abfee2467d5a975d9f6ad941ab6c13ca3df5b359f667"},{"path":"product/qualification/auths-recipe-qualification/src/closure.rs","sha256":"0ad6aee9bd981e2863fa725f209ec84031db2ff12f4c7ac3aaf5120f0bb86039"},{"path":"product/qualification/auths-recipe-qualification/src/error.rs","sha256":"52d5cf720a1e4579008fdda90a3ac2c31f0b8db57985f121f65e54b4da2b7dd1"},{"path":"product/qualification/auths-recipe-qualification/src/evidence.rs","sha256":"ba45a7409d67a8af26ab811af306412014557477a101ab2a8eb0faf8f2bd4b91"},{"path":"product/qualification/auths-recipe-qualification/src/ids.rs","sha256":"e81a906d571497ab2da753e1532d4443706410e0b75fdd59a7d2d788c7aec403"},{"path":"product/qualification/auths-recipe-qualification/src/launch.rs","sha256":"41f2e2de90e1e7d6440a66eda3eb9bea8d5e0741bc232305a76a363ab5f813c1"},{"path":"product/qualification/auths-recipe-qualification/src/lib.rs","sha256":"5c9cff04c8960df805a2f7656cf5e74932798e0db7648341e96ae7073a592404"},{"path":"product/qualification/auths-recipe-qualification/src/model.rs","sha256":"3484eb0ec287b23d4682ade7b1b0f8d1335985b3fb180f06fc28716076957d5f"},{"path":"product/qualification/auths-recipe-qualification/src/release.rs","sha256":"d816b53e2275e902c750ad03803061844e259e28560ab2d1c77e8a43981a4d6a"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/mod.rs","sha256":"7f15b68e05a04f202bcb1fb80de1d9a9a4fda8bfd6af2cd4e5c660fc75d96fe5"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/schemas.rs","sha256":"c59feec2805621f341a90f81fc005e2c12f7a70f9d264fdeacccb2be4fe1c046"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/verification.rs","sha256":"6a6b5834c5dae10af1ba8939b2deae43b85db71544dc8f077ff63b7fe68ac8a8"},{"path":"product/qualification/auths-recipe-qualification/src/verify.rs","sha256":"a470a9b98c04dc8d5dabe4d3dc8ed4e7a3ceb1cde035944a0714462bbf37d56d"},{"path":"product/receipts/auths-receipts/Cargo.toml","sha256":"6001fa1375899953aafcb07c23a6da0c8f57ea7ec08bb9c950b12a60a8cc6f0f"},{"path":"product/receipts/auths-receipts/src/disclosure.rs","sha256":"ba9ed439be0a320c8a01f5b6e9b51361c1a37e076947490d8e4a484ba6bb119c"},{"path":"product/receipts/auths-receipts/src/lib.rs","sha256":"547a57c4160256719cafb7d0ab972d9fc80b0da14fbbce4148c70c414070ff36"},{"path":"product/runtime/auths-connections/Cargo.toml","sha256":"babeb6e1dda3dfb66291713ce1e43dce5c349833d0b50ea4dccbf986030026b2"},{"path":"product/runtime/auths-connections/src/credential.rs","sha256":"82921413bb053f0f6c7931fbd4e6a86c8cc1d8c6b51debd9c2cef33a8d5b1c51"},{"path":"product/runtime/auths-connections/src/kernel.rs","sha256":"a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8"},{"path":"product/runtime/auths-connections/src/lib.rs","sha256":"79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22"},{"path":"product/runtime/auths-connections/src/model.rs","sha256":"de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77"},{"path":"product/runtime/auths-connections/src/registry.rs","sha256":"e57640e003e72ad3235c567c2bb944a262bd64e673f023b62ea091094cc7e946"},{"path":"product/runtime/auths-gateway-kernel/Cargo.toml","sha256":"34f864e67656af4ac7e5c7a347a23f01fc8ab31365b8e23c0ef474483b14a183"},{"path":"product/runtime/auths-gateway-kernel/src/construct.rs","sha256":"e9d65744bae273d65face4285e5d2da75c06a92ab48f7b8333d496604e31c63c"},{"path":"product/runtime/auths-gateway-kernel/src/lib.rs","sha256":"cfda6f8453426564c085475f183b6f790b438768a19668f1b65d33ba59dc8632"},{"path":"product/runtime/auths-gateway-kernel/src/order.rs","sha256":"e0045f877c4b7fe3860c291039853885064ddcdebba7c9b345ab65e81e646dda"},{"path":"product/runtime/auths-gateway-kernel/src/outcome.rs","sha256":"e9785b1afe70788c89b51b18655bcd5acff7b0c8e3d12fb79c6f05a202e67e6b"},{"path":"product/runtime/auths-gateway-kernel/src/ratio.rs","sha256":"7ace22264812e6fc1ef3a62afee402cf43494bb71ae0d3de219ad1b39d690bcb"},{"path":"product/runtime/auths-gateway-kernel/src/recovery.rs","sha256":"9f46dcd1685ab6e4d1ba04a3fc286a9f3afee8fb47829be1fbc670a7926a2dc6"},{"path":"product/runtime/auths-gateway-kernel/src/transition.rs","sha256":"cefb8f01d915880f6921f2501ff881ad94b9de61072c34d9cd19220992f97374"},{"path":"product/runtime/auths-gateway/Cargo.toml","sha256":"00b28be86921dcdc0ad90cce0c62c2961cafefe96ea6c2edf0e926c3d405ccad"},{"path":"product/runtime/auths-gateway/src/admin.rs","sha256":"2d5cc67afac42fbd15f36e2d1693cd1b20cedacf775040dce6ffe04ccc94c9ea"},{"path":"product/runtime/auths-gateway/src/app.rs","sha256":"6f80f63833ea0815bb44fbf3b0cc54624a08e9fb578b035819f2980dc04e8256"},{"path":"product/runtime/auths-gateway/src/audit.rs","sha256":"0edb2037eb7b5d6f13acfce85c54f62a82bf7fdd31bc7e626c4fec183cef61dd"},{"path":"product/runtime/auths-gateway/src/audit_tests.rs","sha256":"990969384a52d75bc2489d9d412a9e7dd814bca1c8f65c701d6205fae62a15d5"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway-harness.rs","sha256":"12b0c24d36b2e6a3be392d3c081a783b355fdd67dc5b54bacc0410e803116b8c"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway.rs","sha256":"2f33a1da5dd54947ee1664795f90b3f07a11bb9ee184774bf470b78b03600f0c"},{"path":"product/runtime/auths-gateway/src/binding.rs","sha256":"663b0ce878319511aa7d05722ab4ab2fa9be18817884ffb2ee9f131ff1e382d1"},{"path":"product/runtime/auths-gateway/src/bounds.rs","sha256":"9cfa0eae4973e5e047a198360b22f041708fa20276b0b90c2ec440f06915d64b"},{"path":"product/runtime/auths-gateway/src/bounds_aggregate_tests.rs","sha256":"ab34f227b7c8692ba1da88ccb32bb3687a66adf8353d8282fae905d4a88eb612"},{"path":"product/runtime/auths-gateway/src/bounds_tests.rs","sha256":"74136bc570da7b9338b5a1a1ed9d3fd892c55135160964f9d3ac0e2cf5741375"},{"path":"product/runtime/auths-gateway/src/connection.rs","sha256":"7b5d049c258a26ed1c93ecf860f51d051a8a65f9b93554af0b1ea93862398ec9"},{"path":"product/runtime/auths-gateway/src/credential_journal.rs","sha256":"7297fccaee5cd8622928e8e0a42bba50da7941970a6f682ecd300c41ee6509da"},{"path":"product/runtime/auths-gateway/src/echo_verify.rs","sha256":"6d453051665f823abd7354d5c50031d9524cf47d6092d2f09080ae814e3b9575"},{"path":"product/runtime/auths-gateway/src/engine.rs","sha256":"f1052aaef43e441b9e0befa3f8ad1e2fd5279a27cb9d63aac0cf9dfdbe85a052"},{"path":"product/runtime/auths-gateway/src/fuzzing.rs","sha256":"ed3b0028487eb546a3b0a91d115aa8f18bcea324b61620bfe8e35a9e6ab18758"},{"path":"product/runtime/auths-gateway/src/generation_floor.rs","sha256":"fe1510ec96ce0f67e9a78edbfa94b33eb7df64c0ac4d0a67901124dcd0164777"},{"path":"product/runtime/auths-gateway/src/harness.rs","sha256":"c87e479f3eb281960f6c9c80d43c7560d7ccb654b0154ec823d3fcec4884ac05"},{"path":"product/runtime/auths-gateway/src/lib.rs","sha256":"a1f51b76524a89842720b4fda58b2293d4bc82b41c912d5a462261603c593cea"},{"path":"product/runtime/auths-gateway/src/listener.rs","sha256":"aa08239bcbc1fcb55e8a212fbdf6a84f12985b0d436dcb51dc58b06e59e435f2"},{"path":"product/runtime/auths-gateway/src/observed_tests.rs","sha256":"a22be071695f89ca2578a4d82fd80d9cb82289213c9bdb8f0470f6b2dc3d9201"},{"path":"product/runtime/auths-gateway/src/observer.rs","sha256":"562ffcaea071c3856e0708dc2fe33516917e145d2438aabb75af0a2b6ba01046"},{"path":"product/runtime/auths-gateway/src/onboarding.rs","sha256":"0dfd7d67e7f02f18a28d1c86ca1b7751d7463f5efcdbe3825de0ad8cbccb3891"},{"path":"product/runtime/auths-gateway/src/operator.rs","sha256":"c3c36954a3e86723df035b47f43b85fc8ab3a6292983522b6258d5c6b4e6c4e4"},{"path":"product/runtime/auths-gateway/src/pending_vectors/attempts.rs","sha256":"47ef3c8cb1c5504d47ae9a0088705ce6715fe86bac1671a34a56fb38a64d0dd3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/bounds.rs","sha256":"e612217307e1da5b0eb5ee6582a7458bb064b8aa8a529fc6555b1b334127ab68"},{"path":"product/runtime/auths-gateway/src/pending_vectors/codes.rs","sha256":"e00670a5ef24eb856cc2c6dcda8e5a263842f55c76bb939c0c27bd9df37e5522"},{"path":"product/runtime/auths-gateway/src/pending_vectors/keys.rs","sha256":"f84c56f2ea9cb34b2b79c72d13fbf2c6585010ec1ed450af58a78c80c1ea1edd"},{"path":"product/runtime/auths-gateway/src/pending_vectors/mod.rs","sha256":"5de8340f0ef71a0b57a09e323fefe473d3160c6ae952b9ba46f714825fbacafc"},{"path":"product/runtime/auths-gateway/src/pending_vectors/outcomes.rs","sha256":"8ec07b9511b48913af36ac999d2aa0e82924289f6acb23ddaeb9f00f99815166"},{"path":"product/runtime/auths-gateway/src/pending_vectors/production.rs","sha256":"f574cabfa4687a4fc846b8f6a234b68ec53b876aed548b11445729cac1a55ede"},{"path":"product/runtime/auths-gateway/src/pending_vectors/recipes.rs","sha256":"51693208270231c25c3aef2a32151d5962114c71e86b88cb9df83181c7af83d9"},{"path":"product/runtime/auths-gateway/src/pre_entry.rs","sha256":"06ea78ca140468bfaba17d9ab04912ad68673954c3203c98fed28272ff2a00c0"},{"path":"product/runtime/auths-gateway/src/property_tests.rs","sha256":"939c081e2e154aaf10186754044bdd65608932c899b970a04a71d0afaa999a93"},{"path":"product/runtime/auths-gateway/src/qualification.rs","sha256":"06b49d3fc2ad4383f9e23beefa96033f1fd6e415e043878327583451a53086cc"},{"path":"product/runtime/auths-gateway/src/qualification_simulation.rs","sha256":"7559fc0faec69d41cba099e537e8ea0b228b34c7fa60e87ebe3f0625bc4921bb"},{"path":"product/runtime/auths-gateway/src/qualification_tests.rs","sha256":"4c1f5083e9258e3068781487a421379091647bbf58e2d643fecc20af726d1e7f"},{"path":"product/runtime/auths-gateway/src/quorum_tests.rs","sha256":"a78380b019104d688c11a4410082c7e08ded3106aab099954c4f8a1b4ae0fd89"},{"path":"product/runtime/auths-gateway/src/readiness.rs","sha256":"911c3f11892f94641574375e2da4c671c802738f71082f12c39832331052d43d"},{"path":"product/runtime/auths-gateway/src/recipe.rs","sha256":"fecf9af67e7afc48d080e9f8f55f8ce28e49d0e08988717a27908bbda461d6b6"},{"path":"product/runtime/auths-gateway/src/recipe/lower.rs","sha256":"8088b8751ed831dbb48247af953c6290ac95e2a438ccd5bd65eff54be06a1fd1"},{"path":"product/runtime/auths-gateway/src/recipe/review.rs","sha256":"c3eb7d9fdd98dacf52750b14b67ad7b7faaecbbdeafff1e0b049f67d0a2d0139"},{"path":"product/runtime/auths-gateway/src/recipe/runtime.rs","sha256":"c286f0d15f974402822c0810d8e97f98411dc1c557755cc23e540d85e2bb42d9"},{"path":"product/runtime/auths-gateway/src/recipe/source.rs","sha256":"1af50298fb1461e1b24cbdf560d43124d6b1c4c529586c911b1c4797214a69ff"},{"path":"product/runtime/auths-gateway/src/recipe/tests.rs","sha256":"aac551a2481bbc60864c64079bc667dcb232e45a0f41a04073ed84ab5dbe1fce"},{"path":"product/runtime/auths-gateway/src/recipe/validate.rs","sha256":"3711b17605cb7b0d639bc1b180449231f5882a306cab20e2c7782155cc63b0d4"},{"path":"product/runtime/auths-gateway/src/scenario_tests.rs","sha256":"67915828ecfe2be0afadb5525277ab205f91172edc90852ec7b77c63b2d17fdc"},{"path":"product/runtime/auths-gateway/src/separation.rs","sha256":"be9306848ca5d801767cf6aa14247c8618312ef0e202f00ce0c24c4844491061"},{"path":"product/runtime/auths-gateway/src/simulation_attestation.rs","sha256":"b5210599a59e62335bebc94f2232f7178c867261dd633a2cef263c3a7bca08dc"},{"path":"product/runtime/auths-gateway/src/store.rs","sha256":"1e5288345c2cb1421aeda277b3158d07607404b0ec46943222ac107b63dcbb46"},{"path":"product/runtime/auths-gateway/src/store_testkit.rs","sha256":"88d82fee42f1b8ef521e8deef0216e938ebeaad822eb2f5020e70b89d145ea70"},{"path":"product/runtime/auths-gateway/src/submit.rs","sha256":"c78dbbba7c45b443febf655056c5edcd635e77be7b21c5b2c318097502415ffe"},{"path":"product/runtime/auths-gateway/src/support.rs","sha256":"9fd979029793a22b15d9776a7fc172476fd7c126a80d4080c65d720845becbcb"},{"path":"product/runtime/auths-gateway/src/transport.rs","sha256":"be2c6dc75b8daec110bf8749fedc3823f6067d40b999aa3eb21126896a97d3ad"},{"path":"product/runtime/auths-kernel-runtime/Cargo.toml","sha256":"926bcd0053e5edd703be8f0027ad009e2982db013c8174c1366edbf38b48087d"},{"path":"product/runtime/auths-kernel-runtime/src/lib.rs","sha256":"7108faae9ca4bc32dc093ddaf885ac8f74f3c9b8d317b7c7d0ed00d1d0ab5972"},{"path":"product/runtime/auths-lifecycle/Cargo.toml","sha256":"c5053c705f8d5554b44e432fe75287a2faf11d644e5a2552e45ad6cd94176af5"},{"path":"product/runtime/auths-lifecycle/src/codec.rs","sha256":"51c4b746749150e8bfcd8ff972b3f6c1ef40bec15583448ec1b471d9ad737dc0"},{"path":"product/runtime/auths-lifecycle/src/digest.rs","sha256":"55282cd7d8aba37713c2dcb5357c9877819edb72a30eadefb860d28d7d3a3eb7"},{"path":"product/runtime/auths-lifecycle/src/identifier.rs","sha256":"31620e8c16de68d3d2d3b84d6353c1a5b9d4151d8247f91fa389b906a8e660f1"},{"path":"product/runtime/auths-lifecycle/src/kernel.rs","sha256":"2abb8c094b36d35b364e74d78091d14c5d6f3d1eb6552cca3b5538dbd017ce23"},{"path":"product/runtime/auths-lifecycle/src/lib.rs","sha256":"afe5a345cd309b5a4f08ffba3170a6d7f16ff914892b3f2006d5208ed24ec736"},{"path":"product/runtime/auths-lifecycle/src/model.rs","sha256":"1af12bbeeeaa65ec02ddcebd7d2c8c92ec1e339fa40ae85b45ab9b01a722a4fa"},{"path":"product/runtime/auths-lifecycle/src/operation.rs","sha256":"78e6d05fcf5d7ea4f148032a3fa26fdfcab77eb346019effe927b08e0d64d732"},{"path":"product/runtime/auths-lifecycle/src/registry.rs","sha256":"53495fe6f7a77422593a41623e28716f1c140dcc1e00f87f6b0ffbfb93a5ef90"},{"path":"product/runtime/auths-lifecycle/src/sealed.rs","sha256":"2e0c03b5813c926c159598bb7890d1523825edbe57cd687d42a5dfb3374a0c19"},{"path":"product/runtime/auths-lifecycle/src/test_support.rs","sha256":"221d9a5c5ef8e1f9f8fd66927484eaf813571d0568470278ecd8fa08a5eec8cd"},{"path":"product/runtime/auths-lifecycle/src/transition.rs","sha256":"011805a28efdd541f44ccea54dd0e34a1e58f4004447ee58013703b4fb6b2822"},{"path":"product/runtime/auths-runtime/Cargo.toml","sha256":"dd29d80a8b4bb56c869f036a6c9998f6e6d1c0383ac5dc03fa42b24abe2a7ff7"},{"path":"product/runtime/auths-runtime/src/lib.rs","sha256":"132ca03d58c14905d3a822a4972f42a22a5ad33a45f2ba9ca44f3a57d810b4b0"},{"path":"product/runtime/auths-runtime/src/production.rs","sha256":"fd4eff4270c571c10fcff6cf27df28961ebf074de8a1a028f500fda1ca376820"},{"path":"product/sdk/auths-approval-quorum/Cargo.toml","sha256":"df904971fca87a24194c5816738a331588fe8f164acb5d70839a35dca5f57114"},{"path":"product/sdk/auths-approval-quorum/src/lib.rs","sha256":"72e4086088a1c0912e4e1a9e980f26a5c280bf5ab16ea39c9f0f58d5096ac2ce"},{"path":"product/sdk/auths-approval-quorum/src/remote.rs","sha256":"9fa029c7c63003adf260f8aec55160c545681c60c1bace0d934e7525862aac7b"},{"path":"product/sdk/auths-approval-quorum/src/remote_tests.rs","sha256":"8a09ce17cfee82a035a74edd535f3ebeb3db0e078784740d3997b17dbdb10197"},{"path":"product/sdk/auths-approval-quorum/src/tests.rs","sha256":"0acbf12be3e497dcc6c2d8f29c9af3b1a7ed8e11b75f6399570d4f217a785060"},{"path":"product/stores/auths-stores/Cargo.toml","sha256":"a32c4b76d17b264be5d40d24497ff237e1ed87822e8bab86229b3db93106dbe3"},{"path":"product/stores/auths-stores/src/gateway_attempt.rs","sha256":"185da8f4a220fba836d5b78a9311f03204681c43a3c53951008084d135bf4d21"},{"path":"product/stores/auths-stores/src/lib.rs","sha256":"e721262edf8a9ab5568ddc27639176312d4a366203b5f73e2d7c11fde2c554e9"},{"path":"product/stores/auths-stores/src/lifecycle.rs","sha256":"94f64d25bc178a9e60ba3c0ee6915d7fb3af7c4468792d76b4e70f43f4de1e2f"}],"schema":"auths.gateway-semantic-closure/1"} \ No newline at end of file diff --git a/product/runtime/auths-gateway/src/lib.rs b/product/runtime/auths-gateway/src/lib.rs index 279af6ee3..a42dc160c 100644 --- a/product/runtime/auths-gateway/src/lib.rs +++ b/product/runtime/auths-gateway/src/lib.rs @@ -52,6 +52,8 @@ mod quorum_tests; #[cfg(test)] mod scenario_tests; #[cfg(test)] +mod simulation_attestation; +#[cfg(test)] mod store_testkit; pub use audit::{ diff --git a/product/runtime/auths-gateway/src/qualification_simulation.rs b/product/runtime/auths-gateway/src/qualification_simulation.rs index 942be51b2..689a12d64 100644 --- a/product/runtime/auths-gateway/src/qualification_simulation.rs +++ b/product/runtime/auths-gateway/src/qualification_simulation.rs @@ -235,11 +235,15 @@ fn publish(family: Family, recipe: &CompiledRecipe, cases: &[Measurement]) { if let Some(directory) = std::env::var_os("AUTHS_QUALIFICATION_SIMULATION_OUTPUT") { let directory = std::path::PathBuf::from(directory); std::fs::create_dir_all(&directory).expect("report directory"); + let bytes = serde_json::to_vec_pretty(&report).expect("report"); + let signature = crate::simulation_attestation::sign(&bytes, family.name()); + std::fs::write(directory.join(format!("{}.json", family.name())), bytes) + .expect("write report"); std::fs::write( - directory.join(format!("{}.json", family.name())), - serde_json::to_vec_pretty(&report).expect("report"), + directory.join(format!("{}.attestation.json", family.name())), + signature, ) - .expect("write report"); + .expect("write detached simulation signature"); } } diff --git a/product/runtime/auths-gateway/src/qualification_tests.rs b/product/runtime/auths-gateway/src/qualification_tests.rs index fb0788e30..4108f07e1 100644 --- a/product/runtime/auths-gateway/src/qualification_tests.rs +++ b/product/runtime/auths-gateway/src/qualification_tests.rs @@ -117,6 +117,53 @@ async fn an_engine_without_a_configured_gate_leases_nothing() { assert_eq!(installation.first.leases.load(Ordering::SeqCst), 0); } +#[test] +fn verify_simulation_reports() { + use sha2::Digest as _; + use std::io::Read as _; + + let Some(directory) = std::env::var_os("AUTHS_QUALIFICATION_SIMULATION_OUTPUT") else { + return; + }; + let directory = std::path::PathBuf::from(directory); + let bounded = |path: &std::path::Path, maximum: u64| { + assert!( + std::fs::symlink_metadata(path) + .expect("metadata") + .file_type() + .is_file() + ); + let mut bytes = Vec::new(); + std::fs::File::open(path) + .expect("public file") + .take(maximum + 1) + .read_to_end(&mut bytes) + .expect("bounded public file"); + assert!(bytes.len() as u64 <= maximum); + bytes + }; + let mut verified = Vec::new(); + for family in ["stripe-refund-v1", "airtable-record-update-v1"] { + let report = bounded(&directory.join(format!("{family}.json")), 1_048_576); + let signature = bounded(&directory.join(format!("{family}.attestation.json")), 4096); + assert!(crate::simulation_attestation::verify(&report, &signature)); + verified.push( + json!({"family": family, "report_sha256": hex::encode(sha2::Sha256::digest(&report)), + "signature_sha256": hex::encode(sha2::Sha256::digest(&signature))}), + ); + } + std::fs::write( + directory.join("provider-signature-verification.json"), + serde_json::to_vec_pretty( + &json!({"schema": "auths.provider-simulation-signature-verification/1", + "simulation": true, "stable_launch_ready": false, "verified": verified, + "scope": "detached self-signed simulation reports; no production trust"}), + ) + .expect("verification report"), + ) + .expect("write verification report"); +} + /// Rehearses the first ceremony under fresh ephemeral trust. The signed /// records are deliberately the issuance testkit's placeholder records; /// their excluded claim says they stand for no provider run. Family driver diff --git a/product/runtime/auths-gateway/src/semantic_closure.rs b/product/runtime/auths-gateway/src/semantic_closure.rs index b5cef10d3..7b208686a 100644 --- a/product/runtime/auths-gateway/src/semantic_closure.rs +++ b/product/runtime/auths-gateway/src/semantic_closure.rs @@ -10,7 +10,7 @@ /// SHA-256 of the schema, a NUL byte, and `semantic-closure.json`. /// Regenerate through `semantic_closure_is_current` with `AUTHS_UPDATE_FIXTURES=1`. pub const GATEWAY_SEMANTIC_CLOSURE_SHA256: &str = - "c9414e3a22dce48048dea9e4f8c2b4baa5d8cfd17a2cf8bddb172ca12751193f"; + "11a256092b821eec54d27e3ad25cc05f7955da236ea23853cced71c32215764d"; #[cfg(test)] mod tests { diff --git a/product/runtime/auths-gateway/src/simulation_attestation.rs b/product/runtime/auths-gateway/src/simulation_attestation.rs new file mode 100644 index 000000000..fc98572b8 --- /dev/null +++ b/product/runtime/auths-gateway/src/simulation_attestation.rs @@ -0,0 +1,120 @@ +//! Detached signatures for measured simulation reports, never qualifications. + +use auths_recipe_qualification_issuance::SigningSeed; +use base64ct::{Base64Unpadded, Encoding as _}; +use ed25519_dalek::{Signature, Signer as _, SigningKey, VerifyingKey}; +use serde::{Deserialize, Serialize}; +use sha2::{Digest as _, Sha256}; + +const SCHEMA: &str = "auths.provider-simulation-attestation/1"; +const DOMAIN: &[u8] = b"auths.provider-simulation-attestation/1\0"; + +#[derive(Deserialize, Serialize)] +#[serde(deny_unknown_fields)] +struct Statement { + schema: String, + simulation: bool, + stable_launch_ready: bool, + signer_kind: String, + family: String, + report_sha256: String, + public_key_b64: String, +} + +#[derive(Deserialize, Serialize)] +#[serde(deny_unknown_fields)] +struct Attestation { + statement: Statement, + signature_b64: String, +} + +fn preimage(statement: &Statement) -> Vec { + let mut bytes = DOMAIN.to_vec(); + bytes.extend(serde_json_canonicalizer::to_vec(statement).expect("simulation statement")); + bytes +} + +pub(crate) fn sign(report: &[u8], family: &str) -> Vec { + let seed = SigningSeed::generate().expect("ephemeral report signer"); + let key = SigningKey::from_bytes(seed.expose()); + let statement = Statement { + schema: SCHEMA.to_owned(), + simulation: true, + stable_launch_ready: false, + signer_kind: "disposable-self-signed-simulation-key".to_owned(), + family: family.to_owned(), + report_sha256: hex::encode(Sha256::digest(report)), + public_key_b64: Base64Unpadded::encode_string(&key.verifying_key().to_bytes()), + }; + let signature_b64 = Base64Unpadded::encode_string(&key.sign(&preimage(&statement)).to_bytes()); + let bytes = serde_json::to_vec_pretty(&Attestation { + statement, + signature_b64, + }) + .expect("simulation attestation"); + assert!(verify(report, &bytes), "verify before publishing"); + bytes +} + +pub(crate) fn verify(report: &[u8], attestation: &[u8]) -> bool { + if report.len() > 1_048_576 || attestation.len() > 4096 { + return false; + } + let Ok(envelope) = serde_json::from_slice::(attestation) else { + return false; + }; + let statement = &envelope.statement; + let Ok(body) = serde_json::from_slice::(report) else { + return false; + }; + if statement.schema != SCHEMA + || !statement.simulation + || statement.stable_launch_ready + || statement.signer_kind != "disposable-self-signed-simulation-key" + || statement.report_sha256 != hex::encode(Sha256::digest(report)) + || body["schema"] != "auths.recipe-qualification-simulation/1" + || body["simulation"] != true + || body["stable_launch_ready"] != false + || body["family"] != statement.family + { + return false; + } + let Ok(public) = Base64Unpadded::decode_vec(&statement.public_key_b64) else { + return false; + }; + let Ok(public) = <[u8; 32]>::try_from(public.as_slice()) else { + return false; + }; + let Ok(key) = VerifyingKey::from_bytes(&public) else { + return false; + }; + let Ok(signature) = Base64Unpadded::decode_vec(&envelope.signature_b64) else { + return false; + }; + let Ok(signature) = Signature::from_slice(&signature) else { + return false; + }; + key.verify_strict(&preimage(statement), &signature).is_ok() +} + +#[test] +fn altered_reports_and_scope_are_refused() { + let report = br#"{"schema":"auths.recipe-qualification-simulation/1","simulation":true,"stable_launch_ready":false,"family":"stripe-refund-v1","cases":[]}"#; + let attestation = sign(report, "stripe-refund-v1"); + assert!(verify(report, &attestation)); + let mut altered = report.to_vec(); + altered.push(b' '); + assert!(!verify(&altered, &attestation)); + let mut envelope: serde_json::Value = serde_json::from_slice(&attestation).expect("envelope"); + envelope["statement"]["simulation"] = false.into(); + assert!(!verify( + report, + &serde_json::to_vec(&envelope).expect("altered scope") + )); + envelope["statement"]["simulation"] = true.into(); + envelope["signature_b64"] = "A".repeat(86).into(); + assert!(!verify( + report, + &serde_json::to_vec(&envelope).expect("altered signature") + )); +} diff --git a/qualification/README.md b/qualification/README.md index d3adbf80a..911a91410 100644 --- a/qualification/README.md +++ b/qualification/README.md @@ -41,7 +41,9 @@ manifest contract requires exactly one digest-bound projection. The owner assigned the agent an independent operator simulation, including the first signing ceremony and both provider harnesses. `simulation/run.py` performs that work with fresh in-memory signing keys, explicit placeholder trust-machine -records and measured provider-driver reports. It imports signed fixtures under +records and measured provider-driver reports. Detached simulation signatures +bind the measured report bytes and are verified after publication. Their keys +are explicitly self-signed and have no protected-run authority. It imports signed fixtures under required test trust and measures real engine credential-store calls. No private keys or production trust inputs are written. This work does not wait for a human ceremony or real provider credentials. diff --git a/qualification/simulation/README.md b/qualification/simulation/README.md index 167b6abac..9f3832ace 100644 --- a/qualification/simulation/README.md +++ b/qualification/simulation/README.md @@ -15,6 +15,11 @@ recipes and drive the native submission driver over durable file claims and mutable counting providers. Independent vertical wire oracles check the actual method, URL, headers, body and idempotency commitment before each write. Reports measure credential leases, write entries and fresh read-back confirmations. +Each measured report has a detached Ed25519 simulation attestation from a fresh +in-memory key. A separate native stage re-reads the published files and verifies +their signatures and report digests. Changed bytes or simulation scope refuse. +These self-signed reports have no production or protected-run signing authority; +the disposable root ceremony below exercises that separate trust machinery. They exercise exact writes, original/fresh proof replay, reopening the store, lost responses, and crashes before the response record is durable. diff --git a/qualification/simulation/run.py b/qualification/simulation/run.py index 11527f1cb..f5bfa628b 100644 --- a/qualification/simulation/run.py +++ b/qualification/simulation/run.py @@ -17,6 +17,7 @@ "stripe-refund-v1.json", "airtable-record-update-v1.json", "bootstrap/simulation.json", + "provider-signature-verification.json", ) @@ -65,6 +66,7 @@ def main() -> None: parser.error("candidate harness digest mismatch") source_dirty = False command = [str(harness), "qualification_simulation", "--nocapture"] + verification = [str(harness), "qualification_tests::verify_simulation_reports", "--exact", "--nocapture"] working_directory = output else: source_commit = subprocess.check_output( @@ -76,6 +78,8 @@ def main() -> None: harness_sha256 = None command = [args.cargo, "test", "--locked", "-p", "auths-gateway", "--features", "loopback-provider", "--lib", "qualification_simulation", "--", "--nocapture"] + verification = command[:command.index("qualification_simulation")] + [ + "qualification_tests::verify_simulation_reports", "--", "--exact", "--nocapture"] working_directory = repository # Provider and signing credentials are not needed and do not reach tests. environment = { @@ -85,12 +89,13 @@ def main() -> None: environment["AUTHS_QUALIFICATION_SIMULATION_OUTPUT"] = str(output) started = time.monotonic() with tempfile.TemporaryFile() as log: - result = subprocess.run(command, cwd=working_directory, env=environment, stdout=log, stderr=subprocess.STDOUT, - timeout=1800, check=False) - if result.returncode: - log.seek(0, os.SEEK_END) - log.seek(max(0, log.tell() - 8192)) - raise SystemExit(log.read().decode("utf-8", errors="replace")) + for stage in (command, verification): + result = subprocess.run(stage, cwd=working_directory, env=environment, stdout=log, stderr=subprocess.STDOUT, + timeout=1800, check=False) + if result.returncode: + log.seek(0, os.SEEK_END) + log.seek(max(0, log.tell() - 8192)) + raise SystemExit(log.read().decode("utf-8", errors="replace")) summaries = [] for name in REPORTS: path = output / name @@ -106,6 +111,13 @@ def main() -> None: record = json.loads(path.read_bytes()) if record["excluded_claims"] != ["everything: this record stands for no run"]: raise SystemExit("bootstrap fixture scope changed") + # The second native stage re-reads and cryptographically verifies these + # exact files after both family runs complete. They are detached simulation + # signatures, with no production root or protected-run authority. + for family in ("stripe-refund-v1", "airtable-record-update-v1"): + signature = output / f"{family}.attestation.json" + if signature.is_symlink() or signature.stat().st_size > 4096: + raise SystemExit("invalid simulation signature") public_members = [] for path in sorted(output.rglob("*.json")): if path.is_symlink() or path.stat().st_size > 1_048_576: @@ -122,6 +134,7 @@ def main() -> None: "families": [summary.get("family") for summary in summaries[:2]], "provider_case_count": sum(len(summary["cases"]) for summary in summaries[:2]), "public_artifacts": public_members, + "provider_reports": "detached simulation signatures verified from published bytes", "keys": "generated in memory and zeroized; no private key files", "excluded_claims": ["protected live evidence", "production qualification", "human acceptance"], } From 2d2ad457c66e682f877e35e811f5b093e55842fa Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 01:05:20 +0100 Subject: [PATCH 044/108] Prepare Python SDK 0.0.1rc1 and GitHub wheel release metadata --- bindings/python-adapters/sqlite/pyproject.toml | 2 +- bindings/python/pyproject.toml | 2 +- bindings/python/python/auths/_doctor.py | 2 +- bindings/python/sdk-runtime-contract.json | 2 +- bindings/python/tools/check_wheel.py | 2 +- bindings/python/uv.lock | 2 +- release/CANDIDATE_CLOSURE.md | 4 ++-- release/RELEASE_CANDIDATE_NOTES.md | 3 ++- release/public-naming.toml | 2 +- release/release-subjects.toml | 2 +- release/semantic-freeze-versions.toml | 6 +++--- release/semantic-freeze.json | 10 +++++----- 12 files changed, 20 insertions(+), 19 deletions(-) diff --git a/bindings/python-adapters/sqlite/pyproject.toml b/bindings/python-adapters/sqlite/pyproject.toml index 0b9f1dd0d..1a34f7a92 100644 --- a/bindings/python-adapters/sqlite/pyproject.toml +++ b/bindings/python-adapters/sqlite/pyproject.toml @@ -7,7 +7,7 @@ name = "auths-sqlite" version = "1.0.0rc1" description = "SQLite runtime-store adapter for Auths Python" requires-python = ">=3.9" -dependencies = ["auths==1.0.0rc1"] +dependencies = ["auths==0.0.1rc1"] license = "MIT OR Apache-2.0" classifiers = [ "Programming Language :: Python :: 3", diff --git a/bindings/python/pyproject.toml b/bindings/python/pyproject.toml index 198ba8c93..370400b6d 100644 --- a/bindings/python/pyproject.toml +++ b/bindings/python/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "maturin" [project] name = "auths" -version = "1.0.0rc1" +version = "0.0.1rc1" description = "Prove exact authority, execute protected actions, and leave signed receipts" readme = "README.md" requires-python = ">=3.9" diff --git a/bindings/python/python/auths/_doctor.py b/bindings/python/python/auths/_doctor.py index 29265972f..644222252 100644 --- a/bindings/python/python/auths/_doctor.py +++ b/bindings/python/python/auths/_doctor.py @@ -31,7 +31,7 @@ def doctor( abi = _native.native_abi_version() compatible = abi == 2 return DoctorReport( - sdk_version="1.0.0rc1", + sdk_version="0.0.1rc1", runtime=( f"CPython {sys.version_info.major}.{sys.version_info.minor} / " f"{_bounded(platform.system())} {_bounded(platform.machine())}" diff --git a/bindings/python/sdk-runtime-contract.json b/bindings/python/sdk-runtime-contract.json index 15fff2c00..c95febe4f 100644 --- a/bindings/python/sdk-runtime-contract.json +++ b/bindings/python/sdk-runtime-contract.json @@ -2,7 +2,7 @@ "schema": "auths.python-runtime-contract/1", "package": { "name": "auths", - "version": "1.0.0rc1", + "version": "0.0.1rc1", "nativeAbi": 2, "wheelAbi": "abi3-py39" }, diff --git a/bindings/python/tools/check_wheel.py b/bindings/python/tools/check_wheel.py index 56b9e8707..1bc2e86a6 100644 --- a/bindings/python/tools/check_wheel.py +++ b/bindings/python/tools/check_wheel.py @@ -172,7 +172,7 @@ def main() -> None: metadata = archive.read(metadata_names[0]).decode("utf-8") required = ( "Name: auths\n", - "Version: 1.0.0rc1\n", + "Version: 0.0.1rc1\n", "Requires-Python: >=3.9\n", "Classifier: Operating System :: Microsoft :: Windows\n", "Classifier: Operating System :: MacOS\n", diff --git a/bindings/python/uv.lock b/bindings/python/uv.lock index cc2350159..ffd2e668c 100644 --- a/bindings/python/uv.lock +++ b/bindings/python/uv.lock @@ -4,5 +4,5 @@ requires-python = ">=3.9" [[package]] name = "auths" -version = "1.0.0rc1" +version = "0.0.1rc1" source = { editable = "." } diff --git a/release/CANDIDATE_CLOSURE.md b/release/CANDIDATE_CLOSURE.md index 815ed0c57..f98d956c5 100644 --- a/release/CANDIDATE_CLOSURE.md +++ b/release/CANDIDATE_CLOSURE.md @@ -19,8 +19,8 @@ behavior remain unchanged and domain-owned. - Rust workspace and maintained crates: `1.0.0-rc.1`. - TypeScript distribution `@auths-dev/sdk`: `1.0.0-rc.1`. -- Python distribution `auths`: `1.0.0rc1`, the PEP 440 spelling equivalent to - the SemVer RC. +- Python distribution `auths`: `0.0.1rc1`, the PEP 440 spelling of the owner-requested + Python SDK coordinate `0.0.1-rc1`. - Candidate tag contract: `auths-v1.0.0-rc.1`. - Release public-surface semantic identity: version 15. - Semantic-freeze inventory: version 15. diff --git a/release/RELEASE_CANDIDATE_NOTES.md b/release/RELEASE_CANDIDATE_NOTES.md index a942c9a71..6a55465ab 100644 --- a/release/RELEASE_CANDIDATE_NOTES.md +++ b/release/RELEASE_CANDIDATE_NOTES.md @@ -9,7 +9,8 @@ The candidate includes: - the `auths` and `auths-sdk` Rust roots and their frozen publishable dependency closure; - the `@auths-dev/sdk` TypeScript package; -- the `auths` Python distribution; +- the `auths` Python distribution at `0.0.1rc1` (`0.0.1-rc1`), supplied as a + GitHub prerelease wheel for installation without a local compiler; - the bounded WebAssembly module contained by the TypeScript package; - deterministic source and assurance archives; and - digest-bound SPDX, provenance, formal, conformance, compatibility, and diff --git a/release/public-naming.toml b/release/public-naming.toml index 535f695ad..c2c87247f 100644 --- a/release/public-naming.toml +++ b/release/public-naming.toml @@ -211,7 +211,7 @@ kind = "cargo" current = "unpublished workspace components" target = "auths-identity, auths-identity-raw-key, auths-signature-ed25519, auths-identity-authority, auths-byte-channel, auths-byte-channel-memory, auths-iroh" state = "publish-neutral-ports-and-reference-adapters" -compatibility = "The 1.0.0-rc.1 coordinates expose identity and transport independently. Reference adapters and the authority bridge remain optional; all packages are versioned in the release order and semantic freeze." +compatibility = "The Rust and TypeScript 1.0.0-rc.1 and Python 0.0.1rc1 coordinates expose identity and transport independently. Reference adapters and the authority bridge remain optional; all packages are versioned in the release order and semantic freeze." owner_pr = "ISSUE-98-SPEC-11" [[surfaces]] diff --git a/release/release-subjects.toml b/release/release-subjects.toml index bfa262770..b451b1fda 100644 --- a/release/release-subjects.toml +++ b/release/release-subjects.toml @@ -40,7 +40,7 @@ coordinate = "auths" media_type = "application/vnd.python.wheel" reproducibility = "platform-reproducible" producer = "maturin build" -publication = "PyPI only after exact-manifest authorization" +publication = "GitHub prerelease assets after exact-manifest authorization; PyPI publication is separately authorized" [[families]] id = "wasm-module" diff --git a/release/semantic-freeze-versions.toml b/release/semantic-freeze-versions.toml index 34c6fbb9d..6d353eb5a 100644 --- a/release/semantic-freeze-versions.toml +++ b/release/semantic-freeze-versions.toml @@ -1,4 +1,4 @@ -freeze_version = 370 +freeze_version = 371 # Semantic identity counters live outside the xtask source tree deliberately. # The formal source closure binds xtask's executable code, while the semantic @@ -47,7 +47,7 @@ freeze_version = 370 "auths.frozen-bytes/product/integrations/auths-stripe/fixtures/v1/manifest.sha256.json" = 1 "auths.identity.protocol" = 123 "auths.modular-components" = 20 -"auths.portable-abi-bindings" = 121 +"auths.portable-abi-bindings" = 122 "auths.product.bounded-domains" = 19 "auths.product.bounded-policy" = 6 "auths.product.configuration-commitments" = 1 @@ -67,4 +67,4 @@ freeze_version = 370 "auths.product.vocabulary" = 24 "auths.release.benchmark-contract" = 1 "auths.release.evolution-contract" = 79 -"auths.release.public-surface" = 370 +"auths.release.public-surface" = 371 diff --git a/release/semantic-freeze.json b/release/semantic-freeze.json index 59d4441ba..731847726 100644 --- a/release/semantic-freeze.json +++ b/release/semantic-freeze.json @@ -1,6 +1,6 @@ { "schema": "auths.semantic-freeze/1", - "freezeVersion": 370, + "freezeVersion": 371, "publicSurface": { "rustRoots": [ "auths", @@ -611,7 +611,7 @@ }, { "id": "auths.portable-abi-bindings", - "version": 121, + "version": 122, "classification": "frozen-meaning", "categories": [ "portable-abi", @@ -631,7 +631,7 @@ "core/crates/auths-model/src/lib.rs", "core/spec/v1/auths-proof.cddl" ], - "sha256": "e9f99815a6e7a86d35e88e050b9cfb8758f9b3b9dd6df7c3495eb04b7dab29a8" + "sha256": "45b4ff9be945f6ba91c34b5684770629133fbcb27da6b26eb14b4347114d4e40" }, { "id": "auths.product.bounded-domains", @@ -1011,7 +1011,7 @@ }, { "id": "auths.release.public-surface", - "version": 370, + "version": 371, "classification": "release-metadata", "categories": [ "package-names", @@ -1104,7 +1104,7 @@ "xtask/src/release_launch.rs", "xtask/src/semantic_freeze.rs" ], - "sha256": "6546b04c364ef8ba03022a369388bc15b90c2cd5afef4733216fa1fbd7561527" + "sha256": "8d51c87a5c638e13ad9dff87ef7f1db4479e681e4b4c395a647b212a88861c8c" } ] } From a4d70ba38eee823fac6af177b8ec63d55c7659a1 Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 01:21:57 +0100 Subject: [PATCH 045/108] Keep protected production-readiness probe out of intermediate issuance fixture --- .../auths-recipe-qualification-issuance/tests/common/mod.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/product/qualification/auths-recipe-qualification-issuance/tests/common/mod.rs b/product/qualification/auths-recipe-qualification-issuance/tests/common/mod.rs index 81a49a17e..59481e527 100644 --- a/product/qualification/auths-recipe-qualification-issuance/tests/common/mod.rs +++ b/product/qualification/auths-recipe-qualification-issuance/tests/common/mod.rs @@ -141,7 +141,9 @@ pub fn executable_corpus() -> auths_recipe_qualification_issuance::execution::Ru .into_iter() .filter(|scenario| harness_scenario(*scenario)) { - if scenario == Scenario::ObserverRotation { + // This fixture exercises intermediate issuance. Production readiness + // requires an actual protected doctor report, not this subprocess double. + if matches!(scenario, Scenario::ObserverRotation | Scenario::ProductionReadiness) { continue; } let mut steps = match scenario { From 43f59bd962e95fe39eec0b681e739fbec9c1344e Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 01:51:30 +0100 Subject: [PATCH 046/108] Format intermediate issuance scenario filter --- .../auths-recipe-qualification-issuance/tests/common/mod.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/product/qualification/auths-recipe-qualification-issuance/tests/common/mod.rs b/product/qualification/auths-recipe-qualification-issuance/tests/common/mod.rs index 59481e527..a5596601b 100644 --- a/product/qualification/auths-recipe-qualification-issuance/tests/common/mod.rs +++ b/product/qualification/auths-recipe-qualification-issuance/tests/common/mod.rs @@ -143,7 +143,10 @@ pub fn executable_corpus() -> auths_recipe_qualification_issuance::execution::Ru { // This fixture exercises intermediate issuance. Production readiness // requires an actual protected doctor report, not this subprocess double. - if matches!(scenario, Scenario::ObserverRotation | Scenario::ProductionReadiness) { + if matches!( + scenario, + Scenario::ObserverRotation | Scenario::ProductionReadiness + ) { continue; } let mut steps = match scenario { From 8b6f96e7e43dacf5b7f237cfc015f84a513a2bd1 Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 01:56:56 +0100 Subject: [PATCH 047/108] Rehearse real Airtable from installed SDK with isolated custody and signed evidence --- docs/PROGRAM_BOARD.md | 14 + ...gateway-polish-and-recipe-qualification.md | 31 ++ .../src/simulation_attestation.rs | 14 + qualification/README.md | 4 +- .../airtable-live-2026-10-07/attestation.json | 12 + .../airtable-live-2026-10-07/report.json | 124 ++++++ .../support-bundle.json | 1 + qualification/simulation/live/Dockerfile | 4 + qualification/simulation/live/README.md | 56 +++ qualification/simulation/live/airtable.py | 359 ++++++++++++++++++ 10 files changed, 618 insertions(+), 1 deletion(-) create mode 100644 qualification/simulation/evidence/airtable-live-2026-10-07/attestation.json create mode 100644 qualification/simulation/evidence/airtable-live-2026-10-07/report.json create mode 100644 qualification/simulation/evidence/airtable-live-2026-10-07/support-bundle.json create mode 100644 qualification/simulation/live/Dockerfile create mode 100644 qualification/simulation/live/README.md create mode 100644 qualification/simulation/live/airtable.py diff --git a/docs/PROGRAM_BOARD.md b/docs/PROGRAM_BOARD.md index e4d4f0dfd..3509811d1 100644 --- a/docs/PROGRAM_BOARD.md +++ b/docs/PROGRAM_BOARD.md @@ -454,3 +454,17 @@ and readiness remain unchanged; real users remain the owner's offline work. The local expanded rehearsal passed 36 provider cases and the two-family ceremony. Hosted kit verification is pending; the kit is designed to run in Docker with no checkout or network mounted. + +On 2026-10-07 the agent used the existing `.env` credentials and completed a +real Airtable operator rehearsal through downloaded gateway commit `20837b56` +and the installed Linux Python SDK `0.0.1rc1`. It passed fresh value/echo +read-back, two-process submission, replay/altered-action/restart refusals, +application credential isolation, support-bundle scanning, record cleanup and +verification of the exact report's detached simulation signature. Evidence is +retained in `qualification/simulation/evidence/airtable-live-2026-10-07/`. +Docker Desktop host sharing initially defeated the file-owner access check; +the runner now receives the credential through operator-only stdin and stages +it privately inside the container. The Stripe keys work, but creating a +distinct test connected account is refused because Connect is not enabled. +These are development live observations, not protected production +qualifications; no production trust or stable-readiness claim has changed. diff --git a/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md b/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md index 73a45cdea..c3eb27de6 100644 --- a/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md +++ b/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md @@ -1699,3 +1699,34 @@ lease gate. Dynamically created provider identifiers need reviewed oracle/corpus binding before execution, not expected digests copied from candidate output. Those real-production prerequisites do not block the owner-directed simulation. No protected live evidence or production qualification is claimed. + +### 22.1 Live independent-operator rehearsal (2026-10-07) + +The agent located and used the existing sandbox credentials without publishing +them. `qualification/simulation/live/airtable.py` passed against real Airtable +with the downloaded gateway package at `20837b56` and the installed Linux +Python SDK `0.0.1rc1`. It fixed a dedicated table in the recipe before review, +created a disposable record, used two independent gateway processes with a +shared durable file store, and obtained one provider-observed submission and +one replay refusal. Fresh independent read-back matched value and echo. +Original-proof replay, altered action and replay after process restart were +refused. The application UID could read neither the provider credential nor +gateway state; the actual support bundle passed secret scanning. Cleanup +deleted the created record. The exact published report has a verified detached +simulation signature and is retained with the support bundle under +`qualification/simulation/evidence/airtable-live-2026-10-07/`. + +The first isolation check caught Docker Desktop host sharing presenting the +credential file as owned by the application caller. The corrected runner +receives dotenv input only through operator stdin, stages it in a root-owned +private directory on the container filesystem and repeats the access check. +It mounts no provider credential or source checkout. Failed journeys also +delete their disposable records. + +The Stripe test keys authenticate, but the platform lists no connected +accounts and refuses creating one with HTTP 400 because Connect is not enabled. +This is a real failed setup, not distinct-account qualification evidence. +The Airtable token reaches the existing base; its restriction to one base has +not been established. These reports exclude protected production qualification, +production PostgreSQL/AWS custody, complete-corpus coverage and independently +witnessed lease/provider-entry counts. Stable readiness remains false. diff --git a/product/runtime/auths-gateway/src/simulation_attestation.rs b/product/runtime/auths-gateway/src/simulation_attestation.rs index fc98572b8..a1b59e934 100644 --- a/product/runtime/auths-gateway/src/simulation_attestation.rs +++ b/product/runtime/auths-gateway/src/simulation_attestation.rs @@ -118,3 +118,17 @@ fn altered_reports_and_scope_are_refused() { &serde_json::to_vec(&envelope).expect("altered signature") )); } + +#[test] +fn installed_python_live_report_verifies_under_the_native_signature_contract() { + let report = include_bytes!( + "../../../../qualification/simulation/evidence/airtable-live-2026-10-07/report.json" + ); + let attestation = include_bytes!( + "../../../../qualification/simulation/evidence/airtable-live-2026-10-07/attestation.json" + ); + assert!(verify(report, attestation)); + let mut altered = report.to_vec(); + altered.push(b' '); + assert!(!verify(&altered, attestation)); +} diff --git a/qualification/README.md b/qualification/README.md index 911a91410..ea5a5fa24 100644 --- a/qualification/README.md +++ b/qualification/README.md @@ -12,7 +12,9 @@ without external credentials and publish explicitly simulated evidence. Proposed are [ADR 0014](../docs/adr/0014-stripe-refund-recipe-qualification.md) and [ADR 0015](../docs/adr/0015-airtable-record-update-recipe-qualification.md). They explicitly remain proposed until their executable corpora and protected -evidence exist. +evidence exist. A separate [live operator rehearsal](simulation/live/README.md) +has now passed against Airtable using downloaded gateway/SDK artifacts, +disposable records and development custody; it does not qualify a production tuple. `cargo xtask release-check` generates `target/release-evidence/launch-readiness.json`. Its `stable_launch_ready` value comes from the gateway build's pinned public diff --git a/qualification/simulation/evidence/airtable-live-2026-10-07/attestation.json b/qualification/simulation/evidence/airtable-live-2026-10-07/attestation.json new file mode 100644 index 000000000..805262f2e --- /dev/null +++ b/qualification/simulation/evidence/airtable-live-2026-10-07/attestation.json @@ -0,0 +1,12 @@ +{ + "statement": { + "schema": "auths.provider-simulation-attestation/1", + "simulation": true, + "stable_launch_ready": false, + "signer_kind": "disposable-self-signed-simulation-key", + "family": "airtable-record-update-v1", + "report_sha256": "a12ce66e95a1be381d7192829703511462ee096fa3a8f4de7ba687603ad1bc16", + "public_key_b64": "E/fZPLxpY+38f21PI7ltrRGy13lb74+yOMQVnw1c9PE" + }, + "signature_b64": "OFQBeMCUhz/NZvYAyqH6K2r8tKw8msPotqzvy6ENbdiVg/Cglak07DpgrgLN/2hweL4kRQJdXHj0w6CNkSdtAQ" +} \ No newline at end of file diff --git a/qualification/simulation/evidence/airtable-live-2026-10-07/report.json b/qualification/simulation/evidence/airtable-live-2026-10-07/report.json new file mode 100644 index 000000000..217bd9acd --- /dev/null +++ b/qualification/simulation/evidence/airtable-live-2026-10-07/report.json @@ -0,0 +1,124 @@ +{ + "schema": "auths.recipe-qualification-simulation/1", + "simulation": true, + "stable_launch_ready": false, + "family": "airtable-record-update-v1", + "provider": "live Airtable Web API v0", + "verification_boundary": "installed SDK and native application socket", + "source_commit": "20837b56a61945d79dedf48a1ff237411dd01185", + "gateway_sha256": "85d6fd1c8b44fa5a7a34d4a012a39d3edf00dc867710c149b7d3da2bc6d2230e", + "compiled_recipe_sha256": "2b95034013998915950fd0f6ec0141bfcc7ca2e731f8e117fd8a5fd7670d5ea5", + "sdk_location": "/opt/consumer/lib/python3.12/site-packages/auths/__init__.py", + "sdk_version": "0.0.1rc1", + "wheel_sha256": "6d079aa4960256a754315d911b55d80bc02848b1ad14225420ea8eae4905656f", + "store": "shared-file-v1", + "custody": "local-file-v1", + "clock": "development-host-clock", + "resources": { + "base": "appQD3Qf0YFBCW9bV", + "table": "tblBx2jwe0IsPYRKT", + "record": "recgLJ1LFbmBY2iZP" + }, + "results": { + "race": [ + { + "evidence": { + "channel": "read-back", + "echo": "auths-e1-5bc7f10da8a385afc4330f72c3a448459e75f96cf791631aa6a354000a7f94d6", + "evidence_digest": "487a67efdee7633443cf483375befbc11fe985461d899cd46e9947de57645769", + "observed_at": 1791334499 + }, + "outcome": "observed-by-provider", + "status": 200 + }, + { + "code": "gateway.attempt.replay", + "outcome": "not-entered" + } + ], + "proof_replay": { + "code": "gateway.attempt.replay", + "outcome": "not-entered" + }, + "altered_action": { + "code": "malformed-proof", + "outcome": "denied" + }, + "restart_replay": { + "code": "gateway.attempt.replay", + "outcome": "not-entered" + }, + "fresh_read_back": { + "replacement_matches": true, + "echo_matches": true + } + }, + "cases": [ + { + "case": "review", + "seconds": 0.156, + "exit_code": 0 + }, + { + "case": "installed-consumer-author", + "seconds": 0.431, + "exit_code": 0 + }, + { + "case": "install", + "seconds": 0.225, + "exit_code": 0 + }, + { + "case": "join", + "seconds": 0.204, + "exit_code": 0 + }, + { + "case": "application-secret-isolation", + "seconds": 0.343, + "exit_code": 0 + }, + { + "case": "two-instance-submit-1", + "seconds": 1.892, + "exit_code": 0 + }, + { + "case": "two-instance-submit-0", + "seconds": 4.446, + "exit_code": 0 + }, + { + "case": "proof-replay", + "seconds": 0.369, + "exit_code": 0 + }, + { + "case": "altered-action", + "seconds": 0.351, + "exit_code": 0 + }, + { + "case": "support-bundle", + "seconds": 0.249, + "exit_code": 0 + }, + { + "case": "restart-replay", + "seconds": 0.445, + "exit_code": 0 + } + ], + "excluded_claims": [ + "protected production qualification", + "production PostgreSQL/AWS custody", + "complete qualification corpus", + "independent provider-entry and lease counters", + "token restriction to one base" + ], + "cleanup": { + "created_record_deleted": true, + "table_retained_for_future_rehearsals": true + } +} \ No newline at end of file diff --git a/qualification/simulation/evidence/airtable-live-2026-10-07/support-bundle.json b/qualification/simulation/evidence/airtable-live-2026-10-07/support-bundle.json new file mode 100644 index 000000000..3b436878e --- /dev/null +++ b/qualification/simulation/evidence/airtable-live-2026-10-07/support-bundle.json @@ -0,0 +1 @@ +{"attempts":{"by_stage":{"observed-by-provider":1},"identifiers":[{"key_sha256":"3378da2c91a437798ccb21aabb428d8d67cfcefa3e2da6744708530badc17e47","stage":"observed-by-provider"}],"listed":1,"truncated":false},"build_sha256":"85d6fd1c8b44fa5a7a34d4a012a39d3edf00dc867710c149b7d3da2bc6d2230e","codes":["gateway.qualification.unavailable"],"connection":{"credential_generation":1,"credential_held":true,"generation":1,"in_flight":0,"state":"active"},"credential_store_kind":"local-file-v1","deployment":"development","gateway_package":"auths-gateway","gateway_version":"1.0.0-rc.1","profile_lock_sha256":"af7f984509ab11a3676cacc85eda2fa638c25bf91f7bfedf3ff3c119e47f3c41","qualification":{"code":"gateway.qualification.unavailable","policy":"optional","state":"unqualified"},"recipe_sha256":"2b95034013998915950fd0f6ec0141bfcc7ca2e731f8e117fd8a5fd7670d5ea5","schema":"auths.gateway-support-bundle/1","semantic_closure_sha256":"11a256092b821eec54d27e3ad25cc05f7955da236ea23853cced71c32215764d","trusted_context_sha256":"1545ed2de0eca13e77038015fa9dd5982f2748473c31ebad40d462cacd3fd4be"} diff --git a/qualification/simulation/live/Dockerfile b/qualification/simulation/live/Dockerfile new file mode 100644 index 000000000..3e6fad3b7 --- /dev/null +++ b/qualification/simulation/live/Dockerfile @@ -0,0 +1,4 @@ +FROM ubuntu:24.04 +RUN DEBIAN_FRONTEND=noninteractive apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends python3 python3-venv ca-certificates \ + && rm -rf /var/lib/apt/lists/* \ + && python3 -m venv /opt/consumer diff --git a/qualification/simulation/live/README.md b/qualification/simulation/live/README.md new file mode 100644 index 000000000..2d4971a48 --- /dev/null +++ b/qualification/simulation/live/README.md @@ -0,0 +1,56 @@ +# Live operator rehearsal + +`airtable.py` exercises a downloaded gateway operator package and an installed +Python wheel against a dedicated Airtable table. It fixes the base/table in the +recipe before review, creates a disposable record, authors proof/action with +native SDK primitives and the gateway's reviewed verifier configuration, and +runs two separate gateway processes against their shared durable file store. +The application UID receives no provider credential and cannot read the token +file or gateway state. The run checks live read-back/value/echo, proof replay, +altered action, process restart, and the real redacted support bundle. Cleanup +deletes the record even after a failed journey. The dedicated empty table is +retained for later rehearsals. + +The report and detached signature use the existing simulation schema and +Ed25519 signature domain. The installed SDK generates a fresh in-memory key, +signs the actual report bytes and re-reads/verifies their published digest and +signature. This signer has no protected release authority. Live provider state +is evidence; the report makes no production qualification, PostgreSQL/AWS, +complete-corpus, token-scope or independently measured lease/entry-counter claim. + +Run inside the maintained Docker image after installing the candidate wheel +with `/opt/consumer/bin/pip install --no-deps /wheel/.whl`. Mount only +the extracted package, public Airtable recipe/profile lock, this script and an +empty report directory. Supply the operator credential through Docker stdin. +Do not mount a source checkout or give a credential environment variable to the application. + +```text +/opt/consumer/bin/python /harness/airtable.py \ + --package /candidate/auths-gateway-operator \ + --inputs /inputs --wheel /wheel/.whl --credential-stdin \ + --base --table \ + --commit --out /reports/run +``` + +The stdin input holds `PERSONAL_ACCESS_TOKEN` in dotenv format. The operator +stages it in a root-owned private directory on the container filesystem, then +sends the token to gateway installation through stdin. Do not mount a credential +file: Docker Desktop's host sharing may make its owner match each caller and +can defeat the expected Unix access check. The application isolation check +must fail to read the staged credential and both gateway state directories. +Child output is bounded and secret-scanned before publication; +provider error response bodies never reach public logs. + +Stripe's distinct-account rehearsal additionally requires Connect enabled on +the test platform. A 400 refusal creating a connected account is a failed setup, +not evidence of account-scope qualification. Do not substitute the platform +account and declare that requirement satisfied. + +The first successful live rehearsal is preserved in +[`../evidence/airtable-live-2026-10-07/`](../evidence/airtable-live-2026-10-07/). +It used gateway commit `20837b56` and the downloaded `0.0.1rc1` Linux wheel. +The two-process submission returned one provider-observed outcome and one +`gateway.attempt.replay`; the original proof and the same proof after process +restart were refused. Altered action bytes were denied as `malformed-proof`. +An independent fresh GET matched both the approved replacement and the gateway +result's echo. The created record was deleted before the report was signed. diff --git a/qualification/simulation/live/airtable.py b/qualification/simulation/live/airtable.py new file mode 100644 index 000000000..5e737ee0c --- /dev/null +++ b/qualification/simulation/live/airtable.py @@ -0,0 +1,359 @@ +#!/usr/bin/env python3 +"""Source-free live-provider rehearsal with an isolated installed SDK consumer. + +This is development evidence, not a protected production qualification. +The operator reads the PAT; the application receives only proof and action. +""" +import argparse +import asyncio +import concurrent.futures +import base64 +from dataclasses import asdict +import hashlib +import importlib.metadata +import json +import os +from pathlib import Path +import re +import selectors +import signal +import subprocess +import sys +import tempfile +import time +import urllib.error +import urllib.request +import uuid + + +class Refusal(Exception): + pass + + +def require(value, code): + if not value: + raise Refusal(code) + + +def canonical(value): + # The signature statement contains only ASCII strings and booleans. + return json.dumps(value, sort_keys=True, separators=(',', ':'), ensure_ascii=False).encode() + + +def author_packet(native, arguments, configuration): + """Author disposable trust using native primitives and the reviewed gateway pin.""" + current = int(time.time()) + audience = 'mcp://airtable-gateway-demo' + resource = audience + '/tools/set_demo_status_v1' + key = native.DevelopmentEd25519Key.generate() + actor = native.Principal(key.principal) + request = native.GrantRequest(actor, 'auths.mcp', 2, [('tools/call', resource)], + current - 60, current + 600, [audience], None, None, 0, None, 'raw-key-baseline', []) + grant_unsigned = native.root_grant(actor, request) + signing = native.prepare_signing(grant_unsigned, key.principal_method, key.verification_method, key.suite) + grant = signing.complete(key.sign(signing.signing_preimage)) + challenge = native.generate_challenge_v1() + call = native.mcp_call('airtable-gateway-demo', 'set_demo_status_v1', canonical(arguments)) + prepared = native.prepare_mcp_call_action(call, actor, grant, challenge, current, 30) + signing = native.prepare_signing(prepared.unsigned, key.principal_method, key.verification_method, key.suite) + action = signing.complete(key.sign(signing.signing_preimage)) + assurance = native.AssurancePolicy('raw-key-baseline', [ + ('root', 'every', 'self-certifying-identifier', None), + ('actor', 'every', 'self-certifying-identifier', None), + ('actor', 'every', 'offline-verifiable', None)]) + anchor = native.TrustAnchor(actor.value, actor, [key.principal_method], [('auths.mcp', 2)], + [('tools/call', resource)], [audience], [audience], current - 60, current + 600, + None, 1, 'raw-key-baseline', None) + template = native.compile_trusted_context(configuration, None, 1, 1, 1, [anchor], assurance, + None, None, 'none-v1', [key.evidence_type], []) + context = template.bind_request(audience, challenge, current) + evidence = (key.evidence_type, key.media_type, key.evidence) + return native.assemble_mcp_proof(prepared, action, [grant], [[evidence]], [evidence], context) + + +def consumer(verb, work, socket): + from auths import _native + from auths.gateway import GatewayClient, GatewayEndpoint + require('PERSONAL_ACCESS_TOKEN' not in os.environ and 'PYTHONPATH' not in os.environ, + 'live.consumer-environment') + if verb == 'author': + args = json.loads((work / 'arguments.json').read_text()) + packet = author_packet(_native, args, bytes.fromhex((work / 'configuration').read_text())) + for name, data in zip(['proof.cbor', 'action.cbor', 'context.cbor'], packet): + (work / name).write_bytes(data) + print(json.dumps({'sdk_location': __import__('auths').__file__, 'sdk_version': importlib.metadata.version('auths')})) + elif verb == 'isolation': + for label, path in [('credential', '/run/provider-secret/provider.env'), ('first-state', '/run/operator/first'), ('second-state', '/run/operator/second')]: + try: + Path(path).read_bytes() if path.endswith('.env') else list(Path(path).iterdir()) + except PermissionError: + continue + raise Refusal('live.application-can-read-' + label) + print('{"isolated":true}') + elif verb == 'sign': + report = (work / 'airtable-record-update-v1.json').read_bytes() + key = _native.DevelopmentEd25519Key.generate() + enc = lambda data: base64.b64encode(data).rstrip(b'=').decode() + statement = {'schema': 'auths.provider-simulation-attestation/1', 'simulation': True, + 'stable_launch_ready': False, 'signer_kind': 'disposable-self-signed-simulation-key', + 'family': 'airtable-record-update-v1', 'report_sha256': hashlib.sha256(report).hexdigest(), + 'public_key_b64': enc(bytes(key.public_key))} + preimage = b'auths.provider-simulation-attestation/1\0' + canonical(statement) + signature = bytes(key.sign(preimage)) + _native.verify_ed25519_preimage_v1(bytes(key.public_key), preimage, signature) + path = work / 'airtable-record-update-v1.attestation.json' + path.write_bytes(json.dumps({'statement': statement, 'signature_b64': enc(signature)}, indent=2).encode()) + # Re-read published bytes and verify the exact digest and signature. + published = json.loads(path.read_bytes()) + require(published['statement']['report_sha256'] == hashlib.sha256((work / 'airtable-record-update-v1.json').read_bytes()).hexdigest(), + 'live.signature-report-mismatch') + _native.verify_ed25519_preimage_v1(base64.b64decode(published['statement']['public_key_b64'] + '=='), + b'auths.provider-simulation-attestation/1\0' + canonical(published['statement']), + base64.b64decode(published['signature_b64'] + '==')) + print('{"persisted_signature_verified":true}') + else: + action = (work / 'action.cbor').read_bytes() + if verb == 'altered': + action += b'\0' + result = asyncio.run(GatewayClient(GatewayEndpoint(socket)).submit( + proof=(work / 'proof.cbor').read_bytes(), action=action)) + print(json.dumps(asdict(result), sort_keys=True)) + + +class Operator: + uid, gid, app_uid = 62001, 62000, 62002 + + def __init__(self, args): + self.args, self.processes, self.steps = args, [], [] + self.binary = args.package / 'bin/auths-gateway' + self.python = Path('/opt/consumer/bin/python') + self.work, self.app = Path('/run/operator'), Path('/run/app') + self.record = None + self.token = None + self.env = {'PATH': '/usr/bin:/bin', 'PYTHONNOUSERSITE': '1'} + + def scan(self, data): + if self.token: + token = self.token.encode() + require(not any(v in data for v in [token, token.hex().encode(), base64.b64encode(token), + base64.urlsafe_b64encode(token)]), 'live.secret-exposure') + + def run(self, label, argv, stdin=b'', uid=None, allowed=(0,)): + start = time.monotonic() + result = subprocess.run(list(map(str, argv)), input=stdin, capture_output=True, timeout=60, + env=self.env, cwd='/run', user=self.uid if uid is None else uid, group=self.gid, extra_groups=[]) + self.scan(result.stdout + result.stderr) + require(len(result.stdout) + len(result.stderr) < 1048576, 'live.output-bound') + if result.returncode not in allowed: + codes = re.findall(rb'live\.[a-z0-9-]+', result.stderr) + raise Refusal('live.command-refused:' + label + (':' + codes[-1].decode() if codes else '')) + self.steps.append({'case': label, 'seconds': round(time.monotonic() - start, 3), + 'exit_code': result.returncode}) + return result.stdout + + def child(self, verb, socket=None): + return [self.python, Path(__file__).resolve(), '--consumer', verb, + '--consumer-work', self.app, '--consumer-socket', socket or '/run/sockets/first.sock'] + + def api(self, method, suffix, body=None): + require(suffix.startswith('/v0/'), 'live.invalid-api-path') + data = None if body is None else canonical(body) + request = urllib.request.Request('https://api.airtable.com' + suffix, data=data, method=method, + headers={'Authorization': 'Bearer ' + self.token, 'Content-Type': 'application/json'}) + try: + with urllib.request.urlopen(request, timeout=25) as response: + payload = response.read(65537) + require(len(payload) <= 65536, 'live.provider-response-bound') + return json.loads(payload) + except urllib.error.HTTPError as error: + raise Refusal('live.airtable-http-' + str(error.code)) from None + + def install(self, state, digest, join=False): + argv = [self.binary, 'install', '--state-dir', state, '--recipe', self.work / 'recipe.json', + '--profile-lock', self.work / 'profile.lock.json', '--trusted-context', self.app / 'context.cbor', + '--approve-digest', digest, '--provider', 'airtable', '--alias', 'live-rehearsal', + '--attempt-store', self.work / 'store', '--credential-stdin'] + argv += ['--join'] if join else ['--account-label', self.args.base] + self.run('join' if join else 'install', argv, stdin=(self.token + '\n').encode()) + + def start(self, name): + sock = Path('/run/sockets') / (name + '.sock') + log = tempfile.TemporaryFile() + process = subprocess.Popen([str(self.binary), 'serve', '--state-dir', str(self.work / name), + '--app-socket', str(sock)], stdout=subprocess.PIPE, stderr=log, env=self.env, cwd='/run', + user=self.uid, group=self.gid, extra_groups=[]) + self.processes.append((process, log)) + with selectors.DefaultSelector() as selector: + selector.register(process.stdout, selectors.EVENT_READ) + require(bool(selector.select(15)), 'live.gateway-start-timeout') + ready = process.stdout.readline(65537) + self.scan(ready) + require(ready.startswith(b'app socket ready'), 'live.gateway-start-refused') + return sock + + def stop(self): + for process, log in self.processes: + process.send_signal(signal.SIGTERM) + try: + process.wait(timeout=30) + except subprocess.TimeoutExpired: + process.kill() + process.wait() + raise Refusal('live.gateway-stop-timeout') + log.seek(0) + self.scan(log.read(1048577)) + require(process.returncode == 0, 'live.gateway-stop-refused') + log.close() + process.stdout.close() + self.processes.clear() + + def exercise(self): + require(os.getuid() == 0, 'live.requires-container-root') + require(not self.args.out.exists(), 'live.output-must-be-new') + self.args.out.mkdir(parents=True) + manifest = json.loads((self.args.package / 'manifest.json').read_text()) + require(manifest['source_commit'] == self.args.commit, 'live.candidate-commit-mismatch') + for entry in manifest['files']: + path = self.args.package / entry['path'] + require(not path.is_symlink() and hashlib.sha256(path.read_bytes()).hexdigest() == entry['sha256'], + 'live.package-hash-mismatch') + require(re.fullmatch(r'app[A-Za-z0-9]{14}', self.args.base) and re.fullmatch(r'tbl[A-Za-z0-9]{14}', self.args.table), + 'live.invalid-resource') + require(self.args.credential_stdin and not sys.stdin.isatty(), 'live.credential-stdin-required') + credential = sys.stdin.buffer.read(8193) + require(len(credential) <= 8192, 'live.credential-input-bound') + private = Path('/run/provider-secret') + private.mkdir(mode=0o700) + descriptor = os.open(private / 'provider.env', os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o600) + with os.fdopen(descriptor, 'wb') as output: + output.write(credential) + for line in credential.decode().splitlines(): + match = re.fullmatch(r'\s*PERSONAL_ACCESS_TOKEN\s*=\s*(.*?)\s*', line) + if match: + self.token = match[1].strip('"\'') + require(self.token and self.token.startswith('pat'), 'live.missing-pat') + for path, uid, mode in [(self.work, self.uid, 0o700), (self.app, self.app_uid, 0o750), + (Path('/run/sockets'), self.uid, 0o770)]: + path.mkdir(mode=mode) + os.chown(path, uid, self.gid) + recipe = json.loads((self.args.inputs / 'recipe.json').read_bytes()) + for member in ['write', 'observation']: + recipe[member]['path'][1]['value'] = self.args.base + recipe[member]['path'][2]['value'] = self.args.table + (self.work / 'recipe.json').write_bytes(canonical(recipe)) + (self.work / 'profile.lock.json').write_bytes((self.args.inputs / 'profile.lock.json').read_bytes()) + for path in self.work.iterdir(): + os.chown(path, self.uid, self.gid) + review = json.loads(self.run('review', [self.binary, 'review', '--recipe', self.work / 'recipe.json', + '--profile-lock', self.work / 'profile.lock.json'])) + record = self.api('POST', '/v0/' + self.args.base + '/' + self.args.table, + {'fields': {'Name': 'Auths disposable qualification ' + str(uuid.uuid4()), 'DemoStatus': 'Pending'}}) + self.record = record['id'] + require(re.fullmatch(r'rec[A-Za-z0-9]{14}', self.record), 'live.invalid-created-record') + operation = str(uuid.uuid4()) + args = {'operator_namespace': 'airtable-demo', 'operation_id': operation, + 'recipe_digest': review['recipe_digest'], 'record_id': self.record, 'replacement': 'Approved'} + (self.app / 'configuration').write_text(review['verifier_configuration']) + (self.app / 'arguments.json').write_bytes(canonical(args)) + os.chown(self.app / 'arguments.json', self.app_uid, self.gid) + authored = json.loads(self.run('installed-consumer-author', self.child('author'), uid=self.app_uid)) + require(authored['sdk_location'].startswith('/opt/consumer/lib/'), 'live.repository-import') + self.install(self.work / 'first', review['recipe_digest']) + self.install(self.work / 'second', review['recipe_digest'], join=True) + first, second = self.start('first'), self.start('second') + self.run('application-secret-isolation', self.child('isolation'), uid=self.app_uid) + # Distinct processes share the actual durable store. Both receive the + # same signed action; the gateway's durable claim chooses entry. + results = [] + with concurrent.futures.ThreadPoolExecutor(max_workers=2) as pool: + futures = [pool.submit(self.run, 'two-instance-submit-' + str(index), self.child('submit', sock), + uid=self.app_uid) for index, sock in enumerate([first, second])] + results = [json.loads(future.result()) for future in futures] + require(any(value.get('outcome') == 'observed-by-provider' for value in results), 'live.write-not-observed') + require(all(value.get('outcome') in ['observed-by-provider', 'not-entered'] for value in results), + 'live.race-unexpected-outcome') + observed = next(value for value in results if value.get('outcome') == 'observed-by-provider') + readback = self.api('GET', '/v0/' + self.args.base + '/' + self.args.table + '/' + self.record) + require(readback['fields']['DemoStatus'] == 'Approved' and + readback['fields']['auths_echo'] == observed['evidence']['echo'], 'live.fresh-read-back-mismatch') + replay = json.loads(self.run('proof-replay', self.child('submit', first), uid=self.app_uid)) + require(replay.get('outcome') == 'not-entered' and replay.get('code') == 'gateway.attempt.replay', 'live.replay-not-refused') + altered = json.loads(self.run('altered-action', self.child('altered', first), uid=self.app_uid)) + require(altered.get('outcome') in ['not-entered', 'denied', 'indeterminate'], 'live.altered-action-entered') + support = self.run('support-bundle', [self.binary, 'support-bundle', '--state-dir', self.work / 'first']) + require(json.loads(support)['deployment'] == 'development', 'live.production-claim') + (self.args.out / 'support-bundle.json').write_bytes(support) + self.stop() + restarted = self.start('first') + replay_after = json.loads(self.run('restart-replay', self.child('submit', restarted), uid=self.app_uid)) + require(replay_after.get('outcome') == 'not-entered' and replay_after.get('code') == 'gateway.attempt.replay', + 'live.restart-replay-entered') + self.stop() + report = {'schema': 'auths.recipe-qualification-simulation/1', 'simulation': True, + 'stable_launch_ready': False, 'family': 'airtable-record-update-v1', + 'provider': 'live Airtable Web API v0', 'verification_boundary': 'installed SDK and native application socket', + 'source_commit': self.args.commit, 'gateway_sha256': hashlib.sha256(self.binary.read_bytes()).hexdigest(), + 'compiled_recipe_sha256': review['recipe_digest'], 'sdk_location': authored['sdk_location'], + 'sdk_version': authored['sdk_version'], 'wheel_sha256': hashlib.sha256(self.args.wheel.read_bytes()).hexdigest(), + 'store': 'shared-file-v1', 'custody': 'local-file-v1', 'clock': 'development-host-clock', + 'resources': {'base': self.args.base, 'table': self.args.table, 'record': self.record}, + 'results': {'race': results, 'proof_replay': replay, 'altered_action': altered, 'restart_replay': replay_after, + 'fresh_read_back': {'replacement_matches': True, 'echo_matches': True}}, + 'cases': self.steps, + 'excluded_claims': ['protected production qualification', 'production PostgreSQL/AWS custody', + 'complete qualification corpus', 'independent provider-entry and lease counters', 'token restriction to one base']} + return report + + def cleanup(self): + try: + self.stop() + finally: + if self.record: + result = self.api('DELETE', '/v0/' + self.args.base + '/' + self.args.table + '/' + self.record) + require(result.get('deleted') is True and result.get('id') == self.record, 'live.cleanup-refused') + self.record = None + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--consumer', choices=['author', 'submit', 'altered', 'isolation', 'sign']) + parser.add_argument('--consumer-work', type=Path) + parser.add_argument('--consumer-socket', type=Path) + parser.add_argument('--package', type=Path) + parser.add_argument('--inputs', type=Path) + parser.add_argument('--wheel', type=Path) + parser.add_argument('--credential-stdin', action='store_true') + parser.add_argument('--base') + parser.add_argument('--table') + parser.add_argument('--commit') + parser.add_argument('--out', type=Path) + args = parser.parse_args() + try: + if args.consumer: + consumer(args.consumer, args.consumer_work, args.consumer_socket) + return + operator = Operator(args) + def interrupted(_signal, _frame): + raise Refusal('live.interrupted') + signal.signal(signal.SIGTERM, interrupted) + signal.signal(signal.SIGINT, interrupted) + try: + report = operator.exercise() + finally: + operator.cleanup() + report['cleanup'] = {'created_record_deleted': True, 'table_retained_for_future_rehearsals': True} + data = json.dumps(report, indent=2).encode() + operator.scan(data) + (args.out / 'airtable-record-update-v1.json').write_bytes(data) + # Sign with the installed SDK's existing Ed25519 primitive. No key is + # serialized or given protected qualification authority. + operator.run('sign-published-report', [operator.python, Path(__file__).resolve(), '--consumer', 'sign', + '--consumer-work', args.out], uid=0) + print('Live Airtable rehearsal passed; fresh read-back, replay refusals, isolation, cleanup and report signature verified.') + except Refusal as error: + print(str(error), file=sys.stderr) + sys.exit(1) + + +if __name__ == '__main__': + main() From 3e9704b5d4d12bc654fc48de9b03ab6adb9fcb41 Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 02:07:26 +0100 Subject: [PATCH 048/108] Qualify platform-only Stripe test refunds without Connect onboarding --- docs/PROGRAM_BOARD.md | 13 + ...0014-stripe-refund-recipe-qualification.md | 55 +-- ...gateway-polish-and-recipe-qualification.md | 35 +- .../src/qualification_simulation.rs | 25 +- .../auths-gateway/src/qualification_tests.rs | 4 +- .../src/simulation_attestation.rs | 14 + qualification/simulation/README.md | 10 +- .../attestation.json | 12 + .../report.json | 128 +++++++ .../support-bundle.json | 1 + qualification/simulation/live/README.md | 41 ++- .../live/stripe-platform/generated.py | 51 +++ .../live/stripe-platform/profile.lock.json | 1 + .../live/stripe-platform/profile.toml | 38 ++ .../live/stripe-platform/recipe.json | 171 +++++++++ .../live/stripe-platform/vectors.json | 1 + qualification/simulation/live/stripe.py | 333 ++++++++++++++++++ qualification/simulation/run.py | 4 +- 18 files changed, 896 insertions(+), 41 deletions(-) create mode 100644 qualification/simulation/evidence/stripe-platform-live-2026-10-07/attestation.json create mode 100644 qualification/simulation/evidence/stripe-platform-live-2026-10-07/report.json create mode 100644 qualification/simulation/evidence/stripe-platform-live-2026-10-07/support-bundle.json create mode 100644 qualification/simulation/live/stripe-platform/generated.py create mode 100644 qualification/simulation/live/stripe-platform/profile.lock.json create mode 100644 qualification/simulation/live/stripe-platform/profile.toml create mode 100644 qualification/simulation/live/stripe-platform/recipe.json create mode 100644 qualification/simulation/live/stripe-platform/vectors.json create mode 100644 qualification/simulation/live/stripe.py diff --git a/docs/PROGRAM_BOARD.md b/docs/PROGRAM_BOARD.md index 3509811d1..58cdfb9c2 100644 --- a/docs/PROGRAM_BOARD.md +++ b/docs/PROGRAM_BOARD.md @@ -468,3 +468,16 @@ it privately inside the container. The Stripe keys work, but creating a distinct test connected account is refused because Connect is not enabled. These are development live observations, not protected production qualifications; no production trust or stable-readiness claim has changed. + +The owner then excluded paid Connect onboarding and authorized adapting the +Stripe test to platform-account refunds. The agent generated a separate +`stripe-platform-refund-v1` profile/recipe with no connected-account argument +or scope header, updated AP-SPEC-066 §7.6 and ADR 0014, and passed the real +Stripe journey using the same downloaded gateway and installed `0.0.1rc1` wheel. +Restricted-key guards, ceilings/partition refusals, fresh refund value/echo +read-back, proof/altered-action/restart refusals, secret isolation, support +scanning, full test-payment cleanup and the published report signature all +passed. Evidence is retained under +`qualification/simulation/evidence/stripe-platform-live-2026-10-07/`. +Connect scope is excluded; both real provider rehearsals remain development +evidence and do not change production qualification or stable readiness. diff --git a/docs/adr/0014-stripe-refund-recipe-qualification.md b/docs/adr/0014-stripe-refund-recipe-qualification.md index 0a0f42ced..b675b6d2e 100644 --- a/docs/adr/0014-stripe-refund-recipe-qualification.md +++ b/docs/adr/0014-stripe-refund-recipe-qualification.md @@ -1,29 +1,39 @@ -# ADR 0014: Qualify the Stripe refund recipe against a disposable Connect account +# ADR 0014: Qualify platform-account Stripe test refunds **Status:** Proposed. No family is a candidate or qualified. Acceptance requires the executable family corpus, independent oracle and protected evidence below. -**Date:** 6 October 2026 +**Date:** 7 October 2026 ## Scope and identity -The proposed family is `stripe-refund-v1`, starting from -[`examples/stripe-refund-approval/recipe.json`](../../examples/stripe-refund-approval/recipe.json) -and its profile lock. Qualification binds the compiled recipe, profile lock, -reviewed provider contract, candidate executable and semantic closure, Linux -x86_64 target, PostgreSQL schema and `aws-secrets-manager-v1` custody. A source -file or provider name alone identifies none of these claims. +The proposed family is `stripe-platform-refund-v1`, starting from the separately +generated profile and reviewed recipe under +[`qualification/simulation/live/stripe-platform/`](../../qualification/simulation/live/stripe-platform/). +The owner excluded paid Connect onboarding on 7 October 2026 and authorized a +platform-account test refund. The recipe contains no account-scope header; the +profile contains no connected-account argument. The existing Connect demo remains a separate example. The native simulation +now compiles this platform recipe and checks it against an independent wire +oracle; evidence for the old Connect recipe cannot establish this recipe's +digest or qualification. -The contract is Stripe API `2025-03-31.basil` in `provider-test-mode`. A test-mode -Connect account must differ from the platform account. Only disposable test -payments may be refunded; no customer data or real-money claim is in scope. -The gateway continues to interpret recipe data. Provider semantics and the -qualification oracle remain in the release harness, outside the runtime build. +Qualification still binds the compiled recipe, profile lock, reviewed provider +contract, candidate executable and semantic closure, Linux x86_64 target, +PostgreSQL schema and `aws-secrets-manager-v1` custody. The current live operator +rehearsal uses development file custody/store and claims no production tuple. + +The contract is Stripe API `2025-03-31.basil` in `provider-test-mode`, directly +under the platform account bound by the credential guard. Only freshly created +disposable test payments may be refunded; no customer data or real-money claim +is in scope. Connect account selection is not applicable because the recipe +declares none. A future connected-account tuple needs independent evidence +against a genuinely distinct account. Provider semantics and the qualification +oracle remain test/release code, outside the runtime build. ## Oracle and provider assumptions The test-only oracle must independently derive the POST URL, ordered form body, -version and account-scope headers, payment-intent basis read, refund locator and +version and idempotency headers, payment-intent basis read, refund locator and fresh observation from the reviewed action and evidence. It must compare both accepted and refused cases with the candidate, including request/evidence commitments. It may reuse canonical encoding and cryptographic primitives; @@ -36,7 +46,7 @@ not proof that the current recipe shares every budget or recovery meaning. | The credential addresses test mode | The `rk_test_` prefix and `/v1/balance` `livemode=false` guard both hold. | | Credential identity stays bound | The unscoped `/v1/account` result agrees with the installed platform commitment on every lease. | | Restricted reads are refused | Unscoped customers and payouts reads return the recipe's declared 403 statuses. | -| The selected account is distinct | Record sanitized platform and connected identifiers; action reads, write and refund read-back carry the exact verified `Stripe-Account`. Credential reads do not. | +| The platform-only scope is exact | Record the sanitized platform identifier; the profile has no connected-account field and the recipe sends no `Stripe-Account` header. The credential guard binds the installed platform on every lease. | | The ceiling uses the selected payment | Fresh amount and currency evidence passes at 50%, and refuses at boundary plus one or with a changed currency. | | The exact request is entered once | Provider and credential witnesses count replay, fresh-challenge replay, race, restart and crash cases separately from the corpus's expected counters. | | A recorded refund is observed | Fresh GET of the returned refund identifier matches amount and echo under the selected account. | @@ -44,14 +54,13 @@ not proof that the current recipe shares every budget or recovery meaning. Stripe documents refund amounts in minor units and a remaining-refundable constraint ([refund API](https://docs.stripe.com/api/refunds/create)); the recipe's -50% basis is not an atomic reservation of that provider balance. Stripe documents -server-side connected-account selection by header -([Connect authentication](https://docs.stripe.com/connect/authentication)). That -does not establish that the platform token is restricted to one connected account. +50% basis is not an atomic reservation of that provider balance. This platform-only contract makes no connected-account selection or restriction +claim. The operator uses a full test key only to create and clean up its fixture; +the gateway receives only the restricted test key. ## Corpus, recovery and publication gates -The maintained offline seeds are the recipe/profile lock, gateway +The maintained platform profile/recipe are accompanied by gateway `attempt-scenarios-v3.json`, `bounds-aggregate.json`, `outcome-v2.json` and `hostile-recipes-v2.json`. They must be expanded into the family-owned `auths.qualification-corpus/1` with executable coverage of every mandatory wall @@ -82,4 +91,8 @@ changed provider behavior or a materially false published assumption. Publish only sanitized disposable identifiers, bounded evidence, signed artifacts and explicit exclusions. Provider availability, settlement, indefinite idempotency, global exactly-once behavior and prevention of writes by other actors remain -provider-owned. No live evidence is claimed by this decision record. +provider-owned. The development live platform-account rehearsal passed on 7 October 2026; +its signed simulation report is retained under +`qualification/simulation/evidence/stripe-platform-live-2026-10-07/`. It +establishes the named test observations under development custody, not +protected production qualification or complete-corpus coverage. diff --git a/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md b/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md index c3eb27de6..6b4267b5c 100644 --- a/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md +++ b/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md @@ -567,12 +567,16 @@ is never silently skipped. Infrastructure failure produces no candidate. The machinery is not accepted using mocks alone. Its release gate requires two recipe families against two live providers: -- the Stripe refund journey, including a genuinely distinct connected account - when account-scope support is part of the qualified tuple; and +- the platform-account Stripe refund journey in test mode, with no Connect + account-scope capability in this launch tuple (owner decision, 7 October 2026); and - one independently authored simple write recipe from the field-lab journey (Airtable or Todoist), proving that qualification does not depend on a first-party provider module. +A future tuple that declares Connect account-scope support must exercise a +genuinely distinct connected account; the platform-only evidence cannot qualify +that capability. + Each requires its own ADR and protected evidence. The two recipes share the qualification mechanism, not provider semantics. Until both attestations verify, the release metadata MUST say `stable_launch_ready: false`. @@ -1730,3 +1734,30 @@ The Airtable token reaches the existing base; its restriction to one base has not been established. These reports exclude protected production qualification, production PostgreSQL/AWS custody, complete-corpus coverage and independently witnessed lease/provider-entry counts. Stable readiness remains false. + +### 22.2 Owner-approved Stripe scope change (2026-10-07) + +The owner has excluded paid Connect onboarding and authorized adapting the +qualification case to a platform-account refund. The launch Stripe family is +now `stripe-platform-refund-v1`: its separately generated profile and reviewed +recipe are under `qualification/simulation/live/stripe-platform/`. Neither the +profile nor the recipe declares a connected-account argument or account-scope +header. The restricted test credential guard, platform-identity commitment, +version pin, denied reads, relative ceiling, count/sum budgets, idempotency, +response locator and fresh echo observation remain required. Connected-account +selection is explicitly outside this tuple and these reports. + +The revised platform-only live Stripe run passed through the downloaded +`20837b56` gateway and installed `0.0.1rc1` Linux wheel. The restricted key +passed its test-mode/platform/denied-read guards. Grant ceiling, relative +ceiling and currency partition violations were refused. One 500-cent refund +against a freshly created 2,000-cent test payment was confirmed by an +independent fresh refund listing with matching amount and echo; original proof, +altered action and replay after restart were refused. The application could +read neither the staged credential nor gateway state. Teardown refunded the +remaining balance and freshly confirmed the charge was fully refunded. +The exact signed simulation report and support bundle are retained under +`qualification/simulation/evidence/stripe-platform-live-2026-10-07/`. +Both live provider journeys now have measured development evidence. They still +exclude protected production qualification and the full production evidence +wall; the normal production lease gate remains unchanged. diff --git a/product/runtime/auths-gateway/src/qualification_simulation.rs b/product/runtime/auths-gateway/src/qualification_simulation.rs index 689a12d64..a31d90847 100644 --- a/product/runtime/auths-gateway/src/qualification_simulation.rs +++ b/product/runtime/auths-gateway/src/qualification_simulation.rs @@ -7,7 +7,6 @@ use super::*; use serde::Serialize; const STRIPE_VERSION: &str = "2025-03-31.basil"; -const STRIPE_ACCOUNT: &str = "acct_TESTACCOUNT01"; const STRIPE_PAYMENT: &str = "pi_TEST0000000001"; fn stripe_setup() -> Value { @@ -15,7 +14,13 @@ fn stripe_setup() -> Value { "../../../../bindings/fixtures/gateway/attempt-scenarios-v3.json" )) .expect("embedded Stripe fixture"); - corpus["defaults"]["stripe"].clone() + let mut setup = corpus["defaults"]["stripe"].clone(); + // The platform-only profile has no connected-account argument or grant scope. + setup["grant_policy"] + .as_object_mut() + .expect("grant policy") + .remove("scope"); + setup } #[derive(Clone, Copy)] @@ -48,7 +53,7 @@ impl Family { } fn name(self) -> &'static str { match self { - Self::Stripe => "stripe-refund-v1", + Self::Stripe => "stripe-platform-refund-v1", Self::Airtable => "airtable-record-update-v1", } } @@ -65,8 +70,12 @@ impl Family { fn recipe(self) -> CompiledRecipe { match self { Self::Stripe => CompiledRecipe::compile( - include_bytes!("../../../../examples/stripe-refund-approval/recipe.json"), - include_bytes!("../../../../examples/stripe-refund-approval/profile.lock.json"), + include_bytes!( + "../../../../qualification/simulation/live/stripe-platform/recipe.json" + ), + include_bytes!( + "../../../../qualification/simulation/live/stripe-platform/profile.lock.json" + ), ) .expect("Stripe recipe"), Self::Airtable => fixture_recipe("airtable"), @@ -76,7 +85,7 @@ impl Family { fn arguments(self, operation: &str) -> Map { match self { Self::Stripe => json!({"operation_id": operation, "payment_intent": STRIPE_PAYMENT, - "amount": 500, "currency": "usd", "connect_account": STRIPE_ACCOUNT}), + "amount": 500, "currency": "usd"}), Self::Airtable => json!({"operation_id": operation, "record_id": RECORD, "replacement": "Approved"}), } @@ -90,7 +99,7 @@ impl Family { /// by this independent vertical, never projected from candidate bytes. fn oracle(self, operation: &str, commitment: &[u8; 32]) -> Value { let namespace = crate::OperatorNamespace::parse(match self { - Self::Stripe => "stripe-refunds", + Self::Stripe => "stripe-platform-refunds", Self::Airtable => "airtable-demo", }) .expect("namespace"); @@ -104,7 +113,7 @@ impl Family { form.append_pair("payment_intent", STRIPE_PAYMENT); json!({"method": "POST", "url": "https://api.stripe.com/v1/refunds", "content_type": "application/x-www-form-urlencoded", "body": form.finish(), - "headers": [["Stripe-Version", STRIPE_VERSION], ["Stripe-Account", STRIPE_ACCOUNT], + "headers": [["Stripe-Version", STRIPE_VERSION], ["Idempotency-Key", crate::idempotency_key(&namespace, &operation)]], "idempotency_key": crate::idempotency_key(&namespace, &operation)}) } diff --git a/product/runtime/auths-gateway/src/qualification_tests.rs b/product/runtime/auths-gateway/src/qualification_tests.rs index 4108f07e1..193bd17fc 100644 --- a/product/runtime/auths-gateway/src/qualification_tests.rs +++ b/product/runtime/auths-gateway/src/qualification_tests.rs @@ -143,7 +143,7 @@ fn verify_simulation_reports() { bytes }; let mut verified = Vec::new(); - for family in ["stripe-refund-v1", "airtable-record-update-v1"] { + for family in ["stripe-platform-refund-v1", "airtable-record-update-v1"] { let report = bounded(&directory.join(format!("{family}.json")), 1_048_576); let signature = bounded(&directory.join(format!("{family}.attestation.json")), 4096); assert!(crate::simulation_attestation::verify(&report, &signature)); @@ -193,7 +193,7 @@ async fn operator_bootstrap_qualification_simulation() { .expect("certificate"); let signer = ReleaseSigner::open(&signer_seed, certificate).expect("signer"); let proposals = [ - proposal(1, &tuple_for("simulation-stripe-refund-v1")), + proposal(1, &tuple_for("simulation-stripe-platform-refund-v1")), proposal(2, &tuple_for("simulation-airtable-update-v1")), ]; let attestations: Vec<_> = proposals diff --git a/product/runtime/auths-gateway/src/simulation_attestation.rs b/product/runtime/auths-gateway/src/simulation_attestation.rs index a1b59e934..914a49ee5 100644 --- a/product/runtime/auths-gateway/src/simulation_attestation.rs +++ b/product/runtime/auths-gateway/src/simulation_attestation.rs @@ -132,3 +132,17 @@ fn installed_python_live_report_verifies_under_the_native_signature_contract() { altered.push(b' '); assert!(!verify(&altered, attestation)); } + +#[test] +fn installed_python_platform_refund_report_verifies_under_the_native_signature_contract() { + let report = include_bytes!( + "../../../../qualification/simulation/evidence/stripe-platform-live-2026-10-07/report.json" + ); + let attestation = include_bytes!( + "../../../../qualification/simulation/evidence/stripe-platform-live-2026-10-07/attestation.json" + ); + assert!(verify(report, attestation)); + let mut altered = report.to_vec(); + altered.push(b' '); + assert!(!verify(&altered, attestation)); +} diff --git a/qualification/simulation/README.md b/qualification/simulation/README.md index 9f3832ace..2606c4f92 100644 --- a/qualification/simulation/README.md +++ b/qualification/simulation/README.md @@ -10,7 +10,7 @@ Use a fresh output directory. No provider credential, signing key file or production environment is needed. The same run is a required job in recipe qualification CI, and uploads its public reports and signing artifacts. -The Stripe refund and Airtable record update harnesses compile the maintained +The platform-account Stripe refund and Airtable record update harnesses compile the maintained recipes and drive the native submission driver over durable file claims and mutable counting providers. Independent vertical wire oracles check the actual method, URL, headers, body and idempotency commitment before each write. Reports @@ -50,3 +50,11 @@ bootstrap records name placeholder provenance. No file is installed under `qualification/trust` or `qualification/families`, and readiness remains false. Native proof/socket and installed-package journeys remain separate SDK workflow checks. This rehearsal does not claim the full protected production corpus. + +The owner approved platform-only Stripe test refunds to avoid paid Connect +onboarding. Both maintained live harnesses passed using the downloaded gateway +and installed Python 0.0.1rc1 wheel in Docker. Their signed reports are retained +in `evidence/stripe-platform-live-2026-10-07/` and +`evidence/airtable-live-2026-10-07/`; see [live instructions](live/README.md). +Those actual provider runs use development custody and exclude protected +production qualification and full mandatory-corpus coverage. diff --git a/qualification/simulation/evidence/stripe-platform-live-2026-10-07/attestation.json b/qualification/simulation/evidence/stripe-platform-live-2026-10-07/attestation.json new file mode 100644 index 000000000..344848855 --- /dev/null +++ b/qualification/simulation/evidence/stripe-platform-live-2026-10-07/attestation.json @@ -0,0 +1,12 @@ +{ + "statement": { + "schema": "auths.provider-simulation-attestation/1", + "simulation": true, + "stable_launch_ready": false, + "signer_kind": "disposable-self-signed-simulation-key", + "family": "stripe-platform-refund-v1", + "report_sha256": "3eaea0009cc3ab5c6ddc34e710d12f44397edc3f36d78ebb35928d46804a0571", + "public_key_b64": "UNsQ2mNZ8JQCFVx/zTHAqDH2+znv3gY6WIHC7X5cpH4" + }, + "signature_b64": "NBDD/ZkPEwoX/hyxMLW3jIFSuVFLPtxg1Y94KEdHXS0zx2vpAZZLkLgFDyyAtJ1QGRHPURJSJ/r7wcj8W7TiAQ" +} \ No newline at end of file diff --git a/qualification/simulation/evidence/stripe-platform-live-2026-10-07/report.json b/qualification/simulation/evidence/stripe-platform-live-2026-10-07/report.json new file mode 100644 index 000000000..b56487bba --- /dev/null +++ b/qualification/simulation/evidence/stripe-platform-live-2026-10-07/report.json @@ -0,0 +1,128 @@ +{ + "schema": "auths.recipe-qualification-simulation/1", + "simulation": true, + "stable_launch_ready": false, + "family": "stripe-platform-refund-v1", + "provider": "live Stripe test mode; platform account", + "source_commit": "20837b56a61945d79dedf48a1ff237411dd01185", + "compiled_recipe_sha256": "b258393c49779150ed521cba3a62a4cd546d349b91d4b2ac69da4a9a643858fb", + "gateway_sha256": "85d6fd1c8b44fa5a7a34d4a012a39d3edf00dc867710c149b7d3da2bc6d2230e", + "wheel_sha256": "6d079aa4960256a754315d911b55d80bc02848b1ad14225420ea8eae4905656f", + "sdk_version": "0.0.1rc1", + "sdk_location": "/opt/consumer/lib/python3.12/site-packages/auths/__init__.py", + "resources": { + "platform_account": "acct_1QekbYID70YvJ7mY", + "payment_intent": "pi_3UNjEgID70YvJ7mY0doGkVOE", + "refund": "re_3UNjEgID70YvJ7mY0MCV4aKv" + }, + "store": "shared-file-v1", + "custody": "local-file-v1", + "clock": "development-host-clock", + "verification_boundary": "installed SDK and native application socket", + "cases": [ + { + "case": "review", + "seconds": 0.164 + }, + { + "case": "bound-extension", + "seconds": 0.124 + }, + { + "case": "installed-consumer-author", + "seconds": 0.419 + }, + { + "case": "install", + "seconds": 2.014 + }, + { + "case": "application-secret-isolation", + "seconds": 0.344 + }, + { + "case": "above-grant", + "seconds": 0.383 + }, + { + "case": "above-ratio", + "seconds": 2.176 + }, + { + "case": "wrong-currency", + "seconds": 0.35 + }, + { + "case": "normal", + "seconds": 4.777 + }, + { + "case": "proof-replay", + "seconds": 0.364 + }, + { + "case": "altered-action", + "seconds": 0.342 + }, + { + "case": "support-bundle", + "seconds": 0.259 + }, + { + "case": "restart-replay", + "seconds": 0.548 + } + ], + "results": { + "above-grant": { + "code": "gateway.policy.above-ceiling", + "outcome": "not-entered" + }, + "above-ratio": { + "code": "gateway.relative-ceiling.above", + "outcome": "not-entered" + }, + "wrong-currency": { + "code": "gateway.policy.partition-denied", + "outcome": "not-entered" + }, + "normal": { + "evidence": { + "channel": "read-back", + "echo": "auths-e1-cd352f4d542ed7350a7effd035471407b1e87fc64aa66eeec525562d1b4b27ec", + "evidence_digest": "eb77bd43524e2bca9d585a2b0d1ea2fb4c5289ed7c546d5693ab4c9475898f03", + "observed_at": 1791334905 + }, + "outcome": "observed-by-provider", + "status": 200 + }, + "proof-replay": { + "code": "gateway.attempt.replay", + "outcome": "not-entered" + }, + "altered-action": { + "code": "malformed-proof", + "outcome": "denied" + }, + "restart-replay": { + "code": "gateway.attempt.replay", + "outcome": "not-entered" + } + }, + "fresh_read_back": { + "refund_count_before_cleanup": 1, + "amount_matches": true, + "echo_matches": true + }, + "excluded_claims": [ + "Connect/connected-account scope", + "protected production qualification", + "production PostgreSQL/AWS custody", + "complete qualification corpus", + "independent lease/provider-entry counters" + ], + "cleanup": { + "test_payment_fully_refunded": true, + "stripe_retains_test_payment_and_refund_records": true + } +} \ No newline at end of file diff --git a/qualification/simulation/evidence/stripe-platform-live-2026-10-07/support-bundle.json b/qualification/simulation/evidence/stripe-platform-live-2026-10-07/support-bundle.json new file mode 100644 index 000000000..40ac25313 --- /dev/null +++ b/qualification/simulation/evidence/stripe-platform-live-2026-10-07/support-bundle.json @@ -0,0 +1 @@ +{"attempts":{"by_stage":{"not-entered":1,"observed-by-provider":1},"identifiers":[{"key_sha256":"0aa2afec3447e90c3680b4cf0403d7ab3bcf66f93cc91f949aeaa19fe012917b","stage":"not-entered"},{"key_sha256":"a5ac6189c4e69ddcdfc6b1aea6db6f4cca98ec27ed8a27077f9c85cfa95f2680","stage":"observed-by-provider"}],"listed":2,"truncated":false},"build_sha256":"85d6fd1c8b44fa5a7a34d4a012a39d3edf00dc867710c149b7d3da2bc6d2230e","codes":["gateway.qualification.unavailable"],"connection":{"credential_generation":1,"credential_held":true,"generation":1,"in_flight":0,"state":"active"},"credential_store_kind":"local-file-v1","deployment":"development","gateway_package":"auths-gateway","gateway_version":"1.0.0-rc.1","profile_lock_sha256":"99901e36cb7c4f5882897603c874698d582e859b5d6b08d53cd80975e89aa01c","qualification":{"code":"gateway.qualification.unavailable","policy":"optional","state":"unqualified"},"recipe_sha256":"b258393c49779150ed521cba3a62a4cd546d349b91d4b2ac69da4a9a643858fb","schema":"auths.gateway-support-bundle/1","semantic_closure_sha256":"11a256092b821eec54d27e3ad25cc05f7955da236ea23853cced71c32215764d","trusted_context_sha256":"9bd112b926302b1ec7dc95b89e070ec7e42b05211ead7bbe4f72dabb2babf007"} diff --git a/qualification/simulation/live/README.md b/qualification/simulation/live/README.md index 2d4971a48..8724b40e9 100644 --- a/qualification/simulation/live/README.md +++ b/qualification/simulation/live/README.md @@ -18,7 +18,7 @@ signature. This signer has no protected release authority. Live provider state is evidence; the report makes no production qualification, PostgreSQL/AWS, complete-corpus, token-scope or independently measured lease/entry-counter claim. -Run inside the maintained Docker image after installing the candidate wheel +Run inside the maintained Docker image (`Dockerfile` in this directory) after installing the candidate wheel with `/opt/consumer/bin/pip install --no-deps /wheel/.whl`. Mount only the extracted package, public Airtable recipe/profile lock, this script and an empty report directory. Supply the operator credential through Docker stdin. @@ -41,10 +41,29 @@ must fail to read the staged credential and both gateway state directories. Child output is bounded and secret-scanned before publication; provider error response bodies never reach public logs. -Stripe's distinct-account rehearsal additionally requires Connect enabled on -the test platform. A 400 refusal creating a connected account is a failed setup, -not evidence of account-scope qualification. Do not substitute the platform -account and declare that requirement satisfied. +The owner authorized platform-account Stripe test refunds on 7 October 2026. +`stripe.py` uses the separately generated `stripe-platform/` profile and recipe, +which have no connected-account field or scope header. It checks the restricted +test key, platform identity, denied reads, grant/relative ceilings, currency, +refund value/echo read-back, proof replay, altered action, restart, secret +isolation, support redaction and exact report signature. Setup creates only a +test PaymentIntent; teardown fully refunds its remaining test balance and +independently reads the charge to confirm cleanup. Stripe retains test payment +and refund records. No Connect/account-scope behavior is claimed. The current +platform test profile is different from the existing scoped Connect example. +For Stripe, use the same mounts and installed wheel, with the public +`stripe-platform/` directory at `/inputs`: + +```text +/opt/consumer/bin/python /harness/stripe.py \ + --package /candidate/auths-gateway-operator \ + --inputs /inputs --wheel /wheel/.whl --credential-stdin \ + --commit --out /reports/run +``` + +Stripe stdin holds `STRIPE_TEST_API_KEY` and `STRIPE_TEST_RESTRICTED_KEY` in +dotenv format. Setup/cleanup use the full test key; gateway installation +receives only the restricted test key. Both keys must be test-mode keys. The first successful live rehearsal is preserved in [`../evidence/airtable-live-2026-10-07/`](../evidence/airtable-live-2026-10-07/). @@ -54,3 +73,15 @@ The two-process submission returned one provider-observed outcome and one restart were refused. Altered action bytes were denied as `malformed-proof`. An independent fresh GET matched both the approved replacement and the gateway result's echo. The created record was deleted before the report was signed. + +The matching platform-only Stripe report, signature and real support bundle +are preserved in +[`../evidence/stripe-platform-live-2026-10-07/`](../evidence/stripe-platform-live-2026-10-07/). +It used the same downloaded gateway and installed `0.0.1rc1` wheel as Airtable. +A newly created 2,000-cent test payment had exactly one 500-cent gateway refund +before teardown, with fresh matching echo/value read-back. Grant ceiling, +relative ceiling and currency partition violations were refused, as were +original-proof replay, altered action and replay after restart. Teardown +refunded the remaining test balance and read the charge to confirm full refund. +The refund object has no `livemode` member; the test-mode evidence is the +credential/balance guard and the PaymentIntent/Charge observations. diff --git a/qualification/simulation/live/stripe-platform/generated.py b/qualification/simulation/live/stripe-platform/generated.py new file mode 100644 index 000000000..106517b8d --- /dev/null +++ b/qualification/simulation/live/stripe-platform/generated.py @@ -0,0 +1,51 @@ +"""Generated by auths; edit profile.toml, then regenerate.""" +from __future__ import annotations + +from dataclasses import dataclass +from typing import Literal, TypeVar + +from auths.self_hosted import ( + EnumField, + ExactMcpTool, + IntegerField, + StringField, +) + +PROFILE_NAME = "stripe-platform-refund" +PROFILE_VERSION = 1 +TOOL_NAME = "create_refund_v1" +SCHEMA_DIGEST = "d2f5b926a3b6989d13b3a4614372e298442de697d92d5e06330288f7de4e257a" + + +@dataclass(frozen=True) +class CreateRefund: + operator_namespace: Literal["stripe-platform-refunds"] + operation_id: str + recipe_digest: str + payment_intent: str + amount: int + currency: str + + +FIELDS = { + "operator_namespace": EnumField(('stripe-platform-refunds',)), + "operation_id": StringField(min_length=1, max_length=128), + "recipe_digest": StringField(min_length=64, max_length=64), + "payment_intent": StringField(min_length=3, max_length=255), + "amount": IntegerField(minimum=1, maximum=99999999), + "currency": StringField(min_length=3, max_length=3), +} + +CommandT = TypeVar("CommandT") + + +def contract_for(command_type: type[CommandT]) -> ExactMcpTool[CommandT]: + return ExactMcpTool( + service="stripe-platform-refunds", + name=TOOL_NAME, + command_type=command_type, + fields=FIELDS, + ) + + +CONTRACT = contract_for(CreateRefund) diff --git a/qualification/simulation/live/stripe-platform/profile.lock.json b/qualification/simulation/live/stripe-platform/profile.lock.json new file mode 100644 index 000000000..51543b425 --- /dev/null +++ b/qualification/simulation/live/stripe-platform/profile.lock.json @@ -0,0 +1 @@ +{"command_schema":{"fields":{"amount":{"kind":"integer","maximum":99999999,"minimum":1},"currency":{"kind":"string","maximum":3,"minimum":3},"operation_id":{"kind":"string","maximum":128,"minimum":1},"operator_namespace":{"type":"enum","variants":["stripe-platform-refunds"]},"payment_intent":{"kind":"string","maximum":255,"minimum":3},"recipe_digest":{"kind":"string","maximum":64,"minimum":64}},"kind":"object"},"generator_format":2,"profile":"stripe-platform-refund","schema":"auths.self-hosted-profile-lock/1","schema_digest":"d2f5b926a3b6989d13b3a4614372e298442de697d92d5e06330288f7de4e257a","service":"stripe-platform-refunds","tool":"create_refund_v1","version":1} diff --git a/qualification/simulation/live/stripe-platform/profile.toml b/qualification/simulation/live/stripe-platform/profile.toml new file mode 100644 index 000000000..1a1592f09 --- /dev/null +++ b/qualification/simulation/live/stripe-platform/profile.toml @@ -0,0 +1,38 @@ +[profile] +name = "stripe-platform-refund" +version = 1 +service = "stripe-platform-refunds" +tool = "create_refund" +command = "CreateRefund" + +[arguments] +type = "object" + +[arguments.fields.operator_namespace] +type = "enum" +variants = ["stripe-platform-refunds"] + +[arguments.fields.operation_id] +type = "string" +min_bytes = 1 +max_bytes = 128 + +[arguments.fields.recipe_digest] +type = "string" +min_bytes = 64 +max_bytes = 64 + +[arguments.fields.payment_intent] +type = "string" +min_bytes = 3 +max_bytes = 255 + +[arguments.fields.amount] +type = "integer" +minimum = 1 +maximum = 99999999 + +[arguments.fields.currency] +type = "string" +min_bytes = 3 +max_bytes = 3 diff --git a/qualification/simulation/live/stripe-platform/recipe.json b/qualification/simulation/live/stripe-platform/recipe.json new file mode 100644 index 000000000..9f9f90ce1 --- /dev/null +++ b/qualification/simulation/live/stripe-platform/recipe.json @@ -0,0 +1,171 @@ +{ + "schema": "auths.gateway-recipe-source/2", + "profile_schema_digest": "d2f5b926a3b6989d13b3a4614372e298442de697d92d5e06330288f7de4e257a", + "service": "stripe-platform-refunds", + "tool": "create_refund_v1", + "operator_namespace": "stripe-platform-refunds", + "credential": { + "kind": "bearer", + "guard": { + "prefixes": [ + "rk_test_" + ], + "probe": { + "path": [ + { + "kind": "fixed", + "value": "v1" + }, + { + "kind": "fixed", + "value": "balance" + } + ], + "json_pointer": "/livemode", + "equals": false, + "maximum_response_bytes": 16384 + }, + "account": { + "path": [ + { + "kind": "fixed", + "value": "v1" + }, + { + "kind": "fixed", + "value": "account" + } + ], + "json_pointer": "/id", + "maximum_response_bytes": 65536 + }, + "denied_reads": [ + { + "method": "GET", + "path": [ + { + "kind": "fixed", + "value": "v1" + }, + { + "kind": "fixed", + "value": "customers" + } + ], + "refused_status": [ + 403 + ] + }, + { + "method": "GET", + "path": [ + { + "kind": "fixed", + "value": "v1" + }, + { + "kind": "fixed", + "value": "payouts" + } + ], + "refused_status": [ + 403 + ] + } + ] + } + }, + "origin": "https://api.stripe.com", + "provider_headers": { + "Stripe-Version": "2025-03-31.basil" + }, + "bounds": { + "sum": { + "argument": "amount", + "partition": "currency" + } + }, + "relative_ceiling": { + "argument": "amount", + "basis_points": 5000, + "path": [ + { + "kind": "fixed", + "value": "v1" + }, + { + "kind": "fixed", + "value": "payment_intents" + }, + { + "kind": "field", + "name": "payment_intent" + } + ], + "json_pointer": "/amount_received", + "bind": [ + { + "pointer": "/currency", + "field": "currency" + } + ], + "maximum_response_bytes": 65536 + }, + "write": { + "method": "POST", + "path": [ + { + "kind": "fixed", + "value": "v1" + }, + { + "kind": "fixed", + "value": "refunds" + } + ], + "body": { + "kind": "form", + "fields": { + "payment_intent": { + "kind": "field", + "name": "payment_intent" + }, + "amount": { + "kind": "field", + "name": "amount" + } + } + }, + "idempotency": { + "kind": "derived-header", + "retention_seconds": 86400 + } + }, + "observation": { + "path": [ + { + "kind": "fixed", + "value": "v1" + }, + { + "kind": "fixed", + "value": "refunds" + }, + { + "kind": "response-field", + "pointer": "/id", + "max_bytes": 255 + } + ], + "json_pointer": "/amount", + "expected_field": "amount", + "maximum_response_bytes": 16384 + }, + "echo": { + "write": { + "kind": "form-field", + "name": "metadata[auths_echo]" + }, + "observe": "/metadata/auths_echo" + } +} diff --git a/qualification/simulation/live/stripe-platform/vectors.json b/qualification/simulation/live/stripe-platform/vectors.json new file mode 100644 index 000000000..5b75d713e --- /dev/null +++ b/qualification/simulation/live/stripe-platform/vectors.json @@ -0,0 +1 @@ +{"profile":"stripe-platform-refund","schema":"auths.self-hosted-profile-vectors/2","schema_digest":"d2f5b926a3b6989d13b3a4614372e298442de697d92d5e06330288f7de4e257a","service":"stripe-platform-refunds","tool":"create_refund_v1","valid_arguments_json":"{\"amount\":1,\"currency\":\"xxx\",\"operation_id\":\"x\",\"operator_namespace\":\"stripe-platform-refunds\",\"payment_intent\":\"xxx\",\"recipe_digest\":\"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\"}","version":1} diff --git a/qualification/simulation/live/stripe.py b/qualification/simulation/live/stripe.py new file mode 100644 index 000000000..8cf14c54e --- /dev/null +++ b/qualification/simulation/live/stripe.py @@ -0,0 +1,333 @@ +#!/usr/bin/env python3 +"""Live platform-account refund rehearsal; Connect is outside this tuple.""" +import argparse +import asyncio +import base64 +from dataclasses import asdict +import hashlib +import importlib.metadata +import json +import os +from pathlib import Path +import re +import selectors +import signal +import subprocess +import sys +import tempfile +import time +import urllib.error +import urllib.parse +import urllib.request +import uuid + + +class Refusal(Exception): + pass + + +def require(value, code): + if not value: + raise Refusal(code) + + +def canonical(value): + return json.dumps(value, sort_keys=True, separators=(',', ':'), ensure_ascii=False).encode() + + +def consumer(args): + from auths import _native as native + from auths.gateway import GatewayClient, GatewayEndpoint + require('STRIPE_TEST_API_KEY' not in os.environ and 'STRIPE_TEST_RESTRICTED_KEY' not in os.environ + and 'PYTHONPATH' not in os.environ, 'live.consumer-environment') + work = args.consumer_work + if args.consumer == 'author': + plan = json.loads((work / 'plan.json').read_bytes()) + current = int(time.time()) + audience = 'mcp://stripe-platform-refunds' + resource = audience + '/tools/create_refund_v1' + key = native.DevelopmentEd25519Key.generate() + actor = native.Principal(key.principal) + extension = plan['extension'] + ext = [(extension['extension_id'], bytes.fromhex(extension['extension_body_hex']))] + request = native.GrantRequest(actor, 'auths.mcp', 2, [('tools/call', resource)], current - 60, + current + 600, [audience], None, None, 0, None, 'raw-key-baseline', ext) + unsigned = native.root_grant(actor, request) + signing = native.prepare_signing(unsigned, key.principal_method, key.verification_method, key.suite) + grant = signing.complete(key.sign(signing.signing_preimage)) + challenge = native.generate_challenge_v1() + anchor = native.TrustAnchor(actor.value, actor, [key.principal_method], [('auths.mcp', 2)], + [('tools/call', resource)], [audience], [audience], current - 60, current + 600, + None, 1, 'raw-key-baseline', None) + assurance = native.AssurancePolicy('raw-key-baseline', [ + ('root', 'every', 'self-certifying-identifier', None), + ('actor', 'every', 'self-certifying-identifier', None), ('actor', 'every', 'offline-verifiable', None)]) + template = native.compile_trusted_context(bytes.fromhex(plan['configuration']), None, 1, 1, 1, + [anchor], assurance, None, None, 'none-v1', [key.evidence_type], [extension['extension_id']]) + context = template.bind_request(audience, challenge, current) + evidence = (key.evidence_type, key.media_type, key.evidence) + for label, arguments in plan['arguments'].items(): + call = native.mcp_call('stripe-platform-refunds', 'create_refund_v1', canonical(arguments)) + prepared = native.prepare_mcp_call_action(call, actor, grant, challenge, current, 120) + signing = native.prepare_signing(prepared.unsigned, key.principal_method, key.verification_method, key.suite) + action = signing.complete(key.sign(signing.signing_preimage)) + proof, action, trust = native.assemble_mcp_proof(prepared, action, [grant], [[evidence]], [evidence], context) + (work / (label + '.proof')).write_bytes(proof) + (work / (label + '.action')).write_bytes(action) + (work / 'context.cbor').write_bytes(trust) + print(json.dumps({'sdk_version': importlib.metadata.version('auths'), 'sdk_location': __import__('auths').__file__})) + elif args.consumer == 'isolation': + for path in ['/run/provider-secret/provider.env', '/run/operator/state']: + try: + Path(path).read_bytes() if path.endswith('.env') else list(Path(path).iterdir()) + except PermissionError: + continue + raise Refusal('live.application-can-read-secret') + print('{"isolated":true}') + elif args.consumer == 'sign': + key = native.DevelopmentEd25519Key.generate() + report = (work / 'report.json').read_bytes() + enc = lambda data: base64.b64encode(data).rstrip(b'=').decode() + statement = {'schema': 'auths.provider-simulation-attestation/1', 'simulation': True, + 'stable_launch_ready': False, 'signer_kind': 'disposable-self-signed-simulation-key', + 'family': 'stripe-platform-refund-v1', 'report_sha256': hashlib.sha256(report).hexdigest(), + 'public_key_b64': enc(bytes(key.public_key))} + preimage = b'auths.provider-simulation-attestation/1\0' + canonical(statement) + signature = bytes(key.sign(preimage)) + path = work / 'attestation.json' + path.write_bytes(json.dumps({'statement': statement, 'signature_b64': enc(signature)}, indent=2).encode()) + envelope = json.loads(path.read_bytes()) + require(envelope['statement']['report_sha256'] == hashlib.sha256((work / 'report.json').read_bytes()).hexdigest(), + 'live.signature-report-mismatch') + native.verify_ed25519_preimage_v1(base64.b64decode(envelope['statement']['public_key_b64'] + '=='), + b'auths.provider-simulation-attestation/1\0' + canonical(envelope['statement']), + base64.b64decode(envelope['signature_b64'] + '==')) + print('{"persisted_signature_verified":true}') + else: + label = args.case + action = (work / (label + '.action')).read_bytes() + if args.consumer == 'altered': + action += b'\0' + result = asyncio.run(GatewayClient(GatewayEndpoint(args.consumer_socket)).submit( + proof=(work / (label + '.proof')).read_bytes(), action=action)) + print(json.dumps(asdict(result), sort_keys=True)) + + +class Operator: + uid, app_uid, gid = 62001, 62002, 62000 + + def __init__(self, args): + self.args, self.steps = args, [] + self.binary = args.package / 'bin/auths-gateway' + self.python = Path('/opt/consumer/bin/python') + self.env = {'PATH': '/usr/bin:/bin', 'PYTHONNOUSERSITE': '1'} + self.work, self.app = Path('/run/operator'), Path('/run/app') + self.process, self.log, self.payment, self.keys = None, None, None, {} + + def scan(self, data): + for key in self.keys.values(): + raw = key.encode() + require(not any(value in data for value in [raw, raw.hex().encode(), base64.b64encode(raw), + base64.urlsafe_b64encode(raw)]), 'live.secret-exposure') + + def run(self, label, argv, stdin=b'', uid=None): + start = time.monotonic() + result = subprocess.run(list(map(str, argv)), input=stdin, capture_output=True, timeout=60, + env=self.env, cwd='/run', user=self.uid if uid is None else uid, group=self.gid, extra_groups=[]) + self.scan(result.stdout + result.stderr) + require(len(result.stdout) + len(result.stderr) <= 1048576, 'live.output-bound') + if result.returncode != 0: + codes = re.findall(rb'(?:live|gateway)\.[a-z0-9.-]+', result.stderr) + raise Refusal('live.command-refused:' + label + (':' + codes[-1].decode() if codes else '')) + self.steps.append({'case': label, 'seconds': round(time.monotonic() - start, 3)}) + return result.stdout + + def child(self, verb, label='normal', work=None): + return [self.python, Path(__file__).resolve(), '--consumer', verb, '--case', label, + '--consumer-work', work or self.app, '--consumer-socket', '/run/sockets/app.sock'] + + def api(self, method, path, fields=None, restricted=False, expected=200): + require(path.startswith('/v1/'), 'live.invalid-provider-path') + key = self.keys['STRIPE_TEST_RESTRICTED_KEY' if restricted else 'STRIPE_TEST_API_KEY'] + data = None if fields is None else urllib.parse.urlencode(fields).encode() + request = urllib.request.Request('https://api.stripe.com' + path, data=data, method=method, + headers={'Authorization': 'Bearer ' + key, 'Stripe-Version': '2025-03-31.basil'}) + try: + response = urllib.request.urlopen(request, timeout=25) + except urllib.error.HTTPError as error: + require(error.code == expected, 'live.stripe-http-' + str(error.code)) + error.close() + return {'http_status': expected} + with response: + require(response.status == expected, 'live.unexpected-provider-status') + body = response.read(65537) + require(len(body) <= 65536, 'live.provider-response-bound') + return json.loads(body) + + def start(self): + self.log = tempfile.TemporaryFile() + self.process = subprocess.Popen([str(self.binary), 'serve', '--state-dir', str(self.work / 'state'), + '--app-socket', '/run/sockets/app.sock'], stdout=subprocess.PIPE, stderr=self.log, + env=self.env, cwd='/run', user=self.uid, group=self.gid, extra_groups=[]) + with selectors.DefaultSelector() as selector: + selector.register(self.process.stdout, selectors.EVENT_READ) + require(bool(selector.select(15)), 'live.gateway-start-timeout') + require(self.process.stdout.readline(65537).startswith(b'app socket ready'), 'live.gateway-start-refused') + + def stop(self): + if self.process: + if self.process.poll() is None: + self.process.send_signal(signal.SIGTERM) + try: + self.process.wait(timeout=30) + except subprocess.TimeoutExpired: + self.process.kill(); self.process.wait() + raise Refusal('live.gateway-stop-timeout') + self.log.seek(0); self.scan(self.log.read(1048577)) + require(self.process.returncode == 0, 'live.gateway-stop-refused') + self.process.stdout.close(); self.log.close() + self.process = None + + def exercise(self): + require(os.getuid() == 0 and not self.args.out.exists(), 'live.private-container-required') + self.args.out.mkdir(parents=True) + require(self.args.credential_stdin and not sys.stdin.isatty(), 'live.credential-stdin-required') + raw = sys.stdin.buffer.read(8193) + require(len(raw) <= 8192, 'live.credential-input-bound') + private = Path('/run/provider-secret'); private.mkdir(mode=0o700) + with os.fdopen(os.open(private / 'provider.env', os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o600), 'wb') as output: + output.write(raw) + for line in raw.decode().splitlines(): + match = re.fullmatch(r'\s*(STRIPE_TEST_API_KEY|STRIPE_TEST_RESTRICTED_KEY)\s*=\s*(.*?)\s*', line) + if match: self.keys[match[1]] = match[2].strip('"\'') + require(self.keys.get('STRIPE_TEST_API_KEY', '').startswith('sk_test_') and + self.keys.get('STRIPE_TEST_RESTRICTED_KEY', '').startswith('rk_test_'), 'live.test-keys-required') + manifest = json.loads((self.args.package / 'manifest.json').read_bytes()) + require(manifest['source_commit'] == self.args.commit, 'live.candidate-commit-mismatch') + for entry in manifest['files']: + path = self.args.package / entry['path'] + require(not path.is_symlink() and hashlib.sha256(path.read_bytes()).hexdigest() == entry['sha256'], 'live.package-hash-mismatch') + platform = self.api('GET', '/v1/account', restricted=True)['id'] + require(self.api('GET', '/v1/balance', restricted=True)['livemode'] is False, 'live.not-test-mode') + for path in ['/v1/customers', '/v1/payouts']: + self.api('GET', path, restricted=True, expected=403) + payment = self.api('POST', '/v1/payment_intents', {'amount': 2000, 'currency': 'usd', + 'payment_method': 'pm_card_visa', 'confirm': 'true', 'automatic_payment_methods[enabled]': 'true', + 'automatic_payment_methods[allow_redirects]': 'never', 'metadata[auths_simulation]': 'disposable-platform-refund'}) + self.payment = payment['id'] + require(payment['livemode'] is False and payment['status'] == 'succeeded', 'live.fixture-payment-not-ready') + for path, uid, mode in [(self.work, self.uid, 0o700), (self.app, self.app_uid, 0o750), + (Path('/run/sockets'), self.uid, 0o770)]: + path.mkdir(mode=mode); os.chown(path, uid, self.gid) + for name in ['recipe.json', 'profile.lock.json']: + (self.work / name).write_bytes((self.args.inputs / name).read_bytes()) + os.chown(self.work / name, self.uid, self.gid) + recipe = json.loads((self.work / 'recipe.json').read_bytes()) + require('account_scope' not in recipe, 'live.connect-scope-outside-contract') + review = json.loads(self.run('review', [self.binary, 'review', '--recipe', self.work / 'recipe.json', '--profile-lock', self.work / 'profile.lock.json'])) + extension = json.loads(self.run('bound-extension', [self.binary, 'bound-extension', '--argument', 'amount', + '--ceiling', '10000', '--window-seconds', '86400', '--max-count', '10', '--sum-limit', '10000', '--partition', 'currency=usd'])) + operation = str(uuid.uuid4()) + normal = {'operator_namespace': 'stripe-platform-refunds', 'operation_id': operation, + 'recipe_digest': review['recipe_digest'], 'payment_intent': self.payment, 'amount': 500, 'currency': 'usd'} + arguments = {'normal': normal, 'above-ratio': {**normal, 'operation_id': operation + '-ratio', 'amount': 1001}, + 'above-grant': {**normal, 'operation_id': operation + '-grant', 'amount': 10001}, + 'wrong-currency': {**normal, 'operation_id': operation + '-currency', 'currency': 'eur'}} + (self.app / 'plan.json').write_bytes(canonical({'configuration': review['verifier_configuration'], + 'extension': extension, 'arguments': arguments})) + os.chown(self.app / 'plan.json', self.app_uid, self.gid) + sdk = json.loads(self.run('installed-consumer-author', self.child('author'), uid=self.app_uid)) + require(sdk['sdk_location'].startswith('/opt/consumer/lib/'), 'live.repository-import') + self.run('install', [self.binary, 'install', '--state-dir', self.work / 'state', '--recipe', self.work / 'recipe.json', + '--profile-lock', self.work / 'profile.lock.json', '--trusted-context', self.app / 'context.cbor', + '--approve-digest', review['recipe_digest'], '--provider', 'stripe', '--alias', 'platform-rehearsal', + '--account-label', platform, '--credential-stdin'], stdin=(self.keys['STRIPE_TEST_RESTRICTED_KEY'] + '\n').encode()) + self.start() + self.run('application-secret-isolation', self.child('isolation'), uid=self.app_uid) + results = {} + for label in ['above-grant', 'above-ratio', 'wrong-currency', 'normal']: + results[label] = json.loads(self.run(label, self.child('submit', label), uid=self.app_uid)) + require(results['above-grant'].get('code') == 'gateway.policy.above-ceiling', 'live.grant-ceiling-not-refused') + require(results['above-ratio'].get('code') == 'gateway.relative-ceiling.above', 'live.ratio-not-refused') + require(results['wrong-currency'].get('outcome') == 'not-entered', 'live.currency-not-refused') + require(results['normal'].get('outcome') == 'observed-by-provider', 'live.refund-not-observed') + echo = results['normal']['evidence']['echo'] + refunds = self.api('GET', '/v1/refunds?' + urllib.parse.urlencode({'payment_intent': self.payment, 'limit': 10}))['data'] + matched = [refund for refund in refunds if refund['amount'] == 500 and refund['metadata'].get('auths_echo') == echo] + require(len(refunds) == 1 and len(matched) == 1 and matched[0]['payment_intent'] == self.payment, + 'live.fresh-refund-read-back-mismatch') + results['proof-replay'] = json.loads(self.run('proof-replay', self.child('submit'), uid=self.app_uid)) + require(results['proof-replay'].get('code') == 'gateway.attempt.replay', 'live.replay-entered') + results['altered-action'] = json.loads(self.run('altered-action', self.child('altered'), uid=self.app_uid)) + require(results['altered-action'].get('outcome') in ['denied', 'indeterminate', 'not-entered'], 'live.altered-action-entered') + support = self.run('support-bundle', [self.binary, 'support-bundle', '--state-dir', self.work / 'state']) + require(json.loads(support)['deployment'] == 'development', 'live.production-claim') + (self.args.out / 'support-bundle.json').write_bytes(support) + self.stop(); self.start() + results['restart-replay'] = json.loads(self.run('restart-replay', self.child('submit'), uid=self.app_uid)) + require(results['restart-replay'].get('code') == 'gateway.attempt.replay', 'live.restart-replay-entered') + self.stop() + return {'schema': 'auths.recipe-qualification-simulation/1', 'simulation': True, 'stable_launch_ready': False, + 'family': 'stripe-platform-refund-v1', 'provider': 'live Stripe test mode; platform account', + 'source_commit': self.args.commit, 'compiled_recipe_sha256': review['recipe_digest'], + 'gateway_sha256': hashlib.sha256(self.binary.read_bytes()).hexdigest(), + 'wheel_sha256': hashlib.sha256(self.args.wheel.read_bytes()).hexdigest(), **sdk, + 'resources': {'platform_account': platform, 'payment_intent': self.payment, 'refund': matched[0]['id']}, + 'store': 'shared-file-v1', 'custody': 'local-file-v1', 'clock': 'development-host-clock', + 'verification_boundary': 'installed SDK and native application socket', 'cases': self.steps, 'results': results, + 'fresh_read_back': {'refund_count_before_cleanup': len(refunds), 'amount_matches': True, 'echo_matches': True}, + 'excluded_claims': ['Connect/connected-account scope', 'protected production qualification', + 'production PostgreSQL/AWS custody', 'complete qualification corpus', 'independent lease/provider-entry counters']} + + def cleanup(self): + try: + self.stop() + finally: + if self.payment: + # Test setup/teardown uses the operator test key, never the app. + refunds = self.api('GET', '/v1/refunds?' + urllib.parse.urlencode({'payment_intent': self.payment, 'limit': 100}))['data'] + total = sum(refund['amount'] for refund in refunds) + if total < 2000: + refund = self.api('POST', '/v1/refunds', {'payment_intent': self.payment, 'amount': 2000 - total, + 'metadata[auths_simulation_cleanup]': 'true'}) + require(refund['status'] == 'succeeded' and refund['payment_intent'] == self.payment, 'live.cleanup-refund-refused') + payment = self.api('GET', '/v1/payment_intents/' + self.payment) + charge = self.api('GET', '/v1/charges/' + payment['latest_charge']) + require(payment['livemode'] is False and charge['livemode'] is False and + charge['refunded'] is True and charge['amount_refunded'] == 2000, 'live.cleanup-read-back-mismatch') + self.payment = None + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--consumer', choices=['author', 'submit', 'altered', 'isolation', 'sign']) + parser.add_argument('--case', default='normal') + parser.add_argument('--consumer-work', type=Path) + parser.add_argument('--consumer-socket', type=Path) + for name in ['package', 'inputs', 'wheel', 'out']: + parser.add_argument('--' + name, type=Path) + parser.add_argument('--commit') + parser.add_argument('--credential-stdin', action='store_true') + args = parser.parse_args() + try: + if args.consumer: + consumer(args); return + operator = Operator(args) + def interrupted(_signal, _frame): + raise Refusal('live.interrupted') + signal.signal(signal.SIGTERM, interrupted); signal.signal(signal.SIGINT, interrupted) + try: + report = operator.exercise() + finally: + operator.cleanup() + report['cleanup'] = {'test_payment_fully_refunded': True, 'stripe_retains_test_payment_and_refund_records': True} + data = json.dumps(report, indent=2).encode(); operator.scan(data) + (args.out / 'report.json').write_bytes(data) + operator.run('sign-published-report', operator.child('sign', work=args.out), uid=0) + print('Live platform Stripe refund rehearsal passed; limits, read-back, replay, isolation, cleanup and signature verified.') + except Refusal as error: + print(str(error), file=sys.stderr); sys.exit(1) + + +if __name__ == '__main__': + main() diff --git a/qualification/simulation/run.py b/qualification/simulation/run.py index f5bfa628b..a6ccbf945 100644 --- a/qualification/simulation/run.py +++ b/qualification/simulation/run.py @@ -14,7 +14,7 @@ import time REPORTS = ( - "stripe-refund-v1.json", + "stripe-platform-refund-v1.json", "airtable-record-update-v1.json", "bootstrap/simulation.json", "provider-signature-verification.json", @@ -114,7 +114,7 @@ def main() -> None: # The second native stage re-reads and cryptographically verifies these # exact files after both family runs complete. They are detached simulation # signatures, with no production root or protected-run authority. - for family in ("stripe-refund-v1", "airtable-record-update-v1"): + for family in ("stripe-platform-refund-v1", "airtable-record-update-v1"): signature = output / f"{family}.attestation.json" if signature.is_symlink() or signature.stat().st_size > 4096: raise SystemExit("invalid simulation signature") From bd5b87f5af18e1782b21411aa4d3a93e531acad3 Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 02:41:39 +0100 Subject: [PATCH 049/108] Refresh gateway closure and document public metadata scan findings --- .gitleaksignore | 10 ++++++++++ docs/PROGRAM_BOARD.md | 2 +- product/runtime/auths-gateway/semantic-closure.json | 2 +- product/runtime/auths-gateway/src/semantic_closure.rs | 2 +- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/.gitleaksignore b/.gitleaksignore index f02eec401..ef57bf711 100644 --- a/.gitleaksignore +++ b/.gitleaksignore @@ -72,3 +72,13 @@ af4791caed6a8cb6fc37313f9cacfe52bc0e2394:product/integrations/auths-stripe/fixtu # generator now names the key "commit" and writes digests as "sha256:". d92064d919b7c2498ce62588ff48a82284f0bcd7:formal/proof-coverage-v1.json:generic-api-key:9 d92064d919b7c2498ce62588ff48a82284f0bcd7:formal/proof-coverage-v1.json:generic-api-key:84 + +# Public metadata in signed development-rehearsal evidence (7 October 2026). +# key_sha256 is hex::encode(AttemptKey), the SHA-256 of public attempt identity; +# support.rs never exports provider credentials. Preserve the exact signed-run +# support bytes; these exceptions cover only the named historical fingerprints. +8b6f96e7e43dacf5b7f237cfc015f84a513a2bd1:qualification/simulation/evidence/airtable-live-2026-10-07/support-bundle.json:generic-api-key:1 +3e9704b5d4d12bc654fc48de9b03ab6adb9fcb41:qualification/simulation/evidence/stripe-platform-live-2026-10-07/support-bundle.json:generic-api-key:1 +# Ordinary progress prose triggered the generic key rule. The current prose +# avoids the ambiguous wording; no credential occurred in the historical line. +3e9704b5d4d12bc654fc48de9b03ab6adb9fcb41:docs/PROGRAM_BOARD.md:generic-api-key:477 diff --git a/docs/PROGRAM_BOARD.md b/docs/PROGRAM_BOARD.md index 58cdfb9c2..a21acd56f 100644 --- a/docs/PROGRAM_BOARD.md +++ b/docs/PROGRAM_BOARD.md @@ -474,7 +474,7 @@ Stripe test to platform-account refunds. The agent generated a separate `stripe-platform-refund-v1` profile/recipe with no connected-account argument or scope header, updated AP-SPEC-066 §7.6 and ADR 0014, and passed the real Stripe journey using the same downloaded gateway and installed `0.0.1rc1` wheel. -Restricted-key guards, ceilings/partition refusals, fresh refund value/echo +Credential guards, limit refusals, fresh refund value/echo read-back, proof/altered-action/restart refusals, secret isolation, support scanning, full test-payment cleanup and the published report signature all passed. Evidence is retained under diff --git a/product/runtime/auths-gateway/semantic-closure.json b/product/runtime/auths-gateway/semantic-closure.json index 27ee3f7be..16f9b8dfe 100644 --- a/product/runtime/auths-gateway/semantic-closure.json +++ b/product/runtime/auths-gateway/semantic-closure.json @@ -1 +1 @@ -{"files":[{"path":"Cargo.lock","sha256":"0e75e2fdef44e79e57797ac6661295ae58ddb8de4a1990a6fd22ce6c54f78604"},{"path":"Cargo.toml","sha256":"6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24"},{"path":"core/adapters/auths-did-keri/Cargo.toml","sha256":"86ba3e3f9a0a70d970568bfb3113b7ba7bbdd81c3eebbb52743dd574a0c0ecaa"},{"path":"core/adapters/auths-did-keri/src/lib.rs","sha256":"a75674842f8a7142004369ccd206ab43e476459293f0ff4bed4d4e659031b3e3"},{"path":"core/adapters/auths-did-key/Cargo.toml","sha256":"d5a3ae07ecde83f91eed4c3785051dd0f44eab6c891754f3309b6b40596707d7"},{"path":"core/adapters/auths-did-key/src/lib.rs","sha256":"b76a3f4528a725df53cfa9242e6e414e1d26caa48468aaed497e28b121f4497c"},{"path":"core/adapters/auths-raw-key/Cargo.toml","sha256":"f49616bc18c19e6aaa7e6a02ccebcdb9f5c1422c1278ef9869e0dbf22ceda7be"},{"path":"core/adapters/auths-raw-key/src/lib.rs","sha256":"45eec1b295dac3bed65cd79c942870b926b06b3f5d38eaebaeb6140ac69315fa"},{"path":"core/crates/auths-algebra-kernel/Cargo.toml","sha256":"0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba"},{"path":"core/crates/auths-algebra-kernel/src/generated.rs","sha256":"ae4bcbef42a408c7ffa0c6a74a42f7de177a6f14479e51d205acf830bda05960"},{"path":"core/crates/auths-algebra-kernel/src/lib.rs","sha256":"6654667eeb9b353d6648954c9fd2e8838462a82ce6b2803eb49e1366892c68c6"},{"path":"core/crates/auths-assurance/Cargo.toml","sha256":"afcb12a97ddd09d7a264b9ecd3fcaefc865ff2c9b4539ee85b00883420ba333a"},{"path":"core/crates/auths-assurance/src/lib.rs","sha256":"0fb2ec844d674b25a9e20b1601452c89c2454901fa506adfa9bb38ef9a7fa213"},{"path":"core/crates/auths-author/Cargo.toml","sha256":"1e6f0e3bc079ddb558decf0db26b291c6e72fc47327b6df1b7650d41689b215f"},{"path":"core/crates/auths-author/src/lib.rs","sha256":"e14475f2f49715a1869d5fa6b11ff1fbb72497e39097e09f833b0bae7e5b3f2b"},{"path":"core/crates/auths-author/src/observations.rs","sha256":"dda7d6bfa6f4bd7e95a480ca283c2c0e996f69c5c15cb0c7197af328131a7066"},{"path":"core/crates/auths-authority/Cargo.toml","sha256":"4f68212938029f79ebd857b4f3038494eb85d0163d49f07e51376715cf959815"},{"path":"core/crates/auths-authority/src/lib.rs","sha256":"da88d5194de4e17449e69972c0fb042afa3c39798a8f570f30771e77c384f1eb"},{"path":"core/crates/auths-codec/Cargo.toml","sha256":"e20e51826e17814effd9d8925d18d5fbdd6c0d37bf50231e743ec2611314722c"},{"path":"core/crates/auths-codec/src/approval.rs","sha256":"fbff43bf4d57f69f8b7738a8647751cde75c5a932dee65d924a1fe9c7202f91f"},{"path":"core/crates/auths-codec/src/bounded_policy.rs","sha256":"d21f6728be2d8a04b6d94921f2b683f7e61cbb42e0ac6866f1c88a49caa534c3"},{"path":"core/crates/auths-codec/src/decode.rs","sha256":"ba2999584cdf53b1b517ecb9c7ea50d39efee17c666a9a38e2ad1ac94379f778"},{"path":"core/crates/auths-codec/src/encode.rs","sha256":"8491192053e2e15d62b4d2a491de22405b7487ead69ab6f6bca40669ce7ca5f7"},{"path":"core/crates/auths-codec/src/error.rs","sha256":"fecb0737c16deb42d859f1dc7727c698438d9ac12064fd99e0024629642c390c"},{"path":"core/crates/auths-codec/src/hash.rs","sha256":"f88e111f1dbb2cef6b7b5e9c948cb45ff92e366710c8a5f5c636138aa748479e"},{"path":"core/crates/auths-codec/src/lib.rs","sha256":"3b0e5c94c6f34f750b88a9333e1d5c8145746d845d3a23e0d2f61807cf592ea7"},{"path":"core/crates/auths-codec/src/observation.rs","sha256":"38328b0c71ff97a4196eeade8b4faa889527ff1f80bb168468bcd49082a3987e"},{"path":"core/crates/auths-composition/Cargo.toml","sha256":"331e13025eb82588b5269ed3975929eb41c823d588c49e4c296273d85c6fe80e"},{"path":"core/crates/auths-composition/src/lib.rs","sha256":"e42e3b0b6a9985b73c533aeb23799c638979aa27a9ce7d0f10a8d60340570fb1"},{"path":"core/crates/auths-model/Cargo.toml","sha256":"565c15302b0cc9270db1e28efa3862804846850ba933cc17aea8abcec4a65987"},{"path":"core/crates/auths-model/src/approval.rs","sha256":"54cf44a9ef747ec21546a4086aecfb130bc7803b0d646430e6082df51e6e305f"},{"path":"core/crates/auths-model/src/bounded.rs","sha256":"f90496abc0a06c028b4d850af6ddab7d850bfafeaa3d042f1b1246a41d8bbbc9"},{"path":"core/crates/auths-model/src/bounded_policy.rs","sha256":"306a8f049cc7cfc7635fe0e4de47eb7813eed63d3c14c3be2b51586aa4eea450"},{"path":"core/crates/auths-model/src/lib.rs","sha256":"e7cfe6bb9574c6b016aa63e70658c31e0b90903ec6479a49f4a2ceb64f5bad97"},{"path":"core/crates/auths-model/src/observation.rs","sha256":"b3ed3e3cc090afca2896a7d3de7988afccc1ee1ea0ebd91b51a8bc0f20ad8dbb"},{"path":"core/crates/auths-multikey/Cargo.toml","sha256":"858756c1197befcada06134742bffe8d58cf674cadd6c046bf710570e96efaf2"},{"path":"core/crates/auths-multikey/src/lib.rs","sha256":"f5177fffb11e40eeaaa665ba886c541fc1f24d5eacdd6983fb03dc20148733f0"},{"path":"core/crates/auths-ports/Cargo.toml","sha256":"596a9b0f5af3717c16a6d13f7054d8a106bcd9f01f5f72c2235dd2afcf0ab16c"},{"path":"core/crates/auths-ports/src/binding.rs","sha256":"a16c012d40aa4249e3ec54372b9611006d0bfe8c7dc3c741911c2194ad17736d"},{"path":"core/crates/auths-ports/src/diagnostics.rs","sha256":"aa596572503b5a65a918bb2ff38281c144ff53821ee914e9325c852828d852df"},{"path":"core/crates/auths-ports/src/lib.rs","sha256":"8da1debf86f9532df0660155d04298beb1ba3a1204508f8586e2e67cd2fb3449"},{"path":"core/crates/auths-ports/src/path.rs","sha256":"b68fc547b4e4d97a60cbbc1cc1939fc6b34a8233b81f840bd396914a707e3ea1"},{"path":"core/crates/auths-raw-key-core/Cargo.toml","sha256":"98c0bc8527a537512e43a74dd6ba9658c6f0cdc16610cf938e3f9b43785d836d"},{"path":"core/crates/auths-raw-key-core/src/lib.rs","sha256":"98c0500c41697aae28708ad0bf970b9a97583d96a3d2c18d23e7fa351e0f7d12"},{"path":"core/crates/auths-registries/Cargo.toml","sha256":"590e49e58b0622d9d6274fea46796dcdb07dec9550eff295cce6a6427ffa51e2"},{"path":"core/crates/auths-registries/src/lib.rs","sha256":"450d3886d85ee333b7e046317fb5b47cde62483d5f3e41d46265e2caf4c373ec"},{"path":"core/crates/auths-registries/src/template.rs","sha256":"1224039dd2b3ce6fa8357613d8cafbae40400493da7176da202b9ade62fa05e4"},{"path":"core/crates/auths-signature-core/Cargo.toml","sha256":"6bee2230eb30af1be0bd5c2d57bd3e1903497a70028d47290d4ac6e9e0e8bca0"},{"path":"core/crates/auths-signature-core/src/lib.rs","sha256":"6e3f9311ded5e49ea50d445eb21e6d8fa12442aa4362a73e0cb6fda15b7cd865"},{"path":"core/crates/auths-signature/Cargo.toml","sha256":"7f7b5682466ba439d8c59579022cb61068cad9fb4bd2d73e1cc21327c902b450"},{"path":"core/crates/auths-signature/src/lib.rs","sha256":"b3d9ac4cc3ba0797b9e1c09f2d6ac05089b25dac4e285a5af28c0165b33d925b"},{"path":"core/crates/auths-verifier/Cargo.toml","sha256":"c43358e06a33324b41a8b93e5cc7279c55f7d21f1f6cfaa539a3fc7b4c27a38f"},{"path":"core/crates/auths-verifier/src/approval.rs","sha256":"c3cae6a49e169051eb555bb092b1069a4d422516d6a2114623a89e5f31ff923f"},{"path":"core/crates/auths-verifier/src/causal.rs","sha256":"9635230f33b13a263573d319ac8a1976addbcc07677514a43e3c7bf28dc04587"},{"path":"core/crates/auths-verifier/src/lib.rs","sha256":"f22dec38dfa47ced8da4f605390da8453273bee1da010f57fd1fdfcb10e0b389"},{"path":"core/crates/auths-verifier/src/observation.rs","sha256":"0bb07f06a0f9524c88427df1c972b1de8ba038a9eeeb15d3134c25125ae84b1e"},{"path":"core/crates/auths-verifier/src/trace.rs","sha256":"2213d72023a1d9e0413a2cf2c51c3dad9e04775d86033a0caaa9d29a8f0036f8"},{"path":"exchange/crates/auths-proof-exchange-model/Cargo.toml","sha256":"34b2db64f93a288e942b5a3918d28cdcbef906e0dc9074ce848018d3d5f7a1fa"},{"path":"exchange/crates/auths-proof-exchange-model/src/lib.rs","sha256":"49fac5aff2339d3a57c41cb8bb2a82852538e8f77ecc4b157c88e264ff31fb55"},{"path":"exchange/crates/auths-proof-exchange-port/Cargo.toml","sha256":"7ff660f1b7579dc570c791090aeb450404fbbf44c92781e289f5ccdde746d739"},{"path":"exchange/crates/auths-proof-exchange-port/src/lib.rs","sha256":"b408fb40c6432edc1facb3d8b3e9433a033f8dc73fe2e0ba5a88c972ca675021"},{"path":"product/config/auths-config/Cargo.toml","sha256":"e4b568ab9f6d84f7d7e6d66443fe825f360db9c27bc7c31d6ddc0647ba3ab304"},{"path":"product/config/auths-config/src/lib.rs","sha256":"fecf00ea65cef9018fda9af2063326d7065b869266d0d9e73a4f06816f1102cc"},{"path":"product/errors/auths-errors/Cargo.toml","sha256":"3b3a199b6460ba75bda84475bb5accd35e1485448a3981038db85bf4772dd350"},{"path":"product/errors/auths-errors/src/lib.rs","sha256":"7feeb9069fa4003f94f1f07c1c94619cf1c883e0dbaaf2187f04d0f742264bdd"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/Cargo.toml","sha256":"716f1f2a117d6d69d8effe9ee9057e24ba3502f20af6a602b06facb638cdabed"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/api.rs","sha256":"9ea61dd7ddd93282b073b98e453e6b75b26dc49689c04e9782435d06a3a09e48"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/clock.rs","sha256":"73f0a6e0f5903883329fa6683f5888288f759512ac69e5c87efd2b6b87f7d79f"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/http.rs","sha256":"14c1fce14e24c984b2a275563a29b6326fb08367922b6e8d37ba38b9cb81aa2b"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/identity.rs","sha256":"186de11230c8b33375951c4368609f8976bf9795f171af3fd7fac26207a94361"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs","sha256":"0b4617d044f5254a5ab22f5a2578f91cc025206a8c1845be39c1c56dcdf7a5df"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/names.rs","sha256":"41bb23572d6002e23ee103d6fe70ecd68764861c6f2e48a1c53af998270a4afa"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs","sha256":"39fed883f4802e68d3b41a68fea0aba0737810996b33d13577de70faba004c29"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/store.rs","sha256":"fc60ee9c49b2f4f063c449b4c78100c5c4872779e94ca168f796603b380ef6e4"},{"path":"product/integrations/auths-custody/Cargo.toml","sha256":"1e14034185ad1ec24a977fd5f41d0abee219606245c046ce2a82287fadef448b"},{"path":"product/integrations/auths-custody/src/conformance.rs","sha256":"8ed1afd58f18fc6becc268908aa6419c9aa404c79da0197963eb2599df44acf6"},{"path":"product/integrations/auths-custody/src/key.rs","sha256":"70cbb0fd21b6f5652157845a22c35be2d0f6c05b3d138fc4b9bb6dbdc3d81c40"},{"path":"product/integrations/auths-custody/src/lib.rs","sha256":"8ee593c1f59b0fd2126bdda9138026f5bc531beb64d4489a99785842e7b98b43"},{"path":"product/operations/auths-operations/Cargo.toml","sha256":"73dde1e914ba5e1386f8d49c0d730423cc72ae77ec44c6554a6a75cc8e8922b1"},{"path":"product/operations/auths-operations/src/explanation.rs","sha256":"b4a39bcbd5712cb9e735ee7deeb281f3fa6af5ddca973735bf3d87dce427ef11"},{"path":"product/operations/auths-operations/src/lib.rs","sha256":"3f401a56555113b98f57bca172a2660eaecedf76247b83a3fdbb089c133a29cd"},{"path":"product/operations/auths-operations/src/render/json.rs","sha256":"2ae042639960afee123730e945d373bc5dda1d2b3af20ae16c939a7e99b9e418"},{"path":"product/operations/auths-operations/src/render/mod.rs","sha256":"b3b7f6fe473f49227ace5a68bfc3d8dc14b5db8dd9888fd9e207070337b1b8bf"},{"path":"product/operations/auths-operations/src/render/text.rs","sha256":"f216cf3bdb00e264523271b16e7059535ac6b1aabf271cebd7935af155e4bfec"},{"path":"product/policy/auths-bounded-policy/Cargo.toml","sha256":"babd5d200923137ead71d8c2528f847cea323ce98da942a1320b054436612c47"},{"path":"product/policy/auths-bounded-policy/src/arithmetic.rs","sha256":"75e43c5d4eab8d1f71c1daf53839f5f9fe45a400afc1f63a30c6f55ce3632627"},{"path":"product/policy/auths-bounded-policy/src/commitment.rs","sha256":"c5706f2d583454e1a7f570f7ada138d4d864bef0205dfae7c1296774f396bb3f"},{"path":"product/policy/auths-bounded-policy/src/eligibility.rs","sha256":"c9acdfb793074e687fc36efad506be27dbd99ffbf40387bc66c8de39ef238432"},{"path":"product/policy/auths-bounded-policy/src/identifier.rs","sha256":"0006a32bae9eb16c4178cf797df418d2b0a781f2bc6474b741dc1a908141831c"},{"path":"product/policy/auths-bounded-policy/src/kernel.rs","sha256":"99187c28b161ac70bee1afed60711f7f645adb4d1671a01863f9849b369811d5"},{"path":"product/policy/auths-bounded-policy/src/lib.rs","sha256":"76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c"},{"path":"product/policy/auths-bounded-policy/src/receipt.rs","sha256":"3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad"},{"path":"product/policy/auths-bounded-policy/src/registry.rs","sha256":"4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0"},{"path":"product/profiles/auths-profile-api/Cargo.toml","sha256":"7ae85761f58625b5d678f961fd052eebf3e000ef565c7312e3ac857763c0017f"},{"path":"product/profiles/auths-profile-api/src/lib.rs","sha256":"a194b82b20bf8aa864c2334ef6c6aec30b2154ded972862252d5dcefa488ab95"},{"path":"product/profiles/auths-profile-mcp/Cargo.toml","sha256":"db264fc25242f7b7e4133cbe5782545b3107b406c87168ae072683cfb59eac66"},{"path":"product/profiles/auths-profile-mcp/src/arguments.rs","sha256":"a5de696586d507e2aee4a49fee99ef1ef4c51a2e46603f8838f1af6d9009833f"},{"path":"product/profiles/auths-profile-mcp/src/lib.rs","sha256":"d0f8b733a09ef8408336cdebc8948d6a5861012ce6878598b11be7084dfd4280"},{"path":"product/profiles/auths-profile-mcp/src/session.rs","sha256":"166c281fa66333388e4760d6098dad02d3359e1d5de4b8f93312c014f97abb03"},{"path":"product/qualification/auths-recipe-qualification/Cargo.toml","sha256":"b7b15b30b9a3d96d4f089d514266d3a892de6608d30707aa44be31cca89ca9fe"},{"path":"product/qualification/auths-recipe-qualification/src/canonical.rs","sha256":"30a9b50777f0dcb4b606abfee2467d5a975d9f6ad941ab6c13ca3df5b359f667"},{"path":"product/qualification/auths-recipe-qualification/src/closure.rs","sha256":"0ad6aee9bd981e2863fa725f209ec84031db2ff12f4c7ac3aaf5120f0bb86039"},{"path":"product/qualification/auths-recipe-qualification/src/error.rs","sha256":"52d5cf720a1e4579008fdda90a3ac2c31f0b8db57985f121f65e54b4da2b7dd1"},{"path":"product/qualification/auths-recipe-qualification/src/evidence.rs","sha256":"ba45a7409d67a8af26ab811af306412014557477a101ab2a8eb0faf8f2bd4b91"},{"path":"product/qualification/auths-recipe-qualification/src/ids.rs","sha256":"e81a906d571497ab2da753e1532d4443706410e0b75fdd59a7d2d788c7aec403"},{"path":"product/qualification/auths-recipe-qualification/src/launch.rs","sha256":"41f2e2de90e1e7d6440a66eda3eb9bea8d5e0741bc232305a76a363ab5f813c1"},{"path":"product/qualification/auths-recipe-qualification/src/lib.rs","sha256":"5c9cff04c8960df805a2f7656cf5e74932798e0db7648341e96ae7073a592404"},{"path":"product/qualification/auths-recipe-qualification/src/model.rs","sha256":"3484eb0ec287b23d4682ade7b1b0f8d1335985b3fb180f06fc28716076957d5f"},{"path":"product/qualification/auths-recipe-qualification/src/release.rs","sha256":"d816b53e2275e902c750ad03803061844e259e28560ab2d1c77e8a43981a4d6a"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/mod.rs","sha256":"7f15b68e05a04f202bcb1fb80de1d9a9a4fda8bfd6af2cd4e5c660fc75d96fe5"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/schemas.rs","sha256":"c59feec2805621f341a90f81fc005e2c12f7a70f9d264fdeacccb2be4fe1c046"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/verification.rs","sha256":"6a6b5834c5dae10af1ba8939b2deae43b85db71544dc8f077ff63b7fe68ac8a8"},{"path":"product/qualification/auths-recipe-qualification/src/verify.rs","sha256":"a470a9b98c04dc8d5dabe4d3dc8ed4e7a3ceb1cde035944a0714462bbf37d56d"},{"path":"product/receipts/auths-receipts/Cargo.toml","sha256":"6001fa1375899953aafcb07c23a6da0c8f57ea7ec08bb9c950b12a60a8cc6f0f"},{"path":"product/receipts/auths-receipts/src/disclosure.rs","sha256":"ba9ed439be0a320c8a01f5b6e9b51361c1a37e076947490d8e4a484ba6bb119c"},{"path":"product/receipts/auths-receipts/src/lib.rs","sha256":"547a57c4160256719cafb7d0ab972d9fc80b0da14fbbce4148c70c414070ff36"},{"path":"product/runtime/auths-connections/Cargo.toml","sha256":"babeb6e1dda3dfb66291713ce1e43dce5c349833d0b50ea4dccbf986030026b2"},{"path":"product/runtime/auths-connections/src/credential.rs","sha256":"82921413bb053f0f6c7931fbd4e6a86c8cc1d8c6b51debd9c2cef33a8d5b1c51"},{"path":"product/runtime/auths-connections/src/kernel.rs","sha256":"a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8"},{"path":"product/runtime/auths-connections/src/lib.rs","sha256":"79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22"},{"path":"product/runtime/auths-connections/src/model.rs","sha256":"de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77"},{"path":"product/runtime/auths-connections/src/registry.rs","sha256":"e57640e003e72ad3235c567c2bb944a262bd64e673f023b62ea091094cc7e946"},{"path":"product/runtime/auths-gateway-kernel/Cargo.toml","sha256":"34f864e67656af4ac7e5c7a347a23f01fc8ab31365b8e23c0ef474483b14a183"},{"path":"product/runtime/auths-gateway-kernel/src/construct.rs","sha256":"e9d65744bae273d65face4285e5d2da75c06a92ab48f7b8333d496604e31c63c"},{"path":"product/runtime/auths-gateway-kernel/src/lib.rs","sha256":"cfda6f8453426564c085475f183b6f790b438768a19668f1b65d33ba59dc8632"},{"path":"product/runtime/auths-gateway-kernel/src/order.rs","sha256":"e0045f877c4b7fe3860c291039853885064ddcdebba7c9b345ab65e81e646dda"},{"path":"product/runtime/auths-gateway-kernel/src/outcome.rs","sha256":"e9785b1afe70788c89b51b18655bcd5acff7b0c8e3d12fb79c6f05a202e67e6b"},{"path":"product/runtime/auths-gateway-kernel/src/ratio.rs","sha256":"7ace22264812e6fc1ef3a62afee402cf43494bb71ae0d3de219ad1b39d690bcb"},{"path":"product/runtime/auths-gateway-kernel/src/recovery.rs","sha256":"9f46dcd1685ab6e4d1ba04a3fc286a9f3afee8fb47829be1fbc670a7926a2dc6"},{"path":"product/runtime/auths-gateway-kernel/src/transition.rs","sha256":"cefb8f01d915880f6921f2501ff881ad94b9de61072c34d9cd19220992f97374"},{"path":"product/runtime/auths-gateway/Cargo.toml","sha256":"00b28be86921dcdc0ad90cce0c62c2961cafefe96ea6c2edf0e926c3d405ccad"},{"path":"product/runtime/auths-gateway/src/admin.rs","sha256":"2d5cc67afac42fbd15f36e2d1693cd1b20cedacf775040dce6ffe04ccc94c9ea"},{"path":"product/runtime/auths-gateway/src/app.rs","sha256":"6f80f63833ea0815bb44fbf3b0cc54624a08e9fb578b035819f2980dc04e8256"},{"path":"product/runtime/auths-gateway/src/audit.rs","sha256":"0edb2037eb7b5d6f13acfce85c54f62a82bf7fdd31bc7e626c4fec183cef61dd"},{"path":"product/runtime/auths-gateway/src/audit_tests.rs","sha256":"990969384a52d75bc2489d9d412a9e7dd814bca1c8f65c701d6205fae62a15d5"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway-harness.rs","sha256":"12b0c24d36b2e6a3be392d3c081a783b355fdd67dc5b54bacc0410e803116b8c"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway.rs","sha256":"2f33a1da5dd54947ee1664795f90b3f07a11bb9ee184774bf470b78b03600f0c"},{"path":"product/runtime/auths-gateway/src/binding.rs","sha256":"663b0ce878319511aa7d05722ab4ab2fa9be18817884ffb2ee9f131ff1e382d1"},{"path":"product/runtime/auths-gateway/src/bounds.rs","sha256":"9cfa0eae4973e5e047a198360b22f041708fa20276b0b90c2ec440f06915d64b"},{"path":"product/runtime/auths-gateway/src/bounds_aggregate_tests.rs","sha256":"ab34f227b7c8692ba1da88ccb32bb3687a66adf8353d8282fae905d4a88eb612"},{"path":"product/runtime/auths-gateway/src/bounds_tests.rs","sha256":"74136bc570da7b9338b5a1a1ed9d3fd892c55135160964f9d3ac0e2cf5741375"},{"path":"product/runtime/auths-gateway/src/connection.rs","sha256":"7b5d049c258a26ed1c93ecf860f51d051a8a65f9b93554af0b1ea93862398ec9"},{"path":"product/runtime/auths-gateway/src/credential_journal.rs","sha256":"7297fccaee5cd8622928e8e0a42bba50da7941970a6f682ecd300c41ee6509da"},{"path":"product/runtime/auths-gateway/src/echo_verify.rs","sha256":"6d453051665f823abd7354d5c50031d9524cf47d6092d2f09080ae814e3b9575"},{"path":"product/runtime/auths-gateway/src/engine.rs","sha256":"f1052aaef43e441b9e0befa3f8ad1e2fd5279a27cb9d63aac0cf9dfdbe85a052"},{"path":"product/runtime/auths-gateway/src/fuzzing.rs","sha256":"ed3b0028487eb546a3b0a91d115aa8f18bcea324b61620bfe8e35a9e6ab18758"},{"path":"product/runtime/auths-gateway/src/generation_floor.rs","sha256":"fe1510ec96ce0f67e9a78edbfa94b33eb7df64c0ac4d0a67901124dcd0164777"},{"path":"product/runtime/auths-gateway/src/harness.rs","sha256":"c87e479f3eb281960f6c9c80d43c7560d7ccb654b0154ec823d3fcec4884ac05"},{"path":"product/runtime/auths-gateway/src/lib.rs","sha256":"a1f51b76524a89842720b4fda58b2293d4bc82b41c912d5a462261603c593cea"},{"path":"product/runtime/auths-gateway/src/listener.rs","sha256":"aa08239bcbc1fcb55e8a212fbdf6a84f12985b0d436dcb51dc58b06e59e435f2"},{"path":"product/runtime/auths-gateway/src/observed_tests.rs","sha256":"a22be071695f89ca2578a4d82fd80d9cb82289213c9bdb8f0470f6b2dc3d9201"},{"path":"product/runtime/auths-gateway/src/observer.rs","sha256":"562ffcaea071c3856e0708dc2fe33516917e145d2438aabb75af0a2b6ba01046"},{"path":"product/runtime/auths-gateway/src/onboarding.rs","sha256":"0dfd7d67e7f02f18a28d1c86ca1b7751d7463f5efcdbe3825de0ad8cbccb3891"},{"path":"product/runtime/auths-gateway/src/operator.rs","sha256":"c3c36954a3e86723df035b47f43b85fc8ab3a6292983522b6258d5c6b4e6c4e4"},{"path":"product/runtime/auths-gateway/src/pending_vectors/attempts.rs","sha256":"47ef3c8cb1c5504d47ae9a0088705ce6715fe86bac1671a34a56fb38a64d0dd3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/bounds.rs","sha256":"e612217307e1da5b0eb5ee6582a7458bb064b8aa8a529fc6555b1b334127ab68"},{"path":"product/runtime/auths-gateway/src/pending_vectors/codes.rs","sha256":"e00670a5ef24eb856cc2c6dcda8e5a263842f55c76bb939c0c27bd9df37e5522"},{"path":"product/runtime/auths-gateway/src/pending_vectors/keys.rs","sha256":"f84c56f2ea9cb34b2b79c72d13fbf2c6585010ec1ed450af58a78c80c1ea1edd"},{"path":"product/runtime/auths-gateway/src/pending_vectors/mod.rs","sha256":"5de8340f0ef71a0b57a09e323fefe473d3160c6ae952b9ba46f714825fbacafc"},{"path":"product/runtime/auths-gateway/src/pending_vectors/outcomes.rs","sha256":"8ec07b9511b48913af36ac999d2aa0e82924289f6acb23ddaeb9f00f99815166"},{"path":"product/runtime/auths-gateway/src/pending_vectors/production.rs","sha256":"f574cabfa4687a4fc846b8f6a234b68ec53b876aed548b11445729cac1a55ede"},{"path":"product/runtime/auths-gateway/src/pending_vectors/recipes.rs","sha256":"51693208270231c25c3aef2a32151d5962114c71e86b88cb9df83181c7af83d9"},{"path":"product/runtime/auths-gateway/src/pre_entry.rs","sha256":"06ea78ca140468bfaba17d9ab04912ad68673954c3203c98fed28272ff2a00c0"},{"path":"product/runtime/auths-gateway/src/property_tests.rs","sha256":"939c081e2e154aaf10186754044bdd65608932c899b970a04a71d0afaa999a93"},{"path":"product/runtime/auths-gateway/src/qualification.rs","sha256":"06b49d3fc2ad4383f9e23beefa96033f1fd6e415e043878327583451a53086cc"},{"path":"product/runtime/auths-gateway/src/qualification_simulation.rs","sha256":"7559fc0faec69d41cba099e537e8ea0b228b34c7fa60e87ebe3f0625bc4921bb"},{"path":"product/runtime/auths-gateway/src/qualification_tests.rs","sha256":"4c1f5083e9258e3068781487a421379091647bbf58e2d643fecc20af726d1e7f"},{"path":"product/runtime/auths-gateway/src/quorum_tests.rs","sha256":"a78380b019104d688c11a4410082c7e08ded3106aab099954c4f8a1b4ae0fd89"},{"path":"product/runtime/auths-gateway/src/readiness.rs","sha256":"911c3f11892f94641574375e2da4c671c802738f71082f12c39832331052d43d"},{"path":"product/runtime/auths-gateway/src/recipe.rs","sha256":"fecf9af67e7afc48d080e9f8f55f8ce28e49d0e08988717a27908bbda461d6b6"},{"path":"product/runtime/auths-gateway/src/recipe/lower.rs","sha256":"8088b8751ed831dbb48247af953c6290ac95e2a438ccd5bd65eff54be06a1fd1"},{"path":"product/runtime/auths-gateway/src/recipe/review.rs","sha256":"c3eb7d9fdd98dacf52750b14b67ad7b7faaecbbdeafff1e0b049f67d0a2d0139"},{"path":"product/runtime/auths-gateway/src/recipe/runtime.rs","sha256":"c286f0d15f974402822c0810d8e97f98411dc1c557755cc23e540d85e2bb42d9"},{"path":"product/runtime/auths-gateway/src/recipe/source.rs","sha256":"1af50298fb1461e1b24cbdf560d43124d6b1c4c529586c911b1c4797214a69ff"},{"path":"product/runtime/auths-gateway/src/recipe/tests.rs","sha256":"aac551a2481bbc60864c64079bc667dcb232e45a0f41a04073ed84ab5dbe1fce"},{"path":"product/runtime/auths-gateway/src/recipe/validate.rs","sha256":"3711b17605cb7b0d639bc1b180449231f5882a306cab20e2c7782155cc63b0d4"},{"path":"product/runtime/auths-gateway/src/scenario_tests.rs","sha256":"67915828ecfe2be0afadb5525277ab205f91172edc90852ec7b77c63b2d17fdc"},{"path":"product/runtime/auths-gateway/src/separation.rs","sha256":"be9306848ca5d801767cf6aa14247c8618312ef0e202f00ce0c24c4844491061"},{"path":"product/runtime/auths-gateway/src/simulation_attestation.rs","sha256":"b5210599a59e62335bebc94f2232f7178c867261dd633a2cef263c3a7bca08dc"},{"path":"product/runtime/auths-gateway/src/store.rs","sha256":"1e5288345c2cb1421aeda277b3158d07607404b0ec46943222ac107b63dcbb46"},{"path":"product/runtime/auths-gateway/src/store_testkit.rs","sha256":"88d82fee42f1b8ef521e8deef0216e938ebeaad822eb2f5020e70b89d145ea70"},{"path":"product/runtime/auths-gateway/src/submit.rs","sha256":"c78dbbba7c45b443febf655056c5edcd635e77be7b21c5b2c318097502415ffe"},{"path":"product/runtime/auths-gateway/src/support.rs","sha256":"9fd979029793a22b15d9776a7fc172476fd7c126a80d4080c65d720845becbcb"},{"path":"product/runtime/auths-gateway/src/transport.rs","sha256":"be2c6dc75b8daec110bf8749fedc3823f6067d40b999aa3eb21126896a97d3ad"},{"path":"product/runtime/auths-kernel-runtime/Cargo.toml","sha256":"926bcd0053e5edd703be8f0027ad009e2982db013c8174c1366edbf38b48087d"},{"path":"product/runtime/auths-kernel-runtime/src/lib.rs","sha256":"7108faae9ca4bc32dc093ddaf885ac8f74f3c9b8d317b7c7d0ed00d1d0ab5972"},{"path":"product/runtime/auths-lifecycle/Cargo.toml","sha256":"c5053c705f8d5554b44e432fe75287a2faf11d644e5a2552e45ad6cd94176af5"},{"path":"product/runtime/auths-lifecycle/src/codec.rs","sha256":"51c4b746749150e8bfcd8ff972b3f6c1ef40bec15583448ec1b471d9ad737dc0"},{"path":"product/runtime/auths-lifecycle/src/digest.rs","sha256":"55282cd7d8aba37713c2dcb5357c9877819edb72a30eadefb860d28d7d3a3eb7"},{"path":"product/runtime/auths-lifecycle/src/identifier.rs","sha256":"31620e8c16de68d3d2d3b84d6353c1a5b9d4151d8247f91fa389b906a8e660f1"},{"path":"product/runtime/auths-lifecycle/src/kernel.rs","sha256":"2abb8c094b36d35b364e74d78091d14c5d6f3d1eb6552cca3b5538dbd017ce23"},{"path":"product/runtime/auths-lifecycle/src/lib.rs","sha256":"afe5a345cd309b5a4f08ffba3170a6d7f16ff914892b3f2006d5208ed24ec736"},{"path":"product/runtime/auths-lifecycle/src/model.rs","sha256":"1af12bbeeeaa65ec02ddcebd7d2c8c92ec1e339fa40ae85b45ab9b01a722a4fa"},{"path":"product/runtime/auths-lifecycle/src/operation.rs","sha256":"78e6d05fcf5d7ea4f148032a3fa26fdfcab77eb346019effe927b08e0d64d732"},{"path":"product/runtime/auths-lifecycle/src/registry.rs","sha256":"53495fe6f7a77422593a41623e28716f1c140dcc1e00f87f6b0ffbfb93a5ef90"},{"path":"product/runtime/auths-lifecycle/src/sealed.rs","sha256":"2e0c03b5813c926c159598bb7890d1523825edbe57cd687d42a5dfb3374a0c19"},{"path":"product/runtime/auths-lifecycle/src/test_support.rs","sha256":"221d9a5c5ef8e1f9f8fd66927484eaf813571d0568470278ecd8fa08a5eec8cd"},{"path":"product/runtime/auths-lifecycle/src/transition.rs","sha256":"011805a28efdd541f44ccea54dd0e34a1e58f4004447ee58013703b4fb6b2822"},{"path":"product/runtime/auths-runtime/Cargo.toml","sha256":"dd29d80a8b4bb56c869f036a6c9998f6e6d1c0383ac5dc03fa42b24abe2a7ff7"},{"path":"product/runtime/auths-runtime/src/lib.rs","sha256":"132ca03d58c14905d3a822a4972f42a22a5ad33a45f2ba9ca44f3a57d810b4b0"},{"path":"product/runtime/auths-runtime/src/production.rs","sha256":"fd4eff4270c571c10fcff6cf27df28961ebf074de8a1a028f500fda1ca376820"},{"path":"product/sdk/auths-approval-quorum/Cargo.toml","sha256":"df904971fca87a24194c5816738a331588fe8f164acb5d70839a35dca5f57114"},{"path":"product/sdk/auths-approval-quorum/src/lib.rs","sha256":"72e4086088a1c0912e4e1a9e980f26a5c280bf5ab16ea39c9f0f58d5096ac2ce"},{"path":"product/sdk/auths-approval-quorum/src/remote.rs","sha256":"9fa029c7c63003adf260f8aec55160c545681c60c1bace0d934e7525862aac7b"},{"path":"product/sdk/auths-approval-quorum/src/remote_tests.rs","sha256":"8a09ce17cfee82a035a74edd535f3ebeb3db0e078784740d3997b17dbdb10197"},{"path":"product/sdk/auths-approval-quorum/src/tests.rs","sha256":"0acbf12be3e497dcc6c2d8f29c9af3b1a7ed8e11b75f6399570d4f217a785060"},{"path":"product/stores/auths-stores/Cargo.toml","sha256":"a32c4b76d17b264be5d40d24497ff237e1ed87822e8bab86229b3db93106dbe3"},{"path":"product/stores/auths-stores/src/gateway_attempt.rs","sha256":"185da8f4a220fba836d5b78a9311f03204681c43a3c53951008084d135bf4d21"},{"path":"product/stores/auths-stores/src/lib.rs","sha256":"e721262edf8a9ab5568ddc27639176312d4a366203b5f73e2d7c11fde2c554e9"},{"path":"product/stores/auths-stores/src/lifecycle.rs","sha256":"94f64d25bc178a9e60ba3c0ee6915d7fb3af7c4468792d76b4e70f43f4de1e2f"}],"schema":"auths.gateway-semantic-closure/1"} \ No newline at end of file +{"files":[{"path":"Cargo.lock","sha256":"0e75e2fdef44e79e57797ac6661295ae58ddb8de4a1990a6fd22ce6c54f78604"},{"path":"Cargo.toml","sha256":"6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24"},{"path":"core/adapters/auths-did-keri/Cargo.toml","sha256":"86ba3e3f9a0a70d970568bfb3113b7ba7bbdd81c3eebbb52743dd574a0c0ecaa"},{"path":"core/adapters/auths-did-keri/src/lib.rs","sha256":"a75674842f8a7142004369ccd206ab43e476459293f0ff4bed4d4e659031b3e3"},{"path":"core/adapters/auths-did-key/Cargo.toml","sha256":"d5a3ae07ecde83f91eed4c3785051dd0f44eab6c891754f3309b6b40596707d7"},{"path":"core/adapters/auths-did-key/src/lib.rs","sha256":"b76a3f4528a725df53cfa9242e6e414e1d26caa48468aaed497e28b121f4497c"},{"path":"core/adapters/auths-raw-key/Cargo.toml","sha256":"f49616bc18c19e6aaa7e6a02ccebcdb9f5c1422c1278ef9869e0dbf22ceda7be"},{"path":"core/adapters/auths-raw-key/src/lib.rs","sha256":"45eec1b295dac3bed65cd79c942870b926b06b3f5d38eaebaeb6140ac69315fa"},{"path":"core/crates/auths-algebra-kernel/Cargo.toml","sha256":"0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba"},{"path":"core/crates/auths-algebra-kernel/src/generated.rs","sha256":"ae4bcbef42a408c7ffa0c6a74a42f7de177a6f14479e51d205acf830bda05960"},{"path":"core/crates/auths-algebra-kernel/src/lib.rs","sha256":"6654667eeb9b353d6648954c9fd2e8838462a82ce6b2803eb49e1366892c68c6"},{"path":"core/crates/auths-assurance/Cargo.toml","sha256":"afcb12a97ddd09d7a264b9ecd3fcaefc865ff2c9b4539ee85b00883420ba333a"},{"path":"core/crates/auths-assurance/src/lib.rs","sha256":"0fb2ec844d674b25a9e20b1601452c89c2454901fa506adfa9bb38ef9a7fa213"},{"path":"core/crates/auths-author/Cargo.toml","sha256":"1e6f0e3bc079ddb558decf0db26b291c6e72fc47327b6df1b7650d41689b215f"},{"path":"core/crates/auths-author/src/lib.rs","sha256":"e14475f2f49715a1869d5fa6b11ff1fbb72497e39097e09f833b0bae7e5b3f2b"},{"path":"core/crates/auths-author/src/observations.rs","sha256":"dda7d6bfa6f4bd7e95a480ca283c2c0e996f69c5c15cb0c7197af328131a7066"},{"path":"core/crates/auths-authority/Cargo.toml","sha256":"4f68212938029f79ebd857b4f3038494eb85d0163d49f07e51376715cf959815"},{"path":"core/crates/auths-authority/src/lib.rs","sha256":"da88d5194de4e17449e69972c0fb042afa3c39798a8f570f30771e77c384f1eb"},{"path":"core/crates/auths-codec/Cargo.toml","sha256":"e20e51826e17814effd9d8925d18d5fbdd6c0d37bf50231e743ec2611314722c"},{"path":"core/crates/auths-codec/src/approval.rs","sha256":"fbff43bf4d57f69f8b7738a8647751cde75c5a932dee65d924a1fe9c7202f91f"},{"path":"core/crates/auths-codec/src/bounded_policy.rs","sha256":"d21f6728be2d8a04b6d94921f2b683f7e61cbb42e0ac6866f1c88a49caa534c3"},{"path":"core/crates/auths-codec/src/decode.rs","sha256":"ba2999584cdf53b1b517ecb9c7ea50d39efee17c666a9a38e2ad1ac94379f778"},{"path":"core/crates/auths-codec/src/encode.rs","sha256":"8491192053e2e15d62b4d2a491de22405b7487ead69ab6f6bca40669ce7ca5f7"},{"path":"core/crates/auths-codec/src/error.rs","sha256":"fecb0737c16deb42d859f1dc7727c698438d9ac12064fd99e0024629642c390c"},{"path":"core/crates/auths-codec/src/hash.rs","sha256":"f88e111f1dbb2cef6b7b5e9c948cb45ff92e366710c8a5f5c636138aa748479e"},{"path":"core/crates/auths-codec/src/lib.rs","sha256":"3b0e5c94c6f34f750b88a9333e1d5c8145746d845d3a23e0d2f61807cf592ea7"},{"path":"core/crates/auths-codec/src/observation.rs","sha256":"38328b0c71ff97a4196eeade8b4faa889527ff1f80bb168468bcd49082a3987e"},{"path":"core/crates/auths-composition/Cargo.toml","sha256":"331e13025eb82588b5269ed3975929eb41c823d588c49e4c296273d85c6fe80e"},{"path":"core/crates/auths-composition/src/lib.rs","sha256":"e42e3b0b6a9985b73c533aeb23799c638979aa27a9ce7d0f10a8d60340570fb1"},{"path":"core/crates/auths-model/Cargo.toml","sha256":"565c15302b0cc9270db1e28efa3862804846850ba933cc17aea8abcec4a65987"},{"path":"core/crates/auths-model/src/approval.rs","sha256":"54cf44a9ef747ec21546a4086aecfb130bc7803b0d646430e6082df51e6e305f"},{"path":"core/crates/auths-model/src/bounded.rs","sha256":"f90496abc0a06c028b4d850af6ddab7d850bfafeaa3d042f1b1246a41d8bbbc9"},{"path":"core/crates/auths-model/src/bounded_policy.rs","sha256":"306a8f049cc7cfc7635fe0e4de47eb7813eed63d3c14c3be2b51586aa4eea450"},{"path":"core/crates/auths-model/src/lib.rs","sha256":"e7cfe6bb9574c6b016aa63e70658c31e0b90903ec6479a49f4a2ceb64f5bad97"},{"path":"core/crates/auths-model/src/observation.rs","sha256":"b3ed3e3cc090afca2896a7d3de7988afccc1ee1ea0ebd91b51a8bc0f20ad8dbb"},{"path":"core/crates/auths-multikey/Cargo.toml","sha256":"858756c1197befcada06134742bffe8d58cf674cadd6c046bf710570e96efaf2"},{"path":"core/crates/auths-multikey/src/lib.rs","sha256":"f5177fffb11e40eeaaa665ba886c541fc1f24d5eacdd6983fb03dc20148733f0"},{"path":"core/crates/auths-ports/Cargo.toml","sha256":"596a9b0f5af3717c16a6d13f7054d8a106bcd9f01f5f72c2235dd2afcf0ab16c"},{"path":"core/crates/auths-ports/src/binding.rs","sha256":"a16c012d40aa4249e3ec54372b9611006d0bfe8c7dc3c741911c2194ad17736d"},{"path":"core/crates/auths-ports/src/diagnostics.rs","sha256":"aa596572503b5a65a918bb2ff38281c144ff53821ee914e9325c852828d852df"},{"path":"core/crates/auths-ports/src/lib.rs","sha256":"8da1debf86f9532df0660155d04298beb1ba3a1204508f8586e2e67cd2fb3449"},{"path":"core/crates/auths-ports/src/path.rs","sha256":"b68fc547b4e4d97a60cbbc1cc1939fc6b34a8233b81f840bd396914a707e3ea1"},{"path":"core/crates/auths-raw-key-core/Cargo.toml","sha256":"98c0bc8527a537512e43a74dd6ba9658c6f0cdc16610cf938e3f9b43785d836d"},{"path":"core/crates/auths-raw-key-core/src/lib.rs","sha256":"98c0500c41697aae28708ad0bf970b9a97583d96a3d2c18d23e7fa351e0f7d12"},{"path":"core/crates/auths-registries/Cargo.toml","sha256":"590e49e58b0622d9d6274fea46796dcdb07dec9550eff295cce6a6427ffa51e2"},{"path":"core/crates/auths-registries/src/lib.rs","sha256":"450d3886d85ee333b7e046317fb5b47cde62483d5f3e41d46265e2caf4c373ec"},{"path":"core/crates/auths-registries/src/template.rs","sha256":"1224039dd2b3ce6fa8357613d8cafbae40400493da7176da202b9ade62fa05e4"},{"path":"core/crates/auths-signature-core/Cargo.toml","sha256":"6bee2230eb30af1be0bd5c2d57bd3e1903497a70028d47290d4ac6e9e0e8bca0"},{"path":"core/crates/auths-signature-core/src/lib.rs","sha256":"6e3f9311ded5e49ea50d445eb21e6d8fa12442aa4362a73e0cb6fda15b7cd865"},{"path":"core/crates/auths-signature/Cargo.toml","sha256":"7f7b5682466ba439d8c59579022cb61068cad9fb4bd2d73e1cc21327c902b450"},{"path":"core/crates/auths-signature/src/lib.rs","sha256":"b3d9ac4cc3ba0797b9e1c09f2d6ac05089b25dac4e285a5af28c0165b33d925b"},{"path":"core/crates/auths-verifier/Cargo.toml","sha256":"c43358e06a33324b41a8b93e5cc7279c55f7d21f1f6cfaa539a3fc7b4c27a38f"},{"path":"core/crates/auths-verifier/src/approval.rs","sha256":"c3cae6a49e169051eb555bb092b1069a4d422516d6a2114623a89e5f31ff923f"},{"path":"core/crates/auths-verifier/src/causal.rs","sha256":"9635230f33b13a263573d319ac8a1976addbcc07677514a43e3c7bf28dc04587"},{"path":"core/crates/auths-verifier/src/lib.rs","sha256":"f22dec38dfa47ced8da4f605390da8453273bee1da010f57fd1fdfcb10e0b389"},{"path":"core/crates/auths-verifier/src/observation.rs","sha256":"0bb07f06a0f9524c88427df1c972b1de8ba038a9eeeb15d3134c25125ae84b1e"},{"path":"core/crates/auths-verifier/src/trace.rs","sha256":"2213d72023a1d9e0413a2cf2c51c3dad9e04775d86033a0caaa9d29a8f0036f8"},{"path":"exchange/crates/auths-proof-exchange-model/Cargo.toml","sha256":"34b2db64f93a288e942b5a3918d28cdcbef906e0dc9074ce848018d3d5f7a1fa"},{"path":"exchange/crates/auths-proof-exchange-model/src/lib.rs","sha256":"49fac5aff2339d3a57c41cb8bb2a82852538e8f77ecc4b157c88e264ff31fb55"},{"path":"exchange/crates/auths-proof-exchange-port/Cargo.toml","sha256":"7ff660f1b7579dc570c791090aeb450404fbbf44c92781e289f5ccdde746d739"},{"path":"exchange/crates/auths-proof-exchange-port/src/lib.rs","sha256":"b408fb40c6432edc1facb3d8b3e9433a033f8dc73fe2e0ba5a88c972ca675021"},{"path":"product/config/auths-config/Cargo.toml","sha256":"e4b568ab9f6d84f7d7e6d66443fe825f360db9c27bc7c31d6ddc0647ba3ab304"},{"path":"product/config/auths-config/src/lib.rs","sha256":"fecf00ea65cef9018fda9af2063326d7065b869266d0d9e73a4f06816f1102cc"},{"path":"product/errors/auths-errors/Cargo.toml","sha256":"3b3a199b6460ba75bda84475bb5accd35e1485448a3981038db85bf4772dd350"},{"path":"product/errors/auths-errors/src/lib.rs","sha256":"7feeb9069fa4003f94f1f07c1c94619cf1c883e0dbaaf2187f04d0f742264bdd"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/Cargo.toml","sha256":"716f1f2a117d6d69d8effe9ee9057e24ba3502f20af6a602b06facb638cdabed"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/api.rs","sha256":"9ea61dd7ddd93282b073b98e453e6b75b26dc49689c04e9782435d06a3a09e48"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/clock.rs","sha256":"73f0a6e0f5903883329fa6683f5888288f759512ac69e5c87efd2b6b87f7d79f"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/http.rs","sha256":"14c1fce14e24c984b2a275563a29b6326fb08367922b6e8d37ba38b9cb81aa2b"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/identity.rs","sha256":"186de11230c8b33375951c4368609f8976bf9795f171af3fd7fac26207a94361"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs","sha256":"0b4617d044f5254a5ab22f5a2578f91cc025206a8c1845be39c1c56dcdf7a5df"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/names.rs","sha256":"41bb23572d6002e23ee103d6fe70ecd68764861c6f2e48a1c53af998270a4afa"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs","sha256":"39fed883f4802e68d3b41a68fea0aba0737810996b33d13577de70faba004c29"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/store.rs","sha256":"fc60ee9c49b2f4f063c449b4c78100c5c4872779e94ca168f796603b380ef6e4"},{"path":"product/integrations/auths-custody/Cargo.toml","sha256":"1e14034185ad1ec24a977fd5f41d0abee219606245c046ce2a82287fadef448b"},{"path":"product/integrations/auths-custody/src/conformance.rs","sha256":"8ed1afd58f18fc6becc268908aa6419c9aa404c79da0197963eb2599df44acf6"},{"path":"product/integrations/auths-custody/src/key.rs","sha256":"70cbb0fd21b6f5652157845a22c35be2d0f6c05b3d138fc4b9bb6dbdc3d81c40"},{"path":"product/integrations/auths-custody/src/lib.rs","sha256":"8ee593c1f59b0fd2126bdda9138026f5bc531beb64d4489a99785842e7b98b43"},{"path":"product/operations/auths-operations/Cargo.toml","sha256":"73dde1e914ba5e1386f8d49c0d730423cc72ae77ec44c6554a6a75cc8e8922b1"},{"path":"product/operations/auths-operations/src/explanation.rs","sha256":"b4a39bcbd5712cb9e735ee7deeb281f3fa6af5ddca973735bf3d87dce427ef11"},{"path":"product/operations/auths-operations/src/lib.rs","sha256":"3f401a56555113b98f57bca172a2660eaecedf76247b83a3fdbb089c133a29cd"},{"path":"product/operations/auths-operations/src/render/json.rs","sha256":"2ae042639960afee123730e945d373bc5dda1d2b3af20ae16c939a7e99b9e418"},{"path":"product/operations/auths-operations/src/render/mod.rs","sha256":"b3b7f6fe473f49227ace5a68bfc3d8dc14b5db8dd9888fd9e207070337b1b8bf"},{"path":"product/operations/auths-operations/src/render/text.rs","sha256":"f216cf3bdb00e264523271b16e7059535ac6b1aabf271cebd7935af155e4bfec"},{"path":"product/policy/auths-bounded-policy/Cargo.toml","sha256":"babd5d200923137ead71d8c2528f847cea323ce98da942a1320b054436612c47"},{"path":"product/policy/auths-bounded-policy/src/arithmetic.rs","sha256":"75e43c5d4eab8d1f71c1daf53839f5f9fe45a400afc1f63a30c6f55ce3632627"},{"path":"product/policy/auths-bounded-policy/src/commitment.rs","sha256":"c5706f2d583454e1a7f570f7ada138d4d864bef0205dfae7c1296774f396bb3f"},{"path":"product/policy/auths-bounded-policy/src/eligibility.rs","sha256":"c9acdfb793074e687fc36efad506be27dbd99ffbf40387bc66c8de39ef238432"},{"path":"product/policy/auths-bounded-policy/src/identifier.rs","sha256":"0006a32bae9eb16c4178cf797df418d2b0a781f2bc6474b741dc1a908141831c"},{"path":"product/policy/auths-bounded-policy/src/kernel.rs","sha256":"99187c28b161ac70bee1afed60711f7f645adb4d1671a01863f9849b369811d5"},{"path":"product/policy/auths-bounded-policy/src/lib.rs","sha256":"76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c"},{"path":"product/policy/auths-bounded-policy/src/receipt.rs","sha256":"3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad"},{"path":"product/policy/auths-bounded-policy/src/registry.rs","sha256":"4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0"},{"path":"product/profiles/auths-profile-api/Cargo.toml","sha256":"7ae85761f58625b5d678f961fd052eebf3e000ef565c7312e3ac857763c0017f"},{"path":"product/profiles/auths-profile-api/src/lib.rs","sha256":"a194b82b20bf8aa864c2334ef6c6aec30b2154ded972862252d5dcefa488ab95"},{"path":"product/profiles/auths-profile-mcp/Cargo.toml","sha256":"db264fc25242f7b7e4133cbe5782545b3107b406c87168ae072683cfb59eac66"},{"path":"product/profiles/auths-profile-mcp/src/arguments.rs","sha256":"a5de696586d507e2aee4a49fee99ef1ef4c51a2e46603f8838f1af6d9009833f"},{"path":"product/profiles/auths-profile-mcp/src/lib.rs","sha256":"d0f8b733a09ef8408336cdebc8948d6a5861012ce6878598b11be7084dfd4280"},{"path":"product/profiles/auths-profile-mcp/src/session.rs","sha256":"166c281fa66333388e4760d6098dad02d3359e1d5de4b8f93312c014f97abb03"},{"path":"product/qualification/auths-recipe-qualification/Cargo.toml","sha256":"b7b15b30b9a3d96d4f089d514266d3a892de6608d30707aa44be31cca89ca9fe"},{"path":"product/qualification/auths-recipe-qualification/src/canonical.rs","sha256":"30a9b50777f0dcb4b606abfee2467d5a975d9f6ad941ab6c13ca3df5b359f667"},{"path":"product/qualification/auths-recipe-qualification/src/closure.rs","sha256":"0ad6aee9bd981e2863fa725f209ec84031db2ff12f4c7ac3aaf5120f0bb86039"},{"path":"product/qualification/auths-recipe-qualification/src/error.rs","sha256":"52d5cf720a1e4579008fdda90a3ac2c31f0b8db57985f121f65e54b4da2b7dd1"},{"path":"product/qualification/auths-recipe-qualification/src/evidence.rs","sha256":"ba45a7409d67a8af26ab811af306412014557477a101ab2a8eb0faf8f2bd4b91"},{"path":"product/qualification/auths-recipe-qualification/src/ids.rs","sha256":"e81a906d571497ab2da753e1532d4443706410e0b75fdd59a7d2d788c7aec403"},{"path":"product/qualification/auths-recipe-qualification/src/launch.rs","sha256":"41f2e2de90e1e7d6440a66eda3eb9bea8d5e0741bc232305a76a363ab5f813c1"},{"path":"product/qualification/auths-recipe-qualification/src/lib.rs","sha256":"5c9cff04c8960df805a2f7656cf5e74932798e0db7648341e96ae7073a592404"},{"path":"product/qualification/auths-recipe-qualification/src/model.rs","sha256":"3484eb0ec287b23d4682ade7b1b0f8d1335985b3fb180f06fc28716076957d5f"},{"path":"product/qualification/auths-recipe-qualification/src/release.rs","sha256":"d816b53e2275e902c750ad03803061844e259e28560ab2d1c77e8a43981a4d6a"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/mod.rs","sha256":"7f15b68e05a04f202bcb1fb80de1d9a9a4fda8bfd6af2cd4e5c660fc75d96fe5"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/schemas.rs","sha256":"c59feec2805621f341a90f81fc005e2c12f7a70f9d264fdeacccb2be4fe1c046"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/verification.rs","sha256":"6a6b5834c5dae10af1ba8939b2deae43b85db71544dc8f077ff63b7fe68ac8a8"},{"path":"product/qualification/auths-recipe-qualification/src/verify.rs","sha256":"a470a9b98c04dc8d5dabe4d3dc8ed4e7a3ceb1cde035944a0714462bbf37d56d"},{"path":"product/receipts/auths-receipts/Cargo.toml","sha256":"6001fa1375899953aafcb07c23a6da0c8f57ea7ec08bb9c950b12a60a8cc6f0f"},{"path":"product/receipts/auths-receipts/src/disclosure.rs","sha256":"ba9ed439be0a320c8a01f5b6e9b51361c1a37e076947490d8e4a484ba6bb119c"},{"path":"product/receipts/auths-receipts/src/lib.rs","sha256":"547a57c4160256719cafb7d0ab972d9fc80b0da14fbbce4148c70c414070ff36"},{"path":"product/runtime/auths-connections/Cargo.toml","sha256":"babeb6e1dda3dfb66291713ce1e43dce5c349833d0b50ea4dccbf986030026b2"},{"path":"product/runtime/auths-connections/src/credential.rs","sha256":"82921413bb053f0f6c7931fbd4e6a86c8cc1d8c6b51debd9c2cef33a8d5b1c51"},{"path":"product/runtime/auths-connections/src/kernel.rs","sha256":"a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8"},{"path":"product/runtime/auths-connections/src/lib.rs","sha256":"79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22"},{"path":"product/runtime/auths-connections/src/model.rs","sha256":"de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77"},{"path":"product/runtime/auths-connections/src/registry.rs","sha256":"e57640e003e72ad3235c567c2bb944a262bd64e673f023b62ea091094cc7e946"},{"path":"product/runtime/auths-gateway-kernel/Cargo.toml","sha256":"34f864e67656af4ac7e5c7a347a23f01fc8ab31365b8e23c0ef474483b14a183"},{"path":"product/runtime/auths-gateway-kernel/src/construct.rs","sha256":"e9d65744bae273d65face4285e5d2da75c06a92ab48f7b8333d496604e31c63c"},{"path":"product/runtime/auths-gateway-kernel/src/lib.rs","sha256":"cfda6f8453426564c085475f183b6f790b438768a19668f1b65d33ba59dc8632"},{"path":"product/runtime/auths-gateway-kernel/src/order.rs","sha256":"e0045f877c4b7fe3860c291039853885064ddcdebba7c9b345ab65e81e646dda"},{"path":"product/runtime/auths-gateway-kernel/src/outcome.rs","sha256":"e9785b1afe70788c89b51b18655bcd5acff7b0c8e3d12fb79c6f05a202e67e6b"},{"path":"product/runtime/auths-gateway-kernel/src/ratio.rs","sha256":"7ace22264812e6fc1ef3a62afee402cf43494bb71ae0d3de219ad1b39d690bcb"},{"path":"product/runtime/auths-gateway-kernel/src/recovery.rs","sha256":"9f46dcd1685ab6e4d1ba04a3fc286a9f3afee8fb47829be1fbc670a7926a2dc6"},{"path":"product/runtime/auths-gateway-kernel/src/transition.rs","sha256":"cefb8f01d915880f6921f2501ff881ad94b9de61072c34d9cd19220992f97374"},{"path":"product/runtime/auths-gateway/Cargo.toml","sha256":"00b28be86921dcdc0ad90cce0c62c2961cafefe96ea6c2edf0e926c3d405ccad"},{"path":"product/runtime/auths-gateway/src/admin.rs","sha256":"2d5cc67afac42fbd15f36e2d1693cd1b20cedacf775040dce6ffe04ccc94c9ea"},{"path":"product/runtime/auths-gateway/src/app.rs","sha256":"6f80f63833ea0815bb44fbf3b0cc54624a08e9fb578b035819f2980dc04e8256"},{"path":"product/runtime/auths-gateway/src/audit.rs","sha256":"0edb2037eb7b5d6f13acfce85c54f62a82bf7fdd31bc7e626c4fec183cef61dd"},{"path":"product/runtime/auths-gateway/src/audit_tests.rs","sha256":"990969384a52d75bc2489d9d412a9e7dd814bca1c8f65c701d6205fae62a15d5"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway-harness.rs","sha256":"12b0c24d36b2e6a3be392d3c081a783b355fdd67dc5b54bacc0410e803116b8c"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway.rs","sha256":"2f33a1da5dd54947ee1664795f90b3f07a11bb9ee184774bf470b78b03600f0c"},{"path":"product/runtime/auths-gateway/src/binding.rs","sha256":"663b0ce878319511aa7d05722ab4ab2fa9be18817884ffb2ee9f131ff1e382d1"},{"path":"product/runtime/auths-gateway/src/bounds.rs","sha256":"9cfa0eae4973e5e047a198360b22f041708fa20276b0b90c2ec440f06915d64b"},{"path":"product/runtime/auths-gateway/src/bounds_aggregate_tests.rs","sha256":"ab34f227b7c8692ba1da88ccb32bb3687a66adf8353d8282fae905d4a88eb612"},{"path":"product/runtime/auths-gateway/src/bounds_tests.rs","sha256":"74136bc570da7b9338b5a1a1ed9d3fd892c55135160964f9d3ac0e2cf5741375"},{"path":"product/runtime/auths-gateway/src/connection.rs","sha256":"7b5d049c258a26ed1c93ecf860f51d051a8a65f9b93554af0b1ea93862398ec9"},{"path":"product/runtime/auths-gateway/src/credential_journal.rs","sha256":"7297fccaee5cd8622928e8e0a42bba50da7941970a6f682ecd300c41ee6509da"},{"path":"product/runtime/auths-gateway/src/echo_verify.rs","sha256":"6d453051665f823abd7354d5c50031d9524cf47d6092d2f09080ae814e3b9575"},{"path":"product/runtime/auths-gateway/src/engine.rs","sha256":"f1052aaef43e441b9e0befa3f8ad1e2fd5279a27cb9d63aac0cf9dfdbe85a052"},{"path":"product/runtime/auths-gateway/src/fuzzing.rs","sha256":"ed3b0028487eb546a3b0a91d115aa8f18bcea324b61620bfe8e35a9e6ab18758"},{"path":"product/runtime/auths-gateway/src/generation_floor.rs","sha256":"fe1510ec96ce0f67e9a78edbfa94b33eb7df64c0ac4d0a67901124dcd0164777"},{"path":"product/runtime/auths-gateway/src/harness.rs","sha256":"c87e479f3eb281960f6c9c80d43c7560d7ccb654b0154ec823d3fcec4884ac05"},{"path":"product/runtime/auths-gateway/src/lib.rs","sha256":"a1f51b76524a89842720b4fda58b2293d4bc82b41c912d5a462261603c593cea"},{"path":"product/runtime/auths-gateway/src/listener.rs","sha256":"aa08239bcbc1fcb55e8a212fbdf6a84f12985b0d436dcb51dc58b06e59e435f2"},{"path":"product/runtime/auths-gateway/src/observed_tests.rs","sha256":"a22be071695f89ca2578a4d82fd80d9cb82289213c9bdb8f0470f6b2dc3d9201"},{"path":"product/runtime/auths-gateway/src/observer.rs","sha256":"562ffcaea071c3856e0708dc2fe33516917e145d2438aabb75af0a2b6ba01046"},{"path":"product/runtime/auths-gateway/src/onboarding.rs","sha256":"0dfd7d67e7f02f18a28d1c86ca1b7751d7463f5efcdbe3825de0ad8cbccb3891"},{"path":"product/runtime/auths-gateway/src/operator.rs","sha256":"c3c36954a3e86723df035b47f43b85fc8ab3a6292983522b6258d5c6b4e6c4e4"},{"path":"product/runtime/auths-gateway/src/pending_vectors/attempts.rs","sha256":"47ef3c8cb1c5504d47ae9a0088705ce6715fe86bac1671a34a56fb38a64d0dd3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/bounds.rs","sha256":"e612217307e1da5b0eb5ee6582a7458bb064b8aa8a529fc6555b1b334127ab68"},{"path":"product/runtime/auths-gateway/src/pending_vectors/codes.rs","sha256":"e00670a5ef24eb856cc2c6dcda8e5a263842f55c76bb939c0c27bd9df37e5522"},{"path":"product/runtime/auths-gateway/src/pending_vectors/keys.rs","sha256":"f84c56f2ea9cb34b2b79c72d13fbf2c6585010ec1ed450af58a78c80c1ea1edd"},{"path":"product/runtime/auths-gateway/src/pending_vectors/mod.rs","sha256":"5de8340f0ef71a0b57a09e323fefe473d3160c6ae952b9ba46f714825fbacafc"},{"path":"product/runtime/auths-gateway/src/pending_vectors/outcomes.rs","sha256":"8ec07b9511b48913af36ac999d2aa0e82924289f6acb23ddaeb9f00f99815166"},{"path":"product/runtime/auths-gateway/src/pending_vectors/production.rs","sha256":"f574cabfa4687a4fc846b8f6a234b68ec53b876aed548b11445729cac1a55ede"},{"path":"product/runtime/auths-gateway/src/pending_vectors/recipes.rs","sha256":"51693208270231c25c3aef2a32151d5962114c71e86b88cb9df83181c7af83d9"},{"path":"product/runtime/auths-gateway/src/pre_entry.rs","sha256":"06ea78ca140468bfaba17d9ab04912ad68673954c3203c98fed28272ff2a00c0"},{"path":"product/runtime/auths-gateway/src/property_tests.rs","sha256":"939c081e2e154aaf10186754044bdd65608932c899b970a04a71d0afaa999a93"},{"path":"product/runtime/auths-gateway/src/qualification.rs","sha256":"06b49d3fc2ad4383f9e23beefa96033f1fd6e415e043878327583451a53086cc"},{"path":"product/runtime/auths-gateway/src/qualification_simulation.rs","sha256":"4ee7cadfb5f46a92713c80f3e55f499cb074d04d8b21ea89d57762af38642bfa"},{"path":"product/runtime/auths-gateway/src/qualification_tests.rs","sha256":"a9178a2e58eea459d5e5dafc53a3999ea7c84dbbffefe6e5eb1f3d098827f028"},{"path":"product/runtime/auths-gateway/src/quorum_tests.rs","sha256":"a78380b019104d688c11a4410082c7e08ded3106aab099954c4f8a1b4ae0fd89"},{"path":"product/runtime/auths-gateway/src/readiness.rs","sha256":"911c3f11892f94641574375e2da4c671c802738f71082f12c39832331052d43d"},{"path":"product/runtime/auths-gateway/src/recipe.rs","sha256":"fecf9af67e7afc48d080e9f8f55f8ce28e49d0e08988717a27908bbda461d6b6"},{"path":"product/runtime/auths-gateway/src/recipe/lower.rs","sha256":"8088b8751ed831dbb48247af953c6290ac95e2a438ccd5bd65eff54be06a1fd1"},{"path":"product/runtime/auths-gateway/src/recipe/review.rs","sha256":"c3eb7d9fdd98dacf52750b14b67ad7b7faaecbbdeafff1e0b049f67d0a2d0139"},{"path":"product/runtime/auths-gateway/src/recipe/runtime.rs","sha256":"c286f0d15f974402822c0810d8e97f98411dc1c557755cc23e540d85e2bb42d9"},{"path":"product/runtime/auths-gateway/src/recipe/source.rs","sha256":"1af50298fb1461e1b24cbdf560d43124d6b1c4c529586c911b1c4797214a69ff"},{"path":"product/runtime/auths-gateway/src/recipe/tests.rs","sha256":"aac551a2481bbc60864c64079bc667dcb232e45a0f41a04073ed84ab5dbe1fce"},{"path":"product/runtime/auths-gateway/src/recipe/validate.rs","sha256":"3711b17605cb7b0d639bc1b180449231f5882a306cab20e2c7782155cc63b0d4"},{"path":"product/runtime/auths-gateway/src/scenario_tests.rs","sha256":"67915828ecfe2be0afadb5525277ab205f91172edc90852ec7b77c63b2d17fdc"},{"path":"product/runtime/auths-gateway/src/separation.rs","sha256":"be9306848ca5d801767cf6aa14247c8618312ef0e202f00ce0c24c4844491061"},{"path":"product/runtime/auths-gateway/src/simulation_attestation.rs","sha256":"88705e5d45415f760f1e3c3a065c35c48f4f4065bf7b3feb7882246983814d6f"},{"path":"product/runtime/auths-gateway/src/store.rs","sha256":"1e5288345c2cb1421aeda277b3158d07607404b0ec46943222ac107b63dcbb46"},{"path":"product/runtime/auths-gateway/src/store_testkit.rs","sha256":"88d82fee42f1b8ef521e8deef0216e938ebeaad822eb2f5020e70b89d145ea70"},{"path":"product/runtime/auths-gateway/src/submit.rs","sha256":"c78dbbba7c45b443febf655056c5edcd635e77be7b21c5b2c318097502415ffe"},{"path":"product/runtime/auths-gateway/src/support.rs","sha256":"9fd979029793a22b15d9776a7fc172476fd7c126a80d4080c65d720845becbcb"},{"path":"product/runtime/auths-gateway/src/transport.rs","sha256":"be2c6dc75b8daec110bf8749fedc3823f6067d40b999aa3eb21126896a97d3ad"},{"path":"product/runtime/auths-kernel-runtime/Cargo.toml","sha256":"926bcd0053e5edd703be8f0027ad009e2982db013c8174c1366edbf38b48087d"},{"path":"product/runtime/auths-kernel-runtime/src/lib.rs","sha256":"7108faae9ca4bc32dc093ddaf885ac8f74f3c9b8d317b7c7d0ed00d1d0ab5972"},{"path":"product/runtime/auths-lifecycle/Cargo.toml","sha256":"c5053c705f8d5554b44e432fe75287a2faf11d644e5a2552e45ad6cd94176af5"},{"path":"product/runtime/auths-lifecycle/src/codec.rs","sha256":"51c4b746749150e8bfcd8ff972b3f6c1ef40bec15583448ec1b471d9ad737dc0"},{"path":"product/runtime/auths-lifecycle/src/digest.rs","sha256":"55282cd7d8aba37713c2dcb5357c9877819edb72a30eadefb860d28d7d3a3eb7"},{"path":"product/runtime/auths-lifecycle/src/identifier.rs","sha256":"31620e8c16de68d3d2d3b84d6353c1a5b9d4151d8247f91fa389b906a8e660f1"},{"path":"product/runtime/auths-lifecycle/src/kernel.rs","sha256":"2abb8c094b36d35b364e74d78091d14c5d6f3d1eb6552cca3b5538dbd017ce23"},{"path":"product/runtime/auths-lifecycle/src/lib.rs","sha256":"afe5a345cd309b5a4f08ffba3170a6d7f16ff914892b3f2006d5208ed24ec736"},{"path":"product/runtime/auths-lifecycle/src/model.rs","sha256":"1af12bbeeeaa65ec02ddcebd7d2c8c92ec1e339fa40ae85b45ab9b01a722a4fa"},{"path":"product/runtime/auths-lifecycle/src/operation.rs","sha256":"78e6d05fcf5d7ea4f148032a3fa26fdfcab77eb346019effe927b08e0d64d732"},{"path":"product/runtime/auths-lifecycle/src/registry.rs","sha256":"53495fe6f7a77422593a41623e28716f1c140dcc1e00f87f6b0ffbfb93a5ef90"},{"path":"product/runtime/auths-lifecycle/src/sealed.rs","sha256":"2e0c03b5813c926c159598bb7890d1523825edbe57cd687d42a5dfb3374a0c19"},{"path":"product/runtime/auths-lifecycle/src/test_support.rs","sha256":"221d9a5c5ef8e1f9f8fd66927484eaf813571d0568470278ecd8fa08a5eec8cd"},{"path":"product/runtime/auths-lifecycle/src/transition.rs","sha256":"011805a28efdd541f44ccea54dd0e34a1e58f4004447ee58013703b4fb6b2822"},{"path":"product/runtime/auths-runtime/Cargo.toml","sha256":"dd29d80a8b4bb56c869f036a6c9998f6e6d1c0383ac5dc03fa42b24abe2a7ff7"},{"path":"product/runtime/auths-runtime/src/lib.rs","sha256":"132ca03d58c14905d3a822a4972f42a22a5ad33a45f2ba9ca44f3a57d810b4b0"},{"path":"product/runtime/auths-runtime/src/production.rs","sha256":"fd4eff4270c571c10fcff6cf27df28961ebf074de8a1a028f500fda1ca376820"},{"path":"product/sdk/auths-approval-quorum/Cargo.toml","sha256":"df904971fca87a24194c5816738a331588fe8f164acb5d70839a35dca5f57114"},{"path":"product/sdk/auths-approval-quorum/src/lib.rs","sha256":"72e4086088a1c0912e4e1a9e980f26a5c280bf5ab16ea39c9f0f58d5096ac2ce"},{"path":"product/sdk/auths-approval-quorum/src/remote.rs","sha256":"9fa029c7c63003adf260f8aec55160c545681c60c1bace0d934e7525862aac7b"},{"path":"product/sdk/auths-approval-quorum/src/remote_tests.rs","sha256":"8a09ce17cfee82a035a74edd535f3ebeb3db0e078784740d3997b17dbdb10197"},{"path":"product/sdk/auths-approval-quorum/src/tests.rs","sha256":"0acbf12be3e497dcc6c2d8f29c9af3b1a7ed8e11b75f6399570d4f217a785060"},{"path":"product/stores/auths-stores/Cargo.toml","sha256":"a32c4b76d17b264be5d40d24497ff237e1ed87822e8bab86229b3db93106dbe3"},{"path":"product/stores/auths-stores/src/gateway_attempt.rs","sha256":"185da8f4a220fba836d5b78a9311f03204681c43a3c53951008084d135bf4d21"},{"path":"product/stores/auths-stores/src/lib.rs","sha256":"e721262edf8a9ab5568ddc27639176312d4a366203b5f73e2d7c11fde2c554e9"},{"path":"product/stores/auths-stores/src/lifecycle.rs","sha256":"94f64d25bc178a9e60ba3c0ee6915d7fb3af7c4468792d76b4e70f43f4de1e2f"}],"schema":"auths.gateway-semantic-closure/1"} \ No newline at end of file diff --git a/product/runtime/auths-gateway/src/semantic_closure.rs b/product/runtime/auths-gateway/src/semantic_closure.rs index 7b208686a..6ec13ddf8 100644 --- a/product/runtime/auths-gateway/src/semantic_closure.rs +++ b/product/runtime/auths-gateway/src/semantic_closure.rs @@ -10,7 +10,7 @@ /// SHA-256 of the schema, a NUL byte, and `semantic-closure.json`. /// Regenerate through `semantic_closure_is_current` with `AUTHS_UPDATE_FIXTURES=1`. pub const GATEWAY_SEMANTIC_CLOSURE_SHA256: &str = - "11a256092b821eec54d27e3ad25cc05f7955da236ea23853cced71c32215764d"; + "1bba718ab65c29ff96190b087e2b63c32b5305f9dce0b070547b2b40e077efd0"; #[cfg(test)] mod tests { From bb3e25f1ea44513c9c4982fe54f3f1a00f5069a3 Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 02:49:08 +0100 Subject: [PATCH 050/108] Make public verification recipes runnable from an installed SDK --- .github/workflows/sdk-recipes.yml | 6 +- .../recipes/python/02_verify_authority.py | 9 ++- bindings/recipes/tools/generate-docs.mjs | 45 +++++++++++- bindings/recipes/tools/run-docs.py | 73 +++++++++++++++++++ .../recipes/typescript/02-verify-authority.ts | 2 +- .../recipes/01_AUTHENTICATE_IDENTITY.md | 4 +- docs/product/recipes/02_VERIFY_AUTHORITY.md | 43 ++++++++++- .../INDEPENDENT_OPERATOR_RC_REHEARSAL.md | 43 +++++++++++ 8 files changed, 213 insertions(+), 12 deletions(-) create mode 100644 bindings/recipes/tools/run-docs.py create mode 100644 docs/research/INDEPENDENT_OPERATOR_RC_REHEARSAL.md diff --git a/.github/workflows/sdk-recipes.yml b/.github/workflows/sdk-recipes.yml index 77b37fa20..37f9ed48e 100644 --- a/.github/workflows/sdk-recipes.yml +++ b/.github/workflows/sdk-recipes.yml @@ -76,6 +76,8 @@ jobs: - run: npm exec tsc -- -p tsconfig.json working-directory: bindings/recipes/typescript - run: .recipe-venv/bin/python -m pip install target/recipe-artifacts/auths-*.whl + - name: Run public Python instructions with no checkout imports or fixture environment + run: .recipe-venv/bin/python bindings/recipes/tools/run-docs.py --out target/recipe-artifacts/public-python-recipes.json - name: Run paired recipes and cross-language receipt verification env: AUTHS_RECIPE_PYTHON: ${{ github.workspace }}/.recipe-venv/bin/python @@ -88,7 +90,9 @@ jobs: - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: name: sdk-recipe-timings-${{ github.run_id }}-${{ github.run_attempt }} - path: target/recipe-artifacts/timings.json + path: | + target/recipe-artifacts/timings.json + target/recipe-artifacts/public-python-recipes.json if-no-files-found: error retention-days: 30 diff --git a/bindings/recipes/python/02_verify_authority.py b/bindings/recipes/python/02_verify_authority.py index a07489c84..a105335ed 100644 --- a/bindings/recipes/python/02_verify_authority.py +++ b/bindings/recipes/python/02_verify_authority.py @@ -7,7 +7,14 @@ from auths.verify import VerificationInput, verify -root = Path(os.environ["AUTHS_RECIPE_FIXTURE"]) +fixture = os.environ.get("AUTHS_RECIPE_FIXTURE") +if not fixture: + raise SystemExit( + "Set AUTHS_RECIPE_FIXTURE to the directory containing workflow.proof.cbor, " + "workflow.action.cbor and workflow.context.cbor; " + "see docs/product/recipes/02_VERIFY_AUTHORITY.md for a disposable example." + ) +root = Path(fixture) proof = (root / "workflow.proof.cbor").read_bytes() action = (root / "workflow.action.cbor").read_bytes() context = (root / "workflow.context.cbor").read_bytes() diff --git a/bindings/recipes/tools/generate-docs.mjs b/bindings/recipes/tools/generate-docs.mjs index 507f73084..87bc12e43 100644 --- a/bindings/recipes/tools/generate-docs.mjs +++ b/bindings/recipes/tools/generate-docs.mjs @@ -10,18 +10,57 @@ const descriptions = { "02-verify-authority": ["02_VERIFY_AUTHORITY.md", "Verify existing authority", "Verify existing proof, action, and trust bytes without gaining an execution capability.", "Load the verification context from your governed trust source and retain the exact profile/semantic versions used by issued evidence."], }; +const authoritySetup = [ + "This recipe reads existing canonical proof, action and trusted-context bytes. Put them in one directory as `workflow.proof.cbor`, `workflow.action.cbor` and `workflow.context.cbor`, and set `AUTHS_RECIPE_FIXTURE` to that directory.", + "", + "For a disposable example, run this with the installed Python package. It generates its own in-memory signing key and public test artifacts; it needs no checkout, provider credential or downloaded fixture. The generated context trusts that disposable key only and is not production trust.", + "", + "```python", + "from pathlib import Path", + "from auths.testkit import development_mcp_artifacts", + "", + 'artifacts = development_mcp_artifacts(', + ' service="recipe-demo", name="publish_report", arguments={"report": "weekly"}', + ")", + 'directory = Path("auths-demo-evidence")', + "directory.mkdir(exist_ok=True)", + "for name, data in [", + ' ("proof", artifacts.proof),', + ' ("action", artifacts.action),', + ' ("context", artifacts.trusted_context),', + "]:", + ' (directory / ("workflow." + name + ".cbor")).write_bytes(data)', + "```", + "", + "Save the verification program below as `verify_authority.py` or compile the TypeScript program, then run:", + "", + "```sh", + 'AUTHS_RECIPE_FIXTURE="$PWD/auths-demo-evidence" python verify_authority.py', + 'AUTHS_RECIPE_FIXTURE="$PWD/auths-demo-evidence" node verify_authority.js', + "```", +].join("\n"); +const protectedClaims = { + "01-authenticate-identity": "The native Rust implementation checks the identity, signature and exact message binding. This authenticates bytes; it grants no authority and performs no provider write.", + "02-verify-authority": "The native Rust verifier checks the supplied proof against the exact action and explicit trusted context. An authorized result is an offline verification result; it acquires no credential and performs no provider write.", +}; +const failureExercises = { + "01-authenticate-identity": "The Python example changes the message while keeping the original signature and requires authentication to fail. No provider is contacted.", + "02-verify-authority": "The Python example changes one action byte and requires authorization to fail. The trust context is an explicit input; do not replace governed production trust with a self-trusting test context.", +}; + for (const recipe of manifest.recipes) { const [filename, title, outcome, production] = descriptions[recipe.id]; const typescript = readFileSync(join(recipes, recipe.typescript), "utf8").trimEnd(); const python = readFileSync(join(recipes, recipe.python), "utf8").trimEnd(); const number = recipe.id.slice(0, 2); + const setup = recipe.id === "02-verify-authority" ? `\n\n${authoritySetup}` : ""; const document = `# ${number} — ${title}\n\n` + `## Outcome\n\n${outcome}\n\n` + - `## Before you start\n\nUse a supported Node.js or CPython runtime and install the single Auths package. The executable source below is run against the packed npm artifact and wheel in CI.\n\n` + + `## Before you start\n\nUse a supported Node.js or CPython runtime and install the single Auths package. The executable source below is run against the packed npm artifact and wheel in CI.${setup}\n\n` + `## TypeScript\n\nSource: \`${recipe.typescript}\`\n\n\`\`\`typescript\n${typescript}\n\`\`\`\n\n` + `## Python\n\nSource: \`${recipe.python}\`\n\n\`\`\`python\n${python}\n\`\`\`\n\n` + - `## What Auths protected\n\nThe recipe uses Rust-owned canonicalization, commitments, authorization, and receipt/recovery semantics. TypeScript and Python coordinate bounded I/O but cannot mint an effect-capable authorization object.\n\n` + - `## Break it safely\n\nThe executable includes its failure exercise and asserts that no unauthorized or duplicate provider entry occurs. CI fails if the adversarial result changes.\n\n` + + `## What Auths protected\n\n${protectedClaims[recipe.id]}\n\n` + + `## Break it safely\n\n${failureExercises[recipe.id]}\n\n` + `## Take it to production\n\n${production}\n`; writeFileSync(join(repository, "docs/product/recipes", filename), document); } diff --git a/bindings/recipes/tools/run-docs.py b/bindings/recipes/tools/run-docs.py new file mode 100644 index 000000000..86ecfb5da --- /dev/null +++ b/bindings/recipes/tools/run-docs.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python3 +"""Exercise the public Python instructions with installed packages in a fresh directory.""" +from __future__ import annotations + +import argparse +import hashlib +import json +import os +from pathlib import Path +import re +import subprocess +import sys +import tempfile +import time + +PAGES = { + '01-authenticate-identity': '01_AUTHENTICATE_IDENTITY.md', + '02-verify-authority': '02_VERIFY_AUTHORITY.md', +} + + +def main() -> None: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--out', type=Path) + args = parser.parse_args() + repository = Path(__file__).resolve().parents[3] + manifest = json.loads((repository / 'bindings/recipes/manifest.json').read_bytes()) + reports = [] + with tempfile.TemporaryDirectory(prefix='auths-public-recipes-') as temporary: + work = Path(temporary) + environment = {'PATH': os.defpath, 'PYTHONNOUSERSITE': '1'} + package = json.loads(subprocess.check_output([ + sys.executable, '-c', + 'import auths, importlib.metadata, json, sys; ' + 'print(json.dumps({"version": importlib.metadata.version("auths"), ' + '"file": auths.__file__, "prefix": sys.prefix}))', + ], cwd=work, env=environment, timeout=30)) + if not Path(package['file']).resolve().is_relative_to(Path(package['prefix']).resolve()): + raise SystemExit('recipes.package-is-not-installed') + for recipe in manifest['recipes']: + page = repository / 'docs/product/recipes' / PAGES[recipe['id']] + source = page.read_text() + blocks = re.findall(r'```python\n(.*?)\n```', source, re.S) + if not blocks: + raise SystemExit('recipes.python-example-missing') + started = time.monotonic() + for index, block in enumerate(blocks): + program = work / (recipe['id'] + '-' + str(index) + '.py') + program.write_text(block + '\n') + child_environment = dict(environment) + if recipe['id'] == '02-verify-authority' and index == len(blocks) - 1: + child_environment['AUTHS_RECIPE_FIXTURE'] = str(work / 'auths-demo-evidence') + result = subprocess.run([sys.executable, str(program)], cwd=work, + env=child_environment, capture_output=True, text=True, timeout=60) + if result.returncode: + raise SystemExit('recipes.public-example-failed:' + recipe['id'] + '\n' + result.stderr[-4096:]) + observation = json.loads(result.stdout.splitlines()[-1]) + if observation.get('outcome') != recipe['expected'] or observation.get('changedRejected') is not True: + raise SystemExit('recipes.public-example-result-mismatch:' + recipe['id']) + reports.append({'recipe': recipe['id'], 'result': observation, + 'seconds': round(time.monotonic() - started, 3), + 'page_sha256': hashlib.sha256(page.read_bytes()).hexdigest()}) + report = {'schema': 'auths.public-python-recipe-rehearsal/1', 'sdk': package, + 'repository_sdk_import': False, 'provider_credentials': False, 'recipes': reports} + encoded = json.dumps(report, indent=2) + '\n' + if args.out: + args.out.parent.mkdir(parents=True, exist_ok=True) + args.out.write_text(encoded) + print(encoded, end='') + + +if __name__ == '__main__': + main() diff --git a/bindings/recipes/typescript/02-verify-authority.ts b/bindings/recipes/typescript/02-verify-authority.ts index 8e5d9757b..b002e6272 100644 --- a/bindings/recipes/typescript/02-verify-authority.ts +++ b/bindings/recipes/typescript/02-verify-authority.ts @@ -2,7 +2,7 @@ import { readFile } from "node:fs/promises"; import { createVerifier } from "@auths-dev/sdk/verify"; const fixture = process.env.AUTHS_RECIPE_FIXTURE; -if (fixture === undefined) throw new Error("AUTHS_RECIPE_FIXTURE is required"); +if (fixture === undefined) throw new Error("Set AUTHS_RECIPE_FIXTURE to the directory containing workflow.proof.cbor, workflow.action.cbor and workflow.context.cbor; see the recipe setup instructions."); const [proof, action, trustedContext] = await Promise.all([ readFile(`${fixture}/workflow.proof.cbor`), readFile(`${fixture}/workflow.action.cbor`), diff --git a/docs/product/recipes/01_AUTHENTICATE_IDENTITY.md b/docs/product/recipes/01_AUTHENTICATE_IDENTITY.md index 7cfa473d8..8f4069467 100644 --- a/docs/product/recipes/01_AUTHENTICATE_IDENTITY.md +++ b/docs/product/recipes/01_AUTHENTICATE_IDENTITY.md @@ -86,11 +86,11 @@ if __name__ == "__main__": ## What Auths protected -The recipe uses Rust-owned canonicalization, commitments, authorization, and receipt/recovery semantics. TypeScript and Python coordinate bounded I/O but cannot mint an effect-capable authorization object. +The native Rust implementation checks the identity, signature and exact message binding. This authenticates bytes; it grants no authority and performs no provider write. ## Break it safely -The executable includes its failure exercise and asserts that no unauthorized or duplicate provider entry occurs. CI fails if the adversarial result changes. +The Python example changes the message while keeping the original signature and requires authentication to fail. No provider is contacted. ## Take it to production diff --git a/docs/product/recipes/02_VERIFY_AUTHORITY.md b/docs/product/recipes/02_VERIFY_AUTHORITY.md index 1dbcc0a65..a8ee9ab09 100644 --- a/docs/product/recipes/02_VERIFY_AUTHORITY.md +++ b/docs/product/recipes/02_VERIFY_AUTHORITY.md @@ -8,6 +8,34 @@ Verify existing proof, action, and trust bytes without gaining an execution capa Use a supported Node.js or CPython runtime and install the single Auths package. The executable source below is run against the packed npm artifact and wheel in CI. +This recipe reads existing canonical proof, action and trusted-context bytes. Put them in one directory as `workflow.proof.cbor`, `workflow.action.cbor` and `workflow.context.cbor`, and set `AUTHS_RECIPE_FIXTURE` to that directory. + +For a disposable example, run this with the installed Python package. It generates its own in-memory signing key and public test artifacts; it needs no checkout, provider credential or downloaded fixture. The generated context trusts that disposable key only and is not production trust. + +```python +from pathlib import Path +from auths.testkit import development_mcp_artifacts + +artifacts = development_mcp_artifacts( + service="recipe-demo", name="publish_report", arguments={"report": "weekly"} +) +directory = Path("auths-demo-evidence") +directory.mkdir(exist_ok=True) +for name, data in [ + ("proof", artifacts.proof), + ("action", artifacts.action), + ("context", artifacts.trusted_context), +]: + (directory / ("workflow." + name + ".cbor")).write_bytes(data) +``` + +Save the verification program below as `verify_authority.py` or compile the TypeScript program, then run: + +```sh +AUTHS_RECIPE_FIXTURE="$PWD/auths-demo-evidence" python verify_authority.py +AUTHS_RECIPE_FIXTURE="$PWD/auths-demo-evidence" node verify_authority.js +``` + ## TypeScript Source: `typescript/02-verify-authority.ts` @@ -17,7 +45,7 @@ import { readFile } from "node:fs/promises"; import { createVerifier } from "@auths-dev/sdk/verify"; const fixture = process.env.AUTHS_RECIPE_FIXTURE; -if (fixture === undefined) throw new Error("AUTHS_RECIPE_FIXTURE is required"); +if (fixture === undefined) throw new Error("Set AUTHS_RECIPE_FIXTURE to the directory containing workflow.proof.cbor, workflow.action.cbor and workflow.context.cbor; see the recipe setup instructions."); const [proof, action, trustedContext] = await Promise.all([ readFile(`${fixture}/workflow.proof.cbor`), readFile(`${fixture}/workflow.action.cbor`), @@ -43,7 +71,14 @@ from pathlib import Path from auths.verify import VerificationInput, verify -root = Path(os.environ["AUTHS_RECIPE_FIXTURE"]) +fixture = os.environ.get("AUTHS_RECIPE_FIXTURE") +if not fixture: + raise SystemExit( + "Set AUTHS_RECIPE_FIXTURE to the directory containing workflow.proof.cbor, " + "workflow.action.cbor and workflow.context.cbor; " + "see docs/product/recipes/02_VERIFY_AUTHORITY.md for a disposable example." + ) +root = Path(fixture) proof = (root / "workflow.proof.cbor").read_bytes() action = (root / "workflow.action.cbor").read_bytes() context = (root / "workflow.context.cbor").read_bytes() @@ -77,11 +112,11 @@ print( ## What Auths protected -The recipe uses Rust-owned canonicalization, commitments, authorization, and receipt/recovery semantics. TypeScript and Python coordinate bounded I/O but cannot mint an effect-capable authorization object. +The native Rust verifier checks the supplied proof against the exact action and explicit trusted context. An authorized result is an offline verification result; it acquires no credential and performs no provider write. ## Break it safely -The executable includes its failure exercise and asserts that no unauthorized or duplicate provider entry occurs. CI fails if the adversarial result changes. +The Python example changes one action byte and requires authorization to fail. The trust context is an explicit input; do not replace governed production trust with a self-trusting test context. ## Take it to production diff --git a/docs/research/INDEPENDENT_OPERATOR_RC_REHEARSAL.md b/docs/research/INDEPENDENT_OPERATOR_RC_REHEARSAL.md new file mode 100644 index 000000000..c218de5ca --- /dev/null +++ b/docs/research/INDEPENDENT_OPERATOR_RC_REHEARSAL.md @@ -0,0 +1,43 @@ +# Independent operator RC rehearsal + +Status: in progress, 7 October 2026. This records the agent acting as a fresh +operator; it does not claim an unfamiliar human trial or security review. + +## Installed Python recipes + +The current recipe manifest contains two effect-free verification recipes. +A fresh Linux amd64 Docker container installed the downloaded `0.0.1rc1` wheel +(SHA-256 `6d079aa4960256a754315d911b55d80bc02848b1ad14225420ea8eae4905656f`). +Networking was disabled. Only the wheel and copied public documentation code +were mounted; no checkout or provider credential reached the application. + +| Observation | Resolution | Verification | +| --- | --- | --- | +| The identity recipe authenticated and rejected a changed message. | No change required. | Actual installed-wheel result: `authenticated`, `changedRejected: true`. | +| Copying the authority recipe produced `KeyError: AUTHS_RECIPE_FIXTURE`; its input files were undocumented. | The generated page now lists the exact three input files, supplies a runnable installed-SDK setup example and shows the environment setting. The program reports a useful missing-input message. | A new clean container ran setup and the recipe: `authorized`, `changedRejected: true`. | +| Both generated pages claimed receipt/recovery and duplicate-provider-entry exercises despite being effect-free. | The generator now describes each actual verification boundary and the Python mutation check precisely. | Pages regenerated from their maintained programs. | + +The authority setup uses the existing native SDK authoring helper, a fresh +in-memory key and explicit disposable trust. It writes only public proof, +action and context bytes. It grants no production trust or execution capability. +The current CI job's historical “ten recipes” display name is stale; coverage is +determined by `bindings/recipes/manifest.json`, not that label. + +## Provider operator journeys + +The real Airtable update and platform-account Stripe test refund passed using +installed artifacts, separate application/operator identities, private staged +credentials and durable state. The exact signed development reports, support +bundles and exclusions are under `qualification/simulation/evidence/`. +Docker Desktop host file sharing did not enforce the intended credential-owner +check; the maintained harnesses now stage credential stdin inside the container. +Gateway proof authoring uses its reviewed verifier configuration. Stripe cleanup +reads the test PaymentIntent and charge; refund objects have no `livemode` field. + +## Remaining release verification + +The tested wheel came from CI, not a published GitHub release. Once promotion +completes, download the actual release asset, verify its manifest/checksum and +repeat these clean-install runs. Protected production qualification and the +full production evidence wall remain unfinished; development rehearsals cannot +supply those claims. From ec75deb1d749afe5f98df37f7afd925e3566ac08 Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 02:54:51 +0100 Subject: [PATCH 051/108] Specify bounded commissioning authority for first qualification --- docs/PROGRAM_BOARD.md | 7 ++ ...d-qualification-commissioning-authority.md | 109 ++++++++++++++++++ ...gateway-polish-and-recipe-qualification.md | 16 +++ qualification/README.md | 7 +- 4 files changed, 138 insertions(+), 1 deletion(-) create mode 100644 docs/adr/0016-bounded-qualification-commissioning-authority.md diff --git a/docs/PROGRAM_BOARD.md b/docs/PROGRAM_BOARD.md index a21acd56f..845c3274d 100644 --- a/docs/PROGRAM_BOARD.md +++ b/docs/PROGRAM_BOARD.md @@ -481,3 +481,10 @@ passed. Evidence is retained under `qualification/simulation/evidence/stripe-platform-live-2026-10-07/`. Connect scope is excluded; both real provider rehearsals remain development evidence and do not change production qualification or stable readiness. + +The next bootstrap design is recorded in proposed ADR 0016. It separates +finite, signed operator commissioning authority from normal application +qualification, with exact candidate/action/run bindings and durable lease +bounds. No gateway accepts such a permit yet; the ordinary production gate +and stable-readiness result remain unchanged. The existing protected AWS +custody workflow provides a reusable infrastructure starting point. diff --git a/docs/adr/0016-bounded-qualification-commissioning-authority.md b/docs/adr/0016-bounded-qualification-commissioning-authority.md new file mode 100644 index 000000000..95da8c55f --- /dev/null +++ b/docs/adr/0016-bounded-qualification-commissioning-authority.md @@ -0,0 +1,109 @@ +# ADR 0016: Bound the first qualification run with explicit commissioning authority + +**Status:** Proposed. No commissioning authority is implemented or accepted by +any current gateway. Ordinary production leases still require qualification. + +**Date:** 7 October 2026 + +## Problem + +The shipped gateway requires an exact-tuple qualification before every +production lease. Issuance requires provider effects through that shipped +candidate before it can sign the first qualification. A development file-store +installation or differently compiled test executable changes the tuple, so its +measurements cannot break this cycle. Fabricating an initial qualification, +relaxing ordinary production policy or substituting simulated provider evidence +would invalidate the claim. + +## Proposed authority boundary + +Introduce a separate, signed, finite qualification-run permit. Its purpose is +authorizing a reviewed commissioning run, not certifying a completed run. The +ordinary application socket continues to require a current qualification. +Only an authenticated private operator session may use commissioning authority; +normal application commands cannot select that session or authority kind. +Both paths must use the same shipped verifier, recipe compiler, reservation, +attempt, credential and provider driver implementations. No test feature, +caller callback, provider module or unverified effect enters the runtime. + +The offline qualification root certifies a protected signer with an explicit +commissioning permission. A permit has its own closed schema and signature +domain, reusing the existing canonicalization and Ed25519 implementation. It is +not decoded as a qualification record or listed as a release qualification. +The signer runs separately from the live harness and validates reviewed offline +inputs before signing. The root key never enters a qualification runner. + +Every permit must bind: + +- the exact candidate commit, executable digest, semantic closure and production + tuple, including PostgreSQL schema and custody kind; +- the reviewed provider contract, recipe, lock and trusted-context digests; +- one protected workflow run and one ephemeral proof-authoring principal; +- reviewed disposable resource bindings and a precomputed finite set of exact + canonical action commitments; +- a maximum credential-lease count, stored atomically and durably for the permit + across both gateway instances and restarts; and +- a signed validity window of at most two hours, current signer certification + and a current root-signed revocation list. + +Resource acquisition, action authoring and independent oracle expansion happen +before permit issuance. Expected request/evidence commitments are derived from +the reviewed reference and bounded resource binding, not candidate answers. +The reference remains test/release code. Runtime permit checks compare closed +identities and commitments; they implement no provider-specific oracle. + +A permit never replaces proof verification, grant attenuation, exact approval, +recipe evaluation, critical reads, budget reservation or durable replay claims. +The principal, target, context, action and run must all match. The lease bound +is claimed durably before custody access. Expiry, revocation, exhaustion, +rollback, unavailable shared state or any mismatch refuses before a lease. +Unknown provider outcomes retain ordinary uncertainty and cannot gain a second +write through permit renewal. A denied input is terminal for those inputs. + +## Evidence and bootstrap sequence + +1. Build and install the exact production candidate with ordinary qualification + required. Demonstrate that ordinary application requests cannot lease. +2. Acquire only the reviewed disposable resources, author the finite actions, + expand the independent oracle and finish the candidate's offline evidence. +3. The protected signer validates those inputs and issues commissioning + authority for that exact run. The authenticated operator imports it. +4. Execute and independently witness the mandatory live cases through the same + shipped driver, production PostgreSQL and production custody. Persist the + actual permit, counters, observations, read-backs and redacted evidence. +5. Close and sign a truthful intermediate qualification without claiming + production readiness. Commissioning authority expires and remains consumed. +6. Import that qualification through the existing verifier. Run ordinary + production requests and the typed production doctor without commissioning + authority. Close a fresh final qualification containing those observations. +7. Only verified final qualifications can contribute to stable launch readiness. + +The two-hour window is a hard maximum, not a promise that the whole wall fits. +Timeout or incomplete evidence produces no qualification. Cleanup retains +operator authority over its own fixtures and does not create provider evidence. +Renewal cannot reset attempt identities or permit counters. + +## Required implementation and rejection evidence + +This proposal is incomplete until closed schemas, signer permissions, sealed +runtime authority, durable PostgreSQL accounting, authenticated operator +commands, independent resource/oracle binding and the protected workflow are +implemented together. New state rejects obsolete disposable schemas under the +prelaunch contract; no compatibility reader or hidden policy relaxation is added. + +Tests must exercise forged signatures, another root/signer/run/principal, +changed context/action/recipe/target, excessive or empty allowlists, time and +revocation faults, unsupported permissions, exhausted counters, two-host races, +crashes around lease claims, restart/rollback, ordinary application attempts to +use a permit, and failure before credentials. The first actual protected run +must show no ordinary lease before qualification, measured finite commissioned +leases, and ordinary qualified operation after import. CI and the signed evidence +must name the exact shipped candidate. Simulations cannot establish this claim. + +## Consequences + +This adds explicit operator commissioning authority and its associated trust +obligation. It does not make the first qualification appear to preexist its own +evidence. Commissioning state remains distinct from `qualified`; readiness +never derives true from a permit. The normal production application gate stays +closed until the existing qualification chain verifies. diff --git a/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md b/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md index 6b4267b5c..ec501eb1b 100644 --- a/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md +++ b/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md @@ -1761,3 +1761,19 @@ The exact signed simulation report and support bundle are retained under Both live provider journeys now have measured development evidence. They still exclude protected production qualification and the full production evidence wall; the normal production lease gate remains unchanged. + +### 22.3 First-run commissioning design (2026-10-07) + +[ADR 0016](../adr/0016-bounded-qualification-commissioning-authority.md) proposes +a separate, finite signed authority for an authenticated operator qualification +run against the exact production candidate. It binds reviewed resource/action +commitments, the production tuple, trusted context, one protected run and actor, +durable shared lease bounds, time and revocation. Normal application leases +remain subject to the current qualification gate. A permit is neither a +qualification nor evidence of provider behavior or production readiness. + +This is a design prerequisite, not implementation completion or a change to +the current gateway's accepted authority. The full signed schema, issuance, +sealed runtime path, PostgreSQL accounting, authenticated operator interface, +protected workflow and rejection/live evidence must land together before the +bootstrap can be claimed resolved. Epic 5's done conditions remain unchanged. diff --git a/qualification/README.md b/qualification/README.md index ea5a5fa24..9a1edc6d7 100644 --- a/qualification/README.md +++ b/qualification/README.md @@ -56,7 +56,12 @@ attestation. Therefore its first qualification cannot bootstrap itself. A development installation or `testkit-production-unqualified` executable changes the target or shipped bytes and cannot establish the required production claim. That real-production authority question remains separate from the requested -simulation; the shipping lease gate has no bypass. +simulation; the shipping lease gate has no bypass. A proposed solution is +[ADR 0016](../docs/adr/0016-bounded-qualification-commissioning-authority.md): +a finite signed permit for an authenticated private qualification-run session, +with exact action commitments, durable lease accounting and a fixed expiry. +It is not implemented, cannot qualify a family, and cannot enable an ordinary +application lease. The current executable corpus also fixes exact request/evidence digests before running, while disposable live resource identifiers may be created during setup. From a86f4da414b3bb82bafc6fb66139d62d1a722712 Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 02:55:28 +0100 Subject: [PATCH 052/108] Describe installed recipe coverage without a stale count --- .github/workflows/sdk-recipes.yml | 2 +- docs/research/INDEPENDENT_OPERATOR_RC_REHEARSAL.md | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/sdk-recipes.yml b/.github/workflows/sdk-recipes.yml index 37f9ed48e..8774a8ee0 100644 --- a/.github/workflows/sdk-recipes.yml +++ b/.github/workflows/sdk-recipes.yml @@ -33,7 +33,7 @@ permissions: jobs: installed-artifacts: - name: ten installed-artifact recipes + name: installed-artifact recipes runs-on: ubuntu-latest steps: - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 diff --git a/docs/research/INDEPENDENT_OPERATOR_RC_REHEARSAL.md b/docs/research/INDEPENDENT_OPERATOR_RC_REHEARSAL.md index c218de5ca..1bf667475 100644 --- a/docs/research/INDEPENDENT_OPERATOR_RC_REHEARSAL.md +++ b/docs/research/INDEPENDENT_OPERATOR_RC_REHEARSAL.md @@ -20,8 +20,9 @@ were mounted; no checkout or provider credential reached the application. The authority setup uses the existing native SDK authoring helper, a fresh in-memory key and explicit disposable trust. It writes only public proof, action and context bytes. It grants no production trust or execution capability. -The current CI job's historical “ten recipes” display name is stale; coverage is -determined by `bindings/recipes/manifest.json`, not that label. +The CI job's historical “ten recipes” display name overstated the current +manifest. It now says “installed-artifact recipes”; coverage is determined by +`bindings/recipes/manifest.json` and the observed results. ## Provider operator journeys From 37b87961c16ce78b793147e1ad61df5f7b52f4fc Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 03:17:39 +0100 Subject: [PATCH 053/108] Add purpose-bound qualification commissioning artifacts --- .../qualification/commissioning-v1.json | 17 + compliance.toml | 28 +- ...d-qualification-commissioning-authority.md | 26 +- .../src/commissioning.rs | 99 +++ .../src/lib.rs | 4 +- .../src/sign.rs | 142 +++- .../tests/commissioning.rs | 742 ++++++++++++++++++ .../src/commissioning.rs | 430 ++++++++++ .../src/commissioning/tests.rs | 125 +++ .../auths-recipe-qualification/src/lib.rs | 9 + .../auths-recipe-qualification/src/release.rs | 2 + .../auths-recipe-qualification/src/verify.rs | 2 +- .../auths-gateway/semantic-closure.json | 2 +- .../auths-gateway/src/semantic_closure.rs | 2 +- 14 files changed, 1608 insertions(+), 22 deletions(-) create mode 100644 bindings/fixtures/qualification/commissioning-v1.json create mode 100644 product/qualification/auths-recipe-qualification-issuance/src/commissioning.rs create mode 100644 product/qualification/auths-recipe-qualification-issuance/tests/commissioning.rs create mode 100644 product/qualification/auths-recipe-qualification/src/commissioning.rs create mode 100644 product/qualification/auths-recipe-qualification/src/commissioning/tests.rs diff --git a/bindings/fixtures/qualification/commissioning-v1.json b/bindings/fixtures/qualification/commissioning-v1.json new file mode 100644 index 000000000..220a9a6c8 --- /dev/null +++ b/bindings/fixtures/qualification/commissioning-v1.json @@ -0,0 +1,17 @@ +{ + "schema": "auths.qualification-commissioning-vectors/1", + "synthetic": true, + "trust_root": "{\"public_key_b64\":\"0EqyMnQrtKs6E2i9RhXk5tAiSrcaAWuvhSCjMsl3hzc\",\"root_id\":\"test-root\",\"schema\":\"auths.qualification-trust-root/1\",\"signature_suite\":\"ed25519-v1\"}", + "signer_certificate": "{\"root_signature_b64\":\"CbNmJUTovHK87FHlPhOC2TtvjfxmR5FHDvg4EAsNSjLR5bjqqG4zBOhDwbwXlNN97La1kMEVU57h3ApQVI_MCg\",\"statement\":{\"issued_at\":1789913600,\"not_after\":1790086400,\"not_before\":1789913600,\"permitted_artifact_kinds\":[\"qualification-commissioning-permit\"],\"public_key_b64\":\"oJql9HpnWYAv-VX43C0qFKXJnSO-l_hkEn_5ODRVpPA\",\"root_id\":\"test-root\",\"schema\":\"auths.qualification-signer-certificate/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"test-commissioner\",\"signer_kind\":\"protected-software-release-key-v1\"}}", + "revocation_list": "{\"root_signature_b64\":\"sAtYxcGQsy05npek7vQrBcpqiHKWqcEV-g4EowFJhxs4guxt73ual7FEngULuO3H15qIZLIy4HrbJdyISzJVAA\",\"statement\":{\"issued_at\":1789996400,\"next_update\":1790086400,\"revoked_qualifications\":[],\"revoked_signers\":[],\"root_id\":\"test-root\",\"schema\":\"auths.qualification-revocation-list/1\",\"sequence\":1}}", + "permit": "{\"signature_b64\":\"3FmM2kWZfmUu0xmRVN3C_CYddjGCeOxm3dd7iHL16oawbDBh6TqOwGqc639oYL63ATmYCxh6e3HsPRqQkS1DAQ\",\"statement\":{\"binding\":{\"allowed_actions\":[\"6363636363636363636363636363636363636363636363636363636363636363\",\"6464646464646464646464646464646464646464646464646464646464646464\"],\"maximum_credential_leases\":32,\"offline_evidence\":{\"conformance_sha256\":\"8749fb03dc89fe583529f59c613c78319e893898118092c61344812be78d1b5c\",\"differential_sha256\":\"5f22f2e011050cbabf1f58bdf92a2912fa489353309b594b4db327865e82cd7f\"},\"principal_sha256\":\"6060606060606060606060606060606060606060606060606060606060606060\",\"protected_run\":\"github.com/auths-dev/auths-proof/actions/runs/1/attempts/1\",\"provider_environment_class\":\"provider-test-mode\",\"resources_sha256\":\"6262626262626262626262626262626262626262626262626262626262626262\",\"source_commit\":\"0123456789abcdef0123456789abcdef01234567\",\"trusted_context_sha256\":\"6161616161616161616161616161616161616161616161616161616161616161\",\"tuple\":{\"compiled_recipe_sha256\":\"1111111111111111111111111111111111111111111111111111111111111111\",\"gateway_semantic_closure_sha256\":\"4444444444444444444444444444444444444444444444444444444444444444\",\"profile_lock_sha256\":\"2222222222222222222222222222222222222222222222222222222222222222\",\"provider_contract_id\":\"3333333333333333333333333333333333333333333333333333333333333333\",\"recipe_family\":\"example-refund-v1\",\"target\":{\"arch\":\"x86_64\",\"credential_store_kind\":\"aws-secrets-manager-v1\",\"gateway_build_sha256\":\"5555555555555555555555555555555555555555555555555555555555555555\",\"gateway_package\":\"auths-gateway\",\"gateway_version\":\"1.0.0-rc.1\",\"os\":\"linux\",\"store_kind\":\"postgresql-v1\",\"store_schema\":\"auths.gateway-store/1\"}}},\"issued_at\":1790000000,\"not_after\":1790007200,\"not_before\":1790000000,\"schema\":\"auths.qualification-commissioning-permit/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"test-commissioner\"}}", + "permit_digest": "1d4f2378f8514c4697d7eeee3d4c5c33c82046d5b80b44ba84c8f5d47e84632b", + "budget_scope_sha256": "01640eb7b447d8b909e6955a186f95e3c7bc6765174ee23d8b3dbd0db1c845e5", + "budget_binding_sha256": "b31130f5b9daf728bac55ca8591eedc844919f460e0852f5a5db8febec3c1da0", + "limits": { + "actions": 256, + "leases": 1024, + "seconds": 7200, + "bytes": 32768 + } +} diff --git a/compliance.toml b/compliance.toml index c6581ec06..6a978ce54 100644 --- a/compliance.toml +++ b/compliance.toml @@ -1161,18 +1161,21 @@ kind = "cargo" layer = "product" path = "product/qualification/auths-recipe-qualification" core_apis = [] -protocol_versions = ["auths.provider-contract/1", "auths.recipe-qualification/1", "auths.recipe-qualification-attestation/1", "auths.qualification-trust-root/1", "auths.qualification-signer-certificate/1", "auths.qualification-revocation-list/1", "auths.qualification-release-index/1", "auths.qualification-evidence/1", "auths.qualification-tuple/1", "auths.gateway-semantic-closure/1", "auths.qualification-schema-vectors/1", "auths.qualification-verification-vectors/1"] -wire_objects = ["GatewaySemanticClosure", "ProviderContract", "QualificationEvidence", "QualificationReleaseIndex", "QualificationRevocationList", "QualificationSignerCertificate", "QualificationTrustRoot", "RecipeQualificationAttestation", "RecipeQualificationRecord"] +protocol_versions = ["auths.provider-contract/1", "auths.recipe-qualification/1", "auths.recipe-qualification-attestation/1", "auths.qualification-commissioning-permit/1", "auths.qualification-commissioning-budget-key/1", "auths.qualification-commissioning-budget-binding/1", "auths.qualification-commissioning-vectors/1", "auths.qualification-trust-root/1", "auths.qualification-signer-certificate/1", "auths.qualification-revocation-list/1", "auths.qualification-release-index/1", "auths.qualification-evidence/1", "auths.qualification-tuple/1", "auths.gateway-semantic-closure/1", "auths.qualification-schema-vectors/1", "auths.qualification-verification-vectors/1"] +wire_objects = ["QualificationCommissioningPermit", "GatewaySemanticClosure", "ProviderContract", "QualificationEvidence", "QualificationReleaseIndex", "QualificationRevocationList", "QualificationSignerCertificate", "QualificationTrustRoot", "RecipeQualificationAttestation", "RecipeQualificationRecord"] fixture_suites = ["bindings/fixtures/qualification"] principal_families = [] signature_families = ["ed25519-v1"] profiles = [] transports = [] -configuration_inputs = ["qualification-trust-root", "qualification-signer-certificate", "qualification-revocation-list", "qualification-release-index"] +configuration_inputs = ["commissioning-permit", "qualification-trust-root", "qualification-signer-certificate", "qualification-revocation-list", "qualification-release-index"] security_state = [] [packages.auths-recipe-qualification.claims] independent-semantic-implementation = [ + "product/qualification/auths-recipe-qualification/src/commissioning/tests.rs#frozen_commissioning_bytes_authenticate_only_their_exact_binding", + "product/qualification/auths-recipe-qualification/src/commissioning/tests.rs#every_single_bit_signature_mutation_is_refused", + "product/qualification/auths-recipe-qualification/src/commissioning/tests.rs#unsigned_shape_never_accepts_extra_duplicate_or_unknown_members", "product/qualification/auths-recipe-qualification/src/vectors/schemas.rs#every_valid_artifact_decodes", "product/qualification/auths-recipe-qualification/src/vectors/schemas.rs#every_structural_case_is_refused_with_its_reason", "product/qualification/auths-recipe-qualification/src/vectors/schemas.rs#contract_drift_changes_the_contract_identifier", @@ -1187,18 +1190,29 @@ kind = "cargo" layer = "product" path = "product/qualification/auths-recipe-qualification-issuance" core_apis = [] -protocol_versions = ["auths.recipe-qualification/1", "auths.recipe-qualification-attestation/1", "auths.qualification-trust-root/1", "auths.qualification-signer-certificate/1", "auths.qualification-revocation-list/1", "auths.qualification-release-index/1", "auths.qualification-evidence/1"] -wire_objects = ["QualificationEvidence", "QualificationReleaseIndex", "QualificationRevocationList", "QualificationSignerCertificate", "QualificationTrustRoot", "RecipeQualificationAttestation", "RecipeQualificationRecord"] +protocol_versions = ["auths.recipe-qualification/1", "auths.recipe-qualification-attestation/1", "auths.qualification-commissioning-permit/1", "auths.qualification-commissioning-budget-key/1", "auths.qualification-commissioning-budget-binding/1", "auths.qualification-commissioning-vectors/1", "auths.qualification-trust-root/1", "auths.qualification-signer-certificate/1", "auths.qualification-revocation-list/1", "auths.qualification-release-index/1", "auths.qualification-evidence/1"] +wire_objects = ["QualificationCommissioningPermit", "QualificationEvidence", "QualificationReleaseIndex", "QualificationRevocationList", "QualificationSignerCertificate", "QualificationTrustRoot", "RecipeQualificationAttestation", "RecipeQualificationRecord"] fixture_suites = [] principal_families = [] signature_families = ["ed25519-v1"] profiles = [] transports = [] -configuration_inputs = ["record-draft", "stage-case-reports", "executable-qualification-corpus", "candidate-observations", "family-harness", "qualification-trust-root-key-file", "release-signer-key-file"] -security_state = ["qualification-trust-root-key", "release-signer-key"] +configuration_inputs = ["record-draft", "stage-case-reports", "executable-qualification-corpus", "candidate-observations", "family-harness", "qualification-trust-root-key-file", "release-signer-key-file", "commissioning-proposal", "commissioning-signer-key-file"] +security_state = ["qualification-trust-root-key", "release-signer-key", "commissioning-signer-key"] [packages.auths-recipe-qualification-issuance.claims] proof-author-or-assembler = [ + "product/qualification/auths-recipe-qualification-issuance/tests/commissioning.rs#a_commissioning_permit_never_qualifies_ordinary_production", + "product/qualification/auths-recipe-qualification-issuance/tests/commissioning.rs#commissioning_and_release_signers_have_separate_purposes", + "product/qualification/auths-recipe-qualification-issuance/tests/commissioning.rs#each_signature_root_and_domain_is_required", + "product/qualification/auths-recipe-qualification-issuance/tests/commissioning.rs#every_runtime_binding_must_equal_the_reviewed_session", + "product/qualification/auths-recipe-qualification-issuance/tests/commissioning.rs#commissioning_windows_are_half_open_and_require_trusted_time", + "product/qualification/auths-recipe-qualification-issuance/tests/commissioning.rs#revocations_are_permanent_and_an_older_list_cannot_restore_authority", + "product/qualification/auths-recipe-qualification-issuance/tests/commissioning.rs#proposal_rechecks_exact_offline_artifacts_and_all_required_scenarios", + "product/qualification/auths-recipe-qualification-issuance/tests/commissioning.rs#action_and_lease_bounds_are_exact_and_never_silently_repaired", + "product/qualification/auths-recipe-qualification-issuance/tests/commissioning.rs#renewal_cannot_change_the_durable_budget_identity_or_binding", + "product/qualification/auths-recipe-qualification-issuance/tests/commissioning.rs#commissioning_artifact_fixture_is_current", + "product/qualification/auths-recipe-qualification-issuance/tests/issuance.rs#a_record_is_assembled_from_its_evidence_and_closes_over_it", "product/qualification/auths-recipe-qualification-issuance/tests/issuance.rs#a_run_with_a_failed_case_produces_no_evidence", "product/qualification/auths-recipe-qualification-issuance/tests/issuance.rs#assembly_refuses_a_wall_that_is_not_whole", diff --git a/docs/adr/0016-bounded-qualification-commissioning-authority.md b/docs/adr/0016-bounded-qualification-commissioning-authority.md index 95da8c55f..31869209f 100644 --- a/docs/adr/0016-bounded-qualification-commissioning-authority.md +++ b/docs/adr/0016-bounded-qualification-commissioning-authority.md @@ -1,7 +1,10 @@ # ADR 0016: Bound the first qualification run with explicit commissioning authority -**Status:** Proposed. No commissioning authority is implemented or accepted by -any current gateway. Ordinary production leases still require qualification. +**Status:** Implementing. The closed permit, commissioning-only signer purpose, +offline evidence closure and pure signature/binding verifier are implemented. +No current gateway accepts commissioning authority. Private operator sessions, +durable shared accounting and the protected live workflow remain required. +Ordinary production leases still require qualification. **Date:** 7 October 2026 @@ -100,6 +103,25 @@ must show no ordinary lease before qualification, measured finite commissioned leases, and ordinary qualified operation after import. CI and the signed evidence must name the exact shipped candidate. Simulations cannot establish this claim. +The initial artifact implementation keeps its run/family budget key independent +of signature, signer and validity window. Its immutable budget binding commits +to every candidate, principal, context, resource, environment, offline-evidence, +action and ceiling member. A durable registration must refuse a changed binding +at the same key; renewal must consume the original counter. Windows are +half-open, and both the issue-to-expiry and start-to-expiry durations are capped +at two hours. Release certificates carry no commissioning permission; +commissioning certificates carry no attestation or index permission. A +mixed-purpose certificate is refused by the commissioning verifier. + +The public synthetic vector is +`bindings/fixtures/qualification/commissioning-v1.json`. Native tests consume +these frozen bytes without issuance code. They cover strict decoding and every +single-bit signature mutation; issuance tests additionally cover purpose/root/ +domain separation, exact runtime bindings, time/revocation boundaries, finite +action/lease bounds, evidence omissions and stable renewal identities. These +tests establish the pure artifact boundary only, not durable consumption or a +completed production bootstrap. + ## Consequences This adds explicit operator commissioning authority and its associated trust diff --git a/product/qualification/auths-recipe-qualification-issuance/src/commissioning.rs b/product/qualification/auths-recipe-qualification-issuance/src/commissioning.rs new file mode 100644 index 000000000..0c7fb9812 --- /dev/null +++ b/product/qualification/auths-recipe-qualification-issuance/src/commissioning.rs @@ -0,0 +1,99 @@ +//! Release-side closure of a finite commissioning proposal. Provider-specific +//! resource/oracle expansion remains in the reviewed family harness, never in +//! the gateway or this shared artifact verifier. + +use crate::IssuanceError; +use auths_recipe_qualification::{ + ClosureFault, CommissioningBinding, EvidenceMemberKind, QualificationEvidence, Scenario, +}; + +/// Immutable reviewed run bindings and the offline evidence they name. +/// +/// Only [`Self::assemble`] constructs this value. It rederives both evidence +/// digests, source/tuple identity and all required offline scenarios. The +/// protected workflow must separately derive resources and allowed actions +/// from its reviewed reference before calling it; candidate results cannot +/// supply an expected request or evidence commitment. +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct CommissioningProposal { + binding: CommissioningBinding, + conformance: QualificationEvidence, + differential: QualificationEvidence, +} + +impl CommissioningProposal { + /// Re-verifies the two canonical offline artifacts and the finite bindings. + /// + /// This is evidence closure, not a provider qualification. The live wall + /// does not exist yet and this value cannot enter a release index. + /// + /// # Errors + /// + /// Returns [`IssuanceError::Closure`] for a changed artifact, missing + /// required offline scenario or another candidate/member, and + /// [`IssuanceError::Format`] for nonproduction, empty, excessive or + /// unordered authority. Inputs are not sorted or silently repaired. + pub fn assemble( + binding: CommissioningBinding, + conformance: QualificationEvidence, + differential: QualificationEvidence, + ) -> Result { + binding.validate()?; + let tuple_digest = binding.tuple.digest()?; + for (artifact, member, expected_digest) in [ + ( + &conformance, + EvidenceMemberKind::Conformance, + binding.offline_evidence.conformance_sha256, + ), + ( + &differential, + EvidenceMemberKind::Differential, + binding.offline_evidence.differential_sha256, + ), + ] { + let body = artifact.body(); + if body.member != member { + return Err(ClosureFault::MemberSet.into()); + } + if artifact.digest() != expected_digest { + return Err(ClosureFault::Digest.into()); + } + if body.commit != binding.source_commit || body.tuple_sha256 != tuple_digest { + return Err(ClosureFault::Candidate.into()); + } + if body + .cases + .iter() + .any(|case| case.unauthorized_provider_entries != 0) + { + return Err(IssuanceError::CaseFailed); + } + for scenario in Scenario::ALL { + if scenario.always_required() + && scenario.member() == member + && !body.cases.iter().any(|case| case.scenario == scenario) + { + return Err(ClosureFault::Scenario.into()); + } + } + } + Ok(Self { + binding, + conformance, + differential, + }) + } + + /// Exact bindings checked by this proposal's constructor. + #[must_use] + pub const fn binding(&self) -> &CommissioningBinding { + &self.binding + } + + /// Re-verified conformance and differential evidence, in member order. + #[must_use] + pub const fn offline_evidence(&self) -> [&QualificationEvidence; 2] { + [&self.conformance, &self.differential] + } +} diff --git a/product/qualification/auths-recipe-qualification-issuance/src/lib.rs b/product/qualification/auths-recipe-qualification-issuance/src/lib.rs index 1d7b395d1..d4351cc3b 100644 --- a/product/qualification/auths-recipe-qualification-issuance/src/lib.rs +++ b/product/qualification/auths-recipe-qualification-issuance/src/lib.rs @@ -12,6 +12,7 @@ #![forbid(unsafe_code)] +mod commissioning; mod error; pub mod execution; mod proposal; @@ -20,6 +21,7 @@ pub mod stages; #[cfg(feature = "testkit")] pub mod testkit; +pub use commissioning::CommissioningProposal; pub use error::IssuanceError; pub use proposal::{CaseReport, NotApplicable, QualificationProposal, RecordDraft, evidence}; -pub use sign::{CertificateRequest, ReleaseSigner, RootSigner, SigningSeed}; +pub use sign::{CertificateRequest, CommissioningSigner, ReleaseSigner, RootSigner, SigningSeed}; diff --git a/product/qualification/auths-recipe-qualification-issuance/src/sign.rs b/product/qualification/auths-recipe-qualification-issuance/src/sign.rs index d00d9f73a..85dc2ffe3 100644 --- a/product/qualification/auths-recipe-qualification-issuance/src/sign.rs +++ b/product/qualification/auths-recipe-qualification-issuance/src/sign.rs @@ -1,11 +1,13 @@ -//! The two signing roles. A trust root signs signer certificates and +//! The distinct signing roles. A trust root signs signer certificates and //! revocation lists. A release signer signs attestations and the release -//! index. Neither type has a method for the other's artifacts. +//! index. A commissioning signer signs finite run permits. None can sign +//! another role's artifacts. -use crate::{IssuanceError, QualificationProposal}; +use crate::{CommissioningProposal, IssuanceError, QualificationProposal}; use auths_recipe_qualification::{ - ATTESTATION_SCHEMA, AttestationBody, AttestationStatement, PublicKeyB64, - QualificationArtifactKind, QualificationId, QualificationReleaseIndex, + ATTESTATION_SCHEMA, AttestationBody, AttestationStatement, COMMISSIONING_PERMIT_SCHEMA, + CommissioningPermitBody, CommissioningPermitStatement, PublicKeyB64, QualificationArtifactKind, + QualificationCommissioningPermit, QualificationId, QualificationReleaseIndex, QualificationRevocationList, QualificationRootId, QualificationSignatureSuite, QualificationSignerCertificate, QualificationSignerId, QualificationSignerKind, QualificationTrustRoot, RELEASE_INDEX_SCHEMA, REVOCATION_LIST_SCHEMA, @@ -141,6 +143,39 @@ impl RootSigner { pub fn certify( &self, request: CertificateRequest, + ) -> Result { + self.certify_for( + request, + vec![ + QualificationArtifactKind::QualificationReleaseIndex, + QualificationArtifactKind::RecipeQualificationAttestation, + ], + ) + } + + /// Certifies a commissioning signer for finite permits only. + /// + /// The certificate carries no attestation or release-index permission. + /// This offline ceremony does not authorize any action: a later protected + /// signer must re-verify a closed commissioning proposal. + /// + /// # Errors + /// + /// Returns [`IssuanceError::Format`] for an invalid certificate window. + pub fn certify_commissioner( + &self, + request: CertificateRequest, + ) -> Result { + self.certify_for( + request, + vec![QualificationArtifactKind::QualificationCommissioningPermit], + ) + } + + fn certify_for( + &self, + request: CertificateRequest, + permitted_artifact_kinds: Vec, ) -> Result { let mut body = SignerCertificateBody { statement: SignerCertificateStatement { @@ -152,10 +187,7 @@ impl RootSigner { issued_at: request.issued_at, not_before: request.not_before, not_after: request.not_after, - permitted_artifact_kinds: vec![ - QualificationArtifactKind::QualificationReleaseIndex, - QualificationArtifactKind::RecipeQualificationAttestation, - ], + permitted_artifact_kinds, root_id: self.root.body().root_id.clone(), }, root_signature_b64: SignatureB64::from_bytes(&[0; 64]), @@ -209,6 +241,98 @@ impl fmt::Debug for RootSigner { } } +/// A protected commissioning key, able to sign closed finite proposals only. +/// It has no release-index, attestation, certificate or revocation method. +pub struct CommissioningSigner { + key: SigningKey, + certificate: QualificationSignerCertificate, +} + +impl CommissioningSigner { + /// Opens the exact key under a commissioning-only certificate. + /// + /// # Errors + /// + /// Returns [`IssuanceError::NotPermitted`] for a release or mixed-purpose + /// certificate, or [`IssuanceError::KeyMismatch`] for another seed. Root + /// authentication is performed independently by the receiving verifier. + pub fn open( + seed: &SigningSeed, + certificate: QualificationSignerCertificate, + ) -> Result { + if certificate.body().statement.permitted_artifact_kinds + != [QualificationArtifactKind::QualificationCommissioningPermit] + { + return Err(IssuanceError::NotPermitted); + } + if seed.public_key() != certificate.body().statement.public_key_b64 { + return Err(IssuanceError::KeyMismatch); + } + Ok(Self { + key: seed.key(), + certificate, + }) + } + + /// The public purpose certificate, without any private key material. + #[must_use] + pub const fn certificate(&self) -> &QualificationSignerCertificate { + &self.certificate + } + + /// Signs one proposal after its exact offline evidence was checked. + /// + /// The receiving gateway still authenticates the certificate under its + /// pinned root, checks current revocations and runtime bindings, and + /// claims the immutable shared budget before any custody acquisition. + /// No qualification record or readiness assertion is produced. + /// + /// # Errors + /// + /// Returns [`IssuanceError::Window`] outside the certificate's window or + /// [`IssuanceError::Format`] for any permit bound, ordering or time fault. + pub fn permit( + &self, + proposal: &CommissioningProposal, + issued_at: u64, + not_before: u64, + not_after: u64, + ) -> Result { + let signer = &self.certificate.body().statement; + if issued_at < signer.issued_at + || not_before < signer.not_before + || not_after > signer.not_after + { + return Err(IssuanceError::Window); + } + let mut body = CommissioningPermitBody { + statement: CommissioningPermitStatement { + schema: COMMISSIONING_PERMIT_SCHEMA.to_owned(), + binding: proposal.binding().clone(), + signer_id: signer.signer_id.clone(), + signature_suite: QualificationSignatureSuite::Ed25519V1, + issued_at, + not_before, + not_after, + }, + signature_b64: SignatureB64::from_bytes(&[0; 64]), + }; + // Refuse malformed authority before producing any signature bytes. + QualificationCommissioningPermit::from_body(&body)?; + body.signature_b64 = signature(&self.key, &body.signing_preimage()?); + Ok(QualificationCommissioningPermit::from_body(&body)?) + } +} + +impl fmt::Debug for CommissioningSigner { + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter + .debug_struct("CommissioningSigner") + .field("signer_id", &self.certificate.body().statement.signer_id) + .finish_non_exhaustive() + } +} + /// A release signer: the key a certificate names, able to sign attestations /// and the release index and nothing else. pub struct ReleaseSigner { diff --git a/product/qualification/auths-recipe-qualification-issuance/tests/commissioning.rs b/product/qualification/auths-recipe-qualification-issuance/tests/commissioning.rs new file mode 100644 index 000000000..f48f449bf --- /dev/null +++ b/product/qualification/auths-recipe-qualification-issuance/tests/commissioning.rs @@ -0,0 +1,742 @@ +//! Purpose separation, closed bounds and exact-run commissioning verification. +//! All keys and evidence are synthetic public test constants; no provider +//! qualification or durable lease consumption is claimed by these tests. + +#![allow(clippy::too_many_lines, reason = "explicit hostile case tables")] + +mod common; + +use auths_recipe_qualification::{ + BoundedText, ClosureFault, CommissioningBinding, CommissioningInputs, + CommissioningOfflineEvidence, CommissioningRefusal, CommissioningRequest, EvidenceMemberKind, + GitCommit, MAX_COMMISSIONING_ACTIONS, MAX_COMMISSIONING_LEASES, MAX_COMMISSIONING_PERMIT_BYTES, + MAX_COMMISSIONING_SECONDS, ProviderEnvironmentClass, QualificationArtifactKind, + QualificationCommissioningPermit, QualificationEvidence, QualificationFormatError, + QualificationInputs, QualificationRevocationList, QualificationRootId, + QualificationSignerCertificate, QualificationSignerId, QualificationTuple, + RecipeQualificationState, Scenario, Sha256Digest, SignatureB64, VerifiedCommissioningPermit, + VerifiedQualifications, VerifierState, +}; +use auths_recipe_qualification_issuance::{ + CertificateRequest, CommissioningProposal, CommissioningSigner, IssuanceError, ReleaseSigner, + RootSigner, SigningSeed, +}; +use common::{DAY, HOUR, NOW, commit, member_evidence, tuple}; +use ed25519_dalek::{Signer as _, SigningKey}; +use serde_json::{Value, json}; +use zeroize::Zeroizing; + +fn digest(byte: u8) -> Sha256Digest { + Sha256Digest::from_bytes([byte; 32]) +} + +fn seed(byte: u8) -> SigningSeed { + SigningSeed::from_bytes(Zeroizing::new([byte; 32])) +} + +fn root() -> RootSigner { + RootSigner::create( + &seed(0x11), + QualificationRootId::parse("test-root").expect("root"), + ) + .expect("root") +} + +fn certificate_request() -> CertificateRequest { + CertificateRequest { + signer_id: QualificationSignerId::parse("test-commissioner").expect("signer"), + public_key_b64: seed(0x22).public_key(), + issued_at: NOW - DAY, + not_before: NOW - DAY, + not_after: NOW + DAY, + } +} + +fn commissioner(root: &RootSigner) -> CommissioningSigner { + CommissioningSigner::open( + &seed(0x22), + root.certify_commissioner(certificate_request()) + .expect("certificate"), + ) + .expect("commissioner") +} + +fn binding() -> CommissioningBinding { + CommissioningBinding { + protected_run: BoundedText::parse( + "github.com/auths-dev/auths-proof/actions/runs/1/attempts/1", + ) + .expect("run"), + source_commit: commit(), + tuple: tuple(), + principal_sha256: digest(0x60), + trusted_context_sha256: digest(0x61), + resources_sha256: digest(0x62), + provider_environment_class: ProviderEnvironmentClass::ProviderTestMode, + offline_evidence: CommissioningOfflineEvidence { + conformance_sha256: member_evidence(EvidenceMemberKind::Conformance).digest(), + differential_sha256: member_evidence(EvidenceMemberKind::Differential).digest(), + }, + allowed_actions: vec![digest(0x63), digest(0x64)], + maximum_credential_leases: 32, + } +} + +fn proposal() -> CommissioningProposal { + CommissioningProposal::assemble( + binding(), + member_evidence(EvidenceMemberKind::Conformance), + member_evidence(EvidenceMemberKind::Differential), + ) + .expect("proposal") +} + +fn permit(signer: &CommissioningSigner) -> QualificationCommissioningPermit { + signer + .permit(&proposal(), NOW, NOW, NOW + MAX_COMMISSIONING_SECONDS) + .expect("permit") +} + +fn revocations(root: &RootSigner, sequence: u64) -> QualificationRevocationList { + root.revoke(sequence, NOW - HOUR, NOW + 24 * HOUR, vec![], vec![]) + .expect("list") +} + +fn verify( + root: &RootSigner, + certificate: &QualificationSignerCertificate, + list: &QualificationRevocationList, + permit: &QualificationCommissioningPermit, +) -> Result { + VerifiedCommissioningPermit::verify( + root.trust_root(), + &CommissioningInputs { + signer_certificate: certificate.canonical_bytes(), + revocation_list: list.canonical_bytes(), + permit: permit.canonical_bytes(), + }, + ) +} + +fn request(binding: &CommissioningBinding) -> CommissioningRequest<'_> { + CommissioningRequest { + source_commit: &binding.source_commit, + tuple: &binding.tuple, + protected_run: &binding.protected_run, + principal_sha256: binding.principal_sha256, + trusted_context_sha256: binding.trusted_context_sha256, + resources_sha256: binding.resources_sha256, + canonical_action_sha256: binding.allowed_actions[0], + } +} + +#[test] +fn a_commissioning_permit_never_qualifies_ordinary_production() { + let root = root(); + let signer = commissioner(&root); + let permit = permit(&signer); + let list = revocations(&root, 1); + let verified = verify(&root, signer.certificate(), &list, &permit).expect("authority"); + assert_eq!(verified.permit(), &permit); + assert_eq!( + verified.evaluate(&request(&binding()), NOW, true, &VerifierState::default()), + Ok(()) + ); + // No permit bytes decode as a record, attestation or release index, even + // when the normal verifier receives the valid purpose certificate/list. + let ordinary = VerifiedQualifications::verify( + root.trust_root(), + &QualificationInputs { + signer_certificate: signer.certificate().canonical_bytes(), + revocation_list: list.canonical_bytes(), + release_index: permit.canonical_bytes(), + records: &[permit.canonical_bytes()], + attestations: &[permit.canonical_bytes()], + }, + ); + let verdict = ordinary.evaluate(&tuple(), NOW, true, &VerifierState::default()); + assert_eq!(verdict.state, RecipeQualificationState::Unqualified); + assert!(!verdict.permits_lease()); +} + +#[test] +fn commissioning_and_release_signers_have_separate_purposes() { + let root = root(); + let signer = commissioner(&root); + let release_certificate = root.certify(certificate_request()).expect("certificate"); + assert_eq!( + CommissioningSigner::open(&seed(0x22), release_certificate.clone()).map(|_| ()), + Err(IssuanceError::NotPermitted) + ); + assert_eq!( + CommissioningSigner::open(&seed(0x33), signer.certificate().clone()).map(|_| ()), + Err(IssuanceError::KeyMismatch) + ); + let release = ReleaseSigner::open(&seed(0x22), signer.certificate().clone()).expect("key"); + assert_eq!( + release.index(NOW, &[]).map(|_| ()), + Err(IssuanceError::NotPermitted) + ); + let record = auths_recipe_qualification_issuance::QualificationProposal::assemble( + common::draft(), + common::all_evidence(), + ) + .expect("record proposal"); + assert_eq!( + release.attest(&record, NOW, NOW, NOW + HOUR).map(|_| ()), + Err(IssuanceError::NotPermitted) + ); + let permit = permit(&signer); + let list = revocations(&root, 1); + assert_eq!( + verify(&root, &release_certificate, &list, &permit).map(|_| ()), + Err(CommissioningRefusal::Unavailable) + ); + + // Even an authentic mixed-purpose certificate is rejected. The offline + // authority must explicitly separate commissioning and qualification keys. + let mut mixed = signer.certificate().body().clone(); + mixed + .statement + .permitted_artifact_kinds + .push(QualificationArtifactKind::QualificationReleaseIndex); + mixed.root_signature_b64 = SignatureB64::from_bytes( + &SigningKey::from_bytes(seed(0x11).expose()) + .sign(&mixed.signing_preimage().expect("preimage")) + .to_bytes(), + ); + let mixed = QualificationSignerCertificate::from_body(&mixed).expect("mixed certificate"); + assert_eq!( + verify(&root, &mixed, &list, &permit).map(|_| ()), + Err(CommissioningRefusal::Unavailable) + ); + assert_eq!( + CommissioningSigner::open(&seed(0x22), mixed).map(|_| ()), + Err(IssuanceError::NotPermitted) + ); + assert!(!format!("{signer:?}").contains("key")); +} + +#[test] +fn each_signature_root_and_domain_is_required() { + let root = root(); + let signer = commissioner(&root); + let permit = permit(&signer); + let list = revocations(&root, 1); + let mut forged = permit.body().clone(); + forged.statement.binding.maximum_credential_leases += 1; + let forged = QualificationCommissioningPermit::from_body(&forged).expect("changed body"); + assert_eq!( + verify(&root, signer.certificate(), &list, &forged).map(|_| ()), + Err(CommissioningRefusal::Unavailable) + ); + let mut certificate = signer.certificate().body().clone(); + certificate.statement.not_after += 1; + let certificate = + QualificationSignerCertificate::from_body(&certificate).expect("changed certificate"); + assert_eq!( + verify(&root, &certificate, &list, &permit).map(|_| ()), + Err(CommissioningRefusal::Unavailable) + ); + let mut changed_list = list.body().clone(); + changed_list.statement.sequence += 1; + let changed_list = QualificationRevocationList::from_body(&changed_list).expect("changed list"); + assert_eq!( + verify(&root, signer.certificate(), &changed_list, &permit).map(|_| ()), + Err(CommissioningRefusal::Unavailable) + ); + let other_root = RootSigner::create( + &seed(0x33), + QualificationRootId::parse("test-root").expect("root"), + ) + .expect("root"); + assert_eq!( + verify(&other_root, signer.certificate(), &list, &permit).map(|_| ()), + Err(CommissioningRefusal::Unavailable) + ); + let mut wrong_domain = permit.body().clone(); + let preimage = wrong_domain.signing_preimage().expect("preimage"); + let statement_bytes = + &preimage[auths_recipe_qualification::COMMISSIONING_PERMIT_SCHEMA.len() + 1..]; + let substituted = [ + b"auths.recipe-qualification-attestation/1\0".as_slice(), + statement_bytes, + ] + .concat(); + wrong_domain.signature_b64 = SignatureB64::from_bytes( + &SigningKey::from_bytes(seed(0x22).expose()) + .sign(&substituted) + .to_bytes(), + ); + let wrong_domain = QualificationCommissioningPermit::from_body(&wrong_domain).expect("permit"); + assert_eq!( + verify(&root, signer.certificate(), &list, &wrong_domain).map(|_| ()), + Err(CommissioningRefusal::Unavailable) + ); + let mut wrong_signer = permit.body().clone(); + wrong_signer.statement.signer_id = + QualificationSignerId::parse("another-commissioner").expect("signer"); + wrong_signer.signature_b64 = SignatureB64::from_bytes( + &SigningKey::from_bytes(seed(0x22).expose()) + .sign(&wrong_signer.signing_preimage().expect("preimage")) + .to_bytes(), + ); + let wrong_signer = QualificationCommissioningPermit::from_body(&wrong_signer).expect("permit"); + assert_eq!( + verify(&root, signer.certificate(), &list, &wrong_signer).map(|_| ()), + Err(CommissioningRefusal::Unavailable) + ); +} + +#[test] +fn every_runtime_binding_must_equal_the_reviewed_session() { + let root = root(); + let signer = commissioner(&root); + let verified = verify( + &root, + signer.certificate(), + &revocations(&root, 1), + &permit(&signer), + ) + .expect("authority"); + let evaluate = |request: &CommissioningRequest<'_>| { + verified.evaluate(request, NOW, true, &VerifierState::default()) + }; + let original = binding(); + let run = BoundedText::parse("github.com/auths-dev/auths-proof/actions/runs/2/attempts/1") + .expect("run"); + let other_commit = GitCommit::parse("f".repeat(40)).expect("commit"); + for request in [ + CommissioningRequest { + protected_run: &run, + ..request(&original) + }, + CommissioningRequest { + source_commit: &other_commit, + ..request(&original) + }, + CommissioningRequest { + principal_sha256: digest(0x70), + ..request(&original) + }, + CommissioningRequest { + trusted_context_sha256: digest(0x70), + ..request(&original) + }, + CommissioningRequest { + resources_sha256: digest(0x70), + ..request(&original) + }, + CommissioningRequest { + canonical_action_sha256: digest(0x70), + ..request(&original) + }, + ] { + assert_eq!( + evaluate(&request), + Err(CommissioningRefusal::BindingMismatch) + ); + } + for (pointer, changed) in [ + ("/recipe_family", json!("another-family")), + ("/compiled_recipe_sha256", json!(digest(0x70))), + ("/profile_lock_sha256", json!(digest(0x70))), + ("/provider_contract_id", json!(digest(0x70))), + ("/gateway_semantic_closure_sha256", json!(digest(0x70))), + ("/target/os", json!("macos")), + ("/target/arch", json!("aarch64")), + ("/target/gateway_package", json!("another-gateway")), + ("/target/gateway_version", json!("2.0.0")), + ("/target/gateway_build_sha256", json!(digest(0x70))), + ("/target/store_kind", json!("shared-file-v1")), + ("/target/store_schema", json!("another-schema")), + ("/target/credential_store_kind", json!("local-file-v1")), + ] { + let mut document = serde_json::to_value(tuple()).expect("tuple"); + *document.pointer_mut(pointer).expect("member") = changed; + let target: QualificationTuple = serde_json::from_value(document).expect("tuple shape"); + assert_eq!( + evaluate(&CommissioningRequest { + tuple: &target, + ..request(&original) + }), + Err(CommissioningRefusal::BindingMismatch), + "{pointer}" + ); + } + let mut another_allowed = request(&original); + another_allowed.canonical_action_sha256 = original.allowed_actions[1]; + assert_eq!(evaluate(&another_allowed), Ok(())); +} + +#[test] +fn commissioning_windows_are_half_open_and_require_trusted_time() { + let root = root(); + let signer = commissioner(&root); + let verified = verify( + &root, + signer.certificate(), + &revocations(&root, 1), + &permit(&signer), + ) + .expect("authority"); + let original = binding(); + for (time, trusted, expected) in [ + (NOW - 1, true, Err(CommissioningRefusal::ClockUntrusted)), + (NOW, false, Err(CommissioningRefusal::ClockUntrusted)), + (NOW, true, Ok(())), + (NOW + MAX_COMMISSIONING_SECONDS - 1, true, Ok(())), + ( + NOW + MAX_COMMISSIONING_SECONDS, + true, + Err(CommissioningRefusal::Expired), + ), + ] { + assert_eq!( + verified.evaluate( + &request(&original), + time, + trusted, + &VerifierState::default() + ), + expected + ); + } + let short_list = root + .revoke(1, NOW - HOUR, NOW + 1, vec![], vec![]) + .expect("list"); + let verified = + verify(&root, signer.certificate(), &short_list, &permit(&signer)).expect("authority"); + assert_eq!( + verified.evaluate( + &request(&original), + NOW + 1, + true, + &VerifierState::default() + ), + Err(CommissioningRefusal::RevocationStale) + ); + for (issued, start, end) in [ + (NOW, NOW, NOW), + (NOW, NOW + 1, NOW + MAX_COMMISSIONING_SECONDS + 1), + (NOW, NOW, NOW + MAX_COMMISSIONING_SECONDS + 1), + (NOW + 1, NOW, NOW + HOUR), + (NOW, NOW, u64::MAX), + ] { + assert_eq!( + signer.permit(&proposal(), issued, start, end).map(|_| ()), + if end == u64::MAX { + Err(IssuanceError::Window) + } else { + Err(IssuanceError::Format( + QualificationFormatError::InvalidTimeWindow, + )) + } + ); + } + assert_eq!( + signer + .permit( + &proposal(), + NOW - 2 * DAY, + NOW - 2 * DAY, + NOW - 2 * DAY + HOUR + ) + .map(|_| ()), + Err(IssuanceError::Window) + ); +} + +#[test] +fn revocations_are_permanent_and_an_older_list_cannot_restore_authority() { + let root = root(); + let signer = commissioner(&root); + let permit = permit(&signer); + let original = binding(); + let revoked = root + .revoke( + 2, + NOW - HOUR, + NOW + HOUR, + vec![certificate_request().signer_id], + vec![], + ) + .expect("revoked"); + let verified = verify(&root, signer.certificate(), &revoked, &permit).expect("signatures"); + let mut state = VerifierState::default(); + assert_eq!( + verified.evaluate(&request(&original), NOW, true, &state), + Err(CommissioningRefusal::Revoked) + ); + assert_eq!( + verified.evaluate(&request(&original), NOW + 2 * HOUR, false, &state), + Err(CommissioningRefusal::Revoked) + ); + verified.remember(&mut state); + let omitted = + verify(&root, signer.certificate(), &revocations(&root, 3), &permit).expect("signatures"); + omitted.remember(&mut state); + assert_eq!(state.accepted_revocation_sequence, 3); + assert_eq!( + omitted.evaluate(&request(&original), NOW, true, &state), + Err(CommissioningRefusal::Revoked) + ); + let unrevoked = + verify(&root, signer.certificate(), &revocations(&root, 1), &permit).expect("signatures"); + let mut floor = VerifierState { + accepted_revocation_sequence: 2, + ..VerifierState::default() + }; + unrevoked.remember(&mut floor); + assert_eq!(floor.accepted_revocation_sequence, 2); + assert_eq!( + unrevoked.evaluate(&request(&original), NOW, true, &floor), + Err(CommissioningRefusal::RevocationRollback) + ); +} + +#[test] +fn proposal_rechecks_exact_offline_artifacts_and_all_required_scenarios() { + let conformance = member_evidence(EvidenceMemberKind::Conformance); + let differential = member_evidence(EvidenceMemberKind::Differential); + for (member, source) in [ + (EvidenceMemberKind::Conformance, &conformance), + (EvidenceMemberKind::Differential, &differential), + ] { + for scenario in Scenario::ALL { + if scenario.member() != member || !scenario.always_required() { + continue; + } + let mut incomplete = source.body().clone(); + incomplete.cases.retain(|case| case.scenario != scenario); + let incomplete = + QualificationEvidence::from_body(&incomplete).expect("incomplete artifact"); + let mut changed = binding(); + let (c, d) = if member == EvidenceMemberKind::Conformance { + changed.offline_evidence.conformance_sha256 = incomplete.digest(); + (incomplete, differential.clone()) + } else { + changed.offline_evidence.differential_sha256 = incomplete.digest(); + (conformance.clone(), incomplete) + }; + assert_eq!( + CommissioningProposal::assemble(changed, c, d), + Err(IssuanceError::Closure(ClosureFault::Scenario)), + "{scenario:?}" + ); + } + } + let mut wrong_digest = binding(); + wrong_digest.offline_evidence.differential_sha256 = digest(0x70); + assert_eq!( + CommissioningProposal::assemble(wrong_digest, conformance.clone(), differential.clone()), + Err(IssuanceError::Closure(ClosureFault::Digest)) + ); + let mut wrong_commit = binding(); + wrong_commit.source_commit = GitCommit::parse("f".repeat(40)).expect("commit"); + assert_eq!( + CommissioningProposal::assemble(wrong_commit, conformance.clone(), differential.clone()), + Err(IssuanceError::Closure(ClosureFault::Candidate)) + ); + let mut wrong_tuple = binding(); + wrong_tuple.tuple.profile_lock_sha256 = digest(0x70); + assert_eq!( + CommissioningProposal::assemble(wrong_tuple, conformance.clone(), differential.clone()), + Err(IssuanceError::Closure(ClosureFault::Candidate)) + ); + assert_eq!( + CommissioningProposal::assemble(binding(), differential.clone(), conformance.clone()), + Err(IssuanceError::Closure(ClosureFault::MemberSet)) + ); + let mut unauthorized = conformance.body().clone(); + unauthorized.cases[0].unauthorized_provider_entries = 1; + let unauthorized = QualificationEvidence::from_body(&unauthorized).expect("reported entry"); + let mut changed = binding(); + changed.offline_evidence.conformance_sha256 = unauthorized.digest(); + assert_eq!( + CommissioningProposal::assemble(changed, unauthorized, differential), + Err(IssuanceError::CaseFailed) + ); + assert_eq!(proposal().offline_evidence()[0], &conformance); +} + +#[test] +fn action_and_lease_bounds_are_exact_and_never_silently_repaired() { + let root = root(); + let signer = commissioner(&root); + let base = permit(&signer).body().clone(); + for count in [ + 0, + 1, + MAX_COMMISSIONING_ACTIONS, + MAX_COMMISSIONING_ACTIONS + 1, + ] { + let mut body = base.clone(); + body.statement.binding.allowed_actions = (0..count) + .map(|index| { + let mut bytes = [0; 32]; + bytes[24..].copy_from_slice(&(index as u64).to_be_bytes()); + Sha256Digest::from_bytes(bytes) + }) + .collect(); + assert_eq!( + QualificationCommissioningPermit::from_body(&body).map(|_| ()), + if (1..=MAX_COMMISSIONING_ACTIONS).contains(&count) { + Ok(()) + } else { + Err(QualificationFormatError::ListBound) + }, + "{count}" + ); + } + for leases in [ + 0, + 1, + MAX_COMMISSIONING_LEASES, + MAX_COMMISSIONING_LEASES + 1, + u64::MAX, + ] { + let mut body = base.clone(); + body.statement.binding.maximum_credential_leases = leases; + assert_eq!( + QualificationCommissioningPermit::from_body(&body).map(|_| ()), + if (1..=MAX_COMMISSIONING_LEASES).contains(&leases) { + Ok(()) + } else { + Err(QualificationFormatError::ListBound) + }, + "{leases}" + ); + } + for actions in [vec![digest(1), digest(1)], vec![digest(2), digest(1)]] { + let mut body = base.clone(); + body.statement.binding.allowed_actions = actions; + assert_eq!( + QualificationCommissioningPermit::from_body(&body).map(|_| ()), + Err(QualificationFormatError::ListOrder) + ); + } + for (pointer, changed) in [ + ("/target/store_kind", json!("shared-file-v1")), + ("/target/credential_store_kind", json!("local-file-v1")), + ] { + let mut body = base.clone(); + let mut target = serde_json::to_value(&body.statement.binding.tuple).expect("tuple"); + *target.pointer_mut(pointer).expect("member") = changed; + body.statement.binding.tuple = serde_json::from_value(target).expect("tuple"); + assert_eq!( + QualificationCommissioningPermit::from_body(&body).map(|_| ()), + Err(QualificationFormatError::Malformed) + ); + } + let permit = permit(&signer); + let mut noncanonical = permit.canonical_bytes().to_vec(); + noncanonical.push(b'\n'); + assert_eq!( + QualificationCommissioningPermit::from_canonical_json(&noncanonical).map(|_| ()), + Err(QualificationFormatError::NonCanonical) + ); + assert_eq!( + QualificationCommissioningPermit::from_canonical_json(&vec![ + b' '; + MAX_COMMISSIONING_PERMIT_BYTES + + 1 + ]) + .map(|_| ()), + Err(QualificationFormatError::Oversized) + ); + let mut extra: Value = serde_json::from_slice(permit.canonical_bytes()).expect("JSON"); + extra["statement"]["unreviewed"] = json!(true); + assert_eq!( + QualificationCommissioningPermit::from_canonical_json( + &serde_json::to_vec(&extra).expect("JSON") + ) + .map(|_| ()), + Err(QualificationFormatError::Malformed) + ); +} + +#[test] +fn renewal_cannot_change_the_durable_budget_identity_or_binding() { + let root = root(); + let signer = commissioner(&root); + let first = signer + .permit(&proposal(), NOW, NOW, NOW + HOUR) + .expect("first"); + let renewed = signer + .permit(&proposal(), NOW + HOUR, NOW + HOUR, NOW + 2 * HOUR) + .expect("renewed"); + assert_ne!(first.digest(), renewed.digest()); + let a = &first.body().statement.binding; + let b = &renewed.body().statement.binding; + assert_eq!(a.budget_key(), b.budget_key()); + assert_eq!(a.budget_binding(), b.budget_binding()); + let original = binding(); + for changed in [ + CommissioningBinding { + maximum_credential_leases: 33, + ..original.clone() + }, + CommissioningBinding { + principal_sha256: digest(0x70), + ..original.clone() + }, + CommissioningBinding { + resources_sha256: digest(0x70), + ..original.clone() + }, + CommissioningBinding { + allowed_actions: vec![digest(0x70)], + ..original.clone() + }, + CommissioningBinding { + trusted_context_sha256: digest(0x70), + ..original.clone() + }, + ] { + assert_eq!(original.budget_key(), changed.budget_key()); + assert_ne!(original.budget_binding(), changed.budget_binding()); + } + let mut another_run = original.clone(); + another_run.protected_run = BoundedText::parse("another-protected-run").expect("run"); + assert_ne!(original.budget_key(), another_run.budget_key()); + let mut another_family = original.clone(); + another_family.tuple.recipe_family = + auths_recipe_qualification::RecipeFamilyId::parse("another-family").expect("family"); + assert_ne!(original.budget_key(), another_family.budget_key()); +} + +#[test] +fn commissioning_artifact_fixture_is_current() { + let root = root(); + let signer = commissioner(&root); + let permit = permit(&signer); + let list = revocations(&root, 1); + let document = json!({ + "schema": "auths.qualification-commissioning-vectors/1", + "synthetic": true, + "trust_root": std::str::from_utf8(root.trust_root().canonical_bytes()).expect("UTF-8"), + "signer_certificate": std::str::from_utf8(signer.certificate().canonical_bytes()).expect("UTF-8"), + "revocation_list": std::str::from_utf8(list.canonical_bytes()).expect("UTF-8"), + "permit": std::str::from_utf8(permit.canonical_bytes()).expect("UTF-8"), + "permit_digest": permit.digest(), + "budget_scope_sha256": permit.body().statement.binding.budget_key().expect("key"), + "budget_binding_sha256": permit.body().statement.binding.budget_binding().expect("binding"), + "limits": { "actions": MAX_COMMISSIONING_ACTIONS, + "leases": MAX_COMMISSIONING_LEASES, "seconds": MAX_COMMISSIONING_SECONDS, + "bytes": MAX_COMMISSIONING_PERMIT_BYTES }, + }); + let path = std::path::Path::new(env!("CARGO_MANIFEST_DIR")) + .join("../../../bindings/fixtures/qualification/commissioning-v1.json"); + let mut encoded = serde_json::to_vec_pretty(&document).expect("fixture"); + encoded.push(b'\n'); + if std::env::var_os("AUTHS_UPDATE_FIXTURES").is_some() { + std::fs::write(path, encoded).expect("fixture write"); + } else { + assert_eq!( + std::fs::read(path).expect("fixture"), + encoded, + "regenerate commissioning fixtures with AUTHS_UPDATE_FIXTURES=1" + ); + } +} diff --git a/product/qualification/auths-recipe-qualification/src/commissioning.rs b/product/qualification/auths-recipe-qualification/src/commissioning.rs new file mode 100644 index 000000000..7fb10faed --- /dev/null +++ b/product/qualification/auths-recipe-qualification/src/commissioning.rs @@ -0,0 +1,430 @@ +//! Explicit authority for one finite commissioning session (ADR 0016). +//! +//! A permit is deliberately outside the qualification record/index types. +//! It proves no provider behavior and never derives production readiness. +//! This pure verifier checks signed authority only. Its runtime consumer must +//! additionally reserve the immutable lease budget in durable shared state +//! before custody access, and keep this authority off the application socket. + +use crate::canonical::{self, Artifact, Canonical, Sealed}; +use crate::verify::verifies; +use crate::{ + BoundedText, GitCommit, LifecycleStoreKind, ProviderEnvironmentClass, + QualificationArtifactKind, QualificationFormatError, QualificationRevocationList, + QualificationSignatureSuite, QualificationSignerCertificate, QualificationSignerId, + QualificationTrustRoot, QualificationTuple, Sha256Digest, SignatureB64, VerifierState, +}; +use serde::{Deserialize, Serialize}; + +#[cfg(test)] +mod tests; + +/// The separate signature domain of a commissioning permit. +pub const COMMISSIONING_PERMIT_SCHEMA: &str = "auths.qualification-commissioning-permit/1"; +/// The domain of the stable run/family budget key. +pub const COMMISSIONING_BUDGET_KEY_DOMAIN: &str = "auths.qualification-commissioning-budget-key/1"; +/// The domain of the immutable budget binding, including its ceiling. +pub const COMMISSIONING_BUDGET_BINDING_DOMAIN: &str = + "auths.qualification-commissioning-budget-binding/1"; +/// The largest commissioning permit accepted before parsing. +pub const MAX_COMMISSIONING_PERMIT_BYTES: usize = 32 * 1024; +/// The maximum distinct exact actions one permit may authorize. +pub const MAX_COMMISSIONING_ACTIONS: usize = 256; +/// The maximum custody acquisitions one permit may authorize. +pub const MAX_COMMISSIONING_LEASES: u64 = 1024; +/// A commissioning permit lasts at most two hours. +pub const MAX_COMMISSIONING_SECONDS: u64 = 2 * 60 * 60; + +/// The two closed offline artifacts a protected signer must re-verify. +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct CommissioningOfflineEvidence { + /// Source, recipe digest, compiler/interpreter and closed-enumeration cases. + pub conformance_sha256: Sha256Digest, + /// The independently reviewed oracle's acceptance/rejection corpus. + pub differential_sha256: Sha256Digest, +} + +/// Everything fixed for a run, excluding signer rotation and time renewal. +/// +/// Runtime identities come from the installed candidate and sealed verifier, +/// never from application assertions. Resource and action bindings are +/// expanded by the protected, reviewed reference before permit issuance. +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct CommissioningBinding { + /// Exact protected workflow run identity, including its attempt. + pub protected_run: BoundedText<256>, + /// The installed candidate's immutable source revision. + pub source_commit: GitCommit, + /// Exact production recipe, contract, semantic closure, binary and target. + pub tuple: QualificationTuple, + /// Commitment to the ephemeral proof-authoring principal's canonical bytes. + pub principal_sha256: Sha256Digest, + /// Commitment to the operator-approved canonical trusted context. + pub trusted_context_sha256: Sha256Digest, + /// Commitment to the reviewed disposable provider resource bindings. + pub resources_sha256: Sha256Digest, + /// What kind of disposable provider environment is actually exercised. + pub provider_environment_class: ProviderEnvironmentClass, + /// Offline evidence which the issuing signer checked for this candidate. + pub offline_evidence: CommissioningOfflineEvidence, + /// Exact canonical action commitments, strictly ascending and unique. + pub allowed_actions: Vec, + /// Lifetime custody-acquisition ceiling for this run and family. + pub maximum_credential_leases: u64, +} + +impl CommissioningBinding { + /// The durable budget's key, stable across renewals and signer rotation. + /// + /// Changing any other binding member must conflict with the original + /// durable registration at this key. It must never open a fresh counter. + /// + /// # Errors + /// + /// Returns [`QualificationFormatError::Malformed`] if canonical encoding + /// fails. No I/O or counter allocation occurs here. + pub fn budget_key(&self) -> Result { + #[derive(Serialize)] + struct Key<'a> { + protected_run: &'a BoundedText<256>, + recipe_family: &'a crate::RecipeFamilyId, + } + Ok(canonical::domain_digest( + COMMISSIONING_BUDGET_KEY_DOMAIN, + &canonical::canonical_bytes(&Key { + protected_run: &self.protected_run, + recipe_family: &self.tuple.recipe_family, + })?, + )) + } + + /// Commitment the durable store must bind immutably at [`Self::budget_key`]. + /// + /// # Errors + /// + /// Returns [`QualificationFormatError::Malformed`] if encoding fails. + pub fn budget_binding(&self) -> Result { + Ok(canonical::domain_digest( + COMMISSIONING_BUDGET_BINDING_DOMAIN, + &canonical::canonical_bytes(self)?, + )) + } + + /// Checks the production-only target, finite lease ceiling and exact list. + /// + /// # Errors + /// + /// Returns a format refusal for a development target or a broken hard + /// bound/order. This check authenticates neither evidence nor signatures. + pub fn validate(&self) -> Result<(), QualificationFormatError> { + if self.tuple.target.store_kind != LifecycleStoreKind::PostgresqlV1 + || !self.tuple.target.credential_store_kind.is_production() + { + return Err(QualificationFormatError::Malformed); + } + if self.allowed_actions.is_empty() + || self.allowed_actions.len() > MAX_COMMISSIONING_ACTIONS + || !(1..=MAX_COMMISSIONING_LEASES).contains(&self.maximum_credential_leases) + { + return Err(QualificationFormatError::ListBound); + } + canonical::strictly_ascending(&self.allowed_actions) + } +} + +/// The exact statement a purpose-certified commissioning signer signs. +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct CommissioningPermitStatement { + /// Exactly [`COMMISSIONING_PERMIT_SCHEMA`]. + pub schema: String, + /// Run bindings which renewal cannot change or reset. + pub binding: CommissioningBinding, + /// The commissioning signer, distinct in purpose from a release signer. + pub signer_id: QualificationSignerId, + /// The signature suite. + pub signature_suite: QualificationSignatureSuite, + /// The actual issue time, no later than the start of the window. + pub issued_at: u64, + /// Start of the finite session. + pub not_before: u64, + /// End of the finite session, at most two hours after issue. + pub not_after: u64, +} + +/// The closed commissioning artifact: a statement and its purpose-bound signature. +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct CommissioningPermitBody { + /// All signed bindings, signer and times. + pub statement: CommissioningPermitStatement, + /// Ed25519 signature over [`Self::signing_preimage`]. + pub signature_b64: SignatureB64, +} + +impl CommissioningPermitBody { + /// Exact signature preimage; no record, index or proof has this domain. + /// + /// # Errors + /// + /// Returns [`QualificationFormatError::Malformed`] if encoding fails. + pub fn signing_preimage(&self) -> Result, QualificationFormatError> { + Ok(canonical::preimage( + COMMISSIONING_PERMIT_SCHEMA, + &canonical::canonical_bytes(&self.statement)?, + )) + } +} + +impl Sealed for CommissioningPermitBody {} + +impl Artifact for CommissioningPermitBody { + const SCHEMA: &'static str = COMMISSIONING_PERMIT_SCHEMA; + const MAX_BYTES: usize = MAX_COMMISSIONING_PERMIT_BYTES; + + fn schema(&self) -> &str { + &self.statement.schema + } + + fn validate(&self) -> Result<(), QualificationFormatError> { + let statement = &self.statement; + canonical::valid_window( + statement.issued_at, + statement.not_before, + statement.not_after, + MAX_COMMISSIONING_SECONDS, + )?; + // Counting from issue prevents a long-dated dormant permit from + // reserving a future two-hour window beyond the maximum lifetime. + if statement.issued_at > statement.not_before + || statement.not_after - statement.issued_at > MAX_COMMISSIONING_SECONDS + { + return Err(QualificationFormatError::InvalidTimeWindow); + } + statement.binding.validate() + } +} + +/// Structurally validated bytes, without any claim of trusted authority. +pub type QualificationCommissioningPermit = Canonical; + +/// Untrusted canonical bytes the commissioning verifier authenticates. +#[derive(Clone, Copy, Debug)] +pub struct CommissioningInputs<'a> { + /// Root-issued, commissioning-purpose signer certificate. + pub signer_certificate: &'a [u8], + /// Root-issued revocation list. + pub revocation_list: &'a [u8], + /// Separately signed commissioning permit. + pub permit: &'a [u8], +} + +/// Runtime bindings derived independently of the supplied permit. +#[derive(Clone, Copy, Debug)] +pub struct CommissioningRequest<'a> { + /// Installed source revision. + pub source_commit: &'a GitCommit, + /// Current deployment tuple, never the caller's reported tuple. + pub tuple: &'a QualificationTuple, + /// Authenticated operator session's protected run identity. + pub protected_run: &'a BoundedText<256>, + /// Sealed verifier's exact proof-authoring principal commitment. + pub principal_sha256: Sha256Digest, + /// Operator-approved context actually executed by the verifier. + pub trusted_context_sha256: Sha256Digest, + /// Operator-approved disposable resource binding. + pub resources_sha256: Sha256Digest, + /// Native commitment of the verified canonical action. + pub canonical_action_sha256: Sha256Digest, +} + +/// A commissioning check's closed first refusal; never a qualification state. +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum CommissioningRefusal { + /// Missing, malformed, forged, wrong-root or wrong-purpose signed inputs. + Unavailable, + /// A currently or previously authenticated list revoked this signer. + Revoked, + /// The revocation sequence went backwards. + RevocationRollback, + /// Untrusted clock or time before signed issue/window start. + ClockUntrusted, + /// Root revocations are past their signed refresh deadline. + RevocationStale, + /// The permit or signer window ended. + Expired, + /// An exact session, principal, action, context, resource or target differs. + BindingMismatch, +} + +impl CommissioningRefusal { + /// Closed reason token, distinct from the qualification code family. + #[must_use] + pub const fn as_str(self) -> &'static str { + match self { + Self::Unavailable => "unavailable", + Self::Revoked => "revoked", + Self::RevocationRollback => "revocation-rollback", + Self::ClockUntrusted => "clock-untrusted", + Self::RevocationStale => "revocation-stale", + Self::Expired => "expired", + Self::BindingMismatch => "binding-mismatch", + } + } +} + +/// Signature-checked commissioning authority, with no lease or readiness grant. +/// +/// Holding this sealed value authenticates bytes only. [`Self::evaluate`] +/// checks current time, remembered revocations and each runtime binding before +/// every lease. Only a private operator session may consume a successful +/// check, after an atomic durable budget claim. +#[derive(Clone, Debug)] +pub struct VerifiedCommissioningPermit { + certificate: QualificationSignerCertificate, + revocations: QualificationRevocationList, + permit: QualificationCommissioningPermit, +} + +impl VerifiedCommissioningPermit { + /// Authenticates all three closed artifacts under the pinned root. + /// + /// # Errors + /// + /// Returns [`CommissioningRefusal::Unavailable`] for any structural, + /// signature, root, signer, permission or certificate-window fault. No + /// supplied root or permit can upgrade ordinary application qualification. + pub fn verify( + root: &QualificationTrustRoot, + inputs: &CommissioningInputs<'_>, + ) -> Result { + let unavailable = CommissioningRefusal::Unavailable; + let certificate = + QualificationSignerCertificate::from_canonical_json(inputs.signer_certificate) + .map_err(|_| unavailable)?; + let revocations = QualificationRevocationList::from_canonical_json(inputs.revocation_list) + .map_err(|_| unavailable)?; + let permit = QualificationCommissioningPermit::from_canonical_json(inputs.permit) + .map_err(|_| unavailable)?; + let cert = certificate.body(); + let signer = &cert.statement; + let list = revocations.body(); + let signed = permit.body(); + let statement = &signed.statement; + let root_key = root.body().public_key_b64.to_bytes(); + let root_signature = |preimage: Result, QualificationFormatError>, + signature: &SignatureB64| { + preimage.is_ok_and(|bytes| verifies(&root_key, &bytes, &signature.to_bytes())) + }; + if signer.root_id != root.body().root_id + || list.statement.root_id != root.body().root_id + || !root_signature(cert.signing_preimage(), &cert.root_signature_b64) + || !root_signature(list.signing_preimage(), &list.root_signature_b64) + || signer.permitted_artifact_kinds + != [QualificationArtifactKind::QualificationCommissioningPermit] + || statement.signer_id != signer.signer_id + || statement.issued_at < signer.issued_at + || statement.not_before < signer.not_before + || statement.not_after > signer.not_after + || !signed.signing_preimage().is_ok_and(|bytes| { + verifies( + &signer.public_key_b64.to_bytes(), + &bytes, + &signed.signature_b64.to_bytes(), + ) + }) + { + return Err(unavailable); + } + Ok(Self { + certificate, + revocations, + permit, + }) + } + + /// Authenticated permit bytes; not proof of current validity or consumption. + #[must_use] + pub const fn permit(&self) -> &QualificationCommissioningPermit { + &self.permit + } + + /// Permanently remembers authenticated revocations and the largest sequence. + /// + /// A stale list still revokes what it names. The runtime must durably + /// persist this state before acknowledging an operator import. + pub fn remember(&self, state: &mut VerifierState) { + let list = &self.revocations.body().statement; + state + .revoked_signers + .extend(list.revoked_signers.iter().cloned()); + state + .revoked_qualifications + .extend(list.revoked_qualifications.iter().cloned()); + state.accepted_revocation_sequence = state.accepted_revocation_sequence.max(list.sequence); + } + + /// Checks signed freshness and exact runtime bindings for one lease attempt. + /// + /// A successful result is a necessary condition only: the runtime must + /// atomically claim one unit from the immutably registered shared budget + /// before credentials, and still execute ordinary proof/recipe/attempt + /// checks. This method cannot mint a [`crate::QualificationVerdict`]. + /// + /// # Errors + /// + /// Returns the first closed refusal. Earlier authenticated revocations + /// dominate time faults; rolled-back lists never restore authority. + pub fn evaluate( + &self, + request: &CommissioningRequest<'_>, + now: u64, + clock_trusted: bool, + state: &VerifierState, + ) -> Result<(), CommissioningRefusal> { + let signer = &self.certificate.body().statement; + let list = &self.revocations.body().statement; + let statement = &self.permit.body().statement; + let binding = &statement.binding; + if state.revoked_signers.contains(&signer.signer_id) + || list.revoked_signers.contains(&signer.signer_id) + { + return Err(CommissioningRefusal::Revoked); + } + if list.sequence < state.accepted_revocation_sequence { + return Err(CommissioningRefusal::RevocationRollback); + } + if !clock_trusted + || now < signer.issued_at + || now < signer.not_before + || now < list.issued_at + || now < statement.issued_at + || now < statement.not_before + { + return Err(CommissioningRefusal::ClockUntrusted); + } + // Windows are half-open. At the deadline, no lease can start. + if now >= list.next_update { + return Err(CommissioningRefusal::RevocationStale); + } + if now >= signer.not_after || now >= statement.not_after { + return Err(CommissioningRefusal::Expired); + } + if binding.source_commit != *request.source_commit + || binding.tuple != *request.tuple + || binding.protected_run != *request.protected_run + || binding.principal_sha256 != request.principal_sha256 + || binding.trusted_context_sha256 != request.trusted_context_sha256 + || binding.resources_sha256 != request.resources_sha256 + || binding + .allowed_actions + .binary_search(&request.canonical_action_sha256) + .is_err() + { + return Err(CommissioningRefusal::BindingMismatch); + } + Ok(()) + } +} diff --git a/product/qualification/auths-recipe-qualification/src/commissioning/tests.rs b/product/qualification/auths-recipe-qualification/src/commissioning/tests.rs new file mode 100644 index 000000000..566af472b --- /dev/null +++ b/product/qualification/auths-recipe-qualification/src/commissioning/tests.rs @@ -0,0 +1,125 @@ +//! Frozen public commissioning bytes, consumed without issuance code. + +use super::*; + +fn fixture() -> serde_json::Value { + let path = std::path::Path::new(env!("CARGO_MANIFEST_DIR")) + .join("../../../bindings/fixtures/qualification/commissioning-v1.json"); + serde_json::from_slice(&std::fs::read(path).expect("fixture")).expect("fixture JSON") +} + +#[test] +fn frozen_commissioning_bytes_authenticate_only_their_exact_binding() { + let fixture = fixture(); + let text = |member: &str| fixture[member].as_str().expect("artifact").as_bytes(); + let root = QualificationTrustRoot::from_canonical_json(text("trust_root")).expect("root"); + let verified = VerifiedCommissioningPermit::verify( + &root, + &CommissioningInputs { + signer_certificate: text("signer_certificate"), + revocation_list: text("revocation_list"), + permit: text("permit"), + }, + ) + .expect("signed permit"); + let permit = verified.permit(); + assert_eq!(permit.digest().to_hex(), fixture["permit_digest"]); + let binding = &permit.body().statement.binding; + assert_eq!( + binding.budget_key().expect("key").to_hex(), + fixture["budget_scope_sha256"] + ); + assert_eq!( + binding.budget_binding().expect("binding").to_hex(), + fixture["budget_binding_sha256"] + ); + let mut request = CommissioningRequest { + source_commit: &binding.source_commit, + tuple: &binding.tuple, + protected_run: &binding.protected_run, + principal_sha256: binding.principal_sha256, + trusted_context_sha256: binding.trusted_context_sha256, + resources_sha256: binding.resources_sha256, + canonical_action_sha256: binding.allowed_actions[0], + }; + let now = permit.body().statement.not_before; + assert_eq!( + verified.evaluate(&request, now, true, &VerifierState::default()), + Ok(()) + ); + request.principal_sha256 = Sha256Digest::from_bytes([0xff; 32]); + assert_eq!( + verified.evaluate(&request, now, true, &VerifierState::default()), + Err(CommissioningRefusal::BindingMismatch) + ); +} + +#[test] +fn every_single_bit_signature_mutation_is_refused() { + let fixture = fixture(); + let text = |member: &str| fixture[member].as_str().expect("artifact").as_bytes(); + let root = QualificationTrustRoot::from_canonical_json(text("trust_root")).expect("root"); + let permit = + QualificationCommissioningPermit::from_canonical_json(text("permit")).expect("permit"); + let original = permit.body().signature_b64.to_bytes(); + for bit in 0..512 { + let mut body = permit.body().clone(); + let mut changed = original; + changed[bit / 8] ^= 1 << (bit % 8); + body.signature_b64 = SignatureB64::from_bytes(&changed); + let changed = QualificationCommissioningPermit::from_body(&body).expect("shape"); + assert_eq!( + VerifiedCommissioningPermit::verify( + &root, + &CommissioningInputs { + signer_certificate: text("signer_certificate"), + revocation_list: text("revocation_list"), + permit: changed.canonical_bytes(), + } + ) + .map(|_| ()), + Err(CommissioningRefusal::Unavailable), + "bit {bit}" + ); + } +} + +#[test] +fn unsigned_shape_never_accepts_extra_duplicate_or_unknown_members() { + let fixture = fixture(); + let permit = QualificationCommissioningPermit::from_canonical_json( + fixture["permit"].as_str().expect("artifact").as_bytes(), + ) + .expect("permit"); + for pointer in [ + "", + "/statement", + "/statement/binding", + "/statement/binding/tuple", + "/statement/binding/tuple/target", + "/statement/binding/offline_evidence", + ] { + let mut document = serde_json::to_value(permit.body()).expect("body"); + document.pointer_mut(pointer).expect("member")["extra"] = serde_json::json!(true); + assert_eq!( + QualificationCommissioningPermit::from_canonical_json( + &canonical::canonical_bytes(&document).expect("canonical") + ) + .map(|_| ()), + Err(QualificationFormatError::Malformed), + "{pointer}" + ); + } + let text = std::str::from_utf8(permit.canonical_bytes()).expect("UTF-8"); + let duplicate = text.replacen("\"issued_at\":", "\"issued_at\":0,\"issued_at\":", 1); + assert_eq!( + QualificationCommissioningPermit::from_canonical_json(duplicate.as_bytes()).map(|_| ()), + Err(QualificationFormatError::Malformed) + ); + let mut body = permit.body().clone(); + body.statement.schema = "auths.qualification-commissioning-permit/0".to_owned(); + assert_eq!( + QualificationCommissioningPermit::from_body(&body).map(|_| ()), + Err(QualificationFormatError::UnknownSchema) + ); +} diff --git a/product/qualification/auths-recipe-qualification/src/lib.rs b/product/qualification/auths-recipe-qualification/src/lib.rs index b3f54a3f3..b74a7df34 100644 --- a/product/qualification/auths-recipe-qualification/src/lib.rs +++ b/product/qualification/auths-recipe-qualification/src/lib.rs @@ -18,6 +18,7 @@ mod canonical; mod closure; +mod commissioning; mod error; mod evidence; mod ids; @@ -47,6 +48,14 @@ pub use closure::{ GatewaySemanticClosure, MAX_SEMANTIC_CLOSURE_BYTES, MAX_SEMANTIC_CLOSURE_FILES, SEMANTIC_CLOSURE_SCHEMA, SemanticClosureBody, SemanticClosureFile, }; +pub use commissioning::{ + COMMISSIONING_BUDGET_BINDING_DOMAIN, COMMISSIONING_BUDGET_KEY_DOMAIN, + COMMISSIONING_PERMIT_SCHEMA, CommissioningBinding, CommissioningInputs, + CommissioningOfflineEvidence, CommissioningPermitBody, CommissioningPermitStatement, + CommissioningRefusal, CommissioningRequest, MAX_COMMISSIONING_ACTIONS, + MAX_COMMISSIONING_LEASES, MAX_COMMISSIONING_PERMIT_BYTES, MAX_COMMISSIONING_SECONDS, + QualificationCommissioningPermit, VerifiedCommissioningPermit, +}; pub use error::QualificationFormatError; pub use evidence::{ ClosureFault, EVIDENCE_SCHEMA, EvidenceBody, EvidenceCase, MAX_EVIDENCE_BYTES, diff --git a/product/qualification/auths-recipe-qualification/src/release.rs b/product/qualification/auths-recipe-qualification/src/release.rs index 5bd73ca15..a6ce6e84b 100644 --- a/product/qualification/auths-recipe-qualification/src/release.rs +++ b/product/qualification/auths-recipe-qualification/src/release.rs @@ -75,6 +75,8 @@ pub enum QualificationSignerKind { #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize, Deserialize)] #[serde(rename_all = "kebab-case")] pub enum QualificationArtifactKind { + /// A bounded first-qualification run, never a completed qualification. + QualificationCommissioningPermit, /// The release index. QualificationReleaseIndex, /// A qualification attestation. diff --git a/product/qualification/auths-recipe-qualification/src/verify.rs b/product/qualification/auths-recipe-qualification/src/verify.rs index dca324b87..6b1e3ce28 100644 --- a/product/qualification/auths-recipe-qualification/src/verify.rs +++ b/product/qualification/auths-recipe-qualification/src/verify.rs @@ -127,7 +127,7 @@ pub struct QualificationInputs<'input> { pub attestations: &'input [&'input [u8]], } -fn verifies(key: &[u8; 32], preimage: &[u8], signature: &[u8; 64]) -> bool { +pub(crate) fn verifies(key: &[u8; 32], preimage: &[u8], signature: &[u8; 64]) -> bool { VerifyingKey::from_bytes(key).is_ok_and(|key| { key.verify_strict(preimage, &Signature::from_bytes(signature)) .is_ok() diff --git a/product/runtime/auths-gateway/semantic-closure.json b/product/runtime/auths-gateway/semantic-closure.json index 16f9b8dfe..c518bb86d 100644 --- a/product/runtime/auths-gateway/semantic-closure.json +++ b/product/runtime/auths-gateway/semantic-closure.json @@ -1 +1 @@ -{"files":[{"path":"Cargo.lock","sha256":"0e75e2fdef44e79e57797ac6661295ae58ddb8de4a1990a6fd22ce6c54f78604"},{"path":"Cargo.toml","sha256":"6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24"},{"path":"core/adapters/auths-did-keri/Cargo.toml","sha256":"86ba3e3f9a0a70d970568bfb3113b7ba7bbdd81c3eebbb52743dd574a0c0ecaa"},{"path":"core/adapters/auths-did-keri/src/lib.rs","sha256":"a75674842f8a7142004369ccd206ab43e476459293f0ff4bed4d4e659031b3e3"},{"path":"core/adapters/auths-did-key/Cargo.toml","sha256":"d5a3ae07ecde83f91eed4c3785051dd0f44eab6c891754f3309b6b40596707d7"},{"path":"core/adapters/auths-did-key/src/lib.rs","sha256":"b76a3f4528a725df53cfa9242e6e414e1d26caa48468aaed497e28b121f4497c"},{"path":"core/adapters/auths-raw-key/Cargo.toml","sha256":"f49616bc18c19e6aaa7e6a02ccebcdb9f5c1422c1278ef9869e0dbf22ceda7be"},{"path":"core/adapters/auths-raw-key/src/lib.rs","sha256":"45eec1b295dac3bed65cd79c942870b926b06b3f5d38eaebaeb6140ac69315fa"},{"path":"core/crates/auths-algebra-kernel/Cargo.toml","sha256":"0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba"},{"path":"core/crates/auths-algebra-kernel/src/generated.rs","sha256":"ae4bcbef42a408c7ffa0c6a74a42f7de177a6f14479e51d205acf830bda05960"},{"path":"core/crates/auths-algebra-kernel/src/lib.rs","sha256":"6654667eeb9b353d6648954c9fd2e8838462a82ce6b2803eb49e1366892c68c6"},{"path":"core/crates/auths-assurance/Cargo.toml","sha256":"afcb12a97ddd09d7a264b9ecd3fcaefc865ff2c9b4539ee85b00883420ba333a"},{"path":"core/crates/auths-assurance/src/lib.rs","sha256":"0fb2ec844d674b25a9e20b1601452c89c2454901fa506adfa9bb38ef9a7fa213"},{"path":"core/crates/auths-author/Cargo.toml","sha256":"1e6f0e3bc079ddb558decf0db26b291c6e72fc47327b6df1b7650d41689b215f"},{"path":"core/crates/auths-author/src/lib.rs","sha256":"e14475f2f49715a1869d5fa6b11ff1fbb72497e39097e09f833b0bae7e5b3f2b"},{"path":"core/crates/auths-author/src/observations.rs","sha256":"dda7d6bfa6f4bd7e95a480ca283c2c0e996f69c5c15cb0c7197af328131a7066"},{"path":"core/crates/auths-authority/Cargo.toml","sha256":"4f68212938029f79ebd857b4f3038494eb85d0163d49f07e51376715cf959815"},{"path":"core/crates/auths-authority/src/lib.rs","sha256":"da88d5194de4e17449e69972c0fb042afa3c39798a8f570f30771e77c384f1eb"},{"path":"core/crates/auths-codec/Cargo.toml","sha256":"e20e51826e17814effd9d8925d18d5fbdd6c0d37bf50231e743ec2611314722c"},{"path":"core/crates/auths-codec/src/approval.rs","sha256":"fbff43bf4d57f69f8b7738a8647751cde75c5a932dee65d924a1fe9c7202f91f"},{"path":"core/crates/auths-codec/src/bounded_policy.rs","sha256":"d21f6728be2d8a04b6d94921f2b683f7e61cbb42e0ac6866f1c88a49caa534c3"},{"path":"core/crates/auths-codec/src/decode.rs","sha256":"ba2999584cdf53b1b517ecb9c7ea50d39efee17c666a9a38e2ad1ac94379f778"},{"path":"core/crates/auths-codec/src/encode.rs","sha256":"8491192053e2e15d62b4d2a491de22405b7487ead69ab6f6bca40669ce7ca5f7"},{"path":"core/crates/auths-codec/src/error.rs","sha256":"fecb0737c16deb42d859f1dc7727c698438d9ac12064fd99e0024629642c390c"},{"path":"core/crates/auths-codec/src/hash.rs","sha256":"f88e111f1dbb2cef6b7b5e9c948cb45ff92e366710c8a5f5c636138aa748479e"},{"path":"core/crates/auths-codec/src/lib.rs","sha256":"3b0e5c94c6f34f750b88a9333e1d5c8145746d845d3a23e0d2f61807cf592ea7"},{"path":"core/crates/auths-codec/src/observation.rs","sha256":"38328b0c71ff97a4196eeade8b4faa889527ff1f80bb168468bcd49082a3987e"},{"path":"core/crates/auths-composition/Cargo.toml","sha256":"331e13025eb82588b5269ed3975929eb41c823d588c49e4c296273d85c6fe80e"},{"path":"core/crates/auths-composition/src/lib.rs","sha256":"e42e3b0b6a9985b73c533aeb23799c638979aa27a9ce7d0f10a8d60340570fb1"},{"path":"core/crates/auths-model/Cargo.toml","sha256":"565c15302b0cc9270db1e28efa3862804846850ba933cc17aea8abcec4a65987"},{"path":"core/crates/auths-model/src/approval.rs","sha256":"54cf44a9ef747ec21546a4086aecfb130bc7803b0d646430e6082df51e6e305f"},{"path":"core/crates/auths-model/src/bounded.rs","sha256":"f90496abc0a06c028b4d850af6ddab7d850bfafeaa3d042f1b1246a41d8bbbc9"},{"path":"core/crates/auths-model/src/bounded_policy.rs","sha256":"306a8f049cc7cfc7635fe0e4de47eb7813eed63d3c14c3be2b51586aa4eea450"},{"path":"core/crates/auths-model/src/lib.rs","sha256":"e7cfe6bb9574c6b016aa63e70658c31e0b90903ec6479a49f4a2ceb64f5bad97"},{"path":"core/crates/auths-model/src/observation.rs","sha256":"b3ed3e3cc090afca2896a7d3de7988afccc1ee1ea0ebd91b51a8bc0f20ad8dbb"},{"path":"core/crates/auths-multikey/Cargo.toml","sha256":"858756c1197befcada06134742bffe8d58cf674cadd6c046bf710570e96efaf2"},{"path":"core/crates/auths-multikey/src/lib.rs","sha256":"f5177fffb11e40eeaaa665ba886c541fc1f24d5eacdd6983fb03dc20148733f0"},{"path":"core/crates/auths-ports/Cargo.toml","sha256":"596a9b0f5af3717c16a6d13f7054d8a106bcd9f01f5f72c2235dd2afcf0ab16c"},{"path":"core/crates/auths-ports/src/binding.rs","sha256":"a16c012d40aa4249e3ec54372b9611006d0bfe8c7dc3c741911c2194ad17736d"},{"path":"core/crates/auths-ports/src/diagnostics.rs","sha256":"aa596572503b5a65a918bb2ff38281c144ff53821ee914e9325c852828d852df"},{"path":"core/crates/auths-ports/src/lib.rs","sha256":"8da1debf86f9532df0660155d04298beb1ba3a1204508f8586e2e67cd2fb3449"},{"path":"core/crates/auths-ports/src/path.rs","sha256":"b68fc547b4e4d97a60cbbc1cc1939fc6b34a8233b81f840bd396914a707e3ea1"},{"path":"core/crates/auths-raw-key-core/Cargo.toml","sha256":"98c0bc8527a537512e43a74dd6ba9658c6f0cdc16610cf938e3f9b43785d836d"},{"path":"core/crates/auths-raw-key-core/src/lib.rs","sha256":"98c0500c41697aae28708ad0bf970b9a97583d96a3d2c18d23e7fa351e0f7d12"},{"path":"core/crates/auths-registries/Cargo.toml","sha256":"590e49e58b0622d9d6274fea46796dcdb07dec9550eff295cce6a6427ffa51e2"},{"path":"core/crates/auths-registries/src/lib.rs","sha256":"450d3886d85ee333b7e046317fb5b47cde62483d5f3e41d46265e2caf4c373ec"},{"path":"core/crates/auths-registries/src/template.rs","sha256":"1224039dd2b3ce6fa8357613d8cafbae40400493da7176da202b9ade62fa05e4"},{"path":"core/crates/auths-signature-core/Cargo.toml","sha256":"6bee2230eb30af1be0bd5c2d57bd3e1903497a70028d47290d4ac6e9e0e8bca0"},{"path":"core/crates/auths-signature-core/src/lib.rs","sha256":"6e3f9311ded5e49ea50d445eb21e6d8fa12442aa4362a73e0cb6fda15b7cd865"},{"path":"core/crates/auths-signature/Cargo.toml","sha256":"7f7b5682466ba439d8c59579022cb61068cad9fb4bd2d73e1cc21327c902b450"},{"path":"core/crates/auths-signature/src/lib.rs","sha256":"b3d9ac4cc3ba0797b9e1c09f2d6ac05089b25dac4e285a5af28c0165b33d925b"},{"path":"core/crates/auths-verifier/Cargo.toml","sha256":"c43358e06a33324b41a8b93e5cc7279c55f7d21f1f6cfaa539a3fc7b4c27a38f"},{"path":"core/crates/auths-verifier/src/approval.rs","sha256":"c3cae6a49e169051eb555bb092b1069a4d422516d6a2114623a89e5f31ff923f"},{"path":"core/crates/auths-verifier/src/causal.rs","sha256":"9635230f33b13a263573d319ac8a1976addbcc07677514a43e3c7bf28dc04587"},{"path":"core/crates/auths-verifier/src/lib.rs","sha256":"f22dec38dfa47ced8da4f605390da8453273bee1da010f57fd1fdfcb10e0b389"},{"path":"core/crates/auths-verifier/src/observation.rs","sha256":"0bb07f06a0f9524c88427df1c972b1de8ba038a9eeeb15d3134c25125ae84b1e"},{"path":"core/crates/auths-verifier/src/trace.rs","sha256":"2213d72023a1d9e0413a2cf2c51c3dad9e04775d86033a0caaa9d29a8f0036f8"},{"path":"exchange/crates/auths-proof-exchange-model/Cargo.toml","sha256":"34b2db64f93a288e942b5a3918d28cdcbef906e0dc9074ce848018d3d5f7a1fa"},{"path":"exchange/crates/auths-proof-exchange-model/src/lib.rs","sha256":"49fac5aff2339d3a57c41cb8bb2a82852538e8f77ecc4b157c88e264ff31fb55"},{"path":"exchange/crates/auths-proof-exchange-port/Cargo.toml","sha256":"7ff660f1b7579dc570c791090aeb450404fbbf44c92781e289f5ccdde746d739"},{"path":"exchange/crates/auths-proof-exchange-port/src/lib.rs","sha256":"b408fb40c6432edc1facb3d8b3e9433a033f8dc73fe2e0ba5a88c972ca675021"},{"path":"product/config/auths-config/Cargo.toml","sha256":"e4b568ab9f6d84f7d7e6d66443fe825f360db9c27bc7c31d6ddc0647ba3ab304"},{"path":"product/config/auths-config/src/lib.rs","sha256":"fecf00ea65cef9018fda9af2063326d7065b869266d0d9e73a4f06816f1102cc"},{"path":"product/errors/auths-errors/Cargo.toml","sha256":"3b3a199b6460ba75bda84475bb5accd35e1485448a3981038db85bf4772dd350"},{"path":"product/errors/auths-errors/src/lib.rs","sha256":"7feeb9069fa4003f94f1f07c1c94619cf1c883e0dbaaf2187f04d0f742264bdd"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/Cargo.toml","sha256":"716f1f2a117d6d69d8effe9ee9057e24ba3502f20af6a602b06facb638cdabed"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/api.rs","sha256":"9ea61dd7ddd93282b073b98e453e6b75b26dc49689c04e9782435d06a3a09e48"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/clock.rs","sha256":"73f0a6e0f5903883329fa6683f5888288f759512ac69e5c87efd2b6b87f7d79f"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/http.rs","sha256":"14c1fce14e24c984b2a275563a29b6326fb08367922b6e8d37ba38b9cb81aa2b"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/identity.rs","sha256":"186de11230c8b33375951c4368609f8976bf9795f171af3fd7fac26207a94361"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs","sha256":"0b4617d044f5254a5ab22f5a2578f91cc025206a8c1845be39c1c56dcdf7a5df"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/names.rs","sha256":"41bb23572d6002e23ee103d6fe70ecd68764861c6f2e48a1c53af998270a4afa"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs","sha256":"39fed883f4802e68d3b41a68fea0aba0737810996b33d13577de70faba004c29"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/store.rs","sha256":"fc60ee9c49b2f4f063c449b4c78100c5c4872779e94ca168f796603b380ef6e4"},{"path":"product/integrations/auths-custody/Cargo.toml","sha256":"1e14034185ad1ec24a977fd5f41d0abee219606245c046ce2a82287fadef448b"},{"path":"product/integrations/auths-custody/src/conformance.rs","sha256":"8ed1afd58f18fc6becc268908aa6419c9aa404c79da0197963eb2599df44acf6"},{"path":"product/integrations/auths-custody/src/key.rs","sha256":"70cbb0fd21b6f5652157845a22c35be2d0f6c05b3d138fc4b9bb6dbdc3d81c40"},{"path":"product/integrations/auths-custody/src/lib.rs","sha256":"8ee593c1f59b0fd2126bdda9138026f5bc531beb64d4489a99785842e7b98b43"},{"path":"product/operations/auths-operations/Cargo.toml","sha256":"73dde1e914ba5e1386f8d49c0d730423cc72ae77ec44c6554a6a75cc8e8922b1"},{"path":"product/operations/auths-operations/src/explanation.rs","sha256":"b4a39bcbd5712cb9e735ee7deeb281f3fa6af5ddca973735bf3d87dce427ef11"},{"path":"product/operations/auths-operations/src/lib.rs","sha256":"3f401a56555113b98f57bca172a2660eaecedf76247b83a3fdbb089c133a29cd"},{"path":"product/operations/auths-operations/src/render/json.rs","sha256":"2ae042639960afee123730e945d373bc5dda1d2b3af20ae16c939a7e99b9e418"},{"path":"product/operations/auths-operations/src/render/mod.rs","sha256":"b3b7f6fe473f49227ace5a68bfc3d8dc14b5db8dd9888fd9e207070337b1b8bf"},{"path":"product/operations/auths-operations/src/render/text.rs","sha256":"f216cf3bdb00e264523271b16e7059535ac6b1aabf271cebd7935af155e4bfec"},{"path":"product/policy/auths-bounded-policy/Cargo.toml","sha256":"babd5d200923137ead71d8c2528f847cea323ce98da942a1320b054436612c47"},{"path":"product/policy/auths-bounded-policy/src/arithmetic.rs","sha256":"75e43c5d4eab8d1f71c1daf53839f5f9fe45a400afc1f63a30c6f55ce3632627"},{"path":"product/policy/auths-bounded-policy/src/commitment.rs","sha256":"c5706f2d583454e1a7f570f7ada138d4d864bef0205dfae7c1296774f396bb3f"},{"path":"product/policy/auths-bounded-policy/src/eligibility.rs","sha256":"c9acdfb793074e687fc36efad506be27dbd99ffbf40387bc66c8de39ef238432"},{"path":"product/policy/auths-bounded-policy/src/identifier.rs","sha256":"0006a32bae9eb16c4178cf797df418d2b0a781f2bc6474b741dc1a908141831c"},{"path":"product/policy/auths-bounded-policy/src/kernel.rs","sha256":"99187c28b161ac70bee1afed60711f7f645adb4d1671a01863f9849b369811d5"},{"path":"product/policy/auths-bounded-policy/src/lib.rs","sha256":"76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c"},{"path":"product/policy/auths-bounded-policy/src/receipt.rs","sha256":"3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad"},{"path":"product/policy/auths-bounded-policy/src/registry.rs","sha256":"4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0"},{"path":"product/profiles/auths-profile-api/Cargo.toml","sha256":"7ae85761f58625b5d678f961fd052eebf3e000ef565c7312e3ac857763c0017f"},{"path":"product/profiles/auths-profile-api/src/lib.rs","sha256":"a194b82b20bf8aa864c2334ef6c6aec30b2154ded972862252d5dcefa488ab95"},{"path":"product/profiles/auths-profile-mcp/Cargo.toml","sha256":"db264fc25242f7b7e4133cbe5782545b3107b406c87168ae072683cfb59eac66"},{"path":"product/profiles/auths-profile-mcp/src/arguments.rs","sha256":"a5de696586d507e2aee4a49fee99ef1ef4c51a2e46603f8838f1af6d9009833f"},{"path":"product/profiles/auths-profile-mcp/src/lib.rs","sha256":"d0f8b733a09ef8408336cdebc8948d6a5861012ce6878598b11be7084dfd4280"},{"path":"product/profiles/auths-profile-mcp/src/session.rs","sha256":"166c281fa66333388e4760d6098dad02d3359e1d5de4b8f93312c014f97abb03"},{"path":"product/qualification/auths-recipe-qualification/Cargo.toml","sha256":"b7b15b30b9a3d96d4f089d514266d3a892de6608d30707aa44be31cca89ca9fe"},{"path":"product/qualification/auths-recipe-qualification/src/canonical.rs","sha256":"30a9b50777f0dcb4b606abfee2467d5a975d9f6ad941ab6c13ca3df5b359f667"},{"path":"product/qualification/auths-recipe-qualification/src/closure.rs","sha256":"0ad6aee9bd981e2863fa725f209ec84031db2ff12f4c7ac3aaf5120f0bb86039"},{"path":"product/qualification/auths-recipe-qualification/src/error.rs","sha256":"52d5cf720a1e4579008fdda90a3ac2c31f0b8db57985f121f65e54b4da2b7dd1"},{"path":"product/qualification/auths-recipe-qualification/src/evidence.rs","sha256":"ba45a7409d67a8af26ab811af306412014557477a101ab2a8eb0faf8f2bd4b91"},{"path":"product/qualification/auths-recipe-qualification/src/ids.rs","sha256":"e81a906d571497ab2da753e1532d4443706410e0b75fdd59a7d2d788c7aec403"},{"path":"product/qualification/auths-recipe-qualification/src/launch.rs","sha256":"41f2e2de90e1e7d6440a66eda3eb9bea8d5e0741bc232305a76a363ab5f813c1"},{"path":"product/qualification/auths-recipe-qualification/src/lib.rs","sha256":"5c9cff04c8960df805a2f7656cf5e74932798e0db7648341e96ae7073a592404"},{"path":"product/qualification/auths-recipe-qualification/src/model.rs","sha256":"3484eb0ec287b23d4682ade7b1b0f8d1335985b3fb180f06fc28716076957d5f"},{"path":"product/qualification/auths-recipe-qualification/src/release.rs","sha256":"d816b53e2275e902c750ad03803061844e259e28560ab2d1c77e8a43981a4d6a"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/mod.rs","sha256":"7f15b68e05a04f202bcb1fb80de1d9a9a4fda8bfd6af2cd4e5c660fc75d96fe5"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/schemas.rs","sha256":"c59feec2805621f341a90f81fc005e2c12f7a70f9d264fdeacccb2be4fe1c046"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/verification.rs","sha256":"6a6b5834c5dae10af1ba8939b2deae43b85db71544dc8f077ff63b7fe68ac8a8"},{"path":"product/qualification/auths-recipe-qualification/src/verify.rs","sha256":"a470a9b98c04dc8d5dabe4d3dc8ed4e7a3ceb1cde035944a0714462bbf37d56d"},{"path":"product/receipts/auths-receipts/Cargo.toml","sha256":"6001fa1375899953aafcb07c23a6da0c8f57ea7ec08bb9c950b12a60a8cc6f0f"},{"path":"product/receipts/auths-receipts/src/disclosure.rs","sha256":"ba9ed439be0a320c8a01f5b6e9b51361c1a37e076947490d8e4a484ba6bb119c"},{"path":"product/receipts/auths-receipts/src/lib.rs","sha256":"547a57c4160256719cafb7d0ab972d9fc80b0da14fbbce4148c70c414070ff36"},{"path":"product/runtime/auths-connections/Cargo.toml","sha256":"babeb6e1dda3dfb66291713ce1e43dce5c349833d0b50ea4dccbf986030026b2"},{"path":"product/runtime/auths-connections/src/credential.rs","sha256":"82921413bb053f0f6c7931fbd4e6a86c8cc1d8c6b51debd9c2cef33a8d5b1c51"},{"path":"product/runtime/auths-connections/src/kernel.rs","sha256":"a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8"},{"path":"product/runtime/auths-connections/src/lib.rs","sha256":"79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22"},{"path":"product/runtime/auths-connections/src/model.rs","sha256":"de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77"},{"path":"product/runtime/auths-connections/src/registry.rs","sha256":"e57640e003e72ad3235c567c2bb944a262bd64e673f023b62ea091094cc7e946"},{"path":"product/runtime/auths-gateway-kernel/Cargo.toml","sha256":"34f864e67656af4ac7e5c7a347a23f01fc8ab31365b8e23c0ef474483b14a183"},{"path":"product/runtime/auths-gateway-kernel/src/construct.rs","sha256":"e9d65744bae273d65face4285e5d2da75c06a92ab48f7b8333d496604e31c63c"},{"path":"product/runtime/auths-gateway-kernel/src/lib.rs","sha256":"cfda6f8453426564c085475f183b6f790b438768a19668f1b65d33ba59dc8632"},{"path":"product/runtime/auths-gateway-kernel/src/order.rs","sha256":"e0045f877c4b7fe3860c291039853885064ddcdebba7c9b345ab65e81e646dda"},{"path":"product/runtime/auths-gateway-kernel/src/outcome.rs","sha256":"e9785b1afe70788c89b51b18655bcd5acff7b0c8e3d12fb79c6f05a202e67e6b"},{"path":"product/runtime/auths-gateway-kernel/src/ratio.rs","sha256":"7ace22264812e6fc1ef3a62afee402cf43494bb71ae0d3de219ad1b39d690bcb"},{"path":"product/runtime/auths-gateway-kernel/src/recovery.rs","sha256":"9f46dcd1685ab6e4d1ba04a3fc286a9f3afee8fb47829be1fbc670a7926a2dc6"},{"path":"product/runtime/auths-gateway-kernel/src/transition.rs","sha256":"cefb8f01d915880f6921f2501ff881ad94b9de61072c34d9cd19220992f97374"},{"path":"product/runtime/auths-gateway/Cargo.toml","sha256":"00b28be86921dcdc0ad90cce0c62c2961cafefe96ea6c2edf0e926c3d405ccad"},{"path":"product/runtime/auths-gateway/src/admin.rs","sha256":"2d5cc67afac42fbd15f36e2d1693cd1b20cedacf775040dce6ffe04ccc94c9ea"},{"path":"product/runtime/auths-gateway/src/app.rs","sha256":"6f80f63833ea0815bb44fbf3b0cc54624a08e9fb578b035819f2980dc04e8256"},{"path":"product/runtime/auths-gateway/src/audit.rs","sha256":"0edb2037eb7b5d6f13acfce85c54f62a82bf7fdd31bc7e626c4fec183cef61dd"},{"path":"product/runtime/auths-gateway/src/audit_tests.rs","sha256":"990969384a52d75bc2489d9d412a9e7dd814bca1c8f65c701d6205fae62a15d5"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway-harness.rs","sha256":"12b0c24d36b2e6a3be392d3c081a783b355fdd67dc5b54bacc0410e803116b8c"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway.rs","sha256":"2f33a1da5dd54947ee1664795f90b3f07a11bb9ee184774bf470b78b03600f0c"},{"path":"product/runtime/auths-gateway/src/binding.rs","sha256":"663b0ce878319511aa7d05722ab4ab2fa9be18817884ffb2ee9f131ff1e382d1"},{"path":"product/runtime/auths-gateway/src/bounds.rs","sha256":"9cfa0eae4973e5e047a198360b22f041708fa20276b0b90c2ec440f06915d64b"},{"path":"product/runtime/auths-gateway/src/bounds_aggregate_tests.rs","sha256":"ab34f227b7c8692ba1da88ccb32bb3687a66adf8353d8282fae905d4a88eb612"},{"path":"product/runtime/auths-gateway/src/bounds_tests.rs","sha256":"74136bc570da7b9338b5a1a1ed9d3fd892c55135160964f9d3ac0e2cf5741375"},{"path":"product/runtime/auths-gateway/src/connection.rs","sha256":"7b5d049c258a26ed1c93ecf860f51d051a8a65f9b93554af0b1ea93862398ec9"},{"path":"product/runtime/auths-gateway/src/credential_journal.rs","sha256":"7297fccaee5cd8622928e8e0a42bba50da7941970a6f682ecd300c41ee6509da"},{"path":"product/runtime/auths-gateway/src/echo_verify.rs","sha256":"6d453051665f823abd7354d5c50031d9524cf47d6092d2f09080ae814e3b9575"},{"path":"product/runtime/auths-gateway/src/engine.rs","sha256":"f1052aaef43e441b9e0befa3f8ad1e2fd5279a27cb9d63aac0cf9dfdbe85a052"},{"path":"product/runtime/auths-gateway/src/fuzzing.rs","sha256":"ed3b0028487eb546a3b0a91d115aa8f18bcea324b61620bfe8e35a9e6ab18758"},{"path":"product/runtime/auths-gateway/src/generation_floor.rs","sha256":"fe1510ec96ce0f67e9a78edbfa94b33eb7df64c0ac4d0a67901124dcd0164777"},{"path":"product/runtime/auths-gateway/src/harness.rs","sha256":"c87e479f3eb281960f6c9c80d43c7560d7ccb654b0154ec823d3fcec4884ac05"},{"path":"product/runtime/auths-gateway/src/lib.rs","sha256":"a1f51b76524a89842720b4fda58b2293d4bc82b41c912d5a462261603c593cea"},{"path":"product/runtime/auths-gateway/src/listener.rs","sha256":"aa08239bcbc1fcb55e8a212fbdf6a84f12985b0d436dcb51dc58b06e59e435f2"},{"path":"product/runtime/auths-gateway/src/observed_tests.rs","sha256":"a22be071695f89ca2578a4d82fd80d9cb82289213c9bdb8f0470f6b2dc3d9201"},{"path":"product/runtime/auths-gateway/src/observer.rs","sha256":"562ffcaea071c3856e0708dc2fe33516917e145d2438aabb75af0a2b6ba01046"},{"path":"product/runtime/auths-gateway/src/onboarding.rs","sha256":"0dfd7d67e7f02f18a28d1c86ca1b7751d7463f5efcdbe3825de0ad8cbccb3891"},{"path":"product/runtime/auths-gateway/src/operator.rs","sha256":"c3c36954a3e86723df035b47f43b85fc8ab3a6292983522b6258d5c6b4e6c4e4"},{"path":"product/runtime/auths-gateway/src/pending_vectors/attempts.rs","sha256":"47ef3c8cb1c5504d47ae9a0088705ce6715fe86bac1671a34a56fb38a64d0dd3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/bounds.rs","sha256":"e612217307e1da5b0eb5ee6582a7458bb064b8aa8a529fc6555b1b334127ab68"},{"path":"product/runtime/auths-gateway/src/pending_vectors/codes.rs","sha256":"e00670a5ef24eb856cc2c6dcda8e5a263842f55c76bb939c0c27bd9df37e5522"},{"path":"product/runtime/auths-gateway/src/pending_vectors/keys.rs","sha256":"f84c56f2ea9cb34b2b79c72d13fbf2c6585010ec1ed450af58a78c80c1ea1edd"},{"path":"product/runtime/auths-gateway/src/pending_vectors/mod.rs","sha256":"5de8340f0ef71a0b57a09e323fefe473d3160c6ae952b9ba46f714825fbacafc"},{"path":"product/runtime/auths-gateway/src/pending_vectors/outcomes.rs","sha256":"8ec07b9511b48913af36ac999d2aa0e82924289f6acb23ddaeb9f00f99815166"},{"path":"product/runtime/auths-gateway/src/pending_vectors/production.rs","sha256":"f574cabfa4687a4fc846b8f6a234b68ec53b876aed548b11445729cac1a55ede"},{"path":"product/runtime/auths-gateway/src/pending_vectors/recipes.rs","sha256":"51693208270231c25c3aef2a32151d5962114c71e86b88cb9df83181c7af83d9"},{"path":"product/runtime/auths-gateway/src/pre_entry.rs","sha256":"06ea78ca140468bfaba17d9ab04912ad68673954c3203c98fed28272ff2a00c0"},{"path":"product/runtime/auths-gateway/src/property_tests.rs","sha256":"939c081e2e154aaf10186754044bdd65608932c899b970a04a71d0afaa999a93"},{"path":"product/runtime/auths-gateway/src/qualification.rs","sha256":"06b49d3fc2ad4383f9e23beefa96033f1fd6e415e043878327583451a53086cc"},{"path":"product/runtime/auths-gateway/src/qualification_simulation.rs","sha256":"4ee7cadfb5f46a92713c80f3e55f499cb074d04d8b21ea89d57762af38642bfa"},{"path":"product/runtime/auths-gateway/src/qualification_tests.rs","sha256":"a9178a2e58eea459d5e5dafc53a3999ea7c84dbbffefe6e5eb1f3d098827f028"},{"path":"product/runtime/auths-gateway/src/quorum_tests.rs","sha256":"a78380b019104d688c11a4410082c7e08ded3106aab099954c4f8a1b4ae0fd89"},{"path":"product/runtime/auths-gateway/src/readiness.rs","sha256":"911c3f11892f94641574375e2da4c671c802738f71082f12c39832331052d43d"},{"path":"product/runtime/auths-gateway/src/recipe.rs","sha256":"fecf9af67e7afc48d080e9f8f55f8ce28e49d0e08988717a27908bbda461d6b6"},{"path":"product/runtime/auths-gateway/src/recipe/lower.rs","sha256":"8088b8751ed831dbb48247af953c6290ac95e2a438ccd5bd65eff54be06a1fd1"},{"path":"product/runtime/auths-gateway/src/recipe/review.rs","sha256":"c3eb7d9fdd98dacf52750b14b67ad7b7faaecbbdeafff1e0b049f67d0a2d0139"},{"path":"product/runtime/auths-gateway/src/recipe/runtime.rs","sha256":"c286f0d15f974402822c0810d8e97f98411dc1c557755cc23e540d85e2bb42d9"},{"path":"product/runtime/auths-gateway/src/recipe/source.rs","sha256":"1af50298fb1461e1b24cbdf560d43124d6b1c4c529586c911b1c4797214a69ff"},{"path":"product/runtime/auths-gateway/src/recipe/tests.rs","sha256":"aac551a2481bbc60864c64079bc667dcb232e45a0f41a04073ed84ab5dbe1fce"},{"path":"product/runtime/auths-gateway/src/recipe/validate.rs","sha256":"3711b17605cb7b0d639bc1b180449231f5882a306cab20e2c7782155cc63b0d4"},{"path":"product/runtime/auths-gateway/src/scenario_tests.rs","sha256":"67915828ecfe2be0afadb5525277ab205f91172edc90852ec7b77c63b2d17fdc"},{"path":"product/runtime/auths-gateway/src/separation.rs","sha256":"be9306848ca5d801767cf6aa14247c8618312ef0e202f00ce0c24c4844491061"},{"path":"product/runtime/auths-gateway/src/simulation_attestation.rs","sha256":"88705e5d45415f760f1e3c3a065c35c48f4f4065bf7b3feb7882246983814d6f"},{"path":"product/runtime/auths-gateway/src/store.rs","sha256":"1e5288345c2cb1421aeda277b3158d07607404b0ec46943222ac107b63dcbb46"},{"path":"product/runtime/auths-gateway/src/store_testkit.rs","sha256":"88d82fee42f1b8ef521e8deef0216e938ebeaad822eb2f5020e70b89d145ea70"},{"path":"product/runtime/auths-gateway/src/submit.rs","sha256":"c78dbbba7c45b443febf655056c5edcd635e77be7b21c5b2c318097502415ffe"},{"path":"product/runtime/auths-gateway/src/support.rs","sha256":"9fd979029793a22b15d9776a7fc172476fd7c126a80d4080c65d720845becbcb"},{"path":"product/runtime/auths-gateway/src/transport.rs","sha256":"be2c6dc75b8daec110bf8749fedc3823f6067d40b999aa3eb21126896a97d3ad"},{"path":"product/runtime/auths-kernel-runtime/Cargo.toml","sha256":"926bcd0053e5edd703be8f0027ad009e2982db013c8174c1366edbf38b48087d"},{"path":"product/runtime/auths-kernel-runtime/src/lib.rs","sha256":"7108faae9ca4bc32dc093ddaf885ac8f74f3c9b8d317b7c7d0ed00d1d0ab5972"},{"path":"product/runtime/auths-lifecycle/Cargo.toml","sha256":"c5053c705f8d5554b44e432fe75287a2faf11d644e5a2552e45ad6cd94176af5"},{"path":"product/runtime/auths-lifecycle/src/codec.rs","sha256":"51c4b746749150e8bfcd8ff972b3f6c1ef40bec15583448ec1b471d9ad737dc0"},{"path":"product/runtime/auths-lifecycle/src/digest.rs","sha256":"55282cd7d8aba37713c2dcb5357c9877819edb72a30eadefb860d28d7d3a3eb7"},{"path":"product/runtime/auths-lifecycle/src/identifier.rs","sha256":"31620e8c16de68d3d2d3b84d6353c1a5b9d4151d8247f91fa389b906a8e660f1"},{"path":"product/runtime/auths-lifecycle/src/kernel.rs","sha256":"2abb8c094b36d35b364e74d78091d14c5d6f3d1eb6552cca3b5538dbd017ce23"},{"path":"product/runtime/auths-lifecycle/src/lib.rs","sha256":"afe5a345cd309b5a4f08ffba3170a6d7f16ff914892b3f2006d5208ed24ec736"},{"path":"product/runtime/auths-lifecycle/src/model.rs","sha256":"1af12bbeeeaa65ec02ddcebd7d2c8c92ec1e339fa40ae85b45ab9b01a722a4fa"},{"path":"product/runtime/auths-lifecycle/src/operation.rs","sha256":"78e6d05fcf5d7ea4f148032a3fa26fdfcab77eb346019effe927b08e0d64d732"},{"path":"product/runtime/auths-lifecycle/src/registry.rs","sha256":"53495fe6f7a77422593a41623e28716f1c140dcc1e00f87f6b0ffbfb93a5ef90"},{"path":"product/runtime/auths-lifecycle/src/sealed.rs","sha256":"2e0c03b5813c926c159598bb7890d1523825edbe57cd687d42a5dfb3374a0c19"},{"path":"product/runtime/auths-lifecycle/src/test_support.rs","sha256":"221d9a5c5ef8e1f9f8fd66927484eaf813571d0568470278ecd8fa08a5eec8cd"},{"path":"product/runtime/auths-lifecycle/src/transition.rs","sha256":"011805a28efdd541f44ccea54dd0e34a1e58f4004447ee58013703b4fb6b2822"},{"path":"product/runtime/auths-runtime/Cargo.toml","sha256":"dd29d80a8b4bb56c869f036a6c9998f6e6d1c0383ac5dc03fa42b24abe2a7ff7"},{"path":"product/runtime/auths-runtime/src/lib.rs","sha256":"132ca03d58c14905d3a822a4972f42a22a5ad33a45f2ba9ca44f3a57d810b4b0"},{"path":"product/runtime/auths-runtime/src/production.rs","sha256":"fd4eff4270c571c10fcff6cf27df28961ebf074de8a1a028f500fda1ca376820"},{"path":"product/sdk/auths-approval-quorum/Cargo.toml","sha256":"df904971fca87a24194c5816738a331588fe8f164acb5d70839a35dca5f57114"},{"path":"product/sdk/auths-approval-quorum/src/lib.rs","sha256":"72e4086088a1c0912e4e1a9e980f26a5c280bf5ab16ea39c9f0f58d5096ac2ce"},{"path":"product/sdk/auths-approval-quorum/src/remote.rs","sha256":"9fa029c7c63003adf260f8aec55160c545681c60c1bace0d934e7525862aac7b"},{"path":"product/sdk/auths-approval-quorum/src/remote_tests.rs","sha256":"8a09ce17cfee82a035a74edd535f3ebeb3db0e078784740d3997b17dbdb10197"},{"path":"product/sdk/auths-approval-quorum/src/tests.rs","sha256":"0acbf12be3e497dcc6c2d8f29c9af3b1a7ed8e11b75f6399570d4f217a785060"},{"path":"product/stores/auths-stores/Cargo.toml","sha256":"a32c4b76d17b264be5d40d24497ff237e1ed87822e8bab86229b3db93106dbe3"},{"path":"product/stores/auths-stores/src/gateway_attempt.rs","sha256":"185da8f4a220fba836d5b78a9311f03204681c43a3c53951008084d135bf4d21"},{"path":"product/stores/auths-stores/src/lib.rs","sha256":"e721262edf8a9ab5568ddc27639176312d4a366203b5f73e2d7c11fde2c554e9"},{"path":"product/stores/auths-stores/src/lifecycle.rs","sha256":"94f64d25bc178a9e60ba3c0ee6915d7fb3af7c4468792d76b4e70f43f4de1e2f"}],"schema":"auths.gateway-semantic-closure/1"} \ No newline at end of file +{"files":[{"path":"Cargo.lock","sha256":"0e75e2fdef44e79e57797ac6661295ae58ddb8de4a1990a6fd22ce6c54f78604"},{"path":"Cargo.toml","sha256":"6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24"},{"path":"core/adapters/auths-did-keri/Cargo.toml","sha256":"86ba3e3f9a0a70d970568bfb3113b7ba7bbdd81c3eebbb52743dd574a0c0ecaa"},{"path":"core/adapters/auths-did-keri/src/lib.rs","sha256":"a75674842f8a7142004369ccd206ab43e476459293f0ff4bed4d4e659031b3e3"},{"path":"core/adapters/auths-did-key/Cargo.toml","sha256":"d5a3ae07ecde83f91eed4c3785051dd0f44eab6c891754f3309b6b40596707d7"},{"path":"core/adapters/auths-did-key/src/lib.rs","sha256":"b76a3f4528a725df53cfa9242e6e414e1d26caa48468aaed497e28b121f4497c"},{"path":"core/adapters/auths-raw-key/Cargo.toml","sha256":"f49616bc18c19e6aaa7e6a02ccebcdb9f5c1422c1278ef9869e0dbf22ceda7be"},{"path":"core/adapters/auths-raw-key/src/lib.rs","sha256":"45eec1b295dac3bed65cd79c942870b926b06b3f5d38eaebaeb6140ac69315fa"},{"path":"core/crates/auths-algebra-kernel/Cargo.toml","sha256":"0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba"},{"path":"core/crates/auths-algebra-kernel/src/generated.rs","sha256":"ae4bcbef42a408c7ffa0c6a74a42f7de177a6f14479e51d205acf830bda05960"},{"path":"core/crates/auths-algebra-kernel/src/lib.rs","sha256":"6654667eeb9b353d6648954c9fd2e8838462a82ce6b2803eb49e1366892c68c6"},{"path":"core/crates/auths-assurance/Cargo.toml","sha256":"afcb12a97ddd09d7a264b9ecd3fcaefc865ff2c9b4539ee85b00883420ba333a"},{"path":"core/crates/auths-assurance/src/lib.rs","sha256":"0fb2ec844d674b25a9e20b1601452c89c2454901fa506adfa9bb38ef9a7fa213"},{"path":"core/crates/auths-author/Cargo.toml","sha256":"1e6f0e3bc079ddb558decf0db26b291c6e72fc47327b6df1b7650d41689b215f"},{"path":"core/crates/auths-author/src/lib.rs","sha256":"e14475f2f49715a1869d5fa6b11ff1fbb72497e39097e09f833b0bae7e5b3f2b"},{"path":"core/crates/auths-author/src/observations.rs","sha256":"dda7d6bfa6f4bd7e95a480ca283c2c0e996f69c5c15cb0c7197af328131a7066"},{"path":"core/crates/auths-authority/Cargo.toml","sha256":"4f68212938029f79ebd857b4f3038494eb85d0163d49f07e51376715cf959815"},{"path":"core/crates/auths-authority/src/lib.rs","sha256":"da88d5194de4e17449e69972c0fb042afa3c39798a8f570f30771e77c384f1eb"},{"path":"core/crates/auths-codec/Cargo.toml","sha256":"e20e51826e17814effd9d8925d18d5fbdd6c0d37bf50231e743ec2611314722c"},{"path":"core/crates/auths-codec/src/approval.rs","sha256":"fbff43bf4d57f69f8b7738a8647751cde75c5a932dee65d924a1fe9c7202f91f"},{"path":"core/crates/auths-codec/src/bounded_policy.rs","sha256":"d21f6728be2d8a04b6d94921f2b683f7e61cbb42e0ac6866f1c88a49caa534c3"},{"path":"core/crates/auths-codec/src/decode.rs","sha256":"ba2999584cdf53b1b517ecb9c7ea50d39efee17c666a9a38e2ad1ac94379f778"},{"path":"core/crates/auths-codec/src/encode.rs","sha256":"8491192053e2e15d62b4d2a491de22405b7487ead69ab6f6bca40669ce7ca5f7"},{"path":"core/crates/auths-codec/src/error.rs","sha256":"fecb0737c16deb42d859f1dc7727c698438d9ac12064fd99e0024629642c390c"},{"path":"core/crates/auths-codec/src/hash.rs","sha256":"f88e111f1dbb2cef6b7b5e9c948cb45ff92e366710c8a5f5c636138aa748479e"},{"path":"core/crates/auths-codec/src/lib.rs","sha256":"3b0e5c94c6f34f750b88a9333e1d5c8145746d845d3a23e0d2f61807cf592ea7"},{"path":"core/crates/auths-codec/src/observation.rs","sha256":"38328b0c71ff97a4196eeade8b4faa889527ff1f80bb168468bcd49082a3987e"},{"path":"core/crates/auths-composition/Cargo.toml","sha256":"331e13025eb82588b5269ed3975929eb41c823d588c49e4c296273d85c6fe80e"},{"path":"core/crates/auths-composition/src/lib.rs","sha256":"e42e3b0b6a9985b73c533aeb23799c638979aa27a9ce7d0f10a8d60340570fb1"},{"path":"core/crates/auths-model/Cargo.toml","sha256":"565c15302b0cc9270db1e28efa3862804846850ba933cc17aea8abcec4a65987"},{"path":"core/crates/auths-model/src/approval.rs","sha256":"54cf44a9ef747ec21546a4086aecfb130bc7803b0d646430e6082df51e6e305f"},{"path":"core/crates/auths-model/src/bounded.rs","sha256":"f90496abc0a06c028b4d850af6ddab7d850bfafeaa3d042f1b1246a41d8bbbc9"},{"path":"core/crates/auths-model/src/bounded_policy.rs","sha256":"306a8f049cc7cfc7635fe0e4de47eb7813eed63d3c14c3be2b51586aa4eea450"},{"path":"core/crates/auths-model/src/lib.rs","sha256":"e7cfe6bb9574c6b016aa63e70658c31e0b90903ec6479a49f4a2ceb64f5bad97"},{"path":"core/crates/auths-model/src/observation.rs","sha256":"b3ed3e3cc090afca2896a7d3de7988afccc1ee1ea0ebd91b51a8bc0f20ad8dbb"},{"path":"core/crates/auths-multikey/Cargo.toml","sha256":"858756c1197befcada06134742bffe8d58cf674cadd6c046bf710570e96efaf2"},{"path":"core/crates/auths-multikey/src/lib.rs","sha256":"f5177fffb11e40eeaaa665ba886c541fc1f24d5eacdd6983fb03dc20148733f0"},{"path":"core/crates/auths-ports/Cargo.toml","sha256":"596a9b0f5af3717c16a6d13f7054d8a106bcd9f01f5f72c2235dd2afcf0ab16c"},{"path":"core/crates/auths-ports/src/binding.rs","sha256":"a16c012d40aa4249e3ec54372b9611006d0bfe8c7dc3c741911c2194ad17736d"},{"path":"core/crates/auths-ports/src/diagnostics.rs","sha256":"aa596572503b5a65a918bb2ff38281c144ff53821ee914e9325c852828d852df"},{"path":"core/crates/auths-ports/src/lib.rs","sha256":"8da1debf86f9532df0660155d04298beb1ba3a1204508f8586e2e67cd2fb3449"},{"path":"core/crates/auths-ports/src/path.rs","sha256":"b68fc547b4e4d97a60cbbc1cc1939fc6b34a8233b81f840bd396914a707e3ea1"},{"path":"core/crates/auths-raw-key-core/Cargo.toml","sha256":"98c0bc8527a537512e43a74dd6ba9658c6f0cdc16610cf938e3f9b43785d836d"},{"path":"core/crates/auths-raw-key-core/src/lib.rs","sha256":"98c0500c41697aae28708ad0bf970b9a97583d96a3d2c18d23e7fa351e0f7d12"},{"path":"core/crates/auths-registries/Cargo.toml","sha256":"590e49e58b0622d9d6274fea46796dcdb07dec9550eff295cce6a6427ffa51e2"},{"path":"core/crates/auths-registries/src/lib.rs","sha256":"450d3886d85ee333b7e046317fb5b47cde62483d5f3e41d46265e2caf4c373ec"},{"path":"core/crates/auths-registries/src/template.rs","sha256":"1224039dd2b3ce6fa8357613d8cafbae40400493da7176da202b9ade62fa05e4"},{"path":"core/crates/auths-signature-core/Cargo.toml","sha256":"6bee2230eb30af1be0bd5c2d57bd3e1903497a70028d47290d4ac6e9e0e8bca0"},{"path":"core/crates/auths-signature-core/src/lib.rs","sha256":"6e3f9311ded5e49ea50d445eb21e6d8fa12442aa4362a73e0cb6fda15b7cd865"},{"path":"core/crates/auths-signature/Cargo.toml","sha256":"7f7b5682466ba439d8c59579022cb61068cad9fb4bd2d73e1cc21327c902b450"},{"path":"core/crates/auths-signature/src/lib.rs","sha256":"b3d9ac4cc3ba0797b9e1c09f2d6ac05089b25dac4e285a5af28c0165b33d925b"},{"path":"core/crates/auths-verifier/Cargo.toml","sha256":"c43358e06a33324b41a8b93e5cc7279c55f7d21f1f6cfaa539a3fc7b4c27a38f"},{"path":"core/crates/auths-verifier/src/approval.rs","sha256":"c3cae6a49e169051eb555bb092b1069a4d422516d6a2114623a89e5f31ff923f"},{"path":"core/crates/auths-verifier/src/causal.rs","sha256":"9635230f33b13a263573d319ac8a1976addbcc07677514a43e3c7bf28dc04587"},{"path":"core/crates/auths-verifier/src/lib.rs","sha256":"f22dec38dfa47ced8da4f605390da8453273bee1da010f57fd1fdfcb10e0b389"},{"path":"core/crates/auths-verifier/src/observation.rs","sha256":"0bb07f06a0f9524c88427df1c972b1de8ba038a9eeeb15d3134c25125ae84b1e"},{"path":"core/crates/auths-verifier/src/trace.rs","sha256":"2213d72023a1d9e0413a2cf2c51c3dad9e04775d86033a0caaa9d29a8f0036f8"},{"path":"exchange/crates/auths-proof-exchange-model/Cargo.toml","sha256":"34b2db64f93a288e942b5a3918d28cdcbef906e0dc9074ce848018d3d5f7a1fa"},{"path":"exchange/crates/auths-proof-exchange-model/src/lib.rs","sha256":"49fac5aff2339d3a57c41cb8bb2a82852538e8f77ecc4b157c88e264ff31fb55"},{"path":"exchange/crates/auths-proof-exchange-port/Cargo.toml","sha256":"7ff660f1b7579dc570c791090aeb450404fbbf44c92781e289f5ccdde746d739"},{"path":"exchange/crates/auths-proof-exchange-port/src/lib.rs","sha256":"b408fb40c6432edc1facb3d8b3e9433a033f8dc73fe2e0ba5a88c972ca675021"},{"path":"product/config/auths-config/Cargo.toml","sha256":"e4b568ab9f6d84f7d7e6d66443fe825f360db9c27bc7c31d6ddc0647ba3ab304"},{"path":"product/config/auths-config/src/lib.rs","sha256":"fecf00ea65cef9018fda9af2063326d7065b869266d0d9e73a4f06816f1102cc"},{"path":"product/errors/auths-errors/Cargo.toml","sha256":"3b3a199b6460ba75bda84475bb5accd35e1485448a3981038db85bf4772dd350"},{"path":"product/errors/auths-errors/src/lib.rs","sha256":"7feeb9069fa4003f94f1f07c1c94619cf1c883e0dbaaf2187f04d0f742264bdd"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/Cargo.toml","sha256":"716f1f2a117d6d69d8effe9ee9057e24ba3502f20af6a602b06facb638cdabed"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/api.rs","sha256":"9ea61dd7ddd93282b073b98e453e6b75b26dc49689c04e9782435d06a3a09e48"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/clock.rs","sha256":"73f0a6e0f5903883329fa6683f5888288f759512ac69e5c87efd2b6b87f7d79f"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/http.rs","sha256":"14c1fce14e24c984b2a275563a29b6326fb08367922b6e8d37ba38b9cb81aa2b"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/identity.rs","sha256":"186de11230c8b33375951c4368609f8976bf9795f171af3fd7fac26207a94361"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs","sha256":"0b4617d044f5254a5ab22f5a2578f91cc025206a8c1845be39c1c56dcdf7a5df"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/names.rs","sha256":"41bb23572d6002e23ee103d6fe70ecd68764861c6f2e48a1c53af998270a4afa"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs","sha256":"39fed883f4802e68d3b41a68fea0aba0737810996b33d13577de70faba004c29"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/store.rs","sha256":"fc60ee9c49b2f4f063c449b4c78100c5c4872779e94ca168f796603b380ef6e4"},{"path":"product/integrations/auths-custody/Cargo.toml","sha256":"1e14034185ad1ec24a977fd5f41d0abee219606245c046ce2a82287fadef448b"},{"path":"product/integrations/auths-custody/src/conformance.rs","sha256":"8ed1afd58f18fc6becc268908aa6419c9aa404c79da0197963eb2599df44acf6"},{"path":"product/integrations/auths-custody/src/key.rs","sha256":"70cbb0fd21b6f5652157845a22c35be2d0f6c05b3d138fc4b9bb6dbdc3d81c40"},{"path":"product/integrations/auths-custody/src/lib.rs","sha256":"8ee593c1f59b0fd2126bdda9138026f5bc531beb64d4489a99785842e7b98b43"},{"path":"product/operations/auths-operations/Cargo.toml","sha256":"73dde1e914ba5e1386f8d49c0d730423cc72ae77ec44c6554a6a75cc8e8922b1"},{"path":"product/operations/auths-operations/src/explanation.rs","sha256":"b4a39bcbd5712cb9e735ee7deeb281f3fa6af5ddca973735bf3d87dce427ef11"},{"path":"product/operations/auths-operations/src/lib.rs","sha256":"3f401a56555113b98f57bca172a2660eaecedf76247b83a3fdbb089c133a29cd"},{"path":"product/operations/auths-operations/src/render/json.rs","sha256":"2ae042639960afee123730e945d373bc5dda1d2b3af20ae16c939a7e99b9e418"},{"path":"product/operations/auths-operations/src/render/mod.rs","sha256":"b3b7f6fe473f49227ace5a68bfc3d8dc14b5db8dd9888fd9e207070337b1b8bf"},{"path":"product/operations/auths-operations/src/render/text.rs","sha256":"f216cf3bdb00e264523271b16e7059535ac6b1aabf271cebd7935af155e4bfec"},{"path":"product/policy/auths-bounded-policy/Cargo.toml","sha256":"babd5d200923137ead71d8c2528f847cea323ce98da942a1320b054436612c47"},{"path":"product/policy/auths-bounded-policy/src/arithmetic.rs","sha256":"75e43c5d4eab8d1f71c1daf53839f5f9fe45a400afc1f63a30c6f55ce3632627"},{"path":"product/policy/auths-bounded-policy/src/commitment.rs","sha256":"c5706f2d583454e1a7f570f7ada138d4d864bef0205dfae7c1296774f396bb3f"},{"path":"product/policy/auths-bounded-policy/src/eligibility.rs","sha256":"c9acdfb793074e687fc36efad506be27dbd99ffbf40387bc66c8de39ef238432"},{"path":"product/policy/auths-bounded-policy/src/identifier.rs","sha256":"0006a32bae9eb16c4178cf797df418d2b0a781f2bc6474b741dc1a908141831c"},{"path":"product/policy/auths-bounded-policy/src/kernel.rs","sha256":"99187c28b161ac70bee1afed60711f7f645adb4d1671a01863f9849b369811d5"},{"path":"product/policy/auths-bounded-policy/src/lib.rs","sha256":"76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c"},{"path":"product/policy/auths-bounded-policy/src/receipt.rs","sha256":"3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad"},{"path":"product/policy/auths-bounded-policy/src/registry.rs","sha256":"4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0"},{"path":"product/profiles/auths-profile-api/Cargo.toml","sha256":"7ae85761f58625b5d678f961fd052eebf3e000ef565c7312e3ac857763c0017f"},{"path":"product/profiles/auths-profile-api/src/lib.rs","sha256":"a194b82b20bf8aa864c2334ef6c6aec30b2154ded972862252d5dcefa488ab95"},{"path":"product/profiles/auths-profile-mcp/Cargo.toml","sha256":"db264fc25242f7b7e4133cbe5782545b3107b406c87168ae072683cfb59eac66"},{"path":"product/profiles/auths-profile-mcp/src/arguments.rs","sha256":"a5de696586d507e2aee4a49fee99ef1ef4c51a2e46603f8838f1af6d9009833f"},{"path":"product/profiles/auths-profile-mcp/src/lib.rs","sha256":"d0f8b733a09ef8408336cdebc8948d6a5861012ce6878598b11be7084dfd4280"},{"path":"product/profiles/auths-profile-mcp/src/session.rs","sha256":"166c281fa66333388e4760d6098dad02d3359e1d5de4b8f93312c014f97abb03"},{"path":"product/qualification/auths-recipe-qualification/Cargo.toml","sha256":"b7b15b30b9a3d96d4f089d514266d3a892de6608d30707aa44be31cca89ca9fe"},{"path":"product/qualification/auths-recipe-qualification/src/canonical.rs","sha256":"30a9b50777f0dcb4b606abfee2467d5a975d9f6ad941ab6c13ca3df5b359f667"},{"path":"product/qualification/auths-recipe-qualification/src/closure.rs","sha256":"0ad6aee9bd981e2863fa725f209ec84031db2ff12f4c7ac3aaf5120f0bb86039"},{"path":"product/qualification/auths-recipe-qualification/src/commissioning.rs","sha256":"e902df9b2c6bd06bedd32ef40e23ce14b4db4882dcb12b0f0aabcb7335cfa515"},{"path":"product/qualification/auths-recipe-qualification/src/commissioning/tests.rs","sha256":"5a226725c2ad7ce920d0bd62d427185e007f4d0949b0f0ec1260aa161d3114d0"},{"path":"product/qualification/auths-recipe-qualification/src/error.rs","sha256":"52d5cf720a1e4579008fdda90a3ac2c31f0b8db57985f121f65e54b4da2b7dd1"},{"path":"product/qualification/auths-recipe-qualification/src/evidence.rs","sha256":"ba45a7409d67a8af26ab811af306412014557477a101ab2a8eb0faf8f2bd4b91"},{"path":"product/qualification/auths-recipe-qualification/src/ids.rs","sha256":"e81a906d571497ab2da753e1532d4443706410e0b75fdd59a7d2d788c7aec403"},{"path":"product/qualification/auths-recipe-qualification/src/launch.rs","sha256":"41f2e2de90e1e7d6440a66eda3eb9bea8d5e0741bc232305a76a363ab5f813c1"},{"path":"product/qualification/auths-recipe-qualification/src/lib.rs","sha256":"7ef5cb7b8eacaa38c5d512b589db5e78e4597aed7d1a10368b86eebfb5a48aeb"},{"path":"product/qualification/auths-recipe-qualification/src/model.rs","sha256":"3484eb0ec287b23d4682ade7b1b0f8d1335985b3fb180f06fc28716076957d5f"},{"path":"product/qualification/auths-recipe-qualification/src/release.rs","sha256":"ec478e53f70052e566aac7e15be2f9e1b1cd46837ac6990ae955fa864d311586"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/mod.rs","sha256":"7f15b68e05a04f202bcb1fb80de1d9a9a4fda8bfd6af2cd4e5c660fc75d96fe5"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/schemas.rs","sha256":"c59feec2805621f341a90f81fc005e2c12f7a70f9d264fdeacccb2be4fe1c046"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/verification.rs","sha256":"6a6b5834c5dae10af1ba8939b2deae43b85db71544dc8f077ff63b7fe68ac8a8"},{"path":"product/qualification/auths-recipe-qualification/src/verify.rs","sha256":"2ec2784435d11e07295de77b2ee1b2c48b2fcf9609a00454c6e7374b621aed5c"},{"path":"product/receipts/auths-receipts/Cargo.toml","sha256":"6001fa1375899953aafcb07c23a6da0c8f57ea7ec08bb9c950b12a60a8cc6f0f"},{"path":"product/receipts/auths-receipts/src/disclosure.rs","sha256":"ba9ed439be0a320c8a01f5b6e9b51361c1a37e076947490d8e4a484ba6bb119c"},{"path":"product/receipts/auths-receipts/src/lib.rs","sha256":"547a57c4160256719cafb7d0ab972d9fc80b0da14fbbce4148c70c414070ff36"},{"path":"product/runtime/auths-connections/Cargo.toml","sha256":"babeb6e1dda3dfb66291713ce1e43dce5c349833d0b50ea4dccbf986030026b2"},{"path":"product/runtime/auths-connections/src/credential.rs","sha256":"82921413bb053f0f6c7931fbd4e6a86c8cc1d8c6b51debd9c2cef33a8d5b1c51"},{"path":"product/runtime/auths-connections/src/kernel.rs","sha256":"a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8"},{"path":"product/runtime/auths-connections/src/lib.rs","sha256":"79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22"},{"path":"product/runtime/auths-connections/src/model.rs","sha256":"de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77"},{"path":"product/runtime/auths-connections/src/registry.rs","sha256":"e57640e003e72ad3235c567c2bb944a262bd64e673f023b62ea091094cc7e946"},{"path":"product/runtime/auths-gateway-kernel/Cargo.toml","sha256":"34f864e67656af4ac7e5c7a347a23f01fc8ab31365b8e23c0ef474483b14a183"},{"path":"product/runtime/auths-gateway-kernel/src/construct.rs","sha256":"e9d65744bae273d65face4285e5d2da75c06a92ab48f7b8333d496604e31c63c"},{"path":"product/runtime/auths-gateway-kernel/src/lib.rs","sha256":"cfda6f8453426564c085475f183b6f790b438768a19668f1b65d33ba59dc8632"},{"path":"product/runtime/auths-gateway-kernel/src/order.rs","sha256":"e0045f877c4b7fe3860c291039853885064ddcdebba7c9b345ab65e81e646dda"},{"path":"product/runtime/auths-gateway-kernel/src/outcome.rs","sha256":"e9785b1afe70788c89b51b18655bcd5acff7b0c8e3d12fb79c6f05a202e67e6b"},{"path":"product/runtime/auths-gateway-kernel/src/ratio.rs","sha256":"7ace22264812e6fc1ef3a62afee402cf43494bb71ae0d3de219ad1b39d690bcb"},{"path":"product/runtime/auths-gateway-kernel/src/recovery.rs","sha256":"9f46dcd1685ab6e4d1ba04a3fc286a9f3afee8fb47829be1fbc670a7926a2dc6"},{"path":"product/runtime/auths-gateway-kernel/src/transition.rs","sha256":"cefb8f01d915880f6921f2501ff881ad94b9de61072c34d9cd19220992f97374"},{"path":"product/runtime/auths-gateway/Cargo.toml","sha256":"00b28be86921dcdc0ad90cce0c62c2961cafefe96ea6c2edf0e926c3d405ccad"},{"path":"product/runtime/auths-gateway/src/admin.rs","sha256":"2d5cc67afac42fbd15f36e2d1693cd1b20cedacf775040dce6ffe04ccc94c9ea"},{"path":"product/runtime/auths-gateway/src/app.rs","sha256":"6f80f63833ea0815bb44fbf3b0cc54624a08e9fb578b035819f2980dc04e8256"},{"path":"product/runtime/auths-gateway/src/audit.rs","sha256":"0edb2037eb7b5d6f13acfce85c54f62a82bf7fdd31bc7e626c4fec183cef61dd"},{"path":"product/runtime/auths-gateway/src/audit_tests.rs","sha256":"990969384a52d75bc2489d9d412a9e7dd814bca1c8f65c701d6205fae62a15d5"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway-harness.rs","sha256":"12b0c24d36b2e6a3be392d3c081a783b355fdd67dc5b54bacc0410e803116b8c"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway.rs","sha256":"2f33a1da5dd54947ee1664795f90b3f07a11bb9ee184774bf470b78b03600f0c"},{"path":"product/runtime/auths-gateway/src/binding.rs","sha256":"663b0ce878319511aa7d05722ab4ab2fa9be18817884ffb2ee9f131ff1e382d1"},{"path":"product/runtime/auths-gateway/src/bounds.rs","sha256":"9cfa0eae4973e5e047a198360b22f041708fa20276b0b90c2ec440f06915d64b"},{"path":"product/runtime/auths-gateway/src/bounds_aggregate_tests.rs","sha256":"ab34f227b7c8692ba1da88ccb32bb3687a66adf8353d8282fae905d4a88eb612"},{"path":"product/runtime/auths-gateway/src/bounds_tests.rs","sha256":"74136bc570da7b9338b5a1a1ed9d3fd892c55135160964f9d3ac0e2cf5741375"},{"path":"product/runtime/auths-gateway/src/connection.rs","sha256":"7b5d049c258a26ed1c93ecf860f51d051a8a65f9b93554af0b1ea93862398ec9"},{"path":"product/runtime/auths-gateway/src/credential_journal.rs","sha256":"7297fccaee5cd8622928e8e0a42bba50da7941970a6f682ecd300c41ee6509da"},{"path":"product/runtime/auths-gateway/src/echo_verify.rs","sha256":"6d453051665f823abd7354d5c50031d9524cf47d6092d2f09080ae814e3b9575"},{"path":"product/runtime/auths-gateway/src/engine.rs","sha256":"f1052aaef43e441b9e0befa3f8ad1e2fd5279a27cb9d63aac0cf9dfdbe85a052"},{"path":"product/runtime/auths-gateway/src/fuzzing.rs","sha256":"ed3b0028487eb546a3b0a91d115aa8f18bcea324b61620bfe8e35a9e6ab18758"},{"path":"product/runtime/auths-gateway/src/generation_floor.rs","sha256":"fe1510ec96ce0f67e9a78edbfa94b33eb7df64c0ac4d0a67901124dcd0164777"},{"path":"product/runtime/auths-gateway/src/harness.rs","sha256":"c87e479f3eb281960f6c9c80d43c7560d7ccb654b0154ec823d3fcec4884ac05"},{"path":"product/runtime/auths-gateway/src/lib.rs","sha256":"a1f51b76524a89842720b4fda58b2293d4bc82b41c912d5a462261603c593cea"},{"path":"product/runtime/auths-gateway/src/listener.rs","sha256":"aa08239bcbc1fcb55e8a212fbdf6a84f12985b0d436dcb51dc58b06e59e435f2"},{"path":"product/runtime/auths-gateway/src/observed_tests.rs","sha256":"a22be071695f89ca2578a4d82fd80d9cb82289213c9bdb8f0470f6b2dc3d9201"},{"path":"product/runtime/auths-gateway/src/observer.rs","sha256":"562ffcaea071c3856e0708dc2fe33516917e145d2438aabb75af0a2b6ba01046"},{"path":"product/runtime/auths-gateway/src/onboarding.rs","sha256":"0dfd7d67e7f02f18a28d1c86ca1b7751d7463f5efcdbe3825de0ad8cbccb3891"},{"path":"product/runtime/auths-gateway/src/operator.rs","sha256":"c3c36954a3e86723df035b47f43b85fc8ab3a6292983522b6258d5c6b4e6c4e4"},{"path":"product/runtime/auths-gateway/src/pending_vectors/attempts.rs","sha256":"47ef3c8cb1c5504d47ae9a0088705ce6715fe86bac1671a34a56fb38a64d0dd3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/bounds.rs","sha256":"e612217307e1da5b0eb5ee6582a7458bb064b8aa8a529fc6555b1b334127ab68"},{"path":"product/runtime/auths-gateway/src/pending_vectors/codes.rs","sha256":"e00670a5ef24eb856cc2c6dcda8e5a263842f55c76bb939c0c27bd9df37e5522"},{"path":"product/runtime/auths-gateway/src/pending_vectors/keys.rs","sha256":"f84c56f2ea9cb34b2b79c72d13fbf2c6585010ec1ed450af58a78c80c1ea1edd"},{"path":"product/runtime/auths-gateway/src/pending_vectors/mod.rs","sha256":"5de8340f0ef71a0b57a09e323fefe473d3160c6ae952b9ba46f714825fbacafc"},{"path":"product/runtime/auths-gateway/src/pending_vectors/outcomes.rs","sha256":"8ec07b9511b48913af36ac999d2aa0e82924289f6acb23ddaeb9f00f99815166"},{"path":"product/runtime/auths-gateway/src/pending_vectors/production.rs","sha256":"f574cabfa4687a4fc846b8f6a234b68ec53b876aed548b11445729cac1a55ede"},{"path":"product/runtime/auths-gateway/src/pending_vectors/recipes.rs","sha256":"51693208270231c25c3aef2a32151d5962114c71e86b88cb9df83181c7af83d9"},{"path":"product/runtime/auths-gateway/src/pre_entry.rs","sha256":"06ea78ca140468bfaba17d9ab04912ad68673954c3203c98fed28272ff2a00c0"},{"path":"product/runtime/auths-gateway/src/property_tests.rs","sha256":"939c081e2e154aaf10186754044bdd65608932c899b970a04a71d0afaa999a93"},{"path":"product/runtime/auths-gateway/src/qualification.rs","sha256":"06b49d3fc2ad4383f9e23beefa96033f1fd6e415e043878327583451a53086cc"},{"path":"product/runtime/auths-gateway/src/qualification_simulation.rs","sha256":"4ee7cadfb5f46a92713c80f3e55f499cb074d04d8b21ea89d57762af38642bfa"},{"path":"product/runtime/auths-gateway/src/qualification_tests.rs","sha256":"a9178a2e58eea459d5e5dafc53a3999ea7c84dbbffefe6e5eb1f3d098827f028"},{"path":"product/runtime/auths-gateway/src/quorum_tests.rs","sha256":"a78380b019104d688c11a4410082c7e08ded3106aab099954c4f8a1b4ae0fd89"},{"path":"product/runtime/auths-gateway/src/readiness.rs","sha256":"911c3f11892f94641574375e2da4c671c802738f71082f12c39832331052d43d"},{"path":"product/runtime/auths-gateway/src/recipe.rs","sha256":"fecf9af67e7afc48d080e9f8f55f8ce28e49d0e08988717a27908bbda461d6b6"},{"path":"product/runtime/auths-gateway/src/recipe/lower.rs","sha256":"8088b8751ed831dbb48247af953c6290ac95e2a438ccd5bd65eff54be06a1fd1"},{"path":"product/runtime/auths-gateway/src/recipe/review.rs","sha256":"c3eb7d9fdd98dacf52750b14b67ad7b7faaecbbdeafff1e0b049f67d0a2d0139"},{"path":"product/runtime/auths-gateway/src/recipe/runtime.rs","sha256":"c286f0d15f974402822c0810d8e97f98411dc1c557755cc23e540d85e2bb42d9"},{"path":"product/runtime/auths-gateway/src/recipe/source.rs","sha256":"1af50298fb1461e1b24cbdf560d43124d6b1c4c529586c911b1c4797214a69ff"},{"path":"product/runtime/auths-gateway/src/recipe/tests.rs","sha256":"aac551a2481bbc60864c64079bc667dcb232e45a0f41a04073ed84ab5dbe1fce"},{"path":"product/runtime/auths-gateway/src/recipe/validate.rs","sha256":"3711b17605cb7b0d639bc1b180449231f5882a306cab20e2c7782155cc63b0d4"},{"path":"product/runtime/auths-gateway/src/scenario_tests.rs","sha256":"67915828ecfe2be0afadb5525277ab205f91172edc90852ec7b77c63b2d17fdc"},{"path":"product/runtime/auths-gateway/src/separation.rs","sha256":"be9306848ca5d801767cf6aa14247c8618312ef0e202f00ce0c24c4844491061"},{"path":"product/runtime/auths-gateway/src/simulation_attestation.rs","sha256":"88705e5d45415f760f1e3c3a065c35c48f4f4065bf7b3feb7882246983814d6f"},{"path":"product/runtime/auths-gateway/src/store.rs","sha256":"1e5288345c2cb1421aeda277b3158d07607404b0ec46943222ac107b63dcbb46"},{"path":"product/runtime/auths-gateway/src/store_testkit.rs","sha256":"88d82fee42f1b8ef521e8deef0216e938ebeaad822eb2f5020e70b89d145ea70"},{"path":"product/runtime/auths-gateway/src/submit.rs","sha256":"c78dbbba7c45b443febf655056c5edcd635e77be7b21c5b2c318097502415ffe"},{"path":"product/runtime/auths-gateway/src/support.rs","sha256":"9fd979029793a22b15d9776a7fc172476fd7c126a80d4080c65d720845becbcb"},{"path":"product/runtime/auths-gateway/src/transport.rs","sha256":"be2c6dc75b8daec110bf8749fedc3823f6067d40b999aa3eb21126896a97d3ad"},{"path":"product/runtime/auths-kernel-runtime/Cargo.toml","sha256":"926bcd0053e5edd703be8f0027ad009e2982db013c8174c1366edbf38b48087d"},{"path":"product/runtime/auths-kernel-runtime/src/lib.rs","sha256":"7108faae9ca4bc32dc093ddaf885ac8f74f3c9b8d317b7c7d0ed00d1d0ab5972"},{"path":"product/runtime/auths-lifecycle/Cargo.toml","sha256":"c5053c705f8d5554b44e432fe75287a2faf11d644e5a2552e45ad6cd94176af5"},{"path":"product/runtime/auths-lifecycle/src/codec.rs","sha256":"51c4b746749150e8bfcd8ff972b3f6c1ef40bec15583448ec1b471d9ad737dc0"},{"path":"product/runtime/auths-lifecycle/src/digest.rs","sha256":"55282cd7d8aba37713c2dcb5357c9877819edb72a30eadefb860d28d7d3a3eb7"},{"path":"product/runtime/auths-lifecycle/src/identifier.rs","sha256":"31620e8c16de68d3d2d3b84d6353c1a5b9d4151d8247f91fa389b906a8e660f1"},{"path":"product/runtime/auths-lifecycle/src/kernel.rs","sha256":"2abb8c094b36d35b364e74d78091d14c5d6f3d1eb6552cca3b5538dbd017ce23"},{"path":"product/runtime/auths-lifecycle/src/lib.rs","sha256":"afe5a345cd309b5a4f08ffba3170a6d7f16ff914892b3f2006d5208ed24ec736"},{"path":"product/runtime/auths-lifecycle/src/model.rs","sha256":"1af12bbeeeaa65ec02ddcebd7d2c8c92ec1e339fa40ae85b45ab9b01a722a4fa"},{"path":"product/runtime/auths-lifecycle/src/operation.rs","sha256":"78e6d05fcf5d7ea4f148032a3fa26fdfcab77eb346019effe927b08e0d64d732"},{"path":"product/runtime/auths-lifecycle/src/registry.rs","sha256":"53495fe6f7a77422593a41623e28716f1c140dcc1e00f87f6b0ffbfb93a5ef90"},{"path":"product/runtime/auths-lifecycle/src/sealed.rs","sha256":"2e0c03b5813c926c159598bb7890d1523825edbe57cd687d42a5dfb3374a0c19"},{"path":"product/runtime/auths-lifecycle/src/test_support.rs","sha256":"221d9a5c5ef8e1f9f8fd66927484eaf813571d0568470278ecd8fa08a5eec8cd"},{"path":"product/runtime/auths-lifecycle/src/transition.rs","sha256":"011805a28efdd541f44ccea54dd0e34a1e58f4004447ee58013703b4fb6b2822"},{"path":"product/runtime/auths-runtime/Cargo.toml","sha256":"dd29d80a8b4bb56c869f036a6c9998f6e6d1c0383ac5dc03fa42b24abe2a7ff7"},{"path":"product/runtime/auths-runtime/src/lib.rs","sha256":"132ca03d58c14905d3a822a4972f42a22a5ad33a45f2ba9ca44f3a57d810b4b0"},{"path":"product/runtime/auths-runtime/src/production.rs","sha256":"fd4eff4270c571c10fcff6cf27df28961ebf074de8a1a028f500fda1ca376820"},{"path":"product/sdk/auths-approval-quorum/Cargo.toml","sha256":"df904971fca87a24194c5816738a331588fe8f164acb5d70839a35dca5f57114"},{"path":"product/sdk/auths-approval-quorum/src/lib.rs","sha256":"72e4086088a1c0912e4e1a9e980f26a5c280bf5ab16ea39c9f0f58d5096ac2ce"},{"path":"product/sdk/auths-approval-quorum/src/remote.rs","sha256":"9fa029c7c63003adf260f8aec55160c545681c60c1bace0d934e7525862aac7b"},{"path":"product/sdk/auths-approval-quorum/src/remote_tests.rs","sha256":"8a09ce17cfee82a035a74edd535f3ebeb3db0e078784740d3997b17dbdb10197"},{"path":"product/sdk/auths-approval-quorum/src/tests.rs","sha256":"0acbf12be3e497dcc6c2d8f29c9af3b1a7ed8e11b75f6399570d4f217a785060"},{"path":"product/stores/auths-stores/Cargo.toml","sha256":"a32c4b76d17b264be5d40d24497ff237e1ed87822e8bab86229b3db93106dbe3"},{"path":"product/stores/auths-stores/src/gateway_attempt.rs","sha256":"185da8f4a220fba836d5b78a9311f03204681c43a3c53951008084d135bf4d21"},{"path":"product/stores/auths-stores/src/lib.rs","sha256":"e721262edf8a9ab5568ddc27639176312d4a366203b5f73e2d7c11fde2c554e9"},{"path":"product/stores/auths-stores/src/lifecycle.rs","sha256":"94f64d25bc178a9e60ba3c0ee6915d7fb3af7c4468792d76b4e70f43f4de1e2f"}],"schema":"auths.gateway-semantic-closure/1"} \ No newline at end of file diff --git a/product/runtime/auths-gateway/src/semantic_closure.rs b/product/runtime/auths-gateway/src/semantic_closure.rs index 6ec13ddf8..1d18ce55a 100644 --- a/product/runtime/auths-gateway/src/semantic_closure.rs +++ b/product/runtime/auths-gateway/src/semantic_closure.rs @@ -10,7 +10,7 @@ /// SHA-256 of the schema, a NUL byte, and `semantic-closure.json`. /// Regenerate through `semantic_closure_is_current` with `AUTHS_UPDATE_FIXTURES=1`. pub const GATEWAY_SEMANTIC_CLOSURE_SHA256: &str = - "1bba718ab65c29ff96190b087e2b63c32b5305f9dce0b070547b2b40e077efd0"; + "3c5fb82215a577faa84203c241e5e3fe49ffa21383bc5e15bc5c55c7e6bf8019"; #[cfg(test)] mod tests { From 8b2accd0df14bc747be4e55bfb54ade93a2a811f Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 03:36:55 +0100 Subject: [PATCH 054/108] Persist lifetime commissioning lease budgets on PostgreSQL --- .../fixtures/gateway/production-codes.json | 104 ++++ .../qualification/schema-vectors.json | 24 +- .../qualification/verification-vectors.json | 94 ++-- compliance.toml | 23 +- ...d-qualification-commissioning-authority.md | 33 +- .../GATEWAY_TRUST_AND_GIT_SIGNING_RUNBOOK.md | 2 +- ...ime-custody-observability-and-assurance.md | 2 +- docs/specs/0063-generalized-gateway.md | 4 +- ...gateway-polish-and-recipe-qualification.md | 2 +- .../qualification/aeneas/source-closure.json | 4 +- .../src/vectors/mod.rs | 2 +- .../auths-gateway/semantic-closure.json | 2 +- .../auths-gateway/src/commissioning_budget.rs | 397 +++++++++++++++ .../src/commissioning_budget/tests.rs | 451 ++++++++++++++++++ product/runtime/auths-gateway/src/lib.rs | 1 + .../src/pending_vectors/production.rs | 13 + .../auths-gateway/src/qualification.rs | 2 +- .../auths-gateway/src/semantic_closure.rs | 2 +- product/runtime/auths-gateway/src/store.rs | 9 +- ...cycle_v5.sql => postgres_lifecycle_v6.sql} | 6 +- .../auths-stores/src/gateway_attempt.rs | 24 +- product/stores/auths-stores/src/lifecycle.rs | 8 +- release/semantic-freeze-versions.toml | 12 +- release/semantic-freeze.json | 24 +- xtask/src/semantic_freeze.rs | 2 +- 25 files changed, 1135 insertions(+), 112 deletions(-) create mode 100644 product/runtime/auths-gateway/src/commissioning_budget.rs create mode 100644 product/runtime/auths-gateway/src/commissioning_budget/tests.rs rename product/stores/auths-stores/migrations/{postgres_lifecycle_v5.sql => postgres_lifecycle_v6.sql} (93%) diff --git a/bindings/fixtures/gateway/production-codes.json b/bindings/fixtures/gateway/production-codes.json index 41c40edaf..2933726c8 100644 --- a/bindings/fixtures/gateway/production-codes.json +++ b/bindings/fixtures/gateway/production-codes.json @@ -20,6 +20,110 @@ "id": "lease-never-precedes-claim" } }, + { + "code": "gateway.commissioning.binding-mismatch", + "owner": "commissioning-budget", + "stage": "before-custody", + "status": "implemented", + "epic": 5, + "case": null + }, + { + "code": "gateway.commissioning.clock-untrusted", + "owner": "commissioning-budget", + "stage": "before-custody", + "status": "implemented", + "epic": 5, + "case": null + }, + { + "code": "gateway.commissioning.contention", + "owner": "commissioning-budget", + "stage": "before-custody", + "status": "implemented", + "epic": 5, + "case": null + }, + { + "code": "gateway.commissioning.exhausted", + "owner": "commissioning-budget", + "stage": "before-custody", + "status": "implemented", + "epic": 5, + "case": null + }, + { + "code": "gateway.commissioning.expired", + "owner": "commissioning-budget", + "stage": "before-custody", + "status": "implemented", + "epic": 5, + "case": null + }, + { + "code": "gateway.commissioning.registration-missing", + "owner": "commissioning-budget", + "stage": "before-custody", + "status": "implemented", + "epic": 5, + "case": null + }, + { + "code": "gateway.commissioning.restore-rollback", + "owner": "commissioning-budget", + "stage": "before-custody", + "status": "implemented", + "epic": 5, + "case": null + }, + { + "code": "gateway.commissioning.revocation-rollback", + "owner": "commissioning-budget", + "stage": "before-custody", + "status": "implemented", + "epic": 5, + "case": null + }, + { + "code": "gateway.commissioning.revocation-stale", + "owner": "commissioning-budget", + "stage": "before-custody", + "status": "implemented", + "epic": 5, + "case": null + }, + { + "code": "gateway.commissioning.revoked", + "owner": "commissioning-budget", + "stage": "before-custody", + "status": "implemented", + "epic": 5, + "case": null + }, + { + "code": "gateway.commissioning.state-corrupt", + "owner": "commissioning-budget", + "stage": "before-custody", + "status": "implemented", + "epic": 5, + "case": null + }, + { + "code": "gateway.commissioning.store-unavailable", + "owner": "commissioning-budget", + "stage": "before-custody", + "status": "implemented", + "epic": 5, + "case": null + }, + { + "code": "gateway.commissioning.unavailable", + "owner": "commissioning-budget", + "stage": "before-custody", + "status": "implemented", + "epic": 5, + "case": null + }, { "code": "gateway.connection.credential-generation-missing", "owner": "engine", diff --git a/bindings/fixtures/qualification/schema-vectors.json b/bindings/fixtures/qualification/schema-vectors.json index ebf79327e..f8db5468e 100644 --- a/bindings/fixtures/qualification/schema-vectors.json +++ b/bindings/fixtures/qualification/schema-vectors.json @@ -23,9 +23,9 @@ "trust_root": "{\"public_key_b64\":\"0EqyMnQrtKs6E2i9RhXk5tAiSrcaAWuvhSCjMsl3hzc\",\"root_id\":\"auths-qualification-root-1\",\"schema\":\"auths.qualification-trust-root/1\",\"signature_suite\":\"ed25519-v1\"}", "signer_certificate": "{\"root_signature_b64\":\"obGs_sPHvOXfTu8emdHu3odSbdq3PEW0XwoKhrOSb1LQTgq9LOvFPrRcuhE6Tis01Ac9ndvtGQiey6UWh0MmBg\",\"statement\":{\"issued_at\":1789913600,\"not_after\":1805465600,\"not_before\":1789913600,\"permitted_artifact_kinds\":[\"qualification-release-index\",\"recipe-qualification-attestation\"],\"public_key_b64\":\"oJql9HpnWYAv-VX43C0qFKXJnSO-l_hkEn_5ODRVpPA\",\"root_id\":\"auths-qualification-root-1\",\"schema\":\"auths.qualification-signer-certificate/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"release-signer-2026-10\",\"signer_kind\":\"protected-software-release-key-v1\"}}", "revocation_list": "{\"root_signature_b64\":\"nVaEVMHFGD_kiB0SIdz3uK3Xh0YlYrUJY-PRkV7_sCAc6mGs39yQxxGsiShFyuVrE_NxGHNnX40Lg6mi_w_hAw\",\"statement\":{\"issued_at\":1789996400,\"next_update\":1790255600,\"revoked_qualifications\":[],\"revoked_signers\":[],\"root_id\":\"auths-qualification-root-1\",\"schema\":\"auths.qualification-revocation-list/1\",\"sequence\":7}}", - "release_index": "{\"signature_b64\":\"QMMwlBk-GT36P5vZFGmqwVaI6dSlhiDIy6b69926s_4UkaNLW8VDkrCtAQtedDPG_B7Mwa7vteWiAtHHGJSuCQ\",\"statement\":{\"entries\":[{\"attestation_sha256\":\"70d270e747fcf8bca9f408758ddcc1cd4470bd0dc8fa675ea68ce960146c8bbd\",\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"record_sha256\":\"d7a00ddda1c3b7afa99bb997fd9d88f864937a104e1b8cdd4370ebb914c6d306\"}],\"issued_at\":1789996400,\"schema\":\"auths.qualification-release-index/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"release-signer-2026-10\"}}", - "record": "{\"capabilities\":[{\"capability\":\"credential-guard\",\"result\":\"exercised\"},{\"capability\":\"version-pin\",\"result\":\"exercised\"},{\"capability\":\"account-binding\",\"reason\":\"the qualified recipe and target declare none\",\"result\":\"not-applicable\"},{\"capability\":\"denied-reads\",\"result\":\"exercised\"},{\"capability\":\"ceiling\",\"result\":\"exercised\"},{\"capability\":\"budget\",\"result\":\"exercised\"},{\"capability\":\"idempotency\",\"result\":\"exercised\"},{\"capability\":\"response-locator\",\"result\":\"exercised\"},{\"capability\":\"echo\",\"result\":\"exercised\"},{\"capability\":\"observation\",\"result\":\"exercised\"},{\"capability\":\"recovery\",\"result\":\"exercised\"},{\"capability\":\"observer-rotation\",\"reason\":\"the qualified recipe and target declare none\",\"result\":\"not-applicable\"}],\"corpus_manifest_sha256\":\"d6c1cad9a6b0fe0fc27d1f8107c2381e8b9ab1bbfc04a47aa8234140de74a23f\",\"custody_descriptor\":\"aws-secrets-manager-v1 with workload identity\",\"evidence\":[{\"cases\":12,\"evidence_sha256\":\"c3a2a799eb04b1ee53a22495e0d95171a9f42f2ad557b639f3fe5440bbed90e7\",\"member\":\"conformance\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"dfd5b5dccc73cae91abec7a76c332dae145eb37eddb18f56dca2e68f2dbc81ab\",\"member\":\"differential\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"a05d5182b4f20eb67c0d95622a70f1e4ac87d1d1b8b7fab219a2276b6da41256\",\"member\":\"hostile\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"00beb3d9e44f8d20d5da8861818ecd7b430714f959a6613dbd2d870997eb90f8\",\"member\":\"live\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"3a4e01d7b8d11480e334d0d2fffc2efeeaf2363d21f9107094c3cfc3c063b362\",\"member\":\"recovery\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"6b428d653e06c75268e2e33f234f30f9cc24616c42faf551699f7a7ac2376011\",\"member\":\"rotation\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"e8713a54bfb187836d4db2f34f181129f2e03f7221bc2d3247134470adcacee8\",\"member\":\"restart\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"8824a7669543ecf652b651fa2d370c548e09b73c1babac841cd689389a1fdcbe\",\"member\":\"multi-instance\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"f31f29dc30a4e8ccd3aea69c012656c2811ac194881147b2cced5dd7dc1a7d9b\",\"member\":\"redaction\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"8e91fde286bdbb80e6d6245e7ab9dab68f92e790922170195fc80aab2eeb227b\",\"member\":\"installed-consumer\",\"result\":\"passed\",\"unauthorized_provider_entries\":0}],\"excluded_claims\":[\"the provider performed or settled the business effect\"],\"generated_artifacts_sha256\":\"fff3ece48e4f5271825e80b355a1243a4c30619329bbbc70bc4e5c1b242973e2\",\"installed_packages\":[{\"name\":\"auths-gateway\",\"sha256\":\"8a58d99c69c098e53c2197df2c6a6a16b131c69798f728db134c978f77e95360\",\"version\":\"1.0.0-rc.1\"},{\"name\":\"auths-python\",\"sha256\":\"59b028e3e66e681bfa195fb6afee775b91f30fc418f05f86353bc71cd021d2f9\",\"version\":\"1.0.0rc1\"}],\"live_effects\":{\"confirmed_by_read_back\":4,\"entered\":4},\"not_after\":1797768800,\"not_before\":1789992800,\"provenance\":{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"environment\":\"recipe-qualification\",\"repository\":\"github.com/auths-dev/auths-proof\",\"workflow\":\".github/workflows/recipe-qualification.yml\"},\"provider_kind\":\"example-payments\",\"provider_resources\":[\"refund:fixture-0001\",\"refund:fixture-0002\"],\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"recipe_decision_record_sha256\":\"0c2328dfcdc21fcd917fd242dd16f9adf1354395a472e589e2778dee99527081\",\"residual_assumptions\":[\"the provider keeps its test mode separate from live data\"],\"schema\":\"auths.recipe-qualification/1\",\"source_closure_sha256\":\"00023b3a6fbf90b531085365646cda2ffcac182f6eaedf453eb680b63ae33106\",\"store_descriptor\":\"postgresql 16 with TLS\",\"tuple\":{\"compiled_recipe_sha256\":\"262f5ef11b349645f2421c533220fc6bbfd70c4a5395f5d65c601406eba7d4ef\",\"gateway_semantic_closure_sha256\":\"01ec13346b098e4f5e1c64a995a50ce15ef339dc1f304966a45c94e80638203b\",\"profile_lock_sha256\":\"4dd8982feedb83403f985de3e1a952a90060e44035ab797e5313ff93957a22d5\",\"provider_contract_id\":\"f15f154a38de58de1b27c70c61a6b20fe532746e2e4462576dbd3d27d76cce3d\",\"recipe_family\":\"example-refund-v1\",\"target\":{\"arch\":\"x86_64\",\"credential_store_kind\":\"aws-secrets-manager-v1\",\"gateway_build_sha256\":\"42194bc83fbd821aaede008519091b4516baf914f8c2e27f3f2ac7a25f7485c3\",\"gateway_package\":\"auths-gateway\",\"gateway_version\":\"1.0.0-rc.1\",\"os\":\"linux\",\"store_kind\":\"postgresql-v1\",\"store_schema\":\"auths.lifecycle.postgresql/5\"}}}", - "attestation": "{\"signature_b64\":\"oR2QsmEvCp-fGvV0ysEM-a3opOp6SlgJzb63U4ESuZz0yRPlyoOK39PhRELjaiaMzpiRyj-LVUmnKkd3pvFNAQ\",\"statement\":{\"issued_at\":1789992800,\"not_after\":1797768800,\"not_before\":1789992800,\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"record_sha256\":\"d7a00ddda1c3b7afa99bb997fd9d88f864937a104e1b8cdd4370ebb914c6d306\",\"schema\":\"auths.recipe-qualification-attestation/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"release-signer-2026-10\"}}", + "release_index": "{\"signature_b64\":\"qLnnKRCjNPMQ4E4htzwihMF_RcLGUtZ-QpmUc0xvAf9So4UwLqsqnQ8iE7KQDBPiDDEaT2tXMdXo8UJx7BKoCw\",\"statement\":{\"entries\":[{\"attestation_sha256\":\"00449fd858186bb6711b8697f6ea376b5c6a99ef79e0443c6ccc23a1a36e8c82\",\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"record_sha256\":\"e5495a2c95356229a778d6781860eed872090ac5f4b6ac447953d353a3592f7a\"}],\"issued_at\":1789996400,\"schema\":\"auths.qualification-release-index/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"release-signer-2026-10\"}}", + "record": "{\"capabilities\":[{\"capability\":\"credential-guard\",\"result\":\"exercised\"},{\"capability\":\"version-pin\",\"result\":\"exercised\"},{\"capability\":\"account-binding\",\"reason\":\"the qualified recipe and target declare none\",\"result\":\"not-applicable\"},{\"capability\":\"denied-reads\",\"result\":\"exercised\"},{\"capability\":\"ceiling\",\"result\":\"exercised\"},{\"capability\":\"budget\",\"result\":\"exercised\"},{\"capability\":\"idempotency\",\"result\":\"exercised\"},{\"capability\":\"response-locator\",\"result\":\"exercised\"},{\"capability\":\"echo\",\"result\":\"exercised\"},{\"capability\":\"observation\",\"result\":\"exercised\"},{\"capability\":\"recovery\",\"result\":\"exercised\"},{\"capability\":\"observer-rotation\",\"reason\":\"the qualified recipe and target declare none\",\"result\":\"not-applicable\"}],\"corpus_manifest_sha256\":\"d6c1cad9a6b0fe0fc27d1f8107c2381e8b9ab1bbfc04a47aa8234140de74a23f\",\"custody_descriptor\":\"aws-secrets-manager-v1 with workload identity\",\"evidence\":[{\"cases\":12,\"evidence_sha256\":\"c3a2a799eb04b1ee53a22495e0d95171a9f42f2ad557b639f3fe5440bbed90e7\",\"member\":\"conformance\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"dfd5b5dccc73cae91abec7a76c332dae145eb37eddb18f56dca2e68f2dbc81ab\",\"member\":\"differential\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"a05d5182b4f20eb67c0d95622a70f1e4ac87d1d1b8b7fab219a2276b6da41256\",\"member\":\"hostile\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"00beb3d9e44f8d20d5da8861818ecd7b430714f959a6613dbd2d870997eb90f8\",\"member\":\"live\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"3a4e01d7b8d11480e334d0d2fffc2efeeaf2363d21f9107094c3cfc3c063b362\",\"member\":\"recovery\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"6b428d653e06c75268e2e33f234f30f9cc24616c42faf551699f7a7ac2376011\",\"member\":\"rotation\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"e8713a54bfb187836d4db2f34f181129f2e03f7221bc2d3247134470adcacee8\",\"member\":\"restart\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"8824a7669543ecf652b651fa2d370c548e09b73c1babac841cd689389a1fdcbe\",\"member\":\"multi-instance\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"f31f29dc30a4e8ccd3aea69c012656c2811ac194881147b2cced5dd7dc1a7d9b\",\"member\":\"redaction\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"8e91fde286bdbb80e6d6245e7ab9dab68f92e790922170195fc80aab2eeb227b\",\"member\":\"installed-consumer\",\"result\":\"passed\",\"unauthorized_provider_entries\":0}],\"excluded_claims\":[\"the provider performed or settled the business effect\"],\"generated_artifacts_sha256\":\"fff3ece48e4f5271825e80b355a1243a4c30619329bbbc70bc4e5c1b242973e2\",\"installed_packages\":[{\"name\":\"auths-gateway\",\"sha256\":\"8a58d99c69c098e53c2197df2c6a6a16b131c69798f728db134c978f77e95360\",\"version\":\"1.0.0-rc.1\"},{\"name\":\"auths-python\",\"sha256\":\"59b028e3e66e681bfa195fb6afee775b91f30fc418f05f86353bc71cd021d2f9\",\"version\":\"1.0.0rc1\"}],\"live_effects\":{\"confirmed_by_read_back\":4,\"entered\":4},\"not_after\":1797768800,\"not_before\":1789992800,\"provenance\":{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"environment\":\"recipe-qualification\",\"repository\":\"github.com/auths-dev/auths-proof\",\"workflow\":\".github/workflows/recipe-qualification.yml\"},\"provider_kind\":\"example-payments\",\"provider_resources\":[\"refund:fixture-0001\",\"refund:fixture-0002\"],\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"recipe_decision_record_sha256\":\"0c2328dfcdc21fcd917fd242dd16f9adf1354395a472e589e2778dee99527081\",\"residual_assumptions\":[\"the provider keeps its test mode separate from live data\"],\"schema\":\"auths.recipe-qualification/1\",\"source_closure_sha256\":\"00023b3a6fbf90b531085365646cda2ffcac182f6eaedf453eb680b63ae33106\",\"store_descriptor\":\"postgresql 16 with TLS\",\"tuple\":{\"compiled_recipe_sha256\":\"262f5ef11b349645f2421c533220fc6bbfd70c4a5395f5d65c601406eba7d4ef\",\"gateway_semantic_closure_sha256\":\"01ec13346b098e4f5e1c64a995a50ce15ef339dc1f304966a45c94e80638203b\",\"profile_lock_sha256\":\"4dd8982feedb83403f985de3e1a952a90060e44035ab797e5313ff93957a22d5\",\"provider_contract_id\":\"f15f154a38de58de1b27c70c61a6b20fe532746e2e4462576dbd3d27d76cce3d\",\"recipe_family\":\"example-refund-v1\",\"target\":{\"arch\":\"x86_64\",\"credential_store_kind\":\"aws-secrets-manager-v1\",\"gateway_build_sha256\":\"42194bc83fbd821aaede008519091b4516baf914f8c2e27f3f2ac7a25f7485c3\",\"gateway_package\":\"auths-gateway\",\"gateway_version\":\"1.0.0-rc.1\",\"os\":\"linux\",\"store_kind\":\"postgresql-v1\",\"store_schema\":\"auths.lifecycle.postgresql/6\"}}}", + "attestation": "{\"signature_b64\":\"RNvz-GVoozTJulLOMogzaDjwNMmNJIciII7dGyYiqv7CLXqD7OeqqnmO4COD_-YI7CtUTuT50ARNLDOYx6HOAw\",\"statement\":{\"issued_at\":1789992800,\"not_after\":1797768800,\"not_before\":1789992800,\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"record_sha256\":\"e5495a2c95356229a778d6781860eed872090ac5f4b6ac447953d353a3592f7a\",\"schema\":\"auths.recipe-qualification-attestation/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"release-signer-2026-10\"}}", "provider_contract": "{\"api_release\":\"2026-09-01.fixture\",\"corpus_manifest_sha256\":\"d6c1cad9a6b0fe0fc27d1f8107c2381e8b9ab1bbfc04a47aa8234140de74a23f\",\"declarations\":{\"idempotency_sha256\":\"d6ee51b4b1b7adbf404892f9326dd33a8d42047c0d7592aa8366ad4fcf99a300\",\"observation_sha256\":\"41eecb260924ac4b305313888b59325a24161b0c9d60ecda92ab26bc10e3fbf5\",\"recovery_sha256\":\"871f9dded4942ff0262f147ca7fd4992b38da2741bac401abf3cd8dc43d4d2d3\",\"retention_sha256\":\"5e783fc5c0cf8950b44fd3095ff0679df34660600d0e7a59cedb2084e850aec7\"},\"environment_class\":\"provider-test-mode\",\"manual_assumptions\":[\"a refund of a refunded payment is rejected, not repeated\",\"the idempotency key is honored for at least 24 hours\"],\"openapi_slice_sha256\":\"b11c8865e81ede17d33a255a677549fa87ba045c67077495b8749fc5455c0b2f\",\"oracle_version\":\"oracle-1\",\"provider\":\"example-payments\",\"schema\":\"auths.provider-contract/1\"}" }, "provider_contract_id": "f15f154a38de58de1b27c70c61a6b20fe532746e2e4462576dbd3d27d76cce3d", @@ -511,21 +511,21 @@ "artifact": "record", "class": "non-canonical", "reason": "non-canonical", - "text": "{\"capabilities\":[{\"capability\":\"credential-guard\",\"result\":\"exercised\"},{\"capability\":\"version-pin\",\"result\":\"exercised\"},{\"capability\":\"account-binding\",\"reason\":\"the qualified recipe and target declare none\",\"result\":\"not-applicable\"},{\"capability\":\"denied-reads\",\"result\":\"exercised\"},{\"capability\":\"ceiling\",\"result\":\"exercised\"},{\"capability\":\"budget\",\"result\":\"exercised\"},{\"capability\":\"idempotency\",\"result\":\"exercised\"},{\"capability\":\"response-locator\",\"result\":\"exercised\"},{\"capability\":\"echo\",\"result\":\"exercised\"},{\"capability\":\"observation\",\"result\":\"exercised\"},{\"capability\":\"recovery\",\"result\":\"exercised\"},{\"capability\":\"observer-rotation\",\"reason\":\"the qualified recipe and target declare none\",\"result\":\"not-applicable\"}],\"corpus_manifest_sha256\":\"d6c1cad9a6b0fe0fc27d1f8107c2381e8b9ab1bbfc04a47aa8234140de74a23f\",\"custody_descriptor\":\"aws-secrets-manager-v1 with workload identity\",\"evidence\":[{\"cases\":12,\"evidence_sha256\":\"c3a2a799eb04b1ee53a22495e0d95171a9f42f2ad557b639f3fe5440bbed90e7\",\"member\":\"conformance\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"dfd5b5dccc73cae91abec7a76c332dae145eb37eddb18f56dca2e68f2dbc81ab\",\"member\":\"differential\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"a05d5182b4f20eb67c0d95622a70f1e4ac87d1d1b8b7fab219a2276b6da41256\",\"member\":\"hostile\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"00beb3d9e44f8d20d5da8861818ecd7b430714f959a6613dbd2d870997eb90f8\",\"member\":\"live\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"3a4e01d7b8d11480e334d0d2fffc2efeeaf2363d21f9107094c3cfc3c063b362\",\"member\":\"recovery\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"6b428d653e06c75268e2e33f234f30f9cc24616c42faf551699f7a7ac2376011\",\"member\":\"rotation\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"e8713a54bfb187836d4db2f34f181129f2e03f7221bc2d3247134470adcacee8\",\"member\":\"restart\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"8824a7669543ecf652b651fa2d370c548e09b73c1babac841cd689389a1fdcbe\",\"member\":\"multi-instance\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"f31f29dc30a4e8ccd3aea69c012656c2811ac194881147b2cced5dd7dc1a7d9b\",\"member\":\"redaction\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"8e91fde286bdbb80e6d6245e7ab9dab68f92e790922170195fc80aab2eeb227b\",\"member\":\"installed-consumer\",\"result\":\"passed\",\"unauthorized_provider_entries\":0}],\"excluded_claims\":[\"the provider performed or settled the business effect\"],\"generated_artifacts_sha256\":\"fff3ece48e4f5271825e80b355a1243a4c30619329bbbc70bc4e5c1b242973e2\",\"installed_packages\":[{\"name\":\"auths-gateway\",\"sha256\":\"8a58d99c69c098e53c2197df2c6a6a16b131c69798f728db134c978f77e95360\",\"version\":\"1.0.0-rc.1\"},{\"name\":\"auths-python\",\"sha256\":\"59b028e3e66e681bfa195fb6afee775b91f30fc418f05f86353bc71cd021d2f9\",\"version\":\"1.0.0rc1\"}],\"live_effects\":{\"confirmed_by_read_back\":4,\"entered\":4},\"not_after\":1797768800,\"not_before\":1789992800,\"provenance\":{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"environment\":\"recipe-qualification\",\"repository\":\"github.com/auths-dev/auths-proof\",\"workflow\":\".github/workflows/recipe-qualification.yml\"},\"provider_kind\":\"example-payments\",\"provider_resources\":[\"refund:fixture-0001\",\"refund:fixture-0002\"],\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"recipe_decision_record_sha256\":\"0c2328dfcdc21fcd917fd242dd16f9adf1354395a472e589e2778dee99527081\",\"residual_assumptions\":[\"the provider keeps its test mode separate from live data\"],\"schema\":\"auths.recipe-qualification/1\",\"source_closure_sha256\":\"00023b3a6fbf90b531085365646cda2ffcac182f6eaedf453eb680b63ae33106\",\"store_descriptor\":\"postgresql 16 with TLS\",\"tuple\":{\"compiled_recipe_sha256\":\"262f5ef11b349645f2421c533220fc6bbfd70c4a5395f5d65c601406eba7d4ef\",\"gateway_semantic_closure_sha256\":\"01ec13346b098e4f5e1c64a995a50ce15ef339dc1f304966a45c94e80638203b\",\"profile_lock_sha256\":\"4dd8982feedb83403f985de3e1a952a90060e44035ab797e5313ff93957a22d5\",\"provider_contract_id\":\"f15f154a38de58de1b27c70c61a6b20fe532746e2e4462576dbd3d27d76cce3d\",\"recipe_family\":\"example-refund-v1\",\"target\":{\"arch\":\"x86_64\",\"credential_store_kind\":\"aws-secrets-manager-v1\",\"gateway_build_sha256\":\"42194bc83fbd821aaede008519091b4516baf914f8c2e27f3f2ac7a25f7485c3\",\"gateway_package\":\"auths-gateway\",\"gateway_version\":\"1.0.0-rc.1\",\"os\":\"linux\",\"store_kind\":\"postgresql-v1\",\"store_schema\":\"auths.lifecycle.postgresql/5\"}}}\n" + "text": "{\"capabilities\":[{\"capability\":\"credential-guard\",\"result\":\"exercised\"},{\"capability\":\"version-pin\",\"result\":\"exercised\"},{\"capability\":\"account-binding\",\"reason\":\"the qualified recipe and target declare none\",\"result\":\"not-applicable\"},{\"capability\":\"denied-reads\",\"result\":\"exercised\"},{\"capability\":\"ceiling\",\"result\":\"exercised\"},{\"capability\":\"budget\",\"result\":\"exercised\"},{\"capability\":\"idempotency\",\"result\":\"exercised\"},{\"capability\":\"response-locator\",\"result\":\"exercised\"},{\"capability\":\"echo\",\"result\":\"exercised\"},{\"capability\":\"observation\",\"result\":\"exercised\"},{\"capability\":\"recovery\",\"result\":\"exercised\"},{\"capability\":\"observer-rotation\",\"reason\":\"the qualified recipe and target declare none\",\"result\":\"not-applicable\"}],\"corpus_manifest_sha256\":\"d6c1cad9a6b0fe0fc27d1f8107c2381e8b9ab1bbfc04a47aa8234140de74a23f\",\"custody_descriptor\":\"aws-secrets-manager-v1 with workload identity\",\"evidence\":[{\"cases\":12,\"evidence_sha256\":\"c3a2a799eb04b1ee53a22495e0d95171a9f42f2ad557b639f3fe5440bbed90e7\",\"member\":\"conformance\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"dfd5b5dccc73cae91abec7a76c332dae145eb37eddb18f56dca2e68f2dbc81ab\",\"member\":\"differential\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"a05d5182b4f20eb67c0d95622a70f1e4ac87d1d1b8b7fab219a2276b6da41256\",\"member\":\"hostile\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"00beb3d9e44f8d20d5da8861818ecd7b430714f959a6613dbd2d870997eb90f8\",\"member\":\"live\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"3a4e01d7b8d11480e334d0d2fffc2efeeaf2363d21f9107094c3cfc3c063b362\",\"member\":\"recovery\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"6b428d653e06c75268e2e33f234f30f9cc24616c42faf551699f7a7ac2376011\",\"member\":\"rotation\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"e8713a54bfb187836d4db2f34f181129f2e03f7221bc2d3247134470adcacee8\",\"member\":\"restart\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"8824a7669543ecf652b651fa2d370c548e09b73c1babac841cd689389a1fdcbe\",\"member\":\"multi-instance\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"f31f29dc30a4e8ccd3aea69c012656c2811ac194881147b2cced5dd7dc1a7d9b\",\"member\":\"redaction\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"8e91fde286bdbb80e6d6245e7ab9dab68f92e790922170195fc80aab2eeb227b\",\"member\":\"installed-consumer\",\"result\":\"passed\",\"unauthorized_provider_entries\":0}],\"excluded_claims\":[\"the provider performed or settled the business effect\"],\"generated_artifacts_sha256\":\"fff3ece48e4f5271825e80b355a1243a4c30619329bbbc70bc4e5c1b242973e2\",\"installed_packages\":[{\"name\":\"auths-gateway\",\"sha256\":\"8a58d99c69c098e53c2197df2c6a6a16b131c69798f728db134c978f77e95360\",\"version\":\"1.0.0-rc.1\"},{\"name\":\"auths-python\",\"sha256\":\"59b028e3e66e681bfa195fb6afee775b91f30fc418f05f86353bc71cd021d2f9\",\"version\":\"1.0.0rc1\"}],\"live_effects\":{\"confirmed_by_read_back\":4,\"entered\":4},\"not_after\":1797768800,\"not_before\":1789992800,\"provenance\":{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"environment\":\"recipe-qualification\",\"repository\":\"github.com/auths-dev/auths-proof\",\"workflow\":\".github/workflows/recipe-qualification.yml\"},\"provider_kind\":\"example-payments\",\"provider_resources\":[\"refund:fixture-0001\",\"refund:fixture-0002\"],\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"recipe_decision_record_sha256\":\"0c2328dfcdc21fcd917fd242dd16f9adf1354395a472e589e2778dee99527081\",\"residual_assumptions\":[\"the provider keeps its test mode separate from live data\"],\"schema\":\"auths.recipe-qualification/1\",\"source_closure_sha256\":\"00023b3a6fbf90b531085365646cda2ffcac182f6eaedf453eb680b63ae33106\",\"store_descriptor\":\"postgresql 16 with TLS\",\"tuple\":{\"compiled_recipe_sha256\":\"262f5ef11b349645f2421c533220fc6bbfd70c4a5395f5d65c601406eba7d4ef\",\"gateway_semantic_closure_sha256\":\"01ec13346b098e4f5e1c64a995a50ce15ef339dc1f304966a45c94e80638203b\",\"profile_lock_sha256\":\"4dd8982feedb83403f985de3e1a952a90060e44035ab797e5313ff93957a22d5\",\"provider_contract_id\":\"f15f154a38de58de1b27c70c61a6b20fe532746e2e4462576dbd3d27d76cce3d\",\"recipe_family\":\"example-refund-v1\",\"target\":{\"arch\":\"x86_64\",\"credential_store_kind\":\"aws-secrets-manager-v1\",\"gateway_build_sha256\":\"42194bc83fbd821aaede008519091b4516baf914f8c2e27f3f2ac7a25f7485c3\",\"gateway_package\":\"auths-gateway\",\"gateway_version\":\"1.0.0-rc.1\",\"os\":\"linux\",\"store_kind\":\"postgresql-v1\",\"store_schema\":\"auths.lifecycle.postgresql/6\"}}}\n" }, { "id": "record-exponent-time", "artifact": "record", "class": "non-canonical", "reason": "malformed", - "text": "{\"capabilities\":[{\"capability\":\"credential-guard\",\"result\":\"exercised\"},{\"capability\":\"version-pin\",\"result\":\"exercised\"},{\"capability\":\"account-binding\",\"reason\":\"the qualified recipe and target declare none\",\"result\":\"not-applicable\"},{\"capability\":\"denied-reads\",\"result\":\"exercised\"},{\"capability\":\"ceiling\",\"result\":\"exercised\"},{\"capability\":\"budget\",\"result\":\"exercised\"},{\"capability\":\"idempotency\",\"result\":\"exercised\"},{\"capability\":\"response-locator\",\"result\":\"exercised\"},{\"capability\":\"echo\",\"result\":\"exercised\"},{\"capability\":\"observation\",\"result\":\"exercised\"},{\"capability\":\"recovery\",\"result\":\"exercised\"},{\"capability\":\"observer-rotation\",\"reason\":\"the qualified recipe and target declare none\",\"result\":\"not-applicable\"}],\"corpus_manifest_sha256\":\"d6c1cad9a6b0fe0fc27d1f8107c2381e8b9ab1bbfc04a47aa8234140de74a23f\",\"custody_descriptor\":\"aws-secrets-manager-v1 with workload identity\",\"evidence\":[{\"cases\":12,\"evidence_sha256\":\"c3a2a799eb04b1ee53a22495e0d95171a9f42f2ad557b639f3fe5440bbed90e7\",\"member\":\"conformance\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"dfd5b5dccc73cae91abec7a76c332dae145eb37eddb18f56dca2e68f2dbc81ab\",\"member\":\"differential\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"a05d5182b4f20eb67c0d95622a70f1e4ac87d1d1b8b7fab219a2276b6da41256\",\"member\":\"hostile\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"00beb3d9e44f8d20d5da8861818ecd7b430714f959a6613dbd2d870997eb90f8\",\"member\":\"live\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"3a4e01d7b8d11480e334d0d2fffc2efeeaf2363d21f9107094c3cfc3c063b362\",\"member\":\"recovery\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"6b428d653e06c75268e2e33f234f30f9cc24616c42faf551699f7a7ac2376011\",\"member\":\"rotation\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"e8713a54bfb187836d4db2f34f181129f2e03f7221bc2d3247134470adcacee8\",\"member\":\"restart\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"8824a7669543ecf652b651fa2d370c548e09b73c1babac841cd689389a1fdcbe\",\"member\":\"multi-instance\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"f31f29dc30a4e8ccd3aea69c012656c2811ac194881147b2cced5dd7dc1a7d9b\",\"member\":\"redaction\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"8e91fde286bdbb80e6d6245e7ab9dab68f92e790922170195fc80aab2eeb227b\",\"member\":\"installed-consumer\",\"result\":\"passed\",\"unauthorized_provider_entries\":0}],\"excluded_claims\":[\"the provider performed or settled the business effect\"],\"generated_artifacts_sha256\":\"fff3ece48e4f5271825e80b355a1243a4c30619329bbbc70bc4e5c1b242973e2\",\"installed_packages\":[{\"name\":\"auths-gateway\",\"sha256\":\"8a58d99c69c098e53c2197df2c6a6a16b131c69798f728db134c978f77e95360\",\"version\":\"1.0.0-rc.1\"},{\"name\":\"auths-python\",\"sha256\":\"59b028e3e66e681bfa195fb6afee775b91f30fc418f05f86353bc71cd021d2f9\",\"version\":\"1.0.0rc1\"}],\"live_effects\":{\"confirmed_by_read_back\":4,\"entered\":4},\"not_after\":1797768800,\"not_before\":1.7899928e9,\"provenance\":{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"environment\":\"recipe-qualification\",\"repository\":\"github.com/auths-dev/auths-proof\",\"workflow\":\".github/workflows/recipe-qualification.yml\"},\"provider_kind\":\"example-payments\",\"provider_resources\":[\"refund:fixture-0001\",\"refund:fixture-0002\"],\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"recipe_decision_record_sha256\":\"0c2328dfcdc21fcd917fd242dd16f9adf1354395a472e589e2778dee99527081\",\"residual_assumptions\":[\"the provider keeps its test mode separate from live data\"],\"schema\":\"auths.recipe-qualification/1\",\"source_closure_sha256\":\"00023b3a6fbf90b531085365646cda2ffcac182f6eaedf453eb680b63ae33106\",\"store_descriptor\":\"postgresql 16 with TLS\",\"tuple\":{\"compiled_recipe_sha256\":\"262f5ef11b349645f2421c533220fc6bbfd70c4a5395f5d65c601406eba7d4ef\",\"gateway_semantic_closure_sha256\":\"01ec13346b098e4f5e1c64a995a50ce15ef339dc1f304966a45c94e80638203b\",\"profile_lock_sha256\":\"4dd8982feedb83403f985de3e1a952a90060e44035ab797e5313ff93957a22d5\",\"provider_contract_id\":\"f15f154a38de58de1b27c70c61a6b20fe532746e2e4462576dbd3d27d76cce3d\",\"recipe_family\":\"example-refund-v1\",\"target\":{\"arch\":\"x86_64\",\"credential_store_kind\":\"aws-secrets-manager-v1\",\"gateway_build_sha256\":\"42194bc83fbd821aaede008519091b4516baf914f8c2e27f3f2ac7a25f7485c3\",\"gateway_package\":\"auths-gateway\",\"gateway_version\":\"1.0.0-rc.1\",\"os\":\"linux\",\"store_kind\":\"postgresql-v1\",\"store_schema\":\"auths.lifecycle.postgresql/5\"}}}" + "text": "{\"capabilities\":[{\"capability\":\"credential-guard\",\"result\":\"exercised\"},{\"capability\":\"version-pin\",\"result\":\"exercised\"},{\"capability\":\"account-binding\",\"reason\":\"the qualified recipe and target declare none\",\"result\":\"not-applicable\"},{\"capability\":\"denied-reads\",\"result\":\"exercised\"},{\"capability\":\"ceiling\",\"result\":\"exercised\"},{\"capability\":\"budget\",\"result\":\"exercised\"},{\"capability\":\"idempotency\",\"result\":\"exercised\"},{\"capability\":\"response-locator\",\"result\":\"exercised\"},{\"capability\":\"echo\",\"result\":\"exercised\"},{\"capability\":\"observation\",\"result\":\"exercised\"},{\"capability\":\"recovery\",\"result\":\"exercised\"},{\"capability\":\"observer-rotation\",\"reason\":\"the qualified recipe and target declare none\",\"result\":\"not-applicable\"}],\"corpus_manifest_sha256\":\"d6c1cad9a6b0fe0fc27d1f8107c2381e8b9ab1bbfc04a47aa8234140de74a23f\",\"custody_descriptor\":\"aws-secrets-manager-v1 with workload identity\",\"evidence\":[{\"cases\":12,\"evidence_sha256\":\"c3a2a799eb04b1ee53a22495e0d95171a9f42f2ad557b639f3fe5440bbed90e7\",\"member\":\"conformance\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"dfd5b5dccc73cae91abec7a76c332dae145eb37eddb18f56dca2e68f2dbc81ab\",\"member\":\"differential\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"a05d5182b4f20eb67c0d95622a70f1e4ac87d1d1b8b7fab219a2276b6da41256\",\"member\":\"hostile\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"00beb3d9e44f8d20d5da8861818ecd7b430714f959a6613dbd2d870997eb90f8\",\"member\":\"live\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"3a4e01d7b8d11480e334d0d2fffc2efeeaf2363d21f9107094c3cfc3c063b362\",\"member\":\"recovery\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"6b428d653e06c75268e2e33f234f30f9cc24616c42faf551699f7a7ac2376011\",\"member\":\"rotation\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"e8713a54bfb187836d4db2f34f181129f2e03f7221bc2d3247134470adcacee8\",\"member\":\"restart\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"8824a7669543ecf652b651fa2d370c548e09b73c1babac841cd689389a1fdcbe\",\"member\":\"multi-instance\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"f31f29dc30a4e8ccd3aea69c012656c2811ac194881147b2cced5dd7dc1a7d9b\",\"member\":\"redaction\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"8e91fde286bdbb80e6d6245e7ab9dab68f92e790922170195fc80aab2eeb227b\",\"member\":\"installed-consumer\",\"result\":\"passed\",\"unauthorized_provider_entries\":0}],\"excluded_claims\":[\"the provider performed or settled the business effect\"],\"generated_artifacts_sha256\":\"fff3ece48e4f5271825e80b355a1243a4c30619329bbbc70bc4e5c1b242973e2\",\"installed_packages\":[{\"name\":\"auths-gateway\",\"sha256\":\"8a58d99c69c098e53c2197df2c6a6a16b131c69798f728db134c978f77e95360\",\"version\":\"1.0.0-rc.1\"},{\"name\":\"auths-python\",\"sha256\":\"59b028e3e66e681bfa195fb6afee775b91f30fc418f05f86353bc71cd021d2f9\",\"version\":\"1.0.0rc1\"}],\"live_effects\":{\"confirmed_by_read_back\":4,\"entered\":4},\"not_after\":1797768800,\"not_before\":1.7899928e9,\"provenance\":{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"environment\":\"recipe-qualification\",\"repository\":\"github.com/auths-dev/auths-proof\",\"workflow\":\".github/workflows/recipe-qualification.yml\"},\"provider_kind\":\"example-payments\",\"provider_resources\":[\"refund:fixture-0001\",\"refund:fixture-0002\"],\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"recipe_decision_record_sha256\":\"0c2328dfcdc21fcd917fd242dd16f9adf1354395a472e589e2778dee99527081\",\"residual_assumptions\":[\"the provider keeps its test mode separate from live data\"],\"schema\":\"auths.recipe-qualification/1\",\"source_closure_sha256\":\"00023b3a6fbf90b531085365646cda2ffcac182f6eaedf453eb680b63ae33106\",\"store_descriptor\":\"postgresql 16 with TLS\",\"tuple\":{\"compiled_recipe_sha256\":\"262f5ef11b349645f2421c533220fc6bbfd70c4a5395f5d65c601406eba7d4ef\",\"gateway_semantic_closure_sha256\":\"01ec13346b098e4f5e1c64a995a50ce15ef339dc1f304966a45c94e80638203b\",\"profile_lock_sha256\":\"4dd8982feedb83403f985de3e1a952a90060e44035ab797e5313ff93957a22d5\",\"provider_contract_id\":\"f15f154a38de58de1b27c70c61a6b20fe532746e2e4462576dbd3d27d76cce3d\",\"recipe_family\":\"example-refund-v1\",\"target\":{\"arch\":\"x86_64\",\"credential_store_kind\":\"aws-secrets-manager-v1\",\"gateway_build_sha256\":\"42194bc83fbd821aaede008519091b4516baf914f8c2e27f3f2ac7a25f7485c3\",\"gateway_package\":\"auths-gateway\",\"gateway_version\":\"1.0.0-rc.1\",\"os\":\"linux\",\"store_kind\":\"postgresql-v1\",\"store_schema\":\"auths.lifecycle.postgresql/6\"}}}" }, { "id": "record-repeated-member", "artifact": "record", "class": "non-canonical", "reason": "malformed", - "text": "{\"schema\":\"auths.recipe-qualification/1\",\"capabilities\":[{\"capability\":\"credential-guard\",\"result\":\"exercised\"},{\"capability\":\"version-pin\",\"result\":\"exercised\"},{\"capability\":\"account-binding\",\"reason\":\"the qualified recipe and target declare none\",\"result\":\"not-applicable\"},{\"capability\":\"denied-reads\",\"result\":\"exercised\"},{\"capability\":\"ceiling\",\"result\":\"exercised\"},{\"capability\":\"budget\",\"result\":\"exercised\"},{\"capability\":\"idempotency\",\"result\":\"exercised\"},{\"capability\":\"response-locator\",\"result\":\"exercised\"},{\"capability\":\"echo\",\"result\":\"exercised\"},{\"capability\":\"observation\",\"result\":\"exercised\"},{\"capability\":\"recovery\",\"result\":\"exercised\"},{\"capability\":\"observer-rotation\",\"reason\":\"the qualified recipe and target declare none\",\"result\":\"not-applicable\"}],\"corpus_manifest_sha256\":\"d6c1cad9a6b0fe0fc27d1f8107c2381e8b9ab1bbfc04a47aa8234140de74a23f\",\"custody_descriptor\":\"aws-secrets-manager-v1 with workload identity\",\"evidence\":[{\"cases\":12,\"evidence_sha256\":\"c3a2a799eb04b1ee53a22495e0d95171a9f42f2ad557b639f3fe5440bbed90e7\",\"member\":\"conformance\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"dfd5b5dccc73cae91abec7a76c332dae145eb37eddb18f56dca2e68f2dbc81ab\",\"member\":\"differential\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"a05d5182b4f20eb67c0d95622a70f1e4ac87d1d1b8b7fab219a2276b6da41256\",\"member\":\"hostile\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"00beb3d9e44f8d20d5da8861818ecd7b430714f959a6613dbd2d870997eb90f8\",\"member\":\"live\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"3a4e01d7b8d11480e334d0d2fffc2efeeaf2363d21f9107094c3cfc3c063b362\",\"member\":\"recovery\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"6b428d653e06c75268e2e33f234f30f9cc24616c42faf551699f7a7ac2376011\",\"member\":\"rotation\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"e8713a54bfb187836d4db2f34f181129f2e03f7221bc2d3247134470adcacee8\",\"member\":\"restart\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"8824a7669543ecf652b651fa2d370c548e09b73c1babac841cd689389a1fdcbe\",\"member\":\"multi-instance\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"f31f29dc30a4e8ccd3aea69c012656c2811ac194881147b2cced5dd7dc1a7d9b\",\"member\":\"redaction\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"8e91fde286bdbb80e6d6245e7ab9dab68f92e790922170195fc80aab2eeb227b\",\"member\":\"installed-consumer\",\"result\":\"passed\",\"unauthorized_provider_entries\":0}],\"excluded_claims\":[\"the provider performed or settled the business effect\"],\"generated_artifacts_sha256\":\"fff3ece48e4f5271825e80b355a1243a4c30619329bbbc70bc4e5c1b242973e2\",\"installed_packages\":[{\"name\":\"auths-gateway\",\"sha256\":\"8a58d99c69c098e53c2197df2c6a6a16b131c69798f728db134c978f77e95360\",\"version\":\"1.0.0-rc.1\"},{\"name\":\"auths-python\",\"sha256\":\"59b028e3e66e681bfa195fb6afee775b91f30fc418f05f86353bc71cd021d2f9\",\"version\":\"1.0.0rc1\"}],\"live_effects\":{\"confirmed_by_read_back\":4,\"entered\":4},\"not_after\":1797768800,\"not_before\":1789992800,\"provenance\":{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"environment\":\"recipe-qualification\",\"repository\":\"github.com/auths-dev/auths-proof\",\"workflow\":\".github/workflows/recipe-qualification.yml\"},\"provider_kind\":\"example-payments\",\"provider_resources\":[\"refund:fixture-0001\",\"refund:fixture-0002\"],\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"recipe_decision_record_sha256\":\"0c2328dfcdc21fcd917fd242dd16f9adf1354395a472e589e2778dee99527081\",\"residual_assumptions\":[\"the provider keeps its test mode separate from live data\"],\"schema\":\"auths.recipe-qualification/1\",\"source_closure_sha256\":\"00023b3a6fbf90b531085365646cda2ffcac182f6eaedf453eb680b63ae33106\",\"store_descriptor\":\"postgresql 16 with TLS\",\"tuple\":{\"compiled_recipe_sha256\":\"262f5ef11b349645f2421c533220fc6bbfd70c4a5395f5d65c601406eba7d4ef\",\"gateway_semantic_closure_sha256\":\"01ec13346b098e4f5e1c64a995a50ce15ef339dc1f304966a45c94e80638203b\",\"profile_lock_sha256\":\"4dd8982feedb83403f985de3e1a952a90060e44035ab797e5313ff93957a22d5\",\"provider_contract_id\":\"f15f154a38de58de1b27c70c61a6b20fe532746e2e4462576dbd3d27d76cce3d\",\"recipe_family\":\"example-refund-v1\",\"target\":{\"arch\":\"x86_64\",\"credential_store_kind\":\"aws-secrets-manager-v1\",\"gateway_build_sha256\":\"42194bc83fbd821aaede008519091b4516baf914f8c2e27f3f2ac7a25f7485c3\",\"gateway_package\":\"auths-gateway\",\"gateway_version\":\"1.0.0-rc.1\",\"os\":\"linux\",\"store_kind\":\"postgresql-v1\",\"store_schema\":\"auths.lifecycle.postgresql/5\"}}}" + "text": "{\"schema\":\"auths.recipe-qualification/1\",\"capabilities\":[{\"capability\":\"credential-guard\",\"result\":\"exercised\"},{\"capability\":\"version-pin\",\"result\":\"exercised\"},{\"capability\":\"account-binding\",\"reason\":\"the qualified recipe and target declare none\",\"result\":\"not-applicable\"},{\"capability\":\"denied-reads\",\"result\":\"exercised\"},{\"capability\":\"ceiling\",\"result\":\"exercised\"},{\"capability\":\"budget\",\"result\":\"exercised\"},{\"capability\":\"idempotency\",\"result\":\"exercised\"},{\"capability\":\"response-locator\",\"result\":\"exercised\"},{\"capability\":\"echo\",\"result\":\"exercised\"},{\"capability\":\"observation\",\"result\":\"exercised\"},{\"capability\":\"recovery\",\"result\":\"exercised\"},{\"capability\":\"observer-rotation\",\"reason\":\"the qualified recipe and target declare none\",\"result\":\"not-applicable\"}],\"corpus_manifest_sha256\":\"d6c1cad9a6b0fe0fc27d1f8107c2381e8b9ab1bbfc04a47aa8234140de74a23f\",\"custody_descriptor\":\"aws-secrets-manager-v1 with workload identity\",\"evidence\":[{\"cases\":12,\"evidence_sha256\":\"c3a2a799eb04b1ee53a22495e0d95171a9f42f2ad557b639f3fe5440bbed90e7\",\"member\":\"conformance\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"dfd5b5dccc73cae91abec7a76c332dae145eb37eddb18f56dca2e68f2dbc81ab\",\"member\":\"differential\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"a05d5182b4f20eb67c0d95622a70f1e4ac87d1d1b8b7fab219a2276b6da41256\",\"member\":\"hostile\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"00beb3d9e44f8d20d5da8861818ecd7b430714f959a6613dbd2d870997eb90f8\",\"member\":\"live\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"3a4e01d7b8d11480e334d0d2fffc2efeeaf2363d21f9107094c3cfc3c063b362\",\"member\":\"recovery\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"6b428d653e06c75268e2e33f234f30f9cc24616c42faf551699f7a7ac2376011\",\"member\":\"rotation\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"e8713a54bfb187836d4db2f34f181129f2e03f7221bc2d3247134470adcacee8\",\"member\":\"restart\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"8824a7669543ecf652b651fa2d370c548e09b73c1babac841cd689389a1fdcbe\",\"member\":\"multi-instance\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"f31f29dc30a4e8ccd3aea69c012656c2811ac194881147b2cced5dd7dc1a7d9b\",\"member\":\"redaction\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"8e91fde286bdbb80e6d6245e7ab9dab68f92e790922170195fc80aab2eeb227b\",\"member\":\"installed-consumer\",\"result\":\"passed\",\"unauthorized_provider_entries\":0}],\"excluded_claims\":[\"the provider performed or settled the business effect\"],\"generated_artifacts_sha256\":\"fff3ece48e4f5271825e80b355a1243a4c30619329bbbc70bc4e5c1b242973e2\",\"installed_packages\":[{\"name\":\"auths-gateway\",\"sha256\":\"8a58d99c69c098e53c2197df2c6a6a16b131c69798f728db134c978f77e95360\",\"version\":\"1.0.0-rc.1\"},{\"name\":\"auths-python\",\"sha256\":\"59b028e3e66e681bfa195fb6afee775b91f30fc418f05f86353bc71cd021d2f9\",\"version\":\"1.0.0rc1\"}],\"live_effects\":{\"confirmed_by_read_back\":4,\"entered\":4},\"not_after\":1797768800,\"not_before\":1789992800,\"provenance\":{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"environment\":\"recipe-qualification\",\"repository\":\"github.com/auths-dev/auths-proof\",\"workflow\":\".github/workflows/recipe-qualification.yml\"},\"provider_kind\":\"example-payments\",\"provider_resources\":[\"refund:fixture-0001\",\"refund:fixture-0002\"],\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"recipe_decision_record_sha256\":\"0c2328dfcdc21fcd917fd242dd16f9adf1354395a472e589e2778dee99527081\",\"residual_assumptions\":[\"the provider keeps its test mode separate from live data\"],\"schema\":\"auths.recipe-qualification/1\",\"source_closure_sha256\":\"00023b3a6fbf90b531085365646cda2ffcac182f6eaedf453eb680b63ae33106\",\"store_descriptor\":\"postgresql 16 with TLS\",\"tuple\":{\"compiled_recipe_sha256\":\"262f5ef11b349645f2421c533220fc6bbfd70c4a5395f5d65c601406eba7d4ef\",\"gateway_semantic_closure_sha256\":\"01ec13346b098e4f5e1c64a995a50ce15ef339dc1f304966a45c94e80638203b\",\"profile_lock_sha256\":\"4dd8982feedb83403f985de3e1a952a90060e44035ab797e5313ff93957a22d5\",\"provider_contract_id\":\"f15f154a38de58de1b27c70c61a6b20fe532746e2e4462576dbd3d27d76cce3d\",\"recipe_family\":\"example-refund-v1\",\"target\":{\"arch\":\"x86_64\",\"credential_store_kind\":\"aws-secrets-manager-v1\",\"gateway_build_sha256\":\"42194bc83fbd821aaede008519091b4516baf914f8c2e27f3f2ac7a25f7485c3\",\"gateway_package\":\"auths-gateway\",\"gateway_version\":\"1.0.0-rc.1\",\"os\":\"linux\",\"store_kind\":\"postgresql-v1\",\"store_schema\":\"auths.lifecycle.postgresql/6\"}}}" }, { "id": "certificate-hardware-signer-kind", @@ -833,14 +833,14 @@ "pointer": "/statement/entries", "value": [ { - "attestation_sha256": "70d270e747fcf8bca9f408758ddcc1cd4470bd0dc8fa675ea68ce960146c8bbd", + "attestation_sha256": "00449fd858186bb6711b8697f6ea376b5c6a99ef79e0443c6ccc23a1a36e8c82", "qualification_id": "qlf_01010101010101010101010101010101", - "record_sha256": "d7a00ddda1c3b7afa99bb997fd9d88f864937a104e1b8cdd4370ebb914c6d306" + "record_sha256": "e5495a2c95356229a778d6781860eed872090ac5f4b6ac447953d353a3592f7a" }, { - "attestation_sha256": "70d270e747fcf8bca9f408758ddcc1cd4470bd0dc8fa675ea68ce960146c8bbd", + "attestation_sha256": "00449fd858186bb6711b8697f6ea376b5c6a99ef79e0443c6ccc23a1a36e8c82", "qualification_id": "qlf_01010101010101010101010101010101", - "record_sha256": "d7a00ddda1c3b7afa99bb997fd9d88f864937a104e1b8cdd4370ebb914c6d306" + "record_sha256": "e5495a2c95356229a778d6781860eed872090ac5f4b6ac447953d353a3592f7a" } ] } @@ -858,9 +858,9 @@ "count": 257, "width": 32, "template": { - "attestation_sha256": "70d270e747fcf8bca9f408758ddcc1cd4470bd0dc8fa675ea68ce960146c8bbd", + "attestation_sha256": "00449fd858186bb6711b8697f6ea376b5c6a99ef79e0443c6ccc23a1a36e8c82", "qualification_id": "qlf_{}", - "record_sha256": "d7a00ddda1c3b7afa99bb997fd9d88f864937a104e1b8cdd4370ebb914c6d306" + "record_sha256": "e5495a2c95356229a778d6781860eed872090ac5f4b6ac447953d353a3592f7a" } } ] diff --git a/bindings/fixtures/qualification/verification-vectors.json b/bindings/fixtures/qualification/verification-vectors.json index 080ae4666..5d2176dbe 100644 --- a/bindings/fixtures/qualification/verification-vectors.json +++ b/bindings/fixtures/qualification/verification-vectors.json @@ -50,12 +50,12 @@ "trust_root": "{\"public_key_b64\":\"0EqyMnQrtKs6E2i9RhXk5tAiSrcaAWuvhSCjMsl3hzc\",\"root_id\":\"auths-qualification-root-1\",\"schema\":\"auths.qualification-trust-root/1\",\"signature_suite\":\"ed25519-v1\"}", "signer_certificate": "{\"root_signature_b64\":\"obGs_sPHvOXfTu8emdHu3odSbdq3PEW0XwoKhrOSb1LQTgq9LOvFPrRcuhE6Tis01Ac9ndvtGQiey6UWh0MmBg\",\"statement\":{\"issued_at\":1789913600,\"not_after\":1805465600,\"not_before\":1789913600,\"permitted_artifact_kinds\":[\"qualification-release-index\",\"recipe-qualification-attestation\"],\"public_key_b64\":\"oJql9HpnWYAv-VX43C0qFKXJnSO-l_hkEn_5ODRVpPA\",\"root_id\":\"auths-qualification-root-1\",\"schema\":\"auths.qualification-signer-certificate/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"release-signer-2026-10\",\"signer_kind\":\"protected-software-release-key-v1\"}}", "revocation_list": "{\"root_signature_b64\":\"nVaEVMHFGD_kiB0SIdz3uK3Xh0YlYrUJY-PRkV7_sCAc6mGs39yQxxGsiShFyuVrE_NxGHNnX40Lg6mi_w_hAw\",\"statement\":{\"issued_at\":1789996400,\"next_update\":1790255600,\"revoked_qualifications\":[],\"revoked_signers\":[],\"root_id\":\"auths-qualification-root-1\",\"schema\":\"auths.qualification-revocation-list/1\",\"sequence\":7}}", - "release_index": "{\"signature_b64\":\"QMMwlBk-GT36P5vZFGmqwVaI6dSlhiDIy6b69926s_4UkaNLW8VDkrCtAQtedDPG_B7Mwa7vteWiAtHHGJSuCQ\",\"statement\":{\"entries\":[{\"attestation_sha256\":\"70d270e747fcf8bca9f408758ddcc1cd4470bd0dc8fa675ea68ce960146c8bbd\",\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"record_sha256\":\"d7a00ddda1c3b7afa99bb997fd9d88f864937a104e1b8cdd4370ebb914c6d306\"}],\"issued_at\":1789996400,\"schema\":\"auths.qualification-release-index/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"release-signer-2026-10\"}}", + "release_index": "{\"signature_b64\":\"qLnnKRCjNPMQ4E4htzwihMF_RcLGUtZ-QpmUc0xvAf9So4UwLqsqnQ8iE7KQDBPiDDEaT2tXMdXo8UJx7BKoCw\",\"statement\":{\"entries\":[{\"attestation_sha256\":\"00449fd858186bb6711b8697f6ea376b5c6a99ef79e0443c6ccc23a1a36e8c82\",\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"record_sha256\":\"e5495a2c95356229a778d6781860eed872090ac5f4b6ac447953d353a3592f7a\"}],\"issued_at\":1789996400,\"schema\":\"auths.qualification-release-index/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"release-signer-2026-10\"}}", "records": [ - "{\"capabilities\":[{\"capability\":\"credential-guard\",\"result\":\"exercised\"},{\"capability\":\"version-pin\",\"result\":\"exercised\"},{\"capability\":\"account-binding\",\"reason\":\"the qualified recipe and target declare none\",\"result\":\"not-applicable\"},{\"capability\":\"denied-reads\",\"result\":\"exercised\"},{\"capability\":\"ceiling\",\"result\":\"exercised\"},{\"capability\":\"budget\",\"result\":\"exercised\"},{\"capability\":\"idempotency\",\"result\":\"exercised\"},{\"capability\":\"response-locator\",\"result\":\"exercised\"},{\"capability\":\"echo\",\"result\":\"exercised\"},{\"capability\":\"observation\",\"result\":\"exercised\"},{\"capability\":\"recovery\",\"result\":\"exercised\"},{\"capability\":\"observer-rotation\",\"reason\":\"the qualified recipe and target declare none\",\"result\":\"not-applicable\"}],\"corpus_manifest_sha256\":\"d6c1cad9a6b0fe0fc27d1f8107c2381e8b9ab1bbfc04a47aa8234140de74a23f\",\"custody_descriptor\":\"aws-secrets-manager-v1 with workload identity\",\"evidence\":[{\"cases\":12,\"evidence_sha256\":\"c3a2a799eb04b1ee53a22495e0d95171a9f42f2ad557b639f3fe5440bbed90e7\",\"member\":\"conformance\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"dfd5b5dccc73cae91abec7a76c332dae145eb37eddb18f56dca2e68f2dbc81ab\",\"member\":\"differential\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"a05d5182b4f20eb67c0d95622a70f1e4ac87d1d1b8b7fab219a2276b6da41256\",\"member\":\"hostile\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"00beb3d9e44f8d20d5da8861818ecd7b430714f959a6613dbd2d870997eb90f8\",\"member\":\"live\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"3a4e01d7b8d11480e334d0d2fffc2efeeaf2363d21f9107094c3cfc3c063b362\",\"member\":\"recovery\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"6b428d653e06c75268e2e33f234f30f9cc24616c42faf551699f7a7ac2376011\",\"member\":\"rotation\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"e8713a54bfb187836d4db2f34f181129f2e03f7221bc2d3247134470adcacee8\",\"member\":\"restart\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"8824a7669543ecf652b651fa2d370c548e09b73c1babac841cd689389a1fdcbe\",\"member\":\"multi-instance\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"f31f29dc30a4e8ccd3aea69c012656c2811ac194881147b2cced5dd7dc1a7d9b\",\"member\":\"redaction\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"8e91fde286bdbb80e6d6245e7ab9dab68f92e790922170195fc80aab2eeb227b\",\"member\":\"installed-consumer\",\"result\":\"passed\",\"unauthorized_provider_entries\":0}],\"excluded_claims\":[\"the provider performed or settled the business effect\"],\"generated_artifacts_sha256\":\"fff3ece48e4f5271825e80b355a1243a4c30619329bbbc70bc4e5c1b242973e2\",\"installed_packages\":[{\"name\":\"auths-gateway\",\"sha256\":\"8a58d99c69c098e53c2197df2c6a6a16b131c69798f728db134c978f77e95360\",\"version\":\"1.0.0-rc.1\"},{\"name\":\"auths-python\",\"sha256\":\"59b028e3e66e681bfa195fb6afee775b91f30fc418f05f86353bc71cd021d2f9\",\"version\":\"1.0.0rc1\"}],\"live_effects\":{\"confirmed_by_read_back\":4,\"entered\":4},\"not_after\":1797768800,\"not_before\":1789992800,\"provenance\":{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"environment\":\"recipe-qualification\",\"repository\":\"github.com/auths-dev/auths-proof\",\"workflow\":\".github/workflows/recipe-qualification.yml\"},\"provider_kind\":\"example-payments\",\"provider_resources\":[\"refund:fixture-0001\",\"refund:fixture-0002\"],\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"recipe_decision_record_sha256\":\"0c2328dfcdc21fcd917fd242dd16f9adf1354395a472e589e2778dee99527081\",\"residual_assumptions\":[\"the provider keeps its test mode separate from live data\"],\"schema\":\"auths.recipe-qualification/1\",\"source_closure_sha256\":\"00023b3a6fbf90b531085365646cda2ffcac182f6eaedf453eb680b63ae33106\",\"store_descriptor\":\"postgresql 16 with TLS\",\"tuple\":{\"compiled_recipe_sha256\":\"262f5ef11b349645f2421c533220fc6bbfd70c4a5395f5d65c601406eba7d4ef\",\"gateway_semantic_closure_sha256\":\"01ec13346b098e4f5e1c64a995a50ce15ef339dc1f304966a45c94e80638203b\",\"profile_lock_sha256\":\"4dd8982feedb83403f985de3e1a952a90060e44035ab797e5313ff93957a22d5\",\"provider_contract_id\":\"f15f154a38de58de1b27c70c61a6b20fe532746e2e4462576dbd3d27d76cce3d\",\"recipe_family\":\"example-refund-v1\",\"target\":{\"arch\":\"x86_64\",\"credential_store_kind\":\"aws-secrets-manager-v1\",\"gateway_build_sha256\":\"42194bc83fbd821aaede008519091b4516baf914f8c2e27f3f2ac7a25f7485c3\",\"gateway_package\":\"auths-gateway\",\"gateway_version\":\"1.0.0-rc.1\",\"os\":\"linux\",\"store_kind\":\"postgresql-v1\",\"store_schema\":\"auths.lifecycle.postgresql/5\"}}}" + "{\"capabilities\":[{\"capability\":\"credential-guard\",\"result\":\"exercised\"},{\"capability\":\"version-pin\",\"result\":\"exercised\"},{\"capability\":\"account-binding\",\"reason\":\"the qualified recipe and target declare none\",\"result\":\"not-applicable\"},{\"capability\":\"denied-reads\",\"result\":\"exercised\"},{\"capability\":\"ceiling\",\"result\":\"exercised\"},{\"capability\":\"budget\",\"result\":\"exercised\"},{\"capability\":\"idempotency\",\"result\":\"exercised\"},{\"capability\":\"response-locator\",\"result\":\"exercised\"},{\"capability\":\"echo\",\"result\":\"exercised\"},{\"capability\":\"observation\",\"result\":\"exercised\"},{\"capability\":\"recovery\",\"result\":\"exercised\"},{\"capability\":\"observer-rotation\",\"reason\":\"the qualified recipe and target declare none\",\"result\":\"not-applicable\"}],\"corpus_manifest_sha256\":\"d6c1cad9a6b0fe0fc27d1f8107c2381e8b9ab1bbfc04a47aa8234140de74a23f\",\"custody_descriptor\":\"aws-secrets-manager-v1 with workload identity\",\"evidence\":[{\"cases\":12,\"evidence_sha256\":\"c3a2a799eb04b1ee53a22495e0d95171a9f42f2ad557b639f3fe5440bbed90e7\",\"member\":\"conformance\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"dfd5b5dccc73cae91abec7a76c332dae145eb37eddb18f56dca2e68f2dbc81ab\",\"member\":\"differential\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"a05d5182b4f20eb67c0d95622a70f1e4ac87d1d1b8b7fab219a2276b6da41256\",\"member\":\"hostile\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"00beb3d9e44f8d20d5da8861818ecd7b430714f959a6613dbd2d870997eb90f8\",\"member\":\"live\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"3a4e01d7b8d11480e334d0d2fffc2efeeaf2363d21f9107094c3cfc3c063b362\",\"member\":\"recovery\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"6b428d653e06c75268e2e33f234f30f9cc24616c42faf551699f7a7ac2376011\",\"member\":\"rotation\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"e8713a54bfb187836d4db2f34f181129f2e03f7221bc2d3247134470adcacee8\",\"member\":\"restart\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"8824a7669543ecf652b651fa2d370c548e09b73c1babac841cd689389a1fdcbe\",\"member\":\"multi-instance\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"f31f29dc30a4e8ccd3aea69c012656c2811ac194881147b2cced5dd7dc1a7d9b\",\"member\":\"redaction\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"8e91fde286bdbb80e6d6245e7ab9dab68f92e790922170195fc80aab2eeb227b\",\"member\":\"installed-consumer\",\"result\":\"passed\",\"unauthorized_provider_entries\":0}],\"excluded_claims\":[\"the provider performed or settled the business effect\"],\"generated_artifacts_sha256\":\"fff3ece48e4f5271825e80b355a1243a4c30619329bbbc70bc4e5c1b242973e2\",\"installed_packages\":[{\"name\":\"auths-gateway\",\"sha256\":\"8a58d99c69c098e53c2197df2c6a6a16b131c69798f728db134c978f77e95360\",\"version\":\"1.0.0-rc.1\"},{\"name\":\"auths-python\",\"sha256\":\"59b028e3e66e681bfa195fb6afee775b91f30fc418f05f86353bc71cd021d2f9\",\"version\":\"1.0.0rc1\"}],\"live_effects\":{\"confirmed_by_read_back\":4,\"entered\":4},\"not_after\":1797768800,\"not_before\":1789992800,\"provenance\":{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"environment\":\"recipe-qualification\",\"repository\":\"github.com/auths-dev/auths-proof\",\"workflow\":\".github/workflows/recipe-qualification.yml\"},\"provider_kind\":\"example-payments\",\"provider_resources\":[\"refund:fixture-0001\",\"refund:fixture-0002\"],\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"recipe_decision_record_sha256\":\"0c2328dfcdc21fcd917fd242dd16f9adf1354395a472e589e2778dee99527081\",\"residual_assumptions\":[\"the provider keeps its test mode separate from live data\"],\"schema\":\"auths.recipe-qualification/1\",\"source_closure_sha256\":\"00023b3a6fbf90b531085365646cda2ffcac182f6eaedf453eb680b63ae33106\",\"store_descriptor\":\"postgresql 16 with TLS\",\"tuple\":{\"compiled_recipe_sha256\":\"262f5ef11b349645f2421c533220fc6bbfd70c4a5395f5d65c601406eba7d4ef\",\"gateway_semantic_closure_sha256\":\"01ec13346b098e4f5e1c64a995a50ce15ef339dc1f304966a45c94e80638203b\",\"profile_lock_sha256\":\"4dd8982feedb83403f985de3e1a952a90060e44035ab797e5313ff93957a22d5\",\"provider_contract_id\":\"f15f154a38de58de1b27c70c61a6b20fe532746e2e4462576dbd3d27d76cce3d\",\"recipe_family\":\"example-refund-v1\",\"target\":{\"arch\":\"x86_64\",\"credential_store_kind\":\"aws-secrets-manager-v1\",\"gateway_build_sha256\":\"42194bc83fbd821aaede008519091b4516baf914f8c2e27f3f2ac7a25f7485c3\",\"gateway_package\":\"auths-gateway\",\"gateway_version\":\"1.0.0-rc.1\",\"os\":\"linux\",\"store_kind\":\"postgresql-v1\",\"store_schema\":\"auths.lifecycle.postgresql/6\"}}}" ], "attestations": [ - "{\"signature_b64\":\"oR2QsmEvCp-fGvV0ysEM-a3opOp6SlgJzb63U4ESuZz0yRPlyoOK39PhRELjaiaMzpiRyj-LVUmnKkd3pvFNAQ\",\"statement\":{\"issued_at\":1789992800,\"not_after\":1797768800,\"not_before\":1789992800,\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"record_sha256\":\"d7a00ddda1c3b7afa99bb997fd9d88f864937a104e1b8cdd4370ebb914c6d306\",\"schema\":\"auths.recipe-qualification-attestation/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"release-signer-2026-10\"}}" + "{\"signature_b64\":\"RNvz-GVoozTJulLOMogzaDjwNMmNJIciII7dGyYiqv7CLXqD7OeqqnmO4COD_-YI7CtUTuT50ARNLDOYx6HOAw\",\"statement\":{\"issued_at\":1789992800,\"not_after\":1797768800,\"not_before\":1789992800,\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"record_sha256\":\"e5495a2c95356229a778d6781860eed872090ac5f4b6ac447953d353a3592f7a\",\"schema\":\"auths.recipe-qualification-attestation/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"release-signer-2026-10\"}}" ], "deployment": { "recipe_family": "example-refund-v1", @@ -70,7 +70,7 @@ "gateway_version": "1.0.0-rc.1", "gateway_build_sha256": "42194bc83fbd821aaede008519091b4516baf914f8c2e27f3f2ac7a25f7485c3", "store_kind": "postgresql-v1", - "store_schema": "auths.lifecycle.postgresql/5", + "store_schema": "auths.lifecycle.postgresql/6", "credential_store_kind": "aws-secrets-manager-v1" } } @@ -91,14 +91,14 @@ "class": "valid", "replace": { "records": [ - "{\"capabilities\":[{\"capability\":\"credential-guard\",\"result\":\"exercised\"},{\"capability\":\"version-pin\",\"result\":\"exercised\"},{\"capability\":\"account-binding\",\"reason\":\"the qualified recipe and target declare none\",\"result\":\"not-applicable\"},{\"capability\":\"denied-reads\",\"result\":\"exercised\"},{\"capability\":\"ceiling\",\"result\":\"exercised\"},{\"capability\":\"budget\",\"result\":\"exercised\"},{\"capability\":\"idempotency\",\"result\":\"exercised\"},{\"capability\":\"response-locator\",\"result\":\"exercised\"},{\"capability\":\"echo\",\"result\":\"exercised\"},{\"capability\":\"observation\",\"result\":\"exercised\"},{\"capability\":\"recovery\",\"result\":\"exercised\"},{\"capability\":\"observer-rotation\",\"reason\":\"the qualified recipe and target declare none\",\"result\":\"not-applicable\"}],\"corpus_manifest_sha256\":\"d6c1cad9a6b0fe0fc27d1f8107c2381e8b9ab1bbfc04a47aa8234140de74a23f\",\"custody_descriptor\":\"aws-secrets-manager-v1 with workload identity\",\"evidence\":[{\"cases\":12,\"evidence_sha256\":\"c3a2a799eb04b1ee53a22495e0d95171a9f42f2ad557b639f3fe5440bbed90e7\",\"member\":\"conformance\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"dfd5b5dccc73cae91abec7a76c332dae145eb37eddb18f56dca2e68f2dbc81ab\",\"member\":\"differential\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"a05d5182b4f20eb67c0d95622a70f1e4ac87d1d1b8b7fab219a2276b6da41256\",\"member\":\"hostile\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"00beb3d9e44f8d20d5da8861818ecd7b430714f959a6613dbd2d870997eb90f8\",\"member\":\"live\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"3a4e01d7b8d11480e334d0d2fffc2efeeaf2363d21f9107094c3cfc3c063b362\",\"member\":\"recovery\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"6b428d653e06c75268e2e33f234f30f9cc24616c42faf551699f7a7ac2376011\",\"member\":\"rotation\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"e8713a54bfb187836d4db2f34f181129f2e03f7221bc2d3247134470adcacee8\",\"member\":\"restart\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"8824a7669543ecf652b651fa2d370c548e09b73c1babac841cd689389a1fdcbe\",\"member\":\"multi-instance\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"f31f29dc30a4e8ccd3aea69c012656c2811ac194881147b2cced5dd7dc1a7d9b\",\"member\":\"redaction\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"8e91fde286bdbb80e6d6245e7ab9dab68f92e790922170195fc80aab2eeb227b\",\"member\":\"installed-consumer\",\"result\":\"passed\",\"unauthorized_provider_entries\":0}],\"excluded_claims\":[\"the provider performed or settled the business effect\"],\"generated_artifacts_sha256\":\"fff3ece48e4f5271825e80b355a1243a4c30619329bbbc70bc4e5c1b242973e2\",\"installed_packages\":[{\"name\":\"auths-gateway\",\"sha256\":\"8a58d99c69c098e53c2197df2c6a6a16b131c69798f728db134c978f77e95360\",\"version\":\"1.0.0-rc.1\"},{\"name\":\"auths-python\",\"sha256\":\"59b028e3e66e681bfa195fb6afee775b91f30fc418f05f86353bc71cd021d2f9\",\"version\":\"1.0.0rc1\"}],\"live_effects\":{\"confirmed_by_read_back\":4,\"entered\":4},\"not_after\":1797768800,\"not_before\":1789992800,\"provenance\":{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"environment\":\"recipe-qualification\",\"repository\":\"github.com/auths-dev/auths-proof\",\"workflow\":\".github/workflows/recipe-qualification.yml\"},\"provider_kind\":\"example-payments\",\"provider_resources\":[\"refund:fixture-0001\",\"refund:fixture-0002\"],\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"recipe_decision_record_sha256\":\"0c2328dfcdc21fcd917fd242dd16f9adf1354395a472e589e2778dee99527081\",\"residual_assumptions\":[\"the provider keeps its test mode separate from live data\"],\"schema\":\"auths.recipe-qualification/1\",\"source_closure_sha256\":\"00023b3a6fbf90b531085365646cda2ffcac182f6eaedf453eb680b63ae33106\",\"store_descriptor\":\"postgresql 16 with TLS\",\"tuple\":{\"compiled_recipe_sha256\":\"262f5ef11b349645f2421c533220fc6bbfd70c4a5395f5d65c601406eba7d4ef\",\"gateway_semantic_closure_sha256\":\"01ec13346b098e4f5e1c64a995a50ce15ef339dc1f304966a45c94e80638203b\",\"profile_lock_sha256\":\"4dd8982feedb83403f985de3e1a952a90060e44035ab797e5313ff93957a22d5\",\"provider_contract_id\":\"f15f154a38de58de1b27c70c61a6b20fe532746e2e4462576dbd3d27d76cce3d\",\"recipe_family\":\"example-refund-v1\",\"target\":{\"arch\":\"x86_64\",\"credential_store_kind\":\"aws-secrets-manager-v1\",\"gateway_build_sha256\":\"42194bc83fbd821aaede008519091b4516baf914f8c2e27f3f2ac7a25f7485c3\",\"gateway_package\":\"auths-gateway\",\"gateway_version\":\"1.0.0-rc.1\",\"os\":\"linux\",\"store_kind\":\"postgresql-v1\",\"store_schema\":\"auths.lifecycle.postgresql/5\"}}}", - "{\"capabilities\":[{\"capability\":\"credential-guard\",\"result\":\"exercised\"},{\"capability\":\"version-pin\",\"result\":\"exercised\"},{\"capability\":\"account-binding\",\"reason\":\"the qualified recipe and target declare none\",\"result\":\"not-applicable\"},{\"capability\":\"denied-reads\",\"result\":\"exercised\"},{\"capability\":\"ceiling\",\"result\":\"exercised\"},{\"capability\":\"budget\",\"result\":\"exercised\"},{\"capability\":\"idempotency\",\"result\":\"exercised\"},{\"capability\":\"response-locator\",\"result\":\"exercised\"},{\"capability\":\"echo\",\"result\":\"exercised\"},{\"capability\":\"observation\",\"result\":\"exercised\"},{\"capability\":\"recovery\",\"result\":\"exercised\"},{\"capability\":\"observer-rotation\",\"reason\":\"the qualified recipe and target declare none\",\"result\":\"not-applicable\"}],\"corpus_manifest_sha256\":\"d6c1cad9a6b0fe0fc27d1f8107c2381e8b9ab1bbfc04a47aa8234140de74a23f\",\"custody_descriptor\":\"aws-secrets-manager-v1 with workload identity\",\"evidence\":[{\"cases\":12,\"evidence_sha256\":\"c3a2a799eb04b1ee53a22495e0d95171a9f42f2ad557b639f3fe5440bbed90e7\",\"member\":\"conformance\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"dfd5b5dccc73cae91abec7a76c332dae145eb37eddb18f56dca2e68f2dbc81ab\",\"member\":\"differential\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"a05d5182b4f20eb67c0d95622a70f1e4ac87d1d1b8b7fab219a2276b6da41256\",\"member\":\"hostile\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"00beb3d9e44f8d20d5da8861818ecd7b430714f959a6613dbd2d870997eb90f8\",\"member\":\"live\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"3a4e01d7b8d11480e334d0d2fffc2efeeaf2363d21f9107094c3cfc3c063b362\",\"member\":\"recovery\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"6b428d653e06c75268e2e33f234f30f9cc24616c42faf551699f7a7ac2376011\",\"member\":\"rotation\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"e8713a54bfb187836d4db2f34f181129f2e03f7221bc2d3247134470adcacee8\",\"member\":\"restart\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"8824a7669543ecf652b651fa2d370c548e09b73c1babac841cd689389a1fdcbe\",\"member\":\"multi-instance\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"f31f29dc30a4e8ccd3aea69c012656c2811ac194881147b2cced5dd7dc1a7d9b\",\"member\":\"redaction\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"8e91fde286bdbb80e6d6245e7ab9dab68f92e790922170195fc80aab2eeb227b\",\"member\":\"installed-consumer\",\"result\":\"passed\",\"unauthorized_provider_entries\":0}],\"excluded_claims\":[\"the provider performed or settled the business effect\"],\"generated_artifacts_sha256\":\"fff3ece48e4f5271825e80b355a1243a4c30619329bbbc70bc4e5c1b242973e2\",\"installed_packages\":[{\"name\":\"auths-gateway\",\"sha256\":\"8a58d99c69c098e53c2197df2c6a6a16b131c69798f728db134c978f77e95360\",\"version\":\"1.0.0-rc.1\"},{\"name\":\"auths-python\",\"sha256\":\"59b028e3e66e681bfa195fb6afee775b91f30fc418f05f86353bc71cd021d2f9\",\"version\":\"1.0.0rc1\"}],\"live_effects\":{\"confirmed_by_read_back\":4,\"entered\":4},\"not_after\":1797768800,\"not_before\":1789992800,\"provenance\":{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"environment\":\"recipe-qualification\",\"repository\":\"github.com/auths-dev/auths-proof\",\"workflow\":\".github/workflows/recipe-qualification.yml\"},\"provider_kind\":\"example-payments\",\"provider_resources\":[\"refund:fixture-0001\",\"refund:fixture-0002\"],\"qualification_id\":\"qlf_02020202020202020202020202020202\",\"recipe_decision_record_sha256\":\"0c2328dfcdc21fcd917fd242dd16f9adf1354395a472e589e2778dee99527081\",\"residual_assumptions\":[\"the provider keeps its test mode separate from live data\"],\"schema\":\"auths.recipe-qualification/1\",\"source_closure_sha256\":\"00023b3a6fbf90b531085365646cda2ffcac182f6eaedf453eb680b63ae33106\",\"store_descriptor\":\"postgresql 16 with TLS\",\"tuple\":{\"compiled_recipe_sha256\":\"262f5ef11b349645f2421c533220fc6bbfd70c4a5395f5d65c601406eba7d4ef\",\"gateway_semantic_closure_sha256\":\"01ec13346b098e4f5e1c64a995a50ce15ef339dc1f304966a45c94e80638203b\",\"profile_lock_sha256\":\"4dd8982feedb83403f985de3e1a952a90060e44035ab797e5313ff93957a22d5\",\"provider_contract_id\":\"f15f154a38de58de1b27c70c61a6b20fe532746e2e4462576dbd3d27d76cce3d\",\"recipe_family\":\"example-refund-v1\",\"target\":{\"arch\":\"aarch64\",\"credential_store_kind\":\"aws-secrets-manager-v1\",\"gateway_build_sha256\":\"42194bc83fbd821aaede008519091b4516baf914f8c2e27f3f2ac7a25f7485c3\",\"gateway_package\":\"auths-gateway\",\"gateway_version\":\"1.0.0-rc.1\",\"os\":\"linux\",\"store_kind\":\"postgresql-v1\",\"store_schema\":\"auths.lifecycle.postgresql/5\"}}}" + "{\"capabilities\":[{\"capability\":\"credential-guard\",\"result\":\"exercised\"},{\"capability\":\"version-pin\",\"result\":\"exercised\"},{\"capability\":\"account-binding\",\"reason\":\"the qualified recipe and target declare none\",\"result\":\"not-applicable\"},{\"capability\":\"denied-reads\",\"result\":\"exercised\"},{\"capability\":\"ceiling\",\"result\":\"exercised\"},{\"capability\":\"budget\",\"result\":\"exercised\"},{\"capability\":\"idempotency\",\"result\":\"exercised\"},{\"capability\":\"response-locator\",\"result\":\"exercised\"},{\"capability\":\"echo\",\"result\":\"exercised\"},{\"capability\":\"observation\",\"result\":\"exercised\"},{\"capability\":\"recovery\",\"result\":\"exercised\"},{\"capability\":\"observer-rotation\",\"reason\":\"the qualified recipe and target declare none\",\"result\":\"not-applicable\"}],\"corpus_manifest_sha256\":\"d6c1cad9a6b0fe0fc27d1f8107c2381e8b9ab1bbfc04a47aa8234140de74a23f\",\"custody_descriptor\":\"aws-secrets-manager-v1 with workload identity\",\"evidence\":[{\"cases\":12,\"evidence_sha256\":\"c3a2a799eb04b1ee53a22495e0d95171a9f42f2ad557b639f3fe5440bbed90e7\",\"member\":\"conformance\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"dfd5b5dccc73cae91abec7a76c332dae145eb37eddb18f56dca2e68f2dbc81ab\",\"member\":\"differential\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"a05d5182b4f20eb67c0d95622a70f1e4ac87d1d1b8b7fab219a2276b6da41256\",\"member\":\"hostile\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"00beb3d9e44f8d20d5da8861818ecd7b430714f959a6613dbd2d870997eb90f8\",\"member\":\"live\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"3a4e01d7b8d11480e334d0d2fffc2efeeaf2363d21f9107094c3cfc3c063b362\",\"member\":\"recovery\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"6b428d653e06c75268e2e33f234f30f9cc24616c42faf551699f7a7ac2376011\",\"member\":\"rotation\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"e8713a54bfb187836d4db2f34f181129f2e03f7221bc2d3247134470adcacee8\",\"member\":\"restart\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"8824a7669543ecf652b651fa2d370c548e09b73c1babac841cd689389a1fdcbe\",\"member\":\"multi-instance\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"f31f29dc30a4e8ccd3aea69c012656c2811ac194881147b2cced5dd7dc1a7d9b\",\"member\":\"redaction\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"8e91fde286bdbb80e6d6245e7ab9dab68f92e790922170195fc80aab2eeb227b\",\"member\":\"installed-consumer\",\"result\":\"passed\",\"unauthorized_provider_entries\":0}],\"excluded_claims\":[\"the provider performed or settled the business effect\"],\"generated_artifacts_sha256\":\"fff3ece48e4f5271825e80b355a1243a4c30619329bbbc70bc4e5c1b242973e2\",\"installed_packages\":[{\"name\":\"auths-gateway\",\"sha256\":\"8a58d99c69c098e53c2197df2c6a6a16b131c69798f728db134c978f77e95360\",\"version\":\"1.0.0-rc.1\"},{\"name\":\"auths-python\",\"sha256\":\"59b028e3e66e681bfa195fb6afee775b91f30fc418f05f86353bc71cd021d2f9\",\"version\":\"1.0.0rc1\"}],\"live_effects\":{\"confirmed_by_read_back\":4,\"entered\":4},\"not_after\":1797768800,\"not_before\":1789992800,\"provenance\":{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"environment\":\"recipe-qualification\",\"repository\":\"github.com/auths-dev/auths-proof\",\"workflow\":\".github/workflows/recipe-qualification.yml\"},\"provider_kind\":\"example-payments\",\"provider_resources\":[\"refund:fixture-0001\",\"refund:fixture-0002\"],\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"recipe_decision_record_sha256\":\"0c2328dfcdc21fcd917fd242dd16f9adf1354395a472e589e2778dee99527081\",\"residual_assumptions\":[\"the provider keeps its test mode separate from live data\"],\"schema\":\"auths.recipe-qualification/1\",\"source_closure_sha256\":\"00023b3a6fbf90b531085365646cda2ffcac182f6eaedf453eb680b63ae33106\",\"store_descriptor\":\"postgresql 16 with TLS\",\"tuple\":{\"compiled_recipe_sha256\":\"262f5ef11b349645f2421c533220fc6bbfd70c4a5395f5d65c601406eba7d4ef\",\"gateway_semantic_closure_sha256\":\"01ec13346b098e4f5e1c64a995a50ce15ef339dc1f304966a45c94e80638203b\",\"profile_lock_sha256\":\"4dd8982feedb83403f985de3e1a952a90060e44035ab797e5313ff93957a22d5\",\"provider_contract_id\":\"f15f154a38de58de1b27c70c61a6b20fe532746e2e4462576dbd3d27d76cce3d\",\"recipe_family\":\"example-refund-v1\",\"target\":{\"arch\":\"x86_64\",\"credential_store_kind\":\"aws-secrets-manager-v1\",\"gateway_build_sha256\":\"42194bc83fbd821aaede008519091b4516baf914f8c2e27f3f2ac7a25f7485c3\",\"gateway_package\":\"auths-gateway\",\"gateway_version\":\"1.0.0-rc.1\",\"os\":\"linux\",\"store_kind\":\"postgresql-v1\",\"store_schema\":\"auths.lifecycle.postgresql/6\"}}}", + "{\"capabilities\":[{\"capability\":\"credential-guard\",\"result\":\"exercised\"},{\"capability\":\"version-pin\",\"result\":\"exercised\"},{\"capability\":\"account-binding\",\"reason\":\"the qualified recipe and target declare none\",\"result\":\"not-applicable\"},{\"capability\":\"denied-reads\",\"result\":\"exercised\"},{\"capability\":\"ceiling\",\"result\":\"exercised\"},{\"capability\":\"budget\",\"result\":\"exercised\"},{\"capability\":\"idempotency\",\"result\":\"exercised\"},{\"capability\":\"response-locator\",\"result\":\"exercised\"},{\"capability\":\"echo\",\"result\":\"exercised\"},{\"capability\":\"observation\",\"result\":\"exercised\"},{\"capability\":\"recovery\",\"result\":\"exercised\"},{\"capability\":\"observer-rotation\",\"reason\":\"the qualified recipe and target declare none\",\"result\":\"not-applicable\"}],\"corpus_manifest_sha256\":\"d6c1cad9a6b0fe0fc27d1f8107c2381e8b9ab1bbfc04a47aa8234140de74a23f\",\"custody_descriptor\":\"aws-secrets-manager-v1 with workload identity\",\"evidence\":[{\"cases\":12,\"evidence_sha256\":\"c3a2a799eb04b1ee53a22495e0d95171a9f42f2ad557b639f3fe5440bbed90e7\",\"member\":\"conformance\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"dfd5b5dccc73cae91abec7a76c332dae145eb37eddb18f56dca2e68f2dbc81ab\",\"member\":\"differential\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"a05d5182b4f20eb67c0d95622a70f1e4ac87d1d1b8b7fab219a2276b6da41256\",\"member\":\"hostile\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"00beb3d9e44f8d20d5da8861818ecd7b430714f959a6613dbd2d870997eb90f8\",\"member\":\"live\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"3a4e01d7b8d11480e334d0d2fffc2efeeaf2363d21f9107094c3cfc3c063b362\",\"member\":\"recovery\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"6b428d653e06c75268e2e33f234f30f9cc24616c42faf551699f7a7ac2376011\",\"member\":\"rotation\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"e8713a54bfb187836d4db2f34f181129f2e03f7221bc2d3247134470adcacee8\",\"member\":\"restart\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"8824a7669543ecf652b651fa2d370c548e09b73c1babac841cd689389a1fdcbe\",\"member\":\"multi-instance\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"f31f29dc30a4e8ccd3aea69c012656c2811ac194881147b2cced5dd7dc1a7d9b\",\"member\":\"redaction\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"8e91fde286bdbb80e6d6245e7ab9dab68f92e790922170195fc80aab2eeb227b\",\"member\":\"installed-consumer\",\"result\":\"passed\",\"unauthorized_provider_entries\":0}],\"excluded_claims\":[\"the provider performed or settled the business effect\"],\"generated_artifacts_sha256\":\"fff3ece48e4f5271825e80b355a1243a4c30619329bbbc70bc4e5c1b242973e2\",\"installed_packages\":[{\"name\":\"auths-gateway\",\"sha256\":\"8a58d99c69c098e53c2197df2c6a6a16b131c69798f728db134c978f77e95360\",\"version\":\"1.0.0-rc.1\"},{\"name\":\"auths-python\",\"sha256\":\"59b028e3e66e681bfa195fb6afee775b91f30fc418f05f86353bc71cd021d2f9\",\"version\":\"1.0.0rc1\"}],\"live_effects\":{\"confirmed_by_read_back\":4,\"entered\":4},\"not_after\":1797768800,\"not_before\":1789992800,\"provenance\":{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"environment\":\"recipe-qualification\",\"repository\":\"github.com/auths-dev/auths-proof\",\"workflow\":\".github/workflows/recipe-qualification.yml\"},\"provider_kind\":\"example-payments\",\"provider_resources\":[\"refund:fixture-0001\",\"refund:fixture-0002\"],\"qualification_id\":\"qlf_02020202020202020202020202020202\",\"recipe_decision_record_sha256\":\"0c2328dfcdc21fcd917fd242dd16f9adf1354395a472e589e2778dee99527081\",\"residual_assumptions\":[\"the provider keeps its test mode separate from live data\"],\"schema\":\"auths.recipe-qualification/1\",\"source_closure_sha256\":\"00023b3a6fbf90b531085365646cda2ffcac182f6eaedf453eb680b63ae33106\",\"store_descriptor\":\"postgresql 16 with TLS\",\"tuple\":{\"compiled_recipe_sha256\":\"262f5ef11b349645f2421c533220fc6bbfd70c4a5395f5d65c601406eba7d4ef\",\"gateway_semantic_closure_sha256\":\"01ec13346b098e4f5e1c64a995a50ce15ef339dc1f304966a45c94e80638203b\",\"profile_lock_sha256\":\"4dd8982feedb83403f985de3e1a952a90060e44035ab797e5313ff93957a22d5\",\"provider_contract_id\":\"f15f154a38de58de1b27c70c61a6b20fe532746e2e4462576dbd3d27d76cce3d\",\"recipe_family\":\"example-refund-v1\",\"target\":{\"arch\":\"aarch64\",\"credential_store_kind\":\"aws-secrets-manager-v1\",\"gateway_build_sha256\":\"42194bc83fbd821aaede008519091b4516baf914f8c2e27f3f2ac7a25f7485c3\",\"gateway_package\":\"auths-gateway\",\"gateway_version\":\"1.0.0-rc.1\",\"os\":\"linux\",\"store_kind\":\"postgresql-v1\",\"store_schema\":\"auths.lifecycle.postgresql/6\"}}}" ], "attestations": [ - "{\"signature_b64\":\"oR2QsmEvCp-fGvV0ysEM-a3opOp6SlgJzb63U4ESuZz0yRPlyoOK39PhRELjaiaMzpiRyj-LVUmnKkd3pvFNAQ\",\"statement\":{\"issued_at\":1789992800,\"not_after\":1797768800,\"not_before\":1789992800,\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"record_sha256\":\"d7a00ddda1c3b7afa99bb997fd9d88f864937a104e1b8cdd4370ebb914c6d306\",\"schema\":\"auths.recipe-qualification-attestation/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"release-signer-2026-10\"}}", - "{\"signature_b64\":\"VOQpMz4m_0eCYsoJt-BDNjXjyrWLzp_PvTl9H4nbNWd7nyWYQK_kkS2_aCa_ciuRacd9nsJI5UDYgQT-dITpAg\",\"statement\":{\"issued_at\":1789992800,\"not_after\":1797768800,\"not_before\":1789992800,\"qualification_id\":\"qlf_02020202020202020202020202020202\",\"record_sha256\":\"6274966a6fb4aa4b9bd77755cc8089e6a00d5e483fef57b4bb454af91270a2c7\",\"schema\":\"auths.recipe-qualification-attestation/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"release-signer-2026-10\"}}" + "{\"signature_b64\":\"RNvz-GVoozTJulLOMogzaDjwNMmNJIciII7dGyYiqv7CLXqD7OeqqnmO4COD_-YI7CtUTuT50ARNLDOYx6HOAw\",\"statement\":{\"issued_at\":1789992800,\"not_after\":1797768800,\"not_before\":1789992800,\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"record_sha256\":\"e5495a2c95356229a778d6781860eed872090ac5f4b6ac447953d353a3592f7a\",\"schema\":\"auths.recipe-qualification-attestation/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"release-signer-2026-10\"}}", + "{\"signature_b64\":\"1Hd7wDEt6bzoXwrcguCBXtcDy32fmhJRgKZVIG5iyFw-vVzLFAE06rP-p786NrT5nTepTF9DXwURduAeTvHSBQ\",\"statement\":{\"issued_at\":1789992800,\"not_after\":1797768800,\"not_before\":1789992800,\"qualification_id\":\"qlf_02020202020202020202020202020202\",\"record_sha256\":\"f4eee7e4a2af6f48d64102f768a9e056cf340d9be38cafde6808d8455785b7b7\",\"schema\":\"auths.recipe-qualification-attestation/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"release-signer-2026-10\"}}" ], - "release_index": "{\"signature_b64\":\"DkU0HaXav14R6WlF4e_qqdpmZ5NiHonJUYtG3LeaHkPs-YLA59c80b0Xorrgmr5-T5mJ_mRfP-7oUIV2RxOwAQ\",\"statement\":{\"entries\":[{\"attestation_sha256\":\"70d270e747fcf8bca9f408758ddcc1cd4470bd0dc8fa675ea68ce960146c8bbd\",\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"record_sha256\":\"d7a00ddda1c3b7afa99bb997fd9d88f864937a104e1b8cdd4370ebb914c6d306\"},{\"attestation_sha256\":\"86a6d76fa26713a1d1eee02cc60efd911ade5d73643e0d5b0adb1d5c7805c736\",\"qualification_id\":\"qlf_02020202020202020202020202020202\",\"record_sha256\":\"6274966a6fb4aa4b9bd77755cc8089e6a00d5e483fef57b4bb454af91270a2c7\"}],\"issued_at\":1789996400,\"schema\":\"auths.qualification-release-index/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"release-signer-2026-10\"}}", + "release_index": "{\"signature_b64\":\"rrIlocaWjnu0yGZqBctFItRCwBdsQACIBWypqxI4-DaRasCgyU0x354oFpqZT0HTcDQyh1cds1BrtMoslrhnDg\",\"statement\":{\"entries\":[{\"attestation_sha256\":\"00449fd858186bb6711b8697f6ea376b5c6a99ef79e0443c6ccc23a1a36e8c82\",\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"record_sha256\":\"e5495a2c95356229a778d6781860eed872090ac5f4b6ac447953d353a3592f7a\"},{\"attestation_sha256\":\"07660bc891d054fb560be8027aa9d74f489f74a347ede9818f826df7d42711a2\",\"qualification_id\":\"qlf_02020202020202020202020202020202\",\"record_sha256\":\"f4eee7e4a2af6f48d64102f768a9e056cf340d9be38cafde6808d8455785b7b7\"}],\"issued_at\":1789996400,\"schema\":\"auths.qualification-release-index/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"release-signer-2026-10\"}}", "deployment": { "recipe_family": "example-refund-v1", "compiled_recipe_sha256": "262f5ef11b349645f2421c533220fc6bbfd70c4a5395f5d65c601406eba7d4ef", @@ -112,7 +112,7 @@ "gateway_version": "1.0.0-rc.1", "gateway_build_sha256": "42194bc83fbd821aaede008519091b4516baf914f8c2e27f3f2ac7a25f7485c3", "store_kind": "postgresql-v1", - "store_schema": "auths.lifecycle.postgresql/5", + "store_schema": "auths.lifecycle.postgresql/6", "credential_store_kind": "aws-secrets-manager-v1" } } @@ -154,9 +154,9 @@ "class": "forged", "replace": { "attestations": [ - "{\"signature_b64\":\"oB2QsmEvCp-fGvV0ysEM-a3opOp6SlgJzb63U4ESuZz0yRPlyoOK39PhRELjaiaMzpiRyj-LVUmnKkd3pvFNAQ\",\"statement\":{\"issued_at\":1789992800,\"not_after\":1797768800,\"not_before\":1789992800,\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"record_sha256\":\"d7a00ddda1c3b7afa99bb997fd9d88f864937a104e1b8cdd4370ebb914c6d306\",\"schema\":\"auths.recipe-qualification-attestation/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"release-signer-2026-10\"}}" + "{\"signature_b64\":\"Rdvz-GVoozTJulLOMogzaDjwNMmNJIciII7dGyYiqv7CLXqD7OeqqnmO4COD_-YI7CtUTuT50ARNLDOYx6HOAw\",\"statement\":{\"issued_at\":1789992800,\"not_after\":1797768800,\"not_before\":1789992800,\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"record_sha256\":\"e5495a2c95356229a778d6781860eed872090ac5f4b6ac447953d353a3592f7a\",\"schema\":\"auths.recipe-qualification-attestation/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"release-signer-2026-10\"}}" ], - "release_index": "{\"signature_b64\":\"Q4kNLqaLBUocWfqElcoBn5LnR-hjcX5SizgJ7o4IoFgu7qlsgGHWscDv33JbLnJPtfkpS-FekbA9uyB7HZfYCA\",\"statement\":{\"entries\":[{\"attestation_sha256\":\"f0ad9a6e35cd8d1d7e7388dcb016596388cabfb7c3658a60e6283e03a314d0c1\",\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"record_sha256\":\"d7a00ddda1c3b7afa99bb997fd9d88f864937a104e1b8cdd4370ebb914c6d306\"}],\"issued_at\":1789996400,\"schema\":\"auths.qualification-release-index/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"release-signer-2026-10\"}}" + "release_index": "{\"signature_b64\":\"CA6xsrEbfeBdNhtmWqR01vTD8Rh4tqH9xiKORfNaFa-URL_hS5mF3RqUA-6imag1YMvDcUEU2QLfqsmmu3dpBg\",\"statement\":{\"entries\":[{\"attestation_sha256\":\"53e358591892ff3a4733a7c685b5fcc5f36df1073c9813059f217ff28191fe18\",\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"record_sha256\":\"e5495a2c95356229a778d6781860eed872090ac5f4b6ac447953d353a3592f7a\"}],\"issued_at\":1789996400,\"schema\":\"auths.qualification-release-index/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"release-signer-2026-10\"}}" }, "expect": { "state": "candidate", @@ -169,7 +169,7 @@ "class": "forged", "replace": { "attestations": [ - "{\"signature_b64\":\"R1FKEhfbdJAcP8kb7xLiGwN9hhSHMedMtBB9toHgSqSXBW0OlAUFlAQTnvHmknYXPAFOghohkfPMw4jvYG-WCQ\",\"statement\":{\"issued_at\":1789992801,\"not_after\":1797768800,\"not_before\":1789992800,\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"record_sha256\":\"d7a00ddda1c3b7afa99bb997fd9d88f864937a104e1b8cdd4370ebb914c6d306\",\"schema\":\"auths.recipe-qualification-attestation/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"release-signer-2026-10\"}}" + "{\"signature_b64\":\"Byp9otAfoNdjUbZD0Fa0L3phBk8rgRCuRd4OwQdt0ja_anYDYlGYW9tBXAXCv6IX5uRWK_m5qh4RbJKQeHDaDA\",\"statement\":{\"issued_at\":1789992801,\"not_after\":1797768800,\"not_before\":1789992800,\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"record_sha256\":\"e5495a2c95356229a778d6781860eed872090ac5f4b6ac447953d353a3592f7a\",\"schema\":\"auths.recipe-qualification-attestation/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"release-signer-2026-10\"}}" ] }, "expect": { @@ -183,9 +183,9 @@ "class": "forged", "replace": { "attestations": [ - "{\"signature_b64\":\"tzcnurCZt_J1H8Fl3TWa5iHZUjpsmYzQIJK61c72CyZ4jSfAsEAYCWVXCASF7zbmHdsCLu6NE4vJ0-hUmAK3DQ\",\"statement\":{\"issued_at\":1789992800,\"not_after\":1797768800,\"not_before\":1789992800,\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"record_sha256\":\"d7a00ddda1c3b7afa99bb997fd9d88f864937a104e1b8cdd4370ebb914c6d306\",\"schema\":\"auths.recipe-qualification-attestation/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"release-signer-2026-10\"}}" + "{\"signature_b64\":\"xrJ1DFsrecZJ1w6RIfbOj1yQ9l-ZcrDRqHPZYP_Cqo1kj9G1Rc2FTRB6O05b_znhal3O9knMDlDpey-_hC4vBg\",\"statement\":{\"issued_at\":1789992800,\"not_after\":1797768800,\"not_before\":1789992800,\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"record_sha256\":\"e5495a2c95356229a778d6781860eed872090ac5f4b6ac447953d353a3592f7a\",\"schema\":\"auths.recipe-qualification-attestation/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"release-signer-2026-10\"}}" ], - "release_index": "{\"signature_b64\":\"Z3UjHuk0P1vXwp3sdRugtrOMMqphXGjTUM0z84-x_sT8FcwD1lFl02AXCEHk3rVBIWsgYolMjd90Ixr3_IgLAA\",\"statement\":{\"entries\":[{\"attestation_sha256\":\"6f0acc99bc26bd63fad9cecd15cfcb3d1986b2a92caea30d5955c10997a67d2c\",\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"record_sha256\":\"d7a00ddda1c3b7afa99bb997fd9d88f864937a104e1b8cdd4370ebb914c6d306\"}],\"issued_at\":1789996400,\"schema\":\"auths.qualification-release-index/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"release-signer-2026-10\"}}" + "release_index": "{\"signature_b64\":\"_5fxI4CUWG1x39gELCP_b6Tgh0TH_Slt2K9dd6PdCt8Hp7rMB9GLSmqIBCbVYxrZP2wE5RbXaIrZPmzmrt0OAg\",\"statement\":{\"entries\":[{\"attestation_sha256\":\"8a24fea63afbe047524b68b394f957b8530a6fbbc78ad4defec2d39dd2a4de80\",\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"record_sha256\":\"e5495a2c95356229a778d6781860eed872090ac5f4b6ac447953d353a3592f7a\"}],\"issued_at\":1789996400,\"schema\":\"auths.qualification-release-index/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"release-signer-2026-10\"}}" }, "expect": { "state": "candidate", @@ -197,7 +197,7 @@ "id": "index-signature-forged", "class": "forged", "replace": { - "release_index": "{\"signature_b64\":\"QcMwlBk-GT36P5vZFGmqwVaI6dSlhiDIy6b69926s_4UkaNLW8VDkrCtAQtedDPG_B7Mwa7vteWiAtHHGJSuCQ\",\"statement\":{\"entries\":[{\"attestation_sha256\":\"70d270e747fcf8bca9f408758ddcc1cd4470bd0dc8fa675ea68ce960146c8bbd\",\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"record_sha256\":\"d7a00ddda1c3b7afa99bb997fd9d88f864937a104e1b8cdd4370ebb914c6d306\"}],\"issued_at\":1789996400,\"schema\":\"auths.qualification-release-index/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"release-signer-2026-10\"}}" + "release_index": "{\"signature_b64\":\"qbnnKRCjNPMQ4E4htzwihMF_RcLGUtZ-QpmUc0xvAf9So4UwLqsqnQ8iE7KQDBPiDDEaT2tXMdXo8UJx7BKoCw\",\"statement\":{\"entries\":[{\"attestation_sha256\":\"00449fd858186bb6711b8697f6ea376b5c6a99ef79e0443c6ccc23a1a36e8c82\",\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"record_sha256\":\"e5495a2c95356229a778d6781860eed872090ac5f4b6ac447953d353a3592f7a\"}],\"issued_at\":1789996400,\"schema\":\"auths.qualification-release-index/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"release-signer-2026-10\"}}" }, "expect": { "state": "unqualified", @@ -209,7 +209,7 @@ "id": "index-signed-by-outsider", "class": "forged", "replace": { - "release_index": "{\"signature_b64\":\"-nPEtyUDG04UApIHZlHnf5R1lKwJU8hGCHRJKEKeFb-ncon0AbR0dylkcpWL6ZuWqhTY5bPxxy42-TBTis5oAg\",\"statement\":{\"entries\":[{\"attestation_sha256\":\"70d270e747fcf8bca9f408758ddcc1cd4470bd0dc8fa675ea68ce960146c8bbd\",\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"record_sha256\":\"d7a00ddda1c3b7afa99bb997fd9d88f864937a104e1b8cdd4370ebb914c6d306\"}],\"issued_at\":1789996400,\"schema\":\"auths.qualification-release-index/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"release-signer-2026-10\"}}" + "release_index": "{\"signature_b64\":\"1keFTCfs9mQxuQntTNOv_W9vqciC-oCRxxlVQrP2XpM23XoFBpxPEVPX25YGxZxGfByqeTTjvrzqEt8x5M0HCQ\",\"statement\":{\"entries\":[{\"attestation_sha256\":\"00449fd858186bb6711b8697f6ea376b5c6a99ef79e0443c6ccc23a1a36e8c82\",\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"record_sha256\":\"e5495a2c95356229a778d6781860eed872090ac5f4b6ac447953d353a3592f7a\"}],\"issued_at\":1789996400,\"schema\":\"auths.qualification-release-index/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"release-signer-2026-10\"}}" }, "expect": { "state": "unqualified", @@ -294,9 +294,9 @@ "class": "forged", "replace": { "attestations": [ - "{\"signature_b64\":\"V5BF5MUPBjm5Ub5-lzccpMHE0xVTpIri4atA0L1fadeyRO8Hsdp3VYzGfEzvUFjup2xN1Ux3RjI7Qfl4UnDhCQ\",\"statement\":{\"issued_at\":1789992800,\"not_after\":1797768800,\"not_before\":1789992800,\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"record_sha256\":\"d7a00ddda1c3b7afa99bb997fd9d88f864937a104e1b8cdd4370ebb914c6d306\",\"schema\":\"auths.recipe-qualification-attestation/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"another-signer\"}}" + "{\"signature_b64\":\"In_Pz4oSQhgTnbrScTBPACd3JNgcw7VDY4468cZMWvsjA-pzYcdCC_SGJHjaHn_LZ4FjVxd4Vv_8EOL41c4hDw\",\"statement\":{\"issued_at\":1789992800,\"not_after\":1797768800,\"not_before\":1789992800,\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"record_sha256\":\"e5495a2c95356229a778d6781860eed872090ac5f4b6ac447953d353a3592f7a\",\"schema\":\"auths.recipe-qualification-attestation/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"another-signer\"}}" ], - "release_index": "{\"signature_b64\":\"CXyGKmB8x1kZA5ZR6UuoGTRfNORjBP1mGycIBj65v_NLaczM4IGAoZgSamxaEnUxOxdf8gJ3TcuDLrL0SZM1Bw\",\"statement\":{\"entries\":[{\"attestation_sha256\":\"894dd22628c540c13068386485c8fc9b6d104bb4b59906f6246519f4e61cd615\",\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"record_sha256\":\"d7a00ddda1c3b7afa99bb997fd9d88f864937a104e1b8cdd4370ebb914c6d306\"}],\"issued_at\":1789996400,\"schema\":\"auths.qualification-release-index/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"release-signer-2026-10\"}}" + "release_index": "{\"signature_b64\":\"PU3HBBhvW9glWplV0oZMyXhF56jPQagnXK9dXP_9IPNHLkNerKW02skNwEVq-YYiq5XZJb8wqsRYw5d32EBmCg\",\"statement\":{\"entries\":[{\"attestation_sha256\":\"b845e328d0333fefb98b407f35e2e7e0f23ad4cdcd2855f60ba858dc16c93b13\",\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"record_sha256\":\"e5495a2c95356229a778d6781860eed872090ac5f4b6ac447953d353a3592f7a\"}],\"issued_at\":1789996400,\"schema\":\"auths.qualification-release-index/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"release-signer-2026-10\"}}" }, "expect": { "state": "candidate", @@ -311,7 +311,7 @@ "attestations": [ "{\"signature_b64\":\"dU8UPdRvQ6Xr6xCtRvpnj5HT5oD_oPcTI1sc3fnHTzNL-eenyjjdJOq0-0wBZicAH4uVvsJV2LmcnPmcRaXXBQ\",\"statement\":{\"issued_at\":1789992800,\"not_after\":1797768800,\"not_before\":1789992800,\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"record_sha256\":\"1bc3a22a5bba0537b35bcb4db6ec7a29fafb9deae8f5f964919628c38654c42d\",\"schema\":\"auths.recipe-qualification-attestation/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"release-signer-2026-10\"}}" ], - "release_index": "{\"signature_b64\":\"0J5IWbuqUb1iNmNmbdPpIUTc_HcvcnJdhPOJaZnqTbP4G9wSmeqTX6U9Or3zZQKWg6L8bbylelLDYmLdwiQtDw\",\"statement\":{\"entries\":[{\"attestation_sha256\":\"b349ee3d88adb475afa1ffabc89b76c010c1d890cc3ccf8ebe282f0e7cdece3f\",\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"record_sha256\":\"d7a00ddda1c3b7afa99bb997fd9d88f864937a104e1b8cdd4370ebb914c6d306\"}],\"issued_at\":1789996400,\"schema\":\"auths.qualification-release-index/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"release-signer-2026-10\"}}" + "release_index": "{\"signature_b64\":\"C_W4OzY5dDjLR_EZAJYZqTKSJVJgs233eInKoc-aMIEPgO202P8lpu5echZJ7Yboh-_xZOegNojFccXqf2d-AQ\",\"statement\":{\"entries\":[{\"attestation_sha256\":\"b349ee3d88adb475afa1ffabc89b76c010c1d890cc3ccf8ebe282f0e7cdece3f\",\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"record_sha256\":\"e5495a2c95356229a778d6781860eed872090ac5f4b6ac447953d353a3592f7a\"}],\"issued_at\":1789996400,\"schema\":\"auths.qualification-release-index/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"release-signer-2026-10\"}}" }, "expect": { "state": "candidate", @@ -324,12 +324,12 @@ "class": "widened-time-bound", "replace": { "records": [ - "{\"capabilities\":[{\"capability\":\"credential-guard\",\"result\":\"exercised\"},{\"capability\":\"version-pin\",\"result\":\"exercised\"},{\"capability\":\"account-binding\",\"reason\":\"the qualified recipe and target declare none\",\"result\":\"not-applicable\"},{\"capability\":\"denied-reads\",\"result\":\"exercised\"},{\"capability\":\"ceiling\",\"result\":\"exercised\"},{\"capability\":\"budget\",\"result\":\"exercised\"},{\"capability\":\"idempotency\",\"result\":\"exercised\"},{\"capability\":\"response-locator\",\"result\":\"exercised\"},{\"capability\":\"echo\",\"result\":\"exercised\"},{\"capability\":\"observation\",\"result\":\"exercised\"},{\"capability\":\"recovery\",\"result\":\"exercised\"},{\"capability\":\"observer-rotation\",\"reason\":\"the qualified recipe and target declare none\",\"result\":\"not-applicable\"}],\"corpus_manifest_sha256\":\"d6c1cad9a6b0fe0fc27d1f8107c2381e8b9ab1bbfc04a47aa8234140de74a23f\",\"custody_descriptor\":\"aws-secrets-manager-v1 with workload identity\",\"evidence\":[{\"cases\":12,\"evidence_sha256\":\"c3a2a799eb04b1ee53a22495e0d95171a9f42f2ad557b639f3fe5440bbed90e7\",\"member\":\"conformance\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"dfd5b5dccc73cae91abec7a76c332dae145eb37eddb18f56dca2e68f2dbc81ab\",\"member\":\"differential\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"a05d5182b4f20eb67c0d95622a70f1e4ac87d1d1b8b7fab219a2276b6da41256\",\"member\":\"hostile\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"00beb3d9e44f8d20d5da8861818ecd7b430714f959a6613dbd2d870997eb90f8\",\"member\":\"live\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"3a4e01d7b8d11480e334d0d2fffc2efeeaf2363d21f9107094c3cfc3c063b362\",\"member\":\"recovery\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"6b428d653e06c75268e2e33f234f30f9cc24616c42faf551699f7a7ac2376011\",\"member\":\"rotation\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"e8713a54bfb187836d4db2f34f181129f2e03f7221bc2d3247134470adcacee8\",\"member\":\"restart\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"8824a7669543ecf652b651fa2d370c548e09b73c1babac841cd689389a1fdcbe\",\"member\":\"multi-instance\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"f31f29dc30a4e8ccd3aea69c012656c2811ac194881147b2cced5dd7dc1a7d9b\",\"member\":\"redaction\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"8e91fde286bdbb80e6d6245e7ab9dab68f92e790922170195fc80aab2eeb227b\",\"member\":\"installed-consumer\",\"result\":\"passed\",\"unauthorized_provider_entries\":0}],\"excluded_claims\":[\"the provider performed or settled the business effect\"],\"generated_artifacts_sha256\":\"fff3ece48e4f5271825e80b355a1243a4c30619329bbbc70bc4e5c1b242973e2\",\"installed_packages\":[{\"name\":\"auths-gateway\",\"sha256\":\"8a58d99c69c098e53c2197df2c6a6a16b131c69798f728db134c978f77e95360\",\"version\":\"1.0.0-rc.1\"},{\"name\":\"auths-python\",\"sha256\":\"59b028e3e66e681bfa195fb6afee775b91f30fc418f05f86353bc71cd021d2f9\",\"version\":\"1.0.0rc1\"}],\"live_effects\":{\"confirmed_by_read_back\":4,\"entered\":4},\"not_after\":1795176800,\"not_before\":1789992800,\"provenance\":{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"environment\":\"recipe-qualification\",\"repository\":\"github.com/auths-dev/auths-proof\",\"workflow\":\".github/workflows/recipe-qualification.yml\"},\"provider_kind\":\"example-payments\",\"provider_resources\":[\"refund:fixture-0001\",\"refund:fixture-0002\"],\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"recipe_decision_record_sha256\":\"0c2328dfcdc21fcd917fd242dd16f9adf1354395a472e589e2778dee99527081\",\"residual_assumptions\":[\"the provider keeps its test mode separate from live data\"],\"schema\":\"auths.recipe-qualification/1\",\"source_closure_sha256\":\"00023b3a6fbf90b531085365646cda2ffcac182f6eaedf453eb680b63ae33106\",\"store_descriptor\":\"postgresql 16 with TLS\",\"tuple\":{\"compiled_recipe_sha256\":\"262f5ef11b349645f2421c533220fc6bbfd70c4a5395f5d65c601406eba7d4ef\",\"gateway_semantic_closure_sha256\":\"01ec13346b098e4f5e1c64a995a50ce15ef339dc1f304966a45c94e80638203b\",\"profile_lock_sha256\":\"4dd8982feedb83403f985de3e1a952a90060e44035ab797e5313ff93957a22d5\",\"provider_contract_id\":\"f15f154a38de58de1b27c70c61a6b20fe532746e2e4462576dbd3d27d76cce3d\",\"recipe_family\":\"example-refund-v1\",\"target\":{\"arch\":\"x86_64\",\"credential_store_kind\":\"aws-secrets-manager-v1\",\"gateway_build_sha256\":\"42194bc83fbd821aaede008519091b4516baf914f8c2e27f3f2ac7a25f7485c3\",\"gateway_package\":\"auths-gateway\",\"gateway_version\":\"1.0.0-rc.1\",\"os\":\"linux\",\"store_kind\":\"postgresql-v1\",\"store_schema\":\"auths.lifecycle.postgresql/5\"}}}" + "{\"capabilities\":[{\"capability\":\"credential-guard\",\"result\":\"exercised\"},{\"capability\":\"version-pin\",\"result\":\"exercised\"},{\"capability\":\"account-binding\",\"reason\":\"the qualified recipe and target declare none\",\"result\":\"not-applicable\"},{\"capability\":\"denied-reads\",\"result\":\"exercised\"},{\"capability\":\"ceiling\",\"result\":\"exercised\"},{\"capability\":\"budget\",\"result\":\"exercised\"},{\"capability\":\"idempotency\",\"result\":\"exercised\"},{\"capability\":\"response-locator\",\"result\":\"exercised\"},{\"capability\":\"echo\",\"result\":\"exercised\"},{\"capability\":\"observation\",\"result\":\"exercised\"},{\"capability\":\"recovery\",\"result\":\"exercised\"},{\"capability\":\"observer-rotation\",\"reason\":\"the qualified recipe and target declare none\",\"result\":\"not-applicable\"}],\"corpus_manifest_sha256\":\"d6c1cad9a6b0fe0fc27d1f8107c2381e8b9ab1bbfc04a47aa8234140de74a23f\",\"custody_descriptor\":\"aws-secrets-manager-v1 with workload identity\",\"evidence\":[{\"cases\":12,\"evidence_sha256\":\"c3a2a799eb04b1ee53a22495e0d95171a9f42f2ad557b639f3fe5440bbed90e7\",\"member\":\"conformance\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"dfd5b5dccc73cae91abec7a76c332dae145eb37eddb18f56dca2e68f2dbc81ab\",\"member\":\"differential\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"a05d5182b4f20eb67c0d95622a70f1e4ac87d1d1b8b7fab219a2276b6da41256\",\"member\":\"hostile\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"00beb3d9e44f8d20d5da8861818ecd7b430714f959a6613dbd2d870997eb90f8\",\"member\":\"live\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"3a4e01d7b8d11480e334d0d2fffc2efeeaf2363d21f9107094c3cfc3c063b362\",\"member\":\"recovery\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"6b428d653e06c75268e2e33f234f30f9cc24616c42faf551699f7a7ac2376011\",\"member\":\"rotation\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"e8713a54bfb187836d4db2f34f181129f2e03f7221bc2d3247134470adcacee8\",\"member\":\"restart\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"8824a7669543ecf652b651fa2d370c548e09b73c1babac841cd689389a1fdcbe\",\"member\":\"multi-instance\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"f31f29dc30a4e8ccd3aea69c012656c2811ac194881147b2cced5dd7dc1a7d9b\",\"member\":\"redaction\",\"result\":\"passed\",\"unauthorized_provider_entries\":0},{\"cases\":12,\"evidence_sha256\":\"8e91fde286bdbb80e6d6245e7ab9dab68f92e790922170195fc80aab2eeb227b\",\"member\":\"installed-consumer\",\"result\":\"passed\",\"unauthorized_provider_entries\":0}],\"excluded_claims\":[\"the provider performed or settled the business effect\"],\"generated_artifacts_sha256\":\"fff3ece48e4f5271825e80b355a1243a4c30619329bbbc70bc4e5c1b242973e2\",\"installed_packages\":[{\"name\":\"auths-gateway\",\"sha256\":\"8a58d99c69c098e53c2197df2c6a6a16b131c69798f728db134c978f77e95360\",\"version\":\"1.0.0-rc.1\"},{\"name\":\"auths-python\",\"sha256\":\"59b028e3e66e681bfa195fb6afee775b91f30fc418f05f86353bc71cd021d2f9\",\"version\":\"1.0.0rc1\"}],\"live_effects\":{\"confirmed_by_read_back\":4,\"entered\":4},\"not_after\":1795176800,\"not_before\":1789992800,\"provenance\":{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"environment\":\"recipe-qualification\",\"repository\":\"github.com/auths-dev/auths-proof\",\"workflow\":\".github/workflows/recipe-qualification.yml\"},\"provider_kind\":\"example-payments\",\"provider_resources\":[\"refund:fixture-0001\",\"refund:fixture-0002\"],\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"recipe_decision_record_sha256\":\"0c2328dfcdc21fcd917fd242dd16f9adf1354395a472e589e2778dee99527081\",\"residual_assumptions\":[\"the provider keeps its test mode separate from live data\"],\"schema\":\"auths.recipe-qualification/1\",\"source_closure_sha256\":\"00023b3a6fbf90b531085365646cda2ffcac182f6eaedf453eb680b63ae33106\",\"store_descriptor\":\"postgresql 16 with TLS\",\"tuple\":{\"compiled_recipe_sha256\":\"262f5ef11b349645f2421c533220fc6bbfd70c4a5395f5d65c601406eba7d4ef\",\"gateway_semantic_closure_sha256\":\"01ec13346b098e4f5e1c64a995a50ce15ef339dc1f304966a45c94e80638203b\",\"profile_lock_sha256\":\"4dd8982feedb83403f985de3e1a952a90060e44035ab797e5313ff93957a22d5\",\"provider_contract_id\":\"f15f154a38de58de1b27c70c61a6b20fe532746e2e4462576dbd3d27d76cce3d\",\"recipe_family\":\"example-refund-v1\",\"target\":{\"arch\":\"x86_64\",\"credential_store_kind\":\"aws-secrets-manager-v1\",\"gateway_build_sha256\":\"42194bc83fbd821aaede008519091b4516baf914f8c2e27f3f2ac7a25f7485c3\",\"gateway_package\":\"auths-gateway\",\"gateway_version\":\"1.0.0-rc.1\",\"os\":\"linux\",\"store_kind\":\"postgresql-v1\",\"store_schema\":\"auths.lifecycle.postgresql/6\"}}}" ], "attestations": [ - "{\"signature_b64\":\"Ia1VvfmqFwQ0O85MZACdtP4fh44y578C1Mq0yHD2j7rog2-txQvDKQ_Wu8uULzx7Qr-xWOck57mB6mzqNgLKCA\",\"statement\":{\"issued_at\":1789992800,\"not_after\":1797768800,\"not_before\":1789992800,\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"record_sha256\":\"e583292fbd3825d1086ba3c2d947266c028d90d3ddaf9403508d608d8e0b58bd\",\"schema\":\"auths.recipe-qualification-attestation/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"release-signer-2026-10\"}}" + "{\"signature_b64\":\"llV5lBszVwmOYM3A6diwpACMWJ5B9H9sFvFfnthdn43G-Vv3jlMPEW1L6opboExmUFvpLvVrX85k5sh-y7mWDw\",\"statement\":{\"issued_at\":1789992800,\"not_after\":1797768800,\"not_before\":1789992800,\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"record_sha256\":\"10cc5b9573f799fbe2edb24ca401950b782e399001276c2a6b010040154499dc\",\"schema\":\"auths.recipe-qualification-attestation/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"release-signer-2026-10\"}}" ], - "release_index": "{\"signature_b64\":\"5rQjGHQ6GOcaSBbqGyNv0jABP3vEhVMEMyQZp7G3oKoVvLyGqbumsZzXyYiuA-I9EZojuc7RczF57DMOzjFGCw\",\"statement\":{\"entries\":[{\"attestation_sha256\":\"68682e0648cdc765e36a4baf88d5503dfa0a5a463b06cda441404120bb5125b0\",\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"record_sha256\":\"e583292fbd3825d1086ba3c2d947266c028d90d3ddaf9403508d608d8e0b58bd\"}],\"issued_at\":1789996400,\"schema\":\"auths.qualification-release-index/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"release-signer-2026-10\"}}" + "release_index": "{\"signature_b64\":\"02dWO040SWUrdjFYAEGatWBeF4ISg4xINKvFWUG-q1lY2nN-pHRhyC4-qEib7YaWeSLuvfOFFr5CXuiyCkg8DQ\",\"statement\":{\"entries\":[{\"attestation_sha256\":\"10dfac2b1176c1a877f5f2cba5ced11a6f2e38f1d634c3d7f764e1651997d568\",\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"record_sha256\":\"10cc5b9573f799fbe2edb24ca401950b782e399001276c2a6b010040154499dc\"}],\"issued_at\":1789996400,\"schema\":\"auths.qualification-release-index/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"release-signer-2026-10\"}}" }, "expect": { "state": "candidate", @@ -342,9 +342,9 @@ "class": "not-yet-valid", "replace": { "attestations": [ - "{\"signature_b64\":\"Gsrdvv__DJeV8jD_wIXrkKcxgAGGyCBbDvvI7oNWcpMogBOaoa4Wi0MQg9-gX8WUiuZUMKh-Mpb_V7IXFnn5DQ\",\"statement\":{\"issued_at\":1789992800,\"not_after\":1792595600,\"not_before\":1790003600,\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"record_sha256\":\"d7a00ddda1c3b7afa99bb997fd9d88f864937a104e1b8cdd4370ebb914c6d306\",\"schema\":\"auths.recipe-qualification-attestation/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"release-signer-2026-10\"}}" + "{\"signature_b64\":\"xhMqiwUs1yCbR0ebhIO4hWPvROOx8HJVvQiAco5fKOF54wRuuJGH6hGsiNdbNPB4PdzsVE4CP8Ufv57b5fl8AQ\",\"statement\":{\"issued_at\":1789992800,\"not_after\":1792595600,\"not_before\":1790003600,\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"record_sha256\":\"e5495a2c95356229a778d6781860eed872090ac5f4b6ac447953d353a3592f7a\",\"schema\":\"auths.recipe-qualification-attestation/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"release-signer-2026-10\"}}" ], - "release_index": "{\"signature_b64\":\"oujpkbId3SweB5yGLpxYF9rBhcNQVQyJwZY5Q5dIlhwmckTllgQS_1IJckUZOguE5n3vJHoDDF-O7t_EZwJQAg\",\"statement\":{\"entries\":[{\"attestation_sha256\":\"b54ecb7102d68cb90db11b02722bd3adf6d79250626fd99b2957e461f1c0f911\",\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"record_sha256\":\"d7a00ddda1c3b7afa99bb997fd9d88f864937a104e1b8cdd4370ebb914c6d306\"}],\"issued_at\":1789996400,\"schema\":\"auths.qualification-release-index/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"release-signer-2026-10\"}}" + "release_index": "{\"signature_b64\":\"Ue5Ra0u17IlVF3otp4TbGtiJgnHSeHUx-RMC-EtR__PKqKA0Gtli-OFtmufJCwiPlK2MNgUGU1gh2KbbTLthBg\",\"statement\":{\"entries\":[{\"attestation_sha256\":\"0ec2dfd894f7b1809e61d1e9c86a67ad61e83cea5bc7924d12d1dcfc7693f15b\",\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"record_sha256\":\"e5495a2c95356229a778d6781860eed872090ac5f4b6ac447953d353a3592f7a\"}],\"issued_at\":1789996400,\"schema\":\"auths.qualification-release-index/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"release-signer-2026-10\"}}" }, "expect": { "state": "candidate", @@ -368,7 +368,7 @@ "id": "unusable-index-before-revocation", "class": "precedence", "replace": { - "release_index": "{\"signature_b64\":\"QcMwlBk-GT36P5vZFGmqwVaI6dSlhiDIy6b69926s_4UkaNLW8VDkrCtAQtedDPG_B7Mwa7vteWiAtHHGJSuCQ\",\"statement\":{\"entries\":[{\"attestation_sha256\":\"70d270e747fcf8bca9f408758ddcc1cd4470bd0dc8fa675ea68ce960146c8bbd\",\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"record_sha256\":\"d7a00ddda1c3b7afa99bb997fd9d88f864937a104e1b8cdd4370ebb914c6d306\"}],\"issued_at\":1789996400,\"schema\":\"auths.qualification-release-index/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"release-signer-2026-10\"}}", + "release_index": "{\"signature_b64\":\"qbnnKRCjNPMQ4E4htzwihMF_RcLGUtZ-QpmUc0xvAf9So4UwLqsqnQ8iE7KQDBPiDDEaT2tXMdXo8UJx7BKoCw\",\"statement\":{\"entries\":[{\"attestation_sha256\":\"00449fd858186bb6711b8697f6ea376b5c6a99ef79e0443c6ccc23a1a36e8c82\",\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"record_sha256\":\"e5495a2c95356229a778d6781860eed872090ac5f4b6ac447953d353a3592f7a\"}],\"issued_at\":1789996400,\"schema\":\"auths.qualification-release-index/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"release-signer-2026-10\"}}", "revocation_list": "{\"root_signature_b64\":\"Oe8aY9Lt91XEvAJ86JGwNpAUwVl5WGvXfP3xvBIraeDWf8B0m0OPMVVmAp5WqglK8RDodbQ9g8CfDgAJI3coBg\",\"statement\":{\"issued_at\":1789996400,\"next_update\":1790255600,\"revoked_qualifications\":[\"qlf_01010101010101010101010101010101\"],\"revoked_signers\":[],\"root_id\":\"auths-qualification-root-1\",\"schema\":\"auths.qualification-revocation-list/1\",\"sequence\":7}}" }, "expect": { @@ -426,9 +426,9 @@ "class": "precedence", "replace": { "attestations": [ - "{\"signature_b64\":\"tzcnurCZt_J1H8Fl3TWa5iHZUjpsmYzQIJK61c72CyZ4jSfAsEAYCWVXCASF7zbmHdsCLu6NE4vJ0-hUmAK3DQ\",\"statement\":{\"issued_at\":1789992800,\"not_after\":1797768800,\"not_before\":1789992800,\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"record_sha256\":\"d7a00ddda1c3b7afa99bb997fd9d88f864937a104e1b8cdd4370ebb914c6d306\",\"schema\":\"auths.recipe-qualification-attestation/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"release-signer-2026-10\"}}" + "{\"signature_b64\":\"xrJ1DFsrecZJ1w6RIfbOj1yQ9l-ZcrDRqHPZYP_Cqo1kj9G1Rc2FTRB6O05b_znhal3O9knMDlDpey-_hC4vBg\",\"statement\":{\"issued_at\":1789992800,\"not_after\":1797768800,\"not_before\":1789992800,\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"record_sha256\":\"e5495a2c95356229a778d6781860eed872090ac5f4b6ac447953d353a3592f7a\",\"schema\":\"auths.recipe-qualification-attestation/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"release-signer-2026-10\"}}" ], - "release_index": "{\"signature_b64\":\"Z3UjHuk0P1vXwp3sdRugtrOMMqphXGjTUM0z84-x_sT8FcwD1lFl02AXCEHk3rVBIWsgYolMjd90Ixr3_IgLAA\",\"statement\":{\"entries\":[{\"attestation_sha256\":\"6f0acc99bc26bd63fad9cecd15cfcb3d1986b2a92caea30d5955c10997a67d2c\",\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"record_sha256\":\"d7a00ddda1c3b7afa99bb997fd9d88f864937a104e1b8cdd4370ebb914c6d306\"}],\"issued_at\":1789996400,\"schema\":\"auths.qualification-release-index/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"release-signer-2026-10\"}}", + "release_index": "{\"signature_b64\":\"_5fxI4CUWG1x39gELCP_b6Tgh0TH_Slt2K9dd6PdCt8Hp7rMB9GLSmqIBCbVYxrZP2wE5RbXaIrZPmzmrt0OAg\",\"statement\":{\"entries\":[{\"attestation_sha256\":\"8a24fea63afbe047524b68b394f957b8530a6fbbc78ad4defec2d39dd2a4de80\",\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"record_sha256\":\"e5495a2c95356229a778d6781860eed872090ac5f4b6ac447953d353a3592f7a\"}],\"issued_at\":1789996400,\"schema\":\"auths.qualification-release-index/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"release-signer-2026-10\"}}", "now": 1790255601 }, "expect": { @@ -442,9 +442,9 @@ "class": "precedence", "replace": { "attestations": [ - "{\"signature_b64\":\"tzcnurCZt_J1H8Fl3TWa5iHZUjpsmYzQIJK61c72CyZ4jSfAsEAYCWVXCASF7zbmHdsCLu6NE4vJ0-hUmAK3DQ\",\"statement\":{\"issued_at\":1789992800,\"not_after\":1797768800,\"not_before\":1789992800,\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"record_sha256\":\"d7a00ddda1c3b7afa99bb997fd9d88f864937a104e1b8cdd4370ebb914c6d306\",\"schema\":\"auths.recipe-qualification-attestation/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"release-signer-2026-10\"}}" + "{\"signature_b64\":\"xrJ1DFsrecZJ1w6RIfbOj1yQ9l-ZcrDRqHPZYP_Cqo1kj9G1Rc2FTRB6O05b_znhal3O9knMDlDpey-_hC4vBg\",\"statement\":{\"issued_at\":1789992800,\"not_after\":1797768800,\"not_before\":1789992800,\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"record_sha256\":\"e5495a2c95356229a778d6781860eed872090ac5f4b6ac447953d353a3592f7a\",\"schema\":\"auths.recipe-qualification-attestation/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"release-signer-2026-10\"}}" ], - "release_index": "{\"signature_b64\":\"Z3UjHuk0P1vXwp3sdRugtrOMMqphXGjTUM0z84-x_sT8FcwD1lFl02AXCEHk3rVBIWsgYolMjd90Ixr3_IgLAA\",\"statement\":{\"entries\":[{\"attestation_sha256\":\"6f0acc99bc26bd63fad9cecd15cfcb3d1986b2a92caea30d5955c10997a67d2c\",\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"record_sha256\":\"d7a00ddda1c3b7afa99bb997fd9d88f864937a104e1b8cdd4370ebb914c6d306\"}],\"issued_at\":1789996400,\"schema\":\"auths.qualification-release-index/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"release-signer-2026-10\"}}", + "release_index": "{\"signature_b64\":\"_5fxI4CUWG1x39gELCP_b6Tgh0TH_Slt2K9dd6PdCt8Hp7rMB9GLSmqIBCbVYxrZP2wE5RbXaIrZPmzmrt0OAg\",\"statement\":{\"entries\":[{\"attestation_sha256\":\"8a24fea63afbe047524b68b394f957b8530a6fbbc78ad4defec2d39dd2a4de80\",\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"record_sha256\":\"e5495a2c95356229a778d6781860eed872090ac5f4b6ac447953d353a3592f7a\"}],\"issued_at\":1789996400,\"schema\":\"auths.qualification-release-index/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"release-signer-2026-10\"}}", "signer_certificate": "{\"root_signature_b64\":\"AzUQnJwFYUZzLtBZTs8b0R2kt6nvkhJoBbMttBXnyAP7dSk7rVfe7sZQxD4Laerbyc7jgH4yzz1dUWdEOfscDA\",\"statement\":{\"issued_at\":1787408000,\"not_after\":1789999999,\"not_before\":1787408000,\"permitted_artifact_kinds\":[\"qualification-release-index\",\"recipe-qualification-attestation\"],\"public_key_b64\":\"oJql9HpnWYAv-VX43C0qFKXJnSO-l_hkEn_5ODRVpPA\",\"root_id\":\"auths-qualification-root-1\",\"schema\":\"auths.qualification-signer-certificate/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"release-signer-2026-10\",\"signer_kind\":\"protected-software-release-key-v1\"}}" }, "expect": { @@ -472,7 +472,7 @@ "gateway_version": "1.0.0-rc.1", "gateway_build_sha256": "42194bc83fbd821aaede008519091b4516baf914f8c2e27f3f2ac7a25f7485c3", "store_kind": "postgresql-v1", - "store_schema": "auths.lifecycle.postgresql/5", + "store_schema": "auths.lifecycle.postgresql/6", "credential_store_kind": "aws-secrets-manager-v1" } } @@ -548,7 +548,7 @@ "id": "index-issued-ahead", "class": "future-issued-at", "replace": { - "release_index": "{\"signature_b64\":\"iFZllyzGcs8v1ERP6LPKqjA6kvxnE5uOQjB8FySMUWiJgJew4OOVPpjTXU0S2f3r61bq0TdsLQdnMF7KTi8ECQ\",\"statement\":{\"entries\":[{\"attestation_sha256\":\"70d270e747fcf8bca9f408758ddcc1cd4470bd0dc8fa675ea68ce960146c8bbd\",\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"record_sha256\":\"d7a00ddda1c3b7afa99bb997fd9d88f864937a104e1b8cdd4370ebb914c6d306\"}],\"issued_at\":1790000060,\"schema\":\"auths.qualification-release-index/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"release-signer-2026-10\"}}" + "release_index": "{\"signature_b64\":\"5taLptZFLigql-wheq4jrzJOZz6psUgXhzyzXzAgIuvuHx7bSgLdWS3PCFCMgooFSKE4-Z-IFgUbVISrNZngCA\",\"statement\":{\"entries\":[{\"attestation_sha256\":\"00449fd858186bb6711b8697f6ea376b5c6a99ef79e0443c6ccc23a1a36e8c82\",\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"record_sha256\":\"e5495a2c95356229a778d6781860eed872090ac5f4b6ac447953d353a3592f7a\"}],\"issued_at\":1790000060,\"schema\":\"auths.qualification-release-index/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"release-signer-2026-10\"}}" }, "expect": { "state": "stale", @@ -561,9 +561,9 @@ "class": "future-issued-at", "replace": { "attestations": [ - "{\"signature_b64\":\"TMNaatveqBWAj3wsq4j1V7vVj9Tu-kZOFMwwXnQDXpQG0I0HURDFo1nF8nITAFoVGuutMmQbmZb_sFhRpZIWBQ\",\"statement\":{\"issued_at\":1790000060,\"not_after\":1797768800,\"not_before\":1789992800,\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"record_sha256\":\"d7a00ddda1c3b7afa99bb997fd9d88f864937a104e1b8cdd4370ebb914c6d306\",\"schema\":\"auths.recipe-qualification-attestation/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"release-signer-2026-10\"}}" + "{\"signature_b64\":\"1OYEnrP0APZgNIc9VFzQmKyYK-ltQO7ZjTduSVOzkNeQ0S8e2Ek4xFw2O3CyVfsajqVeHgDUPmDFsvWDBg-5Bw\",\"statement\":{\"issued_at\":1790000060,\"not_after\":1797768800,\"not_before\":1789992800,\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"record_sha256\":\"e5495a2c95356229a778d6781860eed872090ac5f4b6ac447953d353a3592f7a\",\"schema\":\"auths.recipe-qualification-attestation/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"release-signer-2026-10\"}}" ], - "release_index": "{\"signature_b64\":\"HNKdrtymwAkxEN7ZILJ6An0FAwpfCisSdASlzyWwTdxgS4mIh0iL9c5U2QGPL9HqK8UCPSoJ9gDfniyOez6JBA\",\"statement\":{\"entries\":[{\"attestation_sha256\":\"3015c776a66528d143ce6702186d944e11bca8f210e80123585679a664a68700\",\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"record_sha256\":\"d7a00ddda1c3b7afa99bb997fd9d88f864937a104e1b8cdd4370ebb914c6d306\"}],\"issued_at\":1789996400,\"schema\":\"auths.qualification-release-index/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"release-signer-2026-10\"}}" + "release_index": "{\"signature_b64\":\"QMiLn3BFlwLUUJctksJ9mbmwNJ8IEF5A1D-yy13oE2yuxvABWwZT-4Vw_N4onw1SrMY86a650H6xCqSUy9QNBQ\",\"statement\":{\"entries\":[{\"attestation_sha256\":\"9d6bfaadd23e3be7ce7320fa6ad7779384a3187c7713856b5b12aa5728e86c32\",\"qualification_id\":\"qlf_01010101010101010101010101010101\",\"record_sha256\":\"e5495a2c95356229a778d6781860eed872090ac5f4b6ac447953d353a3592f7a\"}],\"issued_at\":1789996400,\"schema\":\"auths.qualification-release-index/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"release-signer-2026-10\"}}" }, "expect": { "state": "stale", @@ -637,7 +637,7 @@ "gateway_version": "1.0.0-rc.1", "gateway_build_sha256": "42194bc83fbd821aaede008519091b4516baf914f8c2e27f3f2ac7a25f7485c3", "store_kind": "postgresql-v1", - "store_schema": "auths.lifecycle.postgresql/5", + "store_schema": "auths.lifecycle.postgresql/6", "credential_store_kind": "aws-secrets-manager-v1" } }, @@ -740,7 +740,7 @@ "gateway_version": "1.0.0-rc.1", "gateway_build_sha256": "42194bc83fbd821aaede008519091b4516baf914f8c2e27f3f2ac7a25f7485c3", "store_kind": "postgresql-v1", - "store_schema": "auths.lifecycle.postgresql/5", + "store_schema": "auths.lifecycle.postgresql/6", "credential_store_kind": "aws-secrets-manager-v1" } } @@ -768,7 +768,7 @@ "gateway_version": "1.0.0-rc.1", "gateway_build_sha256": "42194bc83fbd821aaede008519091b4516baf914f8c2e27f3f2ac7a25f7485c3", "store_kind": "postgresql-v1", - "store_schema": "auths.lifecycle.postgresql/5", + "store_schema": "auths.lifecycle.postgresql/6", "credential_store_kind": "aws-secrets-manager-v1" } } @@ -796,7 +796,7 @@ "gateway_version": "1.0.0-rc.1", "gateway_build_sha256": "42194bc83fbd821aaede008519091b4516baf914f8c2e27f3f2ac7a25f7485c3", "store_kind": "postgresql-v1", - "store_schema": "auths.lifecycle.postgresql/5", + "store_schema": "auths.lifecycle.postgresql/6", "credential_store_kind": "aws-secrets-manager-v1" } } @@ -824,7 +824,7 @@ "gateway_version": "1.0.0-rc.1", "gateway_build_sha256": "42194bc83fbd821aaede008519091b4516baf914f8c2e27f3f2ac7a25f7485c3", "store_kind": "postgresql-v1", - "store_schema": "auths.lifecycle.postgresql/5", + "store_schema": "auths.lifecycle.postgresql/6", "credential_store_kind": "aws-secrets-manager-v1" } } @@ -852,7 +852,7 @@ "gateway_version": "1.0.0-rc.1", "gateway_build_sha256": "42194bc83fbd821aaede008519091b4516baf914f8c2e27f3f2ac7a25f7485c3", "store_kind": "postgresql-v1", - "store_schema": "auths.lifecycle.postgresql/5", + "store_schema": "auths.lifecycle.postgresql/6", "credential_store_kind": "aws-secrets-manager-v1" } } @@ -880,7 +880,7 @@ "gateway_version": "1.0.0-rc.1", "gateway_build_sha256": "42194bc83fbd821aaede008519091b4516baf914f8c2e27f3f2ac7a25f7485c3", "store_kind": "postgresql-v1", - "store_schema": "auths.lifecycle.postgresql/5", + "store_schema": "auths.lifecycle.postgresql/6", "credential_store_kind": "aws-secrets-manager-v1" } } @@ -908,7 +908,7 @@ "gateway_version": "1.0.0-rc.1", "gateway_build_sha256": "42194bc83fbd821aaede008519091b4516baf914f8c2e27f3f2ac7a25f7485c3", "store_kind": "postgresql-v1", - "store_schema": "auths.lifecycle.postgresql/5", + "store_schema": "auths.lifecycle.postgresql/6", "credential_store_kind": "aws-secrets-manager-v1" } } @@ -936,7 +936,7 @@ "gateway_version": "1.0.0-rc.1", "gateway_build_sha256": "42194bc83fbd821aaede008519091b4516baf914f8c2e27f3f2ac7a25f7485c3", "store_kind": "postgresql-v1", - "store_schema": "auths.lifecycle.postgresql/5", + "store_schema": "auths.lifecycle.postgresql/6", "credential_store_kind": "aws-secrets-manager-v1" } } @@ -964,7 +964,7 @@ "gateway_version": "1.0.0-rc.1", "gateway_build_sha256": "245f158f0e08031548685ae415e98194feb1831db12f4563ecd7ab15b2630651", "store_kind": "postgresql-v1", - "store_schema": "auths.lifecycle.postgresql/5", + "store_schema": "auths.lifecycle.postgresql/6", "credential_store_kind": "aws-secrets-manager-v1" } } @@ -992,7 +992,7 @@ "gateway_version": "1.0.0-rc.2", "gateway_build_sha256": "42194bc83fbd821aaede008519091b4516baf914f8c2e27f3f2ac7a25f7485c3", "store_kind": "postgresql-v1", - "store_schema": "auths.lifecycle.postgresql/5", + "store_schema": "auths.lifecycle.postgresql/6", "credential_store_kind": "aws-secrets-manager-v1" } } @@ -1020,7 +1020,7 @@ "gateway_version": "1.0.0-rc.1", "gateway_build_sha256": "42194bc83fbd821aaede008519091b4516baf914f8c2e27f3f2ac7a25f7485c3", "store_kind": "shared-file-v1", - "store_schema": "auths.lifecycle.postgresql/5", + "store_schema": "auths.lifecycle.postgresql/6", "credential_store_kind": "aws-secrets-manager-v1" } } @@ -1076,7 +1076,7 @@ "gateway_version": "1.0.0-rc.1", "gateway_build_sha256": "42194bc83fbd821aaede008519091b4516baf914f8c2e27f3f2ac7a25f7485c3", "store_kind": "postgresql-v1", - "store_schema": "auths.lifecycle.postgresql/5", + "store_schema": "auths.lifecycle.postgresql/6", "credential_store_kind": "local-file-v1" } } diff --git a/compliance.toml b/compliance.toml index 6a978ce54..aaaf7f667 100644 --- a/compliance.toml +++ b/compliance.toml @@ -1593,15 +1593,15 @@ kind = "cargo" layer = "product" path = "product/runtime/auths-gateway" core_apis = ["auths-author", "auths-codec", "auths-did-keri", "auths-did-key", "auths-model", "auths-multikey", "auths-ports", "auths-raw-key", "auths-raw-key-core", "auths-registries", "auths-signature", "auths-verifier"] -protocol_versions = ["auths.gateway-credential-journal/1", "auths.gateway-credential-collection/1", "auths.gateway-readiness/1", "auths.gateway-support-bundle/1", "auths.gateway-generation-floor/1", "auths.gateway-emergency-stop/1", "auths.gateway-installation/5", "auths.recipe-qualification/1", "auths.recipe-qualification-attestation/1", "auths.qualification-trust-root/1", "auths.qualification-signer-certificate/1", "auths.qualification-revocation-list/1", "auths.qualification-release-index/1", "auths.gateway-semantic-closure/1", "auths.qualification-verification-vectors/1", "auths.gateway-operator-attestation/1", "auths.gateway-admin-request/1", "auths.gateway-admin-response/1", "auths.gateway-connection/1", "auths.provider-connection/2", "auths.gateway-key-identity/1", "auths.lifecycle.transactional-store/4", "auths.gateway-recipe-source/2", "auths.gateway-compiled-recipe/2", "auths.gateway-recipe-review/2", "auths.gateway-recovery-capability/1", "auths.gateway-connection-descriptor/1", "auths.gateway-attempt/3", "auths.gateway-pre-entry/1", "auths.lifecycle.postgresql/5", "auths.gateway-echo/1", "auths.gateway-idempotency-key/1", "auths.gateway-observe/2", "auths.gateway-outcome/2", "auths.gateway-readback/1", "auths.self-hosted-profile-lock/1", "mcp-arguments-v1", "auths.gateway-audit-bundle/2", "auths.gateway-audit-report/3", "auths.gateway-counter-set/1", "auths.gateway-echo-verification/1", "auths.gateway-codes/1", "auths.gateway-production-codes/1", "auths.gateway-custody-vectors/1", "auths.gateway-outcome-vectors/1", "bounded-policy-commitment-v1", "auths.approval-response/1", "auths.gateway-bounded-count/2", "auths.gateway-bounded-sum/1", "auths.gateway.argument-ceiling-window-count/2", "auths.gateway.argument-ceiling-policy/2"] -wire_objects = ["CompiledRecipe", "ClosedProviderRequest", "ClosedCredentialReads", "RecipeReview", "RecoveryCapability", "GatewayAttemptSnapshot", "GatewayPreEntry", "GatewayRecordEntry", "GatewayConnectionDescriptor", "ConnectionRecord", "OperatorAttestation", "OperatorStatement", "GatewayAdminStatus", "GatewayEvidenceSummary", "GatewayObserveRequest", "GatewayObserveResult", "GatewayProviderEvidence", "GatewaySubmitResult", "SignedObservation", "ArgumentCeilingPolicy", "BoundedPolicyCommitment", "AuditReport", "ProviderResult", "AuditedPreEntry", "EchoVerification", "AdminRequestCommand", "ListedValues"] +protocol_versions = ["auths.gateway-commissioning-budget/1", "auths.qualification-commissioning-permit/1", "auths.qualification-commissioning-budget-key/1", "auths.qualification-commissioning-budget-binding/1", "auths.gateway-credential-journal/1", "auths.gateway-credential-collection/1", "auths.gateway-readiness/1", "auths.gateway-support-bundle/1", "auths.gateway-generation-floor/1", "auths.gateway-emergency-stop/1", "auths.gateway-installation/5", "auths.recipe-qualification/1", "auths.recipe-qualification-attestation/1", "auths.qualification-trust-root/1", "auths.qualification-signer-certificate/1", "auths.qualification-revocation-list/1", "auths.qualification-release-index/1", "auths.gateway-semantic-closure/1", "auths.qualification-verification-vectors/1", "auths.gateway-operator-attestation/1", "auths.gateway-admin-request/1", "auths.gateway-admin-response/1", "auths.gateway-connection/1", "auths.provider-connection/2", "auths.gateway-key-identity/1", "auths.lifecycle.transactional-store/4", "auths.gateway-recipe-source/2", "auths.gateway-compiled-recipe/2", "auths.gateway-recipe-review/2", "auths.gateway-recovery-capability/1", "auths.gateway-connection-descriptor/1", "auths.gateway-attempt/3", "auths.gateway-pre-entry/1", "auths.lifecycle.postgresql/6", "auths.gateway-echo/1", "auths.gateway-idempotency-key/1", "auths.gateway-observe/2", "auths.gateway-outcome/2", "auths.gateway-readback/1", "auths.self-hosted-profile-lock/1", "mcp-arguments-v1", "auths.gateway-audit-bundle/2", "auths.gateway-audit-report/3", "auths.gateway-counter-set/1", "auths.gateway-echo-verification/1", "auths.gateway-codes/1", "auths.gateway-production-codes/1", "auths.gateway-custody-vectors/1", "auths.gateway-outcome-vectors/1", "bounded-policy-commitment-v1", "auths.approval-response/1", "auths.gateway-bounded-count/2", "auths.gateway-bounded-sum/1", "auths.gateway.argument-ceiling-window-count/2", "auths.gateway.argument-ceiling-policy/2"] +wire_objects = ["CommissioningBudgetSnapshot", "CompiledRecipe", "ClosedProviderRequest", "ClosedCredentialReads", "RecipeReview", "RecoveryCapability", "GatewayAttemptSnapshot", "GatewayPreEntry", "GatewayRecordEntry", "GatewayConnectionDescriptor", "ConnectionRecord", "OperatorAttestation", "OperatorStatement", "GatewayAdminStatus", "GatewayEvidenceSummary", "GatewayObserveRequest", "GatewayObserveResult", "GatewayProviderEvidence", "GatewaySubmitResult", "SignedObservation", "ArgumentCeilingPolicy", "BoundedPolicyCommitment", "AuditReport", "ProviderResult", "AuditedPreEntry", "EchoVerification", "AdminRequestCommand", "ListedValues"] fixture_suites = ["bindings/fixtures/approval", "bindings/fixtures/gateway", "bindings/fixtures/qualification"] principal_families = ["raw-key-v1", "did-key-v1", "did-keri-v1"] signature_families = ["ed25519-v1", "p256-sha256-v1"] profiles = ["auths.mcp/2"] transports = ["bounded-https", "postgresql-tls", "loopback-http-development"] -configuration_inputs = ["operator-approved-recipe", "profile-lock", "independently-provisioned-trust", "connection-binding", "observer-anchor", "observer-signing-key", "deployment-kind", "operator-attestation", "app-capacity", "development-shared-file-store", "postgresql-store-configuration", "audit-trust-and-observer-pins", "qualification-policy", "recipe-family", "provider-contract-id", "qualification-release-inputs", "deployment-clock"] -security_state = ["durable-credential-cleanup-notes", "host-generation-floor", "recipe-digest", "logical-operation-claims", "credential-reference-generation", "shared-connection-record", "credential-generation", "in-flight-entry-count", "echo-bound-provider-evidence", "observer-signing-seed", "custody-held-observer-key", "principal-separation", "key-identity-separation", "pre-entry-evidence", "relative-ceiling-basis", "gateway-record-batches", "link-subject-count-and-sum-slots", "verified-qualification-index", "remembered-revocations", "accepted-revocation-sequence", "gateway-semantic-closure"] +configuration_inputs = ["commissioning-binding", "commissioning-permit", "retained-commissioning-budget-floor", "operator-approved-recipe", "profile-lock", "independently-provisioned-trust", "connection-binding", "observer-anchor", "observer-signing-key", "deployment-kind", "operator-attestation", "app-capacity", "development-shared-file-store", "postgresql-store-configuration", "audit-trust-and-observer-pins", "qualification-policy", "recipe-family", "provider-contract-id", "qualification-release-inputs", "deployment-clock"] +security_state = ["permanent-commissioning-consumption", "commissioning-revocation-and-time-floor", "durable-credential-cleanup-notes", "host-generation-floor", "recipe-digest", "logical-operation-claims", "credential-reference-generation", "shared-connection-record", "credential-generation", "in-flight-entry-count", "echo-bound-provider-evidence", "observer-signing-seed", "custody-held-observer-key", "principal-separation", "key-identity-separation", "pre-entry-evidence", "relative-ceiling-basis", "gateway-record-batches", "link-subject-count-and-sum-slots", "verified-qualification-index", "remembered-revocations", "accepted-revocation-sequence", "gateway-semantic-closure"] [packages.auths-gateway.claims] operational-diagnostics = [ @@ -1758,6 +1758,17 @@ runtime-enforcement-boundary = [ "product/runtime/auths-gateway/src/onboarding.rs#the_loopback_build_runs_the_same_onboarding_checks", ] stateful-replay-budget-component = [ + "product/runtime/auths-gateway/src/commissioning_budget/tests.rs#capacity_survives_crash_restart_and_sweep_file", + "product/runtime/auths-gateway/src/commissioning_budget/tests.rs#capacity_survives_crash_restart_and_sweep_postgres", + "product/runtime/auths-gateway/src/commissioning_budget/tests.rs#exactly_one_host_claims_the_final_unit_file", + "product/runtime/auths-gateway/src/commissioning_budget/tests.rs#exactly_one_host_claims_the_final_unit_postgres", + "product/runtime/auths-gateway/src/commissioning_budget/tests.rs#renewal_keeps_consumption_and_a_retained_floor_detects_restore_file", + "product/runtime/auths-gateway/src/commissioning_budget/tests.rs#renewal_keeps_consumption_and_a_retained_floor_detects_restore_postgres", + "product/runtime/auths-gateway/src/commissioning_budget/tests.rs#hostile_inputs_consume_nothing_and_revocation_survives_omission_file", + "product/runtime/auths-gateway/src/commissioning_budget/tests.rs#hostile_inputs_consume_nothing_and_revocation_survives_omission_postgres", + "product/runtime/auths-gateway/src/commissioning_budget/tests.rs#snapshots_reject_noncanonical_unknown_oversized_and_impossible_state", + "product/runtime/auths-gateway/src/commissioning_budget/tests.rs#consumption_never_exceeds_the_ceiling_or_charges_a_refused_action", + "product/runtime/auths-gateway/src/recipe/tests.rs#durable_claim_is_one_use_across_races_and_restart", "product/runtime/auths-gateway/src/recipe/tests.rs#response_and_observation_are_distinct_durable_stages", "product/runtime/auths-gateway/src/recipe/tests.rs#read_back_links_only_an_exact_token_with_the_verified_value", @@ -1899,7 +1910,7 @@ kind = "cargo" layer = "product" path = "product/stores/auths-stores" core_apis = ["auths-model"] -protocol_versions = ["auths-proof/v1", "auths.lifecycle.postgresql/5"] +protocol_versions = ["auths-proof/v1", "auths.lifecycle.postgresql/6"] wire_objects = ["AttestedDecisionReceipt", "AttestedExecutionReceipt", "LifecycleRecordV1", "GatewayRecordEntry"] fixture_suites = ["product/fixtures/v1/lifecycle"] principal_families = [] @@ -1907,7 +1918,7 @@ signature_families = [] profiles = [] transports = ["filesystem", "memory", "postgresql-tls"] configuration_inputs = ["budget-algebra", "capacity", "lifecycle-capacity-rule", "receipt-policy"] -security_state = ["budget-ledger", "gateway-attempt-records", "lifecycle-records", "receipt-spool"] +security_state = ["budget-ledger", "gateway-attempt-records", "permanent-commissioning-budget-records", "lifecycle-records", "receipt-spool"] [packages.auths-stores.claims] receipt-producer-consumer = ["product/stores/auths-stores/src/lib.rs#local_spool_policy_persists_attested_receipt_on_primary_failure"] diff --git a/docs/adr/0016-bounded-qualification-commissioning-authority.md b/docs/adr/0016-bounded-qualification-commissioning-authority.md index 31869209f..191467208 100644 --- a/docs/adr/0016-bounded-qualification-commissioning-authority.md +++ b/docs/adr/0016-bounded-qualification-commissioning-authority.md @@ -1,9 +1,10 @@ # ADR 0016: Bound the first qualification run with explicit commissioning authority **Status:** Implementing. The closed permit, commissioning-only signer purpose, -offline evidence closure and pure signature/binding verifier are implemented. -No current gateway accepts commissioning authority. Private operator sessions, -durable shared accounting and the protected live workflow remain required. +offline evidence closure, pure signature/binding verifier and atomic permanent +budget mechanism are implemented. No current gateway accepts commissioning +authority. Private operator sessions, retained host floors before custody and +the protected live workflow remain required. Ordinary production leases still require qualification. **Date:** 7 October 2026 @@ -122,6 +123,32 @@ action/lease bounds, evidence omissions and stable renewal identities. These tests establish the pure artifact boundary only, not durable consumption or a completed production bootstrap. +The accounting component reuses the existing bounded opaque record store's +insert-once and compare-and-swap operations. `commissioning-budget` is a fifth, +non-expiring record kind in PostgreSQL schema 6. Schema 5 is rejected; disposable +prelaunch databases must be recreated, with no migration or compatibility +reader. The existing lifecycle transition contract remains version 4 because +its transition and receipt semantics are unchanged. + +Runtime loading cannot initialize a missing counter. Authenticated fresh setup +registers zero consumption once; a subsequent initialization returns existing +consumption and refuses changed bindings. Every successful claim increments +before custody and is never refunded. The record additionally remembers signer +revocations, the largest accepted revocation sequence and the latest successful +trusted verifier time. A renewed permit cannot reset any of them. + +The private session must persist the returned validated snapshot as an +independently retained host floor before custody, including trust updates from +denied attempts. The mechanism refuses database state below that floor. This +does not detect a coordinated rollback of the database and every retained +witness; retaining witnesses outside the restore set is an explicit operator +obligation, as for the existing connection generation floor. Source tests run +the same final-unit race, crash/reopen, renewal, sweep, revocation and restore +cases on file and TLS PostgreSQL stores; the PostgreSQL cases require the +existing protected CI fixture. A property test additionally bounds consumption +over arbitrary accepted/refused input sequences. These tests exercise storage +accounting only and grant no production credential authority. + ## Consequences This adds explicit operator commissioning authority and its associated trust diff --git a/docs/operations/GATEWAY_TRUST_AND_GIT_SIGNING_RUNBOOK.md b/docs/operations/GATEWAY_TRUST_AND_GIT_SIGNING_RUNBOOK.md index e33eab0fc..b5c69dffa 100644 --- a/docs/operations/GATEWAY_TRUST_AND_GIT_SIGNING_RUNBOOK.md +++ b/docs/operations/GATEWAY_TRUST_AND_GIT_SIGNING_RUNBOOK.md @@ -90,7 +90,7 @@ held which key, is operator evidence and is not produced by this code. `AUTHS_POSTGRES_URL`, `AUTHS_POSTGRES_CA_PEM`, and `AUTHS_POSTGRES_SERVER_NAME`. Connections are TLS-only with certificate and server-name verification. The schema is - `auths.lifecycle.postgresql/5`; it installs only into an empty database. + `auths.lifecycle.postgresql/6`; it installs only into an empty database. A database created at schema 4 or earlier is disposable prelaunch state: recreate it. Gateway claims are stored as attempt record `auths.gateway-attempt/3`; a store holding `/2` records is refused as diff --git a/docs/specs/0038-production-runtime-custody-observability-and-assurance.md b/docs/specs/0038-production-runtime-custody-observability-and-assurance.md index 773efb527..45bd0289e 100644 --- a/docs/specs/0038-production-runtime-custody-observability-and-assurance.md +++ b/docs/specs/0038-production-runtime-custody-observability-and-assurance.md @@ -308,7 +308,7 @@ Implemented (engineering only; no production claim): | Requirement | Where | Evidence | | --- | --- | --- | -| §9.1 Epic 2: claims, provider-bound evidence, and outcome stages on the multi-host PostgreSQL store (Epic 2 qualification open) | `GatewayAttemptStore` in `auths-gateway`; `PostgresLifecycleStore` rows in schema `auths.lifecycle.postgresql/5` (AP-SPEC-063 §9.4 replaced `/4`) | One conformance suite on both stores: claim exactly once, replay, fresh challenge, unknown and re-observe, `echo-mismatch`, concurrent re-observation, fail-closed reads, and concurrent claims from two gateway processes. The PostgreSQL variants run in the PostgreSQL lifecycle workflow against its TLS fixture. | +| §9.1 Epic 2: claims, provider-bound evidence, and outcome stages on the multi-host PostgreSQL store (Epic 2 qualification open) | `GatewayAttemptStore` in `auths-gateway`; `PostgresLifecycleStore` rows in schema `auths.lifecycle.postgresql/6` (AP-SPEC-063 §9.4 replaced `/4`) | One conformance suite on both stores: claim exactly once, replay, fresh challenge, unknown and re-observe, `echo-mismatch`, concurrent re-observation, fail-closed reads, and concurrent claims from two gateway processes. The PostgreSQL variants run in the PostgreSQL lifecycle workflow against its TLS fixture. | | §9.1 Epic 2 fault matrix: replay, fresh challenge, crash after entry, concurrent re-observation | same | The attempt-scenario corpus and the conformance suite, on both stores. The TLS/pooling/failover/backup parts of the Epic 2 matrix are Epic 2's own open work. | | §9.1 Epic 4: observer and Git roots behind `auths-custody` | `GatewayObserver::from_custody`, `CustodyKeySigner`, `CustodyKey` | KMS- and PKCS#11-held keys, through the reference adapters over mock provider APIs, sign observations and grants that verify in the kernel. The shared custody conformance kit runs every `CustodyConformanceCase` and every lifecycle state on both paths. | | §9.1 Epic 4: each signer reports its custody kind | `ObserverCustody`, `GitProofSigner::custody` | Unit tests. | diff --git a/docs/specs/0063-generalized-gateway.md b/docs/specs/0063-generalized-gateway.md index 79e83cb35..da6442da5 100644 --- a/docs/specs/0063-generalized-gateway.md +++ b/docs/specs/0063-generalized-gateway.md @@ -1519,7 +1519,7 @@ entry, with its test evidence, in the change that introduces it: | Kind | Identities | | --- | --- | | Recipe | `auths.gateway-recipe-source/2`, `auths.gateway-compiled-recipe/2`, `auths.gateway-recipe-review/2`, `auths.gateway-recovery-capability/1` | -| Store | `auths.gateway-attempt/3`, `auths.gateway-bounded-count/2`, `auths.gateway-bounded-sum/1`, `auths.gateway-connection/1`, `auths.lifecycle.postgresql/5` | +| Store | `auths.gateway-attempt/3`, `auths.gateway-bounded-count/2`, `auths.gateway-bounded-sum/1`, `auths.gateway-connection/1`, `auths.lifecycle.postgresql/6` | | Policy | `auths.gateway.argument-ceiling-window-count/2`, `auths.gateway.argument-ceiling-policy/2`, `auths.gateway-counter-set/1` | | Evidence | `auths.gateway-pre-entry/1`, `auths.gateway-outcome/2`, `auths.gateway-observe/2`, `auths.gateway-audit-bundle/2`, `auths.gateway-audit-report/2`, `auths.gateway-echo-verification/1`, `auths.gateway-codes/1` | | Operator | `auths.gateway-operator-attestation/1`, `auths.gateway-installation/3`, `auths.gateway-admin-request/1`, `auths.gateway-admin-response/1` | @@ -1579,7 +1579,7 @@ nothing was leased or sent. ### 9.4 PostgreSQL schema 5 -`auths.lifecycle.postgresql/5` replaces `/4`; a `/4` database is refused, not +`auths.lifecycle.postgresql/6` replaces `/4`; a `/4` database is refused, not migrated. `auths_gateway_attempts` is replaced by: ```sql diff --git a/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md b/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md index ec501eb1b..010ac0615 100644 --- a/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md +++ b/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md @@ -1488,7 +1488,7 @@ Each was taken unattended as the narrower or fail-closed reading. rederived from the installed files. The semantic closure, package, version, operating system, and architecture are the build's. The build digest is SHA-256 of the running executable. The store kind and schema - follow the deployment (`postgresql-v1` with `auths.lifecycle.postgresql/5`, + follow the deployment (`postgresql-v1` with `auths.lifecycle.postgresql/6`, or `shared-file-v1` with `auths.gateway-attempt/3`). The recipe family and the provider contract identifier are declared by the operator at install, because a gateway cannot derive them; a wrong declaration matches no diff --git a/formal/qualification/aeneas/source-closure.json b/formal/qualification/aeneas/source-closure.json index 57aeafb20..c2ffeac9d 100644 --- a/formal/qualification/aeneas/source-closure.json +++ b/formal/qualification/aeneas/source-closure.json @@ -1,6 +1,6 @@ { "schema": "auths-proof-translation-source-closure/v2", - "digest": "df1985f8750732aa8896f5d25e48387f42281b05da244bc1d3b3c22ad3599fba", + "digest": "cdfc1e60823a53d8ed627e77d9bdaee386faa45e1d8bd440f8d69645a96dc6cc", "files": [ { "path": ".cargo/config.toml", @@ -401,7 +401,7 @@ }, { "path": "xtask/src/semantic_freeze.rs", - "sha256": "52b36fa91c618677addf4d8ba157783b119b6a64e797047112f0e652281e846a" + "sha256": "9e36c78ae7ed8ce11bbc545ef7db8c1741c826038d01a7fb66d6e7fa5c91b18b" }, { "path": "xtask/src/stripe.rs", diff --git a/product/qualification/auths-recipe-qualification/src/vectors/mod.rs b/product/qualification/auths-recipe-qualification/src/vectors/mod.rs index 48d93f573..47d3314c2 100644 --- a/product/qualification/auths-recipe-qualification/src/vectors/mod.rs +++ b/product/qualification/auths-recipe-qualification/src/vectors/mod.rs @@ -280,7 +280,7 @@ pub(super) fn target() -> QualificationTarget { gateway_version: bounded("1.0.0-rc.1"), gateway_build_sha256: digest_of("gateway build"), store_kind: LifecycleStoreKind::PostgresqlV1, - store_schema: bounded("auths.lifecycle.postgresql/5"), + store_schema: bounded("auths.lifecycle.postgresql/6"), credential_store_kind: CredentialStoreKind::AwsSecretsManagerV1, } } diff --git a/product/runtime/auths-gateway/semantic-closure.json b/product/runtime/auths-gateway/semantic-closure.json index c518bb86d..d2be7dc36 100644 --- a/product/runtime/auths-gateway/semantic-closure.json +++ b/product/runtime/auths-gateway/semantic-closure.json @@ -1 +1 @@ -{"files":[{"path":"Cargo.lock","sha256":"0e75e2fdef44e79e57797ac6661295ae58ddb8de4a1990a6fd22ce6c54f78604"},{"path":"Cargo.toml","sha256":"6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24"},{"path":"core/adapters/auths-did-keri/Cargo.toml","sha256":"86ba3e3f9a0a70d970568bfb3113b7ba7bbdd81c3eebbb52743dd574a0c0ecaa"},{"path":"core/adapters/auths-did-keri/src/lib.rs","sha256":"a75674842f8a7142004369ccd206ab43e476459293f0ff4bed4d4e659031b3e3"},{"path":"core/adapters/auths-did-key/Cargo.toml","sha256":"d5a3ae07ecde83f91eed4c3785051dd0f44eab6c891754f3309b6b40596707d7"},{"path":"core/adapters/auths-did-key/src/lib.rs","sha256":"b76a3f4528a725df53cfa9242e6e414e1d26caa48468aaed497e28b121f4497c"},{"path":"core/adapters/auths-raw-key/Cargo.toml","sha256":"f49616bc18c19e6aaa7e6a02ccebcdb9f5c1422c1278ef9869e0dbf22ceda7be"},{"path":"core/adapters/auths-raw-key/src/lib.rs","sha256":"45eec1b295dac3bed65cd79c942870b926b06b3f5d38eaebaeb6140ac69315fa"},{"path":"core/crates/auths-algebra-kernel/Cargo.toml","sha256":"0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba"},{"path":"core/crates/auths-algebra-kernel/src/generated.rs","sha256":"ae4bcbef42a408c7ffa0c6a74a42f7de177a6f14479e51d205acf830bda05960"},{"path":"core/crates/auths-algebra-kernel/src/lib.rs","sha256":"6654667eeb9b353d6648954c9fd2e8838462a82ce6b2803eb49e1366892c68c6"},{"path":"core/crates/auths-assurance/Cargo.toml","sha256":"afcb12a97ddd09d7a264b9ecd3fcaefc865ff2c9b4539ee85b00883420ba333a"},{"path":"core/crates/auths-assurance/src/lib.rs","sha256":"0fb2ec844d674b25a9e20b1601452c89c2454901fa506adfa9bb38ef9a7fa213"},{"path":"core/crates/auths-author/Cargo.toml","sha256":"1e6f0e3bc079ddb558decf0db26b291c6e72fc47327b6df1b7650d41689b215f"},{"path":"core/crates/auths-author/src/lib.rs","sha256":"e14475f2f49715a1869d5fa6b11ff1fbb72497e39097e09f833b0bae7e5b3f2b"},{"path":"core/crates/auths-author/src/observations.rs","sha256":"dda7d6bfa6f4bd7e95a480ca283c2c0e996f69c5c15cb0c7197af328131a7066"},{"path":"core/crates/auths-authority/Cargo.toml","sha256":"4f68212938029f79ebd857b4f3038494eb85d0163d49f07e51376715cf959815"},{"path":"core/crates/auths-authority/src/lib.rs","sha256":"da88d5194de4e17449e69972c0fb042afa3c39798a8f570f30771e77c384f1eb"},{"path":"core/crates/auths-codec/Cargo.toml","sha256":"e20e51826e17814effd9d8925d18d5fbdd6c0d37bf50231e743ec2611314722c"},{"path":"core/crates/auths-codec/src/approval.rs","sha256":"fbff43bf4d57f69f8b7738a8647751cde75c5a932dee65d924a1fe9c7202f91f"},{"path":"core/crates/auths-codec/src/bounded_policy.rs","sha256":"d21f6728be2d8a04b6d94921f2b683f7e61cbb42e0ac6866f1c88a49caa534c3"},{"path":"core/crates/auths-codec/src/decode.rs","sha256":"ba2999584cdf53b1b517ecb9c7ea50d39efee17c666a9a38e2ad1ac94379f778"},{"path":"core/crates/auths-codec/src/encode.rs","sha256":"8491192053e2e15d62b4d2a491de22405b7487ead69ab6f6bca40669ce7ca5f7"},{"path":"core/crates/auths-codec/src/error.rs","sha256":"fecb0737c16deb42d859f1dc7727c698438d9ac12064fd99e0024629642c390c"},{"path":"core/crates/auths-codec/src/hash.rs","sha256":"f88e111f1dbb2cef6b7b5e9c948cb45ff92e366710c8a5f5c636138aa748479e"},{"path":"core/crates/auths-codec/src/lib.rs","sha256":"3b0e5c94c6f34f750b88a9333e1d5c8145746d845d3a23e0d2f61807cf592ea7"},{"path":"core/crates/auths-codec/src/observation.rs","sha256":"38328b0c71ff97a4196eeade8b4faa889527ff1f80bb168468bcd49082a3987e"},{"path":"core/crates/auths-composition/Cargo.toml","sha256":"331e13025eb82588b5269ed3975929eb41c823d588c49e4c296273d85c6fe80e"},{"path":"core/crates/auths-composition/src/lib.rs","sha256":"e42e3b0b6a9985b73c533aeb23799c638979aa27a9ce7d0f10a8d60340570fb1"},{"path":"core/crates/auths-model/Cargo.toml","sha256":"565c15302b0cc9270db1e28efa3862804846850ba933cc17aea8abcec4a65987"},{"path":"core/crates/auths-model/src/approval.rs","sha256":"54cf44a9ef747ec21546a4086aecfb130bc7803b0d646430e6082df51e6e305f"},{"path":"core/crates/auths-model/src/bounded.rs","sha256":"f90496abc0a06c028b4d850af6ddab7d850bfafeaa3d042f1b1246a41d8bbbc9"},{"path":"core/crates/auths-model/src/bounded_policy.rs","sha256":"306a8f049cc7cfc7635fe0e4de47eb7813eed63d3c14c3be2b51586aa4eea450"},{"path":"core/crates/auths-model/src/lib.rs","sha256":"e7cfe6bb9574c6b016aa63e70658c31e0b90903ec6479a49f4a2ceb64f5bad97"},{"path":"core/crates/auths-model/src/observation.rs","sha256":"b3ed3e3cc090afca2896a7d3de7988afccc1ee1ea0ebd91b51a8bc0f20ad8dbb"},{"path":"core/crates/auths-multikey/Cargo.toml","sha256":"858756c1197befcada06134742bffe8d58cf674cadd6c046bf710570e96efaf2"},{"path":"core/crates/auths-multikey/src/lib.rs","sha256":"f5177fffb11e40eeaaa665ba886c541fc1f24d5eacdd6983fb03dc20148733f0"},{"path":"core/crates/auths-ports/Cargo.toml","sha256":"596a9b0f5af3717c16a6d13f7054d8a106bcd9f01f5f72c2235dd2afcf0ab16c"},{"path":"core/crates/auths-ports/src/binding.rs","sha256":"a16c012d40aa4249e3ec54372b9611006d0bfe8c7dc3c741911c2194ad17736d"},{"path":"core/crates/auths-ports/src/diagnostics.rs","sha256":"aa596572503b5a65a918bb2ff38281c144ff53821ee914e9325c852828d852df"},{"path":"core/crates/auths-ports/src/lib.rs","sha256":"8da1debf86f9532df0660155d04298beb1ba3a1204508f8586e2e67cd2fb3449"},{"path":"core/crates/auths-ports/src/path.rs","sha256":"b68fc547b4e4d97a60cbbc1cc1939fc6b34a8233b81f840bd396914a707e3ea1"},{"path":"core/crates/auths-raw-key-core/Cargo.toml","sha256":"98c0bc8527a537512e43a74dd6ba9658c6f0cdc16610cf938e3f9b43785d836d"},{"path":"core/crates/auths-raw-key-core/src/lib.rs","sha256":"98c0500c41697aae28708ad0bf970b9a97583d96a3d2c18d23e7fa351e0f7d12"},{"path":"core/crates/auths-registries/Cargo.toml","sha256":"590e49e58b0622d9d6274fea46796dcdb07dec9550eff295cce6a6427ffa51e2"},{"path":"core/crates/auths-registries/src/lib.rs","sha256":"450d3886d85ee333b7e046317fb5b47cde62483d5f3e41d46265e2caf4c373ec"},{"path":"core/crates/auths-registries/src/template.rs","sha256":"1224039dd2b3ce6fa8357613d8cafbae40400493da7176da202b9ade62fa05e4"},{"path":"core/crates/auths-signature-core/Cargo.toml","sha256":"6bee2230eb30af1be0bd5c2d57bd3e1903497a70028d47290d4ac6e9e0e8bca0"},{"path":"core/crates/auths-signature-core/src/lib.rs","sha256":"6e3f9311ded5e49ea50d445eb21e6d8fa12442aa4362a73e0cb6fda15b7cd865"},{"path":"core/crates/auths-signature/Cargo.toml","sha256":"7f7b5682466ba439d8c59579022cb61068cad9fb4bd2d73e1cc21327c902b450"},{"path":"core/crates/auths-signature/src/lib.rs","sha256":"b3d9ac4cc3ba0797b9e1c09f2d6ac05089b25dac4e285a5af28c0165b33d925b"},{"path":"core/crates/auths-verifier/Cargo.toml","sha256":"c43358e06a33324b41a8b93e5cc7279c55f7d21f1f6cfaa539a3fc7b4c27a38f"},{"path":"core/crates/auths-verifier/src/approval.rs","sha256":"c3cae6a49e169051eb555bb092b1069a4d422516d6a2114623a89e5f31ff923f"},{"path":"core/crates/auths-verifier/src/causal.rs","sha256":"9635230f33b13a263573d319ac8a1976addbcc07677514a43e3c7bf28dc04587"},{"path":"core/crates/auths-verifier/src/lib.rs","sha256":"f22dec38dfa47ced8da4f605390da8453273bee1da010f57fd1fdfcb10e0b389"},{"path":"core/crates/auths-verifier/src/observation.rs","sha256":"0bb07f06a0f9524c88427df1c972b1de8ba038a9eeeb15d3134c25125ae84b1e"},{"path":"core/crates/auths-verifier/src/trace.rs","sha256":"2213d72023a1d9e0413a2cf2c51c3dad9e04775d86033a0caaa9d29a8f0036f8"},{"path":"exchange/crates/auths-proof-exchange-model/Cargo.toml","sha256":"34b2db64f93a288e942b5a3918d28cdcbef906e0dc9074ce848018d3d5f7a1fa"},{"path":"exchange/crates/auths-proof-exchange-model/src/lib.rs","sha256":"49fac5aff2339d3a57c41cb8bb2a82852538e8f77ecc4b157c88e264ff31fb55"},{"path":"exchange/crates/auths-proof-exchange-port/Cargo.toml","sha256":"7ff660f1b7579dc570c791090aeb450404fbbf44c92781e289f5ccdde746d739"},{"path":"exchange/crates/auths-proof-exchange-port/src/lib.rs","sha256":"b408fb40c6432edc1facb3d8b3e9433a033f8dc73fe2e0ba5a88c972ca675021"},{"path":"product/config/auths-config/Cargo.toml","sha256":"e4b568ab9f6d84f7d7e6d66443fe825f360db9c27bc7c31d6ddc0647ba3ab304"},{"path":"product/config/auths-config/src/lib.rs","sha256":"fecf00ea65cef9018fda9af2063326d7065b869266d0d9e73a4f06816f1102cc"},{"path":"product/errors/auths-errors/Cargo.toml","sha256":"3b3a199b6460ba75bda84475bb5accd35e1485448a3981038db85bf4772dd350"},{"path":"product/errors/auths-errors/src/lib.rs","sha256":"7feeb9069fa4003f94f1f07c1c94619cf1c883e0dbaaf2187f04d0f742264bdd"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/Cargo.toml","sha256":"716f1f2a117d6d69d8effe9ee9057e24ba3502f20af6a602b06facb638cdabed"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/api.rs","sha256":"9ea61dd7ddd93282b073b98e453e6b75b26dc49689c04e9782435d06a3a09e48"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/clock.rs","sha256":"73f0a6e0f5903883329fa6683f5888288f759512ac69e5c87efd2b6b87f7d79f"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/http.rs","sha256":"14c1fce14e24c984b2a275563a29b6326fb08367922b6e8d37ba38b9cb81aa2b"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/identity.rs","sha256":"186de11230c8b33375951c4368609f8976bf9795f171af3fd7fac26207a94361"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs","sha256":"0b4617d044f5254a5ab22f5a2578f91cc025206a8c1845be39c1c56dcdf7a5df"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/names.rs","sha256":"41bb23572d6002e23ee103d6fe70ecd68764861c6f2e48a1c53af998270a4afa"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs","sha256":"39fed883f4802e68d3b41a68fea0aba0737810996b33d13577de70faba004c29"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/store.rs","sha256":"fc60ee9c49b2f4f063c449b4c78100c5c4872779e94ca168f796603b380ef6e4"},{"path":"product/integrations/auths-custody/Cargo.toml","sha256":"1e14034185ad1ec24a977fd5f41d0abee219606245c046ce2a82287fadef448b"},{"path":"product/integrations/auths-custody/src/conformance.rs","sha256":"8ed1afd58f18fc6becc268908aa6419c9aa404c79da0197963eb2599df44acf6"},{"path":"product/integrations/auths-custody/src/key.rs","sha256":"70cbb0fd21b6f5652157845a22c35be2d0f6c05b3d138fc4b9bb6dbdc3d81c40"},{"path":"product/integrations/auths-custody/src/lib.rs","sha256":"8ee593c1f59b0fd2126bdda9138026f5bc531beb64d4489a99785842e7b98b43"},{"path":"product/operations/auths-operations/Cargo.toml","sha256":"73dde1e914ba5e1386f8d49c0d730423cc72ae77ec44c6554a6a75cc8e8922b1"},{"path":"product/operations/auths-operations/src/explanation.rs","sha256":"b4a39bcbd5712cb9e735ee7deeb281f3fa6af5ddca973735bf3d87dce427ef11"},{"path":"product/operations/auths-operations/src/lib.rs","sha256":"3f401a56555113b98f57bca172a2660eaecedf76247b83a3fdbb089c133a29cd"},{"path":"product/operations/auths-operations/src/render/json.rs","sha256":"2ae042639960afee123730e945d373bc5dda1d2b3af20ae16c939a7e99b9e418"},{"path":"product/operations/auths-operations/src/render/mod.rs","sha256":"b3b7f6fe473f49227ace5a68bfc3d8dc14b5db8dd9888fd9e207070337b1b8bf"},{"path":"product/operations/auths-operations/src/render/text.rs","sha256":"f216cf3bdb00e264523271b16e7059535ac6b1aabf271cebd7935af155e4bfec"},{"path":"product/policy/auths-bounded-policy/Cargo.toml","sha256":"babd5d200923137ead71d8c2528f847cea323ce98da942a1320b054436612c47"},{"path":"product/policy/auths-bounded-policy/src/arithmetic.rs","sha256":"75e43c5d4eab8d1f71c1daf53839f5f9fe45a400afc1f63a30c6f55ce3632627"},{"path":"product/policy/auths-bounded-policy/src/commitment.rs","sha256":"c5706f2d583454e1a7f570f7ada138d4d864bef0205dfae7c1296774f396bb3f"},{"path":"product/policy/auths-bounded-policy/src/eligibility.rs","sha256":"c9acdfb793074e687fc36efad506be27dbd99ffbf40387bc66c8de39ef238432"},{"path":"product/policy/auths-bounded-policy/src/identifier.rs","sha256":"0006a32bae9eb16c4178cf797df418d2b0a781f2bc6474b741dc1a908141831c"},{"path":"product/policy/auths-bounded-policy/src/kernel.rs","sha256":"99187c28b161ac70bee1afed60711f7f645adb4d1671a01863f9849b369811d5"},{"path":"product/policy/auths-bounded-policy/src/lib.rs","sha256":"76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c"},{"path":"product/policy/auths-bounded-policy/src/receipt.rs","sha256":"3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad"},{"path":"product/policy/auths-bounded-policy/src/registry.rs","sha256":"4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0"},{"path":"product/profiles/auths-profile-api/Cargo.toml","sha256":"7ae85761f58625b5d678f961fd052eebf3e000ef565c7312e3ac857763c0017f"},{"path":"product/profiles/auths-profile-api/src/lib.rs","sha256":"a194b82b20bf8aa864c2334ef6c6aec30b2154ded972862252d5dcefa488ab95"},{"path":"product/profiles/auths-profile-mcp/Cargo.toml","sha256":"db264fc25242f7b7e4133cbe5782545b3107b406c87168ae072683cfb59eac66"},{"path":"product/profiles/auths-profile-mcp/src/arguments.rs","sha256":"a5de696586d507e2aee4a49fee99ef1ef4c51a2e46603f8838f1af6d9009833f"},{"path":"product/profiles/auths-profile-mcp/src/lib.rs","sha256":"d0f8b733a09ef8408336cdebc8948d6a5861012ce6878598b11be7084dfd4280"},{"path":"product/profiles/auths-profile-mcp/src/session.rs","sha256":"166c281fa66333388e4760d6098dad02d3359e1d5de4b8f93312c014f97abb03"},{"path":"product/qualification/auths-recipe-qualification/Cargo.toml","sha256":"b7b15b30b9a3d96d4f089d514266d3a892de6608d30707aa44be31cca89ca9fe"},{"path":"product/qualification/auths-recipe-qualification/src/canonical.rs","sha256":"30a9b50777f0dcb4b606abfee2467d5a975d9f6ad941ab6c13ca3df5b359f667"},{"path":"product/qualification/auths-recipe-qualification/src/closure.rs","sha256":"0ad6aee9bd981e2863fa725f209ec84031db2ff12f4c7ac3aaf5120f0bb86039"},{"path":"product/qualification/auths-recipe-qualification/src/commissioning.rs","sha256":"e902df9b2c6bd06bedd32ef40e23ce14b4db4882dcb12b0f0aabcb7335cfa515"},{"path":"product/qualification/auths-recipe-qualification/src/commissioning/tests.rs","sha256":"5a226725c2ad7ce920d0bd62d427185e007f4d0949b0f0ec1260aa161d3114d0"},{"path":"product/qualification/auths-recipe-qualification/src/error.rs","sha256":"52d5cf720a1e4579008fdda90a3ac2c31f0b8db57985f121f65e54b4da2b7dd1"},{"path":"product/qualification/auths-recipe-qualification/src/evidence.rs","sha256":"ba45a7409d67a8af26ab811af306412014557477a101ab2a8eb0faf8f2bd4b91"},{"path":"product/qualification/auths-recipe-qualification/src/ids.rs","sha256":"e81a906d571497ab2da753e1532d4443706410e0b75fdd59a7d2d788c7aec403"},{"path":"product/qualification/auths-recipe-qualification/src/launch.rs","sha256":"41f2e2de90e1e7d6440a66eda3eb9bea8d5e0741bc232305a76a363ab5f813c1"},{"path":"product/qualification/auths-recipe-qualification/src/lib.rs","sha256":"7ef5cb7b8eacaa38c5d512b589db5e78e4597aed7d1a10368b86eebfb5a48aeb"},{"path":"product/qualification/auths-recipe-qualification/src/model.rs","sha256":"3484eb0ec287b23d4682ade7b1b0f8d1335985b3fb180f06fc28716076957d5f"},{"path":"product/qualification/auths-recipe-qualification/src/release.rs","sha256":"ec478e53f70052e566aac7e15be2f9e1b1cd46837ac6990ae955fa864d311586"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/mod.rs","sha256":"7f15b68e05a04f202bcb1fb80de1d9a9a4fda8bfd6af2cd4e5c660fc75d96fe5"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/schemas.rs","sha256":"c59feec2805621f341a90f81fc005e2c12f7a70f9d264fdeacccb2be4fe1c046"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/verification.rs","sha256":"6a6b5834c5dae10af1ba8939b2deae43b85db71544dc8f077ff63b7fe68ac8a8"},{"path":"product/qualification/auths-recipe-qualification/src/verify.rs","sha256":"2ec2784435d11e07295de77b2ee1b2c48b2fcf9609a00454c6e7374b621aed5c"},{"path":"product/receipts/auths-receipts/Cargo.toml","sha256":"6001fa1375899953aafcb07c23a6da0c8f57ea7ec08bb9c950b12a60a8cc6f0f"},{"path":"product/receipts/auths-receipts/src/disclosure.rs","sha256":"ba9ed439be0a320c8a01f5b6e9b51361c1a37e076947490d8e4a484ba6bb119c"},{"path":"product/receipts/auths-receipts/src/lib.rs","sha256":"547a57c4160256719cafb7d0ab972d9fc80b0da14fbbce4148c70c414070ff36"},{"path":"product/runtime/auths-connections/Cargo.toml","sha256":"babeb6e1dda3dfb66291713ce1e43dce5c349833d0b50ea4dccbf986030026b2"},{"path":"product/runtime/auths-connections/src/credential.rs","sha256":"82921413bb053f0f6c7931fbd4e6a86c8cc1d8c6b51debd9c2cef33a8d5b1c51"},{"path":"product/runtime/auths-connections/src/kernel.rs","sha256":"a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8"},{"path":"product/runtime/auths-connections/src/lib.rs","sha256":"79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22"},{"path":"product/runtime/auths-connections/src/model.rs","sha256":"de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77"},{"path":"product/runtime/auths-connections/src/registry.rs","sha256":"e57640e003e72ad3235c567c2bb944a262bd64e673f023b62ea091094cc7e946"},{"path":"product/runtime/auths-gateway-kernel/Cargo.toml","sha256":"34f864e67656af4ac7e5c7a347a23f01fc8ab31365b8e23c0ef474483b14a183"},{"path":"product/runtime/auths-gateway-kernel/src/construct.rs","sha256":"e9d65744bae273d65face4285e5d2da75c06a92ab48f7b8333d496604e31c63c"},{"path":"product/runtime/auths-gateway-kernel/src/lib.rs","sha256":"cfda6f8453426564c085475f183b6f790b438768a19668f1b65d33ba59dc8632"},{"path":"product/runtime/auths-gateway-kernel/src/order.rs","sha256":"e0045f877c4b7fe3860c291039853885064ddcdebba7c9b345ab65e81e646dda"},{"path":"product/runtime/auths-gateway-kernel/src/outcome.rs","sha256":"e9785b1afe70788c89b51b18655bcd5acff7b0c8e3d12fb79c6f05a202e67e6b"},{"path":"product/runtime/auths-gateway-kernel/src/ratio.rs","sha256":"7ace22264812e6fc1ef3a62afee402cf43494bb71ae0d3de219ad1b39d690bcb"},{"path":"product/runtime/auths-gateway-kernel/src/recovery.rs","sha256":"9f46dcd1685ab6e4d1ba04a3fc286a9f3afee8fb47829be1fbc670a7926a2dc6"},{"path":"product/runtime/auths-gateway-kernel/src/transition.rs","sha256":"cefb8f01d915880f6921f2501ff881ad94b9de61072c34d9cd19220992f97374"},{"path":"product/runtime/auths-gateway/Cargo.toml","sha256":"00b28be86921dcdc0ad90cce0c62c2961cafefe96ea6c2edf0e926c3d405ccad"},{"path":"product/runtime/auths-gateway/src/admin.rs","sha256":"2d5cc67afac42fbd15f36e2d1693cd1b20cedacf775040dce6ffe04ccc94c9ea"},{"path":"product/runtime/auths-gateway/src/app.rs","sha256":"6f80f63833ea0815bb44fbf3b0cc54624a08e9fb578b035819f2980dc04e8256"},{"path":"product/runtime/auths-gateway/src/audit.rs","sha256":"0edb2037eb7b5d6f13acfce85c54f62a82bf7fdd31bc7e626c4fec183cef61dd"},{"path":"product/runtime/auths-gateway/src/audit_tests.rs","sha256":"990969384a52d75bc2489d9d412a9e7dd814bca1c8f65c701d6205fae62a15d5"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway-harness.rs","sha256":"12b0c24d36b2e6a3be392d3c081a783b355fdd67dc5b54bacc0410e803116b8c"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway.rs","sha256":"2f33a1da5dd54947ee1664795f90b3f07a11bb9ee184774bf470b78b03600f0c"},{"path":"product/runtime/auths-gateway/src/binding.rs","sha256":"663b0ce878319511aa7d05722ab4ab2fa9be18817884ffb2ee9f131ff1e382d1"},{"path":"product/runtime/auths-gateway/src/bounds.rs","sha256":"9cfa0eae4973e5e047a198360b22f041708fa20276b0b90c2ec440f06915d64b"},{"path":"product/runtime/auths-gateway/src/bounds_aggregate_tests.rs","sha256":"ab34f227b7c8692ba1da88ccb32bb3687a66adf8353d8282fae905d4a88eb612"},{"path":"product/runtime/auths-gateway/src/bounds_tests.rs","sha256":"74136bc570da7b9338b5a1a1ed9d3fd892c55135160964f9d3ac0e2cf5741375"},{"path":"product/runtime/auths-gateway/src/connection.rs","sha256":"7b5d049c258a26ed1c93ecf860f51d051a8a65f9b93554af0b1ea93862398ec9"},{"path":"product/runtime/auths-gateway/src/credential_journal.rs","sha256":"7297fccaee5cd8622928e8e0a42bba50da7941970a6f682ecd300c41ee6509da"},{"path":"product/runtime/auths-gateway/src/echo_verify.rs","sha256":"6d453051665f823abd7354d5c50031d9524cf47d6092d2f09080ae814e3b9575"},{"path":"product/runtime/auths-gateway/src/engine.rs","sha256":"f1052aaef43e441b9e0befa3f8ad1e2fd5279a27cb9d63aac0cf9dfdbe85a052"},{"path":"product/runtime/auths-gateway/src/fuzzing.rs","sha256":"ed3b0028487eb546a3b0a91d115aa8f18bcea324b61620bfe8e35a9e6ab18758"},{"path":"product/runtime/auths-gateway/src/generation_floor.rs","sha256":"fe1510ec96ce0f67e9a78edbfa94b33eb7df64c0ac4d0a67901124dcd0164777"},{"path":"product/runtime/auths-gateway/src/harness.rs","sha256":"c87e479f3eb281960f6c9c80d43c7560d7ccb654b0154ec823d3fcec4884ac05"},{"path":"product/runtime/auths-gateway/src/lib.rs","sha256":"a1f51b76524a89842720b4fda58b2293d4bc82b41c912d5a462261603c593cea"},{"path":"product/runtime/auths-gateway/src/listener.rs","sha256":"aa08239bcbc1fcb55e8a212fbdf6a84f12985b0d436dcb51dc58b06e59e435f2"},{"path":"product/runtime/auths-gateway/src/observed_tests.rs","sha256":"a22be071695f89ca2578a4d82fd80d9cb82289213c9bdb8f0470f6b2dc3d9201"},{"path":"product/runtime/auths-gateway/src/observer.rs","sha256":"562ffcaea071c3856e0708dc2fe33516917e145d2438aabb75af0a2b6ba01046"},{"path":"product/runtime/auths-gateway/src/onboarding.rs","sha256":"0dfd7d67e7f02f18a28d1c86ca1b7751d7463f5efcdbe3825de0ad8cbccb3891"},{"path":"product/runtime/auths-gateway/src/operator.rs","sha256":"c3c36954a3e86723df035b47f43b85fc8ab3a6292983522b6258d5c6b4e6c4e4"},{"path":"product/runtime/auths-gateway/src/pending_vectors/attempts.rs","sha256":"47ef3c8cb1c5504d47ae9a0088705ce6715fe86bac1671a34a56fb38a64d0dd3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/bounds.rs","sha256":"e612217307e1da5b0eb5ee6582a7458bb064b8aa8a529fc6555b1b334127ab68"},{"path":"product/runtime/auths-gateway/src/pending_vectors/codes.rs","sha256":"e00670a5ef24eb856cc2c6dcda8e5a263842f55c76bb939c0c27bd9df37e5522"},{"path":"product/runtime/auths-gateway/src/pending_vectors/keys.rs","sha256":"f84c56f2ea9cb34b2b79c72d13fbf2c6585010ec1ed450af58a78c80c1ea1edd"},{"path":"product/runtime/auths-gateway/src/pending_vectors/mod.rs","sha256":"5de8340f0ef71a0b57a09e323fefe473d3160c6ae952b9ba46f714825fbacafc"},{"path":"product/runtime/auths-gateway/src/pending_vectors/outcomes.rs","sha256":"8ec07b9511b48913af36ac999d2aa0e82924289f6acb23ddaeb9f00f99815166"},{"path":"product/runtime/auths-gateway/src/pending_vectors/production.rs","sha256":"f574cabfa4687a4fc846b8f6a234b68ec53b876aed548b11445729cac1a55ede"},{"path":"product/runtime/auths-gateway/src/pending_vectors/recipes.rs","sha256":"51693208270231c25c3aef2a32151d5962114c71e86b88cb9df83181c7af83d9"},{"path":"product/runtime/auths-gateway/src/pre_entry.rs","sha256":"06ea78ca140468bfaba17d9ab04912ad68673954c3203c98fed28272ff2a00c0"},{"path":"product/runtime/auths-gateway/src/property_tests.rs","sha256":"939c081e2e154aaf10186754044bdd65608932c899b970a04a71d0afaa999a93"},{"path":"product/runtime/auths-gateway/src/qualification.rs","sha256":"06b49d3fc2ad4383f9e23beefa96033f1fd6e415e043878327583451a53086cc"},{"path":"product/runtime/auths-gateway/src/qualification_simulation.rs","sha256":"4ee7cadfb5f46a92713c80f3e55f499cb074d04d8b21ea89d57762af38642bfa"},{"path":"product/runtime/auths-gateway/src/qualification_tests.rs","sha256":"a9178a2e58eea459d5e5dafc53a3999ea7c84dbbffefe6e5eb1f3d098827f028"},{"path":"product/runtime/auths-gateway/src/quorum_tests.rs","sha256":"a78380b019104d688c11a4410082c7e08ded3106aab099954c4f8a1b4ae0fd89"},{"path":"product/runtime/auths-gateway/src/readiness.rs","sha256":"911c3f11892f94641574375e2da4c671c802738f71082f12c39832331052d43d"},{"path":"product/runtime/auths-gateway/src/recipe.rs","sha256":"fecf9af67e7afc48d080e9f8f55f8ce28e49d0e08988717a27908bbda461d6b6"},{"path":"product/runtime/auths-gateway/src/recipe/lower.rs","sha256":"8088b8751ed831dbb48247af953c6290ac95e2a438ccd5bd65eff54be06a1fd1"},{"path":"product/runtime/auths-gateway/src/recipe/review.rs","sha256":"c3eb7d9fdd98dacf52750b14b67ad7b7faaecbbdeafff1e0b049f67d0a2d0139"},{"path":"product/runtime/auths-gateway/src/recipe/runtime.rs","sha256":"c286f0d15f974402822c0810d8e97f98411dc1c557755cc23e540d85e2bb42d9"},{"path":"product/runtime/auths-gateway/src/recipe/source.rs","sha256":"1af50298fb1461e1b24cbdf560d43124d6b1c4c529586c911b1c4797214a69ff"},{"path":"product/runtime/auths-gateway/src/recipe/tests.rs","sha256":"aac551a2481bbc60864c64079bc667dcb232e45a0f41a04073ed84ab5dbe1fce"},{"path":"product/runtime/auths-gateway/src/recipe/validate.rs","sha256":"3711b17605cb7b0d639bc1b180449231f5882a306cab20e2c7782155cc63b0d4"},{"path":"product/runtime/auths-gateway/src/scenario_tests.rs","sha256":"67915828ecfe2be0afadb5525277ab205f91172edc90852ec7b77c63b2d17fdc"},{"path":"product/runtime/auths-gateway/src/separation.rs","sha256":"be9306848ca5d801767cf6aa14247c8618312ef0e202f00ce0c24c4844491061"},{"path":"product/runtime/auths-gateway/src/simulation_attestation.rs","sha256":"88705e5d45415f760f1e3c3a065c35c48f4f4065bf7b3feb7882246983814d6f"},{"path":"product/runtime/auths-gateway/src/store.rs","sha256":"1e5288345c2cb1421aeda277b3158d07607404b0ec46943222ac107b63dcbb46"},{"path":"product/runtime/auths-gateway/src/store_testkit.rs","sha256":"88d82fee42f1b8ef521e8deef0216e938ebeaad822eb2f5020e70b89d145ea70"},{"path":"product/runtime/auths-gateway/src/submit.rs","sha256":"c78dbbba7c45b443febf655056c5edcd635e77be7b21c5b2c318097502415ffe"},{"path":"product/runtime/auths-gateway/src/support.rs","sha256":"9fd979029793a22b15d9776a7fc172476fd7c126a80d4080c65d720845becbcb"},{"path":"product/runtime/auths-gateway/src/transport.rs","sha256":"be2c6dc75b8daec110bf8749fedc3823f6067d40b999aa3eb21126896a97d3ad"},{"path":"product/runtime/auths-kernel-runtime/Cargo.toml","sha256":"926bcd0053e5edd703be8f0027ad009e2982db013c8174c1366edbf38b48087d"},{"path":"product/runtime/auths-kernel-runtime/src/lib.rs","sha256":"7108faae9ca4bc32dc093ddaf885ac8f74f3c9b8d317b7c7d0ed00d1d0ab5972"},{"path":"product/runtime/auths-lifecycle/Cargo.toml","sha256":"c5053c705f8d5554b44e432fe75287a2faf11d644e5a2552e45ad6cd94176af5"},{"path":"product/runtime/auths-lifecycle/src/codec.rs","sha256":"51c4b746749150e8bfcd8ff972b3f6c1ef40bec15583448ec1b471d9ad737dc0"},{"path":"product/runtime/auths-lifecycle/src/digest.rs","sha256":"55282cd7d8aba37713c2dcb5357c9877819edb72a30eadefb860d28d7d3a3eb7"},{"path":"product/runtime/auths-lifecycle/src/identifier.rs","sha256":"31620e8c16de68d3d2d3b84d6353c1a5b9d4151d8247f91fa389b906a8e660f1"},{"path":"product/runtime/auths-lifecycle/src/kernel.rs","sha256":"2abb8c094b36d35b364e74d78091d14c5d6f3d1eb6552cca3b5538dbd017ce23"},{"path":"product/runtime/auths-lifecycle/src/lib.rs","sha256":"afe5a345cd309b5a4f08ffba3170a6d7f16ff914892b3f2006d5208ed24ec736"},{"path":"product/runtime/auths-lifecycle/src/model.rs","sha256":"1af12bbeeeaa65ec02ddcebd7d2c8c92ec1e339fa40ae85b45ab9b01a722a4fa"},{"path":"product/runtime/auths-lifecycle/src/operation.rs","sha256":"78e6d05fcf5d7ea4f148032a3fa26fdfcab77eb346019effe927b08e0d64d732"},{"path":"product/runtime/auths-lifecycle/src/registry.rs","sha256":"53495fe6f7a77422593a41623e28716f1c140dcc1e00f87f6b0ffbfb93a5ef90"},{"path":"product/runtime/auths-lifecycle/src/sealed.rs","sha256":"2e0c03b5813c926c159598bb7890d1523825edbe57cd687d42a5dfb3374a0c19"},{"path":"product/runtime/auths-lifecycle/src/test_support.rs","sha256":"221d9a5c5ef8e1f9f8fd66927484eaf813571d0568470278ecd8fa08a5eec8cd"},{"path":"product/runtime/auths-lifecycle/src/transition.rs","sha256":"011805a28efdd541f44ccea54dd0e34a1e58f4004447ee58013703b4fb6b2822"},{"path":"product/runtime/auths-runtime/Cargo.toml","sha256":"dd29d80a8b4bb56c869f036a6c9998f6e6d1c0383ac5dc03fa42b24abe2a7ff7"},{"path":"product/runtime/auths-runtime/src/lib.rs","sha256":"132ca03d58c14905d3a822a4972f42a22a5ad33a45f2ba9ca44f3a57d810b4b0"},{"path":"product/runtime/auths-runtime/src/production.rs","sha256":"fd4eff4270c571c10fcff6cf27df28961ebf074de8a1a028f500fda1ca376820"},{"path":"product/sdk/auths-approval-quorum/Cargo.toml","sha256":"df904971fca87a24194c5816738a331588fe8f164acb5d70839a35dca5f57114"},{"path":"product/sdk/auths-approval-quorum/src/lib.rs","sha256":"72e4086088a1c0912e4e1a9e980f26a5c280bf5ab16ea39c9f0f58d5096ac2ce"},{"path":"product/sdk/auths-approval-quorum/src/remote.rs","sha256":"9fa029c7c63003adf260f8aec55160c545681c60c1bace0d934e7525862aac7b"},{"path":"product/sdk/auths-approval-quorum/src/remote_tests.rs","sha256":"8a09ce17cfee82a035a74edd535f3ebeb3db0e078784740d3997b17dbdb10197"},{"path":"product/sdk/auths-approval-quorum/src/tests.rs","sha256":"0acbf12be3e497dcc6c2d8f29c9af3b1a7ed8e11b75f6399570d4f217a785060"},{"path":"product/stores/auths-stores/Cargo.toml","sha256":"a32c4b76d17b264be5d40d24497ff237e1ed87822e8bab86229b3db93106dbe3"},{"path":"product/stores/auths-stores/src/gateway_attempt.rs","sha256":"185da8f4a220fba836d5b78a9311f03204681c43a3c53951008084d135bf4d21"},{"path":"product/stores/auths-stores/src/lib.rs","sha256":"e721262edf8a9ab5568ddc27639176312d4a366203b5f73e2d7c11fde2c554e9"},{"path":"product/stores/auths-stores/src/lifecycle.rs","sha256":"94f64d25bc178a9e60ba3c0ee6915d7fb3af7c4468792d76b4e70f43f4de1e2f"}],"schema":"auths.gateway-semantic-closure/1"} \ No newline at end of file +{"files":[{"path":"Cargo.lock","sha256":"0e75e2fdef44e79e57797ac6661295ae58ddb8de4a1990a6fd22ce6c54f78604"},{"path":"Cargo.toml","sha256":"6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24"},{"path":"core/adapters/auths-did-keri/Cargo.toml","sha256":"86ba3e3f9a0a70d970568bfb3113b7ba7bbdd81c3eebbb52743dd574a0c0ecaa"},{"path":"core/adapters/auths-did-keri/src/lib.rs","sha256":"a75674842f8a7142004369ccd206ab43e476459293f0ff4bed4d4e659031b3e3"},{"path":"core/adapters/auths-did-key/Cargo.toml","sha256":"d5a3ae07ecde83f91eed4c3785051dd0f44eab6c891754f3309b6b40596707d7"},{"path":"core/adapters/auths-did-key/src/lib.rs","sha256":"b76a3f4528a725df53cfa9242e6e414e1d26caa48468aaed497e28b121f4497c"},{"path":"core/adapters/auths-raw-key/Cargo.toml","sha256":"f49616bc18c19e6aaa7e6a02ccebcdb9f5c1422c1278ef9869e0dbf22ceda7be"},{"path":"core/adapters/auths-raw-key/src/lib.rs","sha256":"45eec1b295dac3bed65cd79c942870b926b06b3f5d38eaebaeb6140ac69315fa"},{"path":"core/crates/auths-algebra-kernel/Cargo.toml","sha256":"0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba"},{"path":"core/crates/auths-algebra-kernel/src/generated.rs","sha256":"ae4bcbef42a408c7ffa0c6a74a42f7de177a6f14479e51d205acf830bda05960"},{"path":"core/crates/auths-algebra-kernel/src/lib.rs","sha256":"6654667eeb9b353d6648954c9fd2e8838462a82ce6b2803eb49e1366892c68c6"},{"path":"core/crates/auths-assurance/Cargo.toml","sha256":"afcb12a97ddd09d7a264b9ecd3fcaefc865ff2c9b4539ee85b00883420ba333a"},{"path":"core/crates/auths-assurance/src/lib.rs","sha256":"0fb2ec844d674b25a9e20b1601452c89c2454901fa506adfa9bb38ef9a7fa213"},{"path":"core/crates/auths-author/Cargo.toml","sha256":"1e6f0e3bc079ddb558decf0db26b291c6e72fc47327b6df1b7650d41689b215f"},{"path":"core/crates/auths-author/src/lib.rs","sha256":"e14475f2f49715a1869d5fa6b11ff1fbb72497e39097e09f833b0bae7e5b3f2b"},{"path":"core/crates/auths-author/src/observations.rs","sha256":"dda7d6bfa6f4bd7e95a480ca283c2c0e996f69c5c15cb0c7197af328131a7066"},{"path":"core/crates/auths-authority/Cargo.toml","sha256":"4f68212938029f79ebd857b4f3038494eb85d0163d49f07e51376715cf959815"},{"path":"core/crates/auths-authority/src/lib.rs","sha256":"da88d5194de4e17449e69972c0fb042afa3c39798a8f570f30771e77c384f1eb"},{"path":"core/crates/auths-codec/Cargo.toml","sha256":"e20e51826e17814effd9d8925d18d5fbdd6c0d37bf50231e743ec2611314722c"},{"path":"core/crates/auths-codec/src/approval.rs","sha256":"fbff43bf4d57f69f8b7738a8647751cde75c5a932dee65d924a1fe9c7202f91f"},{"path":"core/crates/auths-codec/src/bounded_policy.rs","sha256":"d21f6728be2d8a04b6d94921f2b683f7e61cbb42e0ac6866f1c88a49caa534c3"},{"path":"core/crates/auths-codec/src/decode.rs","sha256":"ba2999584cdf53b1b517ecb9c7ea50d39efee17c666a9a38e2ad1ac94379f778"},{"path":"core/crates/auths-codec/src/encode.rs","sha256":"8491192053e2e15d62b4d2a491de22405b7487ead69ab6f6bca40669ce7ca5f7"},{"path":"core/crates/auths-codec/src/error.rs","sha256":"fecb0737c16deb42d859f1dc7727c698438d9ac12064fd99e0024629642c390c"},{"path":"core/crates/auths-codec/src/hash.rs","sha256":"f88e111f1dbb2cef6b7b5e9c948cb45ff92e366710c8a5f5c636138aa748479e"},{"path":"core/crates/auths-codec/src/lib.rs","sha256":"3b0e5c94c6f34f750b88a9333e1d5c8145746d845d3a23e0d2f61807cf592ea7"},{"path":"core/crates/auths-codec/src/observation.rs","sha256":"38328b0c71ff97a4196eeade8b4faa889527ff1f80bb168468bcd49082a3987e"},{"path":"core/crates/auths-composition/Cargo.toml","sha256":"331e13025eb82588b5269ed3975929eb41c823d588c49e4c296273d85c6fe80e"},{"path":"core/crates/auths-composition/src/lib.rs","sha256":"e42e3b0b6a9985b73c533aeb23799c638979aa27a9ce7d0f10a8d60340570fb1"},{"path":"core/crates/auths-model/Cargo.toml","sha256":"565c15302b0cc9270db1e28efa3862804846850ba933cc17aea8abcec4a65987"},{"path":"core/crates/auths-model/src/approval.rs","sha256":"54cf44a9ef747ec21546a4086aecfb130bc7803b0d646430e6082df51e6e305f"},{"path":"core/crates/auths-model/src/bounded.rs","sha256":"f90496abc0a06c028b4d850af6ddab7d850bfafeaa3d042f1b1246a41d8bbbc9"},{"path":"core/crates/auths-model/src/bounded_policy.rs","sha256":"306a8f049cc7cfc7635fe0e4de47eb7813eed63d3c14c3be2b51586aa4eea450"},{"path":"core/crates/auths-model/src/lib.rs","sha256":"e7cfe6bb9574c6b016aa63e70658c31e0b90903ec6479a49f4a2ceb64f5bad97"},{"path":"core/crates/auths-model/src/observation.rs","sha256":"b3ed3e3cc090afca2896a7d3de7988afccc1ee1ea0ebd91b51a8bc0f20ad8dbb"},{"path":"core/crates/auths-multikey/Cargo.toml","sha256":"858756c1197befcada06134742bffe8d58cf674cadd6c046bf710570e96efaf2"},{"path":"core/crates/auths-multikey/src/lib.rs","sha256":"f5177fffb11e40eeaaa665ba886c541fc1f24d5eacdd6983fb03dc20148733f0"},{"path":"core/crates/auths-ports/Cargo.toml","sha256":"596a9b0f5af3717c16a6d13f7054d8a106bcd9f01f5f72c2235dd2afcf0ab16c"},{"path":"core/crates/auths-ports/src/binding.rs","sha256":"a16c012d40aa4249e3ec54372b9611006d0bfe8c7dc3c741911c2194ad17736d"},{"path":"core/crates/auths-ports/src/diagnostics.rs","sha256":"aa596572503b5a65a918bb2ff38281c144ff53821ee914e9325c852828d852df"},{"path":"core/crates/auths-ports/src/lib.rs","sha256":"8da1debf86f9532df0660155d04298beb1ba3a1204508f8586e2e67cd2fb3449"},{"path":"core/crates/auths-ports/src/path.rs","sha256":"b68fc547b4e4d97a60cbbc1cc1939fc6b34a8233b81f840bd396914a707e3ea1"},{"path":"core/crates/auths-raw-key-core/Cargo.toml","sha256":"98c0bc8527a537512e43a74dd6ba9658c6f0cdc16610cf938e3f9b43785d836d"},{"path":"core/crates/auths-raw-key-core/src/lib.rs","sha256":"98c0500c41697aae28708ad0bf970b9a97583d96a3d2c18d23e7fa351e0f7d12"},{"path":"core/crates/auths-registries/Cargo.toml","sha256":"590e49e58b0622d9d6274fea46796dcdb07dec9550eff295cce6a6427ffa51e2"},{"path":"core/crates/auths-registries/src/lib.rs","sha256":"450d3886d85ee333b7e046317fb5b47cde62483d5f3e41d46265e2caf4c373ec"},{"path":"core/crates/auths-registries/src/template.rs","sha256":"1224039dd2b3ce6fa8357613d8cafbae40400493da7176da202b9ade62fa05e4"},{"path":"core/crates/auths-signature-core/Cargo.toml","sha256":"6bee2230eb30af1be0bd5c2d57bd3e1903497a70028d47290d4ac6e9e0e8bca0"},{"path":"core/crates/auths-signature-core/src/lib.rs","sha256":"6e3f9311ded5e49ea50d445eb21e6d8fa12442aa4362a73e0cb6fda15b7cd865"},{"path":"core/crates/auths-signature/Cargo.toml","sha256":"7f7b5682466ba439d8c59579022cb61068cad9fb4bd2d73e1cc21327c902b450"},{"path":"core/crates/auths-signature/src/lib.rs","sha256":"b3d9ac4cc3ba0797b9e1c09f2d6ac05089b25dac4e285a5af28c0165b33d925b"},{"path":"core/crates/auths-verifier/Cargo.toml","sha256":"c43358e06a33324b41a8b93e5cc7279c55f7d21f1f6cfaa539a3fc7b4c27a38f"},{"path":"core/crates/auths-verifier/src/approval.rs","sha256":"c3cae6a49e169051eb555bb092b1069a4d422516d6a2114623a89e5f31ff923f"},{"path":"core/crates/auths-verifier/src/causal.rs","sha256":"9635230f33b13a263573d319ac8a1976addbcc07677514a43e3c7bf28dc04587"},{"path":"core/crates/auths-verifier/src/lib.rs","sha256":"f22dec38dfa47ced8da4f605390da8453273bee1da010f57fd1fdfcb10e0b389"},{"path":"core/crates/auths-verifier/src/observation.rs","sha256":"0bb07f06a0f9524c88427df1c972b1de8ba038a9eeeb15d3134c25125ae84b1e"},{"path":"core/crates/auths-verifier/src/trace.rs","sha256":"2213d72023a1d9e0413a2cf2c51c3dad9e04775d86033a0caaa9d29a8f0036f8"},{"path":"exchange/crates/auths-proof-exchange-model/Cargo.toml","sha256":"34b2db64f93a288e942b5a3918d28cdcbef906e0dc9074ce848018d3d5f7a1fa"},{"path":"exchange/crates/auths-proof-exchange-model/src/lib.rs","sha256":"49fac5aff2339d3a57c41cb8bb2a82852538e8f77ecc4b157c88e264ff31fb55"},{"path":"exchange/crates/auths-proof-exchange-port/Cargo.toml","sha256":"7ff660f1b7579dc570c791090aeb450404fbbf44c92781e289f5ccdde746d739"},{"path":"exchange/crates/auths-proof-exchange-port/src/lib.rs","sha256":"b408fb40c6432edc1facb3d8b3e9433a033f8dc73fe2e0ba5a88c972ca675021"},{"path":"product/config/auths-config/Cargo.toml","sha256":"e4b568ab9f6d84f7d7e6d66443fe825f360db9c27bc7c31d6ddc0647ba3ab304"},{"path":"product/config/auths-config/src/lib.rs","sha256":"fecf00ea65cef9018fda9af2063326d7065b869266d0d9e73a4f06816f1102cc"},{"path":"product/errors/auths-errors/Cargo.toml","sha256":"3b3a199b6460ba75bda84475bb5accd35e1485448a3981038db85bf4772dd350"},{"path":"product/errors/auths-errors/src/lib.rs","sha256":"7feeb9069fa4003f94f1f07c1c94619cf1c883e0dbaaf2187f04d0f742264bdd"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/Cargo.toml","sha256":"716f1f2a117d6d69d8effe9ee9057e24ba3502f20af6a602b06facb638cdabed"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/api.rs","sha256":"9ea61dd7ddd93282b073b98e453e6b75b26dc49689c04e9782435d06a3a09e48"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/clock.rs","sha256":"73f0a6e0f5903883329fa6683f5888288f759512ac69e5c87efd2b6b87f7d79f"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/http.rs","sha256":"14c1fce14e24c984b2a275563a29b6326fb08367922b6e8d37ba38b9cb81aa2b"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/identity.rs","sha256":"186de11230c8b33375951c4368609f8976bf9795f171af3fd7fac26207a94361"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs","sha256":"0b4617d044f5254a5ab22f5a2578f91cc025206a8c1845be39c1c56dcdf7a5df"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/names.rs","sha256":"41bb23572d6002e23ee103d6fe70ecd68764861c6f2e48a1c53af998270a4afa"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs","sha256":"39fed883f4802e68d3b41a68fea0aba0737810996b33d13577de70faba004c29"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/store.rs","sha256":"fc60ee9c49b2f4f063c449b4c78100c5c4872779e94ca168f796603b380ef6e4"},{"path":"product/integrations/auths-custody/Cargo.toml","sha256":"1e14034185ad1ec24a977fd5f41d0abee219606245c046ce2a82287fadef448b"},{"path":"product/integrations/auths-custody/src/conformance.rs","sha256":"8ed1afd58f18fc6becc268908aa6419c9aa404c79da0197963eb2599df44acf6"},{"path":"product/integrations/auths-custody/src/key.rs","sha256":"70cbb0fd21b6f5652157845a22c35be2d0f6c05b3d138fc4b9bb6dbdc3d81c40"},{"path":"product/integrations/auths-custody/src/lib.rs","sha256":"8ee593c1f59b0fd2126bdda9138026f5bc531beb64d4489a99785842e7b98b43"},{"path":"product/operations/auths-operations/Cargo.toml","sha256":"73dde1e914ba5e1386f8d49c0d730423cc72ae77ec44c6554a6a75cc8e8922b1"},{"path":"product/operations/auths-operations/src/explanation.rs","sha256":"b4a39bcbd5712cb9e735ee7deeb281f3fa6af5ddca973735bf3d87dce427ef11"},{"path":"product/operations/auths-operations/src/lib.rs","sha256":"3f401a56555113b98f57bca172a2660eaecedf76247b83a3fdbb089c133a29cd"},{"path":"product/operations/auths-operations/src/render/json.rs","sha256":"2ae042639960afee123730e945d373bc5dda1d2b3af20ae16c939a7e99b9e418"},{"path":"product/operations/auths-operations/src/render/mod.rs","sha256":"b3b7f6fe473f49227ace5a68bfc3d8dc14b5db8dd9888fd9e207070337b1b8bf"},{"path":"product/operations/auths-operations/src/render/text.rs","sha256":"f216cf3bdb00e264523271b16e7059535ac6b1aabf271cebd7935af155e4bfec"},{"path":"product/policy/auths-bounded-policy/Cargo.toml","sha256":"babd5d200923137ead71d8c2528f847cea323ce98da942a1320b054436612c47"},{"path":"product/policy/auths-bounded-policy/src/arithmetic.rs","sha256":"75e43c5d4eab8d1f71c1daf53839f5f9fe45a400afc1f63a30c6f55ce3632627"},{"path":"product/policy/auths-bounded-policy/src/commitment.rs","sha256":"c5706f2d583454e1a7f570f7ada138d4d864bef0205dfae7c1296774f396bb3f"},{"path":"product/policy/auths-bounded-policy/src/eligibility.rs","sha256":"c9acdfb793074e687fc36efad506be27dbd99ffbf40387bc66c8de39ef238432"},{"path":"product/policy/auths-bounded-policy/src/identifier.rs","sha256":"0006a32bae9eb16c4178cf797df418d2b0a781f2bc6474b741dc1a908141831c"},{"path":"product/policy/auths-bounded-policy/src/kernel.rs","sha256":"99187c28b161ac70bee1afed60711f7f645adb4d1671a01863f9849b369811d5"},{"path":"product/policy/auths-bounded-policy/src/lib.rs","sha256":"76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c"},{"path":"product/policy/auths-bounded-policy/src/receipt.rs","sha256":"3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad"},{"path":"product/policy/auths-bounded-policy/src/registry.rs","sha256":"4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0"},{"path":"product/profiles/auths-profile-api/Cargo.toml","sha256":"7ae85761f58625b5d678f961fd052eebf3e000ef565c7312e3ac857763c0017f"},{"path":"product/profiles/auths-profile-api/src/lib.rs","sha256":"a194b82b20bf8aa864c2334ef6c6aec30b2154ded972862252d5dcefa488ab95"},{"path":"product/profiles/auths-profile-mcp/Cargo.toml","sha256":"db264fc25242f7b7e4133cbe5782545b3107b406c87168ae072683cfb59eac66"},{"path":"product/profiles/auths-profile-mcp/src/arguments.rs","sha256":"a5de696586d507e2aee4a49fee99ef1ef4c51a2e46603f8838f1af6d9009833f"},{"path":"product/profiles/auths-profile-mcp/src/lib.rs","sha256":"d0f8b733a09ef8408336cdebc8948d6a5861012ce6878598b11be7084dfd4280"},{"path":"product/profiles/auths-profile-mcp/src/session.rs","sha256":"166c281fa66333388e4760d6098dad02d3359e1d5de4b8f93312c014f97abb03"},{"path":"product/qualification/auths-recipe-qualification/Cargo.toml","sha256":"b7b15b30b9a3d96d4f089d514266d3a892de6608d30707aa44be31cca89ca9fe"},{"path":"product/qualification/auths-recipe-qualification/src/canonical.rs","sha256":"30a9b50777f0dcb4b606abfee2467d5a975d9f6ad941ab6c13ca3df5b359f667"},{"path":"product/qualification/auths-recipe-qualification/src/closure.rs","sha256":"0ad6aee9bd981e2863fa725f209ec84031db2ff12f4c7ac3aaf5120f0bb86039"},{"path":"product/qualification/auths-recipe-qualification/src/commissioning.rs","sha256":"e902df9b2c6bd06bedd32ef40e23ce14b4db4882dcb12b0f0aabcb7335cfa515"},{"path":"product/qualification/auths-recipe-qualification/src/commissioning/tests.rs","sha256":"5a226725c2ad7ce920d0bd62d427185e007f4d0949b0f0ec1260aa161d3114d0"},{"path":"product/qualification/auths-recipe-qualification/src/error.rs","sha256":"52d5cf720a1e4579008fdda90a3ac2c31f0b8db57985f121f65e54b4da2b7dd1"},{"path":"product/qualification/auths-recipe-qualification/src/evidence.rs","sha256":"ba45a7409d67a8af26ab811af306412014557477a101ab2a8eb0faf8f2bd4b91"},{"path":"product/qualification/auths-recipe-qualification/src/ids.rs","sha256":"e81a906d571497ab2da753e1532d4443706410e0b75fdd59a7d2d788c7aec403"},{"path":"product/qualification/auths-recipe-qualification/src/launch.rs","sha256":"41f2e2de90e1e7d6440a66eda3eb9bea8d5e0741bc232305a76a363ab5f813c1"},{"path":"product/qualification/auths-recipe-qualification/src/lib.rs","sha256":"7ef5cb7b8eacaa38c5d512b589db5e78e4597aed7d1a10368b86eebfb5a48aeb"},{"path":"product/qualification/auths-recipe-qualification/src/model.rs","sha256":"3484eb0ec287b23d4682ade7b1b0f8d1335985b3fb180f06fc28716076957d5f"},{"path":"product/qualification/auths-recipe-qualification/src/release.rs","sha256":"ec478e53f70052e566aac7e15be2f9e1b1cd46837ac6990ae955fa864d311586"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/mod.rs","sha256":"fa23a962fd90331152eed5edbcdf271955f7aed79b8da1e065bfe69a20b487a9"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/schemas.rs","sha256":"c59feec2805621f341a90f81fc005e2c12f7a70f9d264fdeacccb2be4fe1c046"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/verification.rs","sha256":"6a6b5834c5dae10af1ba8939b2deae43b85db71544dc8f077ff63b7fe68ac8a8"},{"path":"product/qualification/auths-recipe-qualification/src/verify.rs","sha256":"2ec2784435d11e07295de77b2ee1b2c48b2fcf9609a00454c6e7374b621aed5c"},{"path":"product/receipts/auths-receipts/Cargo.toml","sha256":"6001fa1375899953aafcb07c23a6da0c8f57ea7ec08bb9c950b12a60a8cc6f0f"},{"path":"product/receipts/auths-receipts/src/disclosure.rs","sha256":"ba9ed439be0a320c8a01f5b6e9b51361c1a37e076947490d8e4a484ba6bb119c"},{"path":"product/receipts/auths-receipts/src/lib.rs","sha256":"547a57c4160256719cafb7d0ab972d9fc80b0da14fbbce4148c70c414070ff36"},{"path":"product/runtime/auths-connections/Cargo.toml","sha256":"babeb6e1dda3dfb66291713ce1e43dce5c349833d0b50ea4dccbf986030026b2"},{"path":"product/runtime/auths-connections/src/credential.rs","sha256":"82921413bb053f0f6c7931fbd4e6a86c8cc1d8c6b51debd9c2cef33a8d5b1c51"},{"path":"product/runtime/auths-connections/src/kernel.rs","sha256":"a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8"},{"path":"product/runtime/auths-connections/src/lib.rs","sha256":"79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22"},{"path":"product/runtime/auths-connections/src/model.rs","sha256":"de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77"},{"path":"product/runtime/auths-connections/src/registry.rs","sha256":"e57640e003e72ad3235c567c2bb944a262bd64e673f023b62ea091094cc7e946"},{"path":"product/runtime/auths-gateway-kernel/Cargo.toml","sha256":"34f864e67656af4ac7e5c7a347a23f01fc8ab31365b8e23c0ef474483b14a183"},{"path":"product/runtime/auths-gateway-kernel/src/construct.rs","sha256":"e9d65744bae273d65face4285e5d2da75c06a92ab48f7b8333d496604e31c63c"},{"path":"product/runtime/auths-gateway-kernel/src/lib.rs","sha256":"cfda6f8453426564c085475f183b6f790b438768a19668f1b65d33ba59dc8632"},{"path":"product/runtime/auths-gateway-kernel/src/order.rs","sha256":"e0045f877c4b7fe3860c291039853885064ddcdebba7c9b345ab65e81e646dda"},{"path":"product/runtime/auths-gateway-kernel/src/outcome.rs","sha256":"e9785b1afe70788c89b51b18655bcd5acff7b0c8e3d12fb79c6f05a202e67e6b"},{"path":"product/runtime/auths-gateway-kernel/src/ratio.rs","sha256":"7ace22264812e6fc1ef3a62afee402cf43494bb71ae0d3de219ad1b39d690bcb"},{"path":"product/runtime/auths-gateway-kernel/src/recovery.rs","sha256":"9f46dcd1685ab6e4d1ba04a3fc286a9f3afee8fb47829be1fbc670a7926a2dc6"},{"path":"product/runtime/auths-gateway-kernel/src/transition.rs","sha256":"cefb8f01d915880f6921f2501ff881ad94b9de61072c34d9cd19220992f97374"},{"path":"product/runtime/auths-gateway/Cargo.toml","sha256":"00b28be86921dcdc0ad90cce0c62c2961cafefe96ea6c2edf0e926c3d405ccad"},{"path":"product/runtime/auths-gateway/src/admin.rs","sha256":"2d5cc67afac42fbd15f36e2d1693cd1b20cedacf775040dce6ffe04ccc94c9ea"},{"path":"product/runtime/auths-gateway/src/app.rs","sha256":"6f80f63833ea0815bb44fbf3b0cc54624a08e9fb578b035819f2980dc04e8256"},{"path":"product/runtime/auths-gateway/src/audit.rs","sha256":"0edb2037eb7b5d6f13acfce85c54f62a82bf7fdd31bc7e626c4fec183cef61dd"},{"path":"product/runtime/auths-gateway/src/audit_tests.rs","sha256":"990969384a52d75bc2489d9d412a9e7dd814bca1c8f65c701d6205fae62a15d5"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway-harness.rs","sha256":"12b0c24d36b2e6a3be392d3c081a783b355fdd67dc5b54bacc0410e803116b8c"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway.rs","sha256":"2f33a1da5dd54947ee1664795f90b3f07a11bb9ee184774bf470b78b03600f0c"},{"path":"product/runtime/auths-gateway/src/binding.rs","sha256":"663b0ce878319511aa7d05722ab4ab2fa9be18817884ffb2ee9f131ff1e382d1"},{"path":"product/runtime/auths-gateway/src/bounds.rs","sha256":"9cfa0eae4973e5e047a198360b22f041708fa20276b0b90c2ec440f06915d64b"},{"path":"product/runtime/auths-gateway/src/bounds_aggregate_tests.rs","sha256":"ab34f227b7c8692ba1da88ccb32bb3687a66adf8353d8282fae905d4a88eb612"},{"path":"product/runtime/auths-gateway/src/bounds_tests.rs","sha256":"74136bc570da7b9338b5a1a1ed9d3fd892c55135160964f9d3ac0e2cf5741375"},{"path":"product/runtime/auths-gateway/src/commissioning_budget.rs","sha256":"272bc25811931effb2d4416567c5d2e76df5ab2cc69b860b43f3bbeffb0779eb"},{"path":"product/runtime/auths-gateway/src/commissioning_budget/tests.rs","sha256":"ad182c391b70450582c6ca06e3dadc221409bb3cdbc3c7668dbfc7fbedf63505"},{"path":"product/runtime/auths-gateway/src/connection.rs","sha256":"7b5d049c258a26ed1c93ecf860f51d051a8a65f9b93554af0b1ea93862398ec9"},{"path":"product/runtime/auths-gateway/src/credential_journal.rs","sha256":"7297fccaee5cd8622928e8e0a42bba50da7941970a6f682ecd300c41ee6509da"},{"path":"product/runtime/auths-gateway/src/echo_verify.rs","sha256":"6d453051665f823abd7354d5c50031d9524cf47d6092d2f09080ae814e3b9575"},{"path":"product/runtime/auths-gateway/src/engine.rs","sha256":"f1052aaef43e441b9e0befa3f8ad1e2fd5279a27cb9d63aac0cf9dfdbe85a052"},{"path":"product/runtime/auths-gateway/src/fuzzing.rs","sha256":"ed3b0028487eb546a3b0a91d115aa8f18bcea324b61620bfe8e35a9e6ab18758"},{"path":"product/runtime/auths-gateway/src/generation_floor.rs","sha256":"fe1510ec96ce0f67e9a78edbfa94b33eb7df64c0ac4d0a67901124dcd0164777"},{"path":"product/runtime/auths-gateway/src/harness.rs","sha256":"c87e479f3eb281960f6c9c80d43c7560d7ccb654b0154ec823d3fcec4884ac05"},{"path":"product/runtime/auths-gateway/src/lib.rs","sha256":"5bc8905afe68e463bf070394eae26f6d0a49ea8d3a0265951db0228cf29d3a97"},{"path":"product/runtime/auths-gateway/src/listener.rs","sha256":"aa08239bcbc1fcb55e8a212fbdf6a84f12985b0d436dcb51dc58b06e59e435f2"},{"path":"product/runtime/auths-gateway/src/observed_tests.rs","sha256":"a22be071695f89ca2578a4d82fd80d9cb82289213c9bdb8f0470f6b2dc3d9201"},{"path":"product/runtime/auths-gateway/src/observer.rs","sha256":"562ffcaea071c3856e0708dc2fe33516917e145d2438aabb75af0a2b6ba01046"},{"path":"product/runtime/auths-gateway/src/onboarding.rs","sha256":"0dfd7d67e7f02f18a28d1c86ca1b7751d7463f5efcdbe3825de0ad8cbccb3891"},{"path":"product/runtime/auths-gateway/src/operator.rs","sha256":"c3c36954a3e86723df035b47f43b85fc8ab3a6292983522b6258d5c6b4e6c4e4"},{"path":"product/runtime/auths-gateway/src/pending_vectors/attempts.rs","sha256":"47ef3c8cb1c5504d47ae9a0088705ce6715fe86bac1671a34a56fb38a64d0dd3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/bounds.rs","sha256":"e612217307e1da5b0eb5ee6582a7458bb064b8aa8a529fc6555b1b334127ab68"},{"path":"product/runtime/auths-gateway/src/pending_vectors/codes.rs","sha256":"e00670a5ef24eb856cc2c6dcda8e5a263842f55c76bb939c0c27bd9df37e5522"},{"path":"product/runtime/auths-gateway/src/pending_vectors/keys.rs","sha256":"f84c56f2ea9cb34b2b79c72d13fbf2c6585010ec1ed450af58a78c80c1ea1edd"},{"path":"product/runtime/auths-gateway/src/pending_vectors/mod.rs","sha256":"5de8340f0ef71a0b57a09e323fefe473d3160c6ae952b9ba46f714825fbacafc"},{"path":"product/runtime/auths-gateway/src/pending_vectors/outcomes.rs","sha256":"8ec07b9511b48913af36ac999d2aa0e82924289f6acb23ddaeb9f00f99815166"},{"path":"product/runtime/auths-gateway/src/pending_vectors/production.rs","sha256":"772d032e0a0d9c924fb6d6c188528db85a97e71c9e466ddc19eee277baf83614"},{"path":"product/runtime/auths-gateway/src/pending_vectors/recipes.rs","sha256":"51693208270231c25c3aef2a32151d5962114c71e86b88cb9df83181c7af83d9"},{"path":"product/runtime/auths-gateway/src/pre_entry.rs","sha256":"06ea78ca140468bfaba17d9ab04912ad68673954c3203c98fed28272ff2a00c0"},{"path":"product/runtime/auths-gateway/src/property_tests.rs","sha256":"939c081e2e154aaf10186754044bdd65608932c899b970a04a71d0afaa999a93"},{"path":"product/runtime/auths-gateway/src/qualification.rs","sha256":"0f7eaf3c849ee7eecbebbbe0027f8b1bb65b87da23b2345d610ae088f2db8239"},{"path":"product/runtime/auths-gateway/src/qualification_simulation.rs","sha256":"4ee7cadfb5f46a92713c80f3e55f499cb074d04d8b21ea89d57762af38642bfa"},{"path":"product/runtime/auths-gateway/src/qualification_tests.rs","sha256":"a9178a2e58eea459d5e5dafc53a3999ea7c84dbbffefe6e5eb1f3d098827f028"},{"path":"product/runtime/auths-gateway/src/quorum_tests.rs","sha256":"a78380b019104d688c11a4410082c7e08ded3106aab099954c4f8a1b4ae0fd89"},{"path":"product/runtime/auths-gateway/src/readiness.rs","sha256":"911c3f11892f94641574375e2da4c671c802738f71082f12c39832331052d43d"},{"path":"product/runtime/auths-gateway/src/recipe.rs","sha256":"fecf9af67e7afc48d080e9f8f55f8ce28e49d0e08988717a27908bbda461d6b6"},{"path":"product/runtime/auths-gateway/src/recipe/lower.rs","sha256":"8088b8751ed831dbb48247af953c6290ac95e2a438ccd5bd65eff54be06a1fd1"},{"path":"product/runtime/auths-gateway/src/recipe/review.rs","sha256":"c3eb7d9fdd98dacf52750b14b67ad7b7faaecbbdeafff1e0b049f67d0a2d0139"},{"path":"product/runtime/auths-gateway/src/recipe/runtime.rs","sha256":"c286f0d15f974402822c0810d8e97f98411dc1c557755cc23e540d85e2bb42d9"},{"path":"product/runtime/auths-gateway/src/recipe/source.rs","sha256":"1af50298fb1461e1b24cbdf560d43124d6b1c4c529586c911b1c4797214a69ff"},{"path":"product/runtime/auths-gateway/src/recipe/tests.rs","sha256":"aac551a2481bbc60864c64079bc667dcb232e45a0f41a04073ed84ab5dbe1fce"},{"path":"product/runtime/auths-gateway/src/recipe/validate.rs","sha256":"3711b17605cb7b0d639bc1b180449231f5882a306cab20e2c7782155cc63b0d4"},{"path":"product/runtime/auths-gateway/src/scenario_tests.rs","sha256":"67915828ecfe2be0afadb5525277ab205f91172edc90852ec7b77c63b2d17fdc"},{"path":"product/runtime/auths-gateway/src/separation.rs","sha256":"be9306848ca5d801767cf6aa14247c8618312ef0e202f00ce0c24c4844491061"},{"path":"product/runtime/auths-gateway/src/simulation_attestation.rs","sha256":"88705e5d45415f760f1e3c3a065c35c48f4f4065bf7b3feb7882246983814d6f"},{"path":"product/runtime/auths-gateway/src/store.rs","sha256":"884bcad4d70d53e12eae9c8517f6ecd0643068ee0be0370015119d04d6cc2516"},{"path":"product/runtime/auths-gateway/src/store_testkit.rs","sha256":"88d82fee42f1b8ef521e8deef0216e938ebeaad822eb2f5020e70b89d145ea70"},{"path":"product/runtime/auths-gateway/src/submit.rs","sha256":"c78dbbba7c45b443febf655056c5edcd635e77be7b21c5b2c318097502415ffe"},{"path":"product/runtime/auths-gateway/src/support.rs","sha256":"9fd979029793a22b15d9776a7fc172476fd7c126a80d4080c65d720845becbcb"},{"path":"product/runtime/auths-gateway/src/transport.rs","sha256":"be2c6dc75b8daec110bf8749fedc3823f6067d40b999aa3eb21126896a97d3ad"},{"path":"product/runtime/auths-kernel-runtime/Cargo.toml","sha256":"926bcd0053e5edd703be8f0027ad009e2982db013c8174c1366edbf38b48087d"},{"path":"product/runtime/auths-kernel-runtime/src/lib.rs","sha256":"7108faae9ca4bc32dc093ddaf885ac8f74f3c9b8d317b7c7d0ed00d1d0ab5972"},{"path":"product/runtime/auths-lifecycle/Cargo.toml","sha256":"c5053c705f8d5554b44e432fe75287a2faf11d644e5a2552e45ad6cd94176af5"},{"path":"product/runtime/auths-lifecycle/src/codec.rs","sha256":"51c4b746749150e8bfcd8ff972b3f6c1ef40bec15583448ec1b471d9ad737dc0"},{"path":"product/runtime/auths-lifecycle/src/digest.rs","sha256":"55282cd7d8aba37713c2dcb5357c9877819edb72a30eadefb860d28d7d3a3eb7"},{"path":"product/runtime/auths-lifecycle/src/identifier.rs","sha256":"31620e8c16de68d3d2d3b84d6353c1a5b9d4151d8247f91fa389b906a8e660f1"},{"path":"product/runtime/auths-lifecycle/src/kernel.rs","sha256":"2abb8c094b36d35b364e74d78091d14c5d6f3d1eb6552cca3b5538dbd017ce23"},{"path":"product/runtime/auths-lifecycle/src/lib.rs","sha256":"afe5a345cd309b5a4f08ffba3170a6d7f16ff914892b3f2006d5208ed24ec736"},{"path":"product/runtime/auths-lifecycle/src/model.rs","sha256":"1af12bbeeeaa65ec02ddcebd7d2c8c92ec1e339fa40ae85b45ab9b01a722a4fa"},{"path":"product/runtime/auths-lifecycle/src/operation.rs","sha256":"78e6d05fcf5d7ea4f148032a3fa26fdfcab77eb346019effe927b08e0d64d732"},{"path":"product/runtime/auths-lifecycle/src/registry.rs","sha256":"53495fe6f7a77422593a41623e28716f1c140dcc1e00f87f6b0ffbfb93a5ef90"},{"path":"product/runtime/auths-lifecycle/src/sealed.rs","sha256":"2e0c03b5813c926c159598bb7890d1523825edbe57cd687d42a5dfb3374a0c19"},{"path":"product/runtime/auths-lifecycle/src/test_support.rs","sha256":"221d9a5c5ef8e1f9f8fd66927484eaf813571d0568470278ecd8fa08a5eec8cd"},{"path":"product/runtime/auths-lifecycle/src/transition.rs","sha256":"011805a28efdd541f44ccea54dd0e34a1e58f4004447ee58013703b4fb6b2822"},{"path":"product/runtime/auths-runtime/Cargo.toml","sha256":"dd29d80a8b4bb56c869f036a6c9998f6e6d1c0383ac5dc03fa42b24abe2a7ff7"},{"path":"product/runtime/auths-runtime/src/lib.rs","sha256":"132ca03d58c14905d3a822a4972f42a22a5ad33a45f2ba9ca44f3a57d810b4b0"},{"path":"product/runtime/auths-runtime/src/production.rs","sha256":"fd4eff4270c571c10fcff6cf27df28961ebf074de8a1a028f500fda1ca376820"},{"path":"product/sdk/auths-approval-quorum/Cargo.toml","sha256":"df904971fca87a24194c5816738a331588fe8f164acb5d70839a35dca5f57114"},{"path":"product/sdk/auths-approval-quorum/src/lib.rs","sha256":"72e4086088a1c0912e4e1a9e980f26a5c280bf5ab16ea39c9f0f58d5096ac2ce"},{"path":"product/sdk/auths-approval-quorum/src/remote.rs","sha256":"9fa029c7c63003adf260f8aec55160c545681c60c1bace0d934e7525862aac7b"},{"path":"product/sdk/auths-approval-quorum/src/remote_tests.rs","sha256":"8a09ce17cfee82a035a74edd535f3ebeb3db0e078784740d3997b17dbdb10197"},{"path":"product/sdk/auths-approval-quorum/src/tests.rs","sha256":"0acbf12be3e497dcc6c2d8f29c9af3b1a7ed8e11b75f6399570d4f217a785060"},{"path":"product/stores/auths-stores/Cargo.toml","sha256":"a32c4b76d17b264be5d40d24497ff237e1ed87822e8bab86229b3db93106dbe3"},{"path":"product/stores/auths-stores/src/gateway_attempt.rs","sha256":"218841602d3d9b23b44625f50e5b54cf275ccedc2d5c89f02d2482b8524472af"},{"path":"product/stores/auths-stores/src/lib.rs","sha256":"e721262edf8a9ab5568ddc27639176312d4a366203b5f73e2d7c11fde2c554e9"},{"path":"product/stores/auths-stores/src/lifecycle.rs","sha256":"3f2cecfda13fdcd7c4a944518646bcc8abd1237f900c0332d5822281f8f9f1cd"}],"schema":"auths.gateway-semantic-closure/1"} \ No newline at end of file diff --git a/product/runtime/auths-gateway/src/commissioning_budget.rs b/product/runtime/auths-gateway/src/commissioning_budget.rs new file mode 100644 index 000000000..8ce88bdd8 --- /dev/null +++ b/product/runtime/auths-gateway/src/commissioning_budget.rs @@ -0,0 +1,397 @@ +//! Permanent commissioning consumption on the existing opaque atomic store. +//! +//! This component reserves capacity; it neither leases a credential nor opens +//! the ordinary qualification gate. The authenticated operator creates the +//! record once during fresh setup. Runtime opening never initializes missing +//! state. Before custody, a private commissioning session must persist each +//! returned snapshot as a host-local floor retained independently of database +//! restores. A claimed unit is never refunded, including a crash before lease. + +use crate::{ + GatewayAttemptError, GatewayAttemptKey, GatewayAttemptStore, GatewayInsert, GatewayRecordEntry, + GatewayRecordKind, +}; +use auths_recipe_qualification::{ + CommissioningBinding, CommissioningRefusal, CommissioningRequest, MAX_REVOKED_SIGNERS, + QualificationSignerId, Sha256Digest, VerifiedCommissioningPermit, VerifierState, +}; +use serde::{Deserialize, Serialize}; +use std::{collections::BTreeSet, sync::Arc}; + +/// The permanent counter/floor format, separate from qualifications and attempts. +pub const COMMISSIONING_BUDGET_SCHEMA: &str = "auths.gateway-commissioning-budget/1"; +/// Fixed record limit checked before decoding store or floor bytes. +pub const MAX_COMMISSIONING_BUDGET_BYTES: usize = 16 * 1024; +/// A claim makes at most this many compare-and-swap attempts under contention. +pub const MAX_COMMISSIONING_CLAIM_RETRIES: usize = 16; + +/// A closed refusal before any credential acquisition. +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum CommissioningBudgetRefusal { + /// The signed authority does not satisfy its current runtime check. + Permit(CommissioningRefusal), + /// Shared state could not be read or committed. + Unavailable, + /// Required permanent registration is absent; runtime never recreates it. + Missing, + /// Noncanonical, malformed or inconsistent stored/floor state. + Corrupt, + /// A renewal changed the immutable binding or capacity at the run's key. + BindingMismatch, + /// Database consumption/time/revocation state is below the retained floor. + Rollback, + /// The lifetime ceiling has already been consumed. + Exhausted, + /// Bounded contention retries ended; no lease was authorized by this call. + Contention, +} + +impl CommissioningBudgetRefusal { + /// Stable commissioning code. These are never qualification verdicts. + #[must_use] + pub const fn code(self) -> &'static str { + match self { + Self::Permit(CommissioningRefusal::Unavailable) => "gateway.commissioning.unavailable", + Self::Permit(CommissioningRefusal::Revoked) => "gateway.commissioning.revoked", + Self::Permit(CommissioningRefusal::RevocationRollback) => { + "gateway.commissioning.revocation-rollback" + } + Self::Permit(CommissioningRefusal::ClockUntrusted) => { + "gateway.commissioning.clock-untrusted" + } + Self::Permit(CommissioningRefusal::RevocationStale) => { + "gateway.commissioning.revocation-stale" + } + Self::Permit(CommissioningRefusal::Expired) => "gateway.commissioning.expired", + Self::Permit(CommissioningRefusal::BindingMismatch) | Self::BindingMismatch => { + "gateway.commissioning.binding-mismatch" + } + Self::Unavailable => "gateway.commissioning.store-unavailable", + Self::Missing => "gateway.commissioning.registration-missing", + Self::Corrupt => "gateway.commissioning.state-corrupt", + Self::Rollback => "gateway.commissioning.restore-rollback", + Self::Exhausted => "gateway.commissioning.exhausted", + Self::Contention => "gateway.commissioning.contention", + } + } +} + +#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] +#[serde(deny_unknown_fields)] +struct Record { + schema: String, + budget_scope_sha256: Sha256Digest, + budget_binding_sha256: Sha256Digest, + maximum_credential_leases: u64, + consumed_credential_leases: u64, + latest_verifier_time: u64, + accepted_revocation_sequence: u64, + revoked_signers: BTreeSet, +} + +/// Validated immutable registration plus its monotone consumption/trust state. +/// This is a storage receipt, never a credential or provider-entry capability. +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct CommissioningBudgetSnapshot { + record: Record, + bytes: Vec, +} + +impl CommissioningBudgetSnapshot { + /// Bytes the private session must durably retain before custody access. + #[must_use] + pub fn canonical_bytes(&self) -> &[u8] { + &self.bytes + } + + /// Lifetime acquisitions consumed, including claims followed by crashes. + #[must_use] + pub const fn consumed_credential_leases(&self) -> u64 { + self.record.consumed_credential_leases + } + + /// Immutable signed ceiling at this run/family's stable budget key. + #[must_use] + pub const fn maximum_credential_leases(&self) -> u64 { + self.record.maximum_credential_leases + } + + /// Restores a floor from canonical bytes for this exact reviewed binding. + /// + /// # Errors + /// + /// Returns a closed refusal before parsing oversized input, or when the + /// schema, bounds, canonical form or immutable bindings differ. + pub fn from_canonical_json( + bytes: &[u8], + binding: &CommissioningBinding, + ) -> Result { + if bytes.is_empty() || bytes.len() > MAX_COMMISSIONING_BUDGET_BYTES { + return Err(CommissioningBudgetRefusal::Corrupt); + } + let record: Record = + serde_json::from_slice(bytes).map_err(|_| CommissioningBudgetRefusal::Corrupt)?; + let snapshot = Self::encode(record)?; + if snapshot.bytes != bytes { + return Err(CommissioningBudgetRefusal::Corrupt); + } + snapshot.matches(binding)?; + Ok(snapshot) + } + + fn encode(record: Record) -> Result { + if record.schema != COMMISSIONING_BUDGET_SCHEMA + || !(1..=auths_recipe_qualification::MAX_COMMISSIONING_LEASES) + .contains(&record.maximum_credential_leases) + || record.consumed_credential_leases > record.maximum_credential_leases + || record.accepted_revocation_sequence > (1 << 53) - 1 + || record.latest_verifier_time > 253_402_300_799 + || record.revoked_signers.len() > MAX_REVOKED_SIGNERS + { + return Err(CommissioningBudgetRefusal::Corrupt); + } + let bytes = serde_json_canonicalizer::to_vec(&record) + .map_err(|_| CommissioningBudgetRefusal::Corrupt)?; + if bytes.len() > MAX_COMMISSIONING_BUDGET_BYTES { + return Err(CommissioningBudgetRefusal::Corrupt); + } + Ok(Self { record, bytes }) + } + + fn matches(&self, binding: &CommissioningBinding) -> Result<(), CommissioningBudgetRefusal> { + if self.record.budget_scope_sha256 + != binding + .budget_key() + .map_err(|_| CommissioningBudgetRefusal::BindingMismatch)? + || self.record.budget_binding_sha256 + != binding + .budget_binding() + .map_err(|_| CommissioningBudgetRefusal::BindingMismatch)? + || self.record.maximum_credential_leases != binding.maximum_credential_leases + { + return Err(CommissioningBudgetRefusal::BindingMismatch); + } + Ok(()) + } + + fn not_below(&self, floor: &Self) -> bool { + self.record.budget_scope_sha256 == floor.record.budget_scope_sha256 + && self.record.budget_binding_sha256 == floor.record.budget_binding_sha256 + && self.record.maximum_credential_leases == floor.record.maximum_credential_leases + && self.record.consumed_credential_leases >= floor.record.consumed_credential_leases + && self.record.latest_verifier_time >= floor.record.latest_verifier_time + && self.record.accepted_revocation_sequence >= floor.record.accepted_revocation_sequence + && self + .record + .revoked_signers + .is_superset(&floor.record.revoked_signers) + } +} + +/// An atomically committed counter/trust update, which the session must persist +/// as its floor before acting on `refusal`. Refused requests consume no unit; +/// authenticated revocations are nevertheless durably remembered. +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct CommissioningBudgetUpdate { + snapshot: CommissioningBudgetSnapshot, + refusal: Option, +} + +impl CommissioningBudgetUpdate { + /// Exact committed snapshot to retain outside database restores. + #[must_use] + pub const fn snapshot(&self) -> &CommissioningBudgetSnapshot { + &self.snapshot + } + + /// No credential acquisition when present, even though trust was recorded. + #[must_use] + pub const fn refusal(&self) -> Option { + self.refusal + } +} + +/// Capacity for one exact commissioning binding on an existing atomic store. +/// The production operator path must supply its production PostgreSQL backend; +/// development stores may exercise this mechanism without granting authority. +pub struct CommissioningBudget { + store: Arc, + key: GatewayAttemptKey, + binding: CommissioningBinding, +} + +impl CommissioningBudget { + /// Names the stable run/family key and its immutable reviewed binding. + /// + /// # Errors + /// + /// Returns [`CommissioningBudgetRefusal::BindingMismatch`] for a binding + /// outside the shipping permit's production target and finite bounds. + /// This constructor creates no state and opens no execution authority. + pub fn new( + store: Arc, + binding: CommissioningBinding, + ) -> Result { + binding + .validate() + .map_err(|_| CommissioningBudgetRefusal::BindingMismatch)?; + let key = GatewayAttemptKey::from_bytes( + *binding + .budget_key() + .map_err(|_| CommissioningBudgetRefusal::BindingMismatch)? + .as_bytes(), + ); + Ok(Self { + store, + key, + binding, + }) + } + + /// Registers capacity once during authenticated fresh operator setup. + /// Existing capacity is checked and returned, never reset or overwritten. + /// Runtime opening and renewal must use [`Self::load`] instead. + /// + /// # Errors + /// + /// Returns a store or binding refusal; a failed acknowledgement grants no + /// capacity or credential capability. Retain the returned initial floor. + pub fn initialize(&self) -> Result { + let initial = CommissioningBudgetSnapshot::encode(Record { + schema: COMMISSIONING_BUDGET_SCHEMA.to_owned(), + budget_scope_sha256: self + .binding + .budget_key() + .map_err(|_| CommissioningBudgetRefusal::BindingMismatch)?, + budget_binding_sha256: self + .binding + .budget_binding() + .map_err(|_| CommissioningBudgetRefusal::BindingMismatch)?, + maximum_credential_leases: self.binding.maximum_credential_leases, + consumed_credential_leases: 0, + latest_verifier_time: 0, + accepted_revocation_sequence: 0, + revoked_signers: BTreeSet::new(), + })?; + match self + .store + .insert_all(&[GatewayRecordEntry { + kind: GatewayRecordKind::CommissioningBudget, + key: self.key, + record: initial.bytes.clone(), + expires_at: None, + }]) + .map_err(store_refusal)? + { + GatewayInsert::Inserted => Ok(initial), + GatewayInsert::Exists { .. } => self.load(), + } + } + + /// Reads existing permanent capacity; absence never creates a fresh counter. + /// + /// # Errors + /// + /// Returns a missing, unavailable, corrupt or changed-binding refusal. + pub fn load(&self) -> Result { + let bytes = self + .store + .load(GatewayRecordKind::CommissioningBudget, &self.key) + .map_err(store_refusal)? + .ok_or(CommissioningBudgetRefusal::Missing)?; + CommissioningBudgetSnapshot::from_canonical_json(&bytes, &self.binding) + } + + /// Atomically claims one lifetime unit after current signed authority checks. + /// + /// `floor` is this host's independently retained prior snapshot and `state` + /// includes the installation's prior authenticated revocations. The caller + /// must durably retain the returned snapshot before custody, including on + /// a refusal. There is no refund or sweep operation. The normal gateway + /// proof, action, reservation and attempt checks remain mandatory. + /// + /// # Errors + /// + /// Returns a store/binding/rollback/contention refusal without authorizing + /// custody. Signed authority refusals and exhaustion are returned in the + /// committed update so their revocation memory can be retained. + pub fn claim( + &self, + authority: &VerifiedCommissioningPermit, + request: &CommissioningRequest<'_>, + now: u64, + clock_trusted: bool, + floor: &CommissioningBudgetSnapshot, + state: &VerifierState, + ) -> Result { + let authority_binding = &authority.permit().body().statement.binding; + floor.matches(&self.binding)?; + if authority_binding != &self.binding { + return Err(CommissioningBudgetRefusal::BindingMismatch); + } + for _ in 0..MAX_COMMISSIONING_CLAIM_RETRIES { + let current = self.load()?; + if !current.not_below(floor) { + return Err(CommissioningBudgetRefusal::Rollback); + } + let mut remembered = state.clone(); + remembered.accepted_revocation_sequence = remembered + .accepted_revocation_sequence + .max(current.record.accepted_revocation_sequence); + remembered + .revoked_signers + .extend(current.record.revoked_signers.iter().cloned()); + authority.remember(&mut remembered); + let mut next = current.record.clone(); + next.accepted_revocation_sequence = remembered.accepted_revocation_sequence; + next.revoked_signers = remembered.revoked_signers.clone(); + let refusal = authority + .evaluate(request, now, clock_trusted, &remembered) + .err() + .map(CommissioningBudgetRefusal::Permit) + .or_else(|| { + if now < current.record.latest_verifier_time { + Some(CommissioningBudgetRefusal::Rollback) + } else if current.record.consumed_credential_leases + == current.record.maximum_credential_leases + { + Some(CommissioningBudgetRefusal::Exhausted) + } else { + None + } + }); + if refusal.is_none() { + next.consumed_credential_leases += 1; + next.latest_verifier_time = now; + } + let next = CommissioningBudgetSnapshot::encode(next)?; + match self.store.replace( + GatewayRecordKind::CommissioningBudget, + &self.key, + ¤t.bytes, + &next.bytes, + ) { + Ok(()) => { + return Ok(CommissioningBudgetUpdate { + snapshot: next, + refusal, + }); + } + Err(GatewayAttemptError::Conflict) => {} + Err(error) => return Err(store_refusal(error)), + } + } + Err(CommissioningBudgetRefusal::Contention) + } +} + +const fn store_refusal(error: GatewayAttemptError) -> CommissioningBudgetRefusal { + match error { + GatewayAttemptError::Conflict => CommissioningBudgetRefusal::Contention, + GatewayAttemptError::Unavailable => CommissioningBudgetRefusal::Unavailable, + _ => CommissioningBudgetRefusal::Corrupt, + } +} + +#[cfg(test)] +mod tests; diff --git a/product/runtime/auths-gateway/src/commissioning_budget/tests.rs b/product/runtime/auths-gateway/src/commissioning_budget/tests.rs new file mode 100644 index 000000000..97cf05551 --- /dev/null +++ b/product/runtime/auths-gateway/src/commissioning_budget/tests.rs @@ -0,0 +1,451 @@ +//! Identical capacity, race, crash and rollback checks on both atomic stores. +//! Public synthetic permits authorize no real credential or provider entry. + +use super::*; +use crate::store_testkit::{Backend, TestAttempts}; +use auths_recipe_qualification::{ + CommissioningInputs, QualificationCommissioningPermit, QualificationRevocationList, + QualificationSignerCertificate, QualificationTrustRoot, SignatureB64, +}; +use auths_recipe_qualification_issuance::{RootSigner, SigningSeed}; +use ed25519_dalek::{Signer as _, SigningKey}; +use proptest::prelude::*; +use std::sync::Barrier; +use zeroize::Zeroizing; + +struct Fixture { + root: QualificationTrustRoot, + certificate: QualificationSignerCertificate, + list: QualificationRevocationList, + permit: QualificationCommissioningPermit, +} + +impl Fixture { + fn load() -> Self { + let path = std::path::Path::new(env!("CARGO_MANIFEST_DIR")) + .join("../../../bindings/fixtures/qualification/commissioning-v1.json"); + let document: serde_json::Value = + serde_json::from_slice(&std::fs::read(path).expect("fixture")).expect("JSON"); + let text = |name: &str| document[name].as_str().expect("artifact").as_bytes(); + Self { + root: QualificationTrustRoot::from_canonical_json(text("trust_root")).expect("root"), + certificate: QualificationSignerCertificate::from_canonical_json(text( + "signer_certificate", + )) + .expect("certificate"), + list: QualificationRevocationList::from_canonical_json(text("revocation_list")) + .expect("list"), + permit: QualificationCommissioningPermit::from_canonical_json(text("permit")) + .expect("permit"), + } + } + + fn authority(&self) -> VerifiedCommissioningPermit { + VerifiedCommissioningPermit::verify( + &self.root, + &CommissioningInputs { + signer_certificate: self.certificate.canonical_bytes(), + revocation_list: self.list.canonical_bytes(), + permit: self.permit.canonical_bytes(), + }, + ) + .expect("synthetic authority") + } + + fn binding(&self) -> &CommissioningBinding { + &self.permit.body().statement.binding + } + + fn now(&self) -> u64 { + self.permit.body().statement.not_before + } + + fn request(&self) -> CommissioningRequest<'_> { + let binding = self.binding(); + CommissioningRequest { + source_commit: &binding.source_commit, + tuple: &binding.tuple, + protected_run: &binding.protected_run, + principal_sha256: binding.principal_sha256, + trusted_context_sha256: binding.trusted_context_sha256, + resources_sha256: binding.resources_sha256, + canonical_action_sha256: binding.allowed_actions[0], + } + } + + fn root_signer(&self) -> RootSigner { + RootSigner::open( + &SigningSeed::from_bytes(Zeroizing::new([0x11; 32])), + self.root.clone(), + ) + .expect("public test root") + } +} + +fn budget(store: &TestAttempts, fixture: &Fixture) -> CommissioningBudget { + CommissioningBudget::new(store.raw(), fixture.binding().clone()).expect("binding") +} + +fn consume( + budget: &CommissioningBudget, + fixture: &Fixture, + floor: &CommissioningBudgetSnapshot, +) -> CommissioningBudgetUpdate { + budget + .claim( + &fixture.authority(), + &fixture.request(), + fixture.now(), + true, + floor, + &VerifierState::default(), + ) + .expect("atomic claim") +} + +fn permanent_capacity_and_restart(backend: Backend) { + let store = TestAttempts::open(backend); + let fixture = Fixture::load(); + let budget = budget(&store, &fixture); + assert_eq!(budget.load(), Err(CommissioningBudgetRefusal::Missing)); + let initial = budget.initialize().expect("fresh setup"); + let claimed = consume(&budget, &fixture, &initial); + assert_eq!(claimed.refusal, None); + assert_eq!(claimed.snapshot.consumed_credential_leases(), 1); + // Simulate process loss immediately after the durable claim, before any + // credential acquisition. Reopening does not refund that consumed unit. + drop(budget); + let reopened = CommissioningBudget::new(store.reopen().store(), fixture.binding().clone()) + .expect("reopened budget"); + assert_eq!(reopened.load().expect("permanent record"), claimed.snapshot); + assert_eq!( + reopened.initialize().expect("idempotent setup"), + claimed.snapshot + ); + // A returned receipt is not reused to authorize a second lease: another + // claim always consumes another ordinal on the shared record. + let next = consume(&reopened, &fixture, &claimed.snapshot); + assert_eq!(next.snapshot.consumed_credential_leases(), 2); + let raw = store.raw(); + assert_eq!(raw.sweep_expired(u64::MAX / 2, 10).expect("sweep"), 0); + assert_eq!(reopened.load().expect("not swept"), next.snapshot); +} + +#[test] +fn capacity_survives_crash_restart_and_sweep_file() { + permanent_capacity_and_restart(Backend::File); +} + +#[test] +#[ignore = "requires TLS PostgreSQL fixture"] +fn capacity_survives_crash_restart_and_sweep_postgres() { + permanent_capacity_and_restart(Backend::Postgres); +} + +fn final_unit_race(backend: Backend) { + let store = TestAttempts::open(backend); + let fixture = Fixture::load(); + let budget = budget(&store, &fixture); + let mut floor = budget.initialize().expect("setup"); + for ordinal in 1..fixture.binding().maximum_credential_leases { + let claimed = consume(&budget, &fixture, &floor); + assert_eq!(claimed.refusal, None); + assert_eq!(claimed.snapshot.consumed_credential_leases(), ordinal); + floor = claimed.snapshot; + } + let barrier = Arc::new(Barrier::new(2)); + let handles: Vec<_> = (0..2) + .map(|_| { + // Distinct file handles or PostgreSQL pools model independent hosts. + let budget = CommissioningBudget::new(store.raw(), fixture.binding().clone()) + .expect("second host"); + let authority = fixture.authority(); + let binding = fixture.binding().clone(); + let floor = floor.clone(); + let barrier = Arc::clone(&barrier); + let now = fixture.now(); + std::thread::spawn(move || { + let request = CommissioningRequest { + source_commit: &binding.source_commit, + tuple: &binding.tuple, + protected_run: &binding.protected_run, + principal_sha256: binding.principal_sha256, + trusted_context_sha256: binding.trusted_context_sha256, + resources_sha256: binding.resources_sha256, + canonical_action_sha256: binding.allowed_actions[0], + }; + barrier.wait(); + budget + .claim( + &authority, + &request, + now, + true, + &floor, + &VerifierState::default(), + ) + .expect("raced claim") + }) + }) + .collect(); + let results: Vec<_> = handles + .into_iter() + .map(|handle| handle.join().expect("host")) + .collect(); + assert_eq!( + results + .iter() + .filter(|result| result.refusal.is_none()) + .count(), + 1 + ); + assert_eq!( + results + .iter() + .filter(|result| result.refusal == Some(CommissioningBudgetRefusal::Exhausted)) + .count(), + 1 + ); + assert_eq!( + budget + .load() + .expect("shared capacity") + .consumed_credential_leases(), + fixture.binding().maximum_credential_leases + ); +} + +#[test] +fn exactly_one_host_claims_the_final_unit_file() { + final_unit_race(Backend::File); +} + +#[test] +#[ignore = "requires TLS PostgreSQL fixture"] +fn exactly_one_host_claims_the_final_unit_postgres() { + final_unit_race(Backend::Postgres); +} + +fn renewal_binding_and_rollback(backend: Backend) { + let store = TestAttempts::open(backend); + let mut fixture = Fixture::load(); + let budget = budget(&store, &fixture); + let initial = budget.initialize().expect("setup"); + let first = consume(&budget, &fixture, &initial); + let mut renewed = fixture.permit.body().clone(); + renewed.statement.issued_at += 1; + renewed.statement.not_before += 1; + renewed.signature_b64 = SignatureB64::from_bytes( + &SigningKey::from_bytes(&[0x22; 32]) + .sign(&renewed.signing_preimage().expect("preimage")) + .to_bytes(), + ); + fixture.permit = + QualificationCommissioningPermit::from_body(&renewed).expect("renewed authority"); + let second = consume(&budget, &fixture, &first.snapshot); + assert_eq!(second.refusal, None); + assert_eq!(second.snapshot.consumed_credential_leases(), 2); + let mut changed = fixture.binding().clone(); + changed.maximum_credential_leases += 1; + let changed = CommissioningBudget::new(store.raw(), changed).expect("finite changed ceiling"); + assert_eq!( + changed.initialize(), + Err(CommissioningBudgetRefusal::BindingMismatch) + ); + assert_eq!( + changed.load(), + Err(CommissioningBudgetRefusal::BindingMismatch) + ); + // Inject a restored older database record while retaining the host's + // separately persisted accepted snapshot. Opening never repairs it. + let raw = store.raw(); + raw.replace( + GatewayRecordKind::CommissioningBudget, + &budget.key, + second.snapshot.canonical_bytes(), + initial.canonical_bytes(), + ) + .expect("restore old record"); + assert_eq!( + budget.claim( + &fixture.authority(), + &fixture.request(), + fixture.now(), + true, + &second.snapshot, + &VerifierState::default() + ), + Err(CommissioningBudgetRefusal::Rollback) + ); +} + +#[test] +fn renewal_keeps_consumption_and_a_retained_floor_detects_restore_file() { + renewal_binding_and_rollback(Backend::File); +} + +#[test] +#[ignore = "requires TLS PostgreSQL fixture"] +fn renewal_keeps_consumption_and_a_retained_floor_detects_restore_postgres() { + renewal_binding_and_rollback(Backend::Postgres); +} + +fn refusals_and_permanent_revocations(backend: Backend) { + let store = TestAttempts::open(backend); + let mut fixture = Fixture::load(); + let budget = budget(&store, &fixture); + let initial = budget.initialize().expect("setup"); + let mut request = fixture.request(); + request.canonical_action_sha256 = Sha256Digest::from_bytes([0xff; 32]); + let denied = budget + .claim( + &fixture.authority(), + &request, + fixture.now(), + true, + &initial, + &VerifierState::default(), + ) + .expect("denied update"); + assert_eq!( + denied.refusal, + Some(CommissioningBudgetRefusal::Permit( + CommissioningRefusal::BindingMismatch + )) + ); + assert_eq!(denied.snapshot.consumed_credential_leases(), 0); + let clock = budget + .claim( + &fixture.authority(), + &fixture.request(), + fixture.now(), + false, + &denied.snapshot, + &VerifierState::default(), + ) + .expect("clock update"); + assert_eq!( + clock.refusal, + Some(CommissioningBudgetRefusal::Permit( + CommissioningRefusal::ClockUntrusted + )) + ); + assert_eq!(clock.snapshot.consumed_credential_leases(), 0); + let root = fixture.root_signer(); + fixture.list = root + .revoke( + 2, + fixture.now() - 1, + fixture.now() + 3600, + vec![fixture.certificate.body().statement.signer_id.clone()], + vec![], + ) + .expect("revoked list"); + let revoked = consume(&budget, &fixture, &clock.snapshot); + assert_eq!( + revoked.refusal, + Some(CommissioningBudgetRefusal::Permit( + CommissioningRefusal::Revoked + )) + ); + assert_eq!(revoked.snapshot.consumed_credential_leases(), 0); + fixture.list = root + .revoke(3, fixture.now() - 1, fixture.now() + 3600, vec![], vec![]) + .expect("omitted list"); + let still_revoked = consume(&budget, &fixture, &revoked.snapshot); + assert_eq!(still_revoked.refusal, revoked.refusal); + assert_eq!(still_revoked.snapshot.consumed_credential_leases(), 0); + assert!( + still_revoked + .snapshot + .record + .revoked_signers + .contains(&fixture.certificate.body().statement.signer_id) + ); +} + +#[test] +fn hostile_inputs_consume_nothing_and_revocation_survives_omission_file() { + refusals_and_permanent_revocations(Backend::File); +} + +#[test] +#[ignore = "requires TLS PostgreSQL fixture"] +fn hostile_inputs_consume_nothing_and_revocation_survives_omission_postgres() { + refusals_and_permanent_revocations(Backend::Postgres); +} + +#[test] +fn snapshots_reject_noncanonical_unknown_oversized_and_impossible_state() { + let store = TestAttempts::open(Backend::File); + let fixture = Fixture::load(); + let snapshot = budget(&store, &fixture).initialize().expect("setup"); + let decode = + |bytes: &[u8]| CommissioningBudgetSnapshot::from_canonical_json(bytes, fixture.binding()); + let mut bytes = snapshot.canonical_bytes().to_vec(); + bytes.push(b'\n'); + assert_eq!(decode(&bytes), Err(CommissioningBudgetRefusal::Corrupt)); + assert_eq!( + decode(&vec![b' '; MAX_COMMISSIONING_BUDGET_BYTES + 1]), + Err(CommissioningBudgetRefusal::Corrupt) + ); + let mut document = serde_json::to_value(&snapshot.record).expect("record"); + document["unreviewed"] = serde_json::json!(true); + assert_eq!( + decode(&serde_json_canonicalizer::to_vec(&document).expect("canonical")), + Err(CommissioningBudgetRefusal::Corrupt) + ); + for (pointer, value) in [ + ( + "/schema", + serde_json::json!("auths.gateway-commissioning-budget/0"), + ), + ("/consumed_credential_leases", serde_json::json!(1025)), + ("/maximum_credential_leases", serde_json::json!(0)), + ("/accepted_revocation_sequence", serde_json::json!(u64::MAX)), + ] { + let mut document = serde_json::to_value(&snapshot.record).expect("record"); + *document.pointer_mut(pointer).expect("member") = value; + let bytes = serde_json::to_vec(&document).expect("JSON"); + assert_eq!( + decode(&bytes), + Err(CommissioningBudgetRefusal::Corrupt), + "{pointer}" + ); + } +} + +proptest! { + #![proptest_config(ProptestConfig::with_cases(32))] + + #[test] + fn consumption_never_exceeds_the_ceiling_or_charges_a_refused_action( + inputs in prop::collection::vec((any::(), any::()), 0..64) + ) { + let store = TestAttempts::open(Backend::File); + let fixture = Fixture::load(); + let authority = fixture.authority(); + let budget = budget(&store, &fixture); + let mut floor = budget.initialize().expect("setup"); + let mut eligible = 0; + for (exact_action, trusted_clock) in inputs { + let mut request = fixture.request(); + if !exact_action { + request.canonical_action_sha256 = Sha256Digest::from_bytes([0xff; 32]); + } + let before = floor.consumed_credential_leases(); + let updated = budget.claim(&authority, &request, fixture.now(), trusted_clock, + &floor, &VerifierState::default()).expect("claim or refusal"); + if exact_action && trusted_clock { eligible += 1; } + prop_assert_eq!(updated.snapshot.consumed_credential_leases(), + eligible.min(fixture.binding().maximum_credential_leases)); + prop_assert!(updated.snapshot.consumed_credential_leases() >= before); + if !exact_action || !trusted_clock { + prop_assert!(updated.refusal.is_some()); + prop_assert_eq!(updated.snapshot.consumed_credential_leases(), before); + } + floor = updated.snapshot; + } + prop_assert_eq!(budget.load().expect("permanent record"), floor); + } +} diff --git a/product/runtime/auths-gateway/src/lib.rs b/product/runtime/auths-gateway/src/lib.rs index a42dc160c..c071fcaed 100644 --- a/product/runtime/auths-gateway/src/lib.rs +++ b/product/runtime/auths-gateway/src/lib.rs @@ -12,6 +12,7 @@ pub mod app; mod audit; mod binding; mod bounds; +pub mod commissioning_budget; mod connection; mod credential_journal; mod echo_verify; diff --git a/product/runtime/auths-gateway/src/pending_vectors/production.rs b/product/runtime/auths-gateway/src/pending_vectors/production.rs index 69fd3ba26..62632914b 100644 --- a/product/runtime/auths-gateway/src/pending_vectors/production.rs +++ b/product/runtime/auths-gateway/src/pending_vectors/production.rs @@ -63,6 +63,19 @@ const ROWS: &[&str] = &[ "gateway.qualification.unavailable qualification before-lease implemented 3 V:index-signature-forged", "gateway.qualification.revocation-stale qualification before-lease implemented 3 V:revocation-list-past-next-update", "gateway.qualification.clock-untrusted qualification before-lease implemented 3 V:clock-untrusted", + "gateway.commissioning.unavailable commissioning-budget before-custody implemented 5 -", + "gateway.commissioning.revoked commissioning-budget before-custody implemented 5 -", + "gateway.commissioning.revocation-rollback commissioning-budget before-custody implemented 5 -", + "gateway.commissioning.clock-untrusted commissioning-budget before-custody implemented 5 -", + "gateway.commissioning.revocation-stale commissioning-budget before-custody implemented 5 -", + "gateway.commissioning.expired commissioning-budget before-custody implemented 5 -", + "gateway.commissioning.binding-mismatch commissioning-budget before-custody implemented 5 -", + "gateway.commissioning.store-unavailable commissioning-budget before-custody implemented 5 -", + "gateway.commissioning.registration-missing commissioning-budget before-custody implemented 5 -", + "gateway.commissioning.state-corrupt commissioning-budget before-custody implemented 5 -", + "gateway.commissioning.restore-rollback commissioning-budget before-custody implemented 5 -", + "gateway.commissioning.exhausted commissioning-budget before-custody implemented 5 -", + "gateway.commissioning.contention commissioning-budget before-custody implemented 5 -", "gateway.readiness.connection-disabled readiness doctor implemented 4 -", "gateway.readiness.trust-unavailable readiness doctor implemented 4 -", "gateway.readiness.store-unavailable readiness doctor implemented 4 -", diff --git a/product/runtime/auths-gateway/src/qualification.rs b/product/runtime/auths-gateway/src/qualification.rs index 826cfef71..4b2056752 100644 --- a/product/runtime/auths-gateway/src/qualification.rs +++ b/product/runtime/auths-gateway/src/qualification.rs @@ -23,7 +23,7 @@ use std::time::{Duration, SystemTime, UNIX_EPOCH}; pub const QUALIFICATION_POLICY_REFUSED: &str = "gateway.install.qualification-policy"; /// The schema identifier of the production lifecycle store. -pub const POSTGRES_STORE_SCHEMA: &str = "auths.lifecycle.postgresql/5"; +pub const POSTGRES_STORE_SCHEMA: &str = "auths.lifecycle.postgresql/6"; /// The schema identifier of the development file store. pub const FILE_STORE_SCHEMA: &str = "auths.gateway-attempt/3"; diff --git a/product/runtime/auths-gateway/src/semantic_closure.rs b/product/runtime/auths-gateway/src/semantic_closure.rs index 1d18ce55a..ecc6755a8 100644 --- a/product/runtime/auths-gateway/src/semantic_closure.rs +++ b/product/runtime/auths-gateway/src/semantic_closure.rs @@ -10,7 +10,7 @@ /// SHA-256 of the schema, a NUL byte, and `semantic-closure.json`. /// Regenerate through `semantic_closure_is_current` with `AUTHS_UPDATE_FIXTURES=1`. pub const GATEWAY_SEMANTIC_CLOSURE_SHA256: &str = - "3c5fb82215a577faa84203c241e5e3fe49ffa21383bc5e15bc5c55c7e6bf8019"; + "7bae0f7bdefe140109d5f30fd80b388443271ed8a7bad341c34945e06d5b6ac1"; #[cfg(test)] mod tests { diff --git a/product/runtime/auths-gateway/src/store.rs b/product/runtime/auths-gateway/src/store.rs index c18ab29c0..745f786a6 100644 --- a/product/runtime/auths-gateway/src/store.rs +++ b/product/runtime/auths-gateway/src/store.rs @@ -7,7 +7,7 @@ //! `auths_gateway_kernel::transition::valid_transition`. Records persist //! through a [`GatewayAttemptStore`], which is only an all-or-none //! insert-once, compare-and-swap, and sweep mechanism over opaque bounded -//! bytes of four closed kinds: [`FileGatewayAttemptStore`] for one host, and +//! bytes of five closed kinds: [`FileGatewayAttemptStore`] for one host, and //! the multi-host `PostgresLifecycleStore`, whose production qualification is //! still open. @@ -922,7 +922,7 @@ pub enum GatewayInsert { }, } -/// Durable storage of opaque gateway records of four closed kinds. +/// Durable storage of opaque gateway records of five closed kinds. /// Implementations never interpret the bytes. /// /// Every implementation must pass the same conformance suite: one winner per @@ -996,7 +996,7 @@ pub trait GatewayAttemptStore: Send + Sync { /// Atomic file store for one host. This is not a multi-host store and does /// not establish credential isolation by itself. /// -/// Files are named by kind (`claim-`, `slot-`, `sum-`, `conn-`, then the hex +/// Files are named by kind (`claim-`, `slot-`, `sum-`, `conn-`, `commission-`, then the hex /// key and `.json`). Every mutation holds a host-wide exclusive `flock` on /// `.replace.lock` and every load holds it shared. A batch first writes /// `.batch.json` listing each target and its bytes, then creates the @@ -1079,6 +1079,7 @@ impl FileGatewayAttemptStore { GatewayRecordKind::CountSlot => "slot-", GatewayRecordKind::SumSlot => "sum-", GatewayRecordKind::Connection => "conn-", + GatewayRecordKind::CommissioningBudget => "commission-", }; format!("{prefix}{}.json", hex::encode(key.as_bytes())) } @@ -1279,7 +1280,7 @@ impl FileGatewayAttemptStore { /// A record or batch file name this store writes. fn valid_file_name(name: &str) -> bool { - let Some(rest) = ["claim-", "slot-", "sum-", "conn-"] + let Some(rest) = ["claim-", "slot-", "sum-", "conn-", "commission-"] .iter() .find_map(|prefix| name.strip_prefix(prefix)) else { diff --git a/product/stores/auths-stores/migrations/postgres_lifecycle_v5.sql b/product/stores/auths-stores/migrations/postgres_lifecycle_v6.sql similarity index 93% rename from product/stores/auths-stores/migrations/postgres_lifecycle_v5.sql rename to product/stores/auths-stores/migrations/postgres_lifecycle_v6.sql index af96aaabd..ed41d489c 100644 --- a/product/stores/auths-stores/migrations/postgres_lifecycle_v5.sql +++ b/product/stores/auths-stores/migrations/postgres_lifecycle_v6.sql @@ -1,13 +1,13 @@ CREATE TABLE auths_lifecycle_store_meta ( singleton BOOLEAN PRIMARY KEY DEFAULT TRUE CHECK (singleton), - schema_version INTEGER NOT NULL CHECK (schema_version = 5), + schema_version INTEGER NOT NULL CHECK (schema_version = 6), contract_id TEXT NOT NULL CHECK ( contract_id = 'auths.lifecycle.transactional-store/4' ) ); INSERT INTO auths_lifecycle_store_meta (singleton, schema_version, contract_id) -VALUES (TRUE, 5, 'auths.lifecycle.transactional-store/4'); +VALUES (TRUE, 6, 'auths.lifecycle.transactional-store/4'); CREATE TABLE auths_lifecycle_records ( workflow_id TEXT PRIMARY KEY CHECK ( @@ -55,7 +55,7 @@ CREATE TABLE auths_recovery_leases ( CREATE TABLE auths_gateway_records ( record_key BYTEA PRIMARY KEY CHECK (octet_length(record_key) = 32), record_kind TEXT NOT NULL CHECK ( - record_kind IN ('attempt', 'count-slot', 'sum-slot', 'connection') + record_kind IN ('attempt', 'count-slot', 'sum-slot', 'connection', 'commissioning-budget') ), expires_at BIGINT NULL CHECK (expires_at IS NULL OR expires_at >= 0), record_bytes BYTEA NOT NULL CHECK ( diff --git a/product/stores/auths-stores/src/gateway_attempt.rs b/product/stores/auths-stores/src/gateway_attempt.rs index b2f85a5ba..d5d3732b4 100644 --- a/product/stores/auths-stores/src/gateway_attempt.rs +++ b/product/stores/auths-stores/src/gateway_attempt.rs @@ -2,7 +2,7 @@ //! //! This is a mechanism only: all-or-none insert-once batches, a //! compare-and-swap replacement, and a bounded sweep of expired slots, over -//! bounded bytes tagged with one of four closed record kinds. The gateway +//! bounded bytes tagged with one of five closed record kinds. The gateway //! owns every record format, its stages, and which replacements are valid. use crate::lifecycle::{PostgresLifecycleStore, map_postgres_error}; @@ -27,6 +27,8 @@ pub enum GatewayRecordKind { SumSlot, /// The shared connection record. Connection, + /// A commissioning run's immutable binding and consumed leases; never swept. + CommissioningBudget, } impl GatewayRecordKind { @@ -38,6 +40,7 @@ impl GatewayRecordKind { Self::CountSlot => "count-slot", Self::SumSlot => "sum-slot", Self::Connection => "connection", + Self::CommissioningBudget => "commissioning-budget", } } @@ -49,6 +52,7 @@ impl GatewayRecordKind { "count-slot" => Some(Self::CountSlot), "sum-slot" => Some(Self::SumSlot), "connection" => Some(Self::Connection), + "commissioning-budget" => Some(Self::CommissioningBudget), _ => None, } } @@ -357,12 +361,18 @@ mod tests { bounded(&vec![0; MAX_GATEWAY_RECORD_BYTES + 1]), Err(StoreError::LimitExceeded) ); - let schema = include_str!("../migrations/postgres_lifecycle_v5.sql"); + let schema = include_str!("../migrations/postgres_lifecycle_v6.sql"); assert!( schema.contains("octet_length(record_bytes) BETWEEN 1 AND 262144"), "the schema bound and the Rust bound are the same" ); - for kind in ["attempt", "count-slot", "sum-slot", "connection"] { + for kind in [ + "attempt", + "count-slot", + "sum-slot", + "connection", + "commissioning-budget", + ] { assert_eq!( GatewayRecordKind::parse(kind).map(GatewayRecordKind::as_str), Some(kind) @@ -374,6 +384,14 @@ mod tests { #[test] fn expiry_is_present_exactly_for_slots_and_keys_are_distinct() { + assert_eq!( + entry(GatewayRecordKind::CommissioningBudget, 1, None).validate(), + Ok(()) + ); + assert_eq!( + entry(GatewayRecordKind::CommissioningBudget, 1, Some(9)).validate(), + Err(StoreError::Corrupt) + ); assert_eq!( entry(GatewayRecordKind::Attempt, 1, None).validate(), Ok(()) diff --git a/product/stores/auths-stores/src/lifecycle.rs b/product/stores/auths-stores/src/lifecycle.rs index dff0264aa..d289f80da 100644 --- a/product/stores/auths-stores/src/lifecycle.rs +++ b/product/stores/auths-stores/src/lifecycle.rs @@ -34,9 +34,9 @@ use tokio_postgres_rustls::MakeRustlsConnect; const DATABASE_MAGIC: &[u8; 8] = b"AUTHSLF1"; const MAX_DATABASE_BYTES: usize = 256 * 1024 * 1024; const MAX_RECORD_BYTES: usize = auths_lifecycle::MAX_LIFECYCLE_RECORD_BYTES; -const SCHEMA_VERSION: i32 = 5; +const SCHEMA_VERSION: i32 = 6; const CONTRACT_ID: &str = "auths.lifecycle.transactional-store/4"; -const POSTGRES_SCHEMA: &str = include_str!("../migrations/postgres_lifecycle_v5.sql"); +const POSTGRES_SCHEMA: &str = include_str!("../migrations/postgres_lifecycle_v6.sql"); /// One closed capacity rule configured by a domain registration. #[derive(Clone, Debug, Eq, PartialEq)] @@ -533,7 +533,7 @@ impl PostgresStoreSummary { /// Returns the physical schema identity. #[must_use] pub const fn schema_id(self) -> &'static str { - "auths.lifecycle.postgresql/5" + "auths.lifecycle.postgresql/6" } /// Returns the transactional store contract identity. @@ -705,7 +705,7 @@ impl PostgresLifecycleStore { } let state = self.pool.state(); Ok(PostgresStoreHealth { - schema_version: 5, + schema_version: 6, pool_connections: state.connections, pool_idle_connections: state.idle_connections, }) diff --git a/release/semantic-freeze-versions.toml b/release/semantic-freeze-versions.toml index 34c6fbb9d..1c9dd5edf 100644 --- a/release/semantic-freeze-versions.toml +++ b/release/semantic-freeze-versions.toml @@ -1,4 +1,4 @@ -freeze_version = 370 +freeze_version = 371 # Semantic identity counters live outside the xtask source tree deliberately. # The formal source closure binds xtask's executable code, while the semantic @@ -19,7 +19,7 @@ freeze_version = 370 "auths.frozen-bytes/formal/assurance-manifest-v1.toml" = 58 "auths.frozen-bytes/formal/qualification/aeneas/generated" = 19 "auths.frozen-bytes/formal/qualification/aeneas/qualification.toml" = 16 -"auths.frozen-bytes/formal/qualification/aeneas/source-closure.json" = 98 +"auths.frozen-bytes/formal/qualification/aeneas/source-closure.json" = 99 "auths.frozen-bytes/product/conformance/v1/mechanism-profile-conformance.json" = 1 "auths.frozen-bytes/product/conformance/v1/simplified-product-waist.json" = 4 "auths.frozen-bytes/product/fixtures/v1/bounded-policy/manifest.json" = 3 @@ -45,7 +45,7 @@ freeze_version = 370 "auths.frozen-bytes/product/integrations/auths-stripe/fixtures/subscription-create/v1/manifest.sha256.json" = 1 "auths.frozen-bytes/product/integrations/auths-stripe/fixtures/subscription-modify/v1/manifest.sha256.json" = 1 "auths.frozen-bytes/product/integrations/auths-stripe/fixtures/v1/manifest.sha256.json" = 1 -"auths.identity.protocol" = 123 +"auths.identity.protocol" = 124 "auths.modular-components" = 20 "auths.portable-abi-bindings" = 121 "auths.product.bounded-domains" = 19 @@ -56,15 +56,15 @@ freeze_version = 370 "auths.product.external-custody" = 5 "auths.product.facade" = 26 "auths.product.github-issue-address-v2" = 4 -"auths.product.lifecycle" = 15 +"auths.product.lifecycle" = 16 "auths.product.mcp-closed-execution" = 31 "auths.product.mechanism-profile-conformance" = 12 "auths.product.operations" = 5 -"auths.product.public-sdk-contract" = 120 +"auths.product.public-sdk-contract" = 121 "auths.product.receipts" = 13 "auths.product.release-assurance" = 7 "auths.product.simplified-waist" = 19 "auths.product.vocabulary" = 24 "auths.release.benchmark-contract" = 1 "auths.release.evolution-contract" = 79 -"auths.release.public-surface" = 370 +"auths.release.public-surface" = 371 diff --git a/release/semantic-freeze.json b/release/semantic-freeze.json index 59d4441ba..f987c492e 100644 --- a/release/semantic-freeze.json +++ b/release/semantic-freeze.json @@ -1,6 +1,6 @@ { "schema": "auths.semantic-freeze/1", - "freezeVersion": 370, + "freezeVersion": 371, "publicSurface": { "rustRoots": [ "auths", @@ -238,7 +238,7 @@ }, { "id": "auths.frozen-bytes/formal/qualification/aeneas/source-closure.json", - "version": 98, + "version": 99, "classification": "frozen-bytes", "categories": [ "canonical-generated-evidence" @@ -246,7 +246,7 @@ "owners": [ "formal/qualification/aeneas/source-closure.json" ], - "sha256": "31b4053a1e61e4195ff2bcc0495f1014bd1b1a8970da970282dec29fe4aa500d" + "sha256": "e827f63ea742ae566103c0c06aec972ca2e86a6db250484f6e2554c887092091" }, { "id": "auths.frozen-bytes/product/conformance/v1/mechanism-profile-conformance.json", @@ -550,7 +550,7 @@ }, { "id": "auths.identity.protocol", - "version": 123, + "version": 124, "classification": "frozen-meaning", "categories": [ "identity-protocol-versions", @@ -573,7 +573,7 @@ "core/fixtures/identity/v1/vectors.json", "core/spec/identity/v1" ], - "sha256": "c2496ff9803989ecb37dc36cf9c5cb7c1def8fa70789688645bff82dee578953" + "sha256": "885a3b6753548da2526e612941e6e54d05225c0d79d2412ddc1ef1b8df8f8939" }, { "id": "auths.modular-components", @@ -784,7 +784,7 @@ }, { "id": "auths.product.lifecycle", - "version": 15, + "version": 16, "classification": "frozen-meaning", "categories": [ "reservation-state", @@ -796,12 +796,12 @@ "owners": [ "product/fixtures/v1/lifecycle/registry.toml", "product/runtime/auths-lifecycle/src", - "product/stores/auths-stores/migrations/postgres_lifecycle_v5.sql", + "product/stores/auths-stores/migrations/postgres_lifecycle_v6.sql", "product/stores/auths-stores/src/lifecycle.rs", "product/stores/auths-stores/tests/postgres_lifecycle.rs", "product/stores/auths-stores/tests/postgres_tls" ], - "sha256": "b464afa30111263a30a0c25dea4ca93098efab2dc13adf8ced2debe565f70cdd" + "sha256": "c331eb406c523401d940e8c67fce96200465720920fc74196b2cdbfa11b345d0" }, { "id": "auths.product.mcp-closed-execution", @@ -871,7 +871,7 @@ }, { "id": "auths.product.public-sdk-contract", - "version": 120, + "version": 121, "classification": "frozen-meaning", "categories": [ "rust-sdk-contract", @@ -889,7 +889,7 @@ "product/runtime/auths-runtime/src", "product/sdk/auths-sdk/src" ], - "sha256": "6fff68d41c5a1a2b40986b62a3310ff05086b68ad8fd23cbcccb1d37f24b2de4" + "sha256": "9b4f652ee8cea79abf9db48ede141a33a7ecb722be3237105954da9a1773269b" }, { "id": "auths.product.receipts", @@ -1011,7 +1011,7 @@ }, { "id": "auths.release.public-surface", - "version": 370, + "version": 371, "classification": "release-metadata", "categories": [ "package-names", @@ -1104,7 +1104,7 @@ "xtask/src/release_launch.rs", "xtask/src/semantic_freeze.rs" ], - "sha256": "6546b04c364ef8ba03022a369388bc15b90c2cd5afef4733216fa1fbd7561527" + "sha256": "cebf93d0093e386bdadfb1ef954963844daaff4ce84d06555f7436acbad4df98" } ] } diff --git a/xtask/src/semantic_freeze.rs b/xtask/src/semantic_freeze.rs index e939530c5..ccd1514e0 100644 --- a/xtask/src/semantic_freeze.rs +++ b/xtask/src/semantic_freeze.rs @@ -527,7 +527,7 @@ fn generate_inventory() -> Result { "product/fixtures/v1/lifecycle/registry.toml".to_owned(), "product/runtime/auths-lifecycle/src".to_owned(), "product/stores/auths-stores/src/lifecycle.rs".to_owned(), - "product/stores/auths-stores/migrations/postgres_lifecycle_v5.sql".to_owned(), + "product/stores/auths-stores/migrations/postgres_lifecycle_v6.sql".to_owned(), "product/stores/auths-stores/tests/postgres_lifecycle.rs".to_owned(), "product/stores/auths-stores/tests/postgres_tls".to_owned(), ], From 267a37aadd00e359ad00aeabe44599271ad40966 Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 03:55:13 +0100 Subject: [PATCH 055/108] Add private operator commissioning sessions with retained lease floors --- compliance.toml | 13 + ...d-qualification-commissioning-authority.md | 51 ++- ...gateway-polish-and-recipe-qualification.md | 10 +- .../src/commissioning.rs | 10 +- .../auths-recipe-qualification/src/lib.rs | 10 +- .../auths-gateway/semantic-closure.json | 2 +- .../auths-gateway/src/bin/auths-gateway.rs | 211 ++++++++++- product/runtime/auths-gateway/src/bounds.rs | 10 + .../auths-gateway/src/commissioning_budget.rs | 11 +- .../auths-gateway/src/commissioning_floor.rs | 222 ++++++++++++ .../src/commissioning_floor/tests.rs | 264 ++++++++++++++ .../src/commissioning_session.rs | 296 +++++++++++++++ .../src/commissioning_session/tests.rs | 342 ++++++++++++++++++ product/runtime/auths-gateway/src/engine.rs | 129 ++++++- product/runtime/auths-gateway/src/lib.rs | 6 + .../auths-gateway/src/qualification.rs | 28 ++ .../auths-gateway/src/scenario_tests.rs | 2 + .../auths-gateway/src/semantic_closure.rs | 2 +- product/runtime/auths-gateway/src/submit.rs | 15 +- release/semantic-freeze-versions.toml | 8 +- release/semantic-freeze.json | 14 +- 21 files changed, 1612 insertions(+), 44 deletions(-) create mode 100644 product/runtime/auths-gateway/src/commissioning_floor.rs create mode 100644 product/runtime/auths-gateway/src/commissioning_floor/tests.rs create mode 100644 product/runtime/auths-gateway/src/commissioning_session.rs create mode 100644 product/runtime/auths-gateway/src/commissioning_session/tests.rs diff --git a/compliance.toml b/compliance.toml index aaaf7f667..59a763404 100644 --- a/compliance.toml +++ b/compliance.toml @@ -1759,6 +1759,19 @@ runtime-enforcement-boundary = [ ] stateful-replay-budget-component = [ "product/runtime/auths-gateway/src/commissioning_budget/tests.rs#capacity_survives_crash_restart_and_sweep_file", + "product/runtime/auths-gateway/src/commissioning_floor/tests.rs#runtime_never_creates_a_missing_floor", + "product/runtime/auths-gateway/src/commissioning_floor/tests.rs#committed_floor_survives_restart_and_cannot_be_reset", + "product/runtime/auths-gateway/src/commissioning_floor/tests.rs#concurrent_local_claims_never_decrease_the_witness", + "product/runtime/auths-gateway/src/commissioning_floor/tests.rs#unsafe_witness_paths_refuse_before_capacity_claim", + "product/runtime/auths-gateway/src/commissioning_floor/tests.rs#database_restore_below_retained_witness_is_refused", + "product/runtime/auths-gateway/src/commissioning_floor/tests.rs#database_claim_without_witness_acknowledgement_stays_spent", + "product/runtime/auths-gateway/src/commissioning_session/tests.rs#ordinary_submission_cannot_select_commissioning_authority", + "product/runtime/auths-gateway/src/commissioning_session/tests.rs#exact_native_actor_and_action_require_a_durable_unit_before_custody", + "product/runtime/auths-gateway/src/commissioning_session/tests.rs#absent_registration_and_expiry_after_preparation_never_lease", + "product/runtime/auths-gateway/src/commissioning_session/tests.rs#another_signed_actor_or_action_is_refused_before_custody", + "product/runtime/auths-gateway/src/commissioning_session/tests.rs#changed_resources_run_operator_or_context_cannot_open_a_session", + "product/runtime/auths-gateway/src/bin/auths-gateway.rs#concurrent_operator_imports_keep_every_authenticated_revocation", + "product/runtime/auths-gateway/src/bin/auths-gateway.rs#application_and_admin_frames_cannot_select_a_commissioning_session", "product/runtime/auths-gateway/src/commissioning_budget/tests.rs#capacity_survives_crash_restart_and_sweep_postgres", "product/runtime/auths-gateway/src/commissioning_budget/tests.rs#exactly_one_host_claims_the_final_unit_file", "product/runtime/auths-gateway/src/commissioning_budget/tests.rs#exactly_one_host_claims_the_final_unit_postgres", diff --git a/docs/adr/0016-bounded-qualification-commissioning-authority.md b/docs/adr/0016-bounded-qualification-commissioning-authority.md index 191467208..2f0bf356b 100644 --- a/docs/adr/0016-bounded-qualification-commissioning-authority.md +++ b/docs/adr/0016-bounded-qualification-commissioning-authority.md @@ -1,10 +1,10 @@ # ADR 0016: Bound the first qualification run with explicit commissioning authority **Status:** Implementing. The closed permit, commissioning-only signer purpose, -offline evidence closure, pure signature/binding verifier and atomic permanent -budget mechanism are implemented. No current gateway accepts commissioning -authority. Private operator sessions, retained host floors before custody and -the protected live workflow remain required. +offline evidence closure, pure signature/binding verifier, atomic permanent +budget, retained host floors and authenticated private operator commands are +implemented. Protected family references/workflows, production root pinning +and actual live evidence remain required before the bootstrap is resolved. Ordinary production leases still require qualification. **Date:** 7 October 2026 @@ -151,6 +151,49 @@ accounting only and grant no production credential authority. ## Consequences +The private operator interface is `commissioning-init` followed by +`commissioning-submit`. Both require the existing owner-private production +installation and its signed operator attestation. The directory passed with +`--from` contains `commissioning-permit.json`, `signer-certificate.json` and +`revocation-list.json`. `--protected-run` identifies the exact workflow run and +attempt; `--resource-binding` supplies the exact public resource file reviewed +before issuance. A submit additionally names only `--proof` and `--action`. +The root, production tuple, installed context and synchronized clock come from +the installation, with no command-line root or policy override. + +The source revision is authenticated by the permit's signature together with +the executable digest that the installation computes from its own running +binary. There is no independently changeable runtime source-commit setting. +The actor commitment is raw SHA-256 of the normalized `PrincipalId` UTF-8 +identifier; runtime extracts distinct actors only from the exact action IDs +sealed by native verification and requires exactly one. The action commitment +is the existing `auths.canonical-action.v1` commitment of verified canonical +CBOR; the context and resource commitments are raw SHA-256 of the exact +installed context and reviewed public resource-file bytes respectively. + +A host-private lock covers loading the prior witness, the database claim and +atomic witness replacement. Private regular files reject symbolic links, +hard links, different ownership, public modes, oversized bytes and malformed +state. The snapshot and parent directory are synchronized before a claim +returns. A failed acknowledgement burns any database-committed unit. Setup +also records the authenticated revocation sequence without allowing or charging +a credential acquisition. Import persistence merges prior authenticated +revocations under a separate private host lock, so concurrent or stale writers +cannot erase them. + +After a capacity/floor commit, the session rechecks current trusted time and +reloads the exact connection generation immediately before custody. Waiting +for storage cannot extend the signed permit window. Ordinary app/admin frames +have no commissioning member or command. The operator's private submission +uses the same translated order driver, native verifier, recipe checks, +reservation, replay, transport and observation implementation; its authority +is selected by the authenticated operator process, never by a proof or frame. + +Focused tests use public synthetic authority, frozen native quorum proofs and +counted custody to exercise these boundaries. They establish runtime refusal +and accounting behavior, not protected provider evidence or a completed first +qualification. Production trust remains unavailable until its root is pinned. + This adds explicit operator commissioning authority and its associated trust obligation. It does not make the first qualification appear to preexist its own evidence. Commissioning state remains distinct from `qualified`; readiness diff --git a/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md b/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md index 010ac0615..ce830240b 100644 --- a/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md +++ b/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md @@ -1772,8 +1772,8 @@ durable shared lease bounds, time and revocation. Normal application leases remain subject to the current qualification gate. A permit is neither a qualification nor evidence of provider behavior or production readiness. -This is a design prerequisite, not implementation completion or a change to -the current gateway's accepted authority. The full signed schema, issuance, -sealed runtime path, PostgreSQL accounting, authenticated operator interface, -protected workflow and rejection/live evidence must land together before the -bootstrap can be claimed resolved. Epic 5's done conditions remain unchanged. +The signed schema, pure issuance/verifier, sealed private runtime path, +PostgreSQL accounting, retained host floor and authenticated operator commands +are implemented. Production root pinning, protected family reference/workflow +and rejection/live evidence still must land before the bootstrap can be +claimed resolved. Epic 5's done conditions remain unchanged. diff --git a/product/qualification/auths-recipe-qualification/src/commissioning.rs b/product/qualification/auths-recipe-qualification/src/commissioning.rs index 7fb10faed..35a923681 100644 --- a/product/qualification/auths-recipe-qualification/src/commissioning.rs +++ b/product/qualification/auths-recipe-qualification/src/commissioning.rs @@ -21,6 +21,8 @@ mod tests; /// The separate signature domain of a commissioning permit. pub const COMMISSIONING_PERMIT_SCHEMA: &str = "auths.qualification-commissioning-permit/1"; +/// Public file within a protected commissioning artifact directory. +pub const COMMISSIONING_PERMIT_FILE: &str = "commissioning-permit.json"; /// The domain of the stable run/family budget key. pub const COMMISSIONING_BUDGET_KEY_DOMAIN: &str = "auths.qualification-commissioning-budget-key/1"; /// The domain of the immutable budget binding, including its ceiling. @@ -311,8 +313,8 @@ impl VerifiedCommissioningPermit { let cert = certificate.body(); let signer = &cert.statement; let list = revocations.body(); - let signed = permit.body(); - let statement = &signed.statement; + let permit_body = permit.body(); + let statement = &permit_body.statement; let root_key = root.body().public_key_b64.to_bytes(); let root_signature = |preimage: Result, QualificationFormatError>, signature: &SignatureB64| { @@ -328,11 +330,11 @@ impl VerifiedCommissioningPermit { || statement.issued_at < signer.issued_at || statement.not_before < signer.not_before || statement.not_after > signer.not_after - || !signed.signing_preimage().is_ok_and(|bytes| { + || !permit_body.signing_preimage().is_ok_and(|bytes| { verifies( &signer.public_key_b64.to_bytes(), &bytes, - &signed.signature_b64.to_bytes(), + &permit_body.signature_b64.to_bytes(), ) }) { diff --git a/product/qualification/auths-recipe-qualification/src/lib.rs b/product/qualification/auths-recipe-qualification/src/lib.rs index b74a7df34..a73218320 100644 --- a/product/qualification/auths-recipe-qualification/src/lib.rs +++ b/product/qualification/auths-recipe-qualification/src/lib.rs @@ -50,11 +50,11 @@ pub use closure::{ }; pub use commissioning::{ COMMISSIONING_BUDGET_BINDING_DOMAIN, COMMISSIONING_BUDGET_KEY_DOMAIN, - COMMISSIONING_PERMIT_SCHEMA, CommissioningBinding, CommissioningInputs, - CommissioningOfflineEvidence, CommissioningPermitBody, CommissioningPermitStatement, - CommissioningRefusal, CommissioningRequest, MAX_COMMISSIONING_ACTIONS, - MAX_COMMISSIONING_LEASES, MAX_COMMISSIONING_PERMIT_BYTES, MAX_COMMISSIONING_SECONDS, - QualificationCommissioningPermit, VerifiedCommissioningPermit, + COMMISSIONING_PERMIT_FILE, COMMISSIONING_PERMIT_SCHEMA, CommissioningBinding, + CommissioningInputs, CommissioningOfflineEvidence, CommissioningPermitBody, + CommissioningPermitStatement, CommissioningRefusal, CommissioningRequest, + MAX_COMMISSIONING_ACTIONS, MAX_COMMISSIONING_LEASES, MAX_COMMISSIONING_PERMIT_BYTES, + MAX_COMMISSIONING_SECONDS, QualificationCommissioningPermit, VerifiedCommissioningPermit, }; pub use error::QualificationFormatError; pub use evidence::{ diff --git a/product/runtime/auths-gateway/semantic-closure.json b/product/runtime/auths-gateway/semantic-closure.json index d2be7dc36..e5c25e937 100644 --- a/product/runtime/auths-gateway/semantic-closure.json +++ b/product/runtime/auths-gateway/semantic-closure.json @@ -1 +1 @@ -{"files":[{"path":"Cargo.lock","sha256":"0e75e2fdef44e79e57797ac6661295ae58ddb8de4a1990a6fd22ce6c54f78604"},{"path":"Cargo.toml","sha256":"6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24"},{"path":"core/adapters/auths-did-keri/Cargo.toml","sha256":"86ba3e3f9a0a70d970568bfb3113b7ba7bbdd81c3eebbb52743dd574a0c0ecaa"},{"path":"core/adapters/auths-did-keri/src/lib.rs","sha256":"a75674842f8a7142004369ccd206ab43e476459293f0ff4bed4d4e659031b3e3"},{"path":"core/adapters/auths-did-key/Cargo.toml","sha256":"d5a3ae07ecde83f91eed4c3785051dd0f44eab6c891754f3309b6b40596707d7"},{"path":"core/adapters/auths-did-key/src/lib.rs","sha256":"b76a3f4528a725df53cfa9242e6e414e1d26caa48468aaed497e28b121f4497c"},{"path":"core/adapters/auths-raw-key/Cargo.toml","sha256":"f49616bc18c19e6aaa7e6a02ccebcdb9f5c1422c1278ef9869e0dbf22ceda7be"},{"path":"core/adapters/auths-raw-key/src/lib.rs","sha256":"45eec1b295dac3bed65cd79c942870b926b06b3f5d38eaebaeb6140ac69315fa"},{"path":"core/crates/auths-algebra-kernel/Cargo.toml","sha256":"0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba"},{"path":"core/crates/auths-algebra-kernel/src/generated.rs","sha256":"ae4bcbef42a408c7ffa0c6a74a42f7de177a6f14479e51d205acf830bda05960"},{"path":"core/crates/auths-algebra-kernel/src/lib.rs","sha256":"6654667eeb9b353d6648954c9fd2e8838462a82ce6b2803eb49e1366892c68c6"},{"path":"core/crates/auths-assurance/Cargo.toml","sha256":"afcb12a97ddd09d7a264b9ecd3fcaefc865ff2c9b4539ee85b00883420ba333a"},{"path":"core/crates/auths-assurance/src/lib.rs","sha256":"0fb2ec844d674b25a9e20b1601452c89c2454901fa506adfa9bb38ef9a7fa213"},{"path":"core/crates/auths-author/Cargo.toml","sha256":"1e6f0e3bc079ddb558decf0db26b291c6e72fc47327b6df1b7650d41689b215f"},{"path":"core/crates/auths-author/src/lib.rs","sha256":"e14475f2f49715a1869d5fa6b11ff1fbb72497e39097e09f833b0bae7e5b3f2b"},{"path":"core/crates/auths-author/src/observations.rs","sha256":"dda7d6bfa6f4bd7e95a480ca283c2c0e996f69c5c15cb0c7197af328131a7066"},{"path":"core/crates/auths-authority/Cargo.toml","sha256":"4f68212938029f79ebd857b4f3038494eb85d0163d49f07e51376715cf959815"},{"path":"core/crates/auths-authority/src/lib.rs","sha256":"da88d5194de4e17449e69972c0fb042afa3c39798a8f570f30771e77c384f1eb"},{"path":"core/crates/auths-codec/Cargo.toml","sha256":"e20e51826e17814effd9d8925d18d5fbdd6c0d37bf50231e743ec2611314722c"},{"path":"core/crates/auths-codec/src/approval.rs","sha256":"fbff43bf4d57f69f8b7738a8647751cde75c5a932dee65d924a1fe9c7202f91f"},{"path":"core/crates/auths-codec/src/bounded_policy.rs","sha256":"d21f6728be2d8a04b6d94921f2b683f7e61cbb42e0ac6866f1c88a49caa534c3"},{"path":"core/crates/auths-codec/src/decode.rs","sha256":"ba2999584cdf53b1b517ecb9c7ea50d39efee17c666a9a38e2ad1ac94379f778"},{"path":"core/crates/auths-codec/src/encode.rs","sha256":"8491192053e2e15d62b4d2a491de22405b7487ead69ab6f6bca40669ce7ca5f7"},{"path":"core/crates/auths-codec/src/error.rs","sha256":"fecb0737c16deb42d859f1dc7727c698438d9ac12064fd99e0024629642c390c"},{"path":"core/crates/auths-codec/src/hash.rs","sha256":"f88e111f1dbb2cef6b7b5e9c948cb45ff92e366710c8a5f5c636138aa748479e"},{"path":"core/crates/auths-codec/src/lib.rs","sha256":"3b0e5c94c6f34f750b88a9333e1d5c8145746d845d3a23e0d2f61807cf592ea7"},{"path":"core/crates/auths-codec/src/observation.rs","sha256":"38328b0c71ff97a4196eeade8b4faa889527ff1f80bb168468bcd49082a3987e"},{"path":"core/crates/auths-composition/Cargo.toml","sha256":"331e13025eb82588b5269ed3975929eb41c823d588c49e4c296273d85c6fe80e"},{"path":"core/crates/auths-composition/src/lib.rs","sha256":"e42e3b0b6a9985b73c533aeb23799c638979aa27a9ce7d0f10a8d60340570fb1"},{"path":"core/crates/auths-model/Cargo.toml","sha256":"565c15302b0cc9270db1e28efa3862804846850ba933cc17aea8abcec4a65987"},{"path":"core/crates/auths-model/src/approval.rs","sha256":"54cf44a9ef747ec21546a4086aecfb130bc7803b0d646430e6082df51e6e305f"},{"path":"core/crates/auths-model/src/bounded.rs","sha256":"f90496abc0a06c028b4d850af6ddab7d850bfafeaa3d042f1b1246a41d8bbbc9"},{"path":"core/crates/auths-model/src/bounded_policy.rs","sha256":"306a8f049cc7cfc7635fe0e4de47eb7813eed63d3c14c3be2b51586aa4eea450"},{"path":"core/crates/auths-model/src/lib.rs","sha256":"e7cfe6bb9574c6b016aa63e70658c31e0b90903ec6479a49f4a2ceb64f5bad97"},{"path":"core/crates/auths-model/src/observation.rs","sha256":"b3ed3e3cc090afca2896a7d3de7988afccc1ee1ea0ebd91b51a8bc0f20ad8dbb"},{"path":"core/crates/auths-multikey/Cargo.toml","sha256":"858756c1197befcada06134742bffe8d58cf674cadd6c046bf710570e96efaf2"},{"path":"core/crates/auths-multikey/src/lib.rs","sha256":"f5177fffb11e40eeaaa665ba886c541fc1f24d5eacdd6983fb03dc20148733f0"},{"path":"core/crates/auths-ports/Cargo.toml","sha256":"596a9b0f5af3717c16a6d13f7054d8a106bcd9f01f5f72c2235dd2afcf0ab16c"},{"path":"core/crates/auths-ports/src/binding.rs","sha256":"a16c012d40aa4249e3ec54372b9611006d0bfe8c7dc3c741911c2194ad17736d"},{"path":"core/crates/auths-ports/src/diagnostics.rs","sha256":"aa596572503b5a65a918bb2ff38281c144ff53821ee914e9325c852828d852df"},{"path":"core/crates/auths-ports/src/lib.rs","sha256":"8da1debf86f9532df0660155d04298beb1ba3a1204508f8586e2e67cd2fb3449"},{"path":"core/crates/auths-ports/src/path.rs","sha256":"b68fc547b4e4d97a60cbbc1cc1939fc6b34a8233b81f840bd396914a707e3ea1"},{"path":"core/crates/auths-raw-key-core/Cargo.toml","sha256":"98c0bc8527a537512e43a74dd6ba9658c6f0cdc16610cf938e3f9b43785d836d"},{"path":"core/crates/auths-raw-key-core/src/lib.rs","sha256":"98c0500c41697aae28708ad0bf970b9a97583d96a3d2c18d23e7fa351e0f7d12"},{"path":"core/crates/auths-registries/Cargo.toml","sha256":"590e49e58b0622d9d6274fea46796dcdb07dec9550eff295cce6a6427ffa51e2"},{"path":"core/crates/auths-registries/src/lib.rs","sha256":"450d3886d85ee333b7e046317fb5b47cde62483d5f3e41d46265e2caf4c373ec"},{"path":"core/crates/auths-registries/src/template.rs","sha256":"1224039dd2b3ce6fa8357613d8cafbae40400493da7176da202b9ade62fa05e4"},{"path":"core/crates/auths-signature-core/Cargo.toml","sha256":"6bee2230eb30af1be0bd5c2d57bd3e1903497a70028d47290d4ac6e9e0e8bca0"},{"path":"core/crates/auths-signature-core/src/lib.rs","sha256":"6e3f9311ded5e49ea50d445eb21e6d8fa12442aa4362a73e0cb6fda15b7cd865"},{"path":"core/crates/auths-signature/Cargo.toml","sha256":"7f7b5682466ba439d8c59579022cb61068cad9fb4bd2d73e1cc21327c902b450"},{"path":"core/crates/auths-signature/src/lib.rs","sha256":"b3d9ac4cc3ba0797b9e1c09f2d6ac05089b25dac4e285a5af28c0165b33d925b"},{"path":"core/crates/auths-verifier/Cargo.toml","sha256":"c43358e06a33324b41a8b93e5cc7279c55f7d21f1f6cfaa539a3fc7b4c27a38f"},{"path":"core/crates/auths-verifier/src/approval.rs","sha256":"c3cae6a49e169051eb555bb092b1069a4d422516d6a2114623a89e5f31ff923f"},{"path":"core/crates/auths-verifier/src/causal.rs","sha256":"9635230f33b13a263573d319ac8a1976addbcc07677514a43e3c7bf28dc04587"},{"path":"core/crates/auths-verifier/src/lib.rs","sha256":"f22dec38dfa47ced8da4f605390da8453273bee1da010f57fd1fdfcb10e0b389"},{"path":"core/crates/auths-verifier/src/observation.rs","sha256":"0bb07f06a0f9524c88427df1c972b1de8ba038a9eeeb15d3134c25125ae84b1e"},{"path":"core/crates/auths-verifier/src/trace.rs","sha256":"2213d72023a1d9e0413a2cf2c51c3dad9e04775d86033a0caaa9d29a8f0036f8"},{"path":"exchange/crates/auths-proof-exchange-model/Cargo.toml","sha256":"34b2db64f93a288e942b5a3918d28cdcbef906e0dc9074ce848018d3d5f7a1fa"},{"path":"exchange/crates/auths-proof-exchange-model/src/lib.rs","sha256":"49fac5aff2339d3a57c41cb8bb2a82852538e8f77ecc4b157c88e264ff31fb55"},{"path":"exchange/crates/auths-proof-exchange-port/Cargo.toml","sha256":"7ff660f1b7579dc570c791090aeb450404fbbf44c92781e289f5ccdde746d739"},{"path":"exchange/crates/auths-proof-exchange-port/src/lib.rs","sha256":"b408fb40c6432edc1facb3d8b3e9433a033f8dc73fe2e0ba5a88c972ca675021"},{"path":"product/config/auths-config/Cargo.toml","sha256":"e4b568ab9f6d84f7d7e6d66443fe825f360db9c27bc7c31d6ddc0647ba3ab304"},{"path":"product/config/auths-config/src/lib.rs","sha256":"fecf00ea65cef9018fda9af2063326d7065b869266d0d9e73a4f06816f1102cc"},{"path":"product/errors/auths-errors/Cargo.toml","sha256":"3b3a199b6460ba75bda84475bb5accd35e1485448a3981038db85bf4772dd350"},{"path":"product/errors/auths-errors/src/lib.rs","sha256":"7feeb9069fa4003f94f1f07c1c94619cf1c883e0dbaaf2187f04d0f742264bdd"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/Cargo.toml","sha256":"716f1f2a117d6d69d8effe9ee9057e24ba3502f20af6a602b06facb638cdabed"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/api.rs","sha256":"9ea61dd7ddd93282b073b98e453e6b75b26dc49689c04e9782435d06a3a09e48"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/clock.rs","sha256":"73f0a6e0f5903883329fa6683f5888288f759512ac69e5c87efd2b6b87f7d79f"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/http.rs","sha256":"14c1fce14e24c984b2a275563a29b6326fb08367922b6e8d37ba38b9cb81aa2b"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/identity.rs","sha256":"186de11230c8b33375951c4368609f8976bf9795f171af3fd7fac26207a94361"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs","sha256":"0b4617d044f5254a5ab22f5a2578f91cc025206a8c1845be39c1c56dcdf7a5df"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/names.rs","sha256":"41bb23572d6002e23ee103d6fe70ecd68764861c6f2e48a1c53af998270a4afa"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs","sha256":"39fed883f4802e68d3b41a68fea0aba0737810996b33d13577de70faba004c29"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/store.rs","sha256":"fc60ee9c49b2f4f063c449b4c78100c5c4872779e94ca168f796603b380ef6e4"},{"path":"product/integrations/auths-custody/Cargo.toml","sha256":"1e14034185ad1ec24a977fd5f41d0abee219606245c046ce2a82287fadef448b"},{"path":"product/integrations/auths-custody/src/conformance.rs","sha256":"8ed1afd58f18fc6becc268908aa6419c9aa404c79da0197963eb2599df44acf6"},{"path":"product/integrations/auths-custody/src/key.rs","sha256":"70cbb0fd21b6f5652157845a22c35be2d0f6c05b3d138fc4b9bb6dbdc3d81c40"},{"path":"product/integrations/auths-custody/src/lib.rs","sha256":"8ee593c1f59b0fd2126bdda9138026f5bc531beb64d4489a99785842e7b98b43"},{"path":"product/operations/auths-operations/Cargo.toml","sha256":"73dde1e914ba5e1386f8d49c0d730423cc72ae77ec44c6554a6a75cc8e8922b1"},{"path":"product/operations/auths-operations/src/explanation.rs","sha256":"b4a39bcbd5712cb9e735ee7deeb281f3fa6af5ddca973735bf3d87dce427ef11"},{"path":"product/operations/auths-operations/src/lib.rs","sha256":"3f401a56555113b98f57bca172a2660eaecedf76247b83a3fdbb089c133a29cd"},{"path":"product/operations/auths-operations/src/render/json.rs","sha256":"2ae042639960afee123730e945d373bc5dda1d2b3af20ae16c939a7e99b9e418"},{"path":"product/operations/auths-operations/src/render/mod.rs","sha256":"b3b7f6fe473f49227ace5a68bfc3d8dc14b5db8dd9888fd9e207070337b1b8bf"},{"path":"product/operations/auths-operations/src/render/text.rs","sha256":"f216cf3bdb00e264523271b16e7059535ac6b1aabf271cebd7935af155e4bfec"},{"path":"product/policy/auths-bounded-policy/Cargo.toml","sha256":"babd5d200923137ead71d8c2528f847cea323ce98da942a1320b054436612c47"},{"path":"product/policy/auths-bounded-policy/src/arithmetic.rs","sha256":"75e43c5d4eab8d1f71c1daf53839f5f9fe45a400afc1f63a30c6f55ce3632627"},{"path":"product/policy/auths-bounded-policy/src/commitment.rs","sha256":"c5706f2d583454e1a7f570f7ada138d4d864bef0205dfae7c1296774f396bb3f"},{"path":"product/policy/auths-bounded-policy/src/eligibility.rs","sha256":"c9acdfb793074e687fc36efad506be27dbd99ffbf40387bc66c8de39ef238432"},{"path":"product/policy/auths-bounded-policy/src/identifier.rs","sha256":"0006a32bae9eb16c4178cf797df418d2b0a781f2bc6474b741dc1a908141831c"},{"path":"product/policy/auths-bounded-policy/src/kernel.rs","sha256":"99187c28b161ac70bee1afed60711f7f645adb4d1671a01863f9849b369811d5"},{"path":"product/policy/auths-bounded-policy/src/lib.rs","sha256":"76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c"},{"path":"product/policy/auths-bounded-policy/src/receipt.rs","sha256":"3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad"},{"path":"product/policy/auths-bounded-policy/src/registry.rs","sha256":"4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0"},{"path":"product/profiles/auths-profile-api/Cargo.toml","sha256":"7ae85761f58625b5d678f961fd052eebf3e000ef565c7312e3ac857763c0017f"},{"path":"product/profiles/auths-profile-api/src/lib.rs","sha256":"a194b82b20bf8aa864c2334ef6c6aec30b2154ded972862252d5dcefa488ab95"},{"path":"product/profiles/auths-profile-mcp/Cargo.toml","sha256":"db264fc25242f7b7e4133cbe5782545b3107b406c87168ae072683cfb59eac66"},{"path":"product/profiles/auths-profile-mcp/src/arguments.rs","sha256":"a5de696586d507e2aee4a49fee99ef1ef4c51a2e46603f8838f1af6d9009833f"},{"path":"product/profiles/auths-profile-mcp/src/lib.rs","sha256":"d0f8b733a09ef8408336cdebc8948d6a5861012ce6878598b11be7084dfd4280"},{"path":"product/profiles/auths-profile-mcp/src/session.rs","sha256":"166c281fa66333388e4760d6098dad02d3359e1d5de4b8f93312c014f97abb03"},{"path":"product/qualification/auths-recipe-qualification/Cargo.toml","sha256":"b7b15b30b9a3d96d4f089d514266d3a892de6608d30707aa44be31cca89ca9fe"},{"path":"product/qualification/auths-recipe-qualification/src/canonical.rs","sha256":"30a9b50777f0dcb4b606abfee2467d5a975d9f6ad941ab6c13ca3df5b359f667"},{"path":"product/qualification/auths-recipe-qualification/src/closure.rs","sha256":"0ad6aee9bd981e2863fa725f209ec84031db2ff12f4c7ac3aaf5120f0bb86039"},{"path":"product/qualification/auths-recipe-qualification/src/commissioning.rs","sha256":"e902df9b2c6bd06bedd32ef40e23ce14b4db4882dcb12b0f0aabcb7335cfa515"},{"path":"product/qualification/auths-recipe-qualification/src/commissioning/tests.rs","sha256":"5a226725c2ad7ce920d0bd62d427185e007f4d0949b0f0ec1260aa161d3114d0"},{"path":"product/qualification/auths-recipe-qualification/src/error.rs","sha256":"52d5cf720a1e4579008fdda90a3ac2c31f0b8db57985f121f65e54b4da2b7dd1"},{"path":"product/qualification/auths-recipe-qualification/src/evidence.rs","sha256":"ba45a7409d67a8af26ab811af306412014557477a101ab2a8eb0faf8f2bd4b91"},{"path":"product/qualification/auths-recipe-qualification/src/ids.rs","sha256":"e81a906d571497ab2da753e1532d4443706410e0b75fdd59a7d2d788c7aec403"},{"path":"product/qualification/auths-recipe-qualification/src/launch.rs","sha256":"41f2e2de90e1e7d6440a66eda3eb9bea8d5e0741bc232305a76a363ab5f813c1"},{"path":"product/qualification/auths-recipe-qualification/src/lib.rs","sha256":"7ef5cb7b8eacaa38c5d512b589db5e78e4597aed7d1a10368b86eebfb5a48aeb"},{"path":"product/qualification/auths-recipe-qualification/src/model.rs","sha256":"3484eb0ec287b23d4682ade7b1b0f8d1335985b3fb180f06fc28716076957d5f"},{"path":"product/qualification/auths-recipe-qualification/src/release.rs","sha256":"ec478e53f70052e566aac7e15be2f9e1b1cd46837ac6990ae955fa864d311586"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/mod.rs","sha256":"fa23a962fd90331152eed5edbcdf271955f7aed79b8da1e065bfe69a20b487a9"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/schemas.rs","sha256":"c59feec2805621f341a90f81fc005e2c12f7a70f9d264fdeacccb2be4fe1c046"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/verification.rs","sha256":"6a6b5834c5dae10af1ba8939b2deae43b85db71544dc8f077ff63b7fe68ac8a8"},{"path":"product/qualification/auths-recipe-qualification/src/verify.rs","sha256":"2ec2784435d11e07295de77b2ee1b2c48b2fcf9609a00454c6e7374b621aed5c"},{"path":"product/receipts/auths-receipts/Cargo.toml","sha256":"6001fa1375899953aafcb07c23a6da0c8f57ea7ec08bb9c950b12a60a8cc6f0f"},{"path":"product/receipts/auths-receipts/src/disclosure.rs","sha256":"ba9ed439be0a320c8a01f5b6e9b51361c1a37e076947490d8e4a484ba6bb119c"},{"path":"product/receipts/auths-receipts/src/lib.rs","sha256":"547a57c4160256719cafb7d0ab972d9fc80b0da14fbbce4148c70c414070ff36"},{"path":"product/runtime/auths-connections/Cargo.toml","sha256":"babeb6e1dda3dfb66291713ce1e43dce5c349833d0b50ea4dccbf986030026b2"},{"path":"product/runtime/auths-connections/src/credential.rs","sha256":"82921413bb053f0f6c7931fbd4e6a86c8cc1d8c6b51debd9c2cef33a8d5b1c51"},{"path":"product/runtime/auths-connections/src/kernel.rs","sha256":"a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8"},{"path":"product/runtime/auths-connections/src/lib.rs","sha256":"79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22"},{"path":"product/runtime/auths-connections/src/model.rs","sha256":"de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77"},{"path":"product/runtime/auths-connections/src/registry.rs","sha256":"e57640e003e72ad3235c567c2bb944a262bd64e673f023b62ea091094cc7e946"},{"path":"product/runtime/auths-gateway-kernel/Cargo.toml","sha256":"34f864e67656af4ac7e5c7a347a23f01fc8ab31365b8e23c0ef474483b14a183"},{"path":"product/runtime/auths-gateway-kernel/src/construct.rs","sha256":"e9d65744bae273d65face4285e5d2da75c06a92ab48f7b8333d496604e31c63c"},{"path":"product/runtime/auths-gateway-kernel/src/lib.rs","sha256":"cfda6f8453426564c085475f183b6f790b438768a19668f1b65d33ba59dc8632"},{"path":"product/runtime/auths-gateway-kernel/src/order.rs","sha256":"e0045f877c4b7fe3860c291039853885064ddcdebba7c9b345ab65e81e646dda"},{"path":"product/runtime/auths-gateway-kernel/src/outcome.rs","sha256":"e9785b1afe70788c89b51b18655bcd5acff7b0c8e3d12fb79c6f05a202e67e6b"},{"path":"product/runtime/auths-gateway-kernel/src/ratio.rs","sha256":"7ace22264812e6fc1ef3a62afee402cf43494bb71ae0d3de219ad1b39d690bcb"},{"path":"product/runtime/auths-gateway-kernel/src/recovery.rs","sha256":"9f46dcd1685ab6e4d1ba04a3fc286a9f3afee8fb47829be1fbc670a7926a2dc6"},{"path":"product/runtime/auths-gateway-kernel/src/transition.rs","sha256":"cefb8f01d915880f6921f2501ff881ad94b9de61072c34d9cd19220992f97374"},{"path":"product/runtime/auths-gateway/Cargo.toml","sha256":"00b28be86921dcdc0ad90cce0c62c2961cafefe96ea6c2edf0e926c3d405ccad"},{"path":"product/runtime/auths-gateway/src/admin.rs","sha256":"2d5cc67afac42fbd15f36e2d1693cd1b20cedacf775040dce6ffe04ccc94c9ea"},{"path":"product/runtime/auths-gateway/src/app.rs","sha256":"6f80f63833ea0815bb44fbf3b0cc54624a08e9fb578b035819f2980dc04e8256"},{"path":"product/runtime/auths-gateway/src/audit.rs","sha256":"0edb2037eb7b5d6f13acfce85c54f62a82bf7fdd31bc7e626c4fec183cef61dd"},{"path":"product/runtime/auths-gateway/src/audit_tests.rs","sha256":"990969384a52d75bc2489d9d412a9e7dd814bca1c8f65c701d6205fae62a15d5"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway-harness.rs","sha256":"12b0c24d36b2e6a3be392d3c081a783b355fdd67dc5b54bacc0410e803116b8c"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway.rs","sha256":"2f33a1da5dd54947ee1664795f90b3f07a11bb9ee184774bf470b78b03600f0c"},{"path":"product/runtime/auths-gateway/src/binding.rs","sha256":"663b0ce878319511aa7d05722ab4ab2fa9be18817884ffb2ee9f131ff1e382d1"},{"path":"product/runtime/auths-gateway/src/bounds.rs","sha256":"9cfa0eae4973e5e047a198360b22f041708fa20276b0b90c2ec440f06915d64b"},{"path":"product/runtime/auths-gateway/src/bounds_aggregate_tests.rs","sha256":"ab34f227b7c8692ba1da88ccb32bb3687a66adf8353d8282fae905d4a88eb612"},{"path":"product/runtime/auths-gateway/src/bounds_tests.rs","sha256":"74136bc570da7b9338b5a1a1ed9d3fd892c55135160964f9d3ac0e2cf5741375"},{"path":"product/runtime/auths-gateway/src/commissioning_budget.rs","sha256":"272bc25811931effb2d4416567c5d2e76df5ab2cc69b860b43f3bbeffb0779eb"},{"path":"product/runtime/auths-gateway/src/commissioning_budget/tests.rs","sha256":"ad182c391b70450582c6ca06e3dadc221409bb3cdbc3c7668dbfc7fbedf63505"},{"path":"product/runtime/auths-gateway/src/connection.rs","sha256":"7b5d049c258a26ed1c93ecf860f51d051a8a65f9b93554af0b1ea93862398ec9"},{"path":"product/runtime/auths-gateway/src/credential_journal.rs","sha256":"7297fccaee5cd8622928e8e0a42bba50da7941970a6f682ecd300c41ee6509da"},{"path":"product/runtime/auths-gateway/src/echo_verify.rs","sha256":"6d453051665f823abd7354d5c50031d9524cf47d6092d2f09080ae814e3b9575"},{"path":"product/runtime/auths-gateway/src/engine.rs","sha256":"f1052aaef43e441b9e0befa3f8ad1e2fd5279a27cb9d63aac0cf9dfdbe85a052"},{"path":"product/runtime/auths-gateway/src/fuzzing.rs","sha256":"ed3b0028487eb546a3b0a91d115aa8f18bcea324b61620bfe8e35a9e6ab18758"},{"path":"product/runtime/auths-gateway/src/generation_floor.rs","sha256":"fe1510ec96ce0f67e9a78edbfa94b33eb7df64c0ac4d0a67901124dcd0164777"},{"path":"product/runtime/auths-gateway/src/harness.rs","sha256":"c87e479f3eb281960f6c9c80d43c7560d7ccb654b0154ec823d3fcec4884ac05"},{"path":"product/runtime/auths-gateway/src/lib.rs","sha256":"5bc8905afe68e463bf070394eae26f6d0a49ea8d3a0265951db0228cf29d3a97"},{"path":"product/runtime/auths-gateway/src/listener.rs","sha256":"aa08239bcbc1fcb55e8a212fbdf6a84f12985b0d436dcb51dc58b06e59e435f2"},{"path":"product/runtime/auths-gateway/src/observed_tests.rs","sha256":"a22be071695f89ca2578a4d82fd80d9cb82289213c9bdb8f0470f6b2dc3d9201"},{"path":"product/runtime/auths-gateway/src/observer.rs","sha256":"562ffcaea071c3856e0708dc2fe33516917e145d2438aabb75af0a2b6ba01046"},{"path":"product/runtime/auths-gateway/src/onboarding.rs","sha256":"0dfd7d67e7f02f18a28d1c86ca1b7751d7463f5efcdbe3825de0ad8cbccb3891"},{"path":"product/runtime/auths-gateway/src/operator.rs","sha256":"c3c36954a3e86723df035b47f43b85fc8ab3a6292983522b6258d5c6b4e6c4e4"},{"path":"product/runtime/auths-gateway/src/pending_vectors/attempts.rs","sha256":"47ef3c8cb1c5504d47ae9a0088705ce6715fe86bac1671a34a56fb38a64d0dd3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/bounds.rs","sha256":"e612217307e1da5b0eb5ee6582a7458bb064b8aa8a529fc6555b1b334127ab68"},{"path":"product/runtime/auths-gateway/src/pending_vectors/codes.rs","sha256":"e00670a5ef24eb856cc2c6dcda8e5a263842f55c76bb939c0c27bd9df37e5522"},{"path":"product/runtime/auths-gateway/src/pending_vectors/keys.rs","sha256":"f84c56f2ea9cb34b2b79c72d13fbf2c6585010ec1ed450af58a78c80c1ea1edd"},{"path":"product/runtime/auths-gateway/src/pending_vectors/mod.rs","sha256":"5de8340f0ef71a0b57a09e323fefe473d3160c6ae952b9ba46f714825fbacafc"},{"path":"product/runtime/auths-gateway/src/pending_vectors/outcomes.rs","sha256":"8ec07b9511b48913af36ac999d2aa0e82924289f6acb23ddaeb9f00f99815166"},{"path":"product/runtime/auths-gateway/src/pending_vectors/production.rs","sha256":"772d032e0a0d9c924fb6d6c188528db85a97e71c9e466ddc19eee277baf83614"},{"path":"product/runtime/auths-gateway/src/pending_vectors/recipes.rs","sha256":"51693208270231c25c3aef2a32151d5962114c71e86b88cb9df83181c7af83d9"},{"path":"product/runtime/auths-gateway/src/pre_entry.rs","sha256":"06ea78ca140468bfaba17d9ab04912ad68673954c3203c98fed28272ff2a00c0"},{"path":"product/runtime/auths-gateway/src/property_tests.rs","sha256":"939c081e2e154aaf10186754044bdd65608932c899b970a04a71d0afaa999a93"},{"path":"product/runtime/auths-gateway/src/qualification.rs","sha256":"0f7eaf3c849ee7eecbebbbe0027f8b1bb65b87da23b2345d610ae088f2db8239"},{"path":"product/runtime/auths-gateway/src/qualification_simulation.rs","sha256":"4ee7cadfb5f46a92713c80f3e55f499cb074d04d8b21ea89d57762af38642bfa"},{"path":"product/runtime/auths-gateway/src/qualification_tests.rs","sha256":"a9178a2e58eea459d5e5dafc53a3999ea7c84dbbffefe6e5eb1f3d098827f028"},{"path":"product/runtime/auths-gateway/src/quorum_tests.rs","sha256":"a78380b019104d688c11a4410082c7e08ded3106aab099954c4f8a1b4ae0fd89"},{"path":"product/runtime/auths-gateway/src/readiness.rs","sha256":"911c3f11892f94641574375e2da4c671c802738f71082f12c39832331052d43d"},{"path":"product/runtime/auths-gateway/src/recipe.rs","sha256":"fecf9af67e7afc48d080e9f8f55f8ce28e49d0e08988717a27908bbda461d6b6"},{"path":"product/runtime/auths-gateway/src/recipe/lower.rs","sha256":"8088b8751ed831dbb48247af953c6290ac95e2a438ccd5bd65eff54be06a1fd1"},{"path":"product/runtime/auths-gateway/src/recipe/review.rs","sha256":"c3eb7d9fdd98dacf52750b14b67ad7b7faaecbbdeafff1e0b049f67d0a2d0139"},{"path":"product/runtime/auths-gateway/src/recipe/runtime.rs","sha256":"c286f0d15f974402822c0810d8e97f98411dc1c557755cc23e540d85e2bb42d9"},{"path":"product/runtime/auths-gateway/src/recipe/source.rs","sha256":"1af50298fb1461e1b24cbdf560d43124d6b1c4c529586c911b1c4797214a69ff"},{"path":"product/runtime/auths-gateway/src/recipe/tests.rs","sha256":"aac551a2481bbc60864c64079bc667dcb232e45a0f41a04073ed84ab5dbe1fce"},{"path":"product/runtime/auths-gateway/src/recipe/validate.rs","sha256":"3711b17605cb7b0d639bc1b180449231f5882a306cab20e2c7782155cc63b0d4"},{"path":"product/runtime/auths-gateway/src/scenario_tests.rs","sha256":"67915828ecfe2be0afadb5525277ab205f91172edc90852ec7b77c63b2d17fdc"},{"path":"product/runtime/auths-gateway/src/separation.rs","sha256":"be9306848ca5d801767cf6aa14247c8618312ef0e202f00ce0c24c4844491061"},{"path":"product/runtime/auths-gateway/src/simulation_attestation.rs","sha256":"88705e5d45415f760f1e3c3a065c35c48f4f4065bf7b3feb7882246983814d6f"},{"path":"product/runtime/auths-gateway/src/store.rs","sha256":"884bcad4d70d53e12eae9c8517f6ecd0643068ee0be0370015119d04d6cc2516"},{"path":"product/runtime/auths-gateway/src/store_testkit.rs","sha256":"88d82fee42f1b8ef521e8deef0216e938ebeaad822eb2f5020e70b89d145ea70"},{"path":"product/runtime/auths-gateway/src/submit.rs","sha256":"c78dbbba7c45b443febf655056c5edcd635e77be7b21c5b2c318097502415ffe"},{"path":"product/runtime/auths-gateway/src/support.rs","sha256":"9fd979029793a22b15d9776a7fc172476fd7c126a80d4080c65d720845becbcb"},{"path":"product/runtime/auths-gateway/src/transport.rs","sha256":"be2c6dc75b8daec110bf8749fedc3823f6067d40b999aa3eb21126896a97d3ad"},{"path":"product/runtime/auths-kernel-runtime/Cargo.toml","sha256":"926bcd0053e5edd703be8f0027ad009e2982db013c8174c1366edbf38b48087d"},{"path":"product/runtime/auths-kernel-runtime/src/lib.rs","sha256":"7108faae9ca4bc32dc093ddaf885ac8f74f3c9b8d317b7c7d0ed00d1d0ab5972"},{"path":"product/runtime/auths-lifecycle/Cargo.toml","sha256":"c5053c705f8d5554b44e432fe75287a2faf11d644e5a2552e45ad6cd94176af5"},{"path":"product/runtime/auths-lifecycle/src/codec.rs","sha256":"51c4b746749150e8bfcd8ff972b3f6c1ef40bec15583448ec1b471d9ad737dc0"},{"path":"product/runtime/auths-lifecycle/src/digest.rs","sha256":"55282cd7d8aba37713c2dcb5357c9877819edb72a30eadefb860d28d7d3a3eb7"},{"path":"product/runtime/auths-lifecycle/src/identifier.rs","sha256":"31620e8c16de68d3d2d3b84d6353c1a5b9d4151d8247f91fa389b906a8e660f1"},{"path":"product/runtime/auths-lifecycle/src/kernel.rs","sha256":"2abb8c094b36d35b364e74d78091d14c5d6f3d1eb6552cca3b5538dbd017ce23"},{"path":"product/runtime/auths-lifecycle/src/lib.rs","sha256":"afe5a345cd309b5a4f08ffba3170a6d7f16ff914892b3f2006d5208ed24ec736"},{"path":"product/runtime/auths-lifecycle/src/model.rs","sha256":"1af12bbeeeaa65ec02ddcebd7d2c8c92ec1e339fa40ae85b45ab9b01a722a4fa"},{"path":"product/runtime/auths-lifecycle/src/operation.rs","sha256":"78e6d05fcf5d7ea4f148032a3fa26fdfcab77eb346019effe927b08e0d64d732"},{"path":"product/runtime/auths-lifecycle/src/registry.rs","sha256":"53495fe6f7a77422593a41623e28716f1c140dcc1e00f87f6b0ffbfb93a5ef90"},{"path":"product/runtime/auths-lifecycle/src/sealed.rs","sha256":"2e0c03b5813c926c159598bb7890d1523825edbe57cd687d42a5dfb3374a0c19"},{"path":"product/runtime/auths-lifecycle/src/test_support.rs","sha256":"221d9a5c5ef8e1f9f8fd66927484eaf813571d0568470278ecd8fa08a5eec8cd"},{"path":"product/runtime/auths-lifecycle/src/transition.rs","sha256":"011805a28efdd541f44ccea54dd0e34a1e58f4004447ee58013703b4fb6b2822"},{"path":"product/runtime/auths-runtime/Cargo.toml","sha256":"dd29d80a8b4bb56c869f036a6c9998f6e6d1c0383ac5dc03fa42b24abe2a7ff7"},{"path":"product/runtime/auths-runtime/src/lib.rs","sha256":"132ca03d58c14905d3a822a4972f42a22a5ad33a45f2ba9ca44f3a57d810b4b0"},{"path":"product/runtime/auths-runtime/src/production.rs","sha256":"fd4eff4270c571c10fcff6cf27df28961ebf074de8a1a028f500fda1ca376820"},{"path":"product/sdk/auths-approval-quorum/Cargo.toml","sha256":"df904971fca87a24194c5816738a331588fe8f164acb5d70839a35dca5f57114"},{"path":"product/sdk/auths-approval-quorum/src/lib.rs","sha256":"72e4086088a1c0912e4e1a9e980f26a5c280bf5ab16ea39c9f0f58d5096ac2ce"},{"path":"product/sdk/auths-approval-quorum/src/remote.rs","sha256":"9fa029c7c63003adf260f8aec55160c545681c60c1bace0d934e7525862aac7b"},{"path":"product/sdk/auths-approval-quorum/src/remote_tests.rs","sha256":"8a09ce17cfee82a035a74edd535f3ebeb3db0e078784740d3997b17dbdb10197"},{"path":"product/sdk/auths-approval-quorum/src/tests.rs","sha256":"0acbf12be3e497dcc6c2d8f29c9af3b1a7ed8e11b75f6399570d4f217a785060"},{"path":"product/stores/auths-stores/Cargo.toml","sha256":"a32c4b76d17b264be5d40d24497ff237e1ed87822e8bab86229b3db93106dbe3"},{"path":"product/stores/auths-stores/src/gateway_attempt.rs","sha256":"218841602d3d9b23b44625f50e5b54cf275ccedc2d5c89f02d2482b8524472af"},{"path":"product/stores/auths-stores/src/lib.rs","sha256":"e721262edf8a9ab5568ddc27639176312d4a366203b5f73e2d7c11fde2c554e9"},{"path":"product/stores/auths-stores/src/lifecycle.rs","sha256":"3f2cecfda13fdcd7c4a944518646bcc8abd1237f900c0332d5822281f8f9f1cd"}],"schema":"auths.gateway-semantic-closure/1"} \ No newline at end of file +{"files":[{"path":"Cargo.lock","sha256":"0e75e2fdef44e79e57797ac6661295ae58ddb8de4a1990a6fd22ce6c54f78604"},{"path":"Cargo.toml","sha256":"6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24"},{"path":"core/adapters/auths-did-keri/Cargo.toml","sha256":"86ba3e3f9a0a70d970568bfb3113b7ba7bbdd81c3eebbb52743dd574a0c0ecaa"},{"path":"core/adapters/auths-did-keri/src/lib.rs","sha256":"a75674842f8a7142004369ccd206ab43e476459293f0ff4bed4d4e659031b3e3"},{"path":"core/adapters/auths-did-key/Cargo.toml","sha256":"d5a3ae07ecde83f91eed4c3785051dd0f44eab6c891754f3309b6b40596707d7"},{"path":"core/adapters/auths-did-key/src/lib.rs","sha256":"b76a3f4528a725df53cfa9242e6e414e1d26caa48468aaed497e28b121f4497c"},{"path":"core/adapters/auths-raw-key/Cargo.toml","sha256":"f49616bc18c19e6aaa7e6a02ccebcdb9f5c1422c1278ef9869e0dbf22ceda7be"},{"path":"core/adapters/auths-raw-key/src/lib.rs","sha256":"45eec1b295dac3bed65cd79c942870b926b06b3f5d38eaebaeb6140ac69315fa"},{"path":"core/crates/auths-algebra-kernel/Cargo.toml","sha256":"0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba"},{"path":"core/crates/auths-algebra-kernel/src/generated.rs","sha256":"ae4bcbef42a408c7ffa0c6a74a42f7de177a6f14479e51d205acf830bda05960"},{"path":"core/crates/auths-algebra-kernel/src/lib.rs","sha256":"6654667eeb9b353d6648954c9fd2e8838462a82ce6b2803eb49e1366892c68c6"},{"path":"core/crates/auths-assurance/Cargo.toml","sha256":"afcb12a97ddd09d7a264b9ecd3fcaefc865ff2c9b4539ee85b00883420ba333a"},{"path":"core/crates/auths-assurance/src/lib.rs","sha256":"0fb2ec844d674b25a9e20b1601452c89c2454901fa506adfa9bb38ef9a7fa213"},{"path":"core/crates/auths-author/Cargo.toml","sha256":"1e6f0e3bc079ddb558decf0db26b291c6e72fc47327b6df1b7650d41689b215f"},{"path":"core/crates/auths-author/src/lib.rs","sha256":"e14475f2f49715a1869d5fa6b11ff1fbb72497e39097e09f833b0bae7e5b3f2b"},{"path":"core/crates/auths-author/src/observations.rs","sha256":"dda7d6bfa6f4bd7e95a480ca283c2c0e996f69c5c15cb0c7197af328131a7066"},{"path":"core/crates/auths-authority/Cargo.toml","sha256":"4f68212938029f79ebd857b4f3038494eb85d0163d49f07e51376715cf959815"},{"path":"core/crates/auths-authority/src/lib.rs","sha256":"da88d5194de4e17449e69972c0fb042afa3c39798a8f570f30771e77c384f1eb"},{"path":"core/crates/auths-codec/Cargo.toml","sha256":"e20e51826e17814effd9d8925d18d5fbdd6c0d37bf50231e743ec2611314722c"},{"path":"core/crates/auths-codec/src/approval.rs","sha256":"fbff43bf4d57f69f8b7738a8647751cde75c5a932dee65d924a1fe9c7202f91f"},{"path":"core/crates/auths-codec/src/bounded_policy.rs","sha256":"d21f6728be2d8a04b6d94921f2b683f7e61cbb42e0ac6866f1c88a49caa534c3"},{"path":"core/crates/auths-codec/src/decode.rs","sha256":"ba2999584cdf53b1b517ecb9c7ea50d39efee17c666a9a38e2ad1ac94379f778"},{"path":"core/crates/auths-codec/src/encode.rs","sha256":"8491192053e2e15d62b4d2a491de22405b7487ead69ab6f6bca40669ce7ca5f7"},{"path":"core/crates/auths-codec/src/error.rs","sha256":"fecb0737c16deb42d859f1dc7727c698438d9ac12064fd99e0024629642c390c"},{"path":"core/crates/auths-codec/src/hash.rs","sha256":"f88e111f1dbb2cef6b7b5e9c948cb45ff92e366710c8a5f5c636138aa748479e"},{"path":"core/crates/auths-codec/src/lib.rs","sha256":"3b0e5c94c6f34f750b88a9333e1d5c8145746d845d3a23e0d2f61807cf592ea7"},{"path":"core/crates/auths-codec/src/observation.rs","sha256":"38328b0c71ff97a4196eeade8b4faa889527ff1f80bb168468bcd49082a3987e"},{"path":"core/crates/auths-composition/Cargo.toml","sha256":"331e13025eb82588b5269ed3975929eb41c823d588c49e4c296273d85c6fe80e"},{"path":"core/crates/auths-composition/src/lib.rs","sha256":"e42e3b0b6a9985b73c533aeb23799c638979aa27a9ce7d0f10a8d60340570fb1"},{"path":"core/crates/auths-model/Cargo.toml","sha256":"565c15302b0cc9270db1e28efa3862804846850ba933cc17aea8abcec4a65987"},{"path":"core/crates/auths-model/src/approval.rs","sha256":"54cf44a9ef747ec21546a4086aecfb130bc7803b0d646430e6082df51e6e305f"},{"path":"core/crates/auths-model/src/bounded.rs","sha256":"f90496abc0a06c028b4d850af6ddab7d850bfafeaa3d042f1b1246a41d8bbbc9"},{"path":"core/crates/auths-model/src/bounded_policy.rs","sha256":"306a8f049cc7cfc7635fe0e4de47eb7813eed63d3c14c3be2b51586aa4eea450"},{"path":"core/crates/auths-model/src/lib.rs","sha256":"e7cfe6bb9574c6b016aa63e70658c31e0b90903ec6479a49f4a2ceb64f5bad97"},{"path":"core/crates/auths-model/src/observation.rs","sha256":"b3ed3e3cc090afca2896a7d3de7988afccc1ee1ea0ebd91b51a8bc0f20ad8dbb"},{"path":"core/crates/auths-multikey/Cargo.toml","sha256":"858756c1197befcada06134742bffe8d58cf674cadd6c046bf710570e96efaf2"},{"path":"core/crates/auths-multikey/src/lib.rs","sha256":"f5177fffb11e40eeaaa665ba886c541fc1f24d5eacdd6983fb03dc20148733f0"},{"path":"core/crates/auths-ports/Cargo.toml","sha256":"596a9b0f5af3717c16a6d13f7054d8a106bcd9f01f5f72c2235dd2afcf0ab16c"},{"path":"core/crates/auths-ports/src/binding.rs","sha256":"a16c012d40aa4249e3ec54372b9611006d0bfe8c7dc3c741911c2194ad17736d"},{"path":"core/crates/auths-ports/src/diagnostics.rs","sha256":"aa596572503b5a65a918bb2ff38281c144ff53821ee914e9325c852828d852df"},{"path":"core/crates/auths-ports/src/lib.rs","sha256":"8da1debf86f9532df0660155d04298beb1ba3a1204508f8586e2e67cd2fb3449"},{"path":"core/crates/auths-ports/src/path.rs","sha256":"b68fc547b4e4d97a60cbbc1cc1939fc6b34a8233b81f840bd396914a707e3ea1"},{"path":"core/crates/auths-raw-key-core/Cargo.toml","sha256":"98c0bc8527a537512e43a74dd6ba9658c6f0cdc16610cf938e3f9b43785d836d"},{"path":"core/crates/auths-raw-key-core/src/lib.rs","sha256":"98c0500c41697aae28708ad0bf970b9a97583d96a3d2c18d23e7fa351e0f7d12"},{"path":"core/crates/auths-registries/Cargo.toml","sha256":"590e49e58b0622d9d6274fea46796dcdb07dec9550eff295cce6a6427ffa51e2"},{"path":"core/crates/auths-registries/src/lib.rs","sha256":"450d3886d85ee333b7e046317fb5b47cde62483d5f3e41d46265e2caf4c373ec"},{"path":"core/crates/auths-registries/src/template.rs","sha256":"1224039dd2b3ce6fa8357613d8cafbae40400493da7176da202b9ade62fa05e4"},{"path":"core/crates/auths-signature-core/Cargo.toml","sha256":"6bee2230eb30af1be0bd5c2d57bd3e1903497a70028d47290d4ac6e9e0e8bca0"},{"path":"core/crates/auths-signature-core/src/lib.rs","sha256":"6e3f9311ded5e49ea50d445eb21e6d8fa12442aa4362a73e0cb6fda15b7cd865"},{"path":"core/crates/auths-signature/Cargo.toml","sha256":"7f7b5682466ba439d8c59579022cb61068cad9fb4bd2d73e1cc21327c902b450"},{"path":"core/crates/auths-signature/src/lib.rs","sha256":"b3d9ac4cc3ba0797b9e1c09f2d6ac05089b25dac4e285a5af28c0165b33d925b"},{"path":"core/crates/auths-verifier/Cargo.toml","sha256":"c43358e06a33324b41a8b93e5cc7279c55f7d21f1f6cfaa539a3fc7b4c27a38f"},{"path":"core/crates/auths-verifier/src/approval.rs","sha256":"c3cae6a49e169051eb555bb092b1069a4d422516d6a2114623a89e5f31ff923f"},{"path":"core/crates/auths-verifier/src/causal.rs","sha256":"9635230f33b13a263573d319ac8a1976addbcc07677514a43e3c7bf28dc04587"},{"path":"core/crates/auths-verifier/src/lib.rs","sha256":"f22dec38dfa47ced8da4f605390da8453273bee1da010f57fd1fdfcb10e0b389"},{"path":"core/crates/auths-verifier/src/observation.rs","sha256":"0bb07f06a0f9524c88427df1c972b1de8ba038a9eeeb15d3134c25125ae84b1e"},{"path":"core/crates/auths-verifier/src/trace.rs","sha256":"2213d72023a1d9e0413a2cf2c51c3dad9e04775d86033a0caaa9d29a8f0036f8"},{"path":"exchange/crates/auths-proof-exchange-model/Cargo.toml","sha256":"34b2db64f93a288e942b5a3918d28cdcbef906e0dc9074ce848018d3d5f7a1fa"},{"path":"exchange/crates/auths-proof-exchange-model/src/lib.rs","sha256":"49fac5aff2339d3a57c41cb8bb2a82852538e8f77ecc4b157c88e264ff31fb55"},{"path":"exchange/crates/auths-proof-exchange-port/Cargo.toml","sha256":"7ff660f1b7579dc570c791090aeb450404fbbf44c92781e289f5ccdde746d739"},{"path":"exchange/crates/auths-proof-exchange-port/src/lib.rs","sha256":"b408fb40c6432edc1facb3d8b3e9433a033f8dc73fe2e0ba5a88c972ca675021"},{"path":"product/config/auths-config/Cargo.toml","sha256":"e4b568ab9f6d84f7d7e6d66443fe825f360db9c27bc7c31d6ddc0647ba3ab304"},{"path":"product/config/auths-config/src/lib.rs","sha256":"fecf00ea65cef9018fda9af2063326d7065b869266d0d9e73a4f06816f1102cc"},{"path":"product/errors/auths-errors/Cargo.toml","sha256":"3b3a199b6460ba75bda84475bb5accd35e1485448a3981038db85bf4772dd350"},{"path":"product/errors/auths-errors/src/lib.rs","sha256":"7feeb9069fa4003f94f1f07c1c94619cf1c883e0dbaaf2187f04d0f742264bdd"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/Cargo.toml","sha256":"716f1f2a117d6d69d8effe9ee9057e24ba3502f20af6a602b06facb638cdabed"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/api.rs","sha256":"9ea61dd7ddd93282b073b98e453e6b75b26dc49689c04e9782435d06a3a09e48"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/clock.rs","sha256":"73f0a6e0f5903883329fa6683f5888288f759512ac69e5c87efd2b6b87f7d79f"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/http.rs","sha256":"14c1fce14e24c984b2a275563a29b6326fb08367922b6e8d37ba38b9cb81aa2b"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/identity.rs","sha256":"186de11230c8b33375951c4368609f8976bf9795f171af3fd7fac26207a94361"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs","sha256":"0b4617d044f5254a5ab22f5a2578f91cc025206a8c1845be39c1c56dcdf7a5df"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/names.rs","sha256":"41bb23572d6002e23ee103d6fe70ecd68764861c6f2e48a1c53af998270a4afa"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs","sha256":"39fed883f4802e68d3b41a68fea0aba0737810996b33d13577de70faba004c29"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/store.rs","sha256":"fc60ee9c49b2f4f063c449b4c78100c5c4872779e94ca168f796603b380ef6e4"},{"path":"product/integrations/auths-custody/Cargo.toml","sha256":"1e14034185ad1ec24a977fd5f41d0abee219606245c046ce2a82287fadef448b"},{"path":"product/integrations/auths-custody/src/conformance.rs","sha256":"8ed1afd58f18fc6becc268908aa6419c9aa404c79da0197963eb2599df44acf6"},{"path":"product/integrations/auths-custody/src/key.rs","sha256":"70cbb0fd21b6f5652157845a22c35be2d0f6c05b3d138fc4b9bb6dbdc3d81c40"},{"path":"product/integrations/auths-custody/src/lib.rs","sha256":"8ee593c1f59b0fd2126bdda9138026f5bc531beb64d4489a99785842e7b98b43"},{"path":"product/operations/auths-operations/Cargo.toml","sha256":"73dde1e914ba5e1386f8d49c0d730423cc72ae77ec44c6554a6a75cc8e8922b1"},{"path":"product/operations/auths-operations/src/explanation.rs","sha256":"b4a39bcbd5712cb9e735ee7deeb281f3fa6af5ddca973735bf3d87dce427ef11"},{"path":"product/operations/auths-operations/src/lib.rs","sha256":"3f401a56555113b98f57bca172a2660eaecedf76247b83a3fdbb089c133a29cd"},{"path":"product/operations/auths-operations/src/render/json.rs","sha256":"2ae042639960afee123730e945d373bc5dda1d2b3af20ae16c939a7e99b9e418"},{"path":"product/operations/auths-operations/src/render/mod.rs","sha256":"b3b7f6fe473f49227ace5a68bfc3d8dc14b5db8dd9888fd9e207070337b1b8bf"},{"path":"product/operations/auths-operations/src/render/text.rs","sha256":"f216cf3bdb00e264523271b16e7059535ac6b1aabf271cebd7935af155e4bfec"},{"path":"product/policy/auths-bounded-policy/Cargo.toml","sha256":"babd5d200923137ead71d8c2528f847cea323ce98da942a1320b054436612c47"},{"path":"product/policy/auths-bounded-policy/src/arithmetic.rs","sha256":"75e43c5d4eab8d1f71c1daf53839f5f9fe45a400afc1f63a30c6f55ce3632627"},{"path":"product/policy/auths-bounded-policy/src/commitment.rs","sha256":"c5706f2d583454e1a7f570f7ada138d4d864bef0205dfae7c1296774f396bb3f"},{"path":"product/policy/auths-bounded-policy/src/eligibility.rs","sha256":"c9acdfb793074e687fc36efad506be27dbd99ffbf40387bc66c8de39ef238432"},{"path":"product/policy/auths-bounded-policy/src/identifier.rs","sha256":"0006a32bae9eb16c4178cf797df418d2b0a781f2bc6474b741dc1a908141831c"},{"path":"product/policy/auths-bounded-policy/src/kernel.rs","sha256":"99187c28b161ac70bee1afed60711f7f645adb4d1671a01863f9849b369811d5"},{"path":"product/policy/auths-bounded-policy/src/lib.rs","sha256":"76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c"},{"path":"product/policy/auths-bounded-policy/src/receipt.rs","sha256":"3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad"},{"path":"product/policy/auths-bounded-policy/src/registry.rs","sha256":"4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0"},{"path":"product/profiles/auths-profile-api/Cargo.toml","sha256":"7ae85761f58625b5d678f961fd052eebf3e000ef565c7312e3ac857763c0017f"},{"path":"product/profiles/auths-profile-api/src/lib.rs","sha256":"a194b82b20bf8aa864c2334ef6c6aec30b2154ded972862252d5dcefa488ab95"},{"path":"product/profiles/auths-profile-mcp/Cargo.toml","sha256":"db264fc25242f7b7e4133cbe5782545b3107b406c87168ae072683cfb59eac66"},{"path":"product/profiles/auths-profile-mcp/src/arguments.rs","sha256":"a5de696586d507e2aee4a49fee99ef1ef4c51a2e46603f8838f1af6d9009833f"},{"path":"product/profiles/auths-profile-mcp/src/lib.rs","sha256":"d0f8b733a09ef8408336cdebc8948d6a5861012ce6878598b11be7084dfd4280"},{"path":"product/profiles/auths-profile-mcp/src/session.rs","sha256":"166c281fa66333388e4760d6098dad02d3359e1d5de4b8f93312c014f97abb03"},{"path":"product/qualification/auths-recipe-qualification/Cargo.toml","sha256":"b7b15b30b9a3d96d4f089d514266d3a892de6608d30707aa44be31cca89ca9fe"},{"path":"product/qualification/auths-recipe-qualification/src/canonical.rs","sha256":"30a9b50777f0dcb4b606abfee2467d5a975d9f6ad941ab6c13ca3df5b359f667"},{"path":"product/qualification/auths-recipe-qualification/src/closure.rs","sha256":"0ad6aee9bd981e2863fa725f209ec84031db2ff12f4c7ac3aaf5120f0bb86039"},{"path":"product/qualification/auths-recipe-qualification/src/commissioning.rs","sha256":"66ea49f96887c4642139a48d259c270816e2267ee8cf6344a1340fe47afda9da"},{"path":"product/qualification/auths-recipe-qualification/src/commissioning/tests.rs","sha256":"5a226725c2ad7ce920d0bd62d427185e007f4d0949b0f0ec1260aa161d3114d0"},{"path":"product/qualification/auths-recipe-qualification/src/error.rs","sha256":"52d5cf720a1e4579008fdda90a3ac2c31f0b8db57985f121f65e54b4da2b7dd1"},{"path":"product/qualification/auths-recipe-qualification/src/evidence.rs","sha256":"ba45a7409d67a8af26ab811af306412014557477a101ab2a8eb0faf8f2bd4b91"},{"path":"product/qualification/auths-recipe-qualification/src/ids.rs","sha256":"e81a906d571497ab2da753e1532d4443706410e0b75fdd59a7d2d788c7aec403"},{"path":"product/qualification/auths-recipe-qualification/src/launch.rs","sha256":"41f2e2de90e1e7d6440a66eda3eb9bea8d5e0741bc232305a76a363ab5f813c1"},{"path":"product/qualification/auths-recipe-qualification/src/lib.rs","sha256":"7d26c5bfe9769daebf90c5c2280e0d75742e4cc70d0e608408e0665e3f516a2b"},{"path":"product/qualification/auths-recipe-qualification/src/model.rs","sha256":"3484eb0ec287b23d4682ade7b1b0f8d1335985b3fb180f06fc28716076957d5f"},{"path":"product/qualification/auths-recipe-qualification/src/release.rs","sha256":"ec478e53f70052e566aac7e15be2f9e1b1cd46837ac6990ae955fa864d311586"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/mod.rs","sha256":"fa23a962fd90331152eed5edbcdf271955f7aed79b8da1e065bfe69a20b487a9"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/schemas.rs","sha256":"c59feec2805621f341a90f81fc005e2c12f7a70f9d264fdeacccb2be4fe1c046"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/verification.rs","sha256":"6a6b5834c5dae10af1ba8939b2deae43b85db71544dc8f077ff63b7fe68ac8a8"},{"path":"product/qualification/auths-recipe-qualification/src/verify.rs","sha256":"2ec2784435d11e07295de77b2ee1b2c48b2fcf9609a00454c6e7374b621aed5c"},{"path":"product/receipts/auths-receipts/Cargo.toml","sha256":"6001fa1375899953aafcb07c23a6da0c8f57ea7ec08bb9c950b12a60a8cc6f0f"},{"path":"product/receipts/auths-receipts/src/disclosure.rs","sha256":"ba9ed439be0a320c8a01f5b6e9b51361c1a37e076947490d8e4a484ba6bb119c"},{"path":"product/receipts/auths-receipts/src/lib.rs","sha256":"547a57c4160256719cafb7d0ab972d9fc80b0da14fbbce4148c70c414070ff36"},{"path":"product/runtime/auths-connections/Cargo.toml","sha256":"babeb6e1dda3dfb66291713ce1e43dce5c349833d0b50ea4dccbf986030026b2"},{"path":"product/runtime/auths-connections/src/credential.rs","sha256":"82921413bb053f0f6c7931fbd4e6a86c8cc1d8c6b51debd9c2cef33a8d5b1c51"},{"path":"product/runtime/auths-connections/src/kernel.rs","sha256":"a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8"},{"path":"product/runtime/auths-connections/src/lib.rs","sha256":"79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22"},{"path":"product/runtime/auths-connections/src/model.rs","sha256":"de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77"},{"path":"product/runtime/auths-connections/src/registry.rs","sha256":"e57640e003e72ad3235c567c2bb944a262bd64e673f023b62ea091094cc7e946"},{"path":"product/runtime/auths-gateway-kernel/Cargo.toml","sha256":"34f864e67656af4ac7e5c7a347a23f01fc8ab31365b8e23c0ef474483b14a183"},{"path":"product/runtime/auths-gateway-kernel/src/construct.rs","sha256":"e9d65744bae273d65face4285e5d2da75c06a92ab48f7b8333d496604e31c63c"},{"path":"product/runtime/auths-gateway-kernel/src/lib.rs","sha256":"cfda6f8453426564c085475f183b6f790b438768a19668f1b65d33ba59dc8632"},{"path":"product/runtime/auths-gateway-kernel/src/order.rs","sha256":"e0045f877c4b7fe3860c291039853885064ddcdebba7c9b345ab65e81e646dda"},{"path":"product/runtime/auths-gateway-kernel/src/outcome.rs","sha256":"e9785b1afe70788c89b51b18655bcd5acff7b0c8e3d12fb79c6f05a202e67e6b"},{"path":"product/runtime/auths-gateway-kernel/src/ratio.rs","sha256":"7ace22264812e6fc1ef3a62afee402cf43494bb71ae0d3de219ad1b39d690bcb"},{"path":"product/runtime/auths-gateway-kernel/src/recovery.rs","sha256":"9f46dcd1685ab6e4d1ba04a3fc286a9f3afee8fb47829be1fbc670a7926a2dc6"},{"path":"product/runtime/auths-gateway-kernel/src/transition.rs","sha256":"cefb8f01d915880f6921f2501ff881ad94b9de61072c34d9cd19220992f97374"},{"path":"product/runtime/auths-gateway/Cargo.toml","sha256":"00b28be86921dcdc0ad90cce0c62c2961cafefe96ea6c2edf0e926c3d405ccad"},{"path":"product/runtime/auths-gateway/src/admin.rs","sha256":"2d5cc67afac42fbd15f36e2d1693cd1b20cedacf775040dce6ffe04ccc94c9ea"},{"path":"product/runtime/auths-gateway/src/app.rs","sha256":"6f80f63833ea0815bb44fbf3b0cc54624a08e9fb578b035819f2980dc04e8256"},{"path":"product/runtime/auths-gateway/src/audit.rs","sha256":"0edb2037eb7b5d6f13acfce85c54f62a82bf7fdd31bc7e626c4fec183cef61dd"},{"path":"product/runtime/auths-gateway/src/audit_tests.rs","sha256":"990969384a52d75bc2489d9d412a9e7dd814bca1c8f65c701d6205fae62a15d5"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway-harness.rs","sha256":"12b0c24d36b2e6a3be392d3c081a783b355fdd67dc5b54bacc0410e803116b8c"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway.rs","sha256":"2a5d64c1f8a845d4a073ce12ed7fa23ee7db515b2d356eeae774b1f670e056fa"},{"path":"product/runtime/auths-gateway/src/binding.rs","sha256":"663b0ce878319511aa7d05722ab4ab2fa9be18817884ffb2ee9f131ff1e382d1"},{"path":"product/runtime/auths-gateway/src/bounds.rs","sha256":"38251ad6f22f9d07ef9a219c79fa265ca36f1526eca5f147d7efa46b52ad609d"},{"path":"product/runtime/auths-gateway/src/bounds_aggregate_tests.rs","sha256":"ab34f227b7c8692ba1da88ccb32bb3687a66adf8353d8282fae905d4a88eb612"},{"path":"product/runtime/auths-gateway/src/bounds_tests.rs","sha256":"74136bc570da7b9338b5a1a1ed9d3fd892c55135160964f9d3ac0e2cf5741375"},{"path":"product/runtime/auths-gateway/src/commissioning_budget.rs","sha256":"fab29da3269438cc62330f3eab7b5bd4dc482b4db8af243aae47df5d3aa1deb8"},{"path":"product/runtime/auths-gateway/src/commissioning_budget/tests.rs","sha256":"ad182c391b70450582c6ca06e3dadc221409bb3cdbc3c7668dbfc7fbedf63505"},{"path":"product/runtime/auths-gateway/src/commissioning_floor.rs","sha256":"7fa6991c5ccd5ae1403be84b3da390323fab09f36e15ac01fd7a38ea350c6fdb"},{"path":"product/runtime/auths-gateway/src/commissioning_floor/tests.rs","sha256":"5f7868252dfccb787d26f63ea6d5c3701c72d52c0ff0bc656dd5895f8cbed551"},{"path":"product/runtime/auths-gateway/src/commissioning_session.rs","sha256":"24b48d5eaeaaa3c620e2dfc7ee1f9255fc4519a1eb404b8608cea7af6a910ee2"},{"path":"product/runtime/auths-gateway/src/commissioning_session/tests.rs","sha256":"6f8aad6dae4888c147076937c9ec0968e5b5eedde71d4cfcce0d988bd56b83ec"},{"path":"product/runtime/auths-gateway/src/connection.rs","sha256":"7b5d049c258a26ed1c93ecf860f51d051a8a65f9b93554af0b1ea93862398ec9"},{"path":"product/runtime/auths-gateway/src/credential_journal.rs","sha256":"7297fccaee5cd8622928e8e0a42bba50da7941970a6f682ecd300c41ee6509da"},{"path":"product/runtime/auths-gateway/src/echo_verify.rs","sha256":"6d453051665f823abd7354d5c50031d9524cf47d6092d2f09080ae814e3b9575"},{"path":"product/runtime/auths-gateway/src/engine.rs","sha256":"3ae83ee8eef51082084cc047b4f6b0eb26dd33f711cf5c415572366e716257ac"},{"path":"product/runtime/auths-gateway/src/fuzzing.rs","sha256":"ed3b0028487eb546a3b0a91d115aa8f18bcea324b61620bfe8e35a9e6ab18758"},{"path":"product/runtime/auths-gateway/src/generation_floor.rs","sha256":"fe1510ec96ce0f67e9a78edbfa94b33eb7df64c0ac4d0a67901124dcd0164777"},{"path":"product/runtime/auths-gateway/src/harness.rs","sha256":"c87e479f3eb281960f6c9c80d43c7560d7ccb654b0154ec823d3fcec4884ac05"},{"path":"product/runtime/auths-gateway/src/lib.rs","sha256":"47214352c400c50bd7c5cb54c132218960ce2f5dd0285c1dd9dcdebb4651de3a"},{"path":"product/runtime/auths-gateway/src/listener.rs","sha256":"aa08239bcbc1fcb55e8a212fbdf6a84f12985b0d436dcb51dc58b06e59e435f2"},{"path":"product/runtime/auths-gateway/src/observed_tests.rs","sha256":"a22be071695f89ca2578a4d82fd80d9cb82289213c9bdb8f0470f6b2dc3d9201"},{"path":"product/runtime/auths-gateway/src/observer.rs","sha256":"562ffcaea071c3856e0708dc2fe33516917e145d2438aabb75af0a2b6ba01046"},{"path":"product/runtime/auths-gateway/src/onboarding.rs","sha256":"0dfd7d67e7f02f18a28d1c86ca1b7751d7463f5efcdbe3825de0ad8cbccb3891"},{"path":"product/runtime/auths-gateway/src/operator.rs","sha256":"c3c36954a3e86723df035b47f43b85fc8ab3a6292983522b6258d5c6b4e6c4e4"},{"path":"product/runtime/auths-gateway/src/pending_vectors/attempts.rs","sha256":"47ef3c8cb1c5504d47ae9a0088705ce6715fe86bac1671a34a56fb38a64d0dd3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/bounds.rs","sha256":"e612217307e1da5b0eb5ee6582a7458bb064b8aa8a529fc6555b1b334127ab68"},{"path":"product/runtime/auths-gateway/src/pending_vectors/codes.rs","sha256":"e00670a5ef24eb856cc2c6dcda8e5a263842f55c76bb939c0c27bd9df37e5522"},{"path":"product/runtime/auths-gateway/src/pending_vectors/keys.rs","sha256":"f84c56f2ea9cb34b2b79c72d13fbf2c6585010ec1ed450af58a78c80c1ea1edd"},{"path":"product/runtime/auths-gateway/src/pending_vectors/mod.rs","sha256":"5de8340f0ef71a0b57a09e323fefe473d3160c6ae952b9ba46f714825fbacafc"},{"path":"product/runtime/auths-gateway/src/pending_vectors/outcomes.rs","sha256":"8ec07b9511b48913af36ac999d2aa0e82924289f6acb23ddaeb9f00f99815166"},{"path":"product/runtime/auths-gateway/src/pending_vectors/production.rs","sha256":"772d032e0a0d9c924fb6d6c188528db85a97e71c9e466ddc19eee277baf83614"},{"path":"product/runtime/auths-gateway/src/pending_vectors/recipes.rs","sha256":"51693208270231c25c3aef2a32151d5962114c71e86b88cb9df83181c7af83d9"},{"path":"product/runtime/auths-gateway/src/pre_entry.rs","sha256":"06ea78ca140468bfaba17d9ab04912ad68673954c3203c98fed28272ff2a00c0"},{"path":"product/runtime/auths-gateway/src/property_tests.rs","sha256":"939c081e2e154aaf10186754044bdd65608932c899b970a04a71d0afaa999a93"},{"path":"product/runtime/auths-gateway/src/qualification.rs","sha256":"b239aef182ddf836dad234f2d5c3d2db2c13f14f394b46bc2fb940fc3dff90bf"},{"path":"product/runtime/auths-gateway/src/qualification_simulation.rs","sha256":"4ee7cadfb5f46a92713c80f3e55f499cb074d04d8b21ea89d57762af38642bfa"},{"path":"product/runtime/auths-gateway/src/qualification_tests.rs","sha256":"a9178a2e58eea459d5e5dafc53a3999ea7c84dbbffefe6e5eb1f3d098827f028"},{"path":"product/runtime/auths-gateway/src/quorum_tests.rs","sha256":"a78380b019104d688c11a4410082c7e08ded3106aab099954c4f8a1b4ae0fd89"},{"path":"product/runtime/auths-gateway/src/readiness.rs","sha256":"911c3f11892f94641574375e2da4c671c802738f71082f12c39832331052d43d"},{"path":"product/runtime/auths-gateway/src/recipe.rs","sha256":"fecf9af67e7afc48d080e9f8f55f8ce28e49d0e08988717a27908bbda461d6b6"},{"path":"product/runtime/auths-gateway/src/recipe/lower.rs","sha256":"8088b8751ed831dbb48247af953c6290ac95e2a438ccd5bd65eff54be06a1fd1"},{"path":"product/runtime/auths-gateway/src/recipe/review.rs","sha256":"c3eb7d9fdd98dacf52750b14b67ad7b7faaecbbdeafff1e0b049f67d0a2d0139"},{"path":"product/runtime/auths-gateway/src/recipe/runtime.rs","sha256":"c286f0d15f974402822c0810d8e97f98411dc1c557755cc23e540d85e2bb42d9"},{"path":"product/runtime/auths-gateway/src/recipe/source.rs","sha256":"1af50298fb1461e1b24cbdf560d43124d6b1c4c529586c911b1c4797214a69ff"},{"path":"product/runtime/auths-gateway/src/recipe/tests.rs","sha256":"aac551a2481bbc60864c64079bc667dcb232e45a0f41a04073ed84ab5dbe1fce"},{"path":"product/runtime/auths-gateway/src/recipe/validate.rs","sha256":"3711b17605cb7b0d639bc1b180449231f5882a306cab20e2c7782155cc63b0d4"},{"path":"product/runtime/auths-gateway/src/scenario_tests.rs","sha256":"a8ea1e3a7bf6b0274455bd790ace3ffb9c8716609cde92248920945c61634685"},{"path":"product/runtime/auths-gateway/src/separation.rs","sha256":"be9306848ca5d801767cf6aa14247c8618312ef0e202f00ce0c24c4844491061"},{"path":"product/runtime/auths-gateway/src/simulation_attestation.rs","sha256":"88705e5d45415f760f1e3c3a065c35c48f4f4065bf7b3feb7882246983814d6f"},{"path":"product/runtime/auths-gateway/src/store.rs","sha256":"884bcad4d70d53e12eae9c8517f6ecd0643068ee0be0370015119d04d6cc2516"},{"path":"product/runtime/auths-gateway/src/store_testkit.rs","sha256":"88d82fee42f1b8ef521e8deef0216e938ebeaad822eb2f5020e70b89d145ea70"},{"path":"product/runtime/auths-gateway/src/submit.rs","sha256":"fe2eacb5ad8152eeecbd232c47a356fc72db0098e34fda99532bdf6ef0cf895c"},{"path":"product/runtime/auths-gateway/src/support.rs","sha256":"9fd979029793a22b15d9776a7fc172476fd7c126a80d4080c65d720845becbcb"},{"path":"product/runtime/auths-gateway/src/transport.rs","sha256":"be2c6dc75b8daec110bf8749fedc3823f6067d40b999aa3eb21126896a97d3ad"},{"path":"product/runtime/auths-kernel-runtime/Cargo.toml","sha256":"926bcd0053e5edd703be8f0027ad009e2982db013c8174c1366edbf38b48087d"},{"path":"product/runtime/auths-kernel-runtime/src/lib.rs","sha256":"7108faae9ca4bc32dc093ddaf885ac8f74f3c9b8d317b7c7d0ed00d1d0ab5972"},{"path":"product/runtime/auths-lifecycle/Cargo.toml","sha256":"c5053c705f8d5554b44e432fe75287a2faf11d644e5a2552e45ad6cd94176af5"},{"path":"product/runtime/auths-lifecycle/src/codec.rs","sha256":"51c4b746749150e8bfcd8ff972b3f6c1ef40bec15583448ec1b471d9ad737dc0"},{"path":"product/runtime/auths-lifecycle/src/digest.rs","sha256":"55282cd7d8aba37713c2dcb5357c9877819edb72a30eadefb860d28d7d3a3eb7"},{"path":"product/runtime/auths-lifecycle/src/identifier.rs","sha256":"31620e8c16de68d3d2d3b84d6353c1a5b9d4151d8247f91fa389b906a8e660f1"},{"path":"product/runtime/auths-lifecycle/src/kernel.rs","sha256":"2abb8c094b36d35b364e74d78091d14c5d6f3d1eb6552cca3b5538dbd017ce23"},{"path":"product/runtime/auths-lifecycle/src/lib.rs","sha256":"afe5a345cd309b5a4f08ffba3170a6d7f16ff914892b3f2006d5208ed24ec736"},{"path":"product/runtime/auths-lifecycle/src/model.rs","sha256":"1af12bbeeeaa65ec02ddcebd7d2c8c92ec1e339fa40ae85b45ab9b01a722a4fa"},{"path":"product/runtime/auths-lifecycle/src/operation.rs","sha256":"78e6d05fcf5d7ea4f148032a3fa26fdfcab77eb346019effe927b08e0d64d732"},{"path":"product/runtime/auths-lifecycle/src/registry.rs","sha256":"53495fe6f7a77422593a41623e28716f1c140dcc1e00f87f6b0ffbfb93a5ef90"},{"path":"product/runtime/auths-lifecycle/src/sealed.rs","sha256":"2e0c03b5813c926c159598bb7890d1523825edbe57cd687d42a5dfb3374a0c19"},{"path":"product/runtime/auths-lifecycle/src/test_support.rs","sha256":"221d9a5c5ef8e1f9f8fd66927484eaf813571d0568470278ecd8fa08a5eec8cd"},{"path":"product/runtime/auths-lifecycle/src/transition.rs","sha256":"011805a28efdd541f44ccea54dd0e34a1e58f4004447ee58013703b4fb6b2822"},{"path":"product/runtime/auths-runtime/Cargo.toml","sha256":"dd29d80a8b4bb56c869f036a6c9998f6e6d1c0383ac5dc03fa42b24abe2a7ff7"},{"path":"product/runtime/auths-runtime/src/lib.rs","sha256":"132ca03d58c14905d3a822a4972f42a22a5ad33a45f2ba9ca44f3a57d810b4b0"},{"path":"product/runtime/auths-runtime/src/production.rs","sha256":"fd4eff4270c571c10fcff6cf27df28961ebf074de8a1a028f500fda1ca376820"},{"path":"product/sdk/auths-approval-quorum/Cargo.toml","sha256":"df904971fca87a24194c5816738a331588fe8f164acb5d70839a35dca5f57114"},{"path":"product/sdk/auths-approval-quorum/src/lib.rs","sha256":"72e4086088a1c0912e4e1a9e980f26a5c280bf5ab16ea39c9f0f58d5096ac2ce"},{"path":"product/sdk/auths-approval-quorum/src/remote.rs","sha256":"9fa029c7c63003adf260f8aec55160c545681c60c1bace0d934e7525862aac7b"},{"path":"product/sdk/auths-approval-quorum/src/remote_tests.rs","sha256":"8a09ce17cfee82a035a74edd535f3ebeb3db0e078784740d3997b17dbdb10197"},{"path":"product/sdk/auths-approval-quorum/src/tests.rs","sha256":"0acbf12be3e497dcc6c2d8f29c9af3b1a7ed8e11b75f6399570d4f217a785060"},{"path":"product/stores/auths-stores/Cargo.toml","sha256":"a32c4b76d17b264be5d40d24497ff237e1ed87822e8bab86229b3db93106dbe3"},{"path":"product/stores/auths-stores/src/gateway_attempt.rs","sha256":"218841602d3d9b23b44625f50e5b54cf275ccedc2d5c89f02d2482b8524472af"},{"path":"product/stores/auths-stores/src/lib.rs","sha256":"e721262edf8a9ab5568ddc27639176312d4a366203b5f73e2d7c11fde2c554e9"},{"path":"product/stores/auths-stores/src/lifecycle.rs","sha256":"3f2cecfda13fdcd7c4a944518646bcc8abd1237f900c0332d5822281f8f9f1cd"}],"schema":"auths.gateway-semantic-closure/1"} \ No newline at end of file diff --git a/product/runtime/auths-gateway/src/bin/auths-gateway.rs b/product/runtime/auths-gateway/src/bin/auths-gateway.rs index 51300180d..b9737cde4 100644 --- a/product/runtime/auths-gateway/src/bin/auths-gateway.rs +++ b/product/runtime/auths-gateway/src/bin/auths-gateway.rs @@ -356,6 +356,22 @@ mod unix { #[arg(long, default_value_t = false)] tuple: bool, }, + /// Authenticated operator-only fresh commissioning registration. + /// Registers finite capacity once; never resets existing consumption. + CommissioningInit { + #[command(flatten)] + session: CommissioningOptions, + }, + /// Operator-only exact proof submission under finite commissioning + /// authority. Does not open or change the ordinary application socket. + CommissioningSubmit { + #[command(flatten)] + session: CommissioningOptions, + #[arg(long)] + proof: PathBuf, + #[arg(long)] + action: PathBuf, + }, /// Write a redacted archive for a support request: versions, /// digests, closed states, stable codes, and the digest and stage of /// each stored attempt. It holds no proof, action, body, credential, @@ -604,6 +620,23 @@ mod unix { qualification_trust_root: Option, } + #[derive(clap::Args)] + struct CommissioningOptions { + /// Existing production installation owned by this operator UID. + #[arg(long)] + state_dir: PathBuf, + /// Protected directory containing the permit, signer certificate and + /// root-signed revocation list. Production uses its compiled trust root. + #[arg(long)] + from: PathBuf, + /// Exact run identity, including workflow run attempt. + #[arg(long)] + protected_run: String, + /// Reviewed resource file expanded before permit issuance. + #[arg(long)] + resource_binding: PathBuf, + } + #[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize, ValueEnum)] #[serde(rename_all = "kebab-case")] enum Deployment { @@ -1450,11 +1483,49 @@ mod unix { } fn write_verifier_state(state_dir: &Path, state: &VerifierState) -> Result<(), &'static str> { + // Concurrent imports must never erase a revocation remembered by an + // earlier authenticated operator command in this same installation. + let lock = OpenOptions::new() + .read(true) + .write(true) + .create(true) + .truncate(false) + .mode(0o600) + .custom_flags(i32::from_ne_bytes( + rustix::fs::OFlags::NOFOLLOW.bits().to_ne_bytes(), + )) + .open(state_dir.join("qualification-state.lock")) + .map_err(|_| "gateway.qualification.unavailable")?; + let metadata = lock + .metadata() + .map_err(|_| "gateway.qualification.unavailable")?; + if !metadata.is_file() + || metadata.permissions().mode() & 0o077 != 0 + || metadata.uid() != rustix::process::geteuid().as_raw() + || metadata.nlink() != 1 + { + return Err("gateway.qualification.unavailable"); + } + rustix::fs::flock(&lock, rustix::fs::FlockOperation::LockExclusive) + .map_err(|_| "gateway.qualification.unavailable")?; + let mut merged = read_verifier_state(state_dir)?; + merged.accepted_revocation_sequence = merged + .accepted_revocation_sequence + .max(state.accepted_revocation_sequence); + merged.accepted_index_issued_at = merged + .accepted_index_issued_at + .max(state.accepted_index_issued_at); + merged + .revoked_signers + .extend(state.revoked_signers.iter().cloned()); + merged + .revoked_qualifications + .extend(state.revoked_qualifications.iter().cloned()); let stored = StoredVerifierState { - accepted_revocation_sequence: state.accepted_revocation_sequence, - accepted_index_issued_at: state.accepted_index_issued_at, - revoked_signers: state.revoked_signers.iter().cloned().collect(), - revoked_qualifications: state.revoked_qualifications.iter().cloned().collect(), + accepted_revocation_sequence: merged.accepted_revocation_sequence, + accepted_index_issued_at: merged.accepted_index_issued_at, + revoked_signers: merged.revoked_signers.into_iter().collect(), + revoked_qualifications: merged.revoked_qualifications.into_iter().collect(), }; let bytes = serde_json::to_vec(&stored).map_err(|_| "gateway.qualification.unavailable")?; replace_private_file(&state_dir.join(QUALIFICATION_STATE_FILE), &bytes) @@ -2487,6 +2558,75 @@ mod unix { .map_err(|error| Failure::at(code, socket, error)) } + /// Direct operator process; ordinary application handlers never call this. + async fn commissioning( + options: &CommissioningOptions, + command: Option<(&Path, &Path)>, + ) -> Result<(), Failure> { + use auths_recipe_qualification::{ + BoundedText, COMMISSIONING_PERMIT_FILE, CommissioningInputs, + MAX_COMMISSIONING_PERMIT_BYTES, + }; + private_root(&options.state_dir)?; + if installation(&options.state_dir)?.deployment != Deployment::Production { + return Err("gateway.commissioning.binding-mismatch".into()); + } + let directory = options.state_dir.clone(); + let engine = tokio::task::spawn_blocking(move || load_engine(&directory)) + .await + .map_err(|_| "gateway.commissioning.unavailable")??; + let permit = read_bounded( + &options.from.join(COMMISSIONING_PERMIT_FILE), + MAX_COMMISSIONING_PERMIT_BYTES, + )?; + let certificate = read_bounded( + &options.from.join(RELEASE_SIGNER_CERTIFICATE_FILE), + MAX_SIGNER_CERTIFICATE_BYTES, + )?; + let revocations = read_bounded( + &options.from.join(RELEASE_REVOCATION_LIST_FILE), + MAX_REVOCATION_LIST_BYTES, + )?; + let resources = read_bounded(&options.resource_binding, 64 * 1024)?; + let attestation = read_attestation(&options.state_dir.join(OPERATOR_ATTESTATION_FILE))?; + let protected_run = BoundedText::parse(&options.protected_run) + .map_err(|_| "gateway.commissioning.binding-mismatch")?; + let opened = engine.commissioning_session(&auths_gateway::CommissioningSessionInputs { + artifacts: CommissioningInputs { + signer_certificate: &certificate, + revocation_list: &revocations, + permit: &permit, + }, + operator_attestation: &attestation, + protected_run: &protected_run, + resources: &resources, + floor_directory: &options.state_dir, + }); + // Authenticated lists remain remembered even when they deny opening. + // Persist before acknowledging an import or reaching any custody lease. + write_verifier_state(&options.state_dir, &engine.qualification().verifier_state())?; + let session = opened?; + match command { + None => { + session.initialize_budget().await?; + println!( + "{{\"outcome\":\"commissioning-registered\",\"qualification\":\"required\"}}" + ); + } + Some((proof, action)) => { + let proof = read_bounded(proof, 4 * 1024 * 1024)?; + let action = read_bounded(action, 64 * 1024)?; + let result = session.submit(&proof, &action).await; + println!( + "{}", + serde_json::to_string(&result) + .map_err(|_| "gateway.submit.invalid-response")? + ); + } + } + Ok(()) + } + async fn submit(socket: PathBuf, proof: PathBuf, action: PathBuf) -> Result<(), Failure> { let proof = read_bounded(&proof, 4 * 1024 * 1024)?; let action = read_bounded(&action, 64 * 1024)?; @@ -3252,6 +3392,12 @@ mod unix { .await .map_err(|_| "gateway.qualification.unavailable")? } + Command::CommissioningInit { session } => commissioning(&session, None).await, + Command::CommissioningSubmit { + session, + proof, + action, + } => commissioning(&session, Some((&proof, &action))).await, #[cfg(feature = "loopback-provider")] Command::Serve { state_dir, @@ -3531,6 +3677,63 @@ mod unix { use super::*; use auths_gateway::listener::APP_CAPACITY; + #[test] + fn concurrent_operator_imports_keep_every_authenticated_revocation() { + let directory = tempfile::tempdir().expect("installation"); + let start = Arc::new(std::sync::Barrier::new(9)); + let workers: Vec<_> = (1..=8) + .map(|index| { + let directory = directory.path().to_owned(); + let start = start.clone(); + std::thread::spawn(move || { + let mut state = VerifierState { + accepted_revocation_sequence: index, + accepted_index_issued_at: index * 10, + ..VerifierState::default() + }; + state.revoked_signers.insert( + QualificationSignerId::parse(format!("synthetic-signer-{index}")) + .expect("signer"), + ); + start.wait(); + write_verifier_state(&directory, &state) + }) + }) + .collect(); + start.wait(); + for worker in workers { + worker.join().expect("worker").expect("persisted"); + } + write_verifier_state(directory.path(), &VerifierState::default()) + .expect("stale writer"); + let stored = read_verifier_state(directory.path()).expect("remembered"); + assert_eq!(stored.accepted_revocation_sequence, 8); + assert_eq!(stored.accepted_index_issued_at, 80); + assert_eq!(stored.revoked_signers.len(), 8); + } + + #[test] + fn application_and_admin_frames_cannot_select_a_commissioning_session() { + for field in ["commissioning", "permit", "authority", "operator_session"] { + let mut frame = serde_json::json!({"schema": APP_REQUEST_SCHEMA, + "proof_b64": "AA", "action_b64": "AA"}); + frame[field] = serde_json::json!("synthetic-untrusted-authority"); + assert!( + serde_json::from_value::(frame).is_err(), + "{field}" + ); + } + assert!( + parse_admin_request( + &serde_json::to_vec(&serde_json::json!({ + "schema": ADMIN_REQUEST_SCHEMA, "command": "commissioning-submit" + })) + .expect("frame") + ) + .is_err() + ); + } + fn serve_capacity(arguments: &[&str]) -> Result { let mut command = vec![ "auths-gateway", diff --git a/product/runtime/auths-gateway/src/bounds.rs b/product/runtime/auths-gateway/src/bounds.rs index 524eaf0ba..2f4a4feba 100644 --- a/product/runtime/auths-gateway/src/bounds.rs +++ b/product/runtime/auths-gateway/src/bounds.rs @@ -927,6 +927,9 @@ pub(crate) fn authorized_chains( /// What admission needs of the authorized branches. pub(crate) struct BranchFacts { + /// Distinct actors of the exact action IDs sealed by native verification. + #[cfg(unix)] + pub(crate) actors: Vec, /// Every observation requirement of every grant of every branch. pub(crate) requirements: Vec, /// The longest action validity window of any branch. @@ -956,6 +959,13 @@ pub(crate) fn authorized_branches( } } Ok(BranchFacts { + #[cfg(unix)] + actors: branches + .iter() + .map(|branch| branch.actor.clone()) + .collect::>() + .into_iter() + .collect(), approvers: counted_approvers(proof_cbor, verified)?, requirements, validity_seconds: branches diff --git a/product/runtime/auths-gateway/src/commissioning_budget.rs b/product/runtime/auths-gateway/src/commissioning_budget.rs index 8ce88bdd8..c36ae65a9 100644 --- a/product/runtime/auths-gateway/src/commissioning_budget.rs +++ b/product/runtime/auths-gateway/src/commissioning_budget.rs @@ -126,6 +126,9 @@ impl CommissioningBudgetSnapshot { bytes: &[u8], binding: &CommissioningBinding, ) -> Result { + binding + .validate() + .map_err(|_| CommissioningBudgetRefusal::BindingMismatch)?; if bytes.is_empty() || bytes.len() > MAX_COMMISSIONING_BUDGET_BYTES { return Err(CommissioningBudgetRefusal::Corrupt); } @@ -174,7 +177,7 @@ impl CommissioningBudgetSnapshot { Ok(()) } - fn not_below(&self, floor: &Self) -> bool { + pub(crate) fn not_below(&self, floor: &Self) -> bool { self.record.budget_scope_sha256 == floor.record.budget_scope_sha256 && self.record.budget_binding_sha256 == floor.record.budget_binding_sha256 && self.record.maximum_credential_leases == floor.record.maximum_credential_leases @@ -212,7 +215,7 @@ impl CommissioningBudgetUpdate { } /// Capacity for one exact commissioning binding on an existing atomic store. -/// The production operator path must supply its production PostgreSQL backend; +/// The production operator path must supply its production `PostgreSQL` backend; /// development stores may exercise this mechanism without granting authority. pub struct CommissioningBudget { store: Arc, @@ -344,12 +347,12 @@ impl CommissioningBudget { authority.remember(&mut remembered); let mut next = current.record.clone(); next.accepted_revocation_sequence = remembered.accepted_revocation_sequence; - next.revoked_signers = remembered.revoked_signers.clone(); + next.revoked_signers.clone_from(&remembered.revoked_signers); let refusal = authority .evaluate(request, now, clock_trusted, &remembered) .err() .map(CommissioningBudgetRefusal::Permit) - .or_else(|| { + .or({ if now < current.record.latest_verifier_time { Some(CommissioningBudgetRefusal::Rollback) } else if current.record.consumed_credential_leases diff --git a/product/runtime/auths-gateway/src/commissioning_floor.rs b/product/runtime/auths-gateway/src/commissioning_floor.rs new file mode 100644 index 000000000..460931865 --- /dev/null +++ b/product/runtime/auths-gateway/src/commissioning_floor.rs @@ -0,0 +1,222 @@ +//! Host-retained commissioning witness, outside the database restore set. +//! +//! A host lock spans reading the prior floor, claiming shared capacity and +//! durably replacing the witness. No successful claim is returned until the +//! witness and its directory have been synchronized. A crash or failed write +//! can burn a unit; it cannot refund one. Runtime never initializes a floor. + +use crate::commissioning_budget::{ + CommissioningBudget, CommissioningBudgetRefusal, CommissioningBudgetSnapshot, + CommissioningBudgetUpdate, MAX_COMMISSIONING_BUDGET_BYTES, +}; +use auths_recipe_qualification::{ + CommissioningBinding, CommissioningRequest, VerifiedCommissioningPermit, VerifierState, +}; +#[cfg(unix)] +use std::os::unix::fs::{MetadataExt as _, OpenOptionsExt as _, PermissionsExt as _}; +use std::{ + fs::{self, File, OpenOptions}, + io::{Read as _, Write as _}, + path::PathBuf, +}; + +/// One host's monotone witness for an exact commissioning run/family. +/// The authenticated operator supplies an already-private installation +/// directory, retained independently of database backups. This object grants +/// no application access or credential authority. +#[derive(Clone)] +pub struct CommissioningFloor { + directory: PathBuf, + binding: CommissioningBinding, + leaf: String, +} + +impl CommissioningFloor { + /// Names the floor using the renewal-stable run/family budget key. + /// + /// # Errors + /// Refuses invalid bindings. Does not create files or database state. + pub fn new( + directory: PathBuf, + binding: CommissioningBinding, + ) -> Result { + binding + .validate() + .map_err(|_| CommissioningBudgetRefusal::BindingMismatch)?; + let leaf = format!( + "commissioning-{}", + binding + .budget_key() + .map_err(|_| CommissioningBudgetRefusal::BindingMismatch)? + .to_hex() + ); + Ok(Self { + directory, + binding, + leaf, + }) + } + + /// Fresh authenticated setup retains the registered database snapshot. + /// An existing witness is never reset or overwritten by older state. + /// + /// # Errors + /// Refuses inaccessible, unsafe, corrupt, substituted or decreasing state. + /// Runtime startup and permit renewal must never use this initializer. + #[cfg(unix)] + pub fn initialize( + &self, + registered: &CommissioningBudgetSnapshot, + ) -> Result<(), CommissioningBudgetRefusal> { + let _lock = self.lock()?; + CommissioningBudgetSnapshot::from_canonical_json( + registered.canonical_bytes(), + &self.binding, + )?; + match self.read() { + Ok(previous) if !registered.not_below(&previous) => { + return Err(CommissioningBudgetRefusal::Rollback); + } + Ok(_) | Err(CommissioningBudgetRefusal::Missing) => {} + Err(error) => return Err(error), + } + self.persist(registered) + } + + /// Loads an existing host witness under its private lock. + /// + /// # Errors + /// Missing or unsafe witnesses refuse; no state is recreated. + #[cfg(unix)] + pub fn load(&self) -> Result { + let _lock = self.lock()?; + self.read() + } + + /// Claims shared capacity and durably retains the result before returning. + /// The private operator session must inspect `refusal` before custody. + /// Denial still remembers authenticated revocations. The host lock makes + /// concurrent submissions unable to overwrite a newer local witness. + /// + /// # Errors + /// Returns a typed refusal without authorizing custody. A failed witness + /// write after the database commit leaves its unit consumed permanently. + #[cfg(unix)] + pub fn claim( + &self, + budget: &CommissioningBudget, + authority: &VerifiedCommissioningPermit, + request: &CommissioningRequest<'_>, + now: u64, + clock_trusted: bool, + state: &VerifierState, + ) -> Result { + let _lock = self.lock()?; + let previous = self.read().map_err(|error| match error { + CommissioningBudgetRefusal::Missing => CommissioningBudgetRefusal::Rollback, + other => other, + })?; + let update = budget.claim(authority, request, now, clock_trusted, &previous, state)?; + self.persist(update.snapshot())?; + Ok(update) + } + + #[cfg(unix)] + fn lock(&self) -> Result { + let directory = fs::symlink_metadata(&self.directory) + .map_err(|_| CommissioningBudgetRefusal::Rollback)?; + if !directory.is_dir() + || directory.permissions().mode() & 0o077 != 0 + || directory.uid() != rustix::process::geteuid().as_raw() + { + return Err(CommissioningBudgetRefusal::Rollback); + } + let file = OpenOptions::new() + .read(true) + .write(true) + .create(true) + .truncate(false) + .mode(0o600) + .custom_flags(nofollow()) + .open(self.directory.join(format!("{}.lock", self.leaf))) + .map_err(|_| CommissioningBudgetRefusal::Rollback)?; + let metadata = file + .metadata() + .map_err(|_| CommissioningBudgetRefusal::Rollback)?; + if !safe_file(&metadata) { + return Err(CommissioningBudgetRefusal::Rollback); + } + rustix::fs::flock(&file, rustix::fs::FlockOperation::LockExclusive) + .map_err(|_| CommissioningBudgetRefusal::Rollback)?; + Ok(file) + } + + #[cfg(unix)] + fn read(&self) -> Result { + let file = OpenOptions::new() + .read(true) + .custom_flags(nofollow()) + .open(self.directory.join(format!("{}.json", self.leaf))) + .map_err(|error| { + if error.kind() == std::io::ErrorKind::NotFound { + CommissioningBudgetRefusal::Missing + } else { + CommissioningBudgetRefusal::Rollback + } + })?; + let metadata = file + .metadata() + .map_err(|_| CommissioningBudgetRefusal::Rollback)?; + if !safe_file(&metadata) || metadata.len() > MAX_COMMISSIONING_BUDGET_BYTES as u64 { + return Err(CommissioningBudgetRefusal::Rollback); + } + let mut bytes = Vec::new(); + file.take(MAX_COMMISSIONING_BUDGET_BYTES as u64 + 1) + .read_to_end(&mut bytes) + .map_err(|_| CommissioningBudgetRefusal::Rollback)?; + CommissioningBudgetSnapshot::from_canonical_json(&bytes, &self.binding) + } + + #[cfg(unix)] + fn persist( + &self, + snapshot: &CommissioningBudgetSnapshot, + ) -> Result<(), CommissioningBudgetRefusal> { + let mut pending = tempfile::NamedTempFile::new_in(&self.directory) + .map_err(|_| CommissioningBudgetRefusal::Rollback)?; + pending + .as_file() + .set_permissions(fs::Permissions::from_mode(0o600)) + .map_err(|_| CommissioningBudgetRefusal::Rollback)?; + pending + .write_all(snapshot.canonical_bytes()) + .and_then(|()| pending.as_file().sync_all()) + .map_err(|_| CommissioningBudgetRefusal::Rollback)?; + pending + .persist(self.directory.join(format!("{}.json", self.leaf))) + .map_err(|_| CommissioningBudgetRefusal::Rollback)?; + File::open(&self.directory) + .and_then(|directory| directory.sync_all()) + .map_err(|_| CommissioningBudgetRefusal::Rollback) + } +} + +#[cfg(unix)] +fn nofollow() -> i32 { + i32::from_ne_bytes(rustix::fs::OFlags::NOFOLLOW.bits().to_ne_bytes()) +} + +#[cfg(unix)] +#[allow( + clippy::verbose_bit_mask, + reason = "octal permission bits name the exact forbidden Unix access" +)] +fn safe_file(metadata: &fs::Metadata) -> bool { + metadata.is_file() + && metadata.permissions().mode() & 0o077 == 0 + && metadata.uid() == rustix::process::geteuid().as_raw() + && metadata.nlink() == 1 +} + +#[cfg(all(test, unix))] +mod tests; diff --git a/product/runtime/auths-gateway/src/commissioning_floor/tests.rs b/product/runtime/auths-gateway/src/commissioning_floor/tests.rs new file mode 100644 index 000000000..bcbb77d6a --- /dev/null +++ b/product/runtime/auths-gateway/src/commissioning_floor/tests.rs @@ -0,0 +1,264 @@ +use super::*; +use crate::store_testkit::{Backend, TestAttempts}; +use auths_recipe_qualification::{CommissioningInputs, QualificationTrustRoot}; +use std::sync::{Arc, Barrier}; + +fn fixture() -> VerifiedCommissioningPermit { + let document: serde_json::Value = serde_json::from_slice(include_bytes!( + "../../../../../bindings/fixtures/qualification/commissioning-v1.json" + )) + .expect("public synthetic fixture"); + let text = |name: &str| document[name].as_str().expect("artifact").as_bytes(); + VerifiedCommissioningPermit::verify( + &QualificationTrustRoot::from_canonical_json(text("trust_root")).expect("root"), + &CommissioningInputs { + signer_certificate: text("signer_certificate"), + revocation_list: text("revocation_list"), + permit: text("permit"), + }, + ) + .expect("synthetic authority") +} + +fn request(binding: &CommissioningBinding) -> CommissioningRequest<'_> { + CommissioningRequest { + source_commit: &binding.source_commit, + tuple: &binding.tuple, + protected_run: &binding.protected_run, + principal_sha256: binding.principal_sha256, + trusted_context_sha256: binding.trusted_context_sha256, + resources_sha256: binding.resources_sha256, + canonical_action_sha256: binding.allowed_actions[0], + } +} + +fn setup() -> ( + TestAttempts, + tempfile::TempDir, + VerifiedCommissioningPermit, + CommissioningBudget, + CommissioningFloor, +) { + let store = TestAttempts::open(Backend::File); + let directory = tempfile::tempdir().expect("host floor"); + fs::set_permissions(directory.path(), fs::Permissions::from_mode(0o700)).expect("private"); + let authority = fixture(); + let binding = authority.permit().body().statement.binding.clone(); + let budget = CommissioningBudget::new(store.raw(), binding.clone()).expect("budget"); + let floor = CommissioningFloor::new(directory.path().to_owned(), binding).expect("floor"); + (store, directory, authority, budget, floor) +} + +fn claim( + floor: &CommissioningFloor, + budget: &CommissioningBudget, + authority: &VerifiedCommissioningPermit, +) -> Result { + let statement = &authority.permit().body().statement; + floor.claim( + budget, + authority, + &request(&statement.binding), + statement.not_before, + true, + &VerifierState::default(), + ) +} + +#[test] +fn runtime_never_creates_a_missing_floor() { + let (_store, _directory, authority, budget, floor) = setup(); + budget.initialize().expect("registered"); + assert_eq!( + claim(&floor, &budget, &authority), + Err(CommissioningBudgetRefusal::Rollback) + ); + assert_eq!( + budget + .load() + .expect("database") + .consumed_credential_leases(), + 0 + ); + assert_eq!(floor.load(), Err(CommissioningBudgetRefusal::Missing)); +} + +#[test] +fn committed_floor_survives_restart_and_cannot_be_reset() { + let (_store, directory, authority, budget, floor) = setup(); + let initial = budget.initialize().expect("registered"); + floor.initialize(&initial).expect("fresh floor"); + assert_eq!( + claim(&floor, &budget, &authority).expect("claim").refusal(), + None + ); + let reopened = CommissioningFloor::new( + directory.path().to_owned(), + authority.permit().body().statement.binding.clone(), + ) + .expect("reopen"); + assert_eq!( + reopened + .load() + .expect("retained") + .consumed_credential_leases(), + 1 + ); + assert_eq!( + reopened.initialize(&initial), + Err(CommissioningBudgetRefusal::Rollback) + ); + assert_eq!( + claim(&reopened, &budget, &authority) + .expect("second") + .refusal(), + None + ); + assert_eq!( + reopened.load().expect("floor").consumed_credential_leases(), + 2 + ); +} + +#[test] +fn concurrent_local_claims_never_decrease_the_witness() { + let (_store, _directory, authority, budget, floor) = setup(); + floor + .initialize(&budget.initialize().expect("registration")) + .expect("floor"); + let budget = Arc::new(budget); + let start = Arc::new(Barrier::new(9)); + let workers: Vec<_> = (0..8) + .map(|_| { + let budget = budget.clone(); + let floor = floor.clone(); + let authority = authority.clone(); + let start = start.clone(); + std::thread::spawn(move || { + start.wait(); + claim(&floor, &budget, &authority) + }) + }) + .collect(); + start.wait(); + for worker in workers { + assert_eq!( + worker.join().expect("worker").expect("persisted").refusal(), + None + ); + } + assert_eq!(floor.load().expect("floor").consumed_credential_leases(), 8); + assert_eq!( + budget + .load() + .expect("database") + .consumed_credential_leases(), + 8 + ); +} + +#[test] +fn unsafe_witness_paths_refuse_before_capacity_claim() { + for fault in ["symlink", "hardlink", "public", "oversized", "malformed"] { + let (_store, directory, authority, budget, floor) = setup(); + floor + .initialize(&budget.initialize().expect("registration")) + .expect("floor"); + let path = directory.path().join(format!("{}.json", floor.leaf)); + match fault { + "symlink" => { + let target = directory.path().join("retained.json"); + fs::rename(&path, &target).expect("move"); + std::os::unix::fs::symlink(target, &path).expect("symlink"); + } + "hardlink" => { + fs::hard_link(&path, directory.path().join("alias.json")).expect("link"); + } + "public" => { + fs::set_permissions(&path, fs::Permissions::from_mode(0o644)).expect("mode"); + } + "oversized" => { + fs::write(&path, vec![b' '; MAX_COMMISSIONING_BUDGET_BYTES + 1]).expect("write"); + } + "malformed" => { + fs::write(&path, b"{}").expect("write"); + } + _ => unreachable!(), + } + assert!(claim(&floor, &budget, &authority).is_err(), "{fault}"); + assert_eq!( + budget + .load() + .expect("database") + .consumed_credential_leases(), + 0 + ); + } +} + +#[test] +fn database_restore_below_retained_witness_is_refused() { + let (store, _directory, authority, budget, floor) = setup(); + let initial = budget.initialize().expect("registration"); + floor.initialize(&initial).expect("floor"); + claim(&floor, &budget, &authority).expect("first claim"); + let latest = budget.load().expect("database"); + let key = crate::GatewayAttemptKey::from_bytes( + *authority + .permit() + .body() + .statement + .binding + .budget_key() + .expect("key") + .as_bytes(), + ); + store + .raw() + .replace( + crate::GatewayRecordKind::CommissioningBudget, + &key, + latest.canonical_bytes(), + initial.canonical_bytes(), + ) + .expect("simulate restore"); + assert_eq!( + claim(&floor, &budget, &authority), + Err(CommissioningBudgetRefusal::Rollback) + ); + assert_eq!( + floor.load().expect("retained").consumed_credential_leases(), + 1 + ); +} + +#[test] +fn database_claim_without_witness_acknowledgement_stays_spent() { + let (_store, _directory, authority, budget, floor) = setup(); + let initial = budget.initialize().expect("registration"); + floor.initialize(&initial).expect("floor"); + // Process loss after the shared commit and before the host witness write. + let statement = &authority.permit().body().statement; + budget + .claim( + &authority, + &request(&statement.binding), + statement.not_before, + true, + &initial, + &VerifierState::default(), + ) + .expect("database commit"); + assert_eq!( + floor + .load() + .expect("old witness") + .consumed_credential_leases(), + 0 + ); + claim(&floor, &budget, &authority).expect("restart claim"); + assert_eq!( + floor.load().expect("retained").consumed_credential_leases(), + 2 + ); +} diff --git a/product/runtime/auths-gateway/src/commissioning_session.rs b/product/runtime/auths-gateway/src/commissioning_session.rs new file mode 100644 index 000000000..9e0d02aa7 --- /dev/null +++ b/product/runtime/auths-gateway/src/commissioning_session.rs @@ -0,0 +1,296 @@ +//! Authenticated operator-only commissioning of the exact shipped driver. +//! Ordinary `GatewayEngine::submit` never constructs or selects this session. + +use super::{EngineIo, GatewayEngine, GatewaySubmitResult, VerifiedCommand}; +use crate::commissioning_budget::{CommissioningBudget, CommissioningBudgetRefusal}; +use crate::commissioning_floor::CommissioningFloor; +use crate::submit::{self, SubmitContext}; +use auths_model::PrincipalId; +use auths_recipe_qualification::{ + BoundedText, CommissioningInputs, CommissioningRefusal, CommissioningRequest, + LifecycleStoreKind, QualificationTuple, Sha256Digest, VerifiedCommissioningPermit, +}; +use sha2::{Digest as _, Sha256}; +use std::{ + path::Path, + sync::{Arc, OnceLock}, + time::Instant, +}; + +/// Independent operator inputs. The installed root, target and clock come +/// from the engine's required qualification gate, never from these inputs. +pub struct CommissioningSessionInputs<'a> { + /// Closed permit, purpose certificate and authenticated revocation list. + pub artifacts: CommissioningInputs<'a>, + /// Signed operator attestation for this exact production installation. + pub operator_attestation: &'a [u8], + /// Run/attempt identity established by the protected operator workflow. + pub protected_run: &'a BoundedText<256>, + /// Exact reviewed resource file, SHA-256 bound by the permit; at most 64 KiB. + pub resources: &'a [u8], + /// Private host directory retained outside database restores. + pub floor_directory: &'a Path, +} + +/// SHA-256 of the normalized principal identifier's UTF-8 bytes. +/// Only actors sealed by native verification are compared at runtime. +#[must_use] +pub fn commissioning_principal_sha256(principal: &PrincipalId) -> Sha256Digest { + Sha256Digest::from_bytes(Sha256::digest(principal.as_str().as_bytes()).into()) +} + +/// A sealed operator capability tied to one engine and reviewed protected run. +/// It grants no qualification verdict, readiness state or ordinary app access. +/// Every submission uses native proof verification and the same ordered driver. +pub struct CommissioningSession<'a> { + engine: &'a GatewayEngine, + authority: VerifiedCommissioningPermit, + tuple: QualificationTuple, + protected_run: BoundedText<256>, + resources_sha256: Sha256Digest, + budget: Arc, + floor: CommissioningFloor, +} + +/// Obtained only from exact authorized branches and the closed verified request. +pub(super) struct CommissionedAction { + principal_sha256: Sha256Digest, + canonical_action_sha256: Sha256Digest, +} + +impl GatewayEngine { + /// Authenticates a private commissioning session against installed trust. + /// This does not initialize capacity or alter the ordinary application gate. + /// The caller must be the isolated operator process, not an application. + /// + /// # Errors + /// Refuses missing production identity, invalid operator/permit signatures, + /// time/revocation faults and every changed installed/run/resource binding. + pub fn commissioning_session( + &self, + inputs: &CommissioningSessionInputs<'_>, + ) -> Result, &'static str> { + let (root, tuple) = self + .qualification + .commissioning_target() + .ok_or("gateway.commissioning.unavailable")?; + if tuple.target.store_kind != LifecycleStoreKind::PostgresqlV1 + || tuple.target.store_schema.as_str() != crate::POSTGRES_STORE_SCHEMA + || !tuple.target.credential_store_kind.is_production() + || tuple.compiled_recipe_sha256.as_bytes() != self.recipe.digest() + || inputs.resources.is_empty() + || inputs.resources.len() > 64 * 1024 + { + return Err("gateway.commissioning.binding-mismatch"); + } + let (now, trusted) = self.qualification.commissioning_time(); + if !trusted { + return Err("gateway.commissioning.clock-untrusted"); + } + let expected = crate::OperatorInstallation { + recipe_digest: self.recipe.digest_hex(), + profile_lock_sha256: tuple.profile_lock_sha256.to_hex(), + trusted_context_sha256: self.trusted_context_sha256.to_hex(), + provider: self.connection.provider().as_str().to_owned(), + alias: self.connection.alias().as_str().to_owned(), + deployment: "production".to_owned(), + }; + let operator = + crate::verify_operator_attestation(inputs.operator_attestation, &expected, now) + .map_err(crate::OperatorAttestationError::code)?; + self.check_principal_separation(Some(&operator)) + .map_err(crate::PrincipalSeparationError::code)?; + let authority = VerifiedCommissioningPermit::verify(root, &inputs.artifacts) + .map_err(|_| "gateway.commissioning.unavailable")?; + self.qualification.remember_commissioning(&authority); + let binding = &authority.permit().body().statement.binding; + let resources_sha256 = Sha256Digest::from_bytes(Sha256::digest(inputs.resources).into()); + // The signature binds the candidate source revision to the executable + // digest independently derived by the installation's tuple. There is no + // caller-supplied source-commit override or runtime build-mode switch. + let request = CommissioningRequest { + source_commit: &binding.source_commit, + tuple, + protected_run: inputs.protected_run, + principal_sha256: binding.principal_sha256, + trusted_context_sha256: self.trusted_context_sha256, + resources_sha256, + canonical_action_sha256: binding.allowed_actions[0], + }; + authority + .evaluate(&request, now, trusted, &self.qualification.verifier_state()) + .map_err(permit_code)?; + let budget = Arc::new( + CommissioningBudget::new(self.attempts.store(), binding.clone()) + .map_err(CommissioningBudgetRefusal::code)?, + ); + let floor = CommissioningFloor::new(inputs.floor_directory.to_owned(), binding.clone()) + .map_err(CommissioningBudgetRefusal::code)?; + Ok(CommissioningSession { + engine: self, + tuple: tuple.clone(), + protected_run: inputs.protected_run.clone(), + resources_sha256, + authority, + budget, + floor, + }) + } +} + +impl CommissioningSession<'_> { + /// Fresh authenticated setup registers shared capacity once and retains its + /// floor before returning. Existing consumption/trust is never reset. + /// Startup and renewal use `submit`, which never initializes missing state. + /// + /// # Errors + /// Refuses unavailable, changed, rolled-back or unsafe permanent state. + pub async fn initialize_budget(&self) -> Result<(), &'static str> { + let budget = self.budget.clone(); + let floor = self.floor.clone(); + let authority = self.authority.clone(); + let state = self.engine.qualification.verifier_state(); + let tuple = self.tuple.clone(); + let protected_run = self.protected_run.clone(); + let resources_sha256 = self.resources_sha256; + let trusted_context_sha256 = self.engine.trusted_context_sha256; + let (now, _) = self.engine.qualification.commissioning_time(); + tokio::task::spawn_blocking(move || { + floor.initialize(&budget.initialize()?)?; + let binding = &authority.permit().body().statement.binding; + let request = CommissioningRequest { + source_commit: &binding.source_commit, + tuple: &tuple, + protected_run: &protected_run, + principal_sha256: binding.principal_sha256, + trusted_context_sha256, + resources_sha256, + canonical_action_sha256: binding.allowed_actions[0], + }; + // Setup records authenticated trust without permitting a lease. + // Deliberately withholding clock trust makes this a denied update + // with zero consumption; the shared record and retained floor + // nevertheless remember the root-signed list before acknowledgement. + floor.claim(&budget, &authority, &request, now, false, &state)?; + Ok(()) + }) + .await + .map_err(|_| "gateway.commissioning.store-unavailable")? + .map_err(CommissioningBudgetRefusal::code) + } + + /// Submits proof and canonical action as the authenticated operator. + /// No proof/request can select this method through an ordinary app socket. + /// The exact actor and action must match the finite signed permit; before + /// every custody acquisition an atomic lifetime unit and host floor commit. + pub async fn submit(&self, proof: &[u8], action: &[u8]) -> GatewaySubmitResult { + let io = EngineIo { + engine: self.engine, + proof, + action, + started: Instant::now(), + prepared: OnceLock::new(), + commissioning: Some(self), + commissioned_action: OnceLock::new(), + commissioning_refusal: OnceLock::new(), + }; + submit::run( + &SubmitContext { + recipe: &self.engine.recipe, + attempts: &self.engine.attempts, + context: &self.engine.trusted_context, + observer: self.engine.observer.as_ref(), + }, + &io, + ) + .await + } + + pub(super) fn bind_verified( + &self, + command: &VerifiedCommand, + ) -> Result { + let [actor] = command.actors.as_slice() else { + return Err("gateway.commissioning.binding-mismatch"); + }; + let action = CommissionedAction { + principal_sha256: commissioning_principal_sha256(actor), + canonical_action_sha256: Sha256Digest::from_bytes(*command.request.action_commitment()), + }; + self.check(&action)?; + Ok(action) + } + + pub(super) fn check(&self, action: &CommissionedAction) -> Result<(), &'static str> { + let (now, trusted) = self.engine.qualification.commissioning_time(); + self.authority + .evaluate( + &self.request(action), + now, + trusted, + &self.engine.qualification.verifier_state(), + ) + .map_err(permit_code) + } + + fn request<'a>(&'a self, action: &CommissionedAction) -> CommissioningRequest<'a> { + CommissioningRequest { + source_commit: &self + .authority + .permit() + .body() + .statement + .binding + .source_commit, + tuple: &self.tuple, + protected_run: &self.protected_run, + principal_sha256: action.principal_sha256, + trusted_context_sha256: self.engine.trusted_context_sha256, + resources_sha256: self.resources_sha256, + canonical_action_sha256: action.canonical_action_sha256, + } + } + + pub(super) async fn claim(&self, action: &CommissionedAction) -> Result<(), &'static str> { + let budget = self.budget.clone(); + let floor = self.floor.clone(); + let authority = self.authority.clone(); + let tuple = self.tuple.clone(); + let protected_run = self.protected_run.clone(); + let principal_sha256 = action.principal_sha256; + let canonical_action_sha256 = action.canonical_action_sha256; + let trusted_context_sha256 = self.engine.trusted_context_sha256; + let resources_sha256 = self.resources_sha256; + let state = self.engine.qualification.verifier_state(); + let (now, trusted) = self.engine.qualification.commissioning_time(); + let update = tokio::task::spawn_blocking(move || { + let request = CommissioningRequest { + source_commit: &authority.permit().body().statement.binding.source_commit, + tuple: &tuple, + protected_run: &protected_run, + principal_sha256, + trusted_context_sha256, + resources_sha256, + canonical_action_sha256, + }; + floor.claim(&budget, &authority, &request, now, trusted, &state) + }) + .await + .map_err(|_| "gateway.commissioning.store-unavailable")? + .map_err(CommissioningBudgetRefusal::code)?; + match update.refusal() { + Some(refusal) => Err(refusal.code()), + // A queued host lock or durable store write can outlast the permit + // window. Capacity stays spent, but custody requires fresh time. + None => self.check(action), + } + } +} + +fn permit_code(refusal: CommissioningRefusal) -> &'static str { + CommissioningBudgetRefusal::Permit(refusal).code() +} + +#[cfg(test)] +#[path = "commissioning_session/tests.rs"] +mod tests; diff --git a/product/runtime/auths-gateway/src/commissioning_session/tests.rs b/product/runtime/auths-gateway/src/commissioning_session/tests.rs new file mode 100644 index 000000000..afe51afa8 --- /dev/null +++ b/product/runtime/auths-gateway/src/commissioning_session/tests.rs @@ -0,0 +1,342 @@ +//! Synthetic authority over the installed engine I/O boundary, with real +//! native quorum proof verification and counted custody. No provider I/O, +//! production deployment or protected qualification is claimed here. + +use super::*; +use crate::engine::tests::administration::{Installation, installation}; +use crate::harness::Signer; +use crate::submit::SubmitIo as _; +use crate::{ + FixedClock, OperatorAttestation, OperatorEvidence, OperatorStatement, QualificationGate, + QualificationPolicy, +}; +use auths_recipe_qualification::{ + QualificationCommissioningPermit, QualificationTrustRoot, SignatureB64, VerifierState, +}; +use base64ct::{Base64UrlUnpadded, Encoding as _}; +use ed25519_dalek::{Signer as _, SigningKey}; +use serde_json::Value; +use std::{os::unix::fs::PermissionsExt as _, sync::atomic::Ordering}; + +const NOW: u64 = 1_790_000_000; + +struct Setup { + installation: Installation, + directory: tempfile::TempDir, + clock: Arc, + permit: QualificationCommissioningPermit, + certificate: Vec, + revocations: Vec, + attestation: Vec, + resources: Vec, + proof: Vec, + action: Vec, +} + +impl Setup { + #[allow( + clippy::too_many_lines, + reason = "one explicit fixture binds native proof, operator signature and permit to the same installed engine" + )] + async fn new() -> Self { + let mut installation = installation(8).await; + let document: Value = serde_json::from_slice(include_bytes!( + "../../../../../bindings/fixtures/gateway/approval-quorum.json" + )) + .expect("quorum fixture"); + let decode = |value: &Value| { + Base64UrlUnpadded::decode_vec(value.as_str().expect("base64")).expect("fixture bytes") + }; + let trust = decode(&document["trusted_context_b64"]); + let proof = decode(&document["cases"][0]["proof_b64"]); + let action = decode(&document["cases"][0]["action_b64"]); + let engine = &mut installation.first.engine; + engine.trusted_context = auths_codec::decode_verifier_context(&trust).expect("trust"); + engine.trusted_context_sha256 = Sha256Digest::from_bytes(Sha256::digest(&trust).into()); + let verified = super::super::verify_detailed( + &engine.recipe, + &engine.trusted_context, + NOW, + &proof, + &action, + ) + .expect("native fixture authorization"); + assert_eq!(verified.actors.len(), 1); + let artifacts: Value = serde_json::from_slice(include_bytes!( + "../../../../../bindings/fixtures/qualification/commissioning-v1.json" + )) + .expect("authority fixture"); + let text = |name: &str| artifacts[name].as_str().expect("artifact").as_bytes(); + let original = + QualificationCommissioningPermit::from_canonical_json(text("permit")).expect("permit"); + let mut body = original.body().clone(); + let resources = br#"{"schema":"synthetic-resources/1"}"#.to_vec(); + body.statement.binding.tuple.compiled_recipe_sha256 = + Sha256Digest::from_bytes(*engine.recipe.digest()); + body.statement.binding.tuple.target.store_schema = + BoundedText::parse(crate::POSTGRES_STORE_SCHEMA).expect("schema"); + body.statement.binding.trusted_context_sha256 = engine.trusted_context_sha256; + body.statement.binding.principal_sha256 = + commissioning_principal_sha256(&verified.actors[0]); + body.statement.binding.resources_sha256 = + Sha256Digest::from_bytes(Sha256::digest(&resources).into()); + body.statement.binding.allowed_actions = vec![Sha256Digest::from_bytes( + *verified.request.action_commitment(), + )]; + body.statement.binding.maximum_credential_leases = 1; + let permit = signed(body); + let clock = Arc::new(FixedClock::at(NOW)); + let root = QualificationTrustRoot::from_canonical_json(text("trust_root")).expect("root"); + engine.qualification = Arc::new(QualificationGate::new( + QualificationPolicy::Required, + Some(root), + Some(permit.body().statement.binding.tuple.clone()), + Box::new(clock.clone()), + VerifierState::default(), + )); + let operator = Signer::new(0x44); + let statement = OperatorStatement { + schema: crate::OPERATOR_ATTESTATION_SCHEMA.to_owned(), + operator_principal: operator.principal.as_str().to_owned(), + principal_method: "raw-key-v1".to_owned(), + verification_method: operator.principal.as_str().to_owned(), + signature_suite: "ed25519-v1".to_owned(), + installation: crate::OperatorInstallation { + recipe_digest: engine.recipe.digest_hex(), + profile_lock_sha256: permit + .body() + .statement + .binding + .tuple + .profile_lock_sha256 + .to_hex(), + trusted_context_sha256: engine.trusted_context_sha256.to_hex(), + provider: engine.connection.provider().as_str().to_owned(), + alias: engine.connection.alias().as_str().to_owned(), + deployment: "production".to_owned(), + }, + issued_at: NOW, + }; + let evidence = operator.evidence(); + let attestation = OperatorAttestation { + signature_b64: Base64UrlUnpadded::encode_string( + operator + .sign(&statement.preimage().expect("operator preimage")) + .as_slice(), + ), + statement, + evidence: vec![OperatorEvidence { + evidence_type: evidence.evidence_type().as_str().to_owned(), + media_type: evidence.media_type().as_str().to_owned(), + bytes_b64: Base64UrlUnpadded::encode_string(evidence.bytes()), + }], + }; + let directory = tempfile::tempdir().expect("retained witness"); + std::fs::set_permissions(directory.path(), std::fs::Permissions::from_mode(0o700)) + .expect("private"); + Self { + installation, + directory, + clock, + permit, + certificate: text("signer_certificate").to_vec(), + revocations: text("revocation_list").to_vec(), + attestation: serde_json::to_vec(&attestation).expect("operator bytes"), + resources, + proof, + action, + } + } + + fn inputs(&self) -> CommissioningSessionInputs<'_> { + CommissioningSessionInputs { + artifacts: CommissioningInputs { + signer_certificate: &self.certificate, + revocation_list: &self.revocations, + permit: self.permit.canonical_bytes(), + }, + operator_attestation: &self.attestation, + protected_run: &self.permit.body().statement.binding.protected_run, + resources: &self.resources, + floor_directory: self.directory.path(), + } + } + + fn engine(&self) -> &GatewayEngine { + &self.installation.first.engine + } + fn leases(&self) -> u64 { + self.installation.first.leases.load(Ordering::SeqCst) + } +} + +fn signed( + mut body: auths_recipe_qualification::CommissioningPermitBody, +) -> QualificationCommissioningPermit { + // Public deterministic test key from the frozen commissioning corpus. + body.signature_b64 = SignatureB64::from_bytes( + &SigningKey::from_bytes(&[0x22; 32]) + .sign(&body.signing_preimage().expect("preimage")) + .to_bytes(), + ); + QualificationCommissioningPermit::from_body(&body).expect("signed synthetic permit") +} + +fn io<'a>(setup: &'a Setup, session: Option<&'a CommissioningSession<'a>>) -> EngineIo<'a> { + EngineIo { + engine: setup.engine(), + proof: &setup.proof, + action: &setup.action, + started: Instant::now(), + prepared: OnceLock::new(), + commissioning: session, + commissioned_action: OnceLock::new(), + commissioning_refusal: OnceLock::new(), + } +} + +#[tokio::test] +async fn ordinary_submission_cannot_select_commissioning_authority() { + let setup = Setup::new().await; + let session = setup + .engine() + .commissioning_session(&setup.inputs()) + .expect("operator"); + session.initialize_budget().await.expect("registered"); + let ordinary = io(&setup, None); + ordinary.verify(NOW).expect("native proof"); + assert_eq!( + ordinary.prepare().await, + Err("gateway.qualification.unavailable") + ); + assert!(ordinary.lease().await.is_none()); + assert_eq!(setup.leases(), 0); + assert_eq!( + session + .floor + .load() + .expect("floor") + .consumed_credential_leases(), + 0 + ); + assert!(!setup.engine().qualification().status().permits_lease()); +} + +#[tokio::test] +async fn exact_native_actor_and_action_require_a_durable_unit_before_custody() { + let setup = Setup::new().await; + let session = setup + .engine() + .commissioning_session(&setup.inputs()) + .expect("operator"); + session.initialize_budget().await.expect("registered"); + let commissioned = io(&setup, Some(&session)); + commissioned.verify(NOW).expect("exact native actor/action"); + commissioned + .prepare() + .await + .expect("same connection and transport"); + assert!(commissioned.lease().await.is_some()); + assert_eq!(setup.leases(), 1); + assert_eq!( + session + .floor + .load() + .expect("durable floor") + .consumed_credential_leases(), + 1 + ); + assert!( + commissioned.lease().await.is_none(), + "one-unit lifetime ceiling" + ); + assert_eq!( + commissioned.authority_refusal(), + Some("gateway.commissioning.exhausted") + ); + assert_eq!(setup.leases(), 1); + assert!(!setup.engine().qualification().status().permits_lease()); +} + +#[tokio::test] +async fn absent_registration_and_expiry_after_preparation_never_lease() { + for initialized in [false, true] { + let setup = Setup::new().await; + let session = setup + .engine() + .commissioning_session(&setup.inputs()) + .expect("operator"); + if initialized { + session.initialize_budget().await.expect("registered"); + } + let commissioned = io(&setup, Some(&session)); + commissioned.verify(NOW).expect("native proof"); + commissioned.prepare().await.expect("prepared"); + if initialized { + setup.clock.set(setup.permit.body().statement.not_after); + } + assert!(commissioned.lease().await.is_none()); + assert_eq!(setup.leases(), 0); + } +} + +#[tokio::test] +async fn another_signed_actor_or_action_is_refused_before_custody() { + for wrong_actor in [true, false] { + let mut setup = Setup::new().await; + let mut body = setup.permit.body().clone(); + if wrong_actor { + body.statement.binding.principal_sha256 = + commissioning_principal_sha256(&Signer::new(0x45).principal); + } else { + body.statement.binding.allowed_actions = vec![Sha256Digest::from_bytes([0x61; 32])]; + } + setup.permit = signed(body); + let session = setup + .engine() + .commissioning_session(&setup.inputs()) + .expect("operator"); + session.initialize_budget().await.expect("registered"); + let commissioned = io(&setup, Some(&session)); + assert_eq!( + commissioned.verify(NOW).map(|_| ()), + Err(super::super::not_entered( + "gateway.commissioning.binding-mismatch" + )) + ); + assert!(commissioned.lease().await.is_none()); + assert_eq!(setup.leases(), 0); + assert_eq!( + session + .floor + .load() + .expect("floor") + .consumed_credential_leases(), + 0 + ); + } +} + +#[tokio::test] +async fn changed_resources_run_operator_or_context_cannot_open_a_session() { + let setup = Setup::new().await; + let another_run = BoundedText::parse("another-protected-run:1").expect("run"); + for change in ["resources", "run", "operator", "context"] { + let mut inputs = setup.inputs(); + let mut changed = setup.permit.body().clone(); + changed.statement.binding.trusted_context_sha256 = Sha256Digest::from_bytes([0x61; 32]); + let different_context = signed(changed); + match change { + "resources" => inputs.resources = b"different resources", + "run" => inputs.protected_run = &another_run, + "operator" => inputs.operator_attestation = b"{}", + "context" => inputs.artifacts.permit = different_context.canonical_bytes(), + _ => unreachable!(), + } + assert!( + setup.engine().commissioning_session(&inputs).is_err(), + "{change}" + ); + assert_eq!(setup.leases(), 0); + } +} diff --git a/product/runtime/auths-gateway/src/engine.rs b/product/runtime/auths-gateway/src/engine.rs index f4e546bfa..8e6b7ad5e 100644 --- a/product/runtime/auths-gateway/src/engine.rs +++ b/product/runtime/auths-gateway/src/engine.rs @@ -45,6 +45,14 @@ use std::sync::{Arc, OnceLock}; use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH}; use thiserror::Error; +#[cfg(unix)] +#[path = "commissioning_session.rs"] +mod commissioning; +#[cfg(unix)] +pub use commissioning::{ + CommissioningSession, CommissioningSessionInputs, commissioning_principal_sha256, +}; + const MAX_PROOF_BYTES: usize = 4 * 1024 * 1024; const MAX_ACTION_BYTES: usize = 64 * 1024; const MAX_CONTEXT_BYTES: usize = 4 * 1024 * 1024; @@ -229,6 +237,8 @@ pub struct GatewayAdminStatus { pub struct GatewayEngine { recipe: CompiledRecipe, trusted_context: TrustedContext, + #[cfg(unix)] + trusted_context_sha256: auths_recipe_qualification::Sha256Digest, observer: Option, workload_id: String, profile: ConnectionProfile, @@ -298,6 +308,13 @@ impl GatewayEngine { Ok(Self { recipe, trusted_context, + #[cfg(unix)] + trusted_context_sha256: { + use sha2::Digest as _; + auths_recipe_qualification::Sha256Digest::from_bytes( + sha2::Sha256::digest(trusted_context_cbor).into(), + ) + }, observer: None, workload_id, profile, @@ -974,6 +991,12 @@ impl GatewayEngine { action: &[], started: Instant::now(), prepared: OnceLock::new(), + #[cfg(unix)] + commissioning: None, + #[cfg(unix)] + commissioned_action: OnceLock::new(), + #[cfg(unix)] + commissioning_refusal: OnceLock::new(), }; io.prepare().await?; let context = SubmitContext { @@ -1021,6 +1044,12 @@ impl GatewayEngine { action: action_cbor, started: Instant::now(), prepared: OnceLock::new(), + #[cfg(unix)] + commissioning: None, + #[cfg(unix)] + commissioned_action: OnceLock::new(), + #[cfg(unix)] + commissioning_refusal: OnceLock::new(), }; submit::run( &SubmitContext { @@ -1039,6 +1068,15 @@ impl GatewayEngine { /// hold the secret its credential generation names, and prepares the /// pinned transport. Nothing is stored. async fn prepare_entry(&self) -> Result { + self.prepare_entry_for(|| self.qualification.check()).await + } + + /// Both authority paths perform exactly the same connection and transport + /// checks; the ordinary path supplies only its qualification check. + async fn prepare_entry_for( + &self, + check_authority: impl FnOnce() -> Result<(), &'static str>, + ) -> Result { let loaded = match self.connection.load().await { Ok(Some(loaded)) => loaded, Err(SharedConnectionError::Rollback) => { @@ -1052,7 +1090,7 @@ impl GatewayEngine { } let descriptor = GatewayConnectionDescriptor::from_record(record, &self.recipe) .map_err(|_| "gateway.connection.recipe-mismatch")?; - self.qualification.check()?; + check_authority()?; if self.holds(record).await.is_err() { return Err("gateway.connection.credential-generation-missing"); } @@ -1194,23 +1232,41 @@ struct EngineIo<'a> { action: &'a [u8], started: Instant, prepared: OnceLock, + #[cfg(unix)] + commissioning: Option<&'a CommissioningSession<'a>>, + #[cfg(unix)] + commissioned_action: OnceLock, + #[cfg(unix)] + commissioning_refusal: OnceLock<&'static str>, } impl SubmitIo for EngineIo<'_> { type Lease = StoredSecretLease; fn clock(&self) -> Option { + #[cfg(unix)] + if self.commissioning.is_some() { + return Some(self.engine.qualification.commissioning_time().0); + } wall_clock_seconds() } fn verify(&self, now: u64) -> Result { - verify_detailed( + let verified = verify_detailed( &self.engine.recipe, &self.engine.trusted_context, now, self.proof, self.action, - ) + )?; + #[cfg(unix)] + if let Some(session) = self.commissioning { + let action = session.bind_verified(&verified).map_err(not_entered)?; + self.commissioned_action + .set(action) + .map_err(|_| not_entered("gateway.commissioning.binding-mismatch"))?; + } + Ok(verified) } fn bind_scope(&self, verified: &VerifiedCommand) -> Result<(), &'static str> { @@ -1222,6 +1278,20 @@ impl SubmitIo for EngineIo<'_> { } async fn prepare(&self) -> Result<(), &'static str> { + #[cfg(unix)] + let prepared = match self.commissioning { + Some(session) => { + let action = self + .commissioned_action + .get() + .ok_or("gateway.commissioning.binding-mismatch")?; + self.engine + .prepare_entry_for(|| session.check(action)) + .await? + } + None => self.engine.prepare_entry().await?, + }; + #[cfg(not(unix))] let prepared = self.engine.prepare_entry().await?; self.prepared .set(prepared) @@ -1229,6 +1299,18 @@ impl SubmitIo for EngineIo<'_> { } async fn reload(&self) -> bool { + #[cfg(unix)] + if let Some(session) = self.commissioning { + let checked = self + .commissioned_action + .get() + .ok_or("gateway.commissioning.binding-mismatch") + .and_then(|action| session.check(action)); + if let Err(code) = checked { + let _ = self.commissioning_refusal.set(code); + return false; + } + } match self.prepared.get() { Some(prepared) => self.engine.unchanged(prepared).await, None => false, @@ -1245,9 +1327,43 @@ impl SubmitIo for EngineIo<'_> { async fn lease(&self) -> Option { let prepared = self.prepared.get()?; + #[cfg(unix)] + if let Some(session) = self.commissioning { + if let Err(code) = session.claim(self.commissioned_action.get()?).await { + let _ = self.commissioning_refusal.set(code); + return None; + } + if !self.engine.unchanged(prepared).await { + return None; + } + if let Err(code) = session.check(self.commissioned_action.get()?) { + let _ = self.commissioning_refusal.set(code); + return None; + } + return self + .engine + .credentials + .lease_secret( + &prepared.loaded.record().credential_binding(), + Instant::now() + Duration::from_secs(30), + ) + .await + .ok(); + } self.engine.lease(prepared).await.ok() } + fn authority_refusal(&self) -> Option<&'static str> { + #[cfg(unix)] + { + self.commissioning_refusal.get().copied() + } + #[cfg(not(unix))] + { + None + } + } + fn secret_admitted(&self, lease: &StoredSecretLease, guard: &GuardChecks) -> bool { lease .expose(Instant::now()) @@ -1261,7 +1377,7 @@ impl SubmitIo for EngineIo<'_> { } fn within_entry_deadline(&self, evaluated_at: u64) -> bool { - wall_clock_seconds() + self.clock() .is_some_and(|now| now <= evaluated_at.saturating_add(ENTRY_DEADLINE_SECONDS)) && self.started.elapsed() <= Duration::from_secs(ENTRY_DEADLINE_SECONDS) } @@ -1381,6 +1497,9 @@ pub(crate) fn verify_command( /// need of its authorized branches. #[derive(Clone, Debug)] pub(crate) struct VerifiedCommand { + /// Exact actors of action IDs already sealed by the native verifier. + #[cfg(unix)] + pub(crate) actors: Vec, pub(crate) request: ClosedProviderRequest, /// The bounded branch's links and the counters its claim reserves. pub(crate) bound: Option, @@ -1461,6 +1580,8 @@ pub(crate) fn verify_detailed( .map_err(|_| not_entered("gateway.policy.proof-unavailable"))?; let observer_refusal = crate::separation::check_proof_observers(proof_cbor, action).err(); Ok(VerifiedCommand { + #[cfg(unix)] + actors: branches.actors, request, bound, approvers: branches.approvers, diff --git a/product/runtime/auths-gateway/src/lib.rs b/product/runtime/auths-gateway/src/lib.rs index c071fcaed..e7e5533ab 100644 --- a/product/runtime/auths-gateway/src/lib.rs +++ b/product/runtime/auths-gateway/src/lib.rs @@ -13,6 +13,12 @@ mod audit; mod binding; mod bounds; pub mod commissioning_budget; +#[cfg(unix)] +pub mod commissioning_floor; +#[cfg(unix)] +pub use engine::{ + CommissioningSession, CommissioningSessionInputs, commissioning_principal_sha256, +}; mod connection; mod credential_journal; mod echo_verify; diff --git a/product/runtime/auths-gateway/src/qualification.rs b/product/runtime/auths-gateway/src/qualification.rs index 4b2056752..b7ea22965 100644 --- a/product/runtime/auths-gateway/src/qualification.rs +++ b/product/runtime/auths-gateway/src/qualification.rs @@ -444,6 +444,34 @@ impl QualificationGate { .clone() } + /// Private operator sessions reuse the configured root, target and clock; + /// application inputs cannot supply any of these values. + #[cfg(unix)] + pub(crate) fn commissioning_target( + &self, + ) -> Option<(&QualificationTrustRoot, &QualificationTuple)> { + if self.policy != QualificationPolicy::Required { + return None; + } + Some((self.root.as_ref()?, self.deployment.as_ref()?)) + } + + #[cfg(unix)] + pub(crate) fn commissioning_time(&self) -> (u64, bool) { + match self.clock.now() { + Some(now) => (now, self.clock.trust() == ClockTrustState::Trusted), + None => (0, false), + } + } + + #[cfg(unix)] + pub(crate) fn remember_commissioning( + &self, + permit: &auths_recipe_qualification::VerifiedCommissioningPermit, + ) { + permit.remember(&mut self.state.lock().unwrap_or_else(PoisonError::into_inner)); + } + fn verdict(&self) -> QualificationVerdict { let unavailable = QualificationVerdict { state: RecipeQualificationState::Unqualified, diff --git a/product/runtime/auths-gateway/src/scenario_tests.rs b/product/runtime/auths-gateway/src/scenario_tests.rs index 2101cc401..afa3e9f07 100644 --- a/product/runtime/auths-gateway/src/scenario_tests.rs +++ b/product/runtime/auths-gateway/src/scenario_tests.rs @@ -328,6 +328,8 @@ pub(crate) fn admitted( .closed_request_from_arguments(&arguments, commitment) .map_err(|error| crate::engine::not_entered(error.code()))?; Ok(VerifiedCommand { + #[cfg(unix)] + actors: Vec::new(), request, bound, approvers: Vec::new(), diff --git a/product/runtime/auths-gateway/src/semantic_closure.rs b/product/runtime/auths-gateway/src/semantic_closure.rs index ecc6755a8..f08061885 100644 --- a/product/runtime/auths-gateway/src/semantic_closure.rs +++ b/product/runtime/auths-gateway/src/semantic_closure.rs @@ -10,7 +10,7 @@ /// SHA-256 of the schema, a NUL byte, and `semantic-closure.json`. /// Regenerate through `semantic_closure_is_current` with `AUTHS_UPDATE_FIXTURES=1`. pub const GATEWAY_SEMANTIC_CLOSURE_SHA256: &str = - "7bae0f7bdefe140109d5f30fd80b388443271ed8a7bad341c34945e06d5b6ac1"; + "18e2baae6d72c709a069569298daef381c3e6e80c10becdfdb3a061d3e06157f"; #[cfg(test)] mod tests { diff --git a/product/runtime/auths-gateway/src/submit.rs b/product/runtime/auths-gateway/src/submit.rs index b6be2766f..1c8031e78 100644 --- a/product/runtime/auths-gateway/src/submit.rs +++ b/product/runtime/auths-gateway/src/submit.rs @@ -70,6 +70,13 @@ pub(crate) trait SubmitIo { /// Leases the credential. async fn lease(&self) -> Option; + /// A sealed operator authority's more specific pre-custody refusal, when + /// present. It refines diagnostics only; the translated driver still owns + /// the refusal transition and records no provider entry. + fn authority_refusal(&self) -> Option<&'static str> { + None + } + /// Whether the leased secret starts with a declared prefix. The secret /// never leaves the lease. fn secret_admitted(&self, lease: &Self::Lease, guard: &GuardChecks) -> bool; @@ -714,7 +721,13 @@ impl Run<'_, I> { let Some(claim) = self.claim.take() else { return false; }; - let code = refusal_code(refusal); + let code = match refusal { + Refusal::CredentialUnavailable | Refusal::ConnectionChanged => self + .io + .authority_refusal() + .unwrap_or_else(|| refusal_code(refusal)), + _ => refusal_code(refusal), + }; let pre_entry = (!self.pre_entry.is_empty()).then_some(&self.pre_entry); let recorded = claim.record_not_entered(code, pre_entry).await.is_ok(); if recorded { diff --git a/release/semantic-freeze-versions.toml b/release/semantic-freeze-versions.toml index 1c9dd5edf..5a6688bb7 100644 --- a/release/semantic-freeze-versions.toml +++ b/release/semantic-freeze-versions.toml @@ -1,4 +1,4 @@ -freeze_version = 371 +freeze_version = 372 # Semantic identity counters live outside the xtask source tree deliberately. # The formal source closure binds xtask's executable code, while the semantic @@ -45,7 +45,7 @@ freeze_version = 371 "auths.frozen-bytes/product/integrations/auths-stripe/fixtures/subscription-create/v1/manifest.sha256.json" = 1 "auths.frozen-bytes/product/integrations/auths-stripe/fixtures/subscription-modify/v1/manifest.sha256.json" = 1 "auths.frozen-bytes/product/integrations/auths-stripe/fixtures/v1/manifest.sha256.json" = 1 -"auths.identity.protocol" = 124 +"auths.identity.protocol" = 125 "auths.modular-components" = 20 "auths.portable-abi-bindings" = 121 "auths.product.bounded-domains" = 19 @@ -60,11 +60,11 @@ freeze_version = 371 "auths.product.mcp-closed-execution" = 31 "auths.product.mechanism-profile-conformance" = 12 "auths.product.operations" = 5 -"auths.product.public-sdk-contract" = 121 +"auths.product.public-sdk-contract" = 122 "auths.product.receipts" = 13 "auths.product.release-assurance" = 7 "auths.product.simplified-waist" = 19 "auths.product.vocabulary" = 24 "auths.release.benchmark-contract" = 1 "auths.release.evolution-contract" = 79 -"auths.release.public-surface" = 371 +"auths.release.public-surface" = 372 diff --git a/release/semantic-freeze.json b/release/semantic-freeze.json index f987c492e..3e4d04a1a 100644 --- a/release/semantic-freeze.json +++ b/release/semantic-freeze.json @@ -1,6 +1,6 @@ { "schema": "auths.semantic-freeze/1", - "freezeVersion": 371, + "freezeVersion": 372, "publicSurface": { "rustRoots": [ "auths", @@ -550,7 +550,7 @@ }, { "id": "auths.identity.protocol", - "version": 124, + "version": 125, "classification": "frozen-meaning", "categories": [ "identity-protocol-versions", @@ -573,7 +573,7 @@ "core/fixtures/identity/v1/vectors.json", "core/spec/identity/v1" ], - "sha256": "885a3b6753548da2526e612941e6e54d05225c0d79d2412ddc1ef1b8df8f8939" + "sha256": "aef90d74b6777b88544d01183cfe9ac8ae3270ec7200917d0c05319cd0638c8d" }, { "id": "auths.modular-components", @@ -871,7 +871,7 @@ }, { "id": "auths.product.public-sdk-contract", - "version": 121, + "version": 122, "classification": "frozen-meaning", "categories": [ "rust-sdk-contract", @@ -889,7 +889,7 @@ "product/runtime/auths-runtime/src", "product/sdk/auths-sdk/src" ], - "sha256": "9b4f652ee8cea79abf9db48ede141a33a7ecb722be3237105954da9a1773269b" + "sha256": "3fbc6618d7e844178373509f26ea29becd37115f90950d371abf001a05326050" }, { "id": "auths.product.receipts", @@ -1011,7 +1011,7 @@ }, { "id": "auths.release.public-surface", - "version": 371, + "version": 372, "classification": "release-metadata", "categories": [ "package-names", @@ -1104,7 +1104,7 @@ "xtask/src/release_launch.rs", "xtask/src/semantic_freeze.rs" ], - "sha256": "cebf93d0093e386bdadfb1ef954963844daaff4ce84d06555f7436acbad4df98" + "sha256": "3dc8eeaf46f43840d02b35e00203096fb13b93a7594e34e616db382ee9dd60d9" } ] } From c92531a4fe524ecaad357e8036ceb4ec274ee08b Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 04:09:36 +0100 Subject: [PATCH 056/108] Pin offline qualification root and expose purpose-bound commissioning issuance --- compliance.toml | 2 + ...d-qualification-commissioning-authority.md | 10 +- ...gateway-polish-and-recipe-qualification.md | 3 +- .../src/bin/auths-qualification.rs | 155 ++++++++++++------ .../tests/cli.rs | 155 ++++++++++++++++++ .../auths-gateway/semantic-closure.json | 2 +- .../auths-gateway/src/qualification.rs | 97 ++++++++++- .../auths-gateway/src/semantic_closure.rs | 2 +- qualification/README.md | 34 +++- qualification/trust/ceremony.json | 16 ++ .../commissioning-signer-certificate.json | 1 + .../trust/qualification-trust-root.json | 1 + qualification/trust/revocation-list.json | 1 + qualification/trust/signer-certificate.json | 1 + release/semantic-freeze-versions.toml | 8 +- release/semantic-freeze.json | 14 +- 16 files changed, 429 insertions(+), 73 deletions(-) create mode 100644 qualification/trust/ceremony.json create mode 100644 qualification/trust/commissioning-signer-certificate.json create mode 100644 qualification/trust/qualification-trust-root.json create mode 100644 qualification/trust/revocation-list.json create mode 100644 qualification/trust/signer-certificate.json diff --git a/compliance.toml b/compliance.toml index 59a763404..8139e9f85 100644 --- a/compliance.toml +++ b/compliance.toml @@ -1212,6 +1212,7 @@ proof-author-or-assembler = [ "product/qualification/auths-recipe-qualification-issuance/tests/commissioning.rs#action_and_lease_bounds_are_exact_and_never_silently_repaired", "product/qualification/auths-recipe-qualification-issuance/tests/commissioning.rs#renewal_cannot_change_the_durable_budget_identity_or_binding", "product/qualification/auths-recipe-qualification-issuance/tests/commissioning.rs#commissioning_artifact_fixture_is_current", + "product/qualification/auths-recipe-qualification-issuance/tests/cli.rs#commissioning_cli_requires_its_own_purpose_and_rechecks_offline_evidence", "product/qualification/auths-recipe-qualification-issuance/tests/issuance.rs#a_record_is_assembled_from_its_evidence_and_closes_over_it", "product/qualification/auths-recipe-qualification-issuance/tests/issuance.rs#a_run_with_a_failed_case_produces_no_evidence", @@ -1759,6 +1760,7 @@ runtime-enforcement-boundary = [ ] stateful-replay-budget-component = [ "product/runtime/auths-gateway/src/commissioning_budget/tests.rs#capacity_survives_crash_restart_and_sweep_file", + "product/runtime/auths-gateway/src/qualification.rs#pinned_ceremony_authenticates_separate_signer_purposes", "product/runtime/auths-gateway/src/commissioning_floor/tests.rs#runtime_never_creates_a_missing_floor", "product/runtime/auths-gateway/src/commissioning_floor/tests.rs#committed_floor_survives_restart_and_cannot_be_reset", "product/runtime/auths-gateway/src/commissioning_floor/tests.rs#concurrent_local_claims_never_decrease_the_witness", diff --git a/docs/adr/0016-bounded-qualification-commissioning-authority.md b/docs/adr/0016-bounded-qualification-commissioning-authority.md index 2f0bf356b..b6d922b68 100644 --- a/docs/adr/0016-bounded-qualification-commissioning-authority.md +++ b/docs/adr/0016-bounded-qualification-commissioning-authority.md @@ -3,8 +3,9 @@ **Status:** Implementing. The closed permit, commissioning-only signer purpose, offline evidence closure, pure signature/binding verifier, atomic permanent budget, retained host floors and authenticated private operator commands are -implemented. Protected family references/workflows, production root pinning -and actual live evidence remain required before the bootstrap is resolved. +implemented. The first offline root ceremony and separate public signer +certificates are pinned. Protected family references/workflows and actual live +evidence remain required before the bootstrap is resolved. Ordinary production leases still require qualification. **Date:** 7 October 2026 @@ -192,7 +193,10 @@ is selected by the authenticated operator process, never by a proof or frame. Focused tests use public synthetic authority, frozen native quorum proofs and counted custody to exercise these boundaries. They establish runtime refusal and accounting behavior, not protected provider evidence or a completed first -qualification. Production trust remains unavailable until its root is pinned. +qualification. The first pinned root and public certificates are recorded in +`qualification/trust/ceremony.json`, explicitly as a repository-owner-delegated +technical assessment. Its private root key stays outside the checkout and CI. +No qualification record or release index was issued by this ceremony. This adds explicit operator commissioning authority and its associated trust obligation. It does not make the first qualification appear to preexist its own diff --git a/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md b/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md index ce830240b..65b9c820c 100644 --- a/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md +++ b/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md @@ -1774,6 +1774,7 @@ qualification nor evidence of provider behavior or production readiness. The signed schema, pure issuance/verifier, sealed private runtime path, PostgreSQL accounting, retained host floor and authenticated operator commands -are implemented. Production root pinning, protected family reference/workflow +are implemented. The first offline root and separate purpose certificates are +pinned, with no qualification issued. The protected family reference/workflow and rejection/live evidence still must land before the bootstrap can be claimed resolved. Epic 5's done conditions remain unchanged. diff --git a/product/qualification/auths-recipe-qualification-issuance/src/bin/auths-qualification.rs b/product/qualification/auths-recipe-qualification-issuance/src/bin/auths-qualification.rs index 540ce5bdf..6287529c9 100644 --- a/product/qualification/auths-recipe-qualification-issuance/src/bin/auths-qualification.rs +++ b/product/qualification/auths-recipe-qualification-issuance/src/bin/auths-qualification.rs @@ -5,16 +5,16 @@ //! written to a private file and is never an argument or printed. use auths_recipe_qualification::{ - EvidenceMemberKind, GitCommit, LiveEffects, MAX_INDEX_ENTRIES, ProviderContract, - QualificationId, QualificationInputs, QualificationRootId, QualificationSignerCertificate, - QualificationSignerId, QualificationTrustRoot, QualificationTuple, - RELEASE_ATTESTATIONS_DIRECTORY, RELEASE_INDEX_FILE, RELEASE_RECORDS_DIRECTORY, - RELEASE_REVOCATION_LIST_FILE, RELEASE_SIGNER_CERTIFICATE_FILE, VerifiedQualifications, - VerifierState, + CommissioningBinding, EvidenceMemberKind, GitCommit, LiveEffects, MAX_INDEX_ENTRIES, + ProviderContract, QualificationEvidence, QualificationId, QualificationInputs, + QualificationRootId, QualificationSignerCertificate, QualificationSignerId, + QualificationTrustRoot, QualificationTuple, RELEASE_ATTESTATIONS_DIRECTORY, RELEASE_INDEX_FILE, + RELEASE_RECORDS_DIRECTORY, RELEASE_REVOCATION_LIST_FILE, RELEASE_SIGNER_CERTIFICATE_FILE, + VerifiedQualifications, VerifierState, }; use auths_recipe_qualification_issuance::{ - CaseReport, CertificateRequest, IssuanceError, QualificationProposal, RecordDraft, - ReleaseSigner, RootSigner, SigningSeed, evidence, stages, + CaseReport, CertificateRequest, CommissioningProposal, CommissioningSigner, IssuanceError, + QualificationProposal, RecordDraft, ReleaseSigner, RootSigner, SigningSeed, evidence, stages, }; use base64ct::{Base64UrlUnpadded, Encoding as _}; use clap::{Parser, Subcommand}; @@ -77,24 +77,13 @@ enum Command { key_out: PathBuf, }, /// Offline ceremony: certify a release signer. - Certify { - #[arg(long)] - root_key: PathBuf, - #[arg(long)] - root: PathBuf, - #[arg(long)] - signer_id: String, - #[arg(long)] - public_key: String, - #[arg(long)] - issued_at: Option, - #[arg(long)] - not_before: u64, - #[arg(long)] - not_after: u64, - #[arg(long)] - out: PathBuf, - }, + Certify(CertificateOptions), + /// Offline ceremony: certify a commissioning-only signer. This key may + /// issue bounded run permits, never qualification attestations or indexes. + CertifyCommissioner(CertificateOptions), + /// Protected signer: recheck both offline evidence artifacts and sign one + /// finite reviewed commissioning binding. Grants no qualification state. + CommissioningSign(CommissioningSignOptions), /// Offline ceremony: issue the next revocation list. Revoke { #[arg(long)] @@ -207,6 +196,48 @@ enum Command { }, } +#[derive(clap::Args)] +struct CertificateOptions { + #[arg(long)] + root_key: PathBuf, + #[arg(long)] + root: PathBuf, + #[arg(long)] + signer_id: String, + #[arg(long)] + public_key: String, + #[arg(long)] + issued_at: Option, + #[arg(long)] + not_before: u64, + #[arg(long)] + not_after: u64, + #[arg(long)] + out: PathBuf, +} + +#[derive(clap::Args)] +struct CommissioningSignOptions { + #[arg(long)] + binding: PathBuf, + #[arg(long)] + conformance: PathBuf, + #[arg(long)] + differential: PathBuf, + #[arg(long)] + signer_key: PathBuf, + #[arg(long)] + certificate: PathBuf, + #[arg(long)] + issued_at: Option, + #[arg(long)] + not_before: u64, + #[arg(long)] + not_after: u64, + #[arg(long)] + out: PathBuf, +} + /// A failure: its stable token and what it concerns. Never a key. struct Failure(String); @@ -461,6 +492,26 @@ fn sign( Ok(()) } +fn certify(options: &CertificateOptions, commissioning: bool) -> Result<(), Failure> { + let root = RootSigner::open(&read_key(&options.root_key)?, trust_root(&options.root)?)?; + let request = CertificateRequest { + signer_id: parsed( + QualificationSignerId::parse(&options.signer_id), + "signer-id", + )?, + public_key_b64: parsed(options.public_key.clone().try_into(), "public-key")?, + issued_at: now(options.issued_at)?, + not_before: options.not_before, + not_after: options.not_after, + }; + let certificate = if commissioning { + root.certify_commissioner(request)? + } else { + root.certify(request)? + }; + write(&options.out, certificate.canonical_bytes()) +} + fn ceremony(command: Command) -> Result<(), Failure> { match command { Command::RootInit { @@ -484,26 +535,8 @@ fn ceremony(command: Command) -> Result<(), Failure> { println!("public_key={}", seed.public_key().as_str()); Ok(()) } - Command::Certify { - root_key, - root, - signer_id, - public_key, - issued_at, - not_before, - not_after, - out, - } => { - let root = RootSigner::open(&read_key(&root_key)?, trust_root(&root)?)?; - let certificate = root.certify(CertificateRequest { - signer_id: parsed(QualificationSignerId::parse(signer_id), "signer-id")?, - public_key_b64: parsed(public_key.try_into(), "public-key")?, - issued_at: now(issued_at)?, - not_before, - not_after, - })?; - write(&out, certificate.canonical_bytes()) - } + Command::Certify(options) => certify(&options, false), + Command::CertifyCommissioner(options) => certify(&options, true), Command::Revoke { root_key, root, @@ -672,6 +705,32 @@ fn stage(command: Command) -> Result<(), Failure> { } } +fn commissioning_sign(options: &CommissioningSignOptions) -> Result<(), Failure> { + let binding: CommissioningBinding = json(&options.binding)?; + let offline = |path: &Path| { + QualificationEvidence::from_canonical_json(&read(path)?) + .map_err(|_| failure("invalid-evidence", path)) + }; + let proposal = CommissioningProposal::assemble( + binding, + offline(&options.conformance)?, + offline(&options.differential)?, + )?; + let certificate = + QualificationSignerCertificate::from_canonical_json(&read(&options.certificate)?) + .map_err(|_| failure("invalid-certificate", &options.certificate))?; + let signer = CommissioningSigner::open(&read_key(&options.signer_key)?, certificate)?; + let permit = signer.permit( + &proposal, + now(options.issued_at)?, + options.not_before, + options.not_after, + )?; + write(&options.out, permit.canonical_bytes())?; + println!("commissioning_permit={}", permit.digest().to_hex()); + Ok(()) +} + fn run(command: Command) -> Result<(), Failure> { match command { Command::RunStage { @@ -691,13 +750,15 @@ fn run(command: Command) -> Result<(), Failure> { ), Command::RootInit { .. } | Command::SignerInit { .. } - | Command::Certify { .. } + | Command::Certify(_) + | Command::CertifyCommissioner(_) | Command::Revoke { .. } => ceremony(command), Command::Evidence { .. } | Command::Assemble { .. } => build(command), Command::StageTrust { .. } | Command::StageFreshness { .. } | Command::StageRedaction { .. } | Command::ContractId { .. } => stage(command), + Command::CommissioningSign(options) => commissioning_sign(&options), Command::Sign { proposal_dirs, signer_key, diff --git a/product/qualification/auths-recipe-qualification-issuance/tests/cli.rs b/product/qualification/auths-recipe-qualification-issuance/tests/cli.rs index b08af012e..5f06bc170 100644 --- a/product/qualification/auths-recipe-qualification-issuance/tests/cli.rs +++ b/product/qualification/auths-recipe-qualification-issuance/tests/cli.rs @@ -56,6 +56,161 @@ fn member_token(member: EvidenceMemberKind) -> String { .to_owned() } +#[test] +#[cfg(unix)] +fn commissioning_cli_requires_its_own_purpose_and_rechecks_offline_evidence() { + use auths_recipe_qualification::{ + BoundedText, CommissioningBinding, CommissioningInputs, CommissioningOfflineEvidence, + ProviderEnvironmentClass, QualificationArtifactKind, QualificationCommissioningPermit, + QualificationSignerCertificate, QualificationTrustRoot, Sha256Digest, + VerifiedCommissioningPermit, + }; + let directory = tempfile::tempdir().expect("private ceremony"); + let at = |name: &str| path(directory.path(), name); + succeed(&[ + "root-init", + "--root-id", + "synthetic-cli-root", + "--key-out", + &at("root.key"), + "--root-out", + &at("root.json"), + ]); + let public_key = succeed(&["signer-init", "--key-out", &at("commissioner.key")]) + .trim() + .strip_prefix("public_key=") + .expect("public key") + .to_owned(); + let mut certificates = Vec::new(); + for (command, filename) in [ + ("certify-commissioner", "commissioner.json"), + ("certify", "release.json"), + ] { + succeed(&[ + command, + "--root-key", + &at("root.key"), + "--root", + &at("root.json"), + "--signer-id", + "synthetic-cli-signer", + "--public-key", + &public_key, + "--issued-at", + &(NOW - DAY).to_string(), + "--not-before", + &(NOW - DAY).to_string(), + "--not-after", + &(NOW + DAY).to_string(), + "--out", + &at(filename), + ]); + certificates.push( + QualificationSignerCertificate::from_canonical_json( + &fs::read(at(filename)).expect("certificate"), + ) + .expect("closed certificate"), + ); + } + assert_eq!( + certificates[0].body().statement.permitted_artifact_kinds, + vec![QualificationArtifactKind::QualificationCommissioningPermit] + ); + assert!( + !certificates[1] + .body() + .statement + .permitted_artifact_kinds + .contains(&QualificationArtifactKind::QualificationCommissioningPermit) + ); + succeed(&[ + "revoke", + "--root-key", + &at("root.key"), + "--root", + &at("root.json"), + "--sequence", + "1", + "--issued-at", + &(NOW - HOUR).to_string(), + "--next-update", + &(NOW + DAY).to_string(), + "--out", + &at("revocations.json"), + ]); + let conformance = common::member_evidence(EvidenceMemberKind::Conformance); + let differential = common::member_evidence(EvidenceMemberKind::Differential); + let binding = CommissioningBinding { + protected_run: BoundedText::parse("synthetic-run/attempt/1").expect("run"), + source_commit: common::commit(), + tuple: common::tuple(), + principal_sha256: Sha256Digest::from_bytes([0x61; 32]), + trusted_context_sha256: Sha256Digest::from_bytes([0x62; 32]), + resources_sha256: Sha256Digest::from_bytes([0x63; 32]), + provider_environment_class: ProviderEnvironmentClass::ProviderTestMode, + offline_evidence: CommissioningOfflineEvidence { + conformance_sha256: conformance.digest(), + differential_sha256: differential.digest(), + }, + allowed_actions: vec![Sha256Digest::from_bytes([0x64; 32])], + maximum_credential_leases: 2, + }; + fs::write( + at("binding.json"), + serde_json::to_vec(&binding).expect("binding"), + ) + .expect("write"); + fs::write(at("conformance.json"), conformance.canonical_bytes()).expect("write"); + fs::write(at("differential.json"), differential.canonical_bytes()).expect("write"); + let arguments = |certificate: &str| { + vec![ + "commissioning-sign".to_owned(), + "--binding".to_owned(), + at("binding.json"), + "--conformance".to_owned(), + at("conformance.json"), + "--differential".to_owned(), + at("differential.json"), + "--signer-key".to_owned(), + at("commissioner.key"), + "--certificate".to_owned(), + at(certificate), + "--issued-at".to_owned(), + NOW.to_string(), + "--not-before".to_owned(), + NOW.to_string(), + "--not-after".to_owned(), + (NOW + HOUR).to_string(), + "--out".to_owned(), + at("permit.json"), + ] + }; + assert!(refuse(&borrowed(&arguments("release.json"))).starts_with("qualification.")); + assert!(!Path::new(&at("permit.json")).exists()); + succeed(&borrowed(&arguments("commissioner.json"))); + let permit_bytes = fs::read(at("permit.json")).expect("permit"); + let permit = QualificationCommissioningPermit::from_canonical_json(&permit_bytes) + .expect("closed permit"); + assert_eq!(&permit.body().statement.binding, &binding); + VerifiedCommissioningPermit::verify( + &QualificationTrustRoot::from_canonical_json(&fs::read(at("root.json")).expect("root")) + .expect("closed root"), + &CommissioningInputs { + signer_certificate: certificates[0].canonical_bytes(), + revocation_list: &fs::read(at("revocations.json")).expect("list"), + permit: &permit_bytes, + }, + ) + .expect("native artifact verification"); + // A mislabeled or changed offline member cannot replace the signed output. + fs::write(at("conformance.json"), differential.canonical_bytes()).expect("mutate member"); + assert!(refuse(&borrowed(&arguments("commissioner.json"))).starts_with("qualification.")); + assert_eq!( + fs::read(at("permit.json")).expect("retained permit"), + permit_bytes + ); +} + #[test] #[cfg(unix)] fn a_release_is_built_signed_and_verified_and_a_proposal_alone_is_not() { diff --git a/product/runtime/auths-gateway/semantic-closure.json b/product/runtime/auths-gateway/semantic-closure.json index e5c25e937..e7f0598ac 100644 --- a/product/runtime/auths-gateway/semantic-closure.json +++ b/product/runtime/auths-gateway/semantic-closure.json @@ -1 +1 @@ -{"files":[{"path":"Cargo.lock","sha256":"0e75e2fdef44e79e57797ac6661295ae58ddb8de4a1990a6fd22ce6c54f78604"},{"path":"Cargo.toml","sha256":"6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24"},{"path":"core/adapters/auths-did-keri/Cargo.toml","sha256":"86ba3e3f9a0a70d970568bfb3113b7ba7bbdd81c3eebbb52743dd574a0c0ecaa"},{"path":"core/adapters/auths-did-keri/src/lib.rs","sha256":"a75674842f8a7142004369ccd206ab43e476459293f0ff4bed4d4e659031b3e3"},{"path":"core/adapters/auths-did-key/Cargo.toml","sha256":"d5a3ae07ecde83f91eed4c3785051dd0f44eab6c891754f3309b6b40596707d7"},{"path":"core/adapters/auths-did-key/src/lib.rs","sha256":"b76a3f4528a725df53cfa9242e6e414e1d26caa48468aaed497e28b121f4497c"},{"path":"core/adapters/auths-raw-key/Cargo.toml","sha256":"f49616bc18c19e6aaa7e6a02ccebcdb9f5c1422c1278ef9869e0dbf22ceda7be"},{"path":"core/adapters/auths-raw-key/src/lib.rs","sha256":"45eec1b295dac3bed65cd79c942870b926b06b3f5d38eaebaeb6140ac69315fa"},{"path":"core/crates/auths-algebra-kernel/Cargo.toml","sha256":"0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba"},{"path":"core/crates/auths-algebra-kernel/src/generated.rs","sha256":"ae4bcbef42a408c7ffa0c6a74a42f7de177a6f14479e51d205acf830bda05960"},{"path":"core/crates/auths-algebra-kernel/src/lib.rs","sha256":"6654667eeb9b353d6648954c9fd2e8838462a82ce6b2803eb49e1366892c68c6"},{"path":"core/crates/auths-assurance/Cargo.toml","sha256":"afcb12a97ddd09d7a264b9ecd3fcaefc865ff2c9b4539ee85b00883420ba333a"},{"path":"core/crates/auths-assurance/src/lib.rs","sha256":"0fb2ec844d674b25a9e20b1601452c89c2454901fa506adfa9bb38ef9a7fa213"},{"path":"core/crates/auths-author/Cargo.toml","sha256":"1e6f0e3bc079ddb558decf0db26b291c6e72fc47327b6df1b7650d41689b215f"},{"path":"core/crates/auths-author/src/lib.rs","sha256":"e14475f2f49715a1869d5fa6b11ff1fbb72497e39097e09f833b0bae7e5b3f2b"},{"path":"core/crates/auths-author/src/observations.rs","sha256":"dda7d6bfa6f4bd7e95a480ca283c2c0e996f69c5c15cb0c7197af328131a7066"},{"path":"core/crates/auths-authority/Cargo.toml","sha256":"4f68212938029f79ebd857b4f3038494eb85d0163d49f07e51376715cf959815"},{"path":"core/crates/auths-authority/src/lib.rs","sha256":"da88d5194de4e17449e69972c0fb042afa3c39798a8f570f30771e77c384f1eb"},{"path":"core/crates/auths-codec/Cargo.toml","sha256":"e20e51826e17814effd9d8925d18d5fbdd6c0d37bf50231e743ec2611314722c"},{"path":"core/crates/auths-codec/src/approval.rs","sha256":"fbff43bf4d57f69f8b7738a8647751cde75c5a932dee65d924a1fe9c7202f91f"},{"path":"core/crates/auths-codec/src/bounded_policy.rs","sha256":"d21f6728be2d8a04b6d94921f2b683f7e61cbb42e0ac6866f1c88a49caa534c3"},{"path":"core/crates/auths-codec/src/decode.rs","sha256":"ba2999584cdf53b1b517ecb9c7ea50d39efee17c666a9a38e2ad1ac94379f778"},{"path":"core/crates/auths-codec/src/encode.rs","sha256":"8491192053e2e15d62b4d2a491de22405b7487ead69ab6f6bca40669ce7ca5f7"},{"path":"core/crates/auths-codec/src/error.rs","sha256":"fecb0737c16deb42d859f1dc7727c698438d9ac12064fd99e0024629642c390c"},{"path":"core/crates/auths-codec/src/hash.rs","sha256":"f88e111f1dbb2cef6b7b5e9c948cb45ff92e366710c8a5f5c636138aa748479e"},{"path":"core/crates/auths-codec/src/lib.rs","sha256":"3b0e5c94c6f34f750b88a9333e1d5c8145746d845d3a23e0d2f61807cf592ea7"},{"path":"core/crates/auths-codec/src/observation.rs","sha256":"38328b0c71ff97a4196eeade8b4faa889527ff1f80bb168468bcd49082a3987e"},{"path":"core/crates/auths-composition/Cargo.toml","sha256":"331e13025eb82588b5269ed3975929eb41c823d588c49e4c296273d85c6fe80e"},{"path":"core/crates/auths-composition/src/lib.rs","sha256":"e42e3b0b6a9985b73c533aeb23799c638979aa27a9ce7d0f10a8d60340570fb1"},{"path":"core/crates/auths-model/Cargo.toml","sha256":"565c15302b0cc9270db1e28efa3862804846850ba933cc17aea8abcec4a65987"},{"path":"core/crates/auths-model/src/approval.rs","sha256":"54cf44a9ef747ec21546a4086aecfb130bc7803b0d646430e6082df51e6e305f"},{"path":"core/crates/auths-model/src/bounded.rs","sha256":"f90496abc0a06c028b4d850af6ddab7d850bfafeaa3d042f1b1246a41d8bbbc9"},{"path":"core/crates/auths-model/src/bounded_policy.rs","sha256":"306a8f049cc7cfc7635fe0e4de47eb7813eed63d3c14c3be2b51586aa4eea450"},{"path":"core/crates/auths-model/src/lib.rs","sha256":"e7cfe6bb9574c6b016aa63e70658c31e0b90903ec6479a49f4a2ceb64f5bad97"},{"path":"core/crates/auths-model/src/observation.rs","sha256":"b3ed3e3cc090afca2896a7d3de7988afccc1ee1ea0ebd91b51a8bc0f20ad8dbb"},{"path":"core/crates/auths-multikey/Cargo.toml","sha256":"858756c1197befcada06134742bffe8d58cf674cadd6c046bf710570e96efaf2"},{"path":"core/crates/auths-multikey/src/lib.rs","sha256":"f5177fffb11e40eeaaa665ba886c541fc1f24d5eacdd6983fb03dc20148733f0"},{"path":"core/crates/auths-ports/Cargo.toml","sha256":"596a9b0f5af3717c16a6d13f7054d8a106bcd9f01f5f72c2235dd2afcf0ab16c"},{"path":"core/crates/auths-ports/src/binding.rs","sha256":"a16c012d40aa4249e3ec54372b9611006d0bfe8c7dc3c741911c2194ad17736d"},{"path":"core/crates/auths-ports/src/diagnostics.rs","sha256":"aa596572503b5a65a918bb2ff38281c144ff53821ee914e9325c852828d852df"},{"path":"core/crates/auths-ports/src/lib.rs","sha256":"8da1debf86f9532df0660155d04298beb1ba3a1204508f8586e2e67cd2fb3449"},{"path":"core/crates/auths-ports/src/path.rs","sha256":"b68fc547b4e4d97a60cbbc1cc1939fc6b34a8233b81f840bd396914a707e3ea1"},{"path":"core/crates/auths-raw-key-core/Cargo.toml","sha256":"98c0bc8527a537512e43a74dd6ba9658c6f0cdc16610cf938e3f9b43785d836d"},{"path":"core/crates/auths-raw-key-core/src/lib.rs","sha256":"98c0500c41697aae28708ad0bf970b9a97583d96a3d2c18d23e7fa351e0f7d12"},{"path":"core/crates/auths-registries/Cargo.toml","sha256":"590e49e58b0622d9d6274fea46796dcdb07dec9550eff295cce6a6427ffa51e2"},{"path":"core/crates/auths-registries/src/lib.rs","sha256":"450d3886d85ee333b7e046317fb5b47cde62483d5f3e41d46265e2caf4c373ec"},{"path":"core/crates/auths-registries/src/template.rs","sha256":"1224039dd2b3ce6fa8357613d8cafbae40400493da7176da202b9ade62fa05e4"},{"path":"core/crates/auths-signature-core/Cargo.toml","sha256":"6bee2230eb30af1be0bd5c2d57bd3e1903497a70028d47290d4ac6e9e0e8bca0"},{"path":"core/crates/auths-signature-core/src/lib.rs","sha256":"6e3f9311ded5e49ea50d445eb21e6d8fa12442aa4362a73e0cb6fda15b7cd865"},{"path":"core/crates/auths-signature/Cargo.toml","sha256":"7f7b5682466ba439d8c59579022cb61068cad9fb4bd2d73e1cc21327c902b450"},{"path":"core/crates/auths-signature/src/lib.rs","sha256":"b3d9ac4cc3ba0797b9e1c09f2d6ac05089b25dac4e285a5af28c0165b33d925b"},{"path":"core/crates/auths-verifier/Cargo.toml","sha256":"c43358e06a33324b41a8b93e5cc7279c55f7d21f1f6cfaa539a3fc7b4c27a38f"},{"path":"core/crates/auths-verifier/src/approval.rs","sha256":"c3cae6a49e169051eb555bb092b1069a4d422516d6a2114623a89e5f31ff923f"},{"path":"core/crates/auths-verifier/src/causal.rs","sha256":"9635230f33b13a263573d319ac8a1976addbcc07677514a43e3c7bf28dc04587"},{"path":"core/crates/auths-verifier/src/lib.rs","sha256":"f22dec38dfa47ced8da4f605390da8453273bee1da010f57fd1fdfcb10e0b389"},{"path":"core/crates/auths-verifier/src/observation.rs","sha256":"0bb07f06a0f9524c88427df1c972b1de8ba038a9eeeb15d3134c25125ae84b1e"},{"path":"core/crates/auths-verifier/src/trace.rs","sha256":"2213d72023a1d9e0413a2cf2c51c3dad9e04775d86033a0caaa9d29a8f0036f8"},{"path":"exchange/crates/auths-proof-exchange-model/Cargo.toml","sha256":"34b2db64f93a288e942b5a3918d28cdcbef906e0dc9074ce848018d3d5f7a1fa"},{"path":"exchange/crates/auths-proof-exchange-model/src/lib.rs","sha256":"49fac5aff2339d3a57c41cb8bb2a82852538e8f77ecc4b157c88e264ff31fb55"},{"path":"exchange/crates/auths-proof-exchange-port/Cargo.toml","sha256":"7ff660f1b7579dc570c791090aeb450404fbbf44c92781e289f5ccdde746d739"},{"path":"exchange/crates/auths-proof-exchange-port/src/lib.rs","sha256":"b408fb40c6432edc1facb3d8b3e9433a033f8dc73fe2e0ba5a88c972ca675021"},{"path":"product/config/auths-config/Cargo.toml","sha256":"e4b568ab9f6d84f7d7e6d66443fe825f360db9c27bc7c31d6ddc0647ba3ab304"},{"path":"product/config/auths-config/src/lib.rs","sha256":"fecf00ea65cef9018fda9af2063326d7065b869266d0d9e73a4f06816f1102cc"},{"path":"product/errors/auths-errors/Cargo.toml","sha256":"3b3a199b6460ba75bda84475bb5accd35e1485448a3981038db85bf4772dd350"},{"path":"product/errors/auths-errors/src/lib.rs","sha256":"7feeb9069fa4003f94f1f07c1c94619cf1c883e0dbaaf2187f04d0f742264bdd"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/Cargo.toml","sha256":"716f1f2a117d6d69d8effe9ee9057e24ba3502f20af6a602b06facb638cdabed"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/api.rs","sha256":"9ea61dd7ddd93282b073b98e453e6b75b26dc49689c04e9782435d06a3a09e48"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/clock.rs","sha256":"73f0a6e0f5903883329fa6683f5888288f759512ac69e5c87efd2b6b87f7d79f"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/http.rs","sha256":"14c1fce14e24c984b2a275563a29b6326fb08367922b6e8d37ba38b9cb81aa2b"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/identity.rs","sha256":"186de11230c8b33375951c4368609f8976bf9795f171af3fd7fac26207a94361"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs","sha256":"0b4617d044f5254a5ab22f5a2578f91cc025206a8c1845be39c1c56dcdf7a5df"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/names.rs","sha256":"41bb23572d6002e23ee103d6fe70ecd68764861c6f2e48a1c53af998270a4afa"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs","sha256":"39fed883f4802e68d3b41a68fea0aba0737810996b33d13577de70faba004c29"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/store.rs","sha256":"fc60ee9c49b2f4f063c449b4c78100c5c4872779e94ca168f796603b380ef6e4"},{"path":"product/integrations/auths-custody/Cargo.toml","sha256":"1e14034185ad1ec24a977fd5f41d0abee219606245c046ce2a82287fadef448b"},{"path":"product/integrations/auths-custody/src/conformance.rs","sha256":"8ed1afd58f18fc6becc268908aa6419c9aa404c79da0197963eb2599df44acf6"},{"path":"product/integrations/auths-custody/src/key.rs","sha256":"70cbb0fd21b6f5652157845a22c35be2d0f6c05b3d138fc4b9bb6dbdc3d81c40"},{"path":"product/integrations/auths-custody/src/lib.rs","sha256":"8ee593c1f59b0fd2126bdda9138026f5bc531beb64d4489a99785842e7b98b43"},{"path":"product/operations/auths-operations/Cargo.toml","sha256":"73dde1e914ba5e1386f8d49c0d730423cc72ae77ec44c6554a6a75cc8e8922b1"},{"path":"product/operations/auths-operations/src/explanation.rs","sha256":"b4a39bcbd5712cb9e735ee7deeb281f3fa6af5ddca973735bf3d87dce427ef11"},{"path":"product/operations/auths-operations/src/lib.rs","sha256":"3f401a56555113b98f57bca172a2660eaecedf76247b83a3fdbb089c133a29cd"},{"path":"product/operations/auths-operations/src/render/json.rs","sha256":"2ae042639960afee123730e945d373bc5dda1d2b3af20ae16c939a7e99b9e418"},{"path":"product/operations/auths-operations/src/render/mod.rs","sha256":"b3b7f6fe473f49227ace5a68bfc3d8dc14b5db8dd9888fd9e207070337b1b8bf"},{"path":"product/operations/auths-operations/src/render/text.rs","sha256":"f216cf3bdb00e264523271b16e7059535ac6b1aabf271cebd7935af155e4bfec"},{"path":"product/policy/auths-bounded-policy/Cargo.toml","sha256":"babd5d200923137ead71d8c2528f847cea323ce98da942a1320b054436612c47"},{"path":"product/policy/auths-bounded-policy/src/arithmetic.rs","sha256":"75e43c5d4eab8d1f71c1daf53839f5f9fe45a400afc1f63a30c6f55ce3632627"},{"path":"product/policy/auths-bounded-policy/src/commitment.rs","sha256":"c5706f2d583454e1a7f570f7ada138d4d864bef0205dfae7c1296774f396bb3f"},{"path":"product/policy/auths-bounded-policy/src/eligibility.rs","sha256":"c9acdfb793074e687fc36efad506be27dbd99ffbf40387bc66c8de39ef238432"},{"path":"product/policy/auths-bounded-policy/src/identifier.rs","sha256":"0006a32bae9eb16c4178cf797df418d2b0a781f2bc6474b741dc1a908141831c"},{"path":"product/policy/auths-bounded-policy/src/kernel.rs","sha256":"99187c28b161ac70bee1afed60711f7f645adb4d1671a01863f9849b369811d5"},{"path":"product/policy/auths-bounded-policy/src/lib.rs","sha256":"76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c"},{"path":"product/policy/auths-bounded-policy/src/receipt.rs","sha256":"3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad"},{"path":"product/policy/auths-bounded-policy/src/registry.rs","sha256":"4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0"},{"path":"product/profiles/auths-profile-api/Cargo.toml","sha256":"7ae85761f58625b5d678f961fd052eebf3e000ef565c7312e3ac857763c0017f"},{"path":"product/profiles/auths-profile-api/src/lib.rs","sha256":"a194b82b20bf8aa864c2334ef6c6aec30b2154ded972862252d5dcefa488ab95"},{"path":"product/profiles/auths-profile-mcp/Cargo.toml","sha256":"db264fc25242f7b7e4133cbe5782545b3107b406c87168ae072683cfb59eac66"},{"path":"product/profiles/auths-profile-mcp/src/arguments.rs","sha256":"a5de696586d507e2aee4a49fee99ef1ef4c51a2e46603f8838f1af6d9009833f"},{"path":"product/profiles/auths-profile-mcp/src/lib.rs","sha256":"d0f8b733a09ef8408336cdebc8948d6a5861012ce6878598b11be7084dfd4280"},{"path":"product/profiles/auths-profile-mcp/src/session.rs","sha256":"166c281fa66333388e4760d6098dad02d3359e1d5de4b8f93312c014f97abb03"},{"path":"product/qualification/auths-recipe-qualification/Cargo.toml","sha256":"b7b15b30b9a3d96d4f089d514266d3a892de6608d30707aa44be31cca89ca9fe"},{"path":"product/qualification/auths-recipe-qualification/src/canonical.rs","sha256":"30a9b50777f0dcb4b606abfee2467d5a975d9f6ad941ab6c13ca3df5b359f667"},{"path":"product/qualification/auths-recipe-qualification/src/closure.rs","sha256":"0ad6aee9bd981e2863fa725f209ec84031db2ff12f4c7ac3aaf5120f0bb86039"},{"path":"product/qualification/auths-recipe-qualification/src/commissioning.rs","sha256":"66ea49f96887c4642139a48d259c270816e2267ee8cf6344a1340fe47afda9da"},{"path":"product/qualification/auths-recipe-qualification/src/commissioning/tests.rs","sha256":"5a226725c2ad7ce920d0bd62d427185e007f4d0949b0f0ec1260aa161d3114d0"},{"path":"product/qualification/auths-recipe-qualification/src/error.rs","sha256":"52d5cf720a1e4579008fdda90a3ac2c31f0b8db57985f121f65e54b4da2b7dd1"},{"path":"product/qualification/auths-recipe-qualification/src/evidence.rs","sha256":"ba45a7409d67a8af26ab811af306412014557477a101ab2a8eb0faf8f2bd4b91"},{"path":"product/qualification/auths-recipe-qualification/src/ids.rs","sha256":"e81a906d571497ab2da753e1532d4443706410e0b75fdd59a7d2d788c7aec403"},{"path":"product/qualification/auths-recipe-qualification/src/launch.rs","sha256":"41f2e2de90e1e7d6440a66eda3eb9bea8d5e0741bc232305a76a363ab5f813c1"},{"path":"product/qualification/auths-recipe-qualification/src/lib.rs","sha256":"7d26c5bfe9769daebf90c5c2280e0d75742e4cc70d0e608408e0665e3f516a2b"},{"path":"product/qualification/auths-recipe-qualification/src/model.rs","sha256":"3484eb0ec287b23d4682ade7b1b0f8d1335985b3fb180f06fc28716076957d5f"},{"path":"product/qualification/auths-recipe-qualification/src/release.rs","sha256":"ec478e53f70052e566aac7e15be2f9e1b1cd46837ac6990ae955fa864d311586"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/mod.rs","sha256":"fa23a962fd90331152eed5edbcdf271955f7aed79b8da1e065bfe69a20b487a9"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/schemas.rs","sha256":"c59feec2805621f341a90f81fc005e2c12f7a70f9d264fdeacccb2be4fe1c046"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/verification.rs","sha256":"6a6b5834c5dae10af1ba8939b2deae43b85db71544dc8f077ff63b7fe68ac8a8"},{"path":"product/qualification/auths-recipe-qualification/src/verify.rs","sha256":"2ec2784435d11e07295de77b2ee1b2c48b2fcf9609a00454c6e7374b621aed5c"},{"path":"product/receipts/auths-receipts/Cargo.toml","sha256":"6001fa1375899953aafcb07c23a6da0c8f57ea7ec08bb9c950b12a60a8cc6f0f"},{"path":"product/receipts/auths-receipts/src/disclosure.rs","sha256":"ba9ed439be0a320c8a01f5b6e9b51361c1a37e076947490d8e4a484ba6bb119c"},{"path":"product/receipts/auths-receipts/src/lib.rs","sha256":"547a57c4160256719cafb7d0ab972d9fc80b0da14fbbce4148c70c414070ff36"},{"path":"product/runtime/auths-connections/Cargo.toml","sha256":"babeb6e1dda3dfb66291713ce1e43dce5c349833d0b50ea4dccbf986030026b2"},{"path":"product/runtime/auths-connections/src/credential.rs","sha256":"82921413bb053f0f6c7931fbd4e6a86c8cc1d8c6b51debd9c2cef33a8d5b1c51"},{"path":"product/runtime/auths-connections/src/kernel.rs","sha256":"a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8"},{"path":"product/runtime/auths-connections/src/lib.rs","sha256":"79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22"},{"path":"product/runtime/auths-connections/src/model.rs","sha256":"de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77"},{"path":"product/runtime/auths-connections/src/registry.rs","sha256":"e57640e003e72ad3235c567c2bb944a262bd64e673f023b62ea091094cc7e946"},{"path":"product/runtime/auths-gateway-kernel/Cargo.toml","sha256":"34f864e67656af4ac7e5c7a347a23f01fc8ab31365b8e23c0ef474483b14a183"},{"path":"product/runtime/auths-gateway-kernel/src/construct.rs","sha256":"e9d65744bae273d65face4285e5d2da75c06a92ab48f7b8333d496604e31c63c"},{"path":"product/runtime/auths-gateway-kernel/src/lib.rs","sha256":"cfda6f8453426564c085475f183b6f790b438768a19668f1b65d33ba59dc8632"},{"path":"product/runtime/auths-gateway-kernel/src/order.rs","sha256":"e0045f877c4b7fe3860c291039853885064ddcdebba7c9b345ab65e81e646dda"},{"path":"product/runtime/auths-gateway-kernel/src/outcome.rs","sha256":"e9785b1afe70788c89b51b18655bcd5acff7b0c8e3d12fb79c6f05a202e67e6b"},{"path":"product/runtime/auths-gateway-kernel/src/ratio.rs","sha256":"7ace22264812e6fc1ef3a62afee402cf43494bb71ae0d3de219ad1b39d690bcb"},{"path":"product/runtime/auths-gateway-kernel/src/recovery.rs","sha256":"9f46dcd1685ab6e4d1ba04a3fc286a9f3afee8fb47829be1fbc670a7926a2dc6"},{"path":"product/runtime/auths-gateway-kernel/src/transition.rs","sha256":"cefb8f01d915880f6921f2501ff881ad94b9de61072c34d9cd19220992f97374"},{"path":"product/runtime/auths-gateway/Cargo.toml","sha256":"00b28be86921dcdc0ad90cce0c62c2961cafefe96ea6c2edf0e926c3d405ccad"},{"path":"product/runtime/auths-gateway/src/admin.rs","sha256":"2d5cc67afac42fbd15f36e2d1693cd1b20cedacf775040dce6ffe04ccc94c9ea"},{"path":"product/runtime/auths-gateway/src/app.rs","sha256":"6f80f63833ea0815bb44fbf3b0cc54624a08e9fb578b035819f2980dc04e8256"},{"path":"product/runtime/auths-gateway/src/audit.rs","sha256":"0edb2037eb7b5d6f13acfce85c54f62a82bf7fdd31bc7e626c4fec183cef61dd"},{"path":"product/runtime/auths-gateway/src/audit_tests.rs","sha256":"990969384a52d75bc2489d9d412a9e7dd814bca1c8f65c701d6205fae62a15d5"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway-harness.rs","sha256":"12b0c24d36b2e6a3be392d3c081a783b355fdd67dc5b54bacc0410e803116b8c"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway.rs","sha256":"2a5d64c1f8a845d4a073ce12ed7fa23ee7db515b2d356eeae774b1f670e056fa"},{"path":"product/runtime/auths-gateway/src/binding.rs","sha256":"663b0ce878319511aa7d05722ab4ab2fa9be18817884ffb2ee9f131ff1e382d1"},{"path":"product/runtime/auths-gateway/src/bounds.rs","sha256":"38251ad6f22f9d07ef9a219c79fa265ca36f1526eca5f147d7efa46b52ad609d"},{"path":"product/runtime/auths-gateway/src/bounds_aggregate_tests.rs","sha256":"ab34f227b7c8692ba1da88ccb32bb3687a66adf8353d8282fae905d4a88eb612"},{"path":"product/runtime/auths-gateway/src/bounds_tests.rs","sha256":"74136bc570da7b9338b5a1a1ed9d3fd892c55135160964f9d3ac0e2cf5741375"},{"path":"product/runtime/auths-gateway/src/commissioning_budget.rs","sha256":"fab29da3269438cc62330f3eab7b5bd4dc482b4db8af243aae47df5d3aa1deb8"},{"path":"product/runtime/auths-gateway/src/commissioning_budget/tests.rs","sha256":"ad182c391b70450582c6ca06e3dadc221409bb3cdbc3c7668dbfc7fbedf63505"},{"path":"product/runtime/auths-gateway/src/commissioning_floor.rs","sha256":"7fa6991c5ccd5ae1403be84b3da390323fab09f36e15ac01fd7a38ea350c6fdb"},{"path":"product/runtime/auths-gateway/src/commissioning_floor/tests.rs","sha256":"5f7868252dfccb787d26f63ea6d5c3701c72d52c0ff0bc656dd5895f8cbed551"},{"path":"product/runtime/auths-gateway/src/commissioning_session.rs","sha256":"24b48d5eaeaaa3c620e2dfc7ee1f9255fc4519a1eb404b8608cea7af6a910ee2"},{"path":"product/runtime/auths-gateway/src/commissioning_session/tests.rs","sha256":"6f8aad6dae4888c147076937c9ec0968e5b5eedde71d4cfcce0d988bd56b83ec"},{"path":"product/runtime/auths-gateway/src/connection.rs","sha256":"7b5d049c258a26ed1c93ecf860f51d051a8a65f9b93554af0b1ea93862398ec9"},{"path":"product/runtime/auths-gateway/src/credential_journal.rs","sha256":"7297fccaee5cd8622928e8e0a42bba50da7941970a6f682ecd300c41ee6509da"},{"path":"product/runtime/auths-gateway/src/echo_verify.rs","sha256":"6d453051665f823abd7354d5c50031d9524cf47d6092d2f09080ae814e3b9575"},{"path":"product/runtime/auths-gateway/src/engine.rs","sha256":"3ae83ee8eef51082084cc047b4f6b0eb26dd33f711cf5c415572366e716257ac"},{"path":"product/runtime/auths-gateway/src/fuzzing.rs","sha256":"ed3b0028487eb546a3b0a91d115aa8f18bcea324b61620bfe8e35a9e6ab18758"},{"path":"product/runtime/auths-gateway/src/generation_floor.rs","sha256":"fe1510ec96ce0f67e9a78edbfa94b33eb7df64c0ac4d0a67901124dcd0164777"},{"path":"product/runtime/auths-gateway/src/harness.rs","sha256":"c87e479f3eb281960f6c9c80d43c7560d7ccb654b0154ec823d3fcec4884ac05"},{"path":"product/runtime/auths-gateway/src/lib.rs","sha256":"47214352c400c50bd7c5cb54c132218960ce2f5dd0285c1dd9dcdebb4651de3a"},{"path":"product/runtime/auths-gateway/src/listener.rs","sha256":"aa08239bcbc1fcb55e8a212fbdf6a84f12985b0d436dcb51dc58b06e59e435f2"},{"path":"product/runtime/auths-gateway/src/observed_tests.rs","sha256":"a22be071695f89ca2578a4d82fd80d9cb82289213c9bdb8f0470f6b2dc3d9201"},{"path":"product/runtime/auths-gateway/src/observer.rs","sha256":"562ffcaea071c3856e0708dc2fe33516917e145d2438aabb75af0a2b6ba01046"},{"path":"product/runtime/auths-gateway/src/onboarding.rs","sha256":"0dfd7d67e7f02f18a28d1c86ca1b7751d7463f5efcdbe3825de0ad8cbccb3891"},{"path":"product/runtime/auths-gateway/src/operator.rs","sha256":"c3c36954a3e86723df035b47f43b85fc8ab3a6292983522b6258d5c6b4e6c4e4"},{"path":"product/runtime/auths-gateway/src/pending_vectors/attempts.rs","sha256":"47ef3c8cb1c5504d47ae9a0088705ce6715fe86bac1671a34a56fb38a64d0dd3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/bounds.rs","sha256":"e612217307e1da5b0eb5ee6582a7458bb064b8aa8a529fc6555b1b334127ab68"},{"path":"product/runtime/auths-gateway/src/pending_vectors/codes.rs","sha256":"e00670a5ef24eb856cc2c6dcda8e5a263842f55c76bb939c0c27bd9df37e5522"},{"path":"product/runtime/auths-gateway/src/pending_vectors/keys.rs","sha256":"f84c56f2ea9cb34b2b79c72d13fbf2c6585010ec1ed450af58a78c80c1ea1edd"},{"path":"product/runtime/auths-gateway/src/pending_vectors/mod.rs","sha256":"5de8340f0ef71a0b57a09e323fefe473d3160c6ae952b9ba46f714825fbacafc"},{"path":"product/runtime/auths-gateway/src/pending_vectors/outcomes.rs","sha256":"8ec07b9511b48913af36ac999d2aa0e82924289f6acb23ddaeb9f00f99815166"},{"path":"product/runtime/auths-gateway/src/pending_vectors/production.rs","sha256":"772d032e0a0d9c924fb6d6c188528db85a97e71c9e466ddc19eee277baf83614"},{"path":"product/runtime/auths-gateway/src/pending_vectors/recipes.rs","sha256":"51693208270231c25c3aef2a32151d5962114c71e86b88cb9df83181c7af83d9"},{"path":"product/runtime/auths-gateway/src/pre_entry.rs","sha256":"06ea78ca140468bfaba17d9ab04912ad68673954c3203c98fed28272ff2a00c0"},{"path":"product/runtime/auths-gateway/src/property_tests.rs","sha256":"939c081e2e154aaf10186754044bdd65608932c899b970a04a71d0afaa999a93"},{"path":"product/runtime/auths-gateway/src/qualification.rs","sha256":"b239aef182ddf836dad234f2d5c3d2db2c13f14f394b46bc2fb940fc3dff90bf"},{"path":"product/runtime/auths-gateway/src/qualification_simulation.rs","sha256":"4ee7cadfb5f46a92713c80f3e55f499cb074d04d8b21ea89d57762af38642bfa"},{"path":"product/runtime/auths-gateway/src/qualification_tests.rs","sha256":"a9178a2e58eea459d5e5dafc53a3999ea7c84dbbffefe6e5eb1f3d098827f028"},{"path":"product/runtime/auths-gateway/src/quorum_tests.rs","sha256":"a78380b019104d688c11a4410082c7e08ded3106aab099954c4f8a1b4ae0fd89"},{"path":"product/runtime/auths-gateway/src/readiness.rs","sha256":"911c3f11892f94641574375e2da4c671c802738f71082f12c39832331052d43d"},{"path":"product/runtime/auths-gateway/src/recipe.rs","sha256":"fecf9af67e7afc48d080e9f8f55f8ce28e49d0e08988717a27908bbda461d6b6"},{"path":"product/runtime/auths-gateway/src/recipe/lower.rs","sha256":"8088b8751ed831dbb48247af953c6290ac95e2a438ccd5bd65eff54be06a1fd1"},{"path":"product/runtime/auths-gateway/src/recipe/review.rs","sha256":"c3eb7d9fdd98dacf52750b14b67ad7b7faaecbbdeafff1e0b049f67d0a2d0139"},{"path":"product/runtime/auths-gateway/src/recipe/runtime.rs","sha256":"c286f0d15f974402822c0810d8e97f98411dc1c557755cc23e540d85e2bb42d9"},{"path":"product/runtime/auths-gateway/src/recipe/source.rs","sha256":"1af50298fb1461e1b24cbdf560d43124d6b1c4c529586c911b1c4797214a69ff"},{"path":"product/runtime/auths-gateway/src/recipe/tests.rs","sha256":"aac551a2481bbc60864c64079bc667dcb232e45a0f41a04073ed84ab5dbe1fce"},{"path":"product/runtime/auths-gateway/src/recipe/validate.rs","sha256":"3711b17605cb7b0d639bc1b180449231f5882a306cab20e2c7782155cc63b0d4"},{"path":"product/runtime/auths-gateway/src/scenario_tests.rs","sha256":"a8ea1e3a7bf6b0274455bd790ace3ffb9c8716609cde92248920945c61634685"},{"path":"product/runtime/auths-gateway/src/separation.rs","sha256":"be9306848ca5d801767cf6aa14247c8618312ef0e202f00ce0c24c4844491061"},{"path":"product/runtime/auths-gateway/src/simulation_attestation.rs","sha256":"88705e5d45415f760f1e3c3a065c35c48f4f4065bf7b3feb7882246983814d6f"},{"path":"product/runtime/auths-gateway/src/store.rs","sha256":"884bcad4d70d53e12eae9c8517f6ecd0643068ee0be0370015119d04d6cc2516"},{"path":"product/runtime/auths-gateway/src/store_testkit.rs","sha256":"88d82fee42f1b8ef521e8deef0216e938ebeaad822eb2f5020e70b89d145ea70"},{"path":"product/runtime/auths-gateway/src/submit.rs","sha256":"fe2eacb5ad8152eeecbd232c47a356fc72db0098e34fda99532bdf6ef0cf895c"},{"path":"product/runtime/auths-gateway/src/support.rs","sha256":"9fd979029793a22b15d9776a7fc172476fd7c126a80d4080c65d720845becbcb"},{"path":"product/runtime/auths-gateway/src/transport.rs","sha256":"be2c6dc75b8daec110bf8749fedc3823f6067d40b999aa3eb21126896a97d3ad"},{"path":"product/runtime/auths-kernel-runtime/Cargo.toml","sha256":"926bcd0053e5edd703be8f0027ad009e2982db013c8174c1366edbf38b48087d"},{"path":"product/runtime/auths-kernel-runtime/src/lib.rs","sha256":"7108faae9ca4bc32dc093ddaf885ac8f74f3c9b8d317b7c7d0ed00d1d0ab5972"},{"path":"product/runtime/auths-lifecycle/Cargo.toml","sha256":"c5053c705f8d5554b44e432fe75287a2faf11d644e5a2552e45ad6cd94176af5"},{"path":"product/runtime/auths-lifecycle/src/codec.rs","sha256":"51c4b746749150e8bfcd8ff972b3f6c1ef40bec15583448ec1b471d9ad737dc0"},{"path":"product/runtime/auths-lifecycle/src/digest.rs","sha256":"55282cd7d8aba37713c2dcb5357c9877819edb72a30eadefb860d28d7d3a3eb7"},{"path":"product/runtime/auths-lifecycle/src/identifier.rs","sha256":"31620e8c16de68d3d2d3b84d6353c1a5b9d4151d8247f91fa389b906a8e660f1"},{"path":"product/runtime/auths-lifecycle/src/kernel.rs","sha256":"2abb8c094b36d35b364e74d78091d14c5d6f3d1eb6552cca3b5538dbd017ce23"},{"path":"product/runtime/auths-lifecycle/src/lib.rs","sha256":"afe5a345cd309b5a4f08ffba3170a6d7f16ff914892b3f2006d5208ed24ec736"},{"path":"product/runtime/auths-lifecycle/src/model.rs","sha256":"1af12bbeeeaa65ec02ddcebd7d2c8c92ec1e339fa40ae85b45ab9b01a722a4fa"},{"path":"product/runtime/auths-lifecycle/src/operation.rs","sha256":"78e6d05fcf5d7ea4f148032a3fa26fdfcab77eb346019effe927b08e0d64d732"},{"path":"product/runtime/auths-lifecycle/src/registry.rs","sha256":"53495fe6f7a77422593a41623e28716f1c140dcc1e00f87f6b0ffbfb93a5ef90"},{"path":"product/runtime/auths-lifecycle/src/sealed.rs","sha256":"2e0c03b5813c926c159598bb7890d1523825edbe57cd687d42a5dfb3374a0c19"},{"path":"product/runtime/auths-lifecycle/src/test_support.rs","sha256":"221d9a5c5ef8e1f9f8fd66927484eaf813571d0568470278ecd8fa08a5eec8cd"},{"path":"product/runtime/auths-lifecycle/src/transition.rs","sha256":"011805a28efdd541f44ccea54dd0e34a1e58f4004447ee58013703b4fb6b2822"},{"path":"product/runtime/auths-runtime/Cargo.toml","sha256":"dd29d80a8b4bb56c869f036a6c9998f6e6d1c0383ac5dc03fa42b24abe2a7ff7"},{"path":"product/runtime/auths-runtime/src/lib.rs","sha256":"132ca03d58c14905d3a822a4972f42a22a5ad33a45f2ba9ca44f3a57d810b4b0"},{"path":"product/runtime/auths-runtime/src/production.rs","sha256":"fd4eff4270c571c10fcff6cf27df28961ebf074de8a1a028f500fda1ca376820"},{"path":"product/sdk/auths-approval-quorum/Cargo.toml","sha256":"df904971fca87a24194c5816738a331588fe8f164acb5d70839a35dca5f57114"},{"path":"product/sdk/auths-approval-quorum/src/lib.rs","sha256":"72e4086088a1c0912e4e1a9e980f26a5c280bf5ab16ea39c9f0f58d5096ac2ce"},{"path":"product/sdk/auths-approval-quorum/src/remote.rs","sha256":"9fa029c7c63003adf260f8aec55160c545681c60c1bace0d934e7525862aac7b"},{"path":"product/sdk/auths-approval-quorum/src/remote_tests.rs","sha256":"8a09ce17cfee82a035a74edd535f3ebeb3db0e078784740d3997b17dbdb10197"},{"path":"product/sdk/auths-approval-quorum/src/tests.rs","sha256":"0acbf12be3e497dcc6c2d8f29c9af3b1a7ed8e11b75f6399570d4f217a785060"},{"path":"product/stores/auths-stores/Cargo.toml","sha256":"a32c4b76d17b264be5d40d24497ff237e1ed87822e8bab86229b3db93106dbe3"},{"path":"product/stores/auths-stores/src/gateway_attempt.rs","sha256":"218841602d3d9b23b44625f50e5b54cf275ccedc2d5c89f02d2482b8524472af"},{"path":"product/stores/auths-stores/src/lib.rs","sha256":"e721262edf8a9ab5568ddc27639176312d4a366203b5f73e2d7c11fde2c554e9"},{"path":"product/stores/auths-stores/src/lifecycle.rs","sha256":"3f2cecfda13fdcd7c4a944518646bcc8abd1237f900c0332d5822281f8f9f1cd"}],"schema":"auths.gateway-semantic-closure/1"} \ No newline at end of file +{"files":[{"path":"Cargo.lock","sha256":"0e75e2fdef44e79e57797ac6661295ae58ddb8de4a1990a6fd22ce6c54f78604"},{"path":"Cargo.toml","sha256":"6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24"},{"path":"core/adapters/auths-did-keri/Cargo.toml","sha256":"86ba3e3f9a0a70d970568bfb3113b7ba7bbdd81c3eebbb52743dd574a0c0ecaa"},{"path":"core/adapters/auths-did-keri/src/lib.rs","sha256":"a75674842f8a7142004369ccd206ab43e476459293f0ff4bed4d4e659031b3e3"},{"path":"core/adapters/auths-did-key/Cargo.toml","sha256":"d5a3ae07ecde83f91eed4c3785051dd0f44eab6c891754f3309b6b40596707d7"},{"path":"core/adapters/auths-did-key/src/lib.rs","sha256":"b76a3f4528a725df53cfa9242e6e414e1d26caa48468aaed497e28b121f4497c"},{"path":"core/adapters/auths-raw-key/Cargo.toml","sha256":"f49616bc18c19e6aaa7e6a02ccebcdb9f5c1422c1278ef9869e0dbf22ceda7be"},{"path":"core/adapters/auths-raw-key/src/lib.rs","sha256":"45eec1b295dac3bed65cd79c942870b926b06b3f5d38eaebaeb6140ac69315fa"},{"path":"core/crates/auths-algebra-kernel/Cargo.toml","sha256":"0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba"},{"path":"core/crates/auths-algebra-kernel/src/generated.rs","sha256":"ae4bcbef42a408c7ffa0c6a74a42f7de177a6f14479e51d205acf830bda05960"},{"path":"core/crates/auths-algebra-kernel/src/lib.rs","sha256":"6654667eeb9b353d6648954c9fd2e8838462a82ce6b2803eb49e1366892c68c6"},{"path":"core/crates/auths-assurance/Cargo.toml","sha256":"afcb12a97ddd09d7a264b9ecd3fcaefc865ff2c9b4539ee85b00883420ba333a"},{"path":"core/crates/auths-assurance/src/lib.rs","sha256":"0fb2ec844d674b25a9e20b1601452c89c2454901fa506adfa9bb38ef9a7fa213"},{"path":"core/crates/auths-author/Cargo.toml","sha256":"1e6f0e3bc079ddb558decf0db26b291c6e72fc47327b6df1b7650d41689b215f"},{"path":"core/crates/auths-author/src/lib.rs","sha256":"e14475f2f49715a1869d5fa6b11ff1fbb72497e39097e09f833b0bae7e5b3f2b"},{"path":"core/crates/auths-author/src/observations.rs","sha256":"dda7d6bfa6f4bd7e95a480ca283c2c0e996f69c5c15cb0c7197af328131a7066"},{"path":"core/crates/auths-authority/Cargo.toml","sha256":"4f68212938029f79ebd857b4f3038494eb85d0163d49f07e51376715cf959815"},{"path":"core/crates/auths-authority/src/lib.rs","sha256":"da88d5194de4e17449e69972c0fb042afa3c39798a8f570f30771e77c384f1eb"},{"path":"core/crates/auths-codec/Cargo.toml","sha256":"e20e51826e17814effd9d8925d18d5fbdd6c0d37bf50231e743ec2611314722c"},{"path":"core/crates/auths-codec/src/approval.rs","sha256":"fbff43bf4d57f69f8b7738a8647751cde75c5a932dee65d924a1fe9c7202f91f"},{"path":"core/crates/auths-codec/src/bounded_policy.rs","sha256":"d21f6728be2d8a04b6d94921f2b683f7e61cbb42e0ac6866f1c88a49caa534c3"},{"path":"core/crates/auths-codec/src/decode.rs","sha256":"ba2999584cdf53b1b517ecb9c7ea50d39efee17c666a9a38e2ad1ac94379f778"},{"path":"core/crates/auths-codec/src/encode.rs","sha256":"8491192053e2e15d62b4d2a491de22405b7487ead69ab6f6bca40669ce7ca5f7"},{"path":"core/crates/auths-codec/src/error.rs","sha256":"fecb0737c16deb42d859f1dc7727c698438d9ac12064fd99e0024629642c390c"},{"path":"core/crates/auths-codec/src/hash.rs","sha256":"f88e111f1dbb2cef6b7b5e9c948cb45ff92e366710c8a5f5c636138aa748479e"},{"path":"core/crates/auths-codec/src/lib.rs","sha256":"3b0e5c94c6f34f750b88a9333e1d5c8145746d845d3a23e0d2f61807cf592ea7"},{"path":"core/crates/auths-codec/src/observation.rs","sha256":"38328b0c71ff97a4196eeade8b4faa889527ff1f80bb168468bcd49082a3987e"},{"path":"core/crates/auths-composition/Cargo.toml","sha256":"331e13025eb82588b5269ed3975929eb41c823d588c49e4c296273d85c6fe80e"},{"path":"core/crates/auths-composition/src/lib.rs","sha256":"e42e3b0b6a9985b73c533aeb23799c638979aa27a9ce7d0f10a8d60340570fb1"},{"path":"core/crates/auths-model/Cargo.toml","sha256":"565c15302b0cc9270db1e28efa3862804846850ba933cc17aea8abcec4a65987"},{"path":"core/crates/auths-model/src/approval.rs","sha256":"54cf44a9ef747ec21546a4086aecfb130bc7803b0d646430e6082df51e6e305f"},{"path":"core/crates/auths-model/src/bounded.rs","sha256":"f90496abc0a06c028b4d850af6ddab7d850bfafeaa3d042f1b1246a41d8bbbc9"},{"path":"core/crates/auths-model/src/bounded_policy.rs","sha256":"306a8f049cc7cfc7635fe0e4de47eb7813eed63d3c14c3be2b51586aa4eea450"},{"path":"core/crates/auths-model/src/lib.rs","sha256":"e7cfe6bb9574c6b016aa63e70658c31e0b90903ec6479a49f4a2ceb64f5bad97"},{"path":"core/crates/auths-model/src/observation.rs","sha256":"b3ed3e3cc090afca2896a7d3de7988afccc1ee1ea0ebd91b51a8bc0f20ad8dbb"},{"path":"core/crates/auths-multikey/Cargo.toml","sha256":"858756c1197befcada06134742bffe8d58cf674cadd6c046bf710570e96efaf2"},{"path":"core/crates/auths-multikey/src/lib.rs","sha256":"f5177fffb11e40eeaaa665ba886c541fc1f24d5eacdd6983fb03dc20148733f0"},{"path":"core/crates/auths-ports/Cargo.toml","sha256":"596a9b0f5af3717c16a6d13f7054d8a106bcd9f01f5f72c2235dd2afcf0ab16c"},{"path":"core/crates/auths-ports/src/binding.rs","sha256":"a16c012d40aa4249e3ec54372b9611006d0bfe8c7dc3c741911c2194ad17736d"},{"path":"core/crates/auths-ports/src/diagnostics.rs","sha256":"aa596572503b5a65a918bb2ff38281c144ff53821ee914e9325c852828d852df"},{"path":"core/crates/auths-ports/src/lib.rs","sha256":"8da1debf86f9532df0660155d04298beb1ba3a1204508f8586e2e67cd2fb3449"},{"path":"core/crates/auths-ports/src/path.rs","sha256":"b68fc547b4e4d97a60cbbc1cc1939fc6b34a8233b81f840bd396914a707e3ea1"},{"path":"core/crates/auths-raw-key-core/Cargo.toml","sha256":"98c0bc8527a537512e43a74dd6ba9658c6f0cdc16610cf938e3f9b43785d836d"},{"path":"core/crates/auths-raw-key-core/src/lib.rs","sha256":"98c0500c41697aae28708ad0bf970b9a97583d96a3d2c18d23e7fa351e0f7d12"},{"path":"core/crates/auths-registries/Cargo.toml","sha256":"590e49e58b0622d9d6274fea46796dcdb07dec9550eff295cce6a6427ffa51e2"},{"path":"core/crates/auths-registries/src/lib.rs","sha256":"450d3886d85ee333b7e046317fb5b47cde62483d5f3e41d46265e2caf4c373ec"},{"path":"core/crates/auths-registries/src/template.rs","sha256":"1224039dd2b3ce6fa8357613d8cafbae40400493da7176da202b9ade62fa05e4"},{"path":"core/crates/auths-signature-core/Cargo.toml","sha256":"6bee2230eb30af1be0bd5c2d57bd3e1903497a70028d47290d4ac6e9e0e8bca0"},{"path":"core/crates/auths-signature-core/src/lib.rs","sha256":"6e3f9311ded5e49ea50d445eb21e6d8fa12442aa4362a73e0cb6fda15b7cd865"},{"path":"core/crates/auths-signature/Cargo.toml","sha256":"7f7b5682466ba439d8c59579022cb61068cad9fb4bd2d73e1cc21327c902b450"},{"path":"core/crates/auths-signature/src/lib.rs","sha256":"b3d9ac4cc3ba0797b9e1c09f2d6ac05089b25dac4e285a5af28c0165b33d925b"},{"path":"core/crates/auths-verifier/Cargo.toml","sha256":"c43358e06a33324b41a8b93e5cc7279c55f7d21f1f6cfaa539a3fc7b4c27a38f"},{"path":"core/crates/auths-verifier/src/approval.rs","sha256":"c3cae6a49e169051eb555bb092b1069a4d422516d6a2114623a89e5f31ff923f"},{"path":"core/crates/auths-verifier/src/causal.rs","sha256":"9635230f33b13a263573d319ac8a1976addbcc07677514a43e3c7bf28dc04587"},{"path":"core/crates/auths-verifier/src/lib.rs","sha256":"f22dec38dfa47ced8da4f605390da8453273bee1da010f57fd1fdfcb10e0b389"},{"path":"core/crates/auths-verifier/src/observation.rs","sha256":"0bb07f06a0f9524c88427df1c972b1de8ba038a9eeeb15d3134c25125ae84b1e"},{"path":"core/crates/auths-verifier/src/trace.rs","sha256":"2213d72023a1d9e0413a2cf2c51c3dad9e04775d86033a0caaa9d29a8f0036f8"},{"path":"exchange/crates/auths-proof-exchange-model/Cargo.toml","sha256":"34b2db64f93a288e942b5a3918d28cdcbef906e0dc9074ce848018d3d5f7a1fa"},{"path":"exchange/crates/auths-proof-exchange-model/src/lib.rs","sha256":"49fac5aff2339d3a57c41cb8bb2a82852538e8f77ecc4b157c88e264ff31fb55"},{"path":"exchange/crates/auths-proof-exchange-port/Cargo.toml","sha256":"7ff660f1b7579dc570c791090aeb450404fbbf44c92781e289f5ccdde746d739"},{"path":"exchange/crates/auths-proof-exchange-port/src/lib.rs","sha256":"b408fb40c6432edc1facb3d8b3e9433a033f8dc73fe2e0ba5a88c972ca675021"},{"path":"product/config/auths-config/Cargo.toml","sha256":"e4b568ab9f6d84f7d7e6d66443fe825f360db9c27bc7c31d6ddc0647ba3ab304"},{"path":"product/config/auths-config/src/lib.rs","sha256":"fecf00ea65cef9018fda9af2063326d7065b869266d0d9e73a4f06816f1102cc"},{"path":"product/errors/auths-errors/Cargo.toml","sha256":"3b3a199b6460ba75bda84475bb5accd35e1485448a3981038db85bf4772dd350"},{"path":"product/errors/auths-errors/src/lib.rs","sha256":"7feeb9069fa4003f94f1f07c1c94619cf1c883e0dbaaf2187f04d0f742264bdd"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/Cargo.toml","sha256":"716f1f2a117d6d69d8effe9ee9057e24ba3502f20af6a602b06facb638cdabed"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/api.rs","sha256":"9ea61dd7ddd93282b073b98e453e6b75b26dc49689c04e9782435d06a3a09e48"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/clock.rs","sha256":"73f0a6e0f5903883329fa6683f5888288f759512ac69e5c87efd2b6b87f7d79f"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/http.rs","sha256":"14c1fce14e24c984b2a275563a29b6326fb08367922b6e8d37ba38b9cb81aa2b"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/identity.rs","sha256":"186de11230c8b33375951c4368609f8976bf9795f171af3fd7fac26207a94361"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs","sha256":"0b4617d044f5254a5ab22f5a2578f91cc025206a8c1845be39c1c56dcdf7a5df"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/names.rs","sha256":"41bb23572d6002e23ee103d6fe70ecd68764861c6f2e48a1c53af998270a4afa"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs","sha256":"39fed883f4802e68d3b41a68fea0aba0737810996b33d13577de70faba004c29"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/store.rs","sha256":"fc60ee9c49b2f4f063c449b4c78100c5c4872779e94ca168f796603b380ef6e4"},{"path":"product/integrations/auths-custody/Cargo.toml","sha256":"1e14034185ad1ec24a977fd5f41d0abee219606245c046ce2a82287fadef448b"},{"path":"product/integrations/auths-custody/src/conformance.rs","sha256":"8ed1afd58f18fc6becc268908aa6419c9aa404c79da0197963eb2599df44acf6"},{"path":"product/integrations/auths-custody/src/key.rs","sha256":"70cbb0fd21b6f5652157845a22c35be2d0f6c05b3d138fc4b9bb6dbdc3d81c40"},{"path":"product/integrations/auths-custody/src/lib.rs","sha256":"8ee593c1f59b0fd2126bdda9138026f5bc531beb64d4489a99785842e7b98b43"},{"path":"product/operations/auths-operations/Cargo.toml","sha256":"73dde1e914ba5e1386f8d49c0d730423cc72ae77ec44c6554a6a75cc8e8922b1"},{"path":"product/operations/auths-operations/src/explanation.rs","sha256":"b4a39bcbd5712cb9e735ee7deeb281f3fa6af5ddca973735bf3d87dce427ef11"},{"path":"product/operations/auths-operations/src/lib.rs","sha256":"3f401a56555113b98f57bca172a2660eaecedf76247b83a3fdbb089c133a29cd"},{"path":"product/operations/auths-operations/src/render/json.rs","sha256":"2ae042639960afee123730e945d373bc5dda1d2b3af20ae16c939a7e99b9e418"},{"path":"product/operations/auths-operations/src/render/mod.rs","sha256":"b3b7f6fe473f49227ace5a68bfc3d8dc14b5db8dd9888fd9e207070337b1b8bf"},{"path":"product/operations/auths-operations/src/render/text.rs","sha256":"f216cf3bdb00e264523271b16e7059535ac6b1aabf271cebd7935af155e4bfec"},{"path":"product/policy/auths-bounded-policy/Cargo.toml","sha256":"babd5d200923137ead71d8c2528f847cea323ce98da942a1320b054436612c47"},{"path":"product/policy/auths-bounded-policy/src/arithmetic.rs","sha256":"75e43c5d4eab8d1f71c1daf53839f5f9fe45a400afc1f63a30c6f55ce3632627"},{"path":"product/policy/auths-bounded-policy/src/commitment.rs","sha256":"c5706f2d583454e1a7f570f7ada138d4d864bef0205dfae7c1296774f396bb3f"},{"path":"product/policy/auths-bounded-policy/src/eligibility.rs","sha256":"c9acdfb793074e687fc36efad506be27dbd99ffbf40387bc66c8de39ef238432"},{"path":"product/policy/auths-bounded-policy/src/identifier.rs","sha256":"0006a32bae9eb16c4178cf797df418d2b0a781f2bc6474b741dc1a908141831c"},{"path":"product/policy/auths-bounded-policy/src/kernel.rs","sha256":"99187c28b161ac70bee1afed60711f7f645adb4d1671a01863f9849b369811d5"},{"path":"product/policy/auths-bounded-policy/src/lib.rs","sha256":"76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c"},{"path":"product/policy/auths-bounded-policy/src/receipt.rs","sha256":"3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad"},{"path":"product/policy/auths-bounded-policy/src/registry.rs","sha256":"4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0"},{"path":"product/profiles/auths-profile-api/Cargo.toml","sha256":"7ae85761f58625b5d678f961fd052eebf3e000ef565c7312e3ac857763c0017f"},{"path":"product/profiles/auths-profile-api/src/lib.rs","sha256":"a194b82b20bf8aa864c2334ef6c6aec30b2154ded972862252d5dcefa488ab95"},{"path":"product/profiles/auths-profile-mcp/Cargo.toml","sha256":"db264fc25242f7b7e4133cbe5782545b3107b406c87168ae072683cfb59eac66"},{"path":"product/profiles/auths-profile-mcp/src/arguments.rs","sha256":"a5de696586d507e2aee4a49fee99ef1ef4c51a2e46603f8838f1af6d9009833f"},{"path":"product/profiles/auths-profile-mcp/src/lib.rs","sha256":"d0f8b733a09ef8408336cdebc8948d6a5861012ce6878598b11be7084dfd4280"},{"path":"product/profiles/auths-profile-mcp/src/session.rs","sha256":"166c281fa66333388e4760d6098dad02d3359e1d5de4b8f93312c014f97abb03"},{"path":"product/qualification/auths-recipe-qualification/Cargo.toml","sha256":"b7b15b30b9a3d96d4f089d514266d3a892de6608d30707aa44be31cca89ca9fe"},{"path":"product/qualification/auths-recipe-qualification/src/canonical.rs","sha256":"30a9b50777f0dcb4b606abfee2467d5a975d9f6ad941ab6c13ca3df5b359f667"},{"path":"product/qualification/auths-recipe-qualification/src/closure.rs","sha256":"0ad6aee9bd981e2863fa725f209ec84031db2ff12f4c7ac3aaf5120f0bb86039"},{"path":"product/qualification/auths-recipe-qualification/src/commissioning.rs","sha256":"66ea49f96887c4642139a48d259c270816e2267ee8cf6344a1340fe47afda9da"},{"path":"product/qualification/auths-recipe-qualification/src/commissioning/tests.rs","sha256":"5a226725c2ad7ce920d0bd62d427185e007f4d0949b0f0ec1260aa161d3114d0"},{"path":"product/qualification/auths-recipe-qualification/src/error.rs","sha256":"52d5cf720a1e4579008fdda90a3ac2c31f0b8db57985f121f65e54b4da2b7dd1"},{"path":"product/qualification/auths-recipe-qualification/src/evidence.rs","sha256":"ba45a7409d67a8af26ab811af306412014557477a101ab2a8eb0faf8f2bd4b91"},{"path":"product/qualification/auths-recipe-qualification/src/ids.rs","sha256":"e81a906d571497ab2da753e1532d4443706410e0b75fdd59a7d2d788c7aec403"},{"path":"product/qualification/auths-recipe-qualification/src/launch.rs","sha256":"41f2e2de90e1e7d6440a66eda3eb9bea8d5e0741bc232305a76a363ab5f813c1"},{"path":"product/qualification/auths-recipe-qualification/src/lib.rs","sha256":"7d26c5bfe9769daebf90c5c2280e0d75742e4cc70d0e608408e0665e3f516a2b"},{"path":"product/qualification/auths-recipe-qualification/src/model.rs","sha256":"3484eb0ec287b23d4682ade7b1b0f8d1335985b3fb180f06fc28716076957d5f"},{"path":"product/qualification/auths-recipe-qualification/src/release.rs","sha256":"ec478e53f70052e566aac7e15be2f9e1b1cd46837ac6990ae955fa864d311586"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/mod.rs","sha256":"fa23a962fd90331152eed5edbcdf271955f7aed79b8da1e065bfe69a20b487a9"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/schemas.rs","sha256":"c59feec2805621f341a90f81fc005e2c12f7a70f9d264fdeacccb2be4fe1c046"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/verification.rs","sha256":"6a6b5834c5dae10af1ba8939b2deae43b85db71544dc8f077ff63b7fe68ac8a8"},{"path":"product/qualification/auths-recipe-qualification/src/verify.rs","sha256":"2ec2784435d11e07295de77b2ee1b2c48b2fcf9609a00454c6e7374b621aed5c"},{"path":"product/receipts/auths-receipts/Cargo.toml","sha256":"6001fa1375899953aafcb07c23a6da0c8f57ea7ec08bb9c950b12a60a8cc6f0f"},{"path":"product/receipts/auths-receipts/src/disclosure.rs","sha256":"ba9ed439be0a320c8a01f5b6e9b51361c1a37e076947490d8e4a484ba6bb119c"},{"path":"product/receipts/auths-receipts/src/lib.rs","sha256":"547a57c4160256719cafb7d0ab972d9fc80b0da14fbbce4148c70c414070ff36"},{"path":"product/runtime/auths-connections/Cargo.toml","sha256":"babeb6e1dda3dfb66291713ce1e43dce5c349833d0b50ea4dccbf986030026b2"},{"path":"product/runtime/auths-connections/src/credential.rs","sha256":"82921413bb053f0f6c7931fbd4e6a86c8cc1d8c6b51debd9c2cef33a8d5b1c51"},{"path":"product/runtime/auths-connections/src/kernel.rs","sha256":"a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8"},{"path":"product/runtime/auths-connections/src/lib.rs","sha256":"79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22"},{"path":"product/runtime/auths-connections/src/model.rs","sha256":"de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77"},{"path":"product/runtime/auths-connections/src/registry.rs","sha256":"e57640e003e72ad3235c567c2bb944a262bd64e673f023b62ea091094cc7e946"},{"path":"product/runtime/auths-gateway-kernel/Cargo.toml","sha256":"34f864e67656af4ac7e5c7a347a23f01fc8ab31365b8e23c0ef474483b14a183"},{"path":"product/runtime/auths-gateway-kernel/src/construct.rs","sha256":"e9d65744bae273d65face4285e5d2da75c06a92ab48f7b8333d496604e31c63c"},{"path":"product/runtime/auths-gateway-kernel/src/lib.rs","sha256":"cfda6f8453426564c085475f183b6f790b438768a19668f1b65d33ba59dc8632"},{"path":"product/runtime/auths-gateway-kernel/src/order.rs","sha256":"e0045f877c4b7fe3860c291039853885064ddcdebba7c9b345ab65e81e646dda"},{"path":"product/runtime/auths-gateway-kernel/src/outcome.rs","sha256":"e9785b1afe70788c89b51b18655bcd5acff7b0c8e3d12fb79c6f05a202e67e6b"},{"path":"product/runtime/auths-gateway-kernel/src/ratio.rs","sha256":"7ace22264812e6fc1ef3a62afee402cf43494bb71ae0d3de219ad1b39d690bcb"},{"path":"product/runtime/auths-gateway-kernel/src/recovery.rs","sha256":"9f46dcd1685ab6e4d1ba04a3fc286a9f3afee8fb47829be1fbc670a7926a2dc6"},{"path":"product/runtime/auths-gateway-kernel/src/transition.rs","sha256":"cefb8f01d915880f6921f2501ff881ad94b9de61072c34d9cd19220992f97374"},{"path":"product/runtime/auths-gateway/Cargo.toml","sha256":"00b28be86921dcdc0ad90cce0c62c2961cafefe96ea6c2edf0e926c3d405ccad"},{"path":"product/runtime/auths-gateway/src/admin.rs","sha256":"2d5cc67afac42fbd15f36e2d1693cd1b20cedacf775040dce6ffe04ccc94c9ea"},{"path":"product/runtime/auths-gateway/src/app.rs","sha256":"6f80f63833ea0815bb44fbf3b0cc54624a08e9fb578b035819f2980dc04e8256"},{"path":"product/runtime/auths-gateway/src/audit.rs","sha256":"0edb2037eb7b5d6f13acfce85c54f62a82bf7fdd31bc7e626c4fec183cef61dd"},{"path":"product/runtime/auths-gateway/src/audit_tests.rs","sha256":"990969384a52d75bc2489d9d412a9e7dd814bca1c8f65c701d6205fae62a15d5"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway-harness.rs","sha256":"12b0c24d36b2e6a3be392d3c081a783b355fdd67dc5b54bacc0410e803116b8c"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway.rs","sha256":"2a5d64c1f8a845d4a073ce12ed7fa23ee7db515b2d356eeae774b1f670e056fa"},{"path":"product/runtime/auths-gateway/src/binding.rs","sha256":"663b0ce878319511aa7d05722ab4ab2fa9be18817884ffb2ee9f131ff1e382d1"},{"path":"product/runtime/auths-gateway/src/bounds.rs","sha256":"38251ad6f22f9d07ef9a219c79fa265ca36f1526eca5f147d7efa46b52ad609d"},{"path":"product/runtime/auths-gateway/src/bounds_aggregate_tests.rs","sha256":"ab34f227b7c8692ba1da88ccb32bb3687a66adf8353d8282fae905d4a88eb612"},{"path":"product/runtime/auths-gateway/src/bounds_tests.rs","sha256":"74136bc570da7b9338b5a1a1ed9d3fd892c55135160964f9d3ac0e2cf5741375"},{"path":"product/runtime/auths-gateway/src/commissioning_budget.rs","sha256":"fab29da3269438cc62330f3eab7b5bd4dc482b4db8af243aae47df5d3aa1deb8"},{"path":"product/runtime/auths-gateway/src/commissioning_budget/tests.rs","sha256":"ad182c391b70450582c6ca06e3dadc221409bb3cdbc3c7668dbfc7fbedf63505"},{"path":"product/runtime/auths-gateway/src/commissioning_floor.rs","sha256":"7fa6991c5ccd5ae1403be84b3da390323fab09f36e15ac01fd7a38ea350c6fdb"},{"path":"product/runtime/auths-gateway/src/commissioning_floor/tests.rs","sha256":"5f7868252dfccb787d26f63ea6d5c3701c72d52c0ff0bc656dd5895f8cbed551"},{"path":"product/runtime/auths-gateway/src/commissioning_session.rs","sha256":"24b48d5eaeaaa3c620e2dfc7ee1f9255fc4519a1eb404b8608cea7af6a910ee2"},{"path":"product/runtime/auths-gateway/src/commissioning_session/tests.rs","sha256":"6f8aad6dae4888c147076937c9ec0968e5b5eedde71d4cfcce0d988bd56b83ec"},{"path":"product/runtime/auths-gateway/src/connection.rs","sha256":"7b5d049c258a26ed1c93ecf860f51d051a8a65f9b93554af0b1ea93862398ec9"},{"path":"product/runtime/auths-gateway/src/credential_journal.rs","sha256":"7297fccaee5cd8622928e8e0a42bba50da7941970a6f682ecd300c41ee6509da"},{"path":"product/runtime/auths-gateway/src/echo_verify.rs","sha256":"6d453051665f823abd7354d5c50031d9524cf47d6092d2f09080ae814e3b9575"},{"path":"product/runtime/auths-gateway/src/engine.rs","sha256":"3ae83ee8eef51082084cc047b4f6b0eb26dd33f711cf5c415572366e716257ac"},{"path":"product/runtime/auths-gateway/src/fuzzing.rs","sha256":"ed3b0028487eb546a3b0a91d115aa8f18bcea324b61620bfe8e35a9e6ab18758"},{"path":"product/runtime/auths-gateway/src/generation_floor.rs","sha256":"fe1510ec96ce0f67e9a78edbfa94b33eb7df64c0ac4d0a67901124dcd0164777"},{"path":"product/runtime/auths-gateway/src/harness.rs","sha256":"c87e479f3eb281960f6c9c80d43c7560d7ccb654b0154ec823d3fcec4884ac05"},{"path":"product/runtime/auths-gateway/src/lib.rs","sha256":"47214352c400c50bd7c5cb54c132218960ce2f5dd0285c1dd9dcdebb4651de3a"},{"path":"product/runtime/auths-gateway/src/listener.rs","sha256":"aa08239bcbc1fcb55e8a212fbdf6a84f12985b0d436dcb51dc58b06e59e435f2"},{"path":"product/runtime/auths-gateway/src/observed_tests.rs","sha256":"a22be071695f89ca2578a4d82fd80d9cb82289213c9bdb8f0470f6b2dc3d9201"},{"path":"product/runtime/auths-gateway/src/observer.rs","sha256":"562ffcaea071c3856e0708dc2fe33516917e145d2438aabb75af0a2b6ba01046"},{"path":"product/runtime/auths-gateway/src/onboarding.rs","sha256":"0dfd7d67e7f02f18a28d1c86ca1b7751d7463f5efcdbe3825de0ad8cbccb3891"},{"path":"product/runtime/auths-gateway/src/operator.rs","sha256":"c3c36954a3e86723df035b47f43b85fc8ab3a6292983522b6258d5c6b4e6c4e4"},{"path":"product/runtime/auths-gateway/src/pending_vectors/attempts.rs","sha256":"47ef3c8cb1c5504d47ae9a0088705ce6715fe86bac1671a34a56fb38a64d0dd3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/bounds.rs","sha256":"e612217307e1da5b0eb5ee6582a7458bb064b8aa8a529fc6555b1b334127ab68"},{"path":"product/runtime/auths-gateway/src/pending_vectors/codes.rs","sha256":"e00670a5ef24eb856cc2c6dcda8e5a263842f55c76bb939c0c27bd9df37e5522"},{"path":"product/runtime/auths-gateway/src/pending_vectors/keys.rs","sha256":"f84c56f2ea9cb34b2b79c72d13fbf2c6585010ec1ed450af58a78c80c1ea1edd"},{"path":"product/runtime/auths-gateway/src/pending_vectors/mod.rs","sha256":"5de8340f0ef71a0b57a09e323fefe473d3160c6ae952b9ba46f714825fbacafc"},{"path":"product/runtime/auths-gateway/src/pending_vectors/outcomes.rs","sha256":"8ec07b9511b48913af36ac999d2aa0e82924289f6acb23ddaeb9f00f99815166"},{"path":"product/runtime/auths-gateway/src/pending_vectors/production.rs","sha256":"772d032e0a0d9c924fb6d6c188528db85a97e71c9e466ddc19eee277baf83614"},{"path":"product/runtime/auths-gateway/src/pending_vectors/recipes.rs","sha256":"51693208270231c25c3aef2a32151d5962114c71e86b88cb9df83181c7af83d9"},{"path":"product/runtime/auths-gateway/src/pre_entry.rs","sha256":"06ea78ca140468bfaba17d9ab04912ad68673954c3203c98fed28272ff2a00c0"},{"path":"product/runtime/auths-gateway/src/property_tests.rs","sha256":"939c081e2e154aaf10186754044bdd65608932c899b970a04a71d0afaa999a93"},{"path":"product/runtime/auths-gateway/src/qualification.rs","sha256":"c597c83de2b94f0374ae54e40a8b57c2a64ec6e254704dca32185f448a908aca"},{"path":"product/runtime/auths-gateway/src/qualification_simulation.rs","sha256":"4ee7cadfb5f46a92713c80f3e55f499cb074d04d8b21ea89d57762af38642bfa"},{"path":"product/runtime/auths-gateway/src/qualification_tests.rs","sha256":"a9178a2e58eea459d5e5dafc53a3999ea7c84dbbffefe6e5eb1f3d098827f028"},{"path":"product/runtime/auths-gateway/src/quorum_tests.rs","sha256":"a78380b019104d688c11a4410082c7e08ded3106aab099954c4f8a1b4ae0fd89"},{"path":"product/runtime/auths-gateway/src/readiness.rs","sha256":"911c3f11892f94641574375e2da4c671c802738f71082f12c39832331052d43d"},{"path":"product/runtime/auths-gateway/src/recipe.rs","sha256":"fecf9af67e7afc48d080e9f8f55f8ce28e49d0e08988717a27908bbda461d6b6"},{"path":"product/runtime/auths-gateway/src/recipe/lower.rs","sha256":"8088b8751ed831dbb48247af953c6290ac95e2a438ccd5bd65eff54be06a1fd1"},{"path":"product/runtime/auths-gateway/src/recipe/review.rs","sha256":"c3eb7d9fdd98dacf52750b14b67ad7b7faaecbbdeafff1e0b049f67d0a2d0139"},{"path":"product/runtime/auths-gateway/src/recipe/runtime.rs","sha256":"c286f0d15f974402822c0810d8e97f98411dc1c557755cc23e540d85e2bb42d9"},{"path":"product/runtime/auths-gateway/src/recipe/source.rs","sha256":"1af50298fb1461e1b24cbdf560d43124d6b1c4c529586c911b1c4797214a69ff"},{"path":"product/runtime/auths-gateway/src/recipe/tests.rs","sha256":"aac551a2481bbc60864c64079bc667dcb232e45a0f41a04073ed84ab5dbe1fce"},{"path":"product/runtime/auths-gateway/src/recipe/validate.rs","sha256":"3711b17605cb7b0d639bc1b180449231f5882a306cab20e2c7782155cc63b0d4"},{"path":"product/runtime/auths-gateway/src/scenario_tests.rs","sha256":"a8ea1e3a7bf6b0274455bd790ace3ffb9c8716609cde92248920945c61634685"},{"path":"product/runtime/auths-gateway/src/separation.rs","sha256":"be9306848ca5d801767cf6aa14247c8618312ef0e202f00ce0c24c4844491061"},{"path":"product/runtime/auths-gateway/src/simulation_attestation.rs","sha256":"88705e5d45415f760f1e3c3a065c35c48f4f4065bf7b3feb7882246983814d6f"},{"path":"product/runtime/auths-gateway/src/store.rs","sha256":"884bcad4d70d53e12eae9c8517f6ecd0643068ee0be0370015119d04d6cc2516"},{"path":"product/runtime/auths-gateway/src/store_testkit.rs","sha256":"88d82fee42f1b8ef521e8deef0216e938ebeaad822eb2f5020e70b89d145ea70"},{"path":"product/runtime/auths-gateway/src/submit.rs","sha256":"fe2eacb5ad8152eeecbd232c47a356fc72db0098e34fda99532bdf6ef0cf895c"},{"path":"product/runtime/auths-gateway/src/support.rs","sha256":"9fd979029793a22b15d9776a7fc172476fd7c126a80d4080c65d720845becbcb"},{"path":"product/runtime/auths-gateway/src/transport.rs","sha256":"be2c6dc75b8daec110bf8749fedc3823f6067d40b999aa3eb21126896a97d3ad"},{"path":"product/runtime/auths-kernel-runtime/Cargo.toml","sha256":"926bcd0053e5edd703be8f0027ad009e2982db013c8174c1366edbf38b48087d"},{"path":"product/runtime/auths-kernel-runtime/src/lib.rs","sha256":"7108faae9ca4bc32dc093ddaf885ac8f74f3c9b8d317b7c7d0ed00d1d0ab5972"},{"path":"product/runtime/auths-lifecycle/Cargo.toml","sha256":"c5053c705f8d5554b44e432fe75287a2faf11d644e5a2552e45ad6cd94176af5"},{"path":"product/runtime/auths-lifecycle/src/codec.rs","sha256":"51c4b746749150e8bfcd8ff972b3f6c1ef40bec15583448ec1b471d9ad737dc0"},{"path":"product/runtime/auths-lifecycle/src/digest.rs","sha256":"55282cd7d8aba37713c2dcb5357c9877819edb72a30eadefb860d28d7d3a3eb7"},{"path":"product/runtime/auths-lifecycle/src/identifier.rs","sha256":"31620e8c16de68d3d2d3b84d6353c1a5b9d4151d8247f91fa389b906a8e660f1"},{"path":"product/runtime/auths-lifecycle/src/kernel.rs","sha256":"2abb8c094b36d35b364e74d78091d14c5d6f3d1eb6552cca3b5538dbd017ce23"},{"path":"product/runtime/auths-lifecycle/src/lib.rs","sha256":"afe5a345cd309b5a4f08ffba3170a6d7f16ff914892b3f2006d5208ed24ec736"},{"path":"product/runtime/auths-lifecycle/src/model.rs","sha256":"1af12bbeeeaa65ec02ddcebd7d2c8c92ec1e339fa40ae85b45ab9b01a722a4fa"},{"path":"product/runtime/auths-lifecycle/src/operation.rs","sha256":"78e6d05fcf5d7ea4f148032a3fa26fdfcab77eb346019effe927b08e0d64d732"},{"path":"product/runtime/auths-lifecycle/src/registry.rs","sha256":"53495fe6f7a77422593a41623e28716f1c140dcc1e00f87f6b0ffbfb93a5ef90"},{"path":"product/runtime/auths-lifecycle/src/sealed.rs","sha256":"2e0c03b5813c926c159598bb7890d1523825edbe57cd687d42a5dfb3374a0c19"},{"path":"product/runtime/auths-lifecycle/src/test_support.rs","sha256":"221d9a5c5ef8e1f9f8fd66927484eaf813571d0568470278ecd8fa08a5eec8cd"},{"path":"product/runtime/auths-lifecycle/src/transition.rs","sha256":"011805a28efdd541f44ccea54dd0e34a1e58f4004447ee58013703b4fb6b2822"},{"path":"product/runtime/auths-runtime/Cargo.toml","sha256":"dd29d80a8b4bb56c869f036a6c9998f6e6d1c0383ac5dc03fa42b24abe2a7ff7"},{"path":"product/runtime/auths-runtime/src/lib.rs","sha256":"132ca03d58c14905d3a822a4972f42a22a5ad33a45f2ba9ca44f3a57d810b4b0"},{"path":"product/runtime/auths-runtime/src/production.rs","sha256":"fd4eff4270c571c10fcff6cf27df28961ebf074de8a1a028f500fda1ca376820"},{"path":"product/sdk/auths-approval-quorum/Cargo.toml","sha256":"df904971fca87a24194c5816738a331588fe8f164acb5d70839a35dca5f57114"},{"path":"product/sdk/auths-approval-quorum/src/lib.rs","sha256":"72e4086088a1c0912e4e1a9e980f26a5c280bf5ab16ea39c9f0f58d5096ac2ce"},{"path":"product/sdk/auths-approval-quorum/src/remote.rs","sha256":"9fa029c7c63003adf260f8aec55160c545681c60c1bace0d934e7525862aac7b"},{"path":"product/sdk/auths-approval-quorum/src/remote_tests.rs","sha256":"8a09ce17cfee82a035a74edd535f3ebeb3db0e078784740d3997b17dbdb10197"},{"path":"product/sdk/auths-approval-quorum/src/tests.rs","sha256":"0acbf12be3e497dcc6c2d8f29c9af3b1a7ed8e11b75f6399570d4f217a785060"},{"path":"product/stores/auths-stores/Cargo.toml","sha256":"a32c4b76d17b264be5d40d24497ff237e1ed87822e8bab86229b3db93106dbe3"},{"path":"product/stores/auths-stores/src/gateway_attempt.rs","sha256":"218841602d3d9b23b44625f50e5b54cf275ccedc2d5c89f02d2482b8524472af"},{"path":"product/stores/auths-stores/src/lib.rs","sha256":"e721262edf8a9ab5568ddc27639176312d4a366203b5f73e2d7c11fde2c554e9"},{"path":"product/stores/auths-stores/src/lifecycle.rs","sha256":"3f2cecfda13fdcd7c4a944518646bcc8abd1237f900c0332d5822281f8f9f1cd"}],"schema":"auths.gateway-semantic-closure/1"} \ No newline at end of file diff --git a/product/runtime/auths-gateway/src/qualification.rs b/product/runtime/auths-gateway/src/qualification.rs index b7ea22965..1a39a00b4 100644 --- a/product/runtime/auths-gateway/src/qualification.rs +++ b/product/runtime/auths-gateway/src/qualification.rs @@ -28,9 +28,10 @@ pub const POSTGRES_STORE_SCHEMA: &str = "auths.lifecycle.postgresql/6"; pub const FILE_STORE_SCHEMA: &str = "auths.gateway-attempt/3"; /// The public qualification root this gateway build pins. A reviewed release -/// supplies only the offline ceremony's public artifact here. Until then both -/// the runtime and release projection authenticate no qualification. -pub const PINNED_QUALIFICATION_ROOT: Option<&[u8]> = None; +/// supplies only the offline ceremony's public artifact here. A root alone +/// qualifies nothing; certificates, fresh revocations, index and evidence must +/// still authenticate the exact installed candidate. +pub const PINNED_QUALIFICATION_ROOT: Option<&[u8]> = Some(br#"{"public_key_b64":"pVEllMJVwyOSnakYUAekqDemY0xzc21a9gSB7m4lBsc","root_id":"auths-qualification-root-2026-10","schema":"auths.qualification-trust-root/1","signature_suite":"ed25519-v1"}"#); /// The stable code of one refusal. #[must_use] @@ -673,3 +674,93 @@ mod clock_tests { ); } } + +#[cfg(test)] +mod ceremony_tests { + use super::PINNED_QUALIFICATION_ROOT; + use auths_recipe_qualification::{ + QualificationArtifactKind, QualificationRevocationList, QualificationSignerCertificate, + QualificationTrustRoot, + }; + use ed25519_dalek::{Signature, VerifyingKey}; + use sha2::{Digest as _, Sha256}; + + #[test] + fn pinned_ceremony_authenticates_separate_signer_purposes() { + let root_bytes = + include_bytes!("../../../../qualification/trust/qualification-trust-root.json"); + assert_eq!(PINNED_QUALIFICATION_ROOT, Some(root_bytes.as_slice())); + let root = + QualificationTrustRoot::from_canonical_json(root_bytes).expect("canonical pinned root"); + let verification_key = VerifyingKey::from_bytes(&root.body().public_key_b64.to_bytes()) + .expect("root Ed25519 key"); + let commissioner_bytes = + include_bytes!("../../../../qualification/trust/commissioning-signer-certificate.json"); + let release_bytes = + include_bytes!("../../../../qualification/trust/signer-certificate.json"); + let commissioner = QualificationSignerCertificate::from_canonical_json(commissioner_bytes) + .expect("commissioning certificate"); + let release = QualificationSignerCertificate::from_canonical_json(release_bytes) + .expect("release certificate"); + for certificate in [&commissioner, &release] { + assert_eq!(certificate.body().statement.root_id, root.body().root_id); + verification_key + .verify_strict( + &certificate.body().signing_preimage().expect("preimage"), + &Signature::from_bytes(&certificate.body().root_signature_b64.to_bytes()), + ) + .expect("offline root signature"); + } + assert_ne!( + commissioner.body().statement.public_key_b64, + release.body().statement.public_key_b64 + ); + assert_eq!( + commissioner.body().statement.permitted_artifact_kinds, + vec![QualificationArtifactKind::QualificationCommissioningPermit] + ); + assert_eq!( + release.body().statement.permitted_artifact_kinds, + vec![ + QualificationArtifactKind::QualificationReleaseIndex, + QualificationArtifactKind::RecipeQualificationAttestation + ] + ); + let revocation_bytes = + include_bytes!("../../../../qualification/trust/revocation-list.json"); + let revocations = QualificationRevocationList::from_canonical_json(revocation_bytes) + .expect("root-signed list"); + assert_eq!(revocations.body().statement.root_id, root.body().root_id); + verification_key + .verify_strict( + &revocations.body().signing_preimage().expect("preimage"), + &Signature::from_bytes(&revocations.body().root_signature_b64.to_bytes()), + ) + .expect("revocation signature"); + let metadata: serde_json::Value = serde_json::from_slice(include_bytes!( + "../../../../qualification/trust/ceremony.json" + )) + .expect("ceremony metadata"); + for (name, bytes) in [ + ("qualification-trust-root.json", root_bytes.as_slice()), + ( + "commissioning-signer-certificate.json", + commissioner_bytes.as_slice(), + ), + ("signer-certificate.json", release_bytes.as_slice()), + ("revocation-list.json", revocation_bytes.as_slice()), + ] { + assert_eq!( + metadata["public_artifacts"][name], + hex::encode(Sha256::digest(bytes)), + "{name}" + ); + } + assert_eq!( + metadata["assessment"], + "repository-owner-delegated-technical-assessment" + ); + assert_eq!(metadata["qualification_issued"], false); + assert_eq!(metadata["stable_launch_ready"], false); + } +} diff --git a/product/runtime/auths-gateway/src/semantic_closure.rs b/product/runtime/auths-gateway/src/semantic_closure.rs index f08061885..47ec8b594 100644 --- a/product/runtime/auths-gateway/src/semantic_closure.rs +++ b/product/runtime/auths-gateway/src/semantic_closure.rs @@ -10,7 +10,7 @@ /// SHA-256 of the schema, a NUL byte, and `semantic-closure.json`. /// Regenerate through `semantic_closure_is_current` with `AUTHS_UPDATE_FIXTURES=1`. pub const GATEWAY_SEMANTIC_CLOSURE_SHA256: &str = - "18e2baae6d72c709a069569298daef381c3e6e80c10becdfdb3a061d3e06157f"; + "44a2ed495e507420b2ba834dcb208a3a6a0e5c3ea37af389174072a91e8239d2"; #[cfg(test)] mod tests { diff --git a/qualification/README.md b/qualification/README.md index 9a1edc6d7..5d1b16073 100644 --- a/qualification/README.md +++ b/qualification/README.md @@ -19,7 +19,7 @@ disposable records and development custody; it does not qualify a production tup `cargo xtask release-check` generates `target/release-evidence/launch-readiness.json`. Its `stable_launch_ready` value comes from the gateway build's pinned public root, current signed inputs and their actual evidence; no checked-in flag can -set it. The current build pins no root and therefore derives false. Missing +set it. The current build pins the public ceremony root but has no signed qualification inputs, so it derives false. Missing qualification permits a prerelease while preventing a stable launch claim. The release builder reads public signed inputs from @@ -56,12 +56,11 @@ attestation. Therefore its first qualification cannot bootstrap itself. A development installation or `testkit-production-unqualified` executable changes the target or shipped bytes and cannot establish the required production claim. That real-production authority question remains separate from the requested -simulation; the shipping lease gate has no bypass. A proposed solution is +simulation; the shipping lease gate has no bypass. The implemented commissioning authority is [ADR 0016](../docs/adr/0016-bounded-qualification-commissioning-authority.md): a finite signed permit for an authenticated private qualification-run session, with exact action commitments, durable lease accounting and a fixed expiry. -It is not implemented, cannot qualify a family, and cannot enable an ordinary -application lease. +Its verifier, durable budget and private operator commands are implemented. It cannot qualify a family or enable an ordinary application lease; the protected reference and workflow still need to produce its exact bindings. The current executable corpus also fixes exact request/evidence digests before running, while disposable live resource identifiers may be created during setup. @@ -171,8 +170,31 @@ Public artifacts of the offline root ceremony, committed by the owner: - `signer-certificate.json`: the current release signer's certificate; - `revocation-list.json`: the current revocation list. -No private key is ever in this repository. The directory is empty until the -first ceremony, and until then the signing job refuses to run. +No private key is ever in this repository. `ceremony.json` records the first +offline ceremony and the exact public-artifact hashes. It is an explicitly +delegated technical assessment, not a human release review or provider +qualification. No qualification record or release index has been issued. + +The first qualification uses the separate finite authority in +[ADR 0016](../docs/adr/0016-bounded-qualification-commissioning-authority.md). +`auths-qualification certify-commissioner` certifies a separate key with only +the commissioning-permit purpose; normal `certify` grants only release purposes. +The root key remains offline and never enters either provider runner. + +After the protected reference expands disposable resources and exact actions, +`auths-qualification commissioning-sign` takes `--binding`, `--conformance`, +`--differential`, `--signer-key`, `--certificate`, `--not-before`, `--not-after` +and `--out`. It rechecks both canonical offline members, candidate/tuple/digest +closure and all mandatory scenarios before signing. The permit lasts at most +two hours and is never a qualification record or release-index member. The +reviewed protected reference must independently derive resources/actions; +successful issuance by itself does not establish that reference's correctness. + +The operator receives `commissioning-permit.json`, `signer-certificate.json` +and the current `revocation-list.json` in one artifact directory. Only the +gateway's private `commissioning-init` and `commissioning-submit` commands use +them, with `--from`, `--state-dir`, `--protected-run` and `--resource-binding`. +Ordinary application requests require current qualification throughout. ## `run/` diff --git a/qualification/trust/ceremony.json b/qualification/trust/ceremony.json new file mode 100644 index 000000000..c800234c2 --- /dev/null +++ b/qualification/trust/ceremony.json @@ -0,0 +1,16 @@ +{ + "schema": "auths.qualification-root-ceremony/1", + "created_at": "2026-10-07T03:01:16+00:00", + "assessment": "repository-owner-delegated-technical-assessment", + "operator": "Codex acting under the repository owner\u2019s standing authorization", + "scope": "Offline root ceremony and purpose-separated public signer certificates only", + "private_key_retention": "Owner-private directory outside every Git checkout; no root key in CI", + "qualification_issued": false, + "stable_launch_ready": false, + "public_artifacts": { + "qualification-trust-root.json": "ff4768642d4141eab6c1d8bdec78b5c2aa64aad516de51611b3eb17373204ed8", + "signer-certificate.json": "50e6657008b1e060b8e10ea1747105abf8fa3528d51fb97d027044e57446dbb9", + "commissioning-signer-certificate.json": "639fa51c6b4493b52aad880f9c8df8d4f5b58fceac53aef56f4a891e7ff82bf7", + "revocation-list.json": "c8b34e4cab39c768c40a284c9c8ffd0370f8360d0c715a6b1e0989bb2a990d33" + } +} diff --git a/qualification/trust/commissioning-signer-certificate.json b/qualification/trust/commissioning-signer-certificate.json new file mode 100644 index 000000000..8b4cd8172 --- /dev/null +++ b/qualification/trust/commissioning-signer-certificate.json @@ -0,0 +1 @@ +{"root_signature_b64":"1PVq4vS88l4h4WKOjELN8TjuKPLQIKSHqT-VHl86xQVH4yqwHhNL96R-t-N1Qi2-KioUAEbNoDudOgdd821RDg","statement":{"issued_at":1791342076,"not_after":1793934076,"not_before":1791342076,"permitted_artifact_kinds":["qualification-commissioning-permit"],"public_key_b64":"VRExEtVXOyEedChisGDuMi54eVsibhXuQOZ5aEcWD5I","root_id":"auths-qualification-root-2026-10","schema":"auths.qualification-signer-certificate/1","signature_suite":"ed25519-v1","signer_id":"auths-commissioner-2026-10","signer_kind":"protected-software-release-key-v1"}} \ No newline at end of file diff --git a/qualification/trust/qualification-trust-root.json b/qualification/trust/qualification-trust-root.json new file mode 100644 index 000000000..f1184d434 --- /dev/null +++ b/qualification/trust/qualification-trust-root.json @@ -0,0 +1 @@ +{"public_key_b64":"pVEllMJVwyOSnakYUAekqDemY0xzc21a9gSB7m4lBsc","root_id":"auths-qualification-root-2026-10","schema":"auths.qualification-trust-root/1","signature_suite":"ed25519-v1"} \ No newline at end of file diff --git a/qualification/trust/revocation-list.json b/qualification/trust/revocation-list.json new file mode 100644 index 000000000..83a7e8085 --- /dev/null +++ b/qualification/trust/revocation-list.json @@ -0,0 +1 @@ +{"root_signature_b64":"4gvszV4cHNILhMPi2NxDbtBrhRIf-lQQGt_YPzj5Ae4Av5ec5AuVUCXDPNcja_9MTogd_QPBdFXvPkb-VfgaAw","statement":{"issued_at":1791342076,"next_update":1791428476,"revoked_qualifications":[],"revoked_signers":[],"root_id":"auths-qualification-root-2026-10","schema":"auths.qualification-revocation-list/1","sequence":1}} \ No newline at end of file diff --git a/qualification/trust/signer-certificate.json b/qualification/trust/signer-certificate.json new file mode 100644 index 000000000..bb28c0123 --- /dev/null +++ b/qualification/trust/signer-certificate.json @@ -0,0 +1 @@ +{"root_signature_b64":"atJnLOjTzDXyZ_GWrZfRdKj_uhnDdV8Y77nNSQYtwNQeljUrsq45C-cSRrqPgASmN4XwDiDKMQXXhJSN1OvhAg","statement":{"issued_at":1791342076,"not_after":1806894076,"not_before":1791342076,"permitted_artifact_kinds":["qualification-release-index","recipe-qualification-attestation"],"public_key_b64":"Sg-H5x4f4DNtKM5UN_L6nAE7Z9sEFwnc3eIoRAp1A4Q","root_id":"auths-qualification-root-2026-10","schema":"auths.qualification-signer-certificate/1","signature_suite":"ed25519-v1","signer_id":"auths-release-signer-2026-10","signer_kind":"protected-software-release-key-v1"}} \ No newline at end of file diff --git a/release/semantic-freeze-versions.toml b/release/semantic-freeze-versions.toml index 5a6688bb7..adb0d7b68 100644 --- a/release/semantic-freeze-versions.toml +++ b/release/semantic-freeze-versions.toml @@ -1,4 +1,4 @@ -freeze_version = 372 +freeze_version = 373 # Semantic identity counters live outside the xtask source tree deliberately. # The formal source closure binds xtask's executable code, while the semantic @@ -45,7 +45,7 @@ freeze_version = 372 "auths.frozen-bytes/product/integrations/auths-stripe/fixtures/subscription-create/v1/manifest.sha256.json" = 1 "auths.frozen-bytes/product/integrations/auths-stripe/fixtures/subscription-modify/v1/manifest.sha256.json" = 1 "auths.frozen-bytes/product/integrations/auths-stripe/fixtures/v1/manifest.sha256.json" = 1 -"auths.identity.protocol" = 125 +"auths.identity.protocol" = 126 "auths.modular-components" = 20 "auths.portable-abi-bindings" = 121 "auths.product.bounded-domains" = 19 @@ -60,11 +60,11 @@ freeze_version = 372 "auths.product.mcp-closed-execution" = 31 "auths.product.mechanism-profile-conformance" = 12 "auths.product.operations" = 5 -"auths.product.public-sdk-contract" = 122 +"auths.product.public-sdk-contract" = 123 "auths.product.receipts" = 13 "auths.product.release-assurance" = 7 "auths.product.simplified-waist" = 19 "auths.product.vocabulary" = 24 "auths.release.benchmark-contract" = 1 "auths.release.evolution-contract" = 79 -"auths.release.public-surface" = 372 +"auths.release.public-surface" = 373 diff --git a/release/semantic-freeze.json b/release/semantic-freeze.json index 3e4d04a1a..fa9a7871e 100644 --- a/release/semantic-freeze.json +++ b/release/semantic-freeze.json @@ -1,6 +1,6 @@ { "schema": "auths.semantic-freeze/1", - "freezeVersion": 372, + "freezeVersion": 373, "publicSurface": { "rustRoots": [ "auths", @@ -550,7 +550,7 @@ }, { "id": "auths.identity.protocol", - "version": 125, + "version": 126, "classification": "frozen-meaning", "categories": [ "identity-protocol-versions", @@ -573,7 +573,7 @@ "core/fixtures/identity/v1/vectors.json", "core/spec/identity/v1" ], - "sha256": "aef90d74b6777b88544d01183cfe9ac8ae3270ec7200917d0c05319cd0638c8d" + "sha256": "8efe6e1e8c5da54d4bd433b51e8b9a9e93c6ceadd15f611a6f6f34f09ea00091" }, { "id": "auths.modular-components", @@ -871,7 +871,7 @@ }, { "id": "auths.product.public-sdk-contract", - "version": 122, + "version": 123, "classification": "frozen-meaning", "categories": [ "rust-sdk-contract", @@ -889,7 +889,7 @@ "product/runtime/auths-runtime/src", "product/sdk/auths-sdk/src" ], - "sha256": "3fbc6618d7e844178373509f26ea29becd37115f90950d371abf001a05326050" + "sha256": "cf4df124a49cee9bd90eb486636998cef5af8525f0524389c23d0d9dea9979e1" }, { "id": "auths.product.receipts", @@ -1011,7 +1011,7 @@ }, { "id": "auths.release.public-surface", - "version": 372, + "version": 373, "classification": "release-metadata", "categories": [ "package-names", @@ -1104,7 +1104,7 @@ "xtask/src/release_launch.rs", "xtask/src/semantic_freeze.rs" ], - "sha256": "3dc8eeaf46f43840d02b35e00203096fb13b93a7594e34e616db382ee9dd60d9" + "sha256": "8f6bcbe2b1ec2f1699a93cd8e012be697711f5ee841fe089eaf7e9532d3971ad" } ] } From 4d1aa4efc434689d2b7e717c89242394fd828f75 Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 04:25:45 +0100 Subject: [PATCH 057/108] Derive offline production identity and independently review finite commissioning actions --- .github/workflows/recipe-qualification.yml | 2 + compliance.toml | 2 + ...gateway-polish-and-recipe-qualification.md | 24 +++ .../auths-gateway/semantic-closure.json | 2 +- .../auths-gateway/src/bin/auths-gateway.rs | 186 ++++++++++++++++ .../src/commissioning_session/tests.rs | 50 +++++ product/runtime/auths-gateway/src/engine.rs | 81 +++++++ product/runtime/auths-gateway/src/lib.rs | 3 +- .../auths-gateway/src/semantic_closure.rs | 2 +- qualification/README.md | 14 +- qualification/reference/README.md | 48 +++++ qualification/reference/airtable_record.py | 75 +++++++ qualification/reference/common.py | 65 ++++++ qualification/reference/expand.py | 194 +++++++++++++++++ qualification/reference/stripe_platform.py | 70 ++++++ .../reference/tests/test_reference.py | 202 ++++++++++++++++++ qualification/run/offline.sh | 10 +- release/semantic-freeze-versions.toml | 8 +- release/semantic-freeze.json | 14 +- 19 files changed, 1029 insertions(+), 23 deletions(-) create mode 100644 qualification/reference/README.md create mode 100644 qualification/reference/airtable_record.py create mode 100644 qualification/reference/common.py create mode 100644 qualification/reference/expand.py create mode 100644 qualification/reference/stripe_platform.py create mode 100644 qualification/reference/tests/test_reference.py diff --git a/.github/workflows/recipe-qualification.yml b/.github/workflows/recipe-qualification.yml index a442a6083..51f1846cb 100644 --- a/.github/workflows/recipe-qualification.yml +++ b/.github/workflows/recipe-qualification.yml @@ -43,6 +43,8 @@ jobs: - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 with: python-version: "3.12" + - name: Check the independent resource and request references + run: python -m unittest discover -s qualification/reference/tests - name: Build the portable simulation harness run: | mkdir -p target diff --git a/compliance.toml b/compliance.toml index 8139e9f85..2f62693b6 100644 --- a/compliance.toml +++ b/compliance.toml @@ -1768,12 +1768,14 @@ stateful-replay-budget-component = [ "product/runtime/auths-gateway/src/commissioning_floor/tests.rs#database_restore_below_retained_witness_is_refused", "product/runtime/auths-gateway/src/commissioning_floor/tests.rs#database_claim_without_witness_acknowledgement_stays_spent", "product/runtime/auths-gateway/src/commissioning_session/tests.rs#ordinary_submission_cannot_select_commissioning_authority", + "product/runtime/auths-gateway/src/commissioning_session/tests.rs#offline_review_verifies_exact_actors_and_requests_without_custody", "product/runtime/auths-gateway/src/commissioning_session/tests.rs#exact_native_actor_and_action_require_a_durable_unit_before_custody", "product/runtime/auths-gateway/src/commissioning_session/tests.rs#absent_registration_and_expiry_after_preparation_never_lease", "product/runtime/auths-gateway/src/commissioning_session/tests.rs#another_signed_actor_or_action_is_refused_before_custody", "product/runtime/auths-gateway/src/commissioning_session/tests.rs#changed_resources_run_operator_or_context_cannot_open_a_session", "product/runtime/auths-gateway/src/bin/auths-gateway.rs#concurrent_operator_imports_keep_every_authenticated_revocation", "product/runtime/auths-gateway/src/bin/auths-gateway.rs#application_and_admin_frames_cannot_select_a_commissioning_session", + "product/runtime/auths-gateway/src/bin/auths-gateway.rs#candidate_identity_needs_no_installation_and_binds_the_running_bytes", "product/runtime/auths-gateway/src/commissioning_budget/tests.rs#capacity_survives_crash_restart_and_sweep_postgres", "product/runtime/auths-gateway/src/commissioning_budget/tests.rs#exactly_one_host_claims_the_final_unit_file", "product/runtime/auths-gateway/src/commissioning_budget/tests.rs#exactly_one_host_claims_the_final_unit_postgres", diff --git a/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md b/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md index 65b9c820c..3040faa18 100644 --- a/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md +++ b/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md @@ -1778,3 +1778,27 @@ are implemented. The first offline root and separate purpose certificates are pinned, with no qualification issued. The protected family reference/workflow and rejection/live evidence still must land before the bootstrap can be claimed resolved. Epic 5's done conditions remain unchanged. + +### 22.4 Reviewed commissioning expansion (2026-10-07) + +The default candidate now derives its planned production tuple without installing +custody through `qualification-candidate`. This is offline candidate identity, +not a deployment or a qualified state. The protected live installation must +print the same tuple before permit import or submission. + +`review-submission` verifies a proof and derives its actors, native action +commitment and credential-free closed request without custody, state or provider +I/O. Its optional evaluation time is an offline input and cannot alter the +production lease clock. `qualification/reference/` independently derives the +Stripe/Airtable requests, fixes resource membership and reconstructs the entire +reviewed recipe and exact lock. Expansion invokes a reviewer built by the +signing job from its checkout; downloaded candidate bytes are hashed but never +executed with a signing key. The original candidate digest remains signed. +One actor, finite exact actions, immutable resources and a source-owned ceiling +of 64 custody acquisitions are required. The native issuer additionally checks +offline evidence closure before issuing a two-hour permit. + +Both purpose-separated signer keys now exist in the existing reviewer-protected, +default-branch-only signing environment. The offline root remains outside CI. +Complete family setup/corpora, protected commissioning/live runs and final signed +qualification still remain; these changes issue no qualification or readiness. diff --git a/product/runtime/auths-gateway/semantic-closure.json b/product/runtime/auths-gateway/semantic-closure.json index e7f0598ac..7b48b00da 100644 --- a/product/runtime/auths-gateway/semantic-closure.json +++ b/product/runtime/auths-gateway/semantic-closure.json @@ -1 +1 @@ -{"files":[{"path":"Cargo.lock","sha256":"0e75e2fdef44e79e57797ac6661295ae58ddb8de4a1990a6fd22ce6c54f78604"},{"path":"Cargo.toml","sha256":"6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24"},{"path":"core/adapters/auths-did-keri/Cargo.toml","sha256":"86ba3e3f9a0a70d970568bfb3113b7ba7bbdd81c3eebbb52743dd574a0c0ecaa"},{"path":"core/adapters/auths-did-keri/src/lib.rs","sha256":"a75674842f8a7142004369ccd206ab43e476459293f0ff4bed4d4e659031b3e3"},{"path":"core/adapters/auths-did-key/Cargo.toml","sha256":"d5a3ae07ecde83f91eed4c3785051dd0f44eab6c891754f3309b6b40596707d7"},{"path":"core/adapters/auths-did-key/src/lib.rs","sha256":"b76a3f4528a725df53cfa9242e6e414e1d26caa48468aaed497e28b121f4497c"},{"path":"core/adapters/auths-raw-key/Cargo.toml","sha256":"f49616bc18c19e6aaa7e6a02ccebcdb9f5c1422c1278ef9869e0dbf22ceda7be"},{"path":"core/adapters/auths-raw-key/src/lib.rs","sha256":"45eec1b295dac3bed65cd79c942870b926b06b3f5d38eaebaeb6140ac69315fa"},{"path":"core/crates/auths-algebra-kernel/Cargo.toml","sha256":"0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba"},{"path":"core/crates/auths-algebra-kernel/src/generated.rs","sha256":"ae4bcbef42a408c7ffa0c6a74a42f7de177a6f14479e51d205acf830bda05960"},{"path":"core/crates/auths-algebra-kernel/src/lib.rs","sha256":"6654667eeb9b353d6648954c9fd2e8838462a82ce6b2803eb49e1366892c68c6"},{"path":"core/crates/auths-assurance/Cargo.toml","sha256":"afcb12a97ddd09d7a264b9ecd3fcaefc865ff2c9b4539ee85b00883420ba333a"},{"path":"core/crates/auths-assurance/src/lib.rs","sha256":"0fb2ec844d674b25a9e20b1601452c89c2454901fa506adfa9bb38ef9a7fa213"},{"path":"core/crates/auths-author/Cargo.toml","sha256":"1e6f0e3bc079ddb558decf0db26b291c6e72fc47327b6df1b7650d41689b215f"},{"path":"core/crates/auths-author/src/lib.rs","sha256":"e14475f2f49715a1869d5fa6b11ff1fbb72497e39097e09f833b0bae7e5b3f2b"},{"path":"core/crates/auths-author/src/observations.rs","sha256":"dda7d6bfa6f4bd7e95a480ca283c2c0e996f69c5c15cb0c7197af328131a7066"},{"path":"core/crates/auths-authority/Cargo.toml","sha256":"4f68212938029f79ebd857b4f3038494eb85d0163d49f07e51376715cf959815"},{"path":"core/crates/auths-authority/src/lib.rs","sha256":"da88d5194de4e17449e69972c0fb042afa3c39798a8f570f30771e77c384f1eb"},{"path":"core/crates/auths-codec/Cargo.toml","sha256":"e20e51826e17814effd9d8925d18d5fbdd6c0d37bf50231e743ec2611314722c"},{"path":"core/crates/auths-codec/src/approval.rs","sha256":"fbff43bf4d57f69f8b7738a8647751cde75c5a932dee65d924a1fe9c7202f91f"},{"path":"core/crates/auths-codec/src/bounded_policy.rs","sha256":"d21f6728be2d8a04b6d94921f2b683f7e61cbb42e0ac6866f1c88a49caa534c3"},{"path":"core/crates/auths-codec/src/decode.rs","sha256":"ba2999584cdf53b1b517ecb9c7ea50d39efee17c666a9a38e2ad1ac94379f778"},{"path":"core/crates/auths-codec/src/encode.rs","sha256":"8491192053e2e15d62b4d2a491de22405b7487ead69ab6f6bca40669ce7ca5f7"},{"path":"core/crates/auths-codec/src/error.rs","sha256":"fecb0737c16deb42d859f1dc7727c698438d9ac12064fd99e0024629642c390c"},{"path":"core/crates/auths-codec/src/hash.rs","sha256":"f88e111f1dbb2cef6b7b5e9c948cb45ff92e366710c8a5f5c636138aa748479e"},{"path":"core/crates/auths-codec/src/lib.rs","sha256":"3b0e5c94c6f34f750b88a9333e1d5c8145746d845d3a23e0d2f61807cf592ea7"},{"path":"core/crates/auths-codec/src/observation.rs","sha256":"38328b0c71ff97a4196eeade8b4faa889527ff1f80bb168468bcd49082a3987e"},{"path":"core/crates/auths-composition/Cargo.toml","sha256":"331e13025eb82588b5269ed3975929eb41c823d588c49e4c296273d85c6fe80e"},{"path":"core/crates/auths-composition/src/lib.rs","sha256":"e42e3b0b6a9985b73c533aeb23799c638979aa27a9ce7d0f10a8d60340570fb1"},{"path":"core/crates/auths-model/Cargo.toml","sha256":"565c15302b0cc9270db1e28efa3862804846850ba933cc17aea8abcec4a65987"},{"path":"core/crates/auths-model/src/approval.rs","sha256":"54cf44a9ef747ec21546a4086aecfb130bc7803b0d646430e6082df51e6e305f"},{"path":"core/crates/auths-model/src/bounded.rs","sha256":"f90496abc0a06c028b4d850af6ddab7d850bfafeaa3d042f1b1246a41d8bbbc9"},{"path":"core/crates/auths-model/src/bounded_policy.rs","sha256":"306a8f049cc7cfc7635fe0e4de47eb7813eed63d3c14c3be2b51586aa4eea450"},{"path":"core/crates/auths-model/src/lib.rs","sha256":"e7cfe6bb9574c6b016aa63e70658c31e0b90903ec6479a49f4a2ceb64f5bad97"},{"path":"core/crates/auths-model/src/observation.rs","sha256":"b3ed3e3cc090afca2896a7d3de7988afccc1ee1ea0ebd91b51a8bc0f20ad8dbb"},{"path":"core/crates/auths-multikey/Cargo.toml","sha256":"858756c1197befcada06134742bffe8d58cf674cadd6c046bf710570e96efaf2"},{"path":"core/crates/auths-multikey/src/lib.rs","sha256":"f5177fffb11e40eeaaa665ba886c541fc1f24d5eacdd6983fb03dc20148733f0"},{"path":"core/crates/auths-ports/Cargo.toml","sha256":"596a9b0f5af3717c16a6d13f7054d8a106bcd9f01f5f72c2235dd2afcf0ab16c"},{"path":"core/crates/auths-ports/src/binding.rs","sha256":"a16c012d40aa4249e3ec54372b9611006d0bfe8c7dc3c741911c2194ad17736d"},{"path":"core/crates/auths-ports/src/diagnostics.rs","sha256":"aa596572503b5a65a918bb2ff38281c144ff53821ee914e9325c852828d852df"},{"path":"core/crates/auths-ports/src/lib.rs","sha256":"8da1debf86f9532df0660155d04298beb1ba3a1204508f8586e2e67cd2fb3449"},{"path":"core/crates/auths-ports/src/path.rs","sha256":"b68fc547b4e4d97a60cbbc1cc1939fc6b34a8233b81f840bd396914a707e3ea1"},{"path":"core/crates/auths-raw-key-core/Cargo.toml","sha256":"98c0bc8527a537512e43a74dd6ba9658c6f0cdc16610cf938e3f9b43785d836d"},{"path":"core/crates/auths-raw-key-core/src/lib.rs","sha256":"98c0500c41697aae28708ad0bf970b9a97583d96a3d2c18d23e7fa351e0f7d12"},{"path":"core/crates/auths-registries/Cargo.toml","sha256":"590e49e58b0622d9d6274fea46796dcdb07dec9550eff295cce6a6427ffa51e2"},{"path":"core/crates/auths-registries/src/lib.rs","sha256":"450d3886d85ee333b7e046317fb5b47cde62483d5f3e41d46265e2caf4c373ec"},{"path":"core/crates/auths-registries/src/template.rs","sha256":"1224039dd2b3ce6fa8357613d8cafbae40400493da7176da202b9ade62fa05e4"},{"path":"core/crates/auths-signature-core/Cargo.toml","sha256":"6bee2230eb30af1be0bd5c2d57bd3e1903497a70028d47290d4ac6e9e0e8bca0"},{"path":"core/crates/auths-signature-core/src/lib.rs","sha256":"6e3f9311ded5e49ea50d445eb21e6d8fa12442aa4362a73e0cb6fda15b7cd865"},{"path":"core/crates/auths-signature/Cargo.toml","sha256":"7f7b5682466ba439d8c59579022cb61068cad9fb4bd2d73e1cc21327c902b450"},{"path":"core/crates/auths-signature/src/lib.rs","sha256":"b3d9ac4cc3ba0797b9e1c09f2d6ac05089b25dac4e285a5af28c0165b33d925b"},{"path":"core/crates/auths-verifier/Cargo.toml","sha256":"c43358e06a33324b41a8b93e5cc7279c55f7d21f1f6cfaa539a3fc7b4c27a38f"},{"path":"core/crates/auths-verifier/src/approval.rs","sha256":"c3cae6a49e169051eb555bb092b1069a4d422516d6a2114623a89e5f31ff923f"},{"path":"core/crates/auths-verifier/src/causal.rs","sha256":"9635230f33b13a263573d319ac8a1976addbcc07677514a43e3c7bf28dc04587"},{"path":"core/crates/auths-verifier/src/lib.rs","sha256":"f22dec38dfa47ced8da4f605390da8453273bee1da010f57fd1fdfcb10e0b389"},{"path":"core/crates/auths-verifier/src/observation.rs","sha256":"0bb07f06a0f9524c88427df1c972b1de8ba038a9eeeb15d3134c25125ae84b1e"},{"path":"core/crates/auths-verifier/src/trace.rs","sha256":"2213d72023a1d9e0413a2cf2c51c3dad9e04775d86033a0caaa9d29a8f0036f8"},{"path":"exchange/crates/auths-proof-exchange-model/Cargo.toml","sha256":"34b2db64f93a288e942b5a3918d28cdcbef906e0dc9074ce848018d3d5f7a1fa"},{"path":"exchange/crates/auths-proof-exchange-model/src/lib.rs","sha256":"49fac5aff2339d3a57c41cb8bb2a82852538e8f77ecc4b157c88e264ff31fb55"},{"path":"exchange/crates/auths-proof-exchange-port/Cargo.toml","sha256":"7ff660f1b7579dc570c791090aeb450404fbbf44c92781e289f5ccdde746d739"},{"path":"exchange/crates/auths-proof-exchange-port/src/lib.rs","sha256":"b408fb40c6432edc1facb3d8b3e9433a033f8dc73fe2e0ba5a88c972ca675021"},{"path":"product/config/auths-config/Cargo.toml","sha256":"e4b568ab9f6d84f7d7e6d66443fe825f360db9c27bc7c31d6ddc0647ba3ab304"},{"path":"product/config/auths-config/src/lib.rs","sha256":"fecf00ea65cef9018fda9af2063326d7065b869266d0d9e73a4f06816f1102cc"},{"path":"product/errors/auths-errors/Cargo.toml","sha256":"3b3a199b6460ba75bda84475bb5accd35e1485448a3981038db85bf4772dd350"},{"path":"product/errors/auths-errors/src/lib.rs","sha256":"7feeb9069fa4003f94f1f07c1c94619cf1c883e0dbaaf2187f04d0f742264bdd"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/Cargo.toml","sha256":"716f1f2a117d6d69d8effe9ee9057e24ba3502f20af6a602b06facb638cdabed"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/api.rs","sha256":"9ea61dd7ddd93282b073b98e453e6b75b26dc49689c04e9782435d06a3a09e48"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/clock.rs","sha256":"73f0a6e0f5903883329fa6683f5888288f759512ac69e5c87efd2b6b87f7d79f"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/http.rs","sha256":"14c1fce14e24c984b2a275563a29b6326fb08367922b6e8d37ba38b9cb81aa2b"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/identity.rs","sha256":"186de11230c8b33375951c4368609f8976bf9795f171af3fd7fac26207a94361"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs","sha256":"0b4617d044f5254a5ab22f5a2578f91cc025206a8c1845be39c1c56dcdf7a5df"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/names.rs","sha256":"41bb23572d6002e23ee103d6fe70ecd68764861c6f2e48a1c53af998270a4afa"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs","sha256":"39fed883f4802e68d3b41a68fea0aba0737810996b33d13577de70faba004c29"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/store.rs","sha256":"fc60ee9c49b2f4f063c449b4c78100c5c4872779e94ca168f796603b380ef6e4"},{"path":"product/integrations/auths-custody/Cargo.toml","sha256":"1e14034185ad1ec24a977fd5f41d0abee219606245c046ce2a82287fadef448b"},{"path":"product/integrations/auths-custody/src/conformance.rs","sha256":"8ed1afd58f18fc6becc268908aa6419c9aa404c79da0197963eb2599df44acf6"},{"path":"product/integrations/auths-custody/src/key.rs","sha256":"70cbb0fd21b6f5652157845a22c35be2d0f6c05b3d138fc4b9bb6dbdc3d81c40"},{"path":"product/integrations/auths-custody/src/lib.rs","sha256":"8ee593c1f59b0fd2126bdda9138026f5bc531beb64d4489a99785842e7b98b43"},{"path":"product/operations/auths-operations/Cargo.toml","sha256":"73dde1e914ba5e1386f8d49c0d730423cc72ae77ec44c6554a6a75cc8e8922b1"},{"path":"product/operations/auths-operations/src/explanation.rs","sha256":"b4a39bcbd5712cb9e735ee7deeb281f3fa6af5ddca973735bf3d87dce427ef11"},{"path":"product/operations/auths-operations/src/lib.rs","sha256":"3f401a56555113b98f57bca172a2660eaecedf76247b83a3fdbb089c133a29cd"},{"path":"product/operations/auths-operations/src/render/json.rs","sha256":"2ae042639960afee123730e945d373bc5dda1d2b3af20ae16c939a7e99b9e418"},{"path":"product/operations/auths-operations/src/render/mod.rs","sha256":"b3b7f6fe473f49227ace5a68bfc3d8dc14b5db8dd9888fd9e207070337b1b8bf"},{"path":"product/operations/auths-operations/src/render/text.rs","sha256":"f216cf3bdb00e264523271b16e7059535ac6b1aabf271cebd7935af155e4bfec"},{"path":"product/policy/auths-bounded-policy/Cargo.toml","sha256":"babd5d200923137ead71d8c2528f847cea323ce98da942a1320b054436612c47"},{"path":"product/policy/auths-bounded-policy/src/arithmetic.rs","sha256":"75e43c5d4eab8d1f71c1daf53839f5f9fe45a400afc1f63a30c6f55ce3632627"},{"path":"product/policy/auths-bounded-policy/src/commitment.rs","sha256":"c5706f2d583454e1a7f570f7ada138d4d864bef0205dfae7c1296774f396bb3f"},{"path":"product/policy/auths-bounded-policy/src/eligibility.rs","sha256":"c9acdfb793074e687fc36efad506be27dbd99ffbf40387bc66c8de39ef238432"},{"path":"product/policy/auths-bounded-policy/src/identifier.rs","sha256":"0006a32bae9eb16c4178cf797df418d2b0a781f2bc6474b741dc1a908141831c"},{"path":"product/policy/auths-bounded-policy/src/kernel.rs","sha256":"99187c28b161ac70bee1afed60711f7f645adb4d1671a01863f9849b369811d5"},{"path":"product/policy/auths-bounded-policy/src/lib.rs","sha256":"76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c"},{"path":"product/policy/auths-bounded-policy/src/receipt.rs","sha256":"3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad"},{"path":"product/policy/auths-bounded-policy/src/registry.rs","sha256":"4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0"},{"path":"product/profiles/auths-profile-api/Cargo.toml","sha256":"7ae85761f58625b5d678f961fd052eebf3e000ef565c7312e3ac857763c0017f"},{"path":"product/profiles/auths-profile-api/src/lib.rs","sha256":"a194b82b20bf8aa864c2334ef6c6aec30b2154ded972862252d5dcefa488ab95"},{"path":"product/profiles/auths-profile-mcp/Cargo.toml","sha256":"db264fc25242f7b7e4133cbe5782545b3107b406c87168ae072683cfb59eac66"},{"path":"product/profiles/auths-profile-mcp/src/arguments.rs","sha256":"a5de696586d507e2aee4a49fee99ef1ef4c51a2e46603f8838f1af6d9009833f"},{"path":"product/profiles/auths-profile-mcp/src/lib.rs","sha256":"d0f8b733a09ef8408336cdebc8948d6a5861012ce6878598b11be7084dfd4280"},{"path":"product/profiles/auths-profile-mcp/src/session.rs","sha256":"166c281fa66333388e4760d6098dad02d3359e1d5de4b8f93312c014f97abb03"},{"path":"product/qualification/auths-recipe-qualification/Cargo.toml","sha256":"b7b15b30b9a3d96d4f089d514266d3a892de6608d30707aa44be31cca89ca9fe"},{"path":"product/qualification/auths-recipe-qualification/src/canonical.rs","sha256":"30a9b50777f0dcb4b606abfee2467d5a975d9f6ad941ab6c13ca3df5b359f667"},{"path":"product/qualification/auths-recipe-qualification/src/closure.rs","sha256":"0ad6aee9bd981e2863fa725f209ec84031db2ff12f4c7ac3aaf5120f0bb86039"},{"path":"product/qualification/auths-recipe-qualification/src/commissioning.rs","sha256":"66ea49f96887c4642139a48d259c270816e2267ee8cf6344a1340fe47afda9da"},{"path":"product/qualification/auths-recipe-qualification/src/commissioning/tests.rs","sha256":"5a226725c2ad7ce920d0bd62d427185e007f4d0949b0f0ec1260aa161d3114d0"},{"path":"product/qualification/auths-recipe-qualification/src/error.rs","sha256":"52d5cf720a1e4579008fdda90a3ac2c31f0b8db57985f121f65e54b4da2b7dd1"},{"path":"product/qualification/auths-recipe-qualification/src/evidence.rs","sha256":"ba45a7409d67a8af26ab811af306412014557477a101ab2a8eb0faf8f2bd4b91"},{"path":"product/qualification/auths-recipe-qualification/src/ids.rs","sha256":"e81a906d571497ab2da753e1532d4443706410e0b75fdd59a7d2d788c7aec403"},{"path":"product/qualification/auths-recipe-qualification/src/launch.rs","sha256":"41f2e2de90e1e7d6440a66eda3eb9bea8d5e0741bc232305a76a363ab5f813c1"},{"path":"product/qualification/auths-recipe-qualification/src/lib.rs","sha256":"7d26c5bfe9769daebf90c5c2280e0d75742e4cc70d0e608408e0665e3f516a2b"},{"path":"product/qualification/auths-recipe-qualification/src/model.rs","sha256":"3484eb0ec287b23d4682ade7b1b0f8d1335985b3fb180f06fc28716076957d5f"},{"path":"product/qualification/auths-recipe-qualification/src/release.rs","sha256":"ec478e53f70052e566aac7e15be2f9e1b1cd46837ac6990ae955fa864d311586"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/mod.rs","sha256":"fa23a962fd90331152eed5edbcdf271955f7aed79b8da1e065bfe69a20b487a9"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/schemas.rs","sha256":"c59feec2805621f341a90f81fc005e2c12f7a70f9d264fdeacccb2be4fe1c046"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/verification.rs","sha256":"6a6b5834c5dae10af1ba8939b2deae43b85db71544dc8f077ff63b7fe68ac8a8"},{"path":"product/qualification/auths-recipe-qualification/src/verify.rs","sha256":"2ec2784435d11e07295de77b2ee1b2c48b2fcf9609a00454c6e7374b621aed5c"},{"path":"product/receipts/auths-receipts/Cargo.toml","sha256":"6001fa1375899953aafcb07c23a6da0c8f57ea7ec08bb9c950b12a60a8cc6f0f"},{"path":"product/receipts/auths-receipts/src/disclosure.rs","sha256":"ba9ed439be0a320c8a01f5b6e9b51361c1a37e076947490d8e4a484ba6bb119c"},{"path":"product/receipts/auths-receipts/src/lib.rs","sha256":"547a57c4160256719cafb7d0ab972d9fc80b0da14fbbce4148c70c414070ff36"},{"path":"product/runtime/auths-connections/Cargo.toml","sha256":"babeb6e1dda3dfb66291713ce1e43dce5c349833d0b50ea4dccbf986030026b2"},{"path":"product/runtime/auths-connections/src/credential.rs","sha256":"82921413bb053f0f6c7931fbd4e6a86c8cc1d8c6b51debd9c2cef33a8d5b1c51"},{"path":"product/runtime/auths-connections/src/kernel.rs","sha256":"a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8"},{"path":"product/runtime/auths-connections/src/lib.rs","sha256":"79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22"},{"path":"product/runtime/auths-connections/src/model.rs","sha256":"de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77"},{"path":"product/runtime/auths-connections/src/registry.rs","sha256":"e57640e003e72ad3235c567c2bb944a262bd64e673f023b62ea091094cc7e946"},{"path":"product/runtime/auths-gateway-kernel/Cargo.toml","sha256":"34f864e67656af4ac7e5c7a347a23f01fc8ab31365b8e23c0ef474483b14a183"},{"path":"product/runtime/auths-gateway-kernel/src/construct.rs","sha256":"e9d65744bae273d65face4285e5d2da75c06a92ab48f7b8333d496604e31c63c"},{"path":"product/runtime/auths-gateway-kernel/src/lib.rs","sha256":"cfda6f8453426564c085475f183b6f790b438768a19668f1b65d33ba59dc8632"},{"path":"product/runtime/auths-gateway-kernel/src/order.rs","sha256":"e0045f877c4b7fe3860c291039853885064ddcdebba7c9b345ab65e81e646dda"},{"path":"product/runtime/auths-gateway-kernel/src/outcome.rs","sha256":"e9785b1afe70788c89b51b18655bcd5acff7b0c8e3d12fb79c6f05a202e67e6b"},{"path":"product/runtime/auths-gateway-kernel/src/ratio.rs","sha256":"7ace22264812e6fc1ef3a62afee402cf43494bb71ae0d3de219ad1b39d690bcb"},{"path":"product/runtime/auths-gateway-kernel/src/recovery.rs","sha256":"9f46dcd1685ab6e4d1ba04a3fc286a9f3afee8fb47829be1fbc670a7926a2dc6"},{"path":"product/runtime/auths-gateway-kernel/src/transition.rs","sha256":"cefb8f01d915880f6921f2501ff881ad94b9de61072c34d9cd19220992f97374"},{"path":"product/runtime/auths-gateway/Cargo.toml","sha256":"00b28be86921dcdc0ad90cce0c62c2961cafefe96ea6c2edf0e926c3d405ccad"},{"path":"product/runtime/auths-gateway/src/admin.rs","sha256":"2d5cc67afac42fbd15f36e2d1693cd1b20cedacf775040dce6ffe04ccc94c9ea"},{"path":"product/runtime/auths-gateway/src/app.rs","sha256":"6f80f63833ea0815bb44fbf3b0cc54624a08e9fb578b035819f2980dc04e8256"},{"path":"product/runtime/auths-gateway/src/audit.rs","sha256":"0edb2037eb7b5d6f13acfce85c54f62a82bf7fdd31bc7e626c4fec183cef61dd"},{"path":"product/runtime/auths-gateway/src/audit_tests.rs","sha256":"990969384a52d75bc2489d9d412a9e7dd814bca1c8f65c701d6205fae62a15d5"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway-harness.rs","sha256":"12b0c24d36b2e6a3be392d3c081a783b355fdd67dc5b54bacc0410e803116b8c"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway.rs","sha256":"2a5d64c1f8a845d4a073ce12ed7fa23ee7db515b2d356eeae774b1f670e056fa"},{"path":"product/runtime/auths-gateway/src/binding.rs","sha256":"663b0ce878319511aa7d05722ab4ab2fa9be18817884ffb2ee9f131ff1e382d1"},{"path":"product/runtime/auths-gateway/src/bounds.rs","sha256":"38251ad6f22f9d07ef9a219c79fa265ca36f1526eca5f147d7efa46b52ad609d"},{"path":"product/runtime/auths-gateway/src/bounds_aggregate_tests.rs","sha256":"ab34f227b7c8692ba1da88ccb32bb3687a66adf8353d8282fae905d4a88eb612"},{"path":"product/runtime/auths-gateway/src/bounds_tests.rs","sha256":"74136bc570da7b9338b5a1a1ed9d3fd892c55135160964f9d3ac0e2cf5741375"},{"path":"product/runtime/auths-gateway/src/commissioning_budget.rs","sha256":"fab29da3269438cc62330f3eab7b5bd4dc482b4db8af243aae47df5d3aa1deb8"},{"path":"product/runtime/auths-gateway/src/commissioning_budget/tests.rs","sha256":"ad182c391b70450582c6ca06e3dadc221409bb3cdbc3c7668dbfc7fbedf63505"},{"path":"product/runtime/auths-gateway/src/commissioning_floor.rs","sha256":"7fa6991c5ccd5ae1403be84b3da390323fab09f36e15ac01fd7a38ea350c6fdb"},{"path":"product/runtime/auths-gateway/src/commissioning_floor/tests.rs","sha256":"5f7868252dfccb787d26f63ea6d5c3701c72d52c0ff0bc656dd5895f8cbed551"},{"path":"product/runtime/auths-gateway/src/commissioning_session.rs","sha256":"24b48d5eaeaaa3c620e2dfc7ee1f9255fc4519a1eb404b8608cea7af6a910ee2"},{"path":"product/runtime/auths-gateway/src/commissioning_session/tests.rs","sha256":"6f8aad6dae4888c147076937c9ec0968e5b5eedde71d4cfcce0d988bd56b83ec"},{"path":"product/runtime/auths-gateway/src/connection.rs","sha256":"7b5d049c258a26ed1c93ecf860f51d051a8a65f9b93554af0b1ea93862398ec9"},{"path":"product/runtime/auths-gateway/src/credential_journal.rs","sha256":"7297fccaee5cd8622928e8e0a42bba50da7941970a6f682ecd300c41ee6509da"},{"path":"product/runtime/auths-gateway/src/echo_verify.rs","sha256":"6d453051665f823abd7354d5c50031d9524cf47d6092d2f09080ae814e3b9575"},{"path":"product/runtime/auths-gateway/src/engine.rs","sha256":"3ae83ee8eef51082084cc047b4f6b0eb26dd33f711cf5c415572366e716257ac"},{"path":"product/runtime/auths-gateway/src/fuzzing.rs","sha256":"ed3b0028487eb546a3b0a91d115aa8f18bcea324b61620bfe8e35a9e6ab18758"},{"path":"product/runtime/auths-gateway/src/generation_floor.rs","sha256":"fe1510ec96ce0f67e9a78edbfa94b33eb7df64c0ac4d0a67901124dcd0164777"},{"path":"product/runtime/auths-gateway/src/harness.rs","sha256":"c87e479f3eb281960f6c9c80d43c7560d7ccb654b0154ec823d3fcec4884ac05"},{"path":"product/runtime/auths-gateway/src/lib.rs","sha256":"47214352c400c50bd7c5cb54c132218960ce2f5dd0285c1dd9dcdebb4651de3a"},{"path":"product/runtime/auths-gateway/src/listener.rs","sha256":"aa08239bcbc1fcb55e8a212fbdf6a84f12985b0d436dcb51dc58b06e59e435f2"},{"path":"product/runtime/auths-gateway/src/observed_tests.rs","sha256":"a22be071695f89ca2578a4d82fd80d9cb82289213c9bdb8f0470f6b2dc3d9201"},{"path":"product/runtime/auths-gateway/src/observer.rs","sha256":"562ffcaea071c3856e0708dc2fe33516917e145d2438aabb75af0a2b6ba01046"},{"path":"product/runtime/auths-gateway/src/onboarding.rs","sha256":"0dfd7d67e7f02f18a28d1c86ca1b7751d7463f5efcdbe3825de0ad8cbccb3891"},{"path":"product/runtime/auths-gateway/src/operator.rs","sha256":"c3c36954a3e86723df035b47f43b85fc8ab3a6292983522b6258d5c6b4e6c4e4"},{"path":"product/runtime/auths-gateway/src/pending_vectors/attempts.rs","sha256":"47ef3c8cb1c5504d47ae9a0088705ce6715fe86bac1671a34a56fb38a64d0dd3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/bounds.rs","sha256":"e612217307e1da5b0eb5ee6582a7458bb064b8aa8a529fc6555b1b334127ab68"},{"path":"product/runtime/auths-gateway/src/pending_vectors/codes.rs","sha256":"e00670a5ef24eb856cc2c6dcda8e5a263842f55c76bb939c0c27bd9df37e5522"},{"path":"product/runtime/auths-gateway/src/pending_vectors/keys.rs","sha256":"f84c56f2ea9cb34b2b79c72d13fbf2c6585010ec1ed450af58a78c80c1ea1edd"},{"path":"product/runtime/auths-gateway/src/pending_vectors/mod.rs","sha256":"5de8340f0ef71a0b57a09e323fefe473d3160c6ae952b9ba46f714825fbacafc"},{"path":"product/runtime/auths-gateway/src/pending_vectors/outcomes.rs","sha256":"8ec07b9511b48913af36ac999d2aa0e82924289f6acb23ddaeb9f00f99815166"},{"path":"product/runtime/auths-gateway/src/pending_vectors/production.rs","sha256":"772d032e0a0d9c924fb6d6c188528db85a97e71c9e466ddc19eee277baf83614"},{"path":"product/runtime/auths-gateway/src/pending_vectors/recipes.rs","sha256":"51693208270231c25c3aef2a32151d5962114c71e86b88cb9df83181c7af83d9"},{"path":"product/runtime/auths-gateway/src/pre_entry.rs","sha256":"06ea78ca140468bfaba17d9ab04912ad68673954c3203c98fed28272ff2a00c0"},{"path":"product/runtime/auths-gateway/src/property_tests.rs","sha256":"939c081e2e154aaf10186754044bdd65608932c899b970a04a71d0afaa999a93"},{"path":"product/runtime/auths-gateway/src/qualification.rs","sha256":"c597c83de2b94f0374ae54e40a8b57c2a64ec6e254704dca32185f448a908aca"},{"path":"product/runtime/auths-gateway/src/qualification_simulation.rs","sha256":"4ee7cadfb5f46a92713c80f3e55f499cb074d04d8b21ea89d57762af38642bfa"},{"path":"product/runtime/auths-gateway/src/qualification_tests.rs","sha256":"a9178a2e58eea459d5e5dafc53a3999ea7c84dbbffefe6e5eb1f3d098827f028"},{"path":"product/runtime/auths-gateway/src/quorum_tests.rs","sha256":"a78380b019104d688c11a4410082c7e08ded3106aab099954c4f8a1b4ae0fd89"},{"path":"product/runtime/auths-gateway/src/readiness.rs","sha256":"911c3f11892f94641574375e2da4c671c802738f71082f12c39832331052d43d"},{"path":"product/runtime/auths-gateway/src/recipe.rs","sha256":"fecf9af67e7afc48d080e9f8f55f8ce28e49d0e08988717a27908bbda461d6b6"},{"path":"product/runtime/auths-gateway/src/recipe/lower.rs","sha256":"8088b8751ed831dbb48247af953c6290ac95e2a438ccd5bd65eff54be06a1fd1"},{"path":"product/runtime/auths-gateway/src/recipe/review.rs","sha256":"c3eb7d9fdd98dacf52750b14b67ad7b7faaecbbdeafff1e0b049f67d0a2d0139"},{"path":"product/runtime/auths-gateway/src/recipe/runtime.rs","sha256":"c286f0d15f974402822c0810d8e97f98411dc1c557755cc23e540d85e2bb42d9"},{"path":"product/runtime/auths-gateway/src/recipe/source.rs","sha256":"1af50298fb1461e1b24cbdf560d43124d6b1c4c529586c911b1c4797214a69ff"},{"path":"product/runtime/auths-gateway/src/recipe/tests.rs","sha256":"aac551a2481bbc60864c64079bc667dcb232e45a0f41a04073ed84ab5dbe1fce"},{"path":"product/runtime/auths-gateway/src/recipe/validate.rs","sha256":"3711b17605cb7b0d639bc1b180449231f5882a306cab20e2c7782155cc63b0d4"},{"path":"product/runtime/auths-gateway/src/scenario_tests.rs","sha256":"a8ea1e3a7bf6b0274455bd790ace3ffb9c8716609cde92248920945c61634685"},{"path":"product/runtime/auths-gateway/src/separation.rs","sha256":"be9306848ca5d801767cf6aa14247c8618312ef0e202f00ce0c24c4844491061"},{"path":"product/runtime/auths-gateway/src/simulation_attestation.rs","sha256":"88705e5d45415f760f1e3c3a065c35c48f4f4065bf7b3feb7882246983814d6f"},{"path":"product/runtime/auths-gateway/src/store.rs","sha256":"884bcad4d70d53e12eae9c8517f6ecd0643068ee0be0370015119d04d6cc2516"},{"path":"product/runtime/auths-gateway/src/store_testkit.rs","sha256":"88d82fee42f1b8ef521e8deef0216e938ebeaad822eb2f5020e70b89d145ea70"},{"path":"product/runtime/auths-gateway/src/submit.rs","sha256":"fe2eacb5ad8152eeecbd232c47a356fc72db0098e34fda99532bdf6ef0cf895c"},{"path":"product/runtime/auths-gateway/src/support.rs","sha256":"9fd979029793a22b15d9776a7fc172476fd7c126a80d4080c65d720845becbcb"},{"path":"product/runtime/auths-gateway/src/transport.rs","sha256":"be2c6dc75b8daec110bf8749fedc3823f6067d40b999aa3eb21126896a97d3ad"},{"path":"product/runtime/auths-kernel-runtime/Cargo.toml","sha256":"926bcd0053e5edd703be8f0027ad009e2982db013c8174c1366edbf38b48087d"},{"path":"product/runtime/auths-kernel-runtime/src/lib.rs","sha256":"7108faae9ca4bc32dc093ddaf885ac8f74f3c9b8d317b7c7d0ed00d1d0ab5972"},{"path":"product/runtime/auths-lifecycle/Cargo.toml","sha256":"c5053c705f8d5554b44e432fe75287a2faf11d644e5a2552e45ad6cd94176af5"},{"path":"product/runtime/auths-lifecycle/src/codec.rs","sha256":"51c4b746749150e8bfcd8ff972b3f6c1ef40bec15583448ec1b471d9ad737dc0"},{"path":"product/runtime/auths-lifecycle/src/digest.rs","sha256":"55282cd7d8aba37713c2dcb5357c9877819edb72a30eadefb860d28d7d3a3eb7"},{"path":"product/runtime/auths-lifecycle/src/identifier.rs","sha256":"31620e8c16de68d3d2d3b84d6353c1a5b9d4151d8247f91fa389b906a8e660f1"},{"path":"product/runtime/auths-lifecycle/src/kernel.rs","sha256":"2abb8c094b36d35b364e74d78091d14c5d6f3d1eb6552cca3b5538dbd017ce23"},{"path":"product/runtime/auths-lifecycle/src/lib.rs","sha256":"afe5a345cd309b5a4f08ffba3170a6d7f16ff914892b3f2006d5208ed24ec736"},{"path":"product/runtime/auths-lifecycle/src/model.rs","sha256":"1af12bbeeeaa65ec02ddcebd7d2c8c92ec1e339fa40ae85b45ab9b01a722a4fa"},{"path":"product/runtime/auths-lifecycle/src/operation.rs","sha256":"78e6d05fcf5d7ea4f148032a3fa26fdfcab77eb346019effe927b08e0d64d732"},{"path":"product/runtime/auths-lifecycle/src/registry.rs","sha256":"53495fe6f7a77422593a41623e28716f1c140dcc1e00f87f6b0ffbfb93a5ef90"},{"path":"product/runtime/auths-lifecycle/src/sealed.rs","sha256":"2e0c03b5813c926c159598bb7890d1523825edbe57cd687d42a5dfb3374a0c19"},{"path":"product/runtime/auths-lifecycle/src/test_support.rs","sha256":"221d9a5c5ef8e1f9f8fd66927484eaf813571d0568470278ecd8fa08a5eec8cd"},{"path":"product/runtime/auths-lifecycle/src/transition.rs","sha256":"011805a28efdd541f44ccea54dd0e34a1e58f4004447ee58013703b4fb6b2822"},{"path":"product/runtime/auths-runtime/Cargo.toml","sha256":"dd29d80a8b4bb56c869f036a6c9998f6e6d1c0383ac5dc03fa42b24abe2a7ff7"},{"path":"product/runtime/auths-runtime/src/lib.rs","sha256":"132ca03d58c14905d3a822a4972f42a22a5ad33a45f2ba9ca44f3a57d810b4b0"},{"path":"product/runtime/auths-runtime/src/production.rs","sha256":"fd4eff4270c571c10fcff6cf27df28961ebf074de8a1a028f500fda1ca376820"},{"path":"product/sdk/auths-approval-quorum/Cargo.toml","sha256":"df904971fca87a24194c5816738a331588fe8f164acb5d70839a35dca5f57114"},{"path":"product/sdk/auths-approval-quorum/src/lib.rs","sha256":"72e4086088a1c0912e4e1a9e980f26a5c280bf5ab16ea39c9f0f58d5096ac2ce"},{"path":"product/sdk/auths-approval-quorum/src/remote.rs","sha256":"9fa029c7c63003adf260f8aec55160c545681c60c1bace0d934e7525862aac7b"},{"path":"product/sdk/auths-approval-quorum/src/remote_tests.rs","sha256":"8a09ce17cfee82a035a74edd535f3ebeb3db0e078784740d3997b17dbdb10197"},{"path":"product/sdk/auths-approval-quorum/src/tests.rs","sha256":"0acbf12be3e497dcc6c2d8f29c9af3b1a7ed8e11b75f6399570d4f217a785060"},{"path":"product/stores/auths-stores/Cargo.toml","sha256":"a32c4b76d17b264be5d40d24497ff237e1ed87822e8bab86229b3db93106dbe3"},{"path":"product/stores/auths-stores/src/gateway_attempt.rs","sha256":"218841602d3d9b23b44625f50e5b54cf275ccedc2d5c89f02d2482b8524472af"},{"path":"product/stores/auths-stores/src/lib.rs","sha256":"e721262edf8a9ab5568ddc27639176312d4a366203b5f73e2d7c11fde2c554e9"},{"path":"product/stores/auths-stores/src/lifecycle.rs","sha256":"3f2cecfda13fdcd7c4a944518646bcc8abd1237f900c0332d5822281f8f9f1cd"}],"schema":"auths.gateway-semantic-closure/1"} \ No newline at end of file +{"files":[{"path":"Cargo.lock","sha256":"0e75e2fdef44e79e57797ac6661295ae58ddb8de4a1990a6fd22ce6c54f78604"},{"path":"Cargo.toml","sha256":"6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24"},{"path":"core/adapters/auths-did-keri/Cargo.toml","sha256":"86ba3e3f9a0a70d970568bfb3113b7ba7bbdd81c3eebbb52743dd574a0c0ecaa"},{"path":"core/adapters/auths-did-keri/src/lib.rs","sha256":"a75674842f8a7142004369ccd206ab43e476459293f0ff4bed4d4e659031b3e3"},{"path":"core/adapters/auths-did-key/Cargo.toml","sha256":"d5a3ae07ecde83f91eed4c3785051dd0f44eab6c891754f3309b6b40596707d7"},{"path":"core/adapters/auths-did-key/src/lib.rs","sha256":"b76a3f4528a725df53cfa9242e6e414e1d26caa48468aaed497e28b121f4497c"},{"path":"core/adapters/auths-raw-key/Cargo.toml","sha256":"f49616bc18c19e6aaa7e6a02ccebcdb9f5c1422c1278ef9869e0dbf22ceda7be"},{"path":"core/adapters/auths-raw-key/src/lib.rs","sha256":"45eec1b295dac3bed65cd79c942870b926b06b3f5d38eaebaeb6140ac69315fa"},{"path":"core/crates/auths-algebra-kernel/Cargo.toml","sha256":"0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba"},{"path":"core/crates/auths-algebra-kernel/src/generated.rs","sha256":"ae4bcbef42a408c7ffa0c6a74a42f7de177a6f14479e51d205acf830bda05960"},{"path":"core/crates/auths-algebra-kernel/src/lib.rs","sha256":"6654667eeb9b353d6648954c9fd2e8838462a82ce6b2803eb49e1366892c68c6"},{"path":"core/crates/auths-assurance/Cargo.toml","sha256":"afcb12a97ddd09d7a264b9ecd3fcaefc865ff2c9b4539ee85b00883420ba333a"},{"path":"core/crates/auths-assurance/src/lib.rs","sha256":"0fb2ec844d674b25a9e20b1601452c89c2454901fa506adfa9bb38ef9a7fa213"},{"path":"core/crates/auths-author/Cargo.toml","sha256":"1e6f0e3bc079ddb558decf0db26b291c6e72fc47327b6df1b7650d41689b215f"},{"path":"core/crates/auths-author/src/lib.rs","sha256":"e14475f2f49715a1869d5fa6b11ff1fbb72497e39097e09f833b0bae7e5b3f2b"},{"path":"core/crates/auths-author/src/observations.rs","sha256":"dda7d6bfa6f4bd7e95a480ca283c2c0e996f69c5c15cb0c7197af328131a7066"},{"path":"core/crates/auths-authority/Cargo.toml","sha256":"4f68212938029f79ebd857b4f3038494eb85d0163d49f07e51376715cf959815"},{"path":"core/crates/auths-authority/src/lib.rs","sha256":"da88d5194de4e17449e69972c0fb042afa3c39798a8f570f30771e77c384f1eb"},{"path":"core/crates/auths-codec/Cargo.toml","sha256":"e20e51826e17814effd9d8925d18d5fbdd6c0d37bf50231e743ec2611314722c"},{"path":"core/crates/auths-codec/src/approval.rs","sha256":"fbff43bf4d57f69f8b7738a8647751cde75c5a932dee65d924a1fe9c7202f91f"},{"path":"core/crates/auths-codec/src/bounded_policy.rs","sha256":"d21f6728be2d8a04b6d94921f2b683f7e61cbb42e0ac6866f1c88a49caa534c3"},{"path":"core/crates/auths-codec/src/decode.rs","sha256":"ba2999584cdf53b1b517ecb9c7ea50d39efee17c666a9a38e2ad1ac94379f778"},{"path":"core/crates/auths-codec/src/encode.rs","sha256":"8491192053e2e15d62b4d2a491de22405b7487ead69ab6f6bca40669ce7ca5f7"},{"path":"core/crates/auths-codec/src/error.rs","sha256":"fecb0737c16deb42d859f1dc7727c698438d9ac12064fd99e0024629642c390c"},{"path":"core/crates/auths-codec/src/hash.rs","sha256":"f88e111f1dbb2cef6b7b5e9c948cb45ff92e366710c8a5f5c636138aa748479e"},{"path":"core/crates/auths-codec/src/lib.rs","sha256":"3b0e5c94c6f34f750b88a9333e1d5c8145746d845d3a23e0d2f61807cf592ea7"},{"path":"core/crates/auths-codec/src/observation.rs","sha256":"38328b0c71ff97a4196eeade8b4faa889527ff1f80bb168468bcd49082a3987e"},{"path":"core/crates/auths-composition/Cargo.toml","sha256":"331e13025eb82588b5269ed3975929eb41c823d588c49e4c296273d85c6fe80e"},{"path":"core/crates/auths-composition/src/lib.rs","sha256":"e42e3b0b6a9985b73c533aeb23799c638979aa27a9ce7d0f10a8d60340570fb1"},{"path":"core/crates/auths-model/Cargo.toml","sha256":"565c15302b0cc9270db1e28efa3862804846850ba933cc17aea8abcec4a65987"},{"path":"core/crates/auths-model/src/approval.rs","sha256":"54cf44a9ef747ec21546a4086aecfb130bc7803b0d646430e6082df51e6e305f"},{"path":"core/crates/auths-model/src/bounded.rs","sha256":"f90496abc0a06c028b4d850af6ddab7d850bfafeaa3d042f1b1246a41d8bbbc9"},{"path":"core/crates/auths-model/src/bounded_policy.rs","sha256":"306a8f049cc7cfc7635fe0e4de47eb7813eed63d3c14c3be2b51586aa4eea450"},{"path":"core/crates/auths-model/src/lib.rs","sha256":"e7cfe6bb9574c6b016aa63e70658c31e0b90903ec6479a49f4a2ceb64f5bad97"},{"path":"core/crates/auths-model/src/observation.rs","sha256":"b3ed3e3cc090afca2896a7d3de7988afccc1ee1ea0ebd91b51a8bc0f20ad8dbb"},{"path":"core/crates/auths-multikey/Cargo.toml","sha256":"858756c1197befcada06134742bffe8d58cf674cadd6c046bf710570e96efaf2"},{"path":"core/crates/auths-multikey/src/lib.rs","sha256":"f5177fffb11e40eeaaa665ba886c541fc1f24d5eacdd6983fb03dc20148733f0"},{"path":"core/crates/auths-ports/Cargo.toml","sha256":"596a9b0f5af3717c16a6d13f7054d8a106bcd9f01f5f72c2235dd2afcf0ab16c"},{"path":"core/crates/auths-ports/src/binding.rs","sha256":"a16c012d40aa4249e3ec54372b9611006d0bfe8c7dc3c741911c2194ad17736d"},{"path":"core/crates/auths-ports/src/diagnostics.rs","sha256":"aa596572503b5a65a918bb2ff38281c144ff53821ee914e9325c852828d852df"},{"path":"core/crates/auths-ports/src/lib.rs","sha256":"8da1debf86f9532df0660155d04298beb1ba3a1204508f8586e2e67cd2fb3449"},{"path":"core/crates/auths-ports/src/path.rs","sha256":"b68fc547b4e4d97a60cbbc1cc1939fc6b34a8233b81f840bd396914a707e3ea1"},{"path":"core/crates/auths-raw-key-core/Cargo.toml","sha256":"98c0bc8527a537512e43a74dd6ba9658c6f0cdc16610cf938e3f9b43785d836d"},{"path":"core/crates/auths-raw-key-core/src/lib.rs","sha256":"98c0500c41697aae28708ad0bf970b9a97583d96a3d2c18d23e7fa351e0f7d12"},{"path":"core/crates/auths-registries/Cargo.toml","sha256":"590e49e58b0622d9d6274fea46796dcdb07dec9550eff295cce6a6427ffa51e2"},{"path":"core/crates/auths-registries/src/lib.rs","sha256":"450d3886d85ee333b7e046317fb5b47cde62483d5f3e41d46265e2caf4c373ec"},{"path":"core/crates/auths-registries/src/template.rs","sha256":"1224039dd2b3ce6fa8357613d8cafbae40400493da7176da202b9ade62fa05e4"},{"path":"core/crates/auths-signature-core/Cargo.toml","sha256":"6bee2230eb30af1be0bd5c2d57bd3e1903497a70028d47290d4ac6e9e0e8bca0"},{"path":"core/crates/auths-signature-core/src/lib.rs","sha256":"6e3f9311ded5e49ea50d445eb21e6d8fa12442aa4362a73e0cb6fda15b7cd865"},{"path":"core/crates/auths-signature/Cargo.toml","sha256":"7f7b5682466ba439d8c59579022cb61068cad9fb4bd2d73e1cc21327c902b450"},{"path":"core/crates/auths-signature/src/lib.rs","sha256":"b3d9ac4cc3ba0797b9e1c09f2d6ac05089b25dac4e285a5af28c0165b33d925b"},{"path":"core/crates/auths-verifier/Cargo.toml","sha256":"c43358e06a33324b41a8b93e5cc7279c55f7d21f1f6cfaa539a3fc7b4c27a38f"},{"path":"core/crates/auths-verifier/src/approval.rs","sha256":"c3cae6a49e169051eb555bb092b1069a4d422516d6a2114623a89e5f31ff923f"},{"path":"core/crates/auths-verifier/src/causal.rs","sha256":"9635230f33b13a263573d319ac8a1976addbcc07677514a43e3c7bf28dc04587"},{"path":"core/crates/auths-verifier/src/lib.rs","sha256":"f22dec38dfa47ced8da4f605390da8453273bee1da010f57fd1fdfcb10e0b389"},{"path":"core/crates/auths-verifier/src/observation.rs","sha256":"0bb07f06a0f9524c88427df1c972b1de8ba038a9eeeb15d3134c25125ae84b1e"},{"path":"core/crates/auths-verifier/src/trace.rs","sha256":"2213d72023a1d9e0413a2cf2c51c3dad9e04775d86033a0caaa9d29a8f0036f8"},{"path":"exchange/crates/auths-proof-exchange-model/Cargo.toml","sha256":"34b2db64f93a288e942b5a3918d28cdcbef906e0dc9074ce848018d3d5f7a1fa"},{"path":"exchange/crates/auths-proof-exchange-model/src/lib.rs","sha256":"49fac5aff2339d3a57c41cb8bb2a82852538e8f77ecc4b157c88e264ff31fb55"},{"path":"exchange/crates/auths-proof-exchange-port/Cargo.toml","sha256":"7ff660f1b7579dc570c791090aeb450404fbbf44c92781e289f5ccdde746d739"},{"path":"exchange/crates/auths-proof-exchange-port/src/lib.rs","sha256":"b408fb40c6432edc1facb3d8b3e9433a033f8dc73fe2e0ba5a88c972ca675021"},{"path":"product/config/auths-config/Cargo.toml","sha256":"e4b568ab9f6d84f7d7e6d66443fe825f360db9c27bc7c31d6ddc0647ba3ab304"},{"path":"product/config/auths-config/src/lib.rs","sha256":"fecf00ea65cef9018fda9af2063326d7065b869266d0d9e73a4f06816f1102cc"},{"path":"product/errors/auths-errors/Cargo.toml","sha256":"3b3a199b6460ba75bda84475bb5accd35e1485448a3981038db85bf4772dd350"},{"path":"product/errors/auths-errors/src/lib.rs","sha256":"7feeb9069fa4003f94f1f07c1c94619cf1c883e0dbaaf2187f04d0f742264bdd"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/Cargo.toml","sha256":"716f1f2a117d6d69d8effe9ee9057e24ba3502f20af6a602b06facb638cdabed"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/api.rs","sha256":"9ea61dd7ddd93282b073b98e453e6b75b26dc49689c04e9782435d06a3a09e48"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/clock.rs","sha256":"73f0a6e0f5903883329fa6683f5888288f759512ac69e5c87efd2b6b87f7d79f"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/http.rs","sha256":"14c1fce14e24c984b2a275563a29b6326fb08367922b6e8d37ba38b9cb81aa2b"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/identity.rs","sha256":"186de11230c8b33375951c4368609f8976bf9795f171af3fd7fac26207a94361"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs","sha256":"0b4617d044f5254a5ab22f5a2578f91cc025206a8c1845be39c1c56dcdf7a5df"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/names.rs","sha256":"41bb23572d6002e23ee103d6fe70ecd68764861c6f2e48a1c53af998270a4afa"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs","sha256":"39fed883f4802e68d3b41a68fea0aba0737810996b33d13577de70faba004c29"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/store.rs","sha256":"fc60ee9c49b2f4f063c449b4c78100c5c4872779e94ca168f796603b380ef6e4"},{"path":"product/integrations/auths-custody/Cargo.toml","sha256":"1e14034185ad1ec24a977fd5f41d0abee219606245c046ce2a82287fadef448b"},{"path":"product/integrations/auths-custody/src/conformance.rs","sha256":"8ed1afd58f18fc6becc268908aa6419c9aa404c79da0197963eb2599df44acf6"},{"path":"product/integrations/auths-custody/src/key.rs","sha256":"70cbb0fd21b6f5652157845a22c35be2d0f6c05b3d138fc4b9bb6dbdc3d81c40"},{"path":"product/integrations/auths-custody/src/lib.rs","sha256":"8ee593c1f59b0fd2126bdda9138026f5bc531beb64d4489a99785842e7b98b43"},{"path":"product/operations/auths-operations/Cargo.toml","sha256":"73dde1e914ba5e1386f8d49c0d730423cc72ae77ec44c6554a6a75cc8e8922b1"},{"path":"product/operations/auths-operations/src/explanation.rs","sha256":"b4a39bcbd5712cb9e735ee7deeb281f3fa6af5ddca973735bf3d87dce427ef11"},{"path":"product/operations/auths-operations/src/lib.rs","sha256":"3f401a56555113b98f57bca172a2660eaecedf76247b83a3fdbb089c133a29cd"},{"path":"product/operations/auths-operations/src/render/json.rs","sha256":"2ae042639960afee123730e945d373bc5dda1d2b3af20ae16c939a7e99b9e418"},{"path":"product/operations/auths-operations/src/render/mod.rs","sha256":"b3b7f6fe473f49227ace5a68bfc3d8dc14b5db8dd9888fd9e207070337b1b8bf"},{"path":"product/operations/auths-operations/src/render/text.rs","sha256":"f216cf3bdb00e264523271b16e7059535ac6b1aabf271cebd7935af155e4bfec"},{"path":"product/policy/auths-bounded-policy/Cargo.toml","sha256":"babd5d200923137ead71d8c2528f847cea323ce98da942a1320b054436612c47"},{"path":"product/policy/auths-bounded-policy/src/arithmetic.rs","sha256":"75e43c5d4eab8d1f71c1daf53839f5f9fe45a400afc1f63a30c6f55ce3632627"},{"path":"product/policy/auths-bounded-policy/src/commitment.rs","sha256":"c5706f2d583454e1a7f570f7ada138d4d864bef0205dfae7c1296774f396bb3f"},{"path":"product/policy/auths-bounded-policy/src/eligibility.rs","sha256":"c9acdfb793074e687fc36efad506be27dbd99ffbf40387bc66c8de39ef238432"},{"path":"product/policy/auths-bounded-policy/src/identifier.rs","sha256":"0006a32bae9eb16c4178cf797df418d2b0a781f2bc6474b741dc1a908141831c"},{"path":"product/policy/auths-bounded-policy/src/kernel.rs","sha256":"99187c28b161ac70bee1afed60711f7f645adb4d1671a01863f9849b369811d5"},{"path":"product/policy/auths-bounded-policy/src/lib.rs","sha256":"76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c"},{"path":"product/policy/auths-bounded-policy/src/receipt.rs","sha256":"3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad"},{"path":"product/policy/auths-bounded-policy/src/registry.rs","sha256":"4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0"},{"path":"product/profiles/auths-profile-api/Cargo.toml","sha256":"7ae85761f58625b5d678f961fd052eebf3e000ef565c7312e3ac857763c0017f"},{"path":"product/profiles/auths-profile-api/src/lib.rs","sha256":"a194b82b20bf8aa864c2334ef6c6aec30b2154ded972862252d5dcefa488ab95"},{"path":"product/profiles/auths-profile-mcp/Cargo.toml","sha256":"db264fc25242f7b7e4133cbe5782545b3107b406c87168ae072683cfb59eac66"},{"path":"product/profiles/auths-profile-mcp/src/arguments.rs","sha256":"a5de696586d507e2aee4a49fee99ef1ef4c51a2e46603f8838f1af6d9009833f"},{"path":"product/profiles/auths-profile-mcp/src/lib.rs","sha256":"d0f8b733a09ef8408336cdebc8948d6a5861012ce6878598b11be7084dfd4280"},{"path":"product/profiles/auths-profile-mcp/src/session.rs","sha256":"166c281fa66333388e4760d6098dad02d3359e1d5de4b8f93312c014f97abb03"},{"path":"product/qualification/auths-recipe-qualification/Cargo.toml","sha256":"b7b15b30b9a3d96d4f089d514266d3a892de6608d30707aa44be31cca89ca9fe"},{"path":"product/qualification/auths-recipe-qualification/src/canonical.rs","sha256":"30a9b50777f0dcb4b606abfee2467d5a975d9f6ad941ab6c13ca3df5b359f667"},{"path":"product/qualification/auths-recipe-qualification/src/closure.rs","sha256":"0ad6aee9bd981e2863fa725f209ec84031db2ff12f4c7ac3aaf5120f0bb86039"},{"path":"product/qualification/auths-recipe-qualification/src/commissioning.rs","sha256":"66ea49f96887c4642139a48d259c270816e2267ee8cf6344a1340fe47afda9da"},{"path":"product/qualification/auths-recipe-qualification/src/commissioning/tests.rs","sha256":"5a226725c2ad7ce920d0bd62d427185e007f4d0949b0f0ec1260aa161d3114d0"},{"path":"product/qualification/auths-recipe-qualification/src/error.rs","sha256":"52d5cf720a1e4579008fdda90a3ac2c31f0b8db57985f121f65e54b4da2b7dd1"},{"path":"product/qualification/auths-recipe-qualification/src/evidence.rs","sha256":"ba45a7409d67a8af26ab811af306412014557477a101ab2a8eb0faf8f2bd4b91"},{"path":"product/qualification/auths-recipe-qualification/src/ids.rs","sha256":"e81a906d571497ab2da753e1532d4443706410e0b75fdd59a7d2d788c7aec403"},{"path":"product/qualification/auths-recipe-qualification/src/launch.rs","sha256":"41f2e2de90e1e7d6440a66eda3eb9bea8d5e0741bc232305a76a363ab5f813c1"},{"path":"product/qualification/auths-recipe-qualification/src/lib.rs","sha256":"7d26c5bfe9769daebf90c5c2280e0d75742e4cc70d0e608408e0665e3f516a2b"},{"path":"product/qualification/auths-recipe-qualification/src/model.rs","sha256":"3484eb0ec287b23d4682ade7b1b0f8d1335985b3fb180f06fc28716076957d5f"},{"path":"product/qualification/auths-recipe-qualification/src/release.rs","sha256":"ec478e53f70052e566aac7e15be2f9e1b1cd46837ac6990ae955fa864d311586"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/mod.rs","sha256":"fa23a962fd90331152eed5edbcdf271955f7aed79b8da1e065bfe69a20b487a9"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/schemas.rs","sha256":"c59feec2805621f341a90f81fc005e2c12f7a70f9d264fdeacccb2be4fe1c046"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/verification.rs","sha256":"6a6b5834c5dae10af1ba8939b2deae43b85db71544dc8f077ff63b7fe68ac8a8"},{"path":"product/qualification/auths-recipe-qualification/src/verify.rs","sha256":"2ec2784435d11e07295de77b2ee1b2c48b2fcf9609a00454c6e7374b621aed5c"},{"path":"product/receipts/auths-receipts/Cargo.toml","sha256":"6001fa1375899953aafcb07c23a6da0c8f57ea7ec08bb9c950b12a60a8cc6f0f"},{"path":"product/receipts/auths-receipts/src/disclosure.rs","sha256":"ba9ed439be0a320c8a01f5b6e9b51361c1a37e076947490d8e4a484ba6bb119c"},{"path":"product/receipts/auths-receipts/src/lib.rs","sha256":"547a57c4160256719cafb7d0ab972d9fc80b0da14fbbce4148c70c414070ff36"},{"path":"product/runtime/auths-connections/Cargo.toml","sha256":"babeb6e1dda3dfb66291713ce1e43dce5c349833d0b50ea4dccbf986030026b2"},{"path":"product/runtime/auths-connections/src/credential.rs","sha256":"82921413bb053f0f6c7931fbd4e6a86c8cc1d8c6b51debd9c2cef33a8d5b1c51"},{"path":"product/runtime/auths-connections/src/kernel.rs","sha256":"a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8"},{"path":"product/runtime/auths-connections/src/lib.rs","sha256":"79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22"},{"path":"product/runtime/auths-connections/src/model.rs","sha256":"de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77"},{"path":"product/runtime/auths-connections/src/registry.rs","sha256":"e57640e003e72ad3235c567c2bb944a262bd64e673f023b62ea091094cc7e946"},{"path":"product/runtime/auths-gateway-kernel/Cargo.toml","sha256":"34f864e67656af4ac7e5c7a347a23f01fc8ab31365b8e23c0ef474483b14a183"},{"path":"product/runtime/auths-gateway-kernel/src/construct.rs","sha256":"e9d65744bae273d65face4285e5d2da75c06a92ab48f7b8333d496604e31c63c"},{"path":"product/runtime/auths-gateway-kernel/src/lib.rs","sha256":"cfda6f8453426564c085475f183b6f790b438768a19668f1b65d33ba59dc8632"},{"path":"product/runtime/auths-gateway-kernel/src/order.rs","sha256":"e0045f877c4b7fe3860c291039853885064ddcdebba7c9b345ab65e81e646dda"},{"path":"product/runtime/auths-gateway-kernel/src/outcome.rs","sha256":"e9785b1afe70788c89b51b18655bcd5acff7b0c8e3d12fb79c6f05a202e67e6b"},{"path":"product/runtime/auths-gateway-kernel/src/ratio.rs","sha256":"7ace22264812e6fc1ef3a62afee402cf43494bb71ae0d3de219ad1b39d690bcb"},{"path":"product/runtime/auths-gateway-kernel/src/recovery.rs","sha256":"9f46dcd1685ab6e4d1ba04a3fc286a9f3afee8fb47829be1fbc670a7926a2dc6"},{"path":"product/runtime/auths-gateway-kernel/src/transition.rs","sha256":"cefb8f01d915880f6921f2501ff881ad94b9de61072c34d9cd19220992f97374"},{"path":"product/runtime/auths-gateway/Cargo.toml","sha256":"00b28be86921dcdc0ad90cce0c62c2961cafefe96ea6c2edf0e926c3d405ccad"},{"path":"product/runtime/auths-gateway/src/admin.rs","sha256":"2d5cc67afac42fbd15f36e2d1693cd1b20cedacf775040dce6ffe04ccc94c9ea"},{"path":"product/runtime/auths-gateway/src/app.rs","sha256":"6f80f63833ea0815bb44fbf3b0cc54624a08e9fb578b035819f2980dc04e8256"},{"path":"product/runtime/auths-gateway/src/audit.rs","sha256":"0edb2037eb7b5d6f13acfce85c54f62a82bf7fdd31bc7e626c4fec183cef61dd"},{"path":"product/runtime/auths-gateway/src/audit_tests.rs","sha256":"990969384a52d75bc2489d9d412a9e7dd814bca1c8f65c701d6205fae62a15d5"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway-harness.rs","sha256":"12b0c24d36b2e6a3be392d3c081a783b355fdd67dc5b54bacc0410e803116b8c"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway.rs","sha256":"89e5e073e3be743f40dbf17d3fdad61f94de2da3dc1d10dd0e67c85b1f8f874b"},{"path":"product/runtime/auths-gateway/src/binding.rs","sha256":"663b0ce878319511aa7d05722ab4ab2fa9be18817884ffb2ee9f131ff1e382d1"},{"path":"product/runtime/auths-gateway/src/bounds.rs","sha256":"38251ad6f22f9d07ef9a219c79fa265ca36f1526eca5f147d7efa46b52ad609d"},{"path":"product/runtime/auths-gateway/src/bounds_aggregate_tests.rs","sha256":"ab34f227b7c8692ba1da88ccb32bb3687a66adf8353d8282fae905d4a88eb612"},{"path":"product/runtime/auths-gateway/src/bounds_tests.rs","sha256":"74136bc570da7b9338b5a1a1ed9d3fd892c55135160964f9d3ac0e2cf5741375"},{"path":"product/runtime/auths-gateway/src/commissioning_budget.rs","sha256":"fab29da3269438cc62330f3eab7b5bd4dc482b4db8af243aae47df5d3aa1deb8"},{"path":"product/runtime/auths-gateway/src/commissioning_budget/tests.rs","sha256":"ad182c391b70450582c6ca06e3dadc221409bb3cdbc3c7668dbfc7fbedf63505"},{"path":"product/runtime/auths-gateway/src/commissioning_floor.rs","sha256":"7fa6991c5ccd5ae1403be84b3da390323fab09f36e15ac01fd7a38ea350c6fdb"},{"path":"product/runtime/auths-gateway/src/commissioning_floor/tests.rs","sha256":"5f7868252dfccb787d26f63ea6d5c3701c72d52c0ff0bc656dd5895f8cbed551"},{"path":"product/runtime/auths-gateway/src/commissioning_session.rs","sha256":"24b48d5eaeaaa3c620e2dfc7ee1f9255fc4519a1eb404b8608cea7af6a910ee2"},{"path":"product/runtime/auths-gateway/src/commissioning_session/tests.rs","sha256":"8f8ff5175cecf8a49b8e4acfcd4fa3179cfb656c53275d8246aff59de7c6ae0d"},{"path":"product/runtime/auths-gateway/src/connection.rs","sha256":"7b5d049c258a26ed1c93ecf860f51d051a8a65f9b93554af0b1ea93862398ec9"},{"path":"product/runtime/auths-gateway/src/credential_journal.rs","sha256":"7297fccaee5cd8622928e8e0a42bba50da7941970a6f682ecd300c41ee6509da"},{"path":"product/runtime/auths-gateway/src/echo_verify.rs","sha256":"6d453051665f823abd7354d5c50031d9524cf47d6092d2f09080ae814e3b9575"},{"path":"product/runtime/auths-gateway/src/engine.rs","sha256":"1b4ec0f0692a9af7fa29a0dabb3d22192d70fdb704b369d406e2cd8204dc82fe"},{"path":"product/runtime/auths-gateway/src/fuzzing.rs","sha256":"ed3b0028487eb546a3b0a91d115aa8f18bcea324b61620bfe8e35a9e6ab18758"},{"path":"product/runtime/auths-gateway/src/generation_floor.rs","sha256":"fe1510ec96ce0f67e9a78edbfa94b33eb7df64c0ac4d0a67901124dcd0164777"},{"path":"product/runtime/auths-gateway/src/harness.rs","sha256":"c87e479f3eb281960f6c9c80d43c7560d7ccb654b0154ec823d3fcec4884ac05"},{"path":"product/runtime/auths-gateway/src/lib.rs","sha256":"1a36e2276a96645a76bf109ad9e687a743934e31349ffb0b9e5b1c271e0385c8"},{"path":"product/runtime/auths-gateway/src/listener.rs","sha256":"aa08239bcbc1fcb55e8a212fbdf6a84f12985b0d436dcb51dc58b06e59e435f2"},{"path":"product/runtime/auths-gateway/src/observed_tests.rs","sha256":"a22be071695f89ca2578a4d82fd80d9cb82289213c9bdb8f0470f6b2dc3d9201"},{"path":"product/runtime/auths-gateway/src/observer.rs","sha256":"562ffcaea071c3856e0708dc2fe33516917e145d2438aabb75af0a2b6ba01046"},{"path":"product/runtime/auths-gateway/src/onboarding.rs","sha256":"0dfd7d67e7f02f18a28d1c86ca1b7751d7463f5efcdbe3825de0ad8cbccb3891"},{"path":"product/runtime/auths-gateway/src/operator.rs","sha256":"c3c36954a3e86723df035b47f43b85fc8ab3a6292983522b6258d5c6b4e6c4e4"},{"path":"product/runtime/auths-gateway/src/pending_vectors/attempts.rs","sha256":"47ef3c8cb1c5504d47ae9a0088705ce6715fe86bac1671a34a56fb38a64d0dd3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/bounds.rs","sha256":"e612217307e1da5b0eb5ee6582a7458bb064b8aa8a529fc6555b1b334127ab68"},{"path":"product/runtime/auths-gateway/src/pending_vectors/codes.rs","sha256":"e00670a5ef24eb856cc2c6dcda8e5a263842f55c76bb939c0c27bd9df37e5522"},{"path":"product/runtime/auths-gateway/src/pending_vectors/keys.rs","sha256":"f84c56f2ea9cb34b2b79c72d13fbf2c6585010ec1ed450af58a78c80c1ea1edd"},{"path":"product/runtime/auths-gateway/src/pending_vectors/mod.rs","sha256":"5de8340f0ef71a0b57a09e323fefe473d3160c6ae952b9ba46f714825fbacafc"},{"path":"product/runtime/auths-gateway/src/pending_vectors/outcomes.rs","sha256":"8ec07b9511b48913af36ac999d2aa0e82924289f6acb23ddaeb9f00f99815166"},{"path":"product/runtime/auths-gateway/src/pending_vectors/production.rs","sha256":"772d032e0a0d9c924fb6d6c188528db85a97e71c9e466ddc19eee277baf83614"},{"path":"product/runtime/auths-gateway/src/pending_vectors/recipes.rs","sha256":"51693208270231c25c3aef2a32151d5962114c71e86b88cb9df83181c7af83d9"},{"path":"product/runtime/auths-gateway/src/pre_entry.rs","sha256":"06ea78ca140468bfaba17d9ab04912ad68673954c3203c98fed28272ff2a00c0"},{"path":"product/runtime/auths-gateway/src/property_tests.rs","sha256":"939c081e2e154aaf10186754044bdd65608932c899b970a04a71d0afaa999a93"},{"path":"product/runtime/auths-gateway/src/qualification.rs","sha256":"c597c83de2b94f0374ae54e40a8b57c2a64ec6e254704dca32185f448a908aca"},{"path":"product/runtime/auths-gateway/src/qualification_simulation.rs","sha256":"4ee7cadfb5f46a92713c80f3e55f499cb074d04d8b21ea89d57762af38642bfa"},{"path":"product/runtime/auths-gateway/src/qualification_tests.rs","sha256":"a9178a2e58eea459d5e5dafc53a3999ea7c84dbbffefe6e5eb1f3d098827f028"},{"path":"product/runtime/auths-gateway/src/quorum_tests.rs","sha256":"a78380b019104d688c11a4410082c7e08ded3106aab099954c4f8a1b4ae0fd89"},{"path":"product/runtime/auths-gateway/src/readiness.rs","sha256":"911c3f11892f94641574375e2da4c671c802738f71082f12c39832331052d43d"},{"path":"product/runtime/auths-gateway/src/recipe.rs","sha256":"fecf9af67e7afc48d080e9f8f55f8ce28e49d0e08988717a27908bbda461d6b6"},{"path":"product/runtime/auths-gateway/src/recipe/lower.rs","sha256":"8088b8751ed831dbb48247af953c6290ac95e2a438ccd5bd65eff54be06a1fd1"},{"path":"product/runtime/auths-gateway/src/recipe/review.rs","sha256":"c3eb7d9fdd98dacf52750b14b67ad7b7faaecbbdeafff1e0b049f67d0a2d0139"},{"path":"product/runtime/auths-gateway/src/recipe/runtime.rs","sha256":"c286f0d15f974402822c0810d8e97f98411dc1c557755cc23e540d85e2bb42d9"},{"path":"product/runtime/auths-gateway/src/recipe/source.rs","sha256":"1af50298fb1461e1b24cbdf560d43124d6b1c4c529586c911b1c4797214a69ff"},{"path":"product/runtime/auths-gateway/src/recipe/tests.rs","sha256":"aac551a2481bbc60864c64079bc667dcb232e45a0f41a04073ed84ab5dbe1fce"},{"path":"product/runtime/auths-gateway/src/recipe/validate.rs","sha256":"3711b17605cb7b0d639bc1b180449231f5882a306cab20e2c7782155cc63b0d4"},{"path":"product/runtime/auths-gateway/src/scenario_tests.rs","sha256":"a8ea1e3a7bf6b0274455bd790ace3ffb9c8716609cde92248920945c61634685"},{"path":"product/runtime/auths-gateway/src/separation.rs","sha256":"be9306848ca5d801767cf6aa14247c8618312ef0e202f00ce0c24c4844491061"},{"path":"product/runtime/auths-gateway/src/simulation_attestation.rs","sha256":"88705e5d45415f760f1e3c3a065c35c48f4f4065bf7b3feb7882246983814d6f"},{"path":"product/runtime/auths-gateway/src/store.rs","sha256":"884bcad4d70d53e12eae9c8517f6ecd0643068ee0be0370015119d04d6cc2516"},{"path":"product/runtime/auths-gateway/src/store_testkit.rs","sha256":"88d82fee42f1b8ef521e8deef0216e938ebeaad822eb2f5020e70b89d145ea70"},{"path":"product/runtime/auths-gateway/src/submit.rs","sha256":"fe2eacb5ad8152eeecbd232c47a356fc72db0098e34fda99532bdf6ef0cf895c"},{"path":"product/runtime/auths-gateway/src/support.rs","sha256":"9fd979029793a22b15d9776a7fc172476fd7c126a80d4080c65d720845becbcb"},{"path":"product/runtime/auths-gateway/src/transport.rs","sha256":"be2c6dc75b8daec110bf8749fedc3823f6067d40b999aa3eb21126896a97d3ad"},{"path":"product/runtime/auths-kernel-runtime/Cargo.toml","sha256":"926bcd0053e5edd703be8f0027ad009e2982db013c8174c1366edbf38b48087d"},{"path":"product/runtime/auths-kernel-runtime/src/lib.rs","sha256":"7108faae9ca4bc32dc093ddaf885ac8f74f3c9b8d317b7c7d0ed00d1d0ab5972"},{"path":"product/runtime/auths-lifecycle/Cargo.toml","sha256":"c5053c705f8d5554b44e432fe75287a2faf11d644e5a2552e45ad6cd94176af5"},{"path":"product/runtime/auths-lifecycle/src/codec.rs","sha256":"51c4b746749150e8bfcd8ff972b3f6c1ef40bec15583448ec1b471d9ad737dc0"},{"path":"product/runtime/auths-lifecycle/src/digest.rs","sha256":"55282cd7d8aba37713c2dcb5357c9877819edb72a30eadefb860d28d7d3a3eb7"},{"path":"product/runtime/auths-lifecycle/src/identifier.rs","sha256":"31620e8c16de68d3d2d3b84d6353c1a5b9d4151d8247f91fa389b906a8e660f1"},{"path":"product/runtime/auths-lifecycle/src/kernel.rs","sha256":"2abb8c094b36d35b364e74d78091d14c5d6f3d1eb6552cca3b5538dbd017ce23"},{"path":"product/runtime/auths-lifecycle/src/lib.rs","sha256":"afe5a345cd309b5a4f08ffba3170a6d7f16ff914892b3f2006d5208ed24ec736"},{"path":"product/runtime/auths-lifecycle/src/model.rs","sha256":"1af12bbeeeaa65ec02ddcebd7d2c8c92ec1e339fa40ae85b45ab9b01a722a4fa"},{"path":"product/runtime/auths-lifecycle/src/operation.rs","sha256":"78e6d05fcf5d7ea4f148032a3fa26fdfcab77eb346019effe927b08e0d64d732"},{"path":"product/runtime/auths-lifecycle/src/registry.rs","sha256":"53495fe6f7a77422593a41623e28716f1c140dcc1e00f87f6b0ffbfb93a5ef90"},{"path":"product/runtime/auths-lifecycle/src/sealed.rs","sha256":"2e0c03b5813c926c159598bb7890d1523825edbe57cd687d42a5dfb3374a0c19"},{"path":"product/runtime/auths-lifecycle/src/test_support.rs","sha256":"221d9a5c5ef8e1f9f8fd66927484eaf813571d0568470278ecd8fa08a5eec8cd"},{"path":"product/runtime/auths-lifecycle/src/transition.rs","sha256":"011805a28efdd541f44ccea54dd0e34a1e58f4004447ee58013703b4fb6b2822"},{"path":"product/runtime/auths-runtime/Cargo.toml","sha256":"dd29d80a8b4bb56c869f036a6c9998f6e6d1c0383ac5dc03fa42b24abe2a7ff7"},{"path":"product/runtime/auths-runtime/src/lib.rs","sha256":"132ca03d58c14905d3a822a4972f42a22a5ad33a45f2ba9ca44f3a57d810b4b0"},{"path":"product/runtime/auths-runtime/src/production.rs","sha256":"fd4eff4270c571c10fcff6cf27df28961ebf074de8a1a028f500fda1ca376820"},{"path":"product/sdk/auths-approval-quorum/Cargo.toml","sha256":"df904971fca87a24194c5816738a331588fe8f164acb5d70839a35dca5f57114"},{"path":"product/sdk/auths-approval-quorum/src/lib.rs","sha256":"72e4086088a1c0912e4e1a9e980f26a5c280bf5ab16ea39c9f0f58d5096ac2ce"},{"path":"product/sdk/auths-approval-quorum/src/remote.rs","sha256":"9fa029c7c63003adf260f8aec55160c545681c60c1bace0d934e7525862aac7b"},{"path":"product/sdk/auths-approval-quorum/src/remote_tests.rs","sha256":"8a09ce17cfee82a035a74edd535f3ebeb3db0e078784740d3997b17dbdb10197"},{"path":"product/sdk/auths-approval-quorum/src/tests.rs","sha256":"0acbf12be3e497dcc6c2d8f29c9af3b1a7ed8e11b75f6399570d4f217a785060"},{"path":"product/stores/auths-stores/Cargo.toml","sha256":"a32c4b76d17b264be5d40d24497ff237e1ed87822e8bab86229b3db93106dbe3"},{"path":"product/stores/auths-stores/src/gateway_attempt.rs","sha256":"218841602d3d9b23b44625f50e5b54cf275ccedc2d5c89f02d2482b8524472af"},{"path":"product/stores/auths-stores/src/lib.rs","sha256":"e721262edf8a9ab5568ddc27639176312d4a366203b5f73e2d7c11fde2c554e9"},{"path":"product/stores/auths-stores/src/lifecycle.rs","sha256":"3f2cecfda13fdcd7c4a944518646bcc8abd1237f900c0332d5822281f8f9f1cd"}],"schema":"auths.gateway-semantic-closure/1"} \ No newline at end of file diff --git a/product/runtime/auths-gateway/src/bin/auths-gateway.rs b/product/runtime/auths-gateway/src/bin/auths-gateway.rs index b9737cde4..ef7dd3179 100644 --- a/product/runtime/auths-gateway/src/bin/auths-gateway.rs +++ b/product/runtime/auths-gateway/src/bin/auths-gateway.rs @@ -273,6 +273,23 @@ mod unix { #[arg(long)] profile_lock: PathBuf, }, + /// Offline native proof review: derive the exact credential-free + /// request and actors without installation, custody or provider I/O. + ReviewSubmission { + #[arg(long)] + recipe: PathBuf, + #[arg(long)] + profile_lock: PathBuf, + #[arg(long)] + trusted_context: PathBuf, + #[arg(long)] + proof: PathBuf, + #[arg(long)] + action: PathBuf, + /// Offline evaluation time; no lease or production clock override. + #[arg(long, value_parser = clap::value_parser!(u64).range(..=253_402_300_799))] + evaluated_at: Option, + }, /// Print the grant extension committing to a ceiling on one verified /// integer argument and a count per fixed, epoch-aligned window, and /// optionally a sum limit per listed partition value and a scope, as @@ -356,6 +373,19 @@ mod unix { #[arg(long, default_value_t = false)] tuple: bool, }, + /// Print the planned production tuple from this executable and the + /// reviewed recipe, without installing custody or contacting a provider. + /// This is candidate identity, never qualification or readiness. + QualificationCandidate { + #[arg(long)] + recipe: PathBuf, + #[arg(long)] + profile_lock: PathBuf, + #[arg(long)] + recipe_family: String, + #[arg(long)] + provider_contract_id: String, + }, /// Authenticated operator-only fresh commissioning registration. /// Registers finite capacity once; never resets existing consumption. CommissioningInit { @@ -1598,6 +1628,32 @@ mod unix { }) } + fn qualification_candidate( + recipe_path: &Path, + lock_path: &Path, + family: &str, + contract: &str, + ) -> Result { + let source = read_bounded(recipe_path, 65_536)?; + let lock = read_bounded(lock_path, 65_536)?; + let recipe = installable_recipe(&source, &lock)?; + let executable = std::env::current_exe() + .and_then(fs::read) + .map_err(|_| "gateway.qualification.unavailable")?; + deployment_tuple(&DeploymentFacts { + recipe_family: family, + provider_contract_id: contract, + compiled_recipe_sha256: *recipe.digest(), + profile_lock_sha256: Sha256::digest(&lock).into(), + gateway_build_sha256: Sha256::digest(&executable).into(), + store_kind: LifecycleStoreKind::PostgresqlV1, + store_schema: POSTGRES_STORE_SCHEMA, + credential_store_kind: CredentialStoreKind::parse("aws-secrets-manager-v1") + .map_err(|_| "gateway.qualification.unavailable")?, + }) + .ok_or_else(|| "gateway.qualification.unavailable".into()) + } + /// Builds the installation's gate and loads the inputs the operator /// imported. The policy is decided again from the deployment, so an /// edited manifest cannot relax production. Only a changed installation @@ -2433,6 +2489,42 @@ mod unix { Ok(()) } + fn review_submission_files( + recipe_path: &Path, + lock_path: &Path, + context_path: &Path, + proof_path: &Path, + action_path: &Path, + evaluated_at: Option, + ) -> Result<(), Failure> { + let recipe = installable_recipe( + &read_bounded(recipe_path, 65_536)?, + &read_bounded(lock_path, 65_536)?, + )?; + let trust = read_bounded(context_path, 4 * 1024 * 1024)?; + let context = auths_codec::decode_verifier_context(&trust) + .map_err(|_| "gateway.verify.invalid-trust")?; + let proof = read_bounded(proof_path, 4 * 1024 * 1024)?; + let action = read_bounded(action_path, 64 * 1024)?; + let result = auths_gateway::review_submission( + &recipe, + &context, + match evaluated_at { + Some(timestamp) => timestamp, + None => now()?, + }, + &proof, + &action, + ); + let encoded = match result { + Ok(reviewed) => serde_json::to_string(&reviewed), + Err(refusal) => serde_json::to_string(&refusal), + } + .map_err(|_| "gateway.output")?; + println!("{encoded}"); + Ok(()) + } + /// Parses `=,...`. fn listed_values(text: &str) -> Result { let invalid = "gateway.policy.invalid-policy"; @@ -3392,6 +3484,29 @@ mod unix { .await .map_err(|_| "gateway.qualification.unavailable")? } + Command::QualificationCandidate { + recipe, + profile_lock, + recipe_family, + provider_contract_id, + } => { + let candidate = tokio::task::spawn_blocking(move || { + qualification_candidate( + &recipe, + &profile_lock, + &recipe_family, + &provider_contract_id, + ) + }) + .await + .map_err(|_| "gateway.qualification.unavailable")??; + println!( + "{}", + serde_json_canonicalizer::to_string(&candidate) + .map_err(|_| "gateway.qualification.unavailable")? + ); + Ok(()) + } Command::CommissioningInit { session } => commissioning(&session, None).await, Command::CommissioningSubmit { session, @@ -3437,6 +3552,25 @@ mod unix { recipe, profile_lock, } => Ok(review(&recipe, &profile_lock)?), + Command::ReviewSubmission { + recipe, + profile_lock, + trusted_context, + proof, + action, + evaluated_at, + } => tokio::task::spawn_blocking(move || { + review_submission_files( + &recipe, + &profile_lock, + &trusted_context, + &proof, + &action, + evaluated_at, + ) + }) + .await + .map_err(|_| "gateway.verify.invalid-input")?, Command::BoundExtension(options) => Ok(bound_extension(&options)?), Command::Audit { bundle, @@ -3675,6 +3809,58 @@ mod unix { #[cfg(test)] mod tests { use super::*; + + #[test] + fn candidate_identity_needs_no_installation_and_binds_the_running_bytes() { + let directory = tempfile::tempdir().expect("candidate input"); + let recipe = directory.path().join("recipe.json"); + let lock = directory.path().join("profile.lock.json"); + fs::write( + &recipe, + include_bytes!( + "../../../../../qualification/simulation/live/stripe-platform/recipe.json" + ), + ) + .expect("recipe"); + fs::write( + &lock, + include_bytes!( + "../../../../../qualification/simulation/live/stripe-platform/profile.lock.json" + ), + ) + .expect("lock"); + let contract = "1".repeat(64); + let tuple = + qualification_candidate(&recipe, &lock, "stripe-platform-refund-v1", &contract) + .expect("candidate"); + assert_eq!(tuple.target.store_kind, LifecycleStoreKind::PostgresqlV1); + assert_eq!(tuple.target.store_schema.as_str(), POSTGRES_STORE_SCHEMA); + assert!(tuple.target.credential_store_kind.is_production()); + assert_eq!( + tuple.target.gateway_build_sha256.to_hex(), + digest(&fs::read(std::env::current_exe().expect("executable")).expect("bytes")) + ); + assert_eq!(fs::read_dir(directory.path()).expect("inputs").count(), 2); + for (family, contract) in [ + ("../another-family", contract.as_str()), + ("stripe-platform-refund-v1", "wrong"), + ] { + assert!(qualification_candidate(&recipe, &lock, family, contract).is_err()); + } + let mut changed: serde_json::Value = + serde_json::from_slice(&fs::read(&recipe).expect("source")).expect("recipe"); + changed["tool"] = serde_json::json!("another_tool"); + fs::write(&recipe, serde_json::to_vec(&changed).expect("changed")).expect("source"); + assert!( + qualification_candidate( + &recipe, + &lock, + "stripe-platform-refund-v1", + &"1".repeat(64) + ) + .is_err() + ); + } use auths_gateway::listener::APP_CAPACITY; #[test] diff --git a/product/runtime/auths-gateway/src/commissioning_session/tests.rs b/product/runtime/auths-gateway/src/commissioning_session/tests.rs index afe51afa8..4e2a3127c 100644 --- a/product/runtime/auths-gateway/src/commissioning_session/tests.rs +++ b/product/runtime/auths-gateway/src/commissioning_session/tests.rs @@ -20,6 +20,56 @@ use std::{os::unix::fs::PermissionsExt as _, sync::atomic::Ordering}; const NOW: u64 = 1_790_000_000; +#[tokio::test] +async fn offline_review_verifies_exact_actors_and_requests_without_custody() { + let setup = Setup::new().await; + let engine = setup.engine(); + let before = setup.leases(); + let reviewed = crate::review_submission( + &engine.recipe, + &engine.trusted_context, + NOW, + &setup.proof, + &setup.action, + ) + .expect("reviewed native proof"); + assert_eq!(reviewed.schema, "auths.gateway-submission-review/1"); + assert_eq!(reviewed.actors.len(), 1); + assert_eq!( + Sha256Digest::from_bytes(Sha256::digest(reviewed.actors[0].as_bytes()).into()), + setup.permit.body().statement.binding.principal_sha256 + ); + assert_eq!( + reviewed.action_commitment, + setup.permit.body().statement.binding.allowed_actions[0].to_hex() + ); + let serialized = serde_json::to_value(&reviewed).expect("public projection"); + assert_eq!(serialized["request"]["method"], "POST"); + assert!( + serialized["request"]["headers"] + .as_array() + .expect("headers") + .iter() + .all(|header| header[0] != "Authorization") + ); + let mut changed_action = setup.action.clone(); + changed_action.push(0); + let mut changed_proof = setup.proof.clone(); + let last = changed_proof.last_mut().expect("proof"); + *last ^= 1; + for (proof, action) in [ + (changed_proof.as_slice(), setup.action.as_slice()), + (setup.proof.as_slice(), changed_action.as_slice()), + (&[][..], setup.action.as_slice()), + ] { + assert!( + crate::review_submission(&engine.recipe, &engine.trusted_context, NOW, proof, action) + .is_err() + ); + } + assert_eq!(setup.leases(), before); +} + struct Setup { installation: Installation, directory: tempfile::TempDir, diff --git a/product/runtime/auths-gateway/src/engine.rs b/product/runtime/auths-gateway/src/engine.rs index 8e6b7ad5e..d2f547bfc 100644 --- a/product/runtime/auths-gateway/src/engine.rs +++ b/product/runtime/auths-gateway/src/engine.rs @@ -114,6 +114,87 @@ pub struct GatewayEvidenceSummary { pub observed_at: u64, } +/// A verified submission's bounded, credential-free request projection for +/// offline operator review and differential qualification. It grants no +/// execution authority and records no claim, lease, provider entry or receipt. +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] +pub struct GatewaySubmissionReview { + /// Exactly `auths.gateway-submission-review/1`. + pub schema: &'static str, + /// Every exact actor whose action branch the native verifier authorized. + pub actors: Vec, + /// Native commitment to the verified canonical action bytes. + pub action_commitment: String, + /// Typed profile arguments decoded from the verified action. + pub arguments: Map, + /// The closed outbound request, before any credential is attached. + pub request: GatewayRequestReview, +} + +/// Public request facts used to compare an independently reviewed oracle. +/// No authorization header or provider response is included. +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] +pub struct GatewayRequestReview { + /// Closed HTTP method. + pub method: String, + /// Recipe-derived HTTPS URL. + pub url: String, + /// Recipe-derived body media type. + pub content_type: String, + /// Exact bounded UTF-8 JSON or form body. + pub body: String, + /// Ordered recipe-derived headers, without credential material. + pub headers: Vec<(String, String)>, + /// Declared derived idempotency key, if any. + pub idempotency_key: Option, +} + +/// Reviews proof and action through the same native verification and closed +/// request construction as submission, without opening custody or a store. +/// `now` is an offline evaluation input; this function grants no lease and +/// cannot replace the production deployment clock. +/// +/// # Errors +/// Returns the exact native/profile refusal for invalid or unauthorized input. +/// A successful review establishes only offline eligibility; lifecycle, +/// qualification, custody, guard, evidence and capacity checks still apply +/// when the operator submits through an installed gateway. +#[cfg(unix)] +pub fn review_submission( + recipe: &CompiledRecipe, + context: &TrustedContext, + now: u64, + proof: &[u8], + action: &[u8], +) -> Result { + let command = verify_detailed(recipe, context, now, proof, action)?; + let request = &command.request; + Ok(GatewaySubmissionReview { + schema: "auths.gateway-submission-review/1", + actors: command + .actors + .iter() + .map(|actor| actor.as_str().to_owned()) + .collect(), + action_commitment: hex::encode(request.action_commitment()), + arguments: command.arguments, + request: GatewayRequestReview { + method: request.method().as_str().to_owned(), + url: request.url().to_owned(), + content_type: request.content_type().to_owned(), + body: std::str::from_utf8(request.body()) + .map_err(|_| not_entered("gateway.action.projection"))? + .to_owned(), + headers: request + .headers() + .iter() + .map(|header| (header.name().to_owned(), header.value().to_owned())) + .collect(), + idempotency_key: request.idempotency_key().map(str::to_owned), + }, + }) +} + impl From<&GatewayProviderEvidence> for GatewayEvidenceSummary { fn from(evidence: &GatewayProviderEvidence) -> Self { Self { diff --git a/product/runtime/auths-gateway/src/lib.rs b/product/runtime/auths-gateway/src/lib.rs index e7e5533ab..1b397fae6 100644 --- a/product/runtime/auths-gateway/src/lib.rs +++ b/product/runtime/auths-gateway/src/lib.rs @@ -17,7 +17,8 @@ pub mod commissioning_budget; pub mod commissioning_floor; #[cfg(unix)] pub use engine::{ - CommissioningSession, CommissioningSessionInputs, commissioning_principal_sha256, + CommissioningSession, CommissioningSessionInputs, GatewayRequestReview, + GatewaySubmissionReview, commissioning_principal_sha256, review_submission, }; mod connection; mod credential_journal; diff --git a/product/runtime/auths-gateway/src/semantic_closure.rs b/product/runtime/auths-gateway/src/semantic_closure.rs index 47ec8b594..a323ab1fb 100644 --- a/product/runtime/auths-gateway/src/semantic_closure.rs +++ b/product/runtime/auths-gateway/src/semantic_closure.rs @@ -10,7 +10,7 @@ /// SHA-256 of the schema, a NUL byte, and `semantic-closure.json`. /// Regenerate through `semantic_closure_is_current` with `AUTHS_UPDATE_FIXTURES=1`. pub const GATEWAY_SEMANTIC_CLOSURE_SHA256: &str = - "44a2ed495e507420b2ba834dcb208a3a6a0e5c3ea37af389174072a91e8239d2"; + "f4341fa858a06ea4219b9098ae9d143a1653907095d028be66b9efcfb2c9db28"; #[cfg(test)] mod tests { diff --git a/qualification/README.md b/qualification/README.md index 5d1b16073..f213a92ab 100644 --- a/qualification/README.md +++ b/qualification/README.md @@ -60,7 +60,7 @@ simulation; the shipping lease gate has no bypass. The implemented commissioning [ADR 0016](../docs/adr/0016-bounded-qualification-commissioning-authority.md): a finite signed permit for an authenticated private qualification-run session, with exact action commitments, durable lease accounting and a fixed expiry. -Its verifier, durable budget and private operator commands are implemented. It cannot qualify a family or enable an ordinary application lease; the protected reference and workflow still need to produce its exact bindings. +Its verifier, durable budget and private operator commands are implemented. It cannot qualify a family or enable an ordinary application lease. The [reviewed references](reference/README.md) independently derive exact resource/action bindings; the protected family setup and workflow still need to execute them. The current executable corpus also fixes exact request/evidence digests before running, while disposable live resource identifiers may be created during setup. @@ -116,11 +116,13 @@ harness step harness cleanup ``` -`prepare` installs the candidate in `/gateway-state`, installs the +`prepare` writes the reviewed recipe and lock into ``, installs the consumer packages, and writes `packages.json`. The candidate gateway itself -prints `tuple.json`; the release tool checks the declared contract ID against -`contract.json`. `prepare-live` acquires disposable resources, starts the live -candidate. `run/live.sh` always calls `cleanup`, including after setup or stage +prints its planned production `tuple.json` through `qualification-candidate`, +without custody or provider access; the release tool checks the declared contract ID against +`contract.json`. `prepare-live` installs production custody for the disposable resources and +compares `qualification-status --tuple` with that planned tuple before any +permit import or submission. A changed installation fails closed. `run/live.sh` always calls `cleanup`, including after setup or stage failure; cleanup must remove disposable resources idempotently, and its failure fails the run. Both setup commands receive `AUTHS_GATEWAY` and `AUTHS_QUALIFICATION`. Only the protected live environment supplies @@ -179,7 +181,7 @@ The first qualification uses the separate finite authority in [ADR 0016](../docs/adr/0016-bounded-qualification-commissioning-authority.md). `auths-qualification certify-commissioner` certifies a separate key with only the commissioning-permit purpose; normal `certify` grants only release purposes. -The root key remains offline and never enters either provider runner. +The root key remains offline and never enters either provider runner. Both purpose-separated signer keys were provisioned on 7 October 2026 into the reviewer-protected, main-only `recipe-qualification-signing` environment. No private root material was uploaded. After the protected reference expands disposable resources and exact actions, `auths-qualification commissioning-sign` takes `--binding`, `--conformance`, diff --git a/qualification/reference/README.md b/qualification/reference/README.md new file mode 100644 index 000000000..b3239a2e2 --- /dev/null +++ b/qualification/reference/README.md @@ -0,0 +1,48 @@ +# Reviewed commissioning references + +These are release-only provider references, outside shipping packages. They +neither hold provider credentials nor publish qualification evidence. + +`stripe_platform.py` independently derives the platform-account test refund; +`airtable_record.py` derives the dedicated table's one-field update. The +resource carrier is closed, unique, bounded and tied to one protected run. +Only the dedicated owner-authorized Airtable base/table may replace the two +synthetic fixed path members. Every other recipe member and the exact profile +lock must agree with reviewed source, including guards and ceilings. + +`expand.py` receives public packet files, resource bindings, the original +candidate binary, tuple and canonical conformance/differential evidence. It +hashes the candidate without executing it. It invokes only a reviewer binary +that the signing job builds from its own checkout, with an empty environment, +through `qualification-candidate` and `review-submission`. No program from a +downloaded artifact runs with a signing key. + +Native proof review supplies the exact actors, canonical action commitments +and decoded arguments. The provider reference supplies the expected request. +Their request mappings must agree byte-for-byte before an action enters the +unsigned binding. All actions must have one exact actor, the installed trust +must match, and the lease ceiling is a source-owned 64 acquisitions. The +native issuer separately rechecks both offline artifacts and their mandatory +scenarios before signing. An expansion is neither a live report nor a permit. + +```text +python qualification/reference/expand.py \ + --reviewer \ + --candidate \ + --tuple --recipe --profile-lock \ + --resources --packets \ + --conformance --differential \ + --source-commit \ + --protected-run recipe-qualification// \ + --out-dir +``` + +The public packet carrier is `auths.qualification-public-packets/1`, with +`protected_run`, `trusted_context` (one adjacent filename), and 1–64 `packets`. +Each packet contains `label`, `proof`, `action` (adjacent filenames), and its +expected `arguments`. Unknown fields, path traversal, changed source, wrong +production targets, resource widening, actor changes or an oracle mismatch +prevent output. Filenames never select code. Private author keys are absent. + +The protected family setup, complete corpus and live workflow still need to +use these references. No family is qualified by landing this code. diff --git a/qualification/reference/airtable_record.py b/qualification/reference/airtable_record.py new file mode 100644 index 000000000..1e817f48a --- /dev/null +++ b/qualification/reference/airtable_record.py @@ -0,0 +1,75 @@ +"""Independent Airtable field-update reference, confined to release tooling.""" + +import copy +import urllib.parse + +from common import canonical, closed, digest, echo, identifier, require, text + +FAMILY = 'airtable-record-update-v1' +SERVICE = 'airtable-gateway-demo' +TOOL = 'set_demo_status_v1' +ENVIRONMENT = 'disposable-live-resources' + +# The owner-authorized dedicated field-lab table. A different fixed base/table +# changes the recipe digest and requires an explicit reference review. +BASE = 'appQD3Qf0YFBCW9bV' +TABLE = 'tblBx2jwe0IsPYRKT' + + +def resources(value, protected_run): + closed(value, ['schema', 'protected_run', 'base', 'table', 'records']) + require(value['schema'] == 'auths.airtable-record-qualification-resources/1' + and value['protected_run'] == protected_run + and value['base'] == BASE and value['table'] == TABLE, + 'qualification.reference.resource-binding') + require(type(value['records']) is list and 1 <= len(value['records']) <= 32, + 'qualification.reference.resource-bound') + seen = set() + for record in value['records']: + closed(record, ['id', 'run_metadata']) + record_id = identifier(record['id'], r'rec[A-Za-z0-9]{14}') + require(record_id not in seen and record['run_metadata'] == protected_run, + 'qualification.reference.resource-binding') + seen.add(record_id) + return value + + +def request(arguments, bound_resources, action_commitment, recipe_digest): + closed(arguments, ['operator_namespace', 'operation_id', 'recipe_digest', + 'record_id', 'replacement']) + require(arguments['operator_namespace'] == 'airtable-demo' + and digest(arguments['recipe_digest']) == digest(recipe_digest), + 'qualification.reference.recipe-binding') + operation = text(arguments['operation_id'], maximum=128) + require(any(record['id'] == arguments['record_id'] for record in bound_resources['records']), + 'qualification.reference.resource-binding') + require(arguments['replacement'] in ['Approved', 'Pending'], + 'qualification.reference.replacement') + token = echo('airtable-demo', operation, action_commitment) + path = '/'.join(urllib.parse.quote(segment, safe='') for segment in + ['v0', BASE, TABLE, arguments['record_id']]) + return { + 'method': 'PATCH', 'url': 'https://api.airtable.com/' + path, + 'content_type': 'application/json', + 'body': canonical({'fields': {'DemoStatus': arguments['replacement'], + 'auths_echo': token}}).decode(), + 'headers': [], 'idempotency_key': None, + } + + +def recipe(template, bound_resources): + require(template['service'] == SERVICE and template['tool'] == TOOL + and template['origin'] == 'https://api.airtable.com', + 'qualification.reference.recipe-binding') + result = copy.deepcopy(template) + expected = [ + {'kind': 'fixed', 'value': 'v0'}, + {'kind': 'fixed', 'value': 'appTEST0000000001'}, + {'kind': 'fixed', 'value': 'tblTEST0000000001'}, + {'kind': 'field', 'name': 'record_id'}, + ] + for path in [result['write']['path'], result['observation']['path']]: + require(path == expected, 'qualification.reference.recipe-binding') + path[1]['value'] = bound_resources['base'] + path[2]['value'] = bound_resources['table'] + return result diff --git a/qualification/reference/common.py b/qualification/reference/common.py new file mode 100644 index 000000000..acd1c1c23 --- /dev/null +++ b/qualification/reference/common.py @@ -0,0 +1,65 @@ +"""Bounded byte/encoding primitives for reviewed, release-only references.""" + +import hashlib +import json +import re + + +class Refusal(ValueError): + """A stable, secret-free reference refusal.""" + + +def require(condition, code): + if not condition: + raise Refusal(code) + + +def closed(value, fields): + require(type(value) is dict and set(value) == set(fields), + 'qualification.reference.closed-fields') + + +def text(value, minimum=1, maximum=256): + require(type(value) is str and minimum <= len(value.encode('utf-8')) <= maximum + and all(ord(character) >= 32 for character in value), + 'qualification.reference.text-bound') + return value + + +def identifier(value, pattern): + require(type(value) is str and re.fullmatch(pattern, value) is not None, + 'qualification.reference.resource-binding') + return value + + +def integer(value, minimum, maximum): + require(type(value) is int and minimum <= value <= maximum, + 'qualification.reference.integer-bound') + return value + + +def digest(value): + return identifier(value, r'[0-9a-f]{64}') + + +def canonical(value): + # Reference carriers contain no floating-point values. Native code owns + # CBOR and protocol commitments; this is only the ASCII request oracle. + return json.dumps(value, sort_keys=True, separators=(',', ':'), + ensure_ascii=False, allow_nan=False).encode('utf-8') + + +def sha256(value): + return hashlib.sha256(value).hexdigest() + + +def echo(namespace, operation, action_commitment): + digest(action_commitment) + return 'auths-e1-' + sha256(b'auths.gateway-echo/1\0' + namespace.encode() + + b'\0' + operation.encode() + b'\0' + + bytes.fromhex(action_commitment)) + + +def idempotency(namespace, operation): + return 'auths-i1-' + sha256(b'auths.gateway-idempotency-key/1\0' + + namespace.encode() + b'\0' + operation.encode()) diff --git a/qualification/reference/expand.py b/qualification/reference/expand.py new file mode 100644 index 000000000..780735ab2 --- /dev/null +++ b/qualification/reference/expand.py @@ -0,0 +1,194 @@ +#!/usr/bin/env python3 +"""Recompute finite commissioning bindings from reviewed source and public input. + +Run only the reviewer binary built by the signing job from its own checkout. +The downloaded candidate is hashed, never executed in the signing environment. +No program, expected request, actor or action commitment from an artifact is +trusted. The resulting binding is still unsigned and proves no live behavior. +""" + +import argparse +import json +import os +from pathlib import Path +import stat +import subprocess +import sys + +import airtable_record +import stripe_platform +from common import Refusal, canonical, closed, digest, identifier, require, sha256, text + +REFERENCES = {reference.FAMILY: reference for reference in [stripe_platform, airtable_record]} +MAXIMUM_LEASES = 64 +REPOSITORY = Path(__file__).resolve().parents[2] +SOURCES = { + stripe_platform.FAMILY: REPOSITORY / 'qualification/simulation/live/stripe-platform', + airtable_record.FAMILY: REPOSITORY / 'bindings/fixtures/gateway/airtable', +} + + +def read(path, maximum): + descriptor = os.open(path, os.O_RDONLY | os.O_NOFOLLOW) + with os.fdopen(descriptor, 'rb') as stream: + metadata = os.fstat(stream.fileno()) + require(stat.S_ISREG(metadata.st_mode) and 0 < metadata.st_size <= maximum, + 'qualification.reference.input-bound') + value = stream.read(maximum + 1) + require(0 < len(value) <= maximum, 'qualification.reference.input-bound') + return value + + +def unique_object(pairs): + value = {} + for key, item in pairs: + require(key not in value, 'qualification.reference.duplicate-field') + value[key] = item + return value + + +def decode(value): + return json.loads(value, object_pairs_hook=unique_object, + parse_constant=lambda _: (_ for _ in ()).throw(Refusal('qualification.reference.number'))) + + +def child(binary, arguments): + # Never inherit signer keys or provider credentials. A reviewed executable + # has no custody input, store, installation or network operation here. + result = subprocess.run([str(binary), *map(str, arguments)], capture_output=True, + timeout=15, env={'PATH': '/usr/bin:/bin'}, cwd='/') + require(result.returncode == 0 and 0 < len(result.stdout) <= 65536 + and len(result.stderr) <= 65536, 'qualification.reference.native-review') + return decode(result.stdout) + + +def member(path, name, commit, tuple_digest): + raw = read(path, 2 * 1024 * 1024) + body = decode(raw) + require(raw == canonical(body) and body['schema'] == 'auths.qualification-evidence/1' + and body['member'] == name and body['commit'] == commit + and body['tuple_sha256'] == tuple_digest, + 'qualification.reference.offline-binding') + # The native issuer subsequently validates the closed evidence type and + # every mandatory scenario. This hash is independently rederived here. + return sha256(body['schema'].encode() + b'\0' + raw) + + +def relative(work, value): + identifier(value, r'[a-zA-Z0-9][a-zA-Z0-9_.-]{0,95}') + return work / value + + +def expand(args): + commit = identifier(args.source_commit, r'[0-9a-f]{40}') + protected_run = text(args.protected_run, maximum=256) + require('GITHUB_SHA' not in os.environ or os.environ['GITHUB_SHA'] == commit, + 'qualification.reference.source-binding') + if 'GITHUB_RUN_ID' in os.environ: + expected = 'recipe-qualification/' + os.environ['GITHUB_RUN_ID'] + '/' + os.environ['GITHUB_RUN_ATTEMPT'] + require(protected_run == expected, 'qualification.reference.run-binding') + tuple_value = decode(read(args.tuple, 65536)) + reference = REFERENCES.get(tuple_value['recipe_family']) + require(reference is not None, 'qualification.reference.family') + target = tuple_value['target'] + require(target['os'] == 'linux' and target['arch'] == 'x86_64' + and target['store_kind'] == 'postgresql-v1' + and target['store_schema'] == 'auths.lifecycle.postgresql/6' + and target['credential_store_kind'] == 'aws-secrets-manager-v1', + 'qualification.reference.production-target') + require(sha256(read(args.candidate, 256 * 1024 * 1024)) == target['gateway_build_sha256'], + 'qualification.reference.candidate-bytes') + actual = child(args.reviewer, ['qualification-candidate', '--recipe', args.recipe, + '--profile-lock', args.profile_lock, '--recipe-family', reference.FAMILY, + '--provider-contract-id', tuple_value['provider_contract_id']]) + # Separate builds can differ in executable bytes. Their source-owned + # semantic closure, compiled recipe, lock and all other target fields must + # agree. Only the original candidate digest enters signed authority. + actual['target']['gateway_build_sha256'] = target['gateway_build_sha256'] + require(actual == tuple_value, 'qualification.reference.candidate-binding') + resources_raw = read(args.resources, 65536) + bound_resources = reference.resources(decode(resources_raw), protected_run) + require(resources_raw == canonical(bound_resources), 'qualification.reference.resource-canonical') + source = SOURCES[reference.FAMILY] + expected_recipe = reference.recipe(decode(read(source / 'recipe.json', 65536)), bound_resources) + require(decode(read(args.recipe, 65536)) == expected_recipe + and read(args.profile_lock, 65536) == read(source / 'profile.lock.json', 65536), + 'qualification.reference.reviewed-source') + plan = decode(read(args.packets, 65536)) + closed(plan, ['schema', 'protected_run', 'trusted_context', 'packets']) + require(plan['schema'] == 'auths.qualification-public-packets/1' + and plan['protected_run'] == protected_run + and type(plan['packets']) is list and 1 <= len(plan['packets']) <= 64, + 'qualification.reference.packet-bound') + work = args.packets.parent + context = relative(work, plan['trusted_context']) + context_bytes = read(context, 4 * 1024 * 1024) + actors, commitments, labels, oracle = set(), set(), set(), [] + for packet in plan['packets']: + closed(packet, ['label', 'proof', 'action', 'arguments']) + label = identifier(packet['label'], r'[a-z][a-z0-9-]{0,63}') + require(label not in labels, 'qualification.reference.packet-bound') + labels.add(label) + proof, action = relative(work, packet['proof']), relative(work, packet['action']) + read(proof, 4 * 1024 * 1024) + read(action, 65536) + reviewed = child(args.reviewer, ['review-submission', '--recipe', args.recipe, + '--profile-lock', args.profile_lock, '--trusted-context', context, + '--proof', proof, '--action', action]) + require(reviewed.get('schema') == 'auths.gateway-submission-review/1' + and len(reviewed['actors']) == 1 and reviewed['arguments'] == packet['arguments'], + 'qualification.reference.proof-binding') + commitment = digest(reviewed['action_commitment']) + expected = reference.request(packet['arguments'], bound_resources, commitment, + tuple_value['compiled_recipe_sha256']) + require(reviewed['request'] == expected, 'qualification.reference.oracle-mismatch') + actors.add(reviewed['actors'][0]) + commitments.add(commitment) + oracle.append({'label': label, 'request_sha256': sha256(canonical(expected)), + 'action_commitment': commitment}) + require(len(actors) == 1, 'qualification.reference.principal-binding') + tuple_digest = sha256(b'auths.qualification-tuple/1\0' + canonical(tuple_value)) + binding = { + 'protected_run': protected_run, 'source_commit': commit, 'tuple': tuple_value, + 'principal_sha256': sha256(next(iter(actors)).encode()), + 'trusted_context_sha256': sha256(context_bytes), 'resources_sha256': sha256(resources_raw), + 'provider_environment_class': reference.ENVIRONMENT, + 'offline_evidence': { + 'conformance_sha256': member(args.conformance, 'conformance', commit, tuple_digest), + 'differential_sha256': member(args.differential, 'differential', commit, tuple_digest), + }, + 'allowed_actions': sorted(commitments), 'maximum_credential_leases': MAXIMUM_LEASES, + } + require(not args.out_dir.exists(), 'qualification.reference.output-exists') + args.out_dir.mkdir(mode=0o700) + (args.out_dir / 'binding.json').write_bytes(canonical(binding)) + (args.out_dir / 'oracle-commitments.json').write_bytes(canonical({ + 'schema': 'auths.qualification-reference-expansion/1', + 'protected_run': protected_run, 'source_commit': commit, + 'binding_sha256': sha256(canonical(binding)), 'oracle': oracle, + 'qualification_issued': False, + })) + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + for argument in ['tuple', 'candidate', 'reviewer', 'recipe', 'profile-lock', 'resources', + 'packets', 'conformance', 'differential', 'out-dir']: + parser.add_argument('--' + argument, type=lambda value: Path(value).absolute(), required=True) + parser.add_argument('--source-commit', required=True) + parser.add_argument('--protected-run', required=True) + args = parser.parse_args() + try: + expand(args) + except Refusal as error: + print(str(error), file=sys.stderr) + return 1 + except (OSError, KeyError, ValueError, TypeError, RecursionError, OverflowError, + subprocess.SubprocessError): + print('qualification.reference.invalid-input', file=sys.stderr) + return 1 + return 0 + + +if __name__ == '__main__': + raise SystemExit(main()) diff --git a/qualification/reference/stripe_platform.py b/qualification/reference/stripe_platform.py new file mode 100644 index 000000000..972532f66 --- /dev/null +++ b/qualification/reference/stripe_platform.py @@ -0,0 +1,70 @@ +"""Independent platform-refund reference. Never imported by shipping code.""" + +import urllib.parse + +from common import closed, digest, echo, idempotency, identifier, integer, require, text + +FAMILY = 'stripe-platform-refund-v1' +SERVICE = 'stripe-platform-refunds' +TOOL = 'create_refund_v1' +ENVIRONMENT = 'provider-test-mode' + + +def resources(value, protected_run): + closed(value, ['schema', 'protected_run', 'platform', 'payments']) + require(value['schema'] == 'auths.stripe-platform-qualification-resources/1' + and value['protected_run'] == protected_run, + 'qualification.reference.resource-binding') + identifier(value['platform'], r'acct_[A-Za-z0-9]{1,64}') + payments = value['payments'] + require(type(payments) is list and 1 <= len(payments) <= 32, + 'qualification.reference.resource-bound') + seen = set() + for payment in payments: + closed(payment, ['id', 'amount_received', 'currency', 'livemode', 'run_metadata']) + payment_id = identifier(payment['id'], r'pi_[A-Za-z0-9]{1,128}') + require(payment_id not in seen and payment['livemode'] is False + and payment['currency'] == 'usd' and payment['run_metadata'] == protected_run, + 'qualification.reference.resource-binding') + integer(payment['amount_received'], 1, 99999999) + seen.add(payment_id) + return value + + +def request(arguments, bound_resources, action_commitment, recipe_digest): + closed(arguments, ['operator_namespace', 'operation_id', 'recipe_digest', + 'payment_intent', 'amount', 'currency']) + require(arguments['operator_namespace'] == SERVICE + and digest(arguments['recipe_digest']) == digest(recipe_digest), + 'qualification.reference.recipe-binding') + operation = text(arguments['operation_id'], maximum=128) + amount = integer(arguments['amount'], 1, 99999999) + require(arguments['currency'] == 'usd', 'qualification.reference.currency-binding') + payment = next((item for item in bound_resources['payments'] + if item['id'] == arguments['payment_intent']), None) + require(payment is not None, 'qualification.reference.resource-binding') + # Only bounded actions that the reviewed live run may actually execute + # enter a permit. Rejected boundary vectors stay in the offline corpus. + require(amount <= 10000 and amount * 10000 <= payment['amount_received'] * 5000, + 'qualification.reference.ceiling') + token = echo(SERVICE, operation, action_commitment) + key = idempotency(SERVICE, operation) + body = urllib.parse.urlencode([ + ('amount', str(amount)), ('metadata[auths_echo]', token), + ('payment_intent', payment['id']), + ]) + return { + 'method': 'POST', 'url': 'https://api.stripe.com/v1/refunds', + 'content_type': 'application/x-www-form-urlencoded', 'body': body, + 'headers': [['Stripe-Version', '2025-03-31.basil'], ['Idempotency-Key', key]], + 'idempotency_key': key, + } + + +def recipe(template, bound_resources): + # No resource or platform header is substituted into this family. + require(template['service'] == SERVICE and template['tool'] == TOOL + and template['origin'] == 'https://api.stripe.com' + and 'account_scope' not in template, + 'qualification.reference.recipe-binding') + return template diff --git a/qualification/reference/tests/test_reference.py b/qualification/reference/tests/test_reference.py new file mode 100644 index 000000000..6fc388325 --- /dev/null +++ b/qualification/reference/tests/test_reference.py @@ -0,0 +1,202 @@ +"""Independent request mappings and finite input boundaries; no live claim.""" + +import copy +import json +import os +from pathlib import Path +import sys +import tempfile +from types import SimpleNamespace +import unittest +from unittest.mock import patch +import urllib.parse + +sys.path.insert(0, str(Path(__file__).resolve().parents[1])) +import airtable_record as airtable +import stripe_platform as stripe +from common import Refusal, echo, idempotency +from common import canonical, sha256 +import expand as expansion +from expand import decode, unique_object + + +RUN = 'recipe-qualification/123/1' +DIGEST = '1' * 64 +COMMITMENT = '2' * 64 + + +class References(unittest.TestCase): + def stripe_resources(self): + return {'schema': 'auths.stripe-platform-qualification-resources/1', 'protected_run': RUN, + 'platform': 'acct_TEST123', 'payments': [ + {'id': 'pi_TEST123', 'amount_received': 2000, 'currency': 'usd', + 'livemode': False, 'run_metadata': RUN}]} + + def stripe_arguments(self): + return {'operator_namespace': stripe.SERVICE, 'operation_id': 'qualified-1', + 'recipe_digest': DIGEST, 'payment_intent': 'pi_TEST123', 'amount': 1000, + 'currency': 'usd'} + + def airtable_resources(self): + return {'schema': 'auths.airtable-record-qualification-resources/1', 'protected_run': RUN, + 'base': airtable.BASE, 'table': airtable.TABLE, + 'records': [{'id': 'recTEST0000000001', 'run_metadata': RUN}]} + + def airtable_arguments(self): + return {'operator_namespace': 'airtable-demo', 'operation_id': 'qualified-1', + 'recipe_digest': DIGEST, 'record_id': 'recTEST0000000001', + 'replacement': 'Approved'} + + def test_stripe_boundary_and_exact_form_have_no_connect_header(self): + resources = stripe.resources(self.stripe_resources(), RUN) + arguments = self.stripe_arguments() + request = stripe.request(arguments, resources, COMMITMENT, DIGEST) + self.assertEqual(request['method'], 'POST') + self.assertEqual(request['url'], 'https://api.stripe.com/v1/refunds') + fields = urllib.parse.parse_qsl(request['body']) + self.assertEqual(fields, [('amount', '1000'), + ('metadata[auths_echo]', echo(stripe.SERVICE, 'qualified-1', COMMITMENT)), + ('payment_intent', 'pi_TEST123')]) + self.assertEqual(request['headers'], [ + ['Stripe-Version', '2025-03-31.basil'], + ['Idempotency-Key', idempotency(stripe.SERVICE, 'qualified-1')]]) + for amount in [0, -1, 1001, True, 10000, 99999999]: + with self.subTest(amount=amount), self.assertRaises(Refusal): + stripe.request({**arguments, 'amount': amount}, resources, COMMITMENT, DIGEST) + + def test_stripe_resources_are_test_only_unique_and_bound_to_the_run(self): + mutations = [ + lambda value: value.update(protected_run='another-run'), + lambda value: value['payments'][0].update(livemode=True), + lambda value: value['payments'][0].update(currency='eur'), + lambda value: value['payments'][0].update(run_metadata='another-run'), + lambda value: value['payments'][0].update(id='pi_TEST123/../../other'), + lambda value: value['payments'].append(copy.deepcopy(value['payments'][0])), + lambda value: value.update(payments=[]), + lambda value: value.update(credential='synthetic-forbidden-input'), + ] + for mutate in mutations: + value = self.stripe_resources() + mutate(value) + with self.assertRaises(Refusal): + stripe.resources(value, RUN) + + def test_airtable_mapping_updates_only_the_reviewed_record_field_and_echo(self): + resources = airtable.resources(self.airtable_resources(), RUN) + arguments = self.airtable_arguments() + request = airtable.request(arguments, resources, COMMITMENT, DIGEST) + self.assertEqual(request['method'], 'PATCH') + self.assertEqual(request['url'], + f'https://api.airtable.com/v0/{airtable.BASE}/{airtable.TABLE}/recTEST0000000001') + self.assertEqual(json.loads(request['body']), {'fields': { + 'DemoStatus': 'Approved', 'auths_echo': echo('airtable-demo', 'qualified-1', COMMITMENT)}}) + self.assertEqual(request['headers'], []) + self.assertIsNone(request['idempotency_key']) + for mutation in [{'replacement': 'Deleted'}, {'record_id': '../other'}, + {'recipe_digest': '3' * 64}, {'operator_namespace': 'other'}, + {'authorization': 'synthetic-forbidden-input'}]: + with self.subTest(mutation=mutation), self.assertRaises(Refusal): + airtable.request({**arguments, **mutation}, resources, COMMITMENT, DIGEST) + + def test_airtable_resource_expansion_preserves_every_other_recipe_member(self): + resources = airtable.resources(self.airtable_resources(), RUN) + root = Path(__file__).resolve().parents[3] + template = json.loads((root / 'bindings/fixtures/gateway/airtable/recipe.json').read_bytes()) + original = copy.deepcopy(template) + expanded = airtable.recipe(template, resources) + self.assertEqual(template, original) + for kind in ['write', 'observation']: + self.assertEqual(expanded[kind]['path'][1]['value'], airtable.BASE) + self.assertEqual(expanded[kind]['path'][2]['value'], airtable.TABLE) + expanded[kind]['path'] = original[kind]['path'] + self.assertEqual(expanded, original) + for key in ['base', 'table', 'protected_run']: + with self.assertRaises(Refusal): + airtable.resources({**resources, key: 'another-resource'}, RUN) + + def test_duplicate_json_fields_and_nonfinite_numbers_never_choose_authority(self): + for source in [b'{"resource":1,"resource":2}', b'{"resource":NaN}', b'{"resource":Infinity}']: + with self.assertRaises(Refusal): + decode(source) + with self.assertRaises(Refusal): + unique_object([('member', 'conformance'), ('member', 'differential')]) + + def test_binding_is_rederived_and_altered_source_or_native_observations_refuse(self): + # This isolated unit stub checks expansion plumbing, not cryptographic + # proof validity or a production tuple. Real native proof review has a + # separate Rust test over the frozen quorum corpus. + root = Path(__file__).resolve().parents[3] + with tempfile.TemporaryDirectory() as directory: + work = Path(directory) + source = root / 'qualification/simulation/live/stripe-platform' + for name in ['recipe.json', 'profile.lock.json']: + (work / name).write_bytes((source / name).read_bytes()) + (work / 'candidate').write_bytes(b'synthetic test-only candidate, not an executable') + (work / 'context.cbor').write_bytes(b'synthetic test-only context') + (work / 'proof.cbor').write_bytes(b'synthetic test-only proof') + (work / 'action.cbor').write_bytes(b'synthetic test-only action') + (work / 'resources.json').write_bytes(canonical(self.stripe_resources())) + (work / 'packets.json').write_bytes(canonical({ + 'schema': 'auths.qualification-public-packets/1', 'protected_run': RUN, + 'trusted_context': 'context.cbor', 'packets': [{'label': 'normal', + 'proof': 'proof.cbor', 'action': 'action.cbor', + 'arguments': self.stripe_arguments()}]})) + artifacts = json.loads((root / 'bindings/fixtures/qualification/commissioning-v1.json').read_bytes()) + tuple_value = json.loads(artifacts['permit'])['statement']['binding']['tuple'] + tuple_value['recipe_family'] = stripe.FAMILY + tuple_value['compiled_recipe_sha256'] = DIGEST + tuple_value['target']['gateway_build_sha256'] = sha256((work / 'candidate').read_bytes()) + tuple_value['target']['store_schema'] = 'auths.lifecycle.postgresql/6' + (work / 'tuple.json').write_bytes(canonical(tuple_value)) + tuple_digest = sha256(b'auths.qualification-tuple/1\0' + canonical(tuple_value)) + for member_name in ['conformance', 'differential']: + (work / (member_name + '.json')).write_bytes(canonical({ + 'schema': 'auths.qualification-evidence/1', 'member': member_name, + 'commit': '1' * 40, 'tuple_sha256': tuple_digest, 'cases': [], + })) + args = SimpleNamespace(source_commit='1' * 40, protected_run=RUN, + tuple=work / 'tuple.json', candidate=work / 'candidate', reviewer=work / 'not-an-executable', + recipe=work / 'recipe.json', profile_lock=work / 'profile.lock.json', + resources=work / 'resources.json', packets=work / 'packets.json', + conformance=work / 'conformance.json', differential=work / 'differential.json', + out_dir=work / 'expanded') + def review(_binary, arguments): + if arguments[0] == 'qualification-candidate': + return copy.deepcopy(tuple_value) + return {'schema': 'auths.gateway-submission-review/1', + 'actors': ['raw:synthetic-test-only-actor'], 'action_commitment': COMMITMENT, + 'arguments': self.stripe_arguments(), + 'request': stripe.request(self.stripe_arguments(), self.stripe_resources(), COMMITMENT, DIGEST)} + with patch.dict(os.environ, {'GITHUB_SHA': '1' * 40, 'GITHUB_RUN_ID': '123', + 'GITHUB_RUN_ATTEMPT': '1'}), patch('expand.child', side_effect=review): + expansion.expand(args) + binding = json.loads((args.out_dir / 'binding.json').read_bytes()) + self.assertEqual(binding['allowed_actions'], [COMMITMENT]) + self.assertEqual(binding['maximum_credential_leases'], 64) + self.assertEqual(binding['principal_sha256'], sha256(b'raw:synthetic-test-only-actor')) + self.assertEqual(binding['resources_sha256'], sha256((work / 'resources.json').read_bytes())) + self.assertEqual(binding['trusted_context_sha256'], sha256(b'synthetic test-only context')) + self.assertFalse(json.loads((args.out_dir / 'oracle-commitments.json').read_bytes())['qualification_issued']) + args.out_dir = work / 'changed' + recipe = json.loads((work / 'recipe.json').read_bytes()) + del recipe['credential']['guard'] + (work / 'recipe.json').write_bytes(canonical(recipe)) + with self.assertRaisesRegex(Refusal, 'reviewed-source'): + expansion.expand(args) + self.assertFalse(args.out_dir.exists()) + (work / 'recipe.json').write_bytes((source / 'recipe.json').read_bytes()) + def mismatched_review(binary, arguments): + value = review(binary, arguments) + if arguments[0] == 'review-submission': + value['request']['url'] = 'https://attacker.invalid/write' + return value + with patch('expand.child', side_effect=mismatched_review), self.assertRaisesRegex(Refusal, 'oracle-mismatch'): + expansion.expand(args) + self.assertFalse(args.out_dir.exists()) + (work / 'candidate').write_bytes(b'changed synthetic candidate') + with self.assertRaisesRegex(Refusal, 'candidate-bytes'): + expansion.expand(args) + + +if __name__ == '__main__': + unittest.main() diff --git a/qualification/run/offline.sh b/qualification/run/offline.sh index 7bd56a660..fe6aa68f1 100755 --- a/qualification/run/offline.sh +++ b/qualification/run/offline.sh @@ -29,9 +29,13 @@ export AUTHS_GATEWAY="${root}/target/release/auths-gateway" export AUTHS_QUALIFICATION="${root}/target/release/auths-qualification" "${directory}/harness" prepare "${work}" -# The tuple is obtained from the actual installed candidate, not authored -# by the harness. Installation and package acquisition remain family-owned. -"${AUTHS_GATEWAY}" qualification-status --state-dir "${work}/gateway-state" --tuple \ +# Derive the planned production identity without custody or provider access. +# The protected live runner must compare its actual installation byte-for-byte +# before importing a permit. This command grants no execution authority. +"${AUTHS_GATEWAY}" qualification-candidate \ + --recipe "${work}/recipe.json" --profile-lock "${work}/profile.lock.json" \ + --recipe-family "${family}" \ + --provider-contract-id "$("${AUTHS_QUALIFICATION}" contract-id --contract "${directory}/contract.json")" \ > "${work}/tuple.json" for required in tuple.json packages.json; do [ -s "${work}/${required}" ] || { echo "qualification.harness-incomplete ${required}" >&2; exit 1; } diff --git a/release/semantic-freeze-versions.toml b/release/semantic-freeze-versions.toml index adb0d7b68..242acc0d8 100644 --- a/release/semantic-freeze-versions.toml +++ b/release/semantic-freeze-versions.toml @@ -1,4 +1,4 @@ -freeze_version = 373 +freeze_version = 374 # Semantic identity counters live outside the xtask source tree deliberately. # The formal source closure binds xtask's executable code, while the semantic @@ -45,7 +45,7 @@ freeze_version = 373 "auths.frozen-bytes/product/integrations/auths-stripe/fixtures/subscription-create/v1/manifest.sha256.json" = 1 "auths.frozen-bytes/product/integrations/auths-stripe/fixtures/subscription-modify/v1/manifest.sha256.json" = 1 "auths.frozen-bytes/product/integrations/auths-stripe/fixtures/v1/manifest.sha256.json" = 1 -"auths.identity.protocol" = 126 +"auths.identity.protocol" = 127 "auths.modular-components" = 20 "auths.portable-abi-bindings" = 121 "auths.product.bounded-domains" = 19 @@ -60,11 +60,11 @@ freeze_version = 373 "auths.product.mcp-closed-execution" = 31 "auths.product.mechanism-profile-conformance" = 12 "auths.product.operations" = 5 -"auths.product.public-sdk-contract" = 123 +"auths.product.public-sdk-contract" = 124 "auths.product.receipts" = 13 "auths.product.release-assurance" = 7 "auths.product.simplified-waist" = 19 "auths.product.vocabulary" = 24 "auths.release.benchmark-contract" = 1 "auths.release.evolution-contract" = 79 -"auths.release.public-surface" = 373 +"auths.release.public-surface" = 374 diff --git a/release/semantic-freeze.json b/release/semantic-freeze.json index fa9a7871e..0848f2073 100644 --- a/release/semantic-freeze.json +++ b/release/semantic-freeze.json @@ -1,6 +1,6 @@ { "schema": "auths.semantic-freeze/1", - "freezeVersion": 373, + "freezeVersion": 374, "publicSurface": { "rustRoots": [ "auths", @@ -550,7 +550,7 @@ }, { "id": "auths.identity.protocol", - "version": 126, + "version": 127, "classification": "frozen-meaning", "categories": [ "identity-protocol-versions", @@ -573,7 +573,7 @@ "core/fixtures/identity/v1/vectors.json", "core/spec/identity/v1" ], - "sha256": "8efe6e1e8c5da54d4bd433b51e8b9a9e93c6ceadd15f611a6f6f34f09ea00091" + "sha256": "4bcb664ec6ef4a60c8b28584d30154c569a1e78148467fb08b39243cbd6ee533" }, { "id": "auths.modular-components", @@ -871,7 +871,7 @@ }, { "id": "auths.product.public-sdk-contract", - "version": 123, + "version": 124, "classification": "frozen-meaning", "categories": [ "rust-sdk-contract", @@ -889,7 +889,7 @@ "product/runtime/auths-runtime/src", "product/sdk/auths-sdk/src" ], - "sha256": "cf4df124a49cee9bd90eb486636998cef5af8525f0524389c23d0d9dea9979e1" + "sha256": "669b0a63daba7a7da5019dd37086e683ac5242c0b385c11e1073233438c7b58c" }, { "id": "auths.product.receipts", @@ -1011,7 +1011,7 @@ }, { "id": "auths.release.public-surface", - "version": 373, + "version": 374, "classification": "release-metadata", "categories": [ "package-names", @@ -1104,7 +1104,7 @@ "xtask/src/release_launch.rs", "xtask/src/semantic_freeze.rs" ], - "sha256": "8f6bcbe2b1ec2f1699a93cd8e012be697711f5ee841fe089eaf7e9532d3971ad" + "sha256": "61a7d3fdb282ac8972eb197f9fde1b673a2650d0d0cb53c4cf8880222ebc1184" } ] } From d22e4ec57bca17970639a7f7ab2b3a019f966c65 Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 04:46:13 +0100 Subject: [PATCH 058/108] Separate first-run commissioning from ordinary qualified client evidence --- compliance.toml | 3 + ...0014-stripe-refund-recipe-qualification.md | 2 +- ...able-record-update-recipe-qualification.md | 2 +- ...d-qualification-commissioning-authority.md | 22 +++++ ...NDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md | 22 +++++ ...gateway-polish-and-recipe-qualification.md | 15 +++ .../src/bin/qualification_runner/mod.rs | 12 ++- .../src/execution.rs | 67 +++++++++++-- .../tests/execution.rs | 94 +++++++++++++++++++ qualification/README.md | 24 ++++- qualification/run/assemble.sh | 21 +++-- qualification/run/live.sh | 10 +- release/semantic-freeze-versions.toml | 8 +- release/semantic-freeze.json | 14 +-- 14 files changed, 276 insertions(+), 40 deletions(-) create mode 100644 docs/research/INDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md diff --git a/compliance.toml b/compliance.toml index 2f62693b6..b30a7d4e7 100644 --- a/compliance.toml +++ b/compliance.toml @@ -1226,6 +1226,9 @@ proof-author-or-assembler = [ "product/qualification/auths-recipe-qualification-issuance/tests/protected_run.rs#a_pull_request_reaches_no_secret_and_no_signing_job", "product/qualification/auths-recipe-qualification-issuance/tests/protected_run.rs#the_repository_holds_no_qualification_key", "product/qualification/auths-recipe-qualification-issuance/tests/execution.rs#every_stage_executes_its_operations_and_a_missing_runner_refuses", + "product/qualification/auths-recipe-qualification-issuance/tests/execution.rs#production_readiness_requires_a_read_only_live_probe_on_a_production_target", + "product/qualification/auths-recipe-qualification-issuance/tests/execution.rs#commissioning_client_refusal_cannot_replace_an_ordinary_installed_effect", + "product/qualification/auths-recipe-qualification-issuance/tests/execution.rs#replay_can_complete_an_unresolved_read_back_but_never_write_or_reacquire_after_observation", "product/qualification/auths-recipe-qualification-issuance/tests/execution.rs#observed_faults_and_changed_candidates_produce_no_passing_case", "product/qualification/auths-recipe-qualification-issuance/tests/execution.rs#differential_compares_the_actual_oracle_and_gateway_commitments", "product/qualification/auths-recipe-qualification-issuance/tests/execution.rs#recovery_requires_read_back_and_without_the_capability_stays_unknown", diff --git a/docs/adr/0014-stripe-refund-recipe-qualification.md b/docs/adr/0014-stripe-refund-recipe-qualification.md index b675b6d2e..ab1f11bc5 100644 --- a/docs/adr/0014-stripe-refund-recipe-qualification.md +++ b/docs/adr/0014-stripe-refund-recipe-qualification.md @@ -63,7 +63,7 @@ the gateway receives only the restricted test key. The maintained platform profile/recipe are accompanied by gateway `attempt-scenarios-v3.json`, `bounds-aggregate.json`, `outcome-v2.json` and `hostile-recipes-v2.json`. They must be expanded into the family-owned -`auths.qualification-corpus/1` with executable coverage of every mandatory wall +`auths.qualification-corpus/2` with executable coverage of every mandatory wall scenario; they are not the missing protected family corpus. The live corpus must additionally exercise every declared capability, provider diff --git a/docs/adr/0015-airtable-record-update-recipe-qualification.md b/docs/adr/0015-airtable-record-update-recipe-qualification.md index 489400ee6..051b17b32 100644 --- a/docs/adr/0015-airtable-record-update-recipe-qualification.md +++ b/docs/adr/0015-airtable-record-update-recipe-qualification.md @@ -50,7 +50,7 @@ those capabilities on every lease. The maintained offline seeds are `airtable/vectors.json`, the profile lock and gateway hostile, attempt and outcome corpora. Publish a family-owned executable -`auths.qualification-corpus/1` covering the complete evidence wall, including +`auths.qualification-corpus/2` covering the complete evidence wall, including an oracle-accepted update, all refused mappings, real application isolation and credential drift. These seeds alone are not the missing protected family corpus. diff --git a/docs/adr/0016-bounded-qualification-commissioning-authority.md b/docs/adr/0016-bounded-qualification-commissioning-authority.md index b6d922b68..dd45af582 100644 --- a/docs/adr/0016-bounded-qualification-commissioning-authority.md +++ b/docs/adr/0016-bounded-qualification-commissioning-authority.md @@ -203,3 +203,25 @@ obligation. It does not make the first qualification appear to preexist its own evidence. Commissioning state remains distinct from `qualified`; readiness never derives true from a permit. The normal production application gate stays closed until the existing qualification chain verifies. + +## Three-phase corpus and finite first qualification + +The installed-client journey exposed a second first-run cycle: an ordinary +client must remain refused until qualification exists. The closed release-only +corpus is therefore version 2, with `offline`, `commissioning` and `live` phases. +The commissioning phase requires PostgreSQL and production custody and cannot +claim production readiness. Its installed-client case must witness a missing +qualification refusal with no lease or provider entry. Private operator effects +still need the complete mandatory wall and fresh read-back. + +The resulting first record has a maximum two-hour validity and explicitly +excludes ordinary client success and production readiness. It authorizes the +subsequent ordinary live phase for the same exact tuple. That phase requires +a confirmed installed-client effect and the actual production doctor; a denied +client, a development target or a commissioning doctor cannot substitute. +Assembly reads offline reports and only the selected protected phase. The +contract binds one unchanged manifest containing both phase scopes, so the +first qualification does not require a different recipe, binary or contract. + +This sequencing must still be executed by protected jobs and retained as +measured evidence before the first qualification can be claimed complete. diff --git a/docs/research/INDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md b/docs/research/INDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md new file mode 100644 index 000000000..118a95275 --- /dev/null +++ b/docs/research/INDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md @@ -0,0 +1,22 @@ +# Independent operator qualification notes + +7 October 2026. Repository-owner-delegated technical work; no independent human +audit or real-user trial is claimed. + +| Issue found | Correction and status | +| --- | --- | +| First production qualification required its own pre-existing attestation. | Separate signed, finite commissioning authority; private operator session; durable shared budget and retained host floor. Implemented on PR #206, ordinary application authority unchanged. | +| Offline evidence attempted custody installation before protected setup. | The actual candidate derives a planned production tuple without installation; live setup must compare its installation with that tuple. Implemented. | +| Disposable identifiers and exact actions needed independent expansion. | Closed Stripe/Airtable resources, reconstruction of the whole reviewed recipe/lock, native proof review and independent request oracles. Implemented release-only expansion; protected family setup still needs integration. | +| An installed ordinary client could not succeed before first qualification. | Separate commissioning and ordinary live phases. First records have a two-hour maximum and explicit exclusions; ordinary live evidence requires a confirmed installed-client effect. Implemented runner/assembly controls, protected sequencing still needs integration. | +| The runner prohibited a legitimate read-only recovery lease on replay. | One lease may finish an unresolved entered attempt's observation. A replay cannot write again or reacquire after observation. Implemented with regression cases. | +| A live provider response's exact digest cannot be predicted before creating the effect. | Next: a closed independent fresh-evidence witness, compared with the candidate evidence digest. No wildcard, copying candidate output into expectations or fabricated response is acceptable. | +| The production CLI does not expose independently counted custody/transport boundary observations. | Next: secret-free native witnesses over actual calls, coupled with fresh provider read-back. Budget consumption alone is not a credential-store call count. | +| Existing AWS roles trust the `gateway-custody-live` environment, while the qualification template names separate family environments. | Next: use an explicitly reviewed protected-environment arrangement that matches the actual OIDC trust, with required reviewer, main-only policy and family-specific credential injection. No role trust or gate is weakened. | +| Main-only protected code must be deployed before the first protected qualification run. | A bounded prerequisite rollout of the completed runner is needed before collecting evidence. Epic acceptance stays open until actual runs, signed closure and CI are complete. | + +The public offline root ceremony and purpose-separated certificates are pinned. +Both signer keys are provisioned in the existing reviewer-protected main-only +signing environment; the root key remains outside CI and every Git checkout. +No production family has yet been qualified by this work. Development live +reports remain explicitly separate from protected production evidence. diff --git a/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md b/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md index 3040faa18..cc286c71d 100644 --- a/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md +++ b/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md @@ -1802,3 +1802,18 @@ Both purpose-separated signer keys now exist in the existing reviewer-protected, default-branch-only signing environment. The offline root remains outside CI. Complete family setup/corpora, protected commissioning/live runs and final signed qualification still remain; these changes issue no qualification or readiness. + +### 22.5 Ordinary-client bootstrap closure (2026-10-07) + +The closed release-only corpus now distinguishes offline verification, private +commissioning and ordinary qualified live execution (schema +`auths.qualification-corpus/2`). An installed client in commissioning must +measure a missing-qualification refusal with zero lease and entry; the same +scenario in ordinary live execution must measure a fresh confirmed effect. +Commissioning cases require the production tuple and cannot satisfy production +readiness. Assembly selects one protected phase, limits the first record to two +hours and explicitly excludes the ordinary-client/readiness claims that only +the subsequent phase can establish. Both scopes belong to the same reviewed +manifest and exact tuple. This closes the second dependency cycle without +opening ordinary application leases under a commissioning permit. The protected +workflow and family corpora still must execute this sequence. diff --git a/product/qualification/auths-recipe-qualification-issuance/src/bin/qualification_runner/mod.rs b/product/qualification/auths-recipe-qualification-issuance/src/bin/qualification_runner/mod.rs index eba09ef59..2df481403 100644 --- a/product/qualification/auths-recipe-qualification-issuance/src/bin/qualification_runner/mod.rs +++ b/product/qualification/auths-recipe-qualification-issuance/src/bin/qualification_runner/mod.rs @@ -112,6 +112,7 @@ pub(super) fn run( ) -> Result<(), Failure> { let phase = match phase { "offline" => RunPhase::Offline, + "commissioning" => RunPhase::Commissioning, "live" => RunPhase::Live, _ => return Err(refused()), }; @@ -122,6 +123,7 @@ pub(super) fn run( let work = fs::canonicalize(work).map_err(|_| refused())?; let phase_token = match phase { RunPhase::Offline => "offline", + RunPhase::Commissioning => "commissioning", RunPhase::Live => "live", }; for member in EvidenceMemberKind::ALL { @@ -136,8 +138,8 @@ pub(super) fn run( Err(_) => return Err(refused()), } } - if phase == RunPhase::Live { - match fs::remove_file(work.join("live-effects.json")) { + if phase != RunPhase::Offline { + match fs::remove_file(work.join(format!("{phase_token}-effects.json"))) { Ok(()) => (), Err(error) if error.kind() == std::io::ErrorKind::NotFound => (), Err(_) => return Err(refused()), @@ -186,7 +188,7 @@ pub(super) fn run( } } if reports.is_empty() - || (phase == RunPhase::Live + || (phase != RunPhase::Offline && (live.entered == 0 || live.entered != live.confirmed_by_read_back)) { return Err(refused()); @@ -197,9 +199,9 @@ pub(super) fn run( &cases, )?; } - if phase == RunPhase::Live { + if phase != RunPhase::Offline { let bytes = serde_json::to_vec(&live).map_err(|_| refused())?; - write(&work.join("live-effects.json"), &bytes)?; + write(&work.join(format!("{phase_token}-effects.json")), &bytes)?; } Ok(()) } diff --git a/product/qualification/auths-recipe-qualification-issuance/src/execution.rs b/product/qualification/auths-recipe-qualification-issuance/src/execution.rs index 3f843e669..99a031820 100644 --- a/product/qualification/auths-recipe-qualification-issuance/src/execution.rs +++ b/product/qualification/auths-recipe-qualification-issuance/src/execution.rs @@ -17,7 +17,7 @@ pub const MAX_RUN_CASES: usize = 256; /// Largest sequence of operations within one case. pub const MAX_CASE_STEPS: usize = 32; /// Schema of the reviewed executable corpus. -pub const CORPUS_SCHEMA: &str = "auths.qualification-corpus/1"; +pub const CORPUS_SCHEMA: &str = "auths.qualification-corpus/2"; /// Where an operation may execute. Live cases never execute on a pull request. #[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)] @@ -25,6 +25,9 @@ pub const CORPUS_SCHEMA: &str = "auths.qualification-corpus/1"; pub enum RunPhase { /// No provider credential; an offline provider double is permitted. Offline, + /// First-run production evidence through finite private operator authority. + /// Ordinary installed clients must still demonstrate qualification refusal. + Commissioning, /// Disposable provider resources in a protected environment. Live, } @@ -230,7 +233,8 @@ impl RunCase { } S::DeclaredCapability => has(Op::Submit) || has(Op::Probe), S::ProductionReadiness => { - has(Op::Probe) + self.phase == RunPhase::Live + && has(Op::Probe) && self.steps.iter().all(|step| { step.operation == Op::Probe && step.expected.verdict.outcome == RunOutcome::Complete @@ -259,7 +263,7 @@ impl RunCase { || !required || self.steps.is_empty() || self.steps.len() > MAX_CASE_STEPS - || (live_only && self.phase != RunPhase::Live) + || (live_only && self.phase == RunPhase::Offline) || (has(Op::Oracle) && self.phase != RunPhase::Offline) || self .capabilities @@ -294,7 +298,7 @@ impl RunCase { mut observe: impl FnMut(usize, &RunStep) -> Result, ) -> Result<(CaseReport, LiveEffects), IssuanceError> { self.validate()?; - if self.scenario == Scenario::ProductionReadiness + if (self.scenario == Scenario::ProductionReadiness || self.phase == RunPhase::Commissioning) && (tuple.target.store_kind != auths_recipe_qualification::LifecycleStoreKind::PostgresqlV1 || !tuple.target.credential_store_kind.is_production()) @@ -353,6 +357,31 @@ impl RunCase { effects: LiveEffects, ) -> Result<(), IssuanceError> { use Scenario as S; + if self.scenario == S::InstalledJourney { + let ordinary_effect = self.phase == RunPhase::Live + && effects.entered > 0 + && effects.entered == effects.confirmed_by_read_back + && self.steps.iter().zip(observations).any(|(step, actual)| { + step.operation == Operation::InstalledConsumer + && actual.verdict.outcome == RunOutcome::Observed + && actual.provider_entries > 0 + && actual.provider_entries == actual.confirmed_by_read_back + }); + let first_run_refusal = self.phase == RunPhase::Commissioning + && observations.iter().all(|actual| { + actual.verdict.outcome == RunOutcome::Refused + && matches!( + actual.verdict.code.as_str(), + "gateway.qualification.unavailable" | "gateway.qualification.missing" + ) + && actual.credential_leases == 0 + && actual.provider_entries == 0 + && actual.confirmed_by_read_back == 0 + }); + if !ordinary_effect && !first_run_refusal { + return Err(IssuanceError::CaseFailed); + } + } let no_entry = matches!( self.scenario, S::ApplicationCannotReadSecret @@ -378,11 +407,31 @@ impl RunCase { { return Err(IssuanceError::CaseFailed); } - if self.steps.iter().zip(observations).any(|(step, actual)| { - step.operation == Operation::Replay - && (actual.provider_entries != 0 || actual.credential_leases != 0) - }) { - return Err(IssuanceError::CaseFailed); + let mut unresolved = false; + for (step, actual) in self.steps.iter().zip(observations) { + if step.operation == Operation::Replay { + let read_only_completion = unresolved + && actual.credential_leases <= 1 + && matches!( + actual.verdict.outcome, + RunOutcome::Unknown | RunOutcome::ResponseRecorded | RunOutcome::Observed + ); + if actual.provider_entries != 0 + || (actual.credential_leases != 0 && !read_only_completion) + { + return Err(IssuanceError::CaseFailed); + } + } + if step.operation != Operation::Oracle { + if actual.provider_entries > 0 { + unresolved = matches!( + actual.verdict.outcome, + RunOutcome::Unknown | RunOutcome::ResponseRecorded + ); + } else if actual.verdict.outcome == RunOutcome::Observed { + unresolved = false; + } + } } if matches!( self.scenario, diff --git a/product/qualification/auths-recipe-qualification-issuance/tests/execution.rs b/product/qualification/auths-recipe-qualification-issuance/tests/execution.rs index 38a5a63dc..98c81aa07 100644 --- a/product/qualification/auths-recipe-qualification-issuance/tests/execution.rs +++ b/product/qualification/auths-recipe-qualification-issuance/tests/execution.rs @@ -72,6 +72,100 @@ fn production_readiness_requires_a_read_only_live_probe_on_a_production_target() Err(IssuanceError::CaseFailed) ); assert!(!invoked); + case.phase = RunPhase::Commissioning; + assert_eq!(run(&case, |_, _| {}), Err(IssuanceError::CaseFailed)); +} + +#[test] +fn commissioning_client_refusal_cannot_replace_an_ordinary_installed_effect() { + use auths_recipe_qualification::{BoundedText, LifecycleStoreKind}; + use auths_recipe_qualification_issuance::execution::{Operation, RunPhase}; + let mut obsolete = executable_corpus(); + obsolete.schema = "auths.qualification-corpus/1".to_owned(); + assert!(obsolete.validate().is_err()); + let mut case = executable_corpus() + .cases + .into_iter() + .find(|case| case.scenario == Scenario::InstalledJourney) + .expect("installed client"); + assert!(run(&case, |_, _| {}).is_ok()); + let mut unrelated_effect = case.steps[0].clone(); + unrelated_effect.operation = Operation::Submit; + let expected = &mut case.steps[0].expected; + expected.verdict.outcome = RunOutcome::Refused; + expected.verdict.code = BoundedText::parse("gateway.qualification.unavailable").expect("code"); + expected.verdict.evidence_sha256 = None; + expected.credential_leases = 0; + expected.provider_entries = 0; + expected.confirmed_by_read_back = 0; + assert_eq!( + run(&case, |_, _| {}), + Err(IssuanceError::CaseFailed), + "ordinary qualification needs a confirmed installed-client effect" + ); + let mut masked = case.clone(); + masked.steps.push(unrelated_effect); + assert_eq!(run(&masked, |_, _| {}), Err(IssuanceError::CaseFailed)); + case.phase = RunPhase::Commissioning; + assert!(run(&case, |_, _| {}).is_ok()); + for mutation in 0..4 { + let mut changed = case.clone(); + match mutation { + 0 => changed.steps[0].expected.credential_leases = 1, + 1 => changed.steps[0].expected.provider_entries = 1, + 2 => { + changed.steps[0].expected.verdict.code = + BoundedText::parse("gateway.qualification.expired").expect("code") + } + _ => changed.steps[0].expected.verdict.outcome = RunOutcome::Complete, + } + assert_eq!(run(&changed, |_, _| {}), Err(IssuanceError::CaseFailed)); + } + let mut development = tuple(); + development.target.store_kind = LifecycleStoreKind::SharedFileV1; + let mut invoked = false; + assert_eq!( + case.execute(&development, |_, _| { + invoked = true; + Err(IssuanceError::CaseFailed) + }), + Err(IssuanceError::CaseFailed) + ); + assert!(!invoked); +} + +#[test] +fn replay_can_complete_an_unresolved_read_back_but_never_write_or_reacquire_after_observation() { + use auths_recipe_qualification::BoundedText; + let mut case = executable_corpus() + .cases + .into_iter() + .find(|case| case.scenario == Scenario::AmbiguousResponse) + .expect("ambiguous response"); + let replay = &mut case.steps[1].expected; + replay.credential_leases = 1; + replay.verdict.outcome = RunOutcome::Unknown; + replay.verdict.code = BoundedText::parse("unknown").expect("code"); + assert!(run(&case, |_, _| {}).is_ok()); + let replay = &mut case.steps[1].expected; + replay.verdict.outcome = RunOutcome::Observed; + replay.verdict.evidence_sha256 = Some(tuple().profile_lock_sha256); + replay.confirmed_by_read_back = 1; + assert!(run(&case, |_, _| {}).is_ok()); + for mutation in 0..3 { + let mut changed = case.clone(); + match mutation { + 0 => changed.steps[1].expected.provider_entries = 1, + 1 => changed.steps[1].expected.credential_leases = 2, + _ => { + changed.steps[0].expected.verdict.outcome = RunOutcome::Observed; + changed.steps[0].expected.verdict.evidence_sha256 = + Some(tuple().profile_lock_sha256); + changed.steps[0].expected.confirmed_by_read_back = 1; + } + } + assert_eq!(run(&changed, |_, _| {}), Err(IssuanceError::CaseFailed)); + } } #[test] diff --git a/qualification/README.md b/qualification/README.md index f213a92ab..c85c71854 100644 --- a/qualification/README.md +++ b/qualification/README.md @@ -98,10 +98,10 @@ The harness owns the provider-specific operations and pure oracle. The release runner owns sequencing, assertions, counters, and the resulting case reports. No family harness writes `passed` reports or `live-effects.json`. -`corpus-manifest.json` is `auths.qualification-corpus/1`, decoded as +`corpus-manifest.json` is `auths.qualification-corpus/2`, decoded as `execution::RunCorpus` by `auths-qualification run-stage`. It contains at most 256 unique cases. Each case has `id`, `scenario`, `capabilities`, `phase` -(`offline` or `live`), and at most 32 ordered `steps`. Each step has a closed +(`offline`, `commissioning` or `live`), and at most 32 ordered `steps`. Each step has a closed `operation` and an `expected` observation: exact verdict (outcome, stable code, request and evidence digests), credential leases, provider entries, and writes confirmed by fresh read-back. All required non-trust/non-redaction scenarios @@ -142,7 +142,7 @@ these observations are evidence, not cryptographic proof of provider behavior. The runner independently compares oracle and gateway verdicts and request/ evidence commitments; accepted differential cases require a request digest. Replay, race, restart, crash, ambiguity and recovery cases may enter once only. -Replay operations cannot lease or enter again. Forged/altered inputs cannot +Replay never enters write transport again. An unresolved entered attempt may take one read-only lease to complete its declared observation; an already observed attempt takes none. Forged/altered inputs cannot lease. Recovery runs loss/delay followed by read-back and must remain `unknown` when no recovery capability is declared. Live effects count only successful writes with fresh read-back. Installed-consumer steps run outside the source @@ -212,3 +212,21 @@ credential is stored in it. The signing environment already has both rules. The harness of a family is trusted as reviewed code on the default branch; the run does not execute anything a harness leaves behind as a program in the jobs that assemble, sign, or verify. + +## First qualification and ordinary validation + +One reviewed corpus contains three closed phases. `offline` establishes native +proof, recipe and oracle agreement without custody. `commissioning` exercises +the exact production candidate through finite private operator authority; its +installed-client journey must show an ordinary qualification refusal with zero +leases/entries. It cannot include a production-readiness case. + +Assembly selects offline reports and exactly one protected phase, never mixes +stale commissioning and ordinary live reports. Commissioning records last at +most two hours and explicitly exclude ordinary installed-client success and +production readiness. They permit the existing qualification chain to unlock +the subsequent `live` phase on the same candidate/contract/recipe tuple. +That phase must show a confirmed effect from the installed ordinary client; a +refusal cannot satisfy it. Only that phase can contribute production doctor +evidence to a stable launch projection. A permit or an initial record alone +never establishes stable readiness. diff --git a/qualification/run/assemble.sh b/qualification/run/assemble.sh index d0124a2a5..3c333dc8e 100755 --- a/qualification/run/assemble.sh +++ b/qualification/run/assemble.sh @@ -14,6 +14,9 @@ family="${1:?usage: assemble.sh &2; exit 1; } root="$(git rev-parse --show-toplevel)" directory="${root}/qualification/families/${family}" tool="${AUTHS_QUALIFICATION:-${root}/target/release/auths-qualification}" @@ -21,7 +24,7 @@ tool="${AUTHS_QUALIFICATION:-${root}/target/release/auths-qualification}" # A failed rerun must not leave an earlier proposal available to a signer. rm -rf "${work}/proposal" "${work}/evidence" -for required in tuple.json packages.json facts.json live-effects.json resources.json cases/redaction.scan.json; do +for required in tuple.json packages.json facts.json "${stage}-effects.json" resources.json cases/redaction.scan.json; do [ -s "${work}/${required}" ] || { echo "qualification.evidence-incomplete ${required}" >&2; exit 1; } done commit="$(jq -r .commit "${work}/facts.json")" @@ -40,7 +43,7 @@ for member in conformance differential hostile live recovery rotation restart mu reports=() # Only the current runner's phase reports and release-owned trust/scan # outputs are inputs. Extra harness-authored or stale reports are ignored. - for phase in offline live; do + for phase in offline "${stage}"; do file="${work}/cases/${member}.${phase}.json" [ ! -f "${file}" ] || reports+=(--cases "${file}") done @@ -51,8 +54,8 @@ for member in conformance differential hostile live recovery rotation restart mu [ "${#reports[@]}" -gt 0 ] || { echo "qualification.member-missing ${member}" >&2; exit 1; } live=() if [ "${member}" = live ]; then - live=(--live-entered "$(jq -r .entered "${work}/live-effects.json")" - --live-confirmed "$(jq -r .confirmed_by_read_back "${work}/live-effects.json")") + live=(--live-entered "$(jq -r .entered "${work}/${stage}-effects.json")" + --live-confirmed "$(jq -r .confirmed_by_read_back "${work}/${stage}-effects.json")") fi "${tool}" evidence --member "${member}" --commit "${commit}" \ --tuple "${work}/tuple.json" "${reports[@]}" ${live[@]+"${live[@]}"} \ @@ -60,11 +63,12 @@ for member in conformance differential hostile live recovery rotation restart mu done now="$(date -u +%s)" -identifier="qlf_$(printf '%s\n%s\n%s' "${family}" "${commit}" "${run}" | shasum -a 256 | cut -c1-32)" +identifier="qlf_$(printf '%s\n%s\n%s\n%s' "${family}" "${commit}" "${run}" "${stage}" | shasum -a 256 | cut -c1-32)" jq -n \ --arg identifier "${identifier}" \ --argjson now "${now}" \ --arg environment "${environment}" \ + --arg stage "${stage}" \ --slurpfile record "${directory}/record.json" \ --slurpfile tuple "${work}/tuple.json" \ --slurpfile packages "${work}/packages.json" \ @@ -74,7 +78,7 @@ jq -n \ provider_kind: $record[0].provider_kind, tuple: $tuple[0], not_before: $now, - not_after: ($now + ($record[0].validity_days * 86400)), + not_after: ($now + (if $stage == "commissioning" then 7200 else ($record[0].validity_days * 86400) end)), provenance: {repository: "github.com/auths-dev/auths-proof", commit: $facts[0].commit, workflow: ".github/workflows/recipe-qualification.yml", environment: $environment}, source_closure_sha256: $facts[0].source_closure_sha256, @@ -87,7 +91,10 @@ jq -n \ custody_descriptor: $record[0].custody_descriptor, store_descriptor: $record[0].store_descriptor, residual_assumptions: ($record[0].residual_assumptions | sort), - excluded_claims: ($record[0].excluded_claims | sort)}' \ + excluded_claims: (($record[0].excluded_claims + + (if $stage == "commissioning" then + ["First-run commissioning: ordinary installed clients were refused; their qualified effect and production readiness require the subsequent live phase."] + else [] end)) | unique | sort)}' \ > "${work}/draft.json" "${tool}" assemble --draft "${work}/draft.json" --evidence-dir "${work}/evidence" \ diff --git a/qualification/run/live.sh b/qualification/run/live.sh index 912cb95eb..23148f212 100755 --- a/qualification/run/live.sh +++ b/qualification/run/live.sh @@ -5,12 +5,16 @@ set -euo pipefail family="${1:?usage: live.sh }" work="${2:?usage: live.sh }" +stage="${3:-live}" +[[ "${stage}" = commissioning || "${stage}" = live ]] \ + || { echo "qualification.invalid-stage" >&2; exit 1; } +export AUTHS_QUALIFICATION_STAGE="${stage}" root="$(git rev-parse --show-toplevel)" [[ "${family}" =~ ^[a-z][a-z0-9-]{0,63}$ ]] || { echo "qualification.invalid-family" >&2; exit 1; } harness="${root}/qualification/families/${family}/harness" [ -x "${harness}" ] || { echo "qualification.family-unknown" >&2; exit 1; } tool="${AUTHS_QUALIFICATION:-${root}/target/release/auths-qualification}" -rm -f "${work}/live-effects.json" "${work}/cases/"*.live.json +rm -f "${work}/${stage}-effects.json" "${work}/cases/"*."${stage}".json cleanup() { status=$? @@ -21,7 +25,7 @@ cleanup() { status=1 fi if [ "${status}" -ne 0 ]; then - rm -f "${work}/live-effects.json" "${work}/cases/"*.live.json + rm -f "${work}/${stage}-effects.json" "${work}/cases/"*."${stage}".json fi exit "${status}" } @@ -31,6 +35,6 @@ if ! "${harness}" prepare-live "${work}" >/dev/null 2>&1; then echo "qualification.live-setup-failed" >&2 exit 1 fi -"${tool}" run-stage --phase live \ +"${tool}" run-stage --phase "${stage}" \ --corpus "${root}/qualification/families/${family}/corpus-manifest.json" \ --harness "${harness}" --tuple "${work}/tuple.json" --work-dir "${work}" diff --git a/release/semantic-freeze-versions.toml b/release/semantic-freeze-versions.toml index 242acc0d8..66f47a9d3 100644 --- a/release/semantic-freeze-versions.toml +++ b/release/semantic-freeze-versions.toml @@ -1,4 +1,4 @@ -freeze_version = 374 +freeze_version = 375 # Semantic identity counters live outside the xtask source tree deliberately. # The formal source closure binds xtask's executable code, while the semantic @@ -45,7 +45,7 @@ freeze_version = 374 "auths.frozen-bytes/product/integrations/auths-stripe/fixtures/subscription-create/v1/manifest.sha256.json" = 1 "auths.frozen-bytes/product/integrations/auths-stripe/fixtures/subscription-modify/v1/manifest.sha256.json" = 1 "auths.frozen-bytes/product/integrations/auths-stripe/fixtures/v1/manifest.sha256.json" = 1 -"auths.identity.protocol" = 127 +"auths.identity.protocol" = 128 "auths.modular-components" = 20 "auths.portable-abi-bindings" = 121 "auths.product.bounded-domains" = 19 @@ -60,11 +60,11 @@ freeze_version = 374 "auths.product.mcp-closed-execution" = 31 "auths.product.mechanism-profile-conformance" = 12 "auths.product.operations" = 5 -"auths.product.public-sdk-contract" = 124 +"auths.product.public-sdk-contract" = 125 "auths.product.receipts" = 13 "auths.product.release-assurance" = 7 "auths.product.simplified-waist" = 19 "auths.product.vocabulary" = 24 "auths.release.benchmark-contract" = 1 "auths.release.evolution-contract" = 79 -"auths.release.public-surface" = 374 +"auths.release.public-surface" = 375 diff --git a/release/semantic-freeze.json b/release/semantic-freeze.json index 0848f2073..2836a1b71 100644 --- a/release/semantic-freeze.json +++ b/release/semantic-freeze.json @@ -1,6 +1,6 @@ { "schema": "auths.semantic-freeze/1", - "freezeVersion": 374, + "freezeVersion": 375, "publicSurface": { "rustRoots": [ "auths", @@ -550,7 +550,7 @@ }, { "id": "auths.identity.protocol", - "version": 127, + "version": 128, "classification": "frozen-meaning", "categories": [ "identity-protocol-versions", @@ -573,7 +573,7 @@ "core/fixtures/identity/v1/vectors.json", "core/spec/identity/v1" ], - "sha256": "4bcb664ec6ef4a60c8b28584d30154c569a1e78148467fb08b39243cbd6ee533" + "sha256": "a3bf2b99da3b9b85fc1dc0e860af199821fd28b9d30cb809753bf14173eedab2" }, { "id": "auths.modular-components", @@ -871,7 +871,7 @@ }, { "id": "auths.product.public-sdk-contract", - "version": 124, + "version": 125, "classification": "frozen-meaning", "categories": [ "rust-sdk-contract", @@ -889,7 +889,7 @@ "product/runtime/auths-runtime/src", "product/sdk/auths-sdk/src" ], - "sha256": "669b0a63daba7a7da5019dd37086e683ac5242c0b385c11e1073233438c7b58c" + "sha256": "e2df99fb1455a4f7f5a89c1592ebb22b1f4c09d44e8e93e01c6b7788d62731f3" }, { "id": "auths.product.receipts", @@ -1011,7 +1011,7 @@ }, { "id": "auths.release.public-surface", - "version": 374, + "version": 375, "classification": "release-metadata", "categories": [ "package-names", @@ -1104,7 +1104,7 @@ "xtask/src/release_launch.rs", "xtask/src/semantic_freeze.rs" ], - "sha256": "61a7d3fdb282ac8972eb197f9fde1b673a2650d0d0cb53c4cf8880222ebc1184" + "sha256": "e9d4c908e151be7377d2756c32893fcb2dce5777076f5d971e9e1d060b558a6c" } ] } From f36d9e9dbde60b0443e9d47768cc2a1b01de59a7 Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 04:56:47 +0100 Subject: [PATCH 059/108] Measure actual custody and transport execution at private operator boundaries --- compliance.toml | 1 + ...NDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md | 2 +- .../auths-gateway/semantic-closure.json | 2 +- product/runtime/auths-gateway/src/admin.rs | 7 ++ .../auths-gateway/src/bin/auths-gateway.rs | 34 +++++++- .../src/commissioning_session/tests.rs | 42 ++++++++++ product/runtime/auths-gateway/src/engine.rs | 28 ++++++- .../auths-gateway/src/execution_witness.rs | 78 +++++++++++++++++++ product/runtime/auths-gateway/src/lib.rs | 2 + .../auths-gateway/src/semantic_closure.rs | 2 +- .../runtime/auths-gateway/src/transport.rs | 43 ++++++++++ qualification/README.md | 17 ++++ release/semantic-freeze-versions.toml | 8 +- release/semantic-freeze.json | 14 ++-- 14 files changed, 263 insertions(+), 17 deletions(-) create mode 100644 product/runtime/auths-gateway/src/execution_witness.rs diff --git a/compliance.toml b/compliance.toml index b30a7d4e7..1919e3f55 100644 --- a/compliance.toml +++ b/compliance.toml @@ -1772,6 +1772,7 @@ stateful-replay-budget-component = [ "product/runtime/auths-gateway/src/commissioning_floor/tests.rs#database_claim_without_witness_acknowledgement_stays_spent", "product/runtime/auths-gateway/src/commissioning_session/tests.rs#ordinary_submission_cannot_select_commissioning_authority", "product/runtime/auths-gateway/src/commissioning_session/tests.rs#offline_review_verifies_exact_actors_and_requests_without_custody", + "product/runtime/auths-gateway/src/commissioning_session/tests.rs#execution_witness_measures_custody_calls_even_when_a_charged_call_fails", "product/runtime/auths-gateway/src/commissioning_session/tests.rs#exact_native_actor_and_action_require_a_durable_unit_before_custody", "product/runtime/auths-gateway/src/commissioning_session/tests.rs#absent_registration_and_expiry_after_preparation_never_lease", "product/runtime/auths-gateway/src/commissioning_session/tests.rs#another_signed_actor_or_action_is_refused_before_custody", diff --git a/docs/research/INDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md b/docs/research/INDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md index 118a95275..e072a1ea1 100644 --- a/docs/research/INDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md +++ b/docs/research/INDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md @@ -11,7 +11,7 @@ audit or real-user trial is claimed. | An installed ordinary client could not succeed before first qualification. | Separate commissioning and ordinary live phases. First records have a two-hour maximum and explicit exclusions; ordinary live evidence requires a confirmed installed-client effect. Implemented runner/assembly controls, protected sequencing still needs integration. | | The runner prohibited a legitimate read-only recovery lease on replay. | One lease may finish an unresolved entered attempt's observation. A replay cannot write again or reacquire after observation. Implemented with regression cases. | | A live provider response's exact digest cannot be predicted before creating the effect. | Next: a closed independent fresh-evidence witness, compared with the candidate evidence digest. No wildcard, copying candidate output into expectations or fabricated response is acceptable. | -| The production CLI does not expose independently counted custody/transport boundary observations. | Next: secret-free native witnesses over actual calls, coupled with fresh provider read-back. Budget consumption alone is not a credential-store call count. | +| The production CLI does not expose independently counted custody/transport boundary observations. | Implemented: private process-scoped counters at the actual custody lease call and HTTP execution boundaries, including failures. Commissioning commands return before/after snapshots; ordinary clients cannot reset them. Remote effects still require separate fresh read-back. | | Existing AWS roles trust the `gateway-custody-live` environment, while the qualification template names separate family environments. | Next: use an explicitly reviewed protected-environment arrangement that matches the actual OIDC trust, with required reviewer, main-only policy and family-specific credential injection. No role trust or gate is weakened. | | Main-only protected code must be deployed before the first protected qualification run. | A bounded prerequisite rollout of the completed runner is needed before collecting evidence. Epic acceptance stays open until actual runs, signed closure and CI are complete. | diff --git a/product/runtime/auths-gateway/semantic-closure.json b/product/runtime/auths-gateway/semantic-closure.json index 7b48b00da..eef0bbdfa 100644 --- a/product/runtime/auths-gateway/semantic-closure.json +++ b/product/runtime/auths-gateway/semantic-closure.json @@ -1 +1 @@ -{"files":[{"path":"Cargo.lock","sha256":"0e75e2fdef44e79e57797ac6661295ae58ddb8de4a1990a6fd22ce6c54f78604"},{"path":"Cargo.toml","sha256":"6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24"},{"path":"core/adapters/auths-did-keri/Cargo.toml","sha256":"86ba3e3f9a0a70d970568bfb3113b7ba7bbdd81c3eebbb52743dd574a0c0ecaa"},{"path":"core/adapters/auths-did-keri/src/lib.rs","sha256":"a75674842f8a7142004369ccd206ab43e476459293f0ff4bed4d4e659031b3e3"},{"path":"core/adapters/auths-did-key/Cargo.toml","sha256":"d5a3ae07ecde83f91eed4c3785051dd0f44eab6c891754f3309b6b40596707d7"},{"path":"core/adapters/auths-did-key/src/lib.rs","sha256":"b76a3f4528a725df53cfa9242e6e414e1d26caa48468aaed497e28b121f4497c"},{"path":"core/adapters/auths-raw-key/Cargo.toml","sha256":"f49616bc18c19e6aaa7e6a02ccebcdb9f5c1422c1278ef9869e0dbf22ceda7be"},{"path":"core/adapters/auths-raw-key/src/lib.rs","sha256":"45eec1b295dac3bed65cd79c942870b926b06b3f5d38eaebaeb6140ac69315fa"},{"path":"core/crates/auths-algebra-kernel/Cargo.toml","sha256":"0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba"},{"path":"core/crates/auths-algebra-kernel/src/generated.rs","sha256":"ae4bcbef42a408c7ffa0c6a74a42f7de177a6f14479e51d205acf830bda05960"},{"path":"core/crates/auths-algebra-kernel/src/lib.rs","sha256":"6654667eeb9b353d6648954c9fd2e8838462a82ce6b2803eb49e1366892c68c6"},{"path":"core/crates/auths-assurance/Cargo.toml","sha256":"afcb12a97ddd09d7a264b9ecd3fcaefc865ff2c9b4539ee85b00883420ba333a"},{"path":"core/crates/auths-assurance/src/lib.rs","sha256":"0fb2ec844d674b25a9e20b1601452c89c2454901fa506adfa9bb38ef9a7fa213"},{"path":"core/crates/auths-author/Cargo.toml","sha256":"1e6f0e3bc079ddb558decf0db26b291c6e72fc47327b6df1b7650d41689b215f"},{"path":"core/crates/auths-author/src/lib.rs","sha256":"e14475f2f49715a1869d5fa6b11ff1fbb72497e39097e09f833b0bae7e5b3f2b"},{"path":"core/crates/auths-author/src/observations.rs","sha256":"dda7d6bfa6f4bd7e95a480ca283c2c0e996f69c5c15cb0c7197af328131a7066"},{"path":"core/crates/auths-authority/Cargo.toml","sha256":"4f68212938029f79ebd857b4f3038494eb85d0163d49f07e51376715cf959815"},{"path":"core/crates/auths-authority/src/lib.rs","sha256":"da88d5194de4e17449e69972c0fb042afa3c39798a8f570f30771e77c384f1eb"},{"path":"core/crates/auths-codec/Cargo.toml","sha256":"e20e51826e17814effd9d8925d18d5fbdd6c0d37bf50231e743ec2611314722c"},{"path":"core/crates/auths-codec/src/approval.rs","sha256":"fbff43bf4d57f69f8b7738a8647751cde75c5a932dee65d924a1fe9c7202f91f"},{"path":"core/crates/auths-codec/src/bounded_policy.rs","sha256":"d21f6728be2d8a04b6d94921f2b683f7e61cbb42e0ac6866f1c88a49caa534c3"},{"path":"core/crates/auths-codec/src/decode.rs","sha256":"ba2999584cdf53b1b517ecb9c7ea50d39efee17c666a9a38e2ad1ac94379f778"},{"path":"core/crates/auths-codec/src/encode.rs","sha256":"8491192053e2e15d62b4d2a491de22405b7487ead69ab6f6bca40669ce7ca5f7"},{"path":"core/crates/auths-codec/src/error.rs","sha256":"fecb0737c16deb42d859f1dc7727c698438d9ac12064fd99e0024629642c390c"},{"path":"core/crates/auths-codec/src/hash.rs","sha256":"f88e111f1dbb2cef6b7b5e9c948cb45ff92e366710c8a5f5c636138aa748479e"},{"path":"core/crates/auths-codec/src/lib.rs","sha256":"3b0e5c94c6f34f750b88a9333e1d5c8145746d845d3a23e0d2f61807cf592ea7"},{"path":"core/crates/auths-codec/src/observation.rs","sha256":"38328b0c71ff97a4196eeade8b4faa889527ff1f80bb168468bcd49082a3987e"},{"path":"core/crates/auths-composition/Cargo.toml","sha256":"331e13025eb82588b5269ed3975929eb41c823d588c49e4c296273d85c6fe80e"},{"path":"core/crates/auths-composition/src/lib.rs","sha256":"e42e3b0b6a9985b73c533aeb23799c638979aa27a9ce7d0f10a8d60340570fb1"},{"path":"core/crates/auths-model/Cargo.toml","sha256":"565c15302b0cc9270db1e28efa3862804846850ba933cc17aea8abcec4a65987"},{"path":"core/crates/auths-model/src/approval.rs","sha256":"54cf44a9ef747ec21546a4086aecfb130bc7803b0d646430e6082df51e6e305f"},{"path":"core/crates/auths-model/src/bounded.rs","sha256":"f90496abc0a06c028b4d850af6ddab7d850bfafeaa3d042f1b1246a41d8bbbc9"},{"path":"core/crates/auths-model/src/bounded_policy.rs","sha256":"306a8f049cc7cfc7635fe0e4de47eb7813eed63d3c14c3be2b51586aa4eea450"},{"path":"core/crates/auths-model/src/lib.rs","sha256":"e7cfe6bb9574c6b016aa63e70658c31e0b90903ec6479a49f4a2ceb64f5bad97"},{"path":"core/crates/auths-model/src/observation.rs","sha256":"b3ed3e3cc090afca2896a7d3de7988afccc1ee1ea0ebd91b51a8bc0f20ad8dbb"},{"path":"core/crates/auths-multikey/Cargo.toml","sha256":"858756c1197befcada06134742bffe8d58cf674cadd6c046bf710570e96efaf2"},{"path":"core/crates/auths-multikey/src/lib.rs","sha256":"f5177fffb11e40eeaaa665ba886c541fc1f24d5eacdd6983fb03dc20148733f0"},{"path":"core/crates/auths-ports/Cargo.toml","sha256":"596a9b0f5af3717c16a6d13f7054d8a106bcd9f01f5f72c2235dd2afcf0ab16c"},{"path":"core/crates/auths-ports/src/binding.rs","sha256":"a16c012d40aa4249e3ec54372b9611006d0bfe8c7dc3c741911c2194ad17736d"},{"path":"core/crates/auths-ports/src/diagnostics.rs","sha256":"aa596572503b5a65a918bb2ff38281c144ff53821ee914e9325c852828d852df"},{"path":"core/crates/auths-ports/src/lib.rs","sha256":"8da1debf86f9532df0660155d04298beb1ba3a1204508f8586e2e67cd2fb3449"},{"path":"core/crates/auths-ports/src/path.rs","sha256":"b68fc547b4e4d97a60cbbc1cc1939fc6b34a8233b81f840bd396914a707e3ea1"},{"path":"core/crates/auths-raw-key-core/Cargo.toml","sha256":"98c0bc8527a537512e43a74dd6ba9658c6f0cdc16610cf938e3f9b43785d836d"},{"path":"core/crates/auths-raw-key-core/src/lib.rs","sha256":"98c0500c41697aae28708ad0bf970b9a97583d96a3d2c18d23e7fa351e0f7d12"},{"path":"core/crates/auths-registries/Cargo.toml","sha256":"590e49e58b0622d9d6274fea46796dcdb07dec9550eff295cce6a6427ffa51e2"},{"path":"core/crates/auths-registries/src/lib.rs","sha256":"450d3886d85ee333b7e046317fb5b47cde62483d5f3e41d46265e2caf4c373ec"},{"path":"core/crates/auths-registries/src/template.rs","sha256":"1224039dd2b3ce6fa8357613d8cafbae40400493da7176da202b9ade62fa05e4"},{"path":"core/crates/auths-signature-core/Cargo.toml","sha256":"6bee2230eb30af1be0bd5c2d57bd3e1903497a70028d47290d4ac6e9e0e8bca0"},{"path":"core/crates/auths-signature-core/src/lib.rs","sha256":"6e3f9311ded5e49ea50d445eb21e6d8fa12442aa4362a73e0cb6fda15b7cd865"},{"path":"core/crates/auths-signature/Cargo.toml","sha256":"7f7b5682466ba439d8c59579022cb61068cad9fb4bd2d73e1cc21327c902b450"},{"path":"core/crates/auths-signature/src/lib.rs","sha256":"b3d9ac4cc3ba0797b9e1c09f2d6ac05089b25dac4e285a5af28c0165b33d925b"},{"path":"core/crates/auths-verifier/Cargo.toml","sha256":"c43358e06a33324b41a8b93e5cc7279c55f7d21f1f6cfaa539a3fc7b4c27a38f"},{"path":"core/crates/auths-verifier/src/approval.rs","sha256":"c3cae6a49e169051eb555bb092b1069a4d422516d6a2114623a89e5f31ff923f"},{"path":"core/crates/auths-verifier/src/causal.rs","sha256":"9635230f33b13a263573d319ac8a1976addbcc07677514a43e3c7bf28dc04587"},{"path":"core/crates/auths-verifier/src/lib.rs","sha256":"f22dec38dfa47ced8da4f605390da8453273bee1da010f57fd1fdfcb10e0b389"},{"path":"core/crates/auths-verifier/src/observation.rs","sha256":"0bb07f06a0f9524c88427df1c972b1de8ba038a9eeeb15d3134c25125ae84b1e"},{"path":"core/crates/auths-verifier/src/trace.rs","sha256":"2213d72023a1d9e0413a2cf2c51c3dad9e04775d86033a0caaa9d29a8f0036f8"},{"path":"exchange/crates/auths-proof-exchange-model/Cargo.toml","sha256":"34b2db64f93a288e942b5a3918d28cdcbef906e0dc9074ce848018d3d5f7a1fa"},{"path":"exchange/crates/auths-proof-exchange-model/src/lib.rs","sha256":"49fac5aff2339d3a57c41cb8bb2a82852538e8f77ecc4b157c88e264ff31fb55"},{"path":"exchange/crates/auths-proof-exchange-port/Cargo.toml","sha256":"7ff660f1b7579dc570c791090aeb450404fbbf44c92781e289f5ccdde746d739"},{"path":"exchange/crates/auths-proof-exchange-port/src/lib.rs","sha256":"b408fb40c6432edc1facb3d8b3e9433a033f8dc73fe2e0ba5a88c972ca675021"},{"path":"product/config/auths-config/Cargo.toml","sha256":"e4b568ab9f6d84f7d7e6d66443fe825f360db9c27bc7c31d6ddc0647ba3ab304"},{"path":"product/config/auths-config/src/lib.rs","sha256":"fecf00ea65cef9018fda9af2063326d7065b869266d0d9e73a4f06816f1102cc"},{"path":"product/errors/auths-errors/Cargo.toml","sha256":"3b3a199b6460ba75bda84475bb5accd35e1485448a3981038db85bf4772dd350"},{"path":"product/errors/auths-errors/src/lib.rs","sha256":"7feeb9069fa4003f94f1f07c1c94619cf1c883e0dbaaf2187f04d0f742264bdd"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/Cargo.toml","sha256":"716f1f2a117d6d69d8effe9ee9057e24ba3502f20af6a602b06facb638cdabed"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/api.rs","sha256":"9ea61dd7ddd93282b073b98e453e6b75b26dc49689c04e9782435d06a3a09e48"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/clock.rs","sha256":"73f0a6e0f5903883329fa6683f5888288f759512ac69e5c87efd2b6b87f7d79f"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/http.rs","sha256":"14c1fce14e24c984b2a275563a29b6326fb08367922b6e8d37ba38b9cb81aa2b"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/identity.rs","sha256":"186de11230c8b33375951c4368609f8976bf9795f171af3fd7fac26207a94361"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs","sha256":"0b4617d044f5254a5ab22f5a2578f91cc025206a8c1845be39c1c56dcdf7a5df"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/names.rs","sha256":"41bb23572d6002e23ee103d6fe70ecd68764861c6f2e48a1c53af998270a4afa"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs","sha256":"39fed883f4802e68d3b41a68fea0aba0737810996b33d13577de70faba004c29"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/store.rs","sha256":"fc60ee9c49b2f4f063c449b4c78100c5c4872779e94ca168f796603b380ef6e4"},{"path":"product/integrations/auths-custody/Cargo.toml","sha256":"1e14034185ad1ec24a977fd5f41d0abee219606245c046ce2a82287fadef448b"},{"path":"product/integrations/auths-custody/src/conformance.rs","sha256":"8ed1afd58f18fc6becc268908aa6419c9aa404c79da0197963eb2599df44acf6"},{"path":"product/integrations/auths-custody/src/key.rs","sha256":"70cbb0fd21b6f5652157845a22c35be2d0f6c05b3d138fc4b9bb6dbdc3d81c40"},{"path":"product/integrations/auths-custody/src/lib.rs","sha256":"8ee593c1f59b0fd2126bdda9138026f5bc531beb64d4489a99785842e7b98b43"},{"path":"product/operations/auths-operations/Cargo.toml","sha256":"73dde1e914ba5e1386f8d49c0d730423cc72ae77ec44c6554a6a75cc8e8922b1"},{"path":"product/operations/auths-operations/src/explanation.rs","sha256":"b4a39bcbd5712cb9e735ee7deeb281f3fa6af5ddca973735bf3d87dce427ef11"},{"path":"product/operations/auths-operations/src/lib.rs","sha256":"3f401a56555113b98f57bca172a2660eaecedf76247b83a3fdbb089c133a29cd"},{"path":"product/operations/auths-operations/src/render/json.rs","sha256":"2ae042639960afee123730e945d373bc5dda1d2b3af20ae16c939a7e99b9e418"},{"path":"product/operations/auths-operations/src/render/mod.rs","sha256":"b3b7f6fe473f49227ace5a68bfc3d8dc14b5db8dd9888fd9e207070337b1b8bf"},{"path":"product/operations/auths-operations/src/render/text.rs","sha256":"f216cf3bdb00e264523271b16e7059535ac6b1aabf271cebd7935af155e4bfec"},{"path":"product/policy/auths-bounded-policy/Cargo.toml","sha256":"babd5d200923137ead71d8c2528f847cea323ce98da942a1320b054436612c47"},{"path":"product/policy/auths-bounded-policy/src/arithmetic.rs","sha256":"75e43c5d4eab8d1f71c1daf53839f5f9fe45a400afc1f63a30c6f55ce3632627"},{"path":"product/policy/auths-bounded-policy/src/commitment.rs","sha256":"c5706f2d583454e1a7f570f7ada138d4d864bef0205dfae7c1296774f396bb3f"},{"path":"product/policy/auths-bounded-policy/src/eligibility.rs","sha256":"c9acdfb793074e687fc36efad506be27dbd99ffbf40387bc66c8de39ef238432"},{"path":"product/policy/auths-bounded-policy/src/identifier.rs","sha256":"0006a32bae9eb16c4178cf797df418d2b0a781f2bc6474b741dc1a908141831c"},{"path":"product/policy/auths-bounded-policy/src/kernel.rs","sha256":"99187c28b161ac70bee1afed60711f7f645adb4d1671a01863f9849b369811d5"},{"path":"product/policy/auths-bounded-policy/src/lib.rs","sha256":"76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c"},{"path":"product/policy/auths-bounded-policy/src/receipt.rs","sha256":"3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad"},{"path":"product/policy/auths-bounded-policy/src/registry.rs","sha256":"4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0"},{"path":"product/profiles/auths-profile-api/Cargo.toml","sha256":"7ae85761f58625b5d678f961fd052eebf3e000ef565c7312e3ac857763c0017f"},{"path":"product/profiles/auths-profile-api/src/lib.rs","sha256":"a194b82b20bf8aa864c2334ef6c6aec30b2154ded972862252d5dcefa488ab95"},{"path":"product/profiles/auths-profile-mcp/Cargo.toml","sha256":"db264fc25242f7b7e4133cbe5782545b3107b406c87168ae072683cfb59eac66"},{"path":"product/profiles/auths-profile-mcp/src/arguments.rs","sha256":"a5de696586d507e2aee4a49fee99ef1ef4c51a2e46603f8838f1af6d9009833f"},{"path":"product/profiles/auths-profile-mcp/src/lib.rs","sha256":"d0f8b733a09ef8408336cdebc8948d6a5861012ce6878598b11be7084dfd4280"},{"path":"product/profiles/auths-profile-mcp/src/session.rs","sha256":"166c281fa66333388e4760d6098dad02d3359e1d5de4b8f93312c014f97abb03"},{"path":"product/qualification/auths-recipe-qualification/Cargo.toml","sha256":"b7b15b30b9a3d96d4f089d514266d3a892de6608d30707aa44be31cca89ca9fe"},{"path":"product/qualification/auths-recipe-qualification/src/canonical.rs","sha256":"30a9b50777f0dcb4b606abfee2467d5a975d9f6ad941ab6c13ca3df5b359f667"},{"path":"product/qualification/auths-recipe-qualification/src/closure.rs","sha256":"0ad6aee9bd981e2863fa725f209ec84031db2ff12f4c7ac3aaf5120f0bb86039"},{"path":"product/qualification/auths-recipe-qualification/src/commissioning.rs","sha256":"66ea49f96887c4642139a48d259c270816e2267ee8cf6344a1340fe47afda9da"},{"path":"product/qualification/auths-recipe-qualification/src/commissioning/tests.rs","sha256":"5a226725c2ad7ce920d0bd62d427185e007f4d0949b0f0ec1260aa161d3114d0"},{"path":"product/qualification/auths-recipe-qualification/src/error.rs","sha256":"52d5cf720a1e4579008fdda90a3ac2c31f0b8db57985f121f65e54b4da2b7dd1"},{"path":"product/qualification/auths-recipe-qualification/src/evidence.rs","sha256":"ba45a7409d67a8af26ab811af306412014557477a101ab2a8eb0faf8f2bd4b91"},{"path":"product/qualification/auths-recipe-qualification/src/ids.rs","sha256":"e81a906d571497ab2da753e1532d4443706410e0b75fdd59a7d2d788c7aec403"},{"path":"product/qualification/auths-recipe-qualification/src/launch.rs","sha256":"41f2e2de90e1e7d6440a66eda3eb9bea8d5e0741bc232305a76a363ab5f813c1"},{"path":"product/qualification/auths-recipe-qualification/src/lib.rs","sha256":"7d26c5bfe9769daebf90c5c2280e0d75742e4cc70d0e608408e0665e3f516a2b"},{"path":"product/qualification/auths-recipe-qualification/src/model.rs","sha256":"3484eb0ec287b23d4682ade7b1b0f8d1335985b3fb180f06fc28716076957d5f"},{"path":"product/qualification/auths-recipe-qualification/src/release.rs","sha256":"ec478e53f70052e566aac7e15be2f9e1b1cd46837ac6990ae955fa864d311586"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/mod.rs","sha256":"fa23a962fd90331152eed5edbcdf271955f7aed79b8da1e065bfe69a20b487a9"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/schemas.rs","sha256":"c59feec2805621f341a90f81fc005e2c12f7a70f9d264fdeacccb2be4fe1c046"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/verification.rs","sha256":"6a6b5834c5dae10af1ba8939b2deae43b85db71544dc8f077ff63b7fe68ac8a8"},{"path":"product/qualification/auths-recipe-qualification/src/verify.rs","sha256":"2ec2784435d11e07295de77b2ee1b2c48b2fcf9609a00454c6e7374b621aed5c"},{"path":"product/receipts/auths-receipts/Cargo.toml","sha256":"6001fa1375899953aafcb07c23a6da0c8f57ea7ec08bb9c950b12a60a8cc6f0f"},{"path":"product/receipts/auths-receipts/src/disclosure.rs","sha256":"ba9ed439be0a320c8a01f5b6e9b51361c1a37e076947490d8e4a484ba6bb119c"},{"path":"product/receipts/auths-receipts/src/lib.rs","sha256":"547a57c4160256719cafb7d0ab972d9fc80b0da14fbbce4148c70c414070ff36"},{"path":"product/runtime/auths-connections/Cargo.toml","sha256":"babeb6e1dda3dfb66291713ce1e43dce5c349833d0b50ea4dccbf986030026b2"},{"path":"product/runtime/auths-connections/src/credential.rs","sha256":"82921413bb053f0f6c7931fbd4e6a86c8cc1d8c6b51debd9c2cef33a8d5b1c51"},{"path":"product/runtime/auths-connections/src/kernel.rs","sha256":"a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8"},{"path":"product/runtime/auths-connections/src/lib.rs","sha256":"79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22"},{"path":"product/runtime/auths-connections/src/model.rs","sha256":"de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77"},{"path":"product/runtime/auths-connections/src/registry.rs","sha256":"e57640e003e72ad3235c567c2bb944a262bd64e673f023b62ea091094cc7e946"},{"path":"product/runtime/auths-gateway-kernel/Cargo.toml","sha256":"34f864e67656af4ac7e5c7a347a23f01fc8ab31365b8e23c0ef474483b14a183"},{"path":"product/runtime/auths-gateway-kernel/src/construct.rs","sha256":"e9d65744bae273d65face4285e5d2da75c06a92ab48f7b8333d496604e31c63c"},{"path":"product/runtime/auths-gateway-kernel/src/lib.rs","sha256":"cfda6f8453426564c085475f183b6f790b438768a19668f1b65d33ba59dc8632"},{"path":"product/runtime/auths-gateway-kernel/src/order.rs","sha256":"e0045f877c4b7fe3860c291039853885064ddcdebba7c9b345ab65e81e646dda"},{"path":"product/runtime/auths-gateway-kernel/src/outcome.rs","sha256":"e9785b1afe70788c89b51b18655bcd5acff7b0c8e3d12fb79c6f05a202e67e6b"},{"path":"product/runtime/auths-gateway-kernel/src/ratio.rs","sha256":"7ace22264812e6fc1ef3a62afee402cf43494bb71ae0d3de219ad1b39d690bcb"},{"path":"product/runtime/auths-gateway-kernel/src/recovery.rs","sha256":"9f46dcd1685ab6e4d1ba04a3fc286a9f3afee8fb47829be1fbc670a7926a2dc6"},{"path":"product/runtime/auths-gateway-kernel/src/transition.rs","sha256":"cefb8f01d915880f6921f2501ff881ad94b9de61072c34d9cd19220992f97374"},{"path":"product/runtime/auths-gateway/Cargo.toml","sha256":"00b28be86921dcdc0ad90cce0c62c2961cafefe96ea6c2edf0e926c3d405ccad"},{"path":"product/runtime/auths-gateway/src/admin.rs","sha256":"2d5cc67afac42fbd15f36e2d1693cd1b20cedacf775040dce6ffe04ccc94c9ea"},{"path":"product/runtime/auths-gateway/src/app.rs","sha256":"6f80f63833ea0815bb44fbf3b0cc54624a08e9fb578b035819f2980dc04e8256"},{"path":"product/runtime/auths-gateway/src/audit.rs","sha256":"0edb2037eb7b5d6f13acfce85c54f62a82bf7fdd31bc7e626c4fec183cef61dd"},{"path":"product/runtime/auths-gateway/src/audit_tests.rs","sha256":"990969384a52d75bc2489d9d412a9e7dd814bca1c8f65c701d6205fae62a15d5"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway-harness.rs","sha256":"12b0c24d36b2e6a3be392d3c081a783b355fdd67dc5b54bacc0410e803116b8c"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway.rs","sha256":"89e5e073e3be743f40dbf17d3fdad61f94de2da3dc1d10dd0e67c85b1f8f874b"},{"path":"product/runtime/auths-gateway/src/binding.rs","sha256":"663b0ce878319511aa7d05722ab4ab2fa9be18817884ffb2ee9f131ff1e382d1"},{"path":"product/runtime/auths-gateway/src/bounds.rs","sha256":"38251ad6f22f9d07ef9a219c79fa265ca36f1526eca5f147d7efa46b52ad609d"},{"path":"product/runtime/auths-gateway/src/bounds_aggregate_tests.rs","sha256":"ab34f227b7c8692ba1da88ccb32bb3687a66adf8353d8282fae905d4a88eb612"},{"path":"product/runtime/auths-gateway/src/bounds_tests.rs","sha256":"74136bc570da7b9338b5a1a1ed9d3fd892c55135160964f9d3ac0e2cf5741375"},{"path":"product/runtime/auths-gateway/src/commissioning_budget.rs","sha256":"fab29da3269438cc62330f3eab7b5bd4dc482b4db8af243aae47df5d3aa1deb8"},{"path":"product/runtime/auths-gateway/src/commissioning_budget/tests.rs","sha256":"ad182c391b70450582c6ca06e3dadc221409bb3cdbc3c7668dbfc7fbedf63505"},{"path":"product/runtime/auths-gateway/src/commissioning_floor.rs","sha256":"7fa6991c5ccd5ae1403be84b3da390323fab09f36e15ac01fd7a38ea350c6fdb"},{"path":"product/runtime/auths-gateway/src/commissioning_floor/tests.rs","sha256":"5f7868252dfccb787d26f63ea6d5c3701c72d52c0ff0bc656dd5895f8cbed551"},{"path":"product/runtime/auths-gateway/src/commissioning_session.rs","sha256":"24b48d5eaeaaa3c620e2dfc7ee1f9255fc4519a1eb404b8608cea7af6a910ee2"},{"path":"product/runtime/auths-gateway/src/commissioning_session/tests.rs","sha256":"8f8ff5175cecf8a49b8e4acfcd4fa3179cfb656c53275d8246aff59de7c6ae0d"},{"path":"product/runtime/auths-gateway/src/connection.rs","sha256":"7b5d049c258a26ed1c93ecf860f51d051a8a65f9b93554af0b1ea93862398ec9"},{"path":"product/runtime/auths-gateway/src/credential_journal.rs","sha256":"7297fccaee5cd8622928e8e0a42bba50da7941970a6f682ecd300c41ee6509da"},{"path":"product/runtime/auths-gateway/src/echo_verify.rs","sha256":"6d453051665f823abd7354d5c50031d9524cf47d6092d2f09080ae814e3b9575"},{"path":"product/runtime/auths-gateway/src/engine.rs","sha256":"1b4ec0f0692a9af7fa29a0dabb3d22192d70fdb704b369d406e2cd8204dc82fe"},{"path":"product/runtime/auths-gateway/src/fuzzing.rs","sha256":"ed3b0028487eb546a3b0a91d115aa8f18bcea324b61620bfe8e35a9e6ab18758"},{"path":"product/runtime/auths-gateway/src/generation_floor.rs","sha256":"fe1510ec96ce0f67e9a78edbfa94b33eb7df64c0ac4d0a67901124dcd0164777"},{"path":"product/runtime/auths-gateway/src/harness.rs","sha256":"c87e479f3eb281960f6c9c80d43c7560d7ccb654b0154ec823d3fcec4884ac05"},{"path":"product/runtime/auths-gateway/src/lib.rs","sha256":"1a36e2276a96645a76bf109ad9e687a743934e31349ffb0b9e5b1c271e0385c8"},{"path":"product/runtime/auths-gateway/src/listener.rs","sha256":"aa08239bcbc1fcb55e8a212fbdf6a84f12985b0d436dcb51dc58b06e59e435f2"},{"path":"product/runtime/auths-gateway/src/observed_tests.rs","sha256":"a22be071695f89ca2578a4d82fd80d9cb82289213c9bdb8f0470f6b2dc3d9201"},{"path":"product/runtime/auths-gateway/src/observer.rs","sha256":"562ffcaea071c3856e0708dc2fe33516917e145d2438aabb75af0a2b6ba01046"},{"path":"product/runtime/auths-gateway/src/onboarding.rs","sha256":"0dfd7d67e7f02f18a28d1c86ca1b7751d7463f5efcdbe3825de0ad8cbccb3891"},{"path":"product/runtime/auths-gateway/src/operator.rs","sha256":"c3c36954a3e86723df035b47f43b85fc8ab3a6292983522b6258d5c6b4e6c4e4"},{"path":"product/runtime/auths-gateway/src/pending_vectors/attempts.rs","sha256":"47ef3c8cb1c5504d47ae9a0088705ce6715fe86bac1671a34a56fb38a64d0dd3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/bounds.rs","sha256":"e612217307e1da5b0eb5ee6582a7458bb064b8aa8a529fc6555b1b334127ab68"},{"path":"product/runtime/auths-gateway/src/pending_vectors/codes.rs","sha256":"e00670a5ef24eb856cc2c6dcda8e5a263842f55c76bb939c0c27bd9df37e5522"},{"path":"product/runtime/auths-gateway/src/pending_vectors/keys.rs","sha256":"f84c56f2ea9cb34b2b79c72d13fbf2c6585010ec1ed450af58a78c80c1ea1edd"},{"path":"product/runtime/auths-gateway/src/pending_vectors/mod.rs","sha256":"5de8340f0ef71a0b57a09e323fefe473d3160c6ae952b9ba46f714825fbacafc"},{"path":"product/runtime/auths-gateway/src/pending_vectors/outcomes.rs","sha256":"8ec07b9511b48913af36ac999d2aa0e82924289f6acb23ddaeb9f00f99815166"},{"path":"product/runtime/auths-gateway/src/pending_vectors/production.rs","sha256":"772d032e0a0d9c924fb6d6c188528db85a97e71c9e466ddc19eee277baf83614"},{"path":"product/runtime/auths-gateway/src/pending_vectors/recipes.rs","sha256":"51693208270231c25c3aef2a32151d5962114c71e86b88cb9df83181c7af83d9"},{"path":"product/runtime/auths-gateway/src/pre_entry.rs","sha256":"06ea78ca140468bfaba17d9ab04912ad68673954c3203c98fed28272ff2a00c0"},{"path":"product/runtime/auths-gateway/src/property_tests.rs","sha256":"939c081e2e154aaf10186754044bdd65608932c899b970a04a71d0afaa999a93"},{"path":"product/runtime/auths-gateway/src/qualification.rs","sha256":"c597c83de2b94f0374ae54e40a8b57c2a64ec6e254704dca32185f448a908aca"},{"path":"product/runtime/auths-gateway/src/qualification_simulation.rs","sha256":"4ee7cadfb5f46a92713c80f3e55f499cb074d04d8b21ea89d57762af38642bfa"},{"path":"product/runtime/auths-gateway/src/qualification_tests.rs","sha256":"a9178a2e58eea459d5e5dafc53a3999ea7c84dbbffefe6e5eb1f3d098827f028"},{"path":"product/runtime/auths-gateway/src/quorum_tests.rs","sha256":"a78380b019104d688c11a4410082c7e08ded3106aab099954c4f8a1b4ae0fd89"},{"path":"product/runtime/auths-gateway/src/readiness.rs","sha256":"911c3f11892f94641574375e2da4c671c802738f71082f12c39832331052d43d"},{"path":"product/runtime/auths-gateway/src/recipe.rs","sha256":"fecf9af67e7afc48d080e9f8f55f8ce28e49d0e08988717a27908bbda461d6b6"},{"path":"product/runtime/auths-gateway/src/recipe/lower.rs","sha256":"8088b8751ed831dbb48247af953c6290ac95e2a438ccd5bd65eff54be06a1fd1"},{"path":"product/runtime/auths-gateway/src/recipe/review.rs","sha256":"c3eb7d9fdd98dacf52750b14b67ad7b7faaecbbdeafff1e0b049f67d0a2d0139"},{"path":"product/runtime/auths-gateway/src/recipe/runtime.rs","sha256":"c286f0d15f974402822c0810d8e97f98411dc1c557755cc23e540d85e2bb42d9"},{"path":"product/runtime/auths-gateway/src/recipe/source.rs","sha256":"1af50298fb1461e1b24cbdf560d43124d6b1c4c529586c911b1c4797214a69ff"},{"path":"product/runtime/auths-gateway/src/recipe/tests.rs","sha256":"aac551a2481bbc60864c64079bc667dcb232e45a0f41a04073ed84ab5dbe1fce"},{"path":"product/runtime/auths-gateway/src/recipe/validate.rs","sha256":"3711b17605cb7b0d639bc1b180449231f5882a306cab20e2c7782155cc63b0d4"},{"path":"product/runtime/auths-gateway/src/scenario_tests.rs","sha256":"a8ea1e3a7bf6b0274455bd790ace3ffb9c8716609cde92248920945c61634685"},{"path":"product/runtime/auths-gateway/src/separation.rs","sha256":"be9306848ca5d801767cf6aa14247c8618312ef0e202f00ce0c24c4844491061"},{"path":"product/runtime/auths-gateway/src/simulation_attestation.rs","sha256":"88705e5d45415f760f1e3c3a065c35c48f4f4065bf7b3feb7882246983814d6f"},{"path":"product/runtime/auths-gateway/src/store.rs","sha256":"884bcad4d70d53e12eae9c8517f6ecd0643068ee0be0370015119d04d6cc2516"},{"path":"product/runtime/auths-gateway/src/store_testkit.rs","sha256":"88d82fee42f1b8ef521e8deef0216e938ebeaad822eb2f5020e70b89d145ea70"},{"path":"product/runtime/auths-gateway/src/submit.rs","sha256":"fe2eacb5ad8152eeecbd232c47a356fc72db0098e34fda99532bdf6ef0cf895c"},{"path":"product/runtime/auths-gateway/src/support.rs","sha256":"9fd979029793a22b15d9776a7fc172476fd7c126a80d4080c65d720845becbcb"},{"path":"product/runtime/auths-gateway/src/transport.rs","sha256":"be2c6dc75b8daec110bf8749fedc3823f6067d40b999aa3eb21126896a97d3ad"},{"path":"product/runtime/auths-kernel-runtime/Cargo.toml","sha256":"926bcd0053e5edd703be8f0027ad009e2982db013c8174c1366edbf38b48087d"},{"path":"product/runtime/auths-kernel-runtime/src/lib.rs","sha256":"7108faae9ca4bc32dc093ddaf885ac8f74f3c9b8d317b7c7d0ed00d1d0ab5972"},{"path":"product/runtime/auths-lifecycle/Cargo.toml","sha256":"c5053c705f8d5554b44e432fe75287a2faf11d644e5a2552e45ad6cd94176af5"},{"path":"product/runtime/auths-lifecycle/src/codec.rs","sha256":"51c4b746749150e8bfcd8ff972b3f6c1ef40bec15583448ec1b471d9ad737dc0"},{"path":"product/runtime/auths-lifecycle/src/digest.rs","sha256":"55282cd7d8aba37713c2dcb5357c9877819edb72a30eadefb860d28d7d3a3eb7"},{"path":"product/runtime/auths-lifecycle/src/identifier.rs","sha256":"31620e8c16de68d3d2d3b84d6353c1a5b9d4151d8247f91fa389b906a8e660f1"},{"path":"product/runtime/auths-lifecycle/src/kernel.rs","sha256":"2abb8c094b36d35b364e74d78091d14c5d6f3d1eb6552cca3b5538dbd017ce23"},{"path":"product/runtime/auths-lifecycle/src/lib.rs","sha256":"afe5a345cd309b5a4f08ffba3170a6d7f16ff914892b3f2006d5208ed24ec736"},{"path":"product/runtime/auths-lifecycle/src/model.rs","sha256":"1af12bbeeeaa65ec02ddcebd7d2c8c92ec1e339fa40ae85b45ab9b01a722a4fa"},{"path":"product/runtime/auths-lifecycle/src/operation.rs","sha256":"78e6d05fcf5d7ea4f148032a3fa26fdfcab77eb346019effe927b08e0d64d732"},{"path":"product/runtime/auths-lifecycle/src/registry.rs","sha256":"53495fe6f7a77422593a41623e28716f1c140dcc1e00f87f6b0ffbfb93a5ef90"},{"path":"product/runtime/auths-lifecycle/src/sealed.rs","sha256":"2e0c03b5813c926c159598bb7890d1523825edbe57cd687d42a5dfb3374a0c19"},{"path":"product/runtime/auths-lifecycle/src/test_support.rs","sha256":"221d9a5c5ef8e1f9f8fd66927484eaf813571d0568470278ecd8fa08a5eec8cd"},{"path":"product/runtime/auths-lifecycle/src/transition.rs","sha256":"011805a28efdd541f44ccea54dd0e34a1e58f4004447ee58013703b4fb6b2822"},{"path":"product/runtime/auths-runtime/Cargo.toml","sha256":"dd29d80a8b4bb56c869f036a6c9998f6e6d1c0383ac5dc03fa42b24abe2a7ff7"},{"path":"product/runtime/auths-runtime/src/lib.rs","sha256":"132ca03d58c14905d3a822a4972f42a22a5ad33a45f2ba9ca44f3a57d810b4b0"},{"path":"product/runtime/auths-runtime/src/production.rs","sha256":"fd4eff4270c571c10fcff6cf27df28961ebf074de8a1a028f500fda1ca376820"},{"path":"product/sdk/auths-approval-quorum/Cargo.toml","sha256":"df904971fca87a24194c5816738a331588fe8f164acb5d70839a35dca5f57114"},{"path":"product/sdk/auths-approval-quorum/src/lib.rs","sha256":"72e4086088a1c0912e4e1a9e980f26a5c280bf5ab16ea39c9f0f58d5096ac2ce"},{"path":"product/sdk/auths-approval-quorum/src/remote.rs","sha256":"9fa029c7c63003adf260f8aec55160c545681c60c1bace0d934e7525862aac7b"},{"path":"product/sdk/auths-approval-quorum/src/remote_tests.rs","sha256":"8a09ce17cfee82a035a74edd535f3ebeb3db0e078784740d3997b17dbdb10197"},{"path":"product/sdk/auths-approval-quorum/src/tests.rs","sha256":"0acbf12be3e497dcc6c2d8f29c9af3b1a7ed8e11b75f6399570d4f217a785060"},{"path":"product/stores/auths-stores/Cargo.toml","sha256":"a32c4b76d17b264be5d40d24497ff237e1ed87822e8bab86229b3db93106dbe3"},{"path":"product/stores/auths-stores/src/gateway_attempt.rs","sha256":"218841602d3d9b23b44625f50e5b54cf275ccedc2d5c89f02d2482b8524472af"},{"path":"product/stores/auths-stores/src/lib.rs","sha256":"e721262edf8a9ab5568ddc27639176312d4a366203b5f73e2d7c11fde2c554e9"},{"path":"product/stores/auths-stores/src/lifecycle.rs","sha256":"3f2cecfda13fdcd7c4a944518646bcc8abd1237f900c0332d5822281f8f9f1cd"}],"schema":"auths.gateway-semantic-closure/1"} \ No newline at end of file +{"files":[{"path":"Cargo.lock","sha256":"0e75e2fdef44e79e57797ac6661295ae58ddb8de4a1990a6fd22ce6c54f78604"},{"path":"Cargo.toml","sha256":"6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24"},{"path":"core/adapters/auths-did-keri/Cargo.toml","sha256":"86ba3e3f9a0a70d970568bfb3113b7ba7bbdd81c3eebbb52743dd574a0c0ecaa"},{"path":"core/adapters/auths-did-keri/src/lib.rs","sha256":"a75674842f8a7142004369ccd206ab43e476459293f0ff4bed4d4e659031b3e3"},{"path":"core/adapters/auths-did-key/Cargo.toml","sha256":"d5a3ae07ecde83f91eed4c3785051dd0f44eab6c891754f3309b6b40596707d7"},{"path":"core/adapters/auths-did-key/src/lib.rs","sha256":"b76a3f4528a725df53cfa9242e6e414e1d26caa48468aaed497e28b121f4497c"},{"path":"core/adapters/auths-raw-key/Cargo.toml","sha256":"f49616bc18c19e6aaa7e6a02ccebcdb9f5c1422c1278ef9869e0dbf22ceda7be"},{"path":"core/adapters/auths-raw-key/src/lib.rs","sha256":"45eec1b295dac3bed65cd79c942870b926b06b3f5d38eaebaeb6140ac69315fa"},{"path":"core/crates/auths-algebra-kernel/Cargo.toml","sha256":"0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba"},{"path":"core/crates/auths-algebra-kernel/src/generated.rs","sha256":"ae4bcbef42a408c7ffa0c6a74a42f7de177a6f14479e51d205acf830bda05960"},{"path":"core/crates/auths-algebra-kernel/src/lib.rs","sha256":"6654667eeb9b353d6648954c9fd2e8838462a82ce6b2803eb49e1366892c68c6"},{"path":"core/crates/auths-assurance/Cargo.toml","sha256":"afcb12a97ddd09d7a264b9ecd3fcaefc865ff2c9b4539ee85b00883420ba333a"},{"path":"core/crates/auths-assurance/src/lib.rs","sha256":"0fb2ec844d674b25a9e20b1601452c89c2454901fa506adfa9bb38ef9a7fa213"},{"path":"core/crates/auths-author/Cargo.toml","sha256":"1e6f0e3bc079ddb558decf0db26b291c6e72fc47327b6df1b7650d41689b215f"},{"path":"core/crates/auths-author/src/lib.rs","sha256":"e14475f2f49715a1869d5fa6b11ff1fbb72497e39097e09f833b0bae7e5b3f2b"},{"path":"core/crates/auths-author/src/observations.rs","sha256":"dda7d6bfa6f4bd7e95a480ca283c2c0e996f69c5c15cb0c7197af328131a7066"},{"path":"core/crates/auths-authority/Cargo.toml","sha256":"4f68212938029f79ebd857b4f3038494eb85d0163d49f07e51376715cf959815"},{"path":"core/crates/auths-authority/src/lib.rs","sha256":"da88d5194de4e17449e69972c0fb042afa3c39798a8f570f30771e77c384f1eb"},{"path":"core/crates/auths-codec/Cargo.toml","sha256":"e20e51826e17814effd9d8925d18d5fbdd6c0d37bf50231e743ec2611314722c"},{"path":"core/crates/auths-codec/src/approval.rs","sha256":"fbff43bf4d57f69f8b7738a8647751cde75c5a932dee65d924a1fe9c7202f91f"},{"path":"core/crates/auths-codec/src/bounded_policy.rs","sha256":"d21f6728be2d8a04b6d94921f2b683f7e61cbb42e0ac6866f1c88a49caa534c3"},{"path":"core/crates/auths-codec/src/decode.rs","sha256":"ba2999584cdf53b1b517ecb9c7ea50d39efee17c666a9a38e2ad1ac94379f778"},{"path":"core/crates/auths-codec/src/encode.rs","sha256":"8491192053e2e15d62b4d2a491de22405b7487ead69ab6f6bca40669ce7ca5f7"},{"path":"core/crates/auths-codec/src/error.rs","sha256":"fecb0737c16deb42d859f1dc7727c698438d9ac12064fd99e0024629642c390c"},{"path":"core/crates/auths-codec/src/hash.rs","sha256":"f88e111f1dbb2cef6b7b5e9c948cb45ff92e366710c8a5f5c636138aa748479e"},{"path":"core/crates/auths-codec/src/lib.rs","sha256":"3b0e5c94c6f34f750b88a9333e1d5c8145746d845d3a23e0d2f61807cf592ea7"},{"path":"core/crates/auths-codec/src/observation.rs","sha256":"38328b0c71ff97a4196eeade8b4faa889527ff1f80bb168468bcd49082a3987e"},{"path":"core/crates/auths-composition/Cargo.toml","sha256":"331e13025eb82588b5269ed3975929eb41c823d588c49e4c296273d85c6fe80e"},{"path":"core/crates/auths-composition/src/lib.rs","sha256":"e42e3b0b6a9985b73c533aeb23799c638979aa27a9ce7d0f10a8d60340570fb1"},{"path":"core/crates/auths-model/Cargo.toml","sha256":"565c15302b0cc9270db1e28efa3862804846850ba933cc17aea8abcec4a65987"},{"path":"core/crates/auths-model/src/approval.rs","sha256":"54cf44a9ef747ec21546a4086aecfb130bc7803b0d646430e6082df51e6e305f"},{"path":"core/crates/auths-model/src/bounded.rs","sha256":"f90496abc0a06c028b4d850af6ddab7d850bfafeaa3d042f1b1246a41d8bbbc9"},{"path":"core/crates/auths-model/src/bounded_policy.rs","sha256":"306a8f049cc7cfc7635fe0e4de47eb7813eed63d3c14c3be2b51586aa4eea450"},{"path":"core/crates/auths-model/src/lib.rs","sha256":"e7cfe6bb9574c6b016aa63e70658c31e0b90903ec6479a49f4a2ceb64f5bad97"},{"path":"core/crates/auths-model/src/observation.rs","sha256":"b3ed3e3cc090afca2896a7d3de7988afccc1ee1ea0ebd91b51a8bc0f20ad8dbb"},{"path":"core/crates/auths-multikey/Cargo.toml","sha256":"858756c1197befcada06134742bffe8d58cf674cadd6c046bf710570e96efaf2"},{"path":"core/crates/auths-multikey/src/lib.rs","sha256":"f5177fffb11e40eeaaa665ba886c541fc1f24d5eacdd6983fb03dc20148733f0"},{"path":"core/crates/auths-ports/Cargo.toml","sha256":"596a9b0f5af3717c16a6d13f7054d8a106bcd9f01f5f72c2235dd2afcf0ab16c"},{"path":"core/crates/auths-ports/src/binding.rs","sha256":"a16c012d40aa4249e3ec54372b9611006d0bfe8c7dc3c741911c2194ad17736d"},{"path":"core/crates/auths-ports/src/diagnostics.rs","sha256":"aa596572503b5a65a918bb2ff38281c144ff53821ee914e9325c852828d852df"},{"path":"core/crates/auths-ports/src/lib.rs","sha256":"8da1debf86f9532df0660155d04298beb1ba3a1204508f8586e2e67cd2fb3449"},{"path":"core/crates/auths-ports/src/path.rs","sha256":"b68fc547b4e4d97a60cbbc1cc1939fc6b34a8233b81f840bd396914a707e3ea1"},{"path":"core/crates/auths-raw-key-core/Cargo.toml","sha256":"98c0bc8527a537512e43a74dd6ba9658c6f0cdc16610cf938e3f9b43785d836d"},{"path":"core/crates/auths-raw-key-core/src/lib.rs","sha256":"98c0500c41697aae28708ad0bf970b9a97583d96a3d2c18d23e7fa351e0f7d12"},{"path":"core/crates/auths-registries/Cargo.toml","sha256":"590e49e58b0622d9d6274fea46796dcdb07dec9550eff295cce6a6427ffa51e2"},{"path":"core/crates/auths-registries/src/lib.rs","sha256":"450d3886d85ee333b7e046317fb5b47cde62483d5f3e41d46265e2caf4c373ec"},{"path":"core/crates/auths-registries/src/template.rs","sha256":"1224039dd2b3ce6fa8357613d8cafbae40400493da7176da202b9ade62fa05e4"},{"path":"core/crates/auths-signature-core/Cargo.toml","sha256":"6bee2230eb30af1be0bd5c2d57bd3e1903497a70028d47290d4ac6e9e0e8bca0"},{"path":"core/crates/auths-signature-core/src/lib.rs","sha256":"6e3f9311ded5e49ea50d445eb21e6d8fa12442aa4362a73e0cb6fda15b7cd865"},{"path":"core/crates/auths-signature/Cargo.toml","sha256":"7f7b5682466ba439d8c59579022cb61068cad9fb4bd2d73e1cc21327c902b450"},{"path":"core/crates/auths-signature/src/lib.rs","sha256":"b3d9ac4cc3ba0797b9e1c09f2d6ac05089b25dac4e285a5af28c0165b33d925b"},{"path":"core/crates/auths-verifier/Cargo.toml","sha256":"c43358e06a33324b41a8b93e5cc7279c55f7d21f1f6cfaa539a3fc7b4c27a38f"},{"path":"core/crates/auths-verifier/src/approval.rs","sha256":"c3cae6a49e169051eb555bb092b1069a4d422516d6a2114623a89e5f31ff923f"},{"path":"core/crates/auths-verifier/src/causal.rs","sha256":"9635230f33b13a263573d319ac8a1976addbcc07677514a43e3c7bf28dc04587"},{"path":"core/crates/auths-verifier/src/lib.rs","sha256":"f22dec38dfa47ced8da4f605390da8453273bee1da010f57fd1fdfcb10e0b389"},{"path":"core/crates/auths-verifier/src/observation.rs","sha256":"0bb07f06a0f9524c88427df1c972b1de8ba038a9eeeb15d3134c25125ae84b1e"},{"path":"core/crates/auths-verifier/src/trace.rs","sha256":"2213d72023a1d9e0413a2cf2c51c3dad9e04775d86033a0caaa9d29a8f0036f8"},{"path":"exchange/crates/auths-proof-exchange-model/Cargo.toml","sha256":"34b2db64f93a288e942b5a3918d28cdcbef906e0dc9074ce848018d3d5f7a1fa"},{"path":"exchange/crates/auths-proof-exchange-model/src/lib.rs","sha256":"49fac5aff2339d3a57c41cb8bb2a82852538e8f77ecc4b157c88e264ff31fb55"},{"path":"exchange/crates/auths-proof-exchange-port/Cargo.toml","sha256":"7ff660f1b7579dc570c791090aeb450404fbbf44c92781e289f5ccdde746d739"},{"path":"exchange/crates/auths-proof-exchange-port/src/lib.rs","sha256":"b408fb40c6432edc1facb3d8b3e9433a033f8dc73fe2e0ba5a88c972ca675021"},{"path":"product/config/auths-config/Cargo.toml","sha256":"e4b568ab9f6d84f7d7e6d66443fe825f360db9c27bc7c31d6ddc0647ba3ab304"},{"path":"product/config/auths-config/src/lib.rs","sha256":"fecf00ea65cef9018fda9af2063326d7065b869266d0d9e73a4f06816f1102cc"},{"path":"product/errors/auths-errors/Cargo.toml","sha256":"3b3a199b6460ba75bda84475bb5accd35e1485448a3981038db85bf4772dd350"},{"path":"product/errors/auths-errors/src/lib.rs","sha256":"7feeb9069fa4003f94f1f07c1c94619cf1c883e0dbaaf2187f04d0f742264bdd"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/Cargo.toml","sha256":"716f1f2a117d6d69d8effe9ee9057e24ba3502f20af6a602b06facb638cdabed"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/api.rs","sha256":"9ea61dd7ddd93282b073b98e453e6b75b26dc49689c04e9782435d06a3a09e48"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/clock.rs","sha256":"73f0a6e0f5903883329fa6683f5888288f759512ac69e5c87efd2b6b87f7d79f"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/http.rs","sha256":"14c1fce14e24c984b2a275563a29b6326fb08367922b6e8d37ba38b9cb81aa2b"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/identity.rs","sha256":"186de11230c8b33375951c4368609f8976bf9795f171af3fd7fac26207a94361"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs","sha256":"0b4617d044f5254a5ab22f5a2578f91cc025206a8c1845be39c1c56dcdf7a5df"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/names.rs","sha256":"41bb23572d6002e23ee103d6fe70ecd68764861c6f2e48a1c53af998270a4afa"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs","sha256":"39fed883f4802e68d3b41a68fea0aba0737810996b33d13577de70faba004c29"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/store.rs","sha256":"fc60ee9c49b2f4f063c449b4c78100c5c4872779e94ca168f796603b380ef6e4"},{"path":"product/integrations/auths-custody/Cargo.toml","sha256":"1e14034185ad1ec24a977fd5f41d0abee219606245c046ce2a82287fadef448b"},{"path":"product/integrations/auths-custody/src/conformance.rs","sha256":"8ed1afd58f18fc6becc268908aa6419c9aa404c79da0197963eb2599df44acf6"},{"path":"product/integrations/auths-custody/src/key.rs","sha256":"70cbb0fd21b6f5652157845a22c35be2d0f6c05b3d138fc4b9bb6dbdc3d81c40"},{"path":"product/integrations/auths-custody/src/lib.rs","sha256":"8ee593c1f59b0fd2126bdda9138026f5bc531beb64d4489a99785842e7b98b43"},{"path":"product/operations/auths-operations/Cargo.toml","sha256":"73dde1e914ba5e1386f8d49c0d730423cc72ae77ec44c6554a6a75cc8e8922b1"},{"path":"product/operations/auths-operations/src/explanation.rs","sha256":"b4a39bcbd5712cb9e735ee7deeb281f3fa6af5ddca973735bf3d87dce427ef11"},{"path":"product/operations/auths-operations/src/lib.rs","sha256":"3f401a56555113b98f57bca172a2660eaecedf76247b83a3fdbb089c133a29cd"},{"path":"product/operations/auths-operations/src/render/json.rs","sha256":"2ae042639960afee123730e945d373bc5dda1d2b3af20ae16c939a7e99b9e418"},{"path":"product/operations/auths-operations/src/render/mod.rs","sha256":"b3b7f6fe473f49227ace5a68bfc3d8dc14b5db8dd9888fd9e207070337b1b8bf"},{"path":"product/operations/auths-operations/src/render/text.rs","sha256":"f216cf3bdb00e264523271b16e7059535ac6b1aabf271cebd7935af155e4bfec"},{"path":"product/policy/auths-bounded-policy/Cargo.toml","sha256":"babd5d200923137ead71d8c2528f847cea323ce98da942a1320b054436612c47"},{"path":"product/policy/auths-bounded-policy/src/arithmetic.rs","sha256":"75e43c5d4eab8d1f71c1daf53839f5f9fe45a400afc1f63a30c6f55ce3632627"},{"path":"product/policy/auths-bounded-policy/src/commitment.rs","sha256":"c5706f2d583454e1a7f570f7ada138d4d864bef0205dfae7c1296774f396bb3f"},{"path":"product/policy/auths-bounded-policy/src/eligibility.rs","sha256":"c9acdfb793074e687fc36efad506be27dbd99ffbf40387bc66c8de39ef238432"},{"path":"product/policy/auths-bounded-policy/src/identifier.rs","sha256":"0006a32bae9eb16c4178cf797df418d2b0a781f2bc6474b741dc1a908141831c"},{"path":"product/policy/auths-bounded-policy/src/kernel.rs","sha256":"99187c28b161ac70bee1afed60711f7f645adb4d1671a01863f9849b369811d5"},{"path":"product/policy/auths-bounded-policy/src/lib.rs","sha256":"76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c"},{"path":"product/policy/auths-bounded-policy/src/receipt.rs","sha256":"3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad"},{"path":"product/policy/auths-bounded-policy/src/registry.rs","sha256":"4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0"},{"path":"product/profiles/auths-profile-api/Cargo.toml","sha256":"7ae85761f58625b5d678f961fd052eebf3e000ef565c7312e3ac857763c0017f"},{"path":"product/profiles/auths-profile-api/src/lib.rs","sha256":"a194b82b20bf8aa864c2334ef6c6aec30b2154ded972862252d5dcefa488ab95"},{"path":"product/profiles/auths-profile-mcp/Cargo.toml","sha256":"db264fc25242f7b7e4133cbe5782545b3107b406c87168ae072683cfb59eac66"},{"path":"product/profiles/auths-profile-mcp/src/arguments.rs","sha256":"a5de696586d507e2aee4a49fee99ef1ef4c51a2e46603f8838f1af6d9009833f"},{"path":"product/profiles/auths-profile-mcp/src/lib.rs","sha256":"d0f8b733a09ef8408336cdebc8948d6a5861012ce6878598b11be7084dfd4280"},{"path":"product/profiles/auths-profile-mcp/src/session.rs","sha256":"166c281fa66333388e4760d6098dad02d3359e1d5de4b8f93312c014f97abb03"},{"path":"product/qualification/auths-recipe-qualification/Cargo.toml","sha256":"b7b15b30b9a3d96d4f089d514266d3a892de6608d30707aa44be31cca89ca9fe"},{"path":"product/qualification/auths-recipe-qualification/src/canonical.rs","sha256":"30a9b50777f0dcb4b606abfee2467d5a975d9f6ad941ab6c13ca3df5b359f667"},{"path":"product/qualification/auths-recipe-qualification/src/closure.rs","sha256":"0ad6aee9bd981e2863fa725f209ec84031db2ff12f4c7ac3aaf5120f0bb86039"},{"path":"product/qualification/auths-recipe-qualification/src/commissioning.rs","sha256":"66ea49f96887c4642139a48d259c270816e2267ee8cf6344a1340fe47afda9da"},{"path":"product/qualification/auths-recipe-qualification/src/commissioning/tests.rs","sha256":"5a226725c2ad7ce920d0bd62d427185e007f4d0949b0f0ec1260aa161d3114d0"},{"path":"product/qualification/auths-recipe-qualification/src/error.rs","sha256":"52d5cf720a1e4579008fdda90a3ac2c31f0b8db57985f121f65e54b4da2b7dd1"},{"path":"product/qualification/auths-recipe-qualification/src/evidence.rs","sha256":"ba45a7409d67a8af26ab811af306412014557477a101ab2a8eb0faf8f2bd4b91"},{"path":"product/qualification/auths-recipe-qualification/src/ids.rs","sha256":"e81a906d571497ab2da753e1532d4443706410e0b75fdd59a7d2d788c7aec403"},{"path":"product/qualification/auths-recipe-qualification/src/launch.rs","sha256":"41f2e2de90e1e7d6440a66eda3eb9bea8d5e0741bc232305a76a363ab5f813c1"},{"path":"product/qualification/auths-recipe-qualification/src/lib.rs","sha256":"7d26c5bfe9769daebf90c5c2280e0d75742e4cc70d0e608408e0665e3f516a2b"},{"path":"product/qualification/auths-recipe-qualification/src/model.rs","sha256":"3484eb0ec287b23d4682ade7b1b0f8d1335985b3fb180f06fc28716076957d5f"},{"path":"product/qualification/auths-recipe-qualification/src/release.rs","sha256":"ec478e53f70052e566aac7e15be2f9e1b1cd46837ac6990ae955fa864d311586"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/mod.rs","sha256":"fa23a962fd90331152eed5edbcdf271955f7aed79b8da1e065bfe69a20b487a9"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/schemas.rs","sha256":"c59feec2805621f341a90f81fc005e2c12f7a70f9d264fdeacccb2be4fe1c046"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/verification.rs","sha256":"6a6b5834c5dae10af1ba8939b2deae43b85db71544dc8f077ff63b7fe68ac8a8"},{"path":"product/qualification/auths-recipe-qualification/src/verify.rs","sha256":"2ec2784435d11e07295de77b2ee1b2c48b2fcf9609a00454c6e7374b621aed5c"},{"path":"product/receipts/auths-receipts/Cargo.toml","sha256":"6001fa1375899953aafcb07c23a6da0c8f57ea7ec08bb9c950b12a60a8cc6f0f"},{"path":"product/receipts/auths-receipts/src/disclosure.rs","sha256":"ba9ed439be0a320c8a01f5b6e9b51361c1a37e076947490d8e4a484ba6bb119c"},{"path":"product/receipts/auths-receipts/src/lib.rs","sha256":"547a57c4160256719cafb7d0ab972d9fc80b0da14fbbce4148c70c414070ff36"},{"path":"product/runtime/auths-connections/Cargo.toml","sha256":"babeb6e1dda3dfb66291713ce1e43dce5c349833d0b50ea4dccbf986030026b2"},{"path":"product/runtime/auths-connections/src/credential.rs","sha256":"82921413bb053f0f6c7931fbd4e6a86c8cc1d8c6b51debd9c2cef33a8d5b1c51"},{"path":"product/runtime/auths-connections/src/kernel.rs","sha256":"a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8"},{"path":"product/runtime/auths-connections/src/lib.rs","sha256":"79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22"},{"path":"product/runtime/auths-connections/src/model.rs","sha256":"de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77"},{"path":"product/runtime/auths-connections/src/registry.rs","sha256":"e57640e003e72ad3235c567c2bb944a262bd64e673f023b62ea091094cc7e946"},{"path":"product/runtime/auths-gateway-kernel/Cargo.toml","sha256":"34f864e67656af4ac7e5c7a347a23f01fc8ab31365b8e23c0ef474483b14a183"},{"path":"product/runtime/auths-gateway-kernel/src/construct.rs","sha256":"e9d65744bae273d65face4285e5d2da75c06a92ab48f7b8333d496604e31c63c"},{"path":"product/runtime/auths-gateway-kernel/src/lib.rs","sha256":"cfda6f8453426564c085475f183b6f790b438768a19668f1b65d33ba59dc8632"},{"path":"product/runtime/auths-gateway-kernel/src/order.rs","sha256":"e0045f877c4b7fe3860c291039853885064ddcdebba7c9b345ab65e81e646dda"},{"path":"product/runtime/auths-gateway-kernel/src/outcome.rs","sha256":"e9785b1afe70788c89b51b18655bcd5acff7b0c8e3d12fb79c6f05a202e67e6b"},{"path":"product/runtime/auths-gateway-kernel/src/ratio.rs","sha256":"7ace22264812e6fc1ef3a62afee402cf43494bb71ae0d3de219ad1b39d690bcb"},{"path":"product/runtime/auths-gateway-kernel/src/recovery.rs","sha256":"9f46dcd1685ab6e4d1ba04a3fc286a9f3afee8fb47829be1fbc670a7926a2dc6"},{"path":"product/runtime/auths-gateway-kernel/src/transition.rs","sha256":"cefb8f01d915880f6921f2501ff881ad94b9de61072c34d9cd19220992f97374"},{"path":"product/runtime/auths-gateway/Cargo.toml","sha256":"00b28be86921dcdc0ad90cce0c62c2961cafefe96ea6c2edf0e926c3d405ccad"},{"path":"product/runtime/auths-gateway/src/admin.rs","sha256":"0dee40a9fb67c5de10142fc37a7bbabdd8979fb0199fb26caf4bdb024e0a5a40"},{"path":"product/runtime/auths-gateway/src/app.rs","sha256":"6f80f63833ea0815bb44fbf3b0cc54624a08e9fb578b035819f2980dc04e8256"},{"path":"product/runtime/auths-gateway/src/audit.rs","sha256":"0edb2037eb7b5d6f13acfce85c54f62a82bf7fdd31bc7e626c4fec183cef61dd"},{"path":"product/runtime/auths-gateway/src/audit_tests.rs","sha256":"990969384a52d75bc2489d9d412a9e7dd814bca1c8f65c701d6205fae62a15d5"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway-harness.rs","sha256":"12b0c24d36b2e6a3be392d3c081a783b355fdd67dc5b54bacc0410e803116b8c"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway.rs","sha256":"24d4224f03c680ee1fc3f3441cca8707fe002ce2c78588e8c337f2f150ea2e44"},{"path":"product/runtime/auths-gateway/src/binding.rs","sha256":"663b0ce878319511aa7d05722ab4ab2fa9be18817884ffb2ee9f131ff1e382d1"},{"path":"product/runtime/auths-gateway/src/bounds.rs","sha256":"38251ad6f22f9d07ef9a219c79fa265ca36f1526eca5f147d7efa46b52ad609d"},{"path":"product/runtime/auths-gateway/src/bounds_aggregate_tests.rs","sha256":"ab34f227b7c8692ba1da88ccb32bb3687a66adf8353d8282fae905d4a88eb612"},{"path":"product/runtime/auths-gateway/src/bounds_tests.rs","sha256":"74136bc570da7b9338b5a1a1ed9d3fd892c55135160964f9d3ac0e2cf5741375"},{"path":"product/runtime/auths-gateway/src/commissioning_budget.rs","sha256":"fab29da3269438cc62330f3eab7b5bd4dc482b4db8af243aae47df5d3aa1deb8"},{"path":"product/runtime/auths-gateway/src/commissioning_budget/tests.rs","sha256":"ad182c391b70450582c6ca06e3dadc221409bb3cdbc3c7668dbfc7fbedf63505"},{"path":"product/runtime/auths-gateway/src/commissioning_floor.rs","sha256":"7fa6991c5ccd5ae1403be84b3da390323fab09f36e15ac01fd7a38ea350c6fdb"},{"path":"product/runtime/auths-gateway/src/commissioning_floor/tests.rs","sha256":"5f7868252dfccb787d26f63ea6d5c3701c72d52c0ff0bc656dd5895f8cbed551"},{"path":"product/runtime/auths-gateway/src/commissioning_session.rs","sha256":"24b48d5eaeaaa3c620e2dfc7ee1f9255fc4519a1eb404b8608cea7af6a910ee2"},{"path":"product/runtime/auths-gateway/src/commissioning_session/tests.rs","sha256":"531510bbd1bb0a7544c2bfd14f68b028f523bd4ed25dc4a68521fd0d8418a440"},{"path":"product/runtime/auths-gateway/src/connection.rs","sha256":"7b5d049c258a26ed1c93ecf860f51d051a8a65f9b93554af0b1ea93862398ec9"},{"path":"product/runtime/auths-gateway/src/credential_journal.rs","sha256":"7297fccaee5cd8622928e8e0a42bba50da7941970a6f682ecd300c41ee6509da"},{"path":"product/runtime/auths-gateway/src/echo_verify.rs","sha256":"6d453051665f823abd7354d5c50031d9524cf47d6092d2f09080ae814e3b9575"},{"path":"product/runtime/auths-gateway/src/engine.rs","sha256":"1abff20b98bc894c45bfc5c4414c81a99966d1ec95d924a5b0cd6f4c5626ca24"},{"path":"product/runtime/auths-gateway/src/execution_witness.rs","sha256":"e8b1a8e41d5e3fa309760067849d390ef065feeb46701a83391832645a2f000c"},{"path":"product/runtime/auths-gateway/src/fuzzing.rs","sha256":"ed3b0028487eb546a3b0a91d115aa8f18bcea324b61620bfe8e35a9e6ab18758"},{"path":"product/runtime/auths-gateway/src/generation_floor.rs","sha256":"fe1510ec96ce0f67e9a78edbfa94b33eb7df64c0ac4d0a67901124dcd0164777"},{"path":"product/runtime/auths-gateway/src/harness.rs","sha256":"c87e479f3eb281960f6c9c80d43c7560d7ccb654b0154ec823d3fcec4884ac05"},{"path":"product/runtime/auths-gateway/src/lib.rs","sha256":"fad95d031f88072dd024c78facf0bb0267562b1ac743ddd7219fce47e64024f0"},{"path":"product/runtime/auths-gateway/src/listener.rs","sha256":"aa08239bcbc1fcb55e8a212fbdf6a84f12985b0d436dcb51dc58b06e59e435f2"},{"path":"product/runtime/auths-gateway/src/observed_tests.rs","sha256":"a22be071695f89ca2578a4d82fd80d9cb82289213c9bdb8f0470f6b2dc3d9201"},{"path":"product/runtime/auths-gateway/src/observer.rs","sha256":"562ffcaea071c3856e0708dc2fe33516917e145d2438aabb75af0a2b6ba01046"},{"path":"product/runtime/auths-gateway/src/onboarding.rs","sha256":"0dfd7d67e7f02f18a28d1c86ca1b7751d7463f5efcdbe3825de0ad8cbccb3891"},{"path":"product/runtime/auths-gateway/src/operator.rs","sha256":"c3c36954a3e86723df035b47f43b85fc8ab3a6292983522b6258d5c6b4e6c4e4"},{"path":"product/runtime/auths-gateway/src/pending_vectors/attempts.rs","sha256":"47ef3c8cb1c5504d47ae9a0088705ce6715fe86bac1671a34a56fb38a64d0dd3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/bounds.rs","sha256":"e612217307e1da5b0eb5ee6582a7458bb064b8aa8a529fc6555b1b334127ab68"},{"path":"product/runtime/auths-gateway/src/pending_vectors/codes.rs","sha256":"e00670a5ef24eb856cc2c6dcda8e5a263842f55c76bb939c0c27bd9df37e5522"},{"path":"product/runtime/auths-gateway/src/pending_vectors/keys.rs","sha256":"f84c56f2ea9cb34b2b79c72d13fbf2c6585010ec1ed450af58a78c80c1ea1edd"},{"path":"product/runtime/auths-gateway/src/pending_vectors/mod.rs","sha256":"5de8340f0ef71a0b57a09e323fefe473d3160c6ae952b9ba46f714825fbacafc"},{"path":"product/runtime/auths-gateway/src/pending_vectors/outcomes.rs","sha256":"8ec07b9511b48913af36ac999d2aa0e82924289f6acb23ddaeb9f00f99815166"},{"path":"product/runtime/auths-gateway/src/pending_vectors/production.rs","sha256":"772d032e0a0d9c924fb6d6c188528db85a97e71c9e466ddc19eee277baf83614"},{"path":"product/runtime/auths-gateway/src/pending_vectors/recipes.rs","sha256":"51693208270231c25c3aef2a32151d5962114c71e86b88cb9df83181c7af83d9"},{"path":"product/runtime/auths-gateway/src/pre_entry.rs","sha256":"06ea78ca140468bfaba17d9ab04912ad68673954c3203c98fed28272ff2a00c0"},{"path":"product/runtime/auths-gateway/src/property_tests.rs","sha256":"939c081e2e154aaf10186754044bdd65608932c899b970a04a71d0afaa999a93"},{"path":"product/runtime/auths-gateway/src/qualification.rs","sha256":"c597c83de2b94f0374ae54e40a8b57c2a64ec6e254704dca32185f448a908aca"},{"path":"product/runtime/auths-gateway/src/qualification_simulation.rs","sha256":"4ee7cadfb5f46a92713c80f3e55f499cb074d04d8b21ea89d57762af38642bfa"},{"path":"product/runtime/auths-gateway/src/qualification_tests.rs","sha256":"a9178a2e58eea459d5e5dafc53a3999ea7c84dbbffefe6e5eb1f3d098827f028"},{"path":"product/runtime/auths-gateway/src/quorum_tests.rs","sha256":"a78380b019104d688c11a4410082c7e08ded3106aab099954c4f8a1b4ae0fd89"},{"path":"product/runtime/auths-gateway/src/readiness.rs","sha256":"911c3f11892f94641574375e2da4c671c802738f71082f12c39832331052d43d"},{"path":"product/runtime/auths-gateway/src/recipe.rs","sha256":"fecf9af67e7afc48d080e9f8f55f8ce28e49d0e08988717a27908bbda461d6b6"},{"path":"product/runtime/auths-gateway/src/recipe/lower.rs","sha256":"8088b8751ed831dbb48247af953c6290ac95e2a438ccd5bd65eff54be06a1fd1"},{"path":"product/runtime/auths-gateway/src/recipe/review.rs","sha256":"c3eb7d9fdd98dacf52750b14b67ad7b7faaecbbdeafff1e0b049f67d0a2d0139"},{"path":"product/runtime/auths-gateway/src/recipe/runtime.rs","sha256":"c286f0d15f974402822c0810d8e97f98411dc1c557755cc23e540d85e2bb42d9"},{"path":"product/runtime/auths-gateway/src/recipe/source.rs","sha256":"1af50298fb1461e1b24cbdf560d43124d6b1c4c529586c911b1c4797214a69ff"},{"path":"product/runtime/auths-gateway/src/recipe/tests.rs","sha256":"aac551a2481bbc60864c64079bc667dcb232e45a0f41a04073ed84ab5dbe1fce"},{"path":"product/runtime/auths-gateway/src/recipe/validate.rs","sha256":"3711b17605cb7b0d639bc1b180449231f5882a306cab20e2c7782155cc63b0d4"},{"path":"product/runtime/auths-gateway/src/scenario_tests.rs","sha256":"a8ea1e3a7bf6b0274455bd790ace3ffb9c8716609cde92248920945c61634685"},{"path":"product/runtime/auths-gateway/src/separation.rs","sha256":"be9306848ca5d801767cf6aa14247c8618312ef0e202f00ce0c24c4844491061"},{"path":"product/runtime/auths-gateway/src/simulation_attestation.rs","sha256":"88705e5d45415f760f1e3c3a065c35c48f4f4065bf7b3feb7882246983814d6f"},{"path":"product/runtime/auths-gateway/src/store.rs","sha256":"884bcad4d70d53e12eae9c8517f6ecd0643068ee0be0370015119d04d6cc2516"},{"path":"product/runtime/auths-gateway/src/store_testkit.rs","sha256":"88d82fee42f1b8ef521e8deef0216e938ebeaad822eb2f5020e70b89d145ea70"},{"path":"product/runtime/auths-gateway/src/submit.rs","sha256":"fe2eacb5ad8152eeecbd232c47a356fc72db0098e34fda99532bdf6ef0cf895c"},{"path":"product/runtime/auths-gateway/src/support.rs","sha256":"9fd979029793a22b15d9776a7fc172476fd7c126a80d4080c65d720845becbcb"},{"path":"product/runtime/auths-gateway/src/transport.rs","sha256":"978fc9fb34a33b3db265b5d1c3ce11696a5b9f08529e46dd2a1e7bb62afb9220"},{"path":"product/runtime/auths-kernel-runtime/Cargo.toml","sha256":"926bcd0053e5edd703be8f0027ad009e2982db013c8174c1366edbf38b48087d"},{"path":"product/runtime/auths-kernel-runtime/src/lib.rs","sha256":"7108faae9ca4bc32dc093ddaf885ac8f74f3c9b8d317b7c7d0ed00d1d0ab5972"},{"path":"product/runtime/auths-lifecycle/Cargo.toml","sha256":"c5053c705f8d5554b44e432fe75287a2faf11d644e5a2552e45ad6cd94176af5"},{"path":"product/runtime/auths-lifecycle/src/codec.rs","sha256":"51c4b746749150e8bfcd8ff972b3f6c1ef40bec15583448ec1b471d9ad737dc0"},{"path":"product/runtime/auths-lifecycle/src/digest.rs","sha256":"55282cd7d8aba37713c2dcb5357c9877819edb72a30eadefb860d28d7d3a3eb7"},{"path":"product/runtime/auths-lifecycle/src/identifier.rs","sha256":"31620e8c16de68d3d2d3b84d6353c1a5b9d4151d8247f91fa389b906a8e660f1"},{"path":"product/runtime/auths-lifecycle/src/kernel.rs","sha256":"2abb8c094b36d35b364e74d78091d14c5d6f3d1eb6552cca3b5538dbd017ce23"},{"path":"product/runtime/auths-lifecycle/src/lib.rs","sha256":"afe5a345cd309b5a4f08ffba3170a6d7f16ff914892b3f2006d5208ed24ec736"},{"path":"product/runtime/auths-lifecycle/src/model.rs","sha256":"1af12bbeeeaa65ec02ddcebd7d2c8c92ec1e339fa40ae85b45ab9b01a722a4fa"},{"path":"product/runtime/auths-lifecycle/src/operation.rs","sha256":"78e6d05fcf5d7ea4f148032a3fa26fdfcab77eb346019effe927b08e0d64d732"},{"path":"product/runtime/auths-lifecycle/src/registry.rs","sha256":"53495fe6f7a77422593a41623e28716f1c140dcc1e00f87f6b0ffbfb93a5ef90"},{"path":"product/runtime/auths-lifecycle/src/sealed.rs","sha256":"2e0c03b5813c926c159598bb7890d1523825edbe57cd687d42a5dfb3374a0c19"},{"path":"product/runtime/auths-lifecycle/src/test_support.rs","sha256":"221d9a5c5ef8e1f9f8fd66927484eaf813571d0568470278ecd8fa08a5eec8cd"},{"path":"product/runtime/auths-lifecycle/src/transition.rs","sha256":"011805a28efdd541f44ccea54dd0e34a1e58f4004447ee58013703b4fb6b2822"},{"path":"product/runtime/auths-runtime/Cargo.toml","sha256":"dd29d80a8b4bb56c869f036a6c9998f6e6d1c0383ac5dc03fa42b24abe2a7ff7"},{"path":"product/runtime/auths-runtime/src/lib.rs","sha256":"132ca03d58c14905d3a822a4972f42a22a5ad33a45f2ba9ca44f3a57d810b4b0"},{"path":"product/runtime/auths-runtime/src/production.rs","sha256":"fd4eff4270c571c10fcff6cf27df28961ebf074de8a1a028f500fda1ca376820"},{"path":"product/sdk/auths-approval-quorum/Cargo.toml","sha256":"df904971fca87a24194c5816738a331588fe8f164acb5d70839a35dca5f57114"},{"path":"product/sdk/auths-approval-quorum/src/lib.rs","sha256":"72e4086088a1c0912e4e1a9e980f26a5c280bf5ab16ea39c9f0f58d5096ac2ce"},{"path":"product/sdk/auths-approval-quorum/src/remote.rs","sha256":"9fa029c7c63003adf260f8aec55160c545681c60c1bace0d934e7525862aac7b"},{"path":"product/sdk/auths-approval-quorum/src/remote_tests.rs","sha256":"8a09ce17cfee82a035a74edd535f3ebeb3db0e078784740d3997b17dbdb10197"},{"path":"product/sdk/auths-approval-quorum/src/tests.rs","sha256":"0acbf12be3e497dcc6c2d8f29c9af3b1a7ed8e11b75f6399570d4f217a785060"},{"path":"product/stores/auths-stores/Cargo.toml","sha256":"a32c4b76d17b264be5d40d24497ff237e1ed87822e8bab86229b3db93106dbe3"},{"path":"product/stores/auths-stores/src/gateway_attempt.rs","sha256":"218841602d3d9b23b44625f50e5b54cf275ccedc2d5c89f02d2482b8524472af"},{"path":"product/stores/auths-stores/src/lib.rs","sha256":"e721262edf8a9ab5568ddc27639176312d4a366203b5f73e2d7c11fde2c554e9"},{"path":"product/stores/auths-stores/src/lifecycle.rs","sha256":"3f2cecfda13fdcd7c4a944518646bcc8abd1237f900c0332d5822281f8f9f1cd"}],"schema":"auths.gateway-semantic-closure/1"} \ No newline at end of file diff --git a/product/runtime/auths-gateway/src/admin.rs b/product/runtime/auths-gateway/src/admin.rs index 55f01a0eb..bb67d56e2 100644 --- a/product/runtime/auths-gateway/src/admin.rs +++ b/product/runtime/auths-gateway/src/admin.rs @@ -35,6 +35,8 @@ pub enum AdminRequestCommand { }, /// Report connection state. Status {}, + /// Read process-local custody and transport measurements; grants no authority. + ExecutionWitness {}, /// Read the qualification inputs the operator placed on this host again /// and report the resulting state. QualificationReload {}, @@ -86,7 +88,12 @@ mod tests { parse("\"command\":\"qualification-reload\""), Ok(AdminRequestCommand::QualificationReload {}) ); + assert_eq!( + parse("\"command\":\"execution-witness\""), + Ok(AdminRequestCommand::ExecutionWitness {}) + ); for refused in [ + "\"command\":\"execution-witness\",\"reset\":true", "\"command\":\"qualification-reload\",\"state\":\"qualified\"", "\"command\":\"qualification-reload\",\"policy\":\"optional\"", "\"command\":\"qualification-import\"", diff --git a/product/runtime/auths-gateway/src/bin/auths-gateway.rs b/product/runtime/auths-gateway/src/bin/auths-gateway.rs index ef7dd3179..a03f7601d 100644 --- a/product/runtime/auths-gateway/src/bin/auths-gateway.rs +++ b/product/runtime/auths-gateway/src/bin/auths-gateway.rs @@ -426,6 +426,13 @@ mod unix { #[arg(long)] admin_socket: Option, }, + /// Read actual custody/HTTP boundary counts through the private socket. + ExecutionWitness { + #[arg(long)] + state_dir: PathBuf, + #[arg(long)] + admin_socket: Option, + }, /// Ask the private operator socket for one read-only re-observation /// of a stored attempt. Reobserve { @@ -952,6 +959,8 @@ mod unix { #[serde(skip_serializing_if = "Option::is_none")] status: Option, #[serde(skip_serializing_if = "Option::is_none")] + execution_witness: Option, + #[serde(skip_serializing_if = "Option::is_none")] result: Option, /// The reference commitment of a prepared successor. It names the /// stored secret without revealing it or where it is kept. @@ -991,6 +1000,7 @@ mod unix { drained: None, in_flight: None, status: None, + execution_witness: None, result: None, commitment: None, qualification: None, @@ -2079,6 +2089,7 @@ mod unix { RotatePrepare(Zeroizing>), RotateCommit([u8; 32]), Status, + ExecutionWitness, Reobserve(String), QualificationReload, } @@ -2098,6 +2109,7 @@ mod unix { AdminRequestCommand::Enable {} => Ok(AdminCommand::Enable), AdminRequestCommand::Revoke {} => Ok(AdminCommand::Revoke), AdminRequestCommand::Status {} => Ok(AdminCommand::Status), + AdminRequestCommand::ExecutionWitness {} => Ok(AdminCommand::ExecutionWitness), AdminRequestCommand::QualificationReload {} => Ok(AdminCommand::QualificationReload), AdminRequestCommand::Reobserve { operation_id } => { Ok(AdminCommand::Reobserve(operation_id)) @@ -2183,6 +2195,11 @@ mod unix { }, Err(code) => AdminResponse::refused(code), }, + Ok(AdminCommand::ExecutionWitness) => AdminResponse { + ok: true, + execution_witness: Some(engine.execution_witness()), + ..AdminResponse::refused("gateway.admin.execution-witness") + }, Ok(AdminCommand::QualificationReload) => { let reloading = Arc::clone(&engine); let directory = Arc::clone(&state_dir); @@ -2708,10 +2725,17 @@ mod unix { Some((proof, action)) => { let proof = read_bounded(proof, 4 * 1024 * 1024)?; let action = read_bounded(action, 64 * 1024)?; + let before = engine.execution_witness(); let result = session.submit(&proof, &action).await; + let measured = serde_json::json!({ + "schema": "auths.gateway-commissioning-execution/1", + "result": result, + "before": before, + "after": engine.execution_witness(), + }); println!( "{}", - serde_json::to_string(&result) + serde_json::to_string(&measured) .map_err(|_| "gateway.submit.invalid-response")? ); } @@ -3624,6 +3648,14 @@ mod unix { let command = serde_json::json!({"command": "revoke"}); admin_command(&state_dir, &admin_socket, command, None).await } + Command::ExecutionWitness { + state_dir, + admin_socket, + } => { + let admin_socket = admin_socket_path(&state_dir, admin_socket); + let command = serde_json::json!({"command": "execution-witness"}); + admin_command(&state_dir, &admin_socket, command, None).await + } Command::Status { state_dir, admin_socket, diff --git a/product/runtime/auths-gateway/src/commissioning_session/tests.rs b/product/runtime/auths-gateway/src/commissioning_session/tests.rs index 4e2a3127c..f440adb96 100644 --- a/product/runtime/auths-gateway/src/commissioning_session/tests.rs +++ b/product/runtime/auths-gateway/src/commissioning_session/tests.rs @@ -261,6 +261,7 @@ async fn ordinary_submission_cannot_select_commissioning_authority() { ); assert!(ordinary.lease().await.is_none()); assert_eq!(setup.leases(), 0); + assert_eq!(setup.engine().execution_witness().credential_lease_calls, 0); assert_eq!( session .floor @@ -390,3 +391,44 @@ async fn changed_resources_run_operator_or_context_cannot_open_a_session() { assert_eq!(setup.leases(), 0); } } + +#[tokio::test] +async fn execution_witness_measures_custody_calls_even_when_a_charged_call_fails() { + let setup = Setup::new().await; + let before = setup.engine().execution_witness(); + let session = setup + .engine() + .commissioning_session(&setup.inputs()) + .expect("operator"); + session.initialize_budget().await.expect("registered"); + let commissioned = io(&setup, Some(&session)); + commissioned.verify(NOW).expect("native exact actor"); + commissioned + .prepare() + .await + .expect("prepared with custody present"); + let record = commissioned.prepared.get().expect("entry").loaded.record(); + setup + .engine() + .credentials + .delete_connection(record.connection_id(), &[record.credential_generation()]) + .await + .expect("remove custody after preparation"); + assert!(commissioned.lease().await.is_none()); + assert_eq!(setup.leases(), 1, "the actual failing store call was made"); + let after = setup.engine().execution_witness(); + assert_eq!(after.scope, before.scope); + assert_eq!( + after.credential_lease_calls - before.credential_lease_calls, + 1 + ); + assert_eq!(after.write_transport_entries, 0); + assert_eq!(after.read_transport_entries, 0); + assert!( + commissioned.lease().await.is_none(), + "spent capacity cannot retry" + ); + assert_eq!(setup.engine().execution_witness(), after); + let restarted = Setup::new().await; + assert_ne!(restarted.engine().execution_witness().scope, after.scope); +} diff --git a/product/runtime/auths-gateway/src/engine.rs b/product/runtime/auths-gateway/src/engine.rs index d2f547bfc..50552c275 100644 --- a/product/runtime/auths-gateway/src/engine.rs +++ b/product/runtime/auths-gateway/src/engine.rs @@ -70,6 +70,9 @@ pub enum GatewayEngineConfigurationError { /// The installed recipe differs from the operator-approved digest. #[error("gateway recipe approval digest mismatch")] UnapprovedRecipe, + /// An independent process measurement scope could not be allocated. + #[error("gateway execution witness unavailable")] + WitnessUnavailable, } /// Closed, secret-free application result. A recorded response or matching @@ -331,6 +334,7 @@ pub struct GatewayEngine { qualification: Arc, attempts: GatewayAttempts, in_flight: AtomicU64, + execution_witness: Arc, /// The gateway clock of the last successful slot sweep; zero before one. last_sweep: AtomicU64, drain_limit: Duration, @@ -405,6 +409,10 @@ impl GatewayEngine { qualification: Arc::new(crate::QualificationGate::unconfigured()), attempts, in_flight: AtomicU64::new(0), + execution_witness: Arc::new( + crate::execution_witness::ExecutionWitness::new() + .map_err(|_| GatewayEngineConfigurationError::WitnessUnavailable)?, + ), last_sweep: AtomicU64::new(0), drain_limit: DRAIN_LIMIT, retirement_delay: crate::CredentialRetirementDelay::FIXED.as_duration(), @@ -969,6 +977,14 @@ impl GatewayEngine { deleted.map(|()| outcome) } + /// Reads process-local execution counters without accessing custody, the + /// store, the network, or qualification authority. A snapshot is diagnostic + /// evidence only; it never confirms a provider effect. + #[must_use] + pub fn execution_witness(&self) -> crate::GatewayExecutionWitness { + self.execution_witness.snapshot() + } + /// Reads the shared record's state and this process's counts. Nothing is /// changed. /// @@ -1182,11 +1198,17 @@ impl GatewayEngine { descriptor.credential(), port, ) - .map(|transport| PreparedEntry { loaded, transport }) + .map(|transport| PreparedEntry { + loaded, + transport: transport.with_witness(Arc::clone(&self.execution_witness)), + }) .map_err(|_| "gateway.transport.preparation"); } GatewayHttpTransport::prepare(&self.recipe, descriptor.credential()) - .map(|transport| PreparedEntry { loaded, transport }) + .map(|transport| PreparedEntry { + loaded, + transport: transport.with_witness(Arc::clone(&self.execution_witness)), + }) .map_err(|_| "gateway.transport.preparation") } @@ -1206,6 +1228,7 @@ impl GatewayEngine { // Time moved since the entry was prepared, so the gate is asked // again: nothing reaches the credential store unqualified. self.qualification.check().map_err(|_| ())?; + self.execution_witness.lease(); self.credentials .lease_secret( &prepared.loaded.record().credential_binding(), @@ -1421,6 +1444,7 @@ impl SubmitIo for EngineIo<'_> { let _ = self.commissioning_refusal.set(code); return None; } + self.engine.execution_witness.lease(); return self .engine .credentials diff --git a/product/runtime/auths-gateway/src/execution_witness.rs b/product/runtime/auths-gateway/src/execution_witness.rs new file mode 100644 index 000000000..35be49b0c --- /dev/null +++ b/product/runtime/auths-gateway/src/execution_witness.rs @@ -0,0 +1,78 @@ +//! Secret-free measurements at custody and HTTP execution boundaries. +//! +//! These are process-local diagnostics, never authority or proof of a remote +//! effect. A runner must use snapshots from the same scope, wait for its calls +//! to finish, and independently read back every claimed provider effect. + +use serde::{Deserialize, Serialize}; +use std::sync::atomic::{AtomicU64, Ordering}; + +/// One process-local execution measurement, read through the private operator +/// channel. Counts include attempted calls that subsequently fail. +#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] +#[serde(deny_unknown_fields)] +pub struct GatewayExecutionWitness { + /// Exactly `auths.gateway-execution-witness/1`. + pub schema: String, + /// Fresh random scope for this engine instance. Different scopes must + /// never be subtracted, including after a process restart. + pub scope: String, + /// Actual execution calls to the credential store's lease method. + pub credential_lease_calls: u64, + /// Closed write requests passed to the HTTP client's execution method. + /// This includes ambiguous failures, and does not prove remote receipt. + pub write_transport_entries: u64, + /// Read requests passed to the HTTP client's execution method, including + /// credential probes. These are not provider writes. + pub read_transport_entries: u64, +} + +pub(crate) struct ExecutionWitness { + scope: String, + leases: AtomicU64, + writes: AtomicU64, + reads: AtomicU64, +} + +impl ExecutionWitness { + pub(crate) fn new() -> Result { + let mut scope = [0; 16]; + getrandom::fill(&mut scope)?; + Ok(Self { + scope: hex::encode(scope), + leases: AtomicU64::new(0), + writes: AtomicU64::new(0), + reads: AtomicU64::new(0), + }) + } + + pub(crate) fn lease(&self) { + increment(&self.leases); + } + + pub(crate) fn write(&self) { + increment(&self.writes); + } + + pub(crate) fn read(&self) { + increment(&self.reads); + } + + pub(crate) fn snapshot(&self) -> GatewayExecutionWitness { + GatewayExecutionWitness { + schema: "auths.gateway-execution-witness/1".to_owned(), + scope: self.scope.clone(), + credential_lease_calls: self.leases.load(Ordering::SeqCst), + write_transport_entries: self.writes.load(Ordering::SeqCst), + read_transport_entries: self.reads.load(Ordering::SeqCst), + } + } +} + +fn increment(counter: &AtomicU64) { + // Saturation is explicit: an evidence consumer must refuse saturated + // snapshots. Wrapping could make a later snapshot appear to precede one. + let _ = counter.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |value| { + Some(value.saturating_add(1)) + }); +} diff --git a/product/runtime/auths-gateway/src/lib.rs b/product/runtime/auths-gateway/src/lib.rs index 1b397fae6..bba869b55 100644 --- a/product/runtime/auths-gateway/src/lib.rs +++ b/product/runtime/auths-gateway/src/lib.rs @@ -24,6 +24,8 @@ mod connection; mod credential_journal; mod echo_verify; mod engine; +mod execution_witness; +pub use execution_witness::GatewayExecutionWitness; #[cfg(feature = "fuzzing")] pub mod fuzzing; mod generation_floor; diff --git a/product/runtime/auths-gateway/src/semantic_closure.rs b/product/runtime/auths-gateway/src/semantic_closure.rs index a323ab1fb..544ddb306 100644 --- a/product/runtime/auths-gateway/src/semantic_closure.rs +++ b/product/runtime/auths-gateway/src/semantic_closure.rs @@ -10,7 +10,7 @@ /// SHA-256 of the schema, a NUL byte, and `semantic-closure.json`. /// Regenerate through `semantic_closure_is_current` with `AUTHS_UPDATE_FIXTURES=1`. pub const GATEWAY_SEMANTIC_CLOSURE_SHA256: &str = - "f4341fa858a06ea4219b9098ae9d143a1653907095d028be66b9efcfb2c9db28"; + "a136eb511dba4f9cd37fbfe75e7ca6a58d179dc24ff06d4198778ec875e41cf7"; #[cfg(test)] mod tests { diff --git a/product/runtime/auths-gateway/src/transport.rs b/product/runtime/auths-gateway/src/transport.rs index f87aeef09..9ce6567af 100644 --- a/product/runtime/auths-gateway/src/transport.rs +++ b/product/runtime/auths-gateway/src/transport.rs @@ -179,9 +179,18 @@ pub(crate) struct GatewayHttpTransport { requirement: CredentialRequirement, /// Version headers every response must echo with these values. required_versions: Vec<(String, String)>, + witness: Option>, } impl GatewayHttpTransport { + pub(crate) fn with_witness( + mut self, + witness: std::sync::Arc, + ) -> Self { + self.witness = Some(witness); + self + } + /// Resolves and pins a public IPv4 address before claim or secret access. pub(crate) fn prepare( recipe: &CompiledRecipe, @@ -221,6 +230,7 @@ impl GatewayHttpTransport { target_origin: origin.to_owned(), requirement: connection_requirement.clone(), required_versions: recipe.required_response_versions(), + witness: None, }) } @@ -252,6 +262,7 @@ impl GatewayHttpTransport { target_origin: format!("http://{}:{port}", Ipv4Addr::LOCALHOST), requirement: connection_requirement.clone(), required_versions: recipe.required_response_versions(), + witness: None, }) } @@ -292,6 +303,9 @@ impl GatewayHttpTransport { .body(request.body().to_vec()) .build() .map_err(|_| GatewayTransportError::NotEntered)?; + if let Some(witness) = &self.witness { + witness.write(); + } let mut response = match self.client.execute(outbound).await { Ok(response) => response, Err(_) => return Ok(WriteTransportOutcome::Unknown), @@ -358,6 +372,9 @@ impl GatewayHttpTransport { ); } let outbound = outbound.build().ok()?; + if let Some(witness) = &self.witness { + witness.read(); + } let mut response = self.client.execute(outbound).await.ok()?; let status = response.status().as_u16(); let version_ok = self.versions_echoed(response.headers()); @@ -396,6 +413,7 @@ impl GatewayHttpTransport { target_origin: format!("http://{}:{port}", Ipv4Addr::LOCALHOST), requirement: review.credential().clone(), required_versions: recipe.required_response_versions(), + witness: None, } } @@ -635,7 +653,25 @@ mod tests { target_origin: format!("http://{}:{port}", Ipv4Addr::LOCALHOST), requirement: recipe.review().credential().clone(), required_versions: Vec::new(), + witness: None, }; + let witness = std::sync::Arc::new( + crate::execution_witness::ExecutionWitness::new().expect("scope"), + ); + let transport = transport.with_witness(std::sync::Arc::clone(&witness)); + assert!( + transport + .read( + reqwest::Method::GET, + "https://unapproved.example/", + &[], + 1024, + b"synthetic-transport-fixture", + ) + .await + .is_none() + ); + assert_eq!(witness.snapshot().read_transport_entries, 0); assert!(matches!( transport.write(&request, &lease).await, Ok(WriteTransportOutcome::ResponseRecorded { status: 200, .. }) @@ -655,6 +691,13 @@ mod tests { .and_then(|response| response.usable_body().map(<[u8]>::to_vec)) .is_some() ); + let measured = witness.snapshot(); + assert_eq!(measured.write_transport_entries, 1); + assert_eq!(measured.read_transport_entries, 1); + assert_eq!( + measured.credential_lease_calls, 0, + "transport never calls custody" + ); let heads = provider.await.expect("provider"); assert!(heads[0].starts_with("patch /v0/"), "{}", heads[0]); assert!(heads[1].starts_with("get /v0/"), "{}", heads[1]); diff --git a/qualification/README.md b/qualification/README.md index c85c71854..79487c3cf 100644 --- a/qualification/README.md +++ b/qualification/README.md @@ -230,3 +230,20 @@ That phase must show a confirmed effect from the installed ordinary client; a refusal cannot satisfy it. Only that phase can contribute production doctor evidence to a stable launch projection. A permit or an initial record alone never establishes stable readiness. + +### Measured execution boundaries + +The private `auths-gateway execution-witness` command reads process-local +`auths.gateway-execution-witness/1` counters without consulting custody, the +store or the provider. The application channel cannot request or reset them. +Subtract snapshots only with the same random scope, after all measured calls +complete; reject decreasing or saturated counters. Aggregate each separately +scoped host for a two-instance race. Restart establishes a fresh scope. + +`commissioning-submit` returns `auths.gateway-commissioning-execution/1` with +its result and before/after snapshots from its own short-lived engine. A +credential lease count is an actual store call, including a failing call; +a write entry is the HTTP client's execution boundary, including ambiguity. +Neither is a claim that a provider received or performed a mutation. Reads, +including credential probes, are counted separately. First qualification must +still independently read back the reviewed disposable resource. diff --git a/release/semantic-freeze-versions.toml b/release/semantic-freeze-versions.toml index 66f47a9d3..c5decd70d 100644 --- a/release/semantic-freeze-versions.toml +++ b/release/semantic-freeze-versions.toml @@ -1,4 +1,4 @@ -freeze_version = 375 +freeze_version = 376 # Semantic identity counters live outside the xtask source tree deliberately. # The formal source closure binds xtask's executable code, while the semantic @@ -45,7 +45,7 @@ freeze_version = 375 "auths.frozen-bytes/product/integrations/auths-stripe/fixtures/subscription-create/v1/manifest.sha256.json" = 1 "auths.frozen-bytes/product/integrations/auths-stripe/fixtures/subscription-modify/v1/manifest.sha256.json" = 1 "auths.frozen-bytes/product/integrations/auths-stripe/fixtures/v1/manifest.sha256.json" = 1 -"auths.identity.protocol" = 128 +"auths.identity.protocol" = 129 "auths.modular-components" = 20 "auths.portable-abi-bindings" = 121 "auths.product.bounded-domains" = 19 @@ -60,11 +60,11 @@ freeze_version = 375 "auths.product.mcp-closed-execution" = 31 "auths.product.mechanism-profile-conformance" = 12 "auths.product.operations" = 5 -"auths.product.public-sdk-contract" = 125 +"auths.product.public-sdk-contract" = 126 "auths.product.receipts" = 13 "auths.product.release-assurance" = 7 "auths.product.simplified-waist" = 19 "auths.product.vocabulary" = 24 "auths.release.benchmark-contract" = 1 "auths.release.evolution-contract" = 79 -"auths.release.public-surface" = 375 +"auths.release.public-surface" = 376 diff --git a/release/semantic-freeze.json b/release/semantic-freeze.json index 2836a1b71..6abe4635f 100644 --- a/release/semantic-freeze.json +++ b/release/semantic-freeze.json @@ -1,6 +1,6 @@ { "schema": "auths.semantic-freeze/1", - "freezeVersion": 375, + "freezeVersion": 376, "publicSurface": { "rustRoots": [ "auths", @@ -550,7 +550,7 @@ }, { "id": "auths.identity.protocol", - "version": 128, + "version": 129, "classification": "frozen-meaning", "categories": [ "identity-protocol-versions", @@ -573,7 +573,7 @@ "core/fixtures/identity/v1/vectors.json", "core/spec/identity/v1" ], - "sha256": "a3bf2b99da3b9b85fc1dc0e860af199821fd28b9d30cb809753bf14173eedab2" + "sha256": "4eeec6390c1fc6e85b7f76279dd702ae301ac5f9e00bd7a0b5f062b491bc0ef0" }, { "id": "auths.modular-components", @@ -871,7 +871,7 @@ }, { "id": "auths.product.public-sdk-contract", - "version": 125, + "version": 126, "classification": "frozen-meaning", "categories": [ "rust-sdk-contract", @@ -889,7 +889,7 @@ "product/runtime/auths-runtime/src", "product/sdk/auths-sdk/src" ], - "sha256": "e2df99fb1455a4f7f5a89c1592ebb22b1f4c09d44e8e93e01c6b7788d62731f3" + "sha256": "576e0cabf2f50698660ffaf92a8a47e35d4c8ff935b6484f9d0953a3c0d862d9" }, { "id": "auths.product.receipts", @@ -1011,7 +1011,7 @@ }, { "id": "auths.release.public-surface", - "version": 375, + "version": 376, "classification": "release-metadata", "categories": [ "package-names", @@ -1104,7 +1104,7 @@ "xtask/src/release_launch.rs", "xtask/src/semantic_freeze.rs" ], - "sha256": "e9d4c908e151be7377d2756c32893fcb2dce5777076f5d971e9e1d060b558a6c" + "sha256": "ba482c91283ddab5b0f4ba89a8bbd4c76d7decde5206ae139ebd18f747c7488b" } ] } From 3f65fdf76a1a5bb02fa7e2798f82bf19a2650686 Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 05:01:52 +0100 Subject: [PATCH 060/108] Bind fresh qualification witnesses to reviewed subjects and retain measured traces --- compliance.toml | 2 + ...0014-stripe-refund-recipe-qualification.md | 2 +- ...able-record-update-recipe-qualification.md | 2 +- ...NDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md | 2 +- ...gateway-polish-and-recipe-qualification.md | 2 +- .../src/bin/qualification_runner/mod.rs | 36 ++++- .../src/execution.rs | 105 ++++++++++++- .../tests/common/mod.rs | 4 +- .../tests/execution.rs | 142 +++++++++++++++++- qualification/README.md | 24 ++- qualification/reference/README.md | 14 ++ qualification/reference/fresh_evidence.py | 72 +++++++++ qualification/reference/measure.py | 44 ++++++ .../reference/tests/test_reference.py | 52 +++++++ release/semantic-freeze-versions.toml | 8 +- release/semantic-freeze.json | 14 +- 16 files changed, 501 insertions(+), 24 deletions(-) create mode 100644 qualification/reference/fresh_evidence.py create mode 100644 qualification/reference/measure.py diff --git a/compliance.toml b/compliance.toml index 1919e3f55..890ac6c2d 100644 --- a/compliance.toml +++ b/compliance.toml @@ -1228,6 +1228,8 @@ proof-author-or-assembler = [ "product/qualification/auths-recipe-qualification-issuance/tests/execution.rs#every_stage_executes_its_operations_and_a_missing_runner_refuses", "product/qualification/auths-recipe-qualification-issuance/tests/execution.rs#production_readiness_requires_a_read_only_live_probe_on_a_production_target", "product/qualification/auths-recipe-qualification-issuance/tests/execution.rs#commissioning_client_refusal_cannot_replace_an_ordinary_installed_effect", + "product/qualification/auths-recipe-qualification-issuance/tests/execution.rs#fresh_evidence_is_closed_to_the_reviewed_subject_and_exact_candidate_digest", + "product/qualification/auths-recipe-qualification-issuance/tests/execution.rs#a_dynamic_doctor_witness_must_match_the_actual_production_tuple", "product/qualification/auths-recipe-qualification-issuance/tests/execution.rs#replay_can_complete_an_unresolved_read_back_but_never_write_or_reacquire_after_observation", "product/qualification/auths-recipe-qualification-issuance/tests/execution.rs#observed_faults_and_changed_candidates_produce_no_passing_case", "product/qualification/auths-recipe-qualification-issuance/tests/execution.rs#differential_compares_the_actual_oracle_and_gateway_commitments", diff --git a/docs/adr/0014-stripe-refund-recipe-qualification.md b/docs/adr/0014-stripe-refund-recipe-qualification.md index ab1f11bc5..9a6713e53 100644 --- a/docs/adr/0014-stripe-refund-recipe-qualification.md +++ b/docs/adr/0014-stripe-refund-recipe-qualification.md @@ -63,7 +63,7 @@ the gateway receives only the restricted test key. The maintained platform profile/recipe are accompanied by gateway `attempt-scenarios-v3.json`, `bounds-aggregate.json`, `outcome-v2.json` and `hostile-recipes-v2.json`. They must be expanded into the family-owned -`auths.qualification-corpus/2` with executable coverage of every mandatory wall +`auths.qualification-corpus/3` with executable coverage of every mandatory wall scenario; they are not the missing protected family corpus. The live corpus must additionally exercise every declared capability, provider diff --git a/docs/adr/0015-airtable-record-update-recipe-qualification.md b/docs/adr/0015-airtable-record-update-recipe-qualification.md index 051b17b32..8449f4972 100644 --- a/docs/adr/0015-airtable-record-update-recipe-qualification.md +++ b/docs/adr/0015-airtable-record-update-recipe-qualification.md @@ -50,7 +50,7 @@ those capabilities on every lease. The maintained offline seeds are `airtable/vectors.json`, the profile lock and gateway hostile, attempt and outcome corpora. Publish a family-owned executable -`auths.qualification-corpus/2` covering the complete evidence wall, including +`auths.qualification-corpus/3` covering the complete evidence wall, including an oracle-accepted update, all refused mappings, real application isolation and credential drift. These seeds alone are not the missing protected family corpus. diff --git a/docs/research/INDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md b/docs/research/INDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md index e072a1ea1..90cff82ea 100644 --- a/docs/research/INDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md +++ b/docs/research/INDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md @@ -10,7 +10,7 @@ audit or real-user trial is claimed. | Disposable identifiers and exact actions needed independent expansion. | Closed Stripe/Airtable resources, reconstruction of the whole reviewed recipe/lock, native proof review and independent request oracles. Implemented release-only expansion; protected family setup still needs integration. | | An installed ordinary client could not succeed before first qualification. | Separate commissioning and ordinary live phases. First records have a two-hour maximum and explicit exclusions; ordinary live evidence requires a confirmed installed-client effect. Implemented runner/assembly controls, protected sequencing still needs integration. | | The runner prohibited a legitimate read-only recovery lease on replay. | One lease may finish an unresolved entered attempt's observation. A replay cannot write again or reacquire after observation. Implemented with regression cases. | -| A live provider response's exact digest cannot be predicted before creating the effect. | Next: a closed independent fresh-evidence witness, compared with the candidate evidence digest. No wildcard, copying candidate output into expectations or fabricated response is acceptable. | +| A live provider response's exact digest cannot be predicted before creating the effect. | Implemented: corpus schema 3 declares a closed evidence source and reviewed subject; fresh provider-response/doctor witnesses must match the candidate digest and actual tuple. All remaining facts stay exact. Closed step observations are retained for the trace scan. | | The production CLI does not expose independently counted custody/transport boundary observations. | Implemented: private process-scoped counters at the actual custody lease call and HTTP execution boundaries, including failures. Commissioning commands return before/after snapshots; ordinary clients cannot reset them. Remote effects still require separate fresh read-back. | | Existing AWS roles trust the `gateway-custody-live` environment, while the qualification template names separate family environments. | Next: use an explicitly reviewed protected-environment arrangement that matches the actual OIDC trust, with required reviewer, main-only policy and family-specific credential injection. No role trust or gate is weakened. | | Main-only protected code must be deployed before the first protected qualification run. | A bounded prerequisite rollout of the completed runner is needed before collecting evidence. Epic acceptance stays open until actual runs, signed closure and CI are complete. | diff --git a/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md b/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md index cc286c71d..956c28135 100644 --- a/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md +++ b/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md @@ -1807,7 +1807,7 @@ qualification still remain; these changes issue no qualification or readiness. The closed release-only corpus now distinguishes offline verification, private commissioning and ordinary qualified live execution (schema -`auths.qualification-corpus/2`). An installed client in commissioning must +`auths.qualification-corpus/3`). An installed client in commissioning must measure a missing-qualification refusal with zero lease and entry; the same scenario in ordinary live execution must measure a fresh confirmed effect. Commissioning cases require the production tuple and cannot satisfy production diff --git a/product/qualification/auths-recipe-qualification-issuance/src/bin/qualification_runner/mod.rs b/product/qualification/auths-recipe-qualification-issuance/src/bin/qualification_runner/mod.rs index 2df481403..2aa58e141 100644 --- a/product/qualification/auths-recipe-qualification-issuance/src/bin/qualification_runner/mod.rs +++ b/product/qualification/auths-recipe-qualification-issuance/src/bin/qualification_runner/mod.rs @@ -126,6 +126,14 @@ pub(super) fn run( RunPhase::Commissioning => "commissioning", RunPhase::Live => "live", }; + for index in 0..auths_recipe_qualification_issuance::execution::MAX_RUN_CASES { + let path = work.join(format!("scan/trace/{phase_token}-{index:03}.json")); + match fs::remove_file(path) { + Ok(()) => (), + Err(error) if error.kind() == std::io::ErrorKind::NotFound => (), + Err(_) => return Err(refused()), + } + } for member in EvidenceMemberKind::ALL { let token = serde_json::to_value(member).map_err(|_| refused())?; let path = work.join(format!( @@ -156,11 +164,17 @@ pub(super) fn run( entered: 0, confirmed_by_read_back: 0, }; - for case in corpus.cases.iter().filter(|case| case.phase == phase) { + for (case_index, case) in corpus + .cases + .iter() + .enumerate() + .filter(|(_, case)| case.phase == phase) + { + let mut observations = Vec::with_capacity(case.steps.len()); let (report, effects) = case.execute(&tuple, |index, step| { let operation = serde_json::to_value(step.operation).map_err(|_| IssuanceError::CaseFailed)?; - execute_step( + let observation = execute_step( &harness, case.id.as_str(), index, @@ -168,8 +182,24 @@ pub(super) fn run( &work, Duration::from_secs(timeout_seconds), ) - .map_err(|_| IssuanceError::CaseFailed) + .map_err(|_| IssuanceError::CaseFailed)?; + observations.push(observation.clone()); + Ok(observation) })?; + // Closed, bounded observations remain auditable and enter the existing + // trace scan. Provider bodies, credentials and child output never do. + let trace = serde_json::to_vec(&serde_json::json!({ + "schema": "auths.qualification-execution-trace/1", + "phase": phase, + "tuple_sha256": tuple.digest().map_err(|_| refused())?, + "case": case.id, + "observations": observations, + })) + .map_err(|_| refused())?; + write( + &work.join(format!("scan/trace/{phase_token}-{case_index:03}.json")), + &trace, + )?; let member = case.scenario.member(); let token = serde_json::to_value(member).map_err(|_| refused())?; reports diff --git a/product/qualification/auths-recipe-qualification-issuance/src/execution.rs b/product/qualification/auths-recipe-qualification-issuance/src/execution.rs index 99a031820..4b0537925 100644 --- a/product/qualification/auths-recipe-qualification-issuance/src/execution.rs +++ b/product/qualification/auths-recipe-qualification-issuance/src/execution.rs @@ -17,7 +17,7 @@ pub const MAX_RUN_CASES: usize = 256; /// Largest sequence of operations within one case. pub const MAX_CASE_STEPS: usize = 32; /// Schema of the reviewed executable corpus. -pub const CORPUS_SCHEMA: &str = "auths.qualification-corpus/2"; +pub const CORPUS_SCHEMA: &str = "auths.qualification-corpus/3"; /// Where an operation may execute. Live cases never execute on a pull request. #[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)] @@ -106,6 +106,44 @@ pub struct ExpectedObservation { pub confirmed_by_read_back: u32, } +/// Source-owned evidence comparison. Every non-evidence fact stays exact. +#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] +#[serde(tag = "kind", rename_all = "kebab-case", deny_unknown_fields)] +pub enum EvidenceComparison { + /// Compare the complete verdict, including a precomputed evidence digest. + Static {}, + /// Compare an observed candidate response digest with a separately obtained + /// fresh provider response over this exact reviewed resource/action subject. + IndependentReadBack { + /// Domain-bound resource/action/expected-state commitment from the oracle. + subject_sha256: Sha256Digest, + }, + /// Compare the digest of a checked production doctor report for this tuple. + ProductionDoctor {}, +} + +/// Fresh evidence retained by the release harness separately from the candidate +/// verdict. The harness must execute the reviewed oracle/read independently; +/// copying the candidate's digest is not an independent witness. +#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] +#[serde(tag = "kind", rename_all = "kebab-case", deny_unknown_fields)] +pub enum FreshEvidenceWitness { + /// Exact bytes from a new bounded read of the reviewed provider resource. + IndependentReadBack { + /// The same source-owned subject the corpus commits to. + subject_sha256: Sha256Digest, + /// SHA-256 of the independently read response bytes. + response_sha256: Sha256Digest, + }, + /// A source-reviewed production doctor check, including tuple equality. + ProductionDoctor { + /// The actual candidate tuple checked in the report. + tuple_sha256: Sha256Digest, + /// SHA-256 of the independently validated raw doctor report. + report_sha256: Sha256Digest, + }, +} + /// One actual observation. There is deliberately no `passed` member. #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] #[serde(deny_unknown_fields)] @@ -114,6 +152,8 @@ pub struct RunObservation { pub tuple_sha256: Sha256Digest, /// Facts compared with the corpus, including independently measured counters. pub observed: ExpectedObservation, + /// An independently obtained fresh witness, only for the declared comparison. + pub fresh_evidence: Option, /// Provider entries not authorized by the exact action. pub unauthorized_provider_entries: u32, /// Whether the application or exported outputs exposed a secret. @@ -130,6 +170,8 @@ pub struct RunObservation { pub struct RunStep { /// Operation executed by the family harness on the candidate. pub operation: Operation, + /// Explicit evidence source; never an optional wildcard digest. + pub evidence_comparison: EvidenceComparison, /// Assertions made by the release runner, not the family harness. pub expected: ExpectedObservation, } @@ -240,7 +282,9 @@ impl RunCase { && step.expected.verdict.outcome == RunOutcome::Complete && step.expected.verdict.code.as_str() == "production-readiness-passed" && step.expected.verdict.request_sha256.is_none() - && step.expected.verdict.evidence_sha256.is_some() + && (step.expected.verdict.evidence_sha256.is_some() + || step.evidence_comparison + == EvidenceComparison::ProductionDoctor {}) && step.expected.credential_leases == 0 && step.expected.provider_entries == 0 && step.expected.confirmed_by_read_back == 0 @@ -260,6 +304,7 @@ impl RunCase { | S::ProductionReadiness ); if !harness_scenario(self.scenario) + || self.steps.iter().any(|step| !step.valid_comparison(self)) || !required || self.steps.is_empty() || self.steps.len() > MAX_CASE_STEPS @@ -314,7 +359,7 @@ impl RunCase { for (index, step) in self.steps.iter().enumerate() { let actual = observe(index, step)?; if actual.tuple_sha256 != tuple_digest - || actual.observed != step.expected + || !step.matches(&actual, tuple_digest) || actual.unauthorized_provider_entries != 0 || actual.secret_exposed || actual.repository_imported @@ -484,3 +529,57 @@ impl RunCase { Ok(()) } } + +impl RunStep { + fn valid_comparison(&self, case: &RunCase) -> bool { + use EvidenceComparison as Comparison; + match self.evidence_comparison { + Comparison::Static {} => true, + Comparison::IndependentReadBack { .. } => { + case.phase != RunPhase::Offline + && self.expected.verdict.evidence_sha256.is_none() + && self.expected.verdict.outcome == RunOutcome::Observed + && matches!( + self.operation, + Operation::Submit + | Operation::Replay + | Operation::Race + | Operation::ReadBack + | Operation::InstalledConsumer + ) + } + Comparison::ProductionDoctor {} => { + case.phase == RunPhase::Live + && case.scenario == Scenario::ProductionReadiness + && self.operation == Operation::Probe + && self.expected.verdict.evidence_sha256.is_none() + } + } + } + + fn matches(&self, actual: &RunObservation, tuple: Sha256Digest) -> bool { + use EvidenceComparison as Comparison; + use FreshEvidenceWitness as Witness; + let expected_evidence = match (&self.evidence_comparison, &actual.fresh_evidence) { + (Comparison::Static {}, None) => return actual.observed == self.expected, + ( + Comparison::IndependentReadBack { subject_sha256 }, + Some(Witness::IndependentReadBack { + subject_sha256: witnessed, + response_sha256, + }), + ) if subject_sha256 == witnessed => Some(*response_sha256), + ( + Comparison::ProductionDoctor {}, + Some(Witness::ProductionDoctor { + tuple_sha256, + report_sha256, + }), + ) if tuple_sha256 == &tuple => Some(*report_sha256), + _ => return false, + }; + let mut expected = self.expected.clone(); + expected.verdict.evidence_sha256 = expected_evidence; + actual.observed == expected + } +} diff --git a/product/qualification/auths-recipe-qualification-issuance/tests/common/mod.rs b/product/qualification/auths-recipe-qualification-issuance/tests/common/mod.rs index a5596601b..fcff4af69 100644 --- a/product/qualification/auths-recipe-qualification-issuance/tests/common/mod.rs +++ b/product/qualification/auths-recipe-qualification-issuance/tests/common/mod.rs @@ -124,6 +124,8 @@ pub fn executable_corpus() -> auths_recipe_qualification_issuance::execution::Ru }; let step = |operation, outcome, entries, confirmed| RunStep { operation, + evidence_comparison: + auths_recipe_qualification_issuance::execution::EvidenceComparison::Static {}, expected: ExpectedObservation { verdict: RunVerdict { outcome, @@ -295,7 +297,7 @@ if mode == 'failed': print('synthetic-canary-must-not-leave-child', file=sys.stderr) sys.exit(1) actual = {'tuple_sha256': (work / 'tuple-digest').read_text(), 'observed': step['expected'], - 'unauthorized_provider_entries': 0, 'secret_exposed': False, + 'fresh_evidence': None, 'unauthorized_provider_entries': 0, 'secret_exposed': False, 'repository_imported': False, 'provider_token_received': False} if operation == 'installed-consumer': assert pathlib.Path.cwd() == work diff --git a/product/qualification/auths-recipe-qualification-issuance/tests/execution.rs b/product/qualification/auths-recipe-qualification-issuance/tests/execution.rs index 98c81aa07..498d98bf0 100644 --- a/product/qualification/auths-recipe-qualification-issuance/tests/execution.rs +++ b/product/qualification/auths-recipe-qualification-issuance/tests/execution.rs @@ -18,6 +18,7 @@ fn run( let mut actual = RunObservation { tuple_sha256: tuple().digest().expect("digest"), observed: step.expected.clone(), + fresh_evidence: None, unauthorized_provider_entries: 0, secret_exposed: false, repository_imported: false, @@ -179,6 +180,7 @@ fn every_stage_executes_its_operations_and_a_missing_runner_refuses() { Ok(RunObservation { tuple_sha256: tuple().digest().expect("digest"), observed: step.expected.clone(), + fresh_evidence: None, unauthorized_provider_entries: 0, secret_exposed: false, repository_imported: false, @@ -327,7 +329,28 @@ fn subprocess_failures_invalidate_reports_and_installed_consumers_get_no_credent ); } let executed = fs::read_to_string(work.join("executed")).expect("operations"); - for case in executable_corpus().cases { + for (case_index, case) in executable_corpus().cases.into_iter().enumerate() { + let phase = serde_json::to_value(case.phase).expect("phase"); + let trace: serde_json::Value = serde_json::from_slice( + &fs::read(work.join(format!( + "scan/trace/{}-{case_index:03}.json", + phase.as_str().expect("token"), + ))) + .expect("closed trace"), + ) + .expect("trace JSON"); + assert_eq!( + trace["tuple_sha256"], + tuple().digest().expect("tuple").to_hex() + ); + assert_eq!(trace["case"], case.id.as_str()); + assert_eq!( + trace["observations"] + .as_array() + .expect("observations") + .len(), + case.steps.len() + ); for (index, step) in case.steps.iter().enumerate() { let operation = serde_json::to_value(step.operation).expect("operation"); assert!(executed.lines().any(|line| line @@ -367,3 +390,120 @@ fn subprocess_failures_invalidate_reports_and_installed_consumers_get_no_credent "invalid corpus input also clears stale passing evidence" ); } + +#[test] +fn fresh_evidence_is_closed_to_the_reviewed_subject_and_exact_candidate_digest() { + use auths_recipe_qualification_issuance::execution::{ + EvidenceComparison, FreshEvidenceWitness, + }; + let mut case = executable_corpus() + .cases + .into_iter() + .find(|case| case.scenario == Scenario::InstalledJourney) + .expect("live journey"); + let subject = tuple().compiled_recipe_sha256; + let response = tuple().profile_lock_sha256; + case.steps[0].evidence_comparison = EvidenceComparison::IndependentReadBack { + subject_sha256: subject, + }; + case.steps[0].expected.verdict.evidence_sha256 = None; + let set_witness = |actual: &mut RunObservation| { + actual.observed.verdict.evidence_sha256 = Some(response); + actual.fresh_evidence = Some(FreshEvidenceWitness::IndependentReadBack { + subject_sha256: subject, + response_sha256: response, + }); + }; + assert!(run(&case, |_, actual| set_witness(actual)).is_ok()); + for index in 0..6 { + assert_eq!( + run(&case, |_, actual| { + set_witness(actual); + match index { + 0 => actual.fresh_evidence = None, + 1 => actual.observed.verdict.evidence_sha256 = None, + 2 => actual.observed.verdict.evidence_sha256 = Some(subject), + 3 => { + actual.fresh_evidence = Some(FreshEvidenceWitness::IndependentReadBack { + subject_sha256: response, + response_sha256: response, + }) + } + 4 => { + actual.fresh_evidence = Some(FreshEvidenceWitness::ProductionDoctor { + tuple_sha256: tuple().digest().expect("tuple"), + report_sha256: response, + }) + } + _ => actual.observed.provider_entries += 1, + } + }), + Err(IssuanceError::CaseFailed) + ); + } + let mut offline = case.clone(); + offline.phase = auths_recipe_qualification_issuance::execution::RunPhase::Offline; + assert!(run(&offline, |_, actual| set_witness(actual)).is_err()); + let mut static_case = case.clone(); + static_case.steps[0].evidence_comparison = EvidenceComparison::Static {}; + assert!(run(&static_case, |_, actual| set_witness(actual)).is_err()); + case.steps[0].expected.verdict.evidence_sha256 = Some(response); + assert!( + run(&case, |_, actual| set_witness(actual)).is_err(), + "two evidence sources are ambiguous" + ); +} + +#[test] +fn a_dynamic_doctor_witness_must_match_the_actual_production_tuple() { + use auths_recipe_qualification::{BoundedText, LifecycleStoreKind}; + use auths_recipe_qualification_issuance::execution::{ + EvidenceComparison, FreshEvidenceWitness, Operation, RunPhase, + }; + let mut case = executable_corpus() + .cases + .into_iter() + .find(|case| case.scenario == Scenario::ApplicationCannotReadSecret) + .expect("probe"); + case.scenario = Scenario::ProductionReadiness; + case.phase = RunPhase::Live; + case.steps.truncate(1); + case.steps[0].operation = Operation::Probe; + case.steps[0].evidence_comparison = EvidenceComparison::ProductionDoctor {}; + let expected = &mut case.steps[0].expected; + expected.verdict.outcome = RunOutcome::Complete; + expected.verdict.code = BoundedText::parse("production-readiness-passed").expect("code"); + expected.verdict.evidence_sha256 = None; + let report = tuple().profile_lock_sha256; + let set = |actual: &mut RunObservation| { + actual.observed.verdict.evidence_sha256 = Some(report); + actual.fresh_evidence = Some(FreshEvidenceWitness::ProductionDoctor { + tuple_sha256: tuple().digest().expect("tuple"), + report_sha256: report, + }); + }; + assert!(run(&case, |_, actual| set(actual)).is_ok()); + assert!( + run(&case, |_, actual| { + set(actual); + actual.fresh_evidence = Some(FreshEvidenceWitness::ProductionDoctor { + tuple_sha256: report, + report_sha256: report, + }); + }) + .is_err() + ); + let mut development = tuple(); + development.target.store_kind = LifecycleStoreKind::SharedFileV1; + let mut invoked = false; + assert!( + case.execute(&development, |_, _| { + invoked = true; + Err(IssuanceError::CaseFailed) + }) + .is_err() + ); + assert!(!invoked); + case.phase = RunPhase::Commissioning; + assert!(run(&case, |_, actual| set(actual)).is_err()); +} diff --git a/qualification/README.md b/qualification/README.md index 79487c3cf..6323fdc82 100644 --- a/qualification/README.md +++ b/qualification/README.md @@ -98,7 +98,7 @@ The harness owns the provider-specific operations and pure oracle. The release runner owns sequencing, assertions, counters, and the resulting case reports. No family harness writes `passed` reports or `live-effects.json`. -`corpus-manifest.json` is `auths.qualification-corpus/2`, decoded as +`corpus-manifest.json` is `auths.qualification-corpus/3`, decoded as `execution::RunCorpus` by `auths-qualification run-stage`. It contains at most 256 unique cases. Each case has `id`, `scenario`, `capabilities`, `phase` (`offline`, `commissioning` or `live`), and at most 32 ordered `steps`. Each step has a closed @@ -247,3 +247,25 @@ a write entry is the HTTP client's execution boundary, including ambiguity. Neither is a claim that a provider received or performed a mutation. Reads, including credential probes, are counted separately. First qualification must still independently read back the reviewed disposable resource. + +### Fresh evidence comparisons + +Every corpus step declares `evidence_comparison`: `static`, +`independent-read-back` with a reviewed `subject_sha256`, or +`production-doctor`. Static comparisons require the complete precomputed +verdict and forbid a fresh witness. Dynamic comparisons require an absent +precomputed evidence digest; every other expected field remains exact. + +An independent read-back is allowed only for an observed protected operation. +The separate fresh witness must name the exact reviewed resource/action/state +subject, and its raw response digest must equal the candidate's evidence +digest. Different bytes fail the run, even if both responses appear successful. +The reference validates fresh provider state and echo before creating this +witness; it never accepts the candidate's locator or digest as the oracle. +A doctor witness is confined to a read-only production-readiness probe in the +ordinary live phase and must name the actual tuple. Unknown sources, omitted +witnesses, mismatched subjects/digests and extra fields fail closed. + +The runner retains closed actual observations under `scan/trace`, separately +from the pass reports. They contain no provider body or secret and undergo the +existing protected redaction scan before export. diff --git a/qualification/reference/README.md b/qualification/reference/README.md index b3239a2e2..162021d6f 100644 --- a/qualification/reference/README.md +++ b/qualification/reference/README.md @@ -46,3 +46,17 @@ prevent output. Filenames never select code. Private author keys are absent. The protected family setup, complete corpus and live workflow still need to use these references. No family is qualified by landing this code. + +`measure.py` validates and subtracts native execution snapshots: matching fresh +scope, no saturation/decrease, no duplicate host in an aggregate. Restarted +engines must be measured separately. Budget consumption is never substituted +for actual custody calls. + +`fresh_evidence.py` is the separate response oracle for the reviewed Stripe +refund and Airtable update. It validates the approved resource, exact intended +value, test-mode success (Stripe) and the action-derived echo, then hashes the +raw independently fetched response. It accepts no candidate response digest +or locator. Its subject binds the full reviewed request, resource ledger, +action and expected state. The corpus runner compares this fresh witness with +the candidate's own digest. Synthetic unit responses test refusals and exact +bytes; they are not qualification evidence. diff --git a/qualification/reference/fresh_evidence.py b/qualification/reference/fresh_evidence.py new file mode 100644 index 000000000..5bcf5163b --- /dev/null +++ b/qualification/reference/fresh_evidence.py @@ -0,0 +1,72 @@ +"""Independent bounded response checks for the two reviewed provider families. + +This module performs no I/O and accepts no candidate result/digest/locator. +The protected reference harness supplies bytes from its own fresh read of a +resource selected from the reviewed run ledger and action, then the runner +compares the witness with the candidate separately. +""" + +import json +from common import canonical, digest, echo, identifier, require, sha256 +import airtable_record as airtable +import stripe_platform as stripe + + +def decode(response): + require(type(response) is bytes and 0 < len(response) <= 65536, + 'qualification.fresh.response-bound') + def unique(pairs): + result = {} + for key, value in pairs: + require(key not in result, 'qualification.fresh.duplicate-member') + result[key] = value + return result + def invalid(_value): + require(False, 'qualification.fresh.invalid-json') + try: + value = json.loads(response, object_pairs_hook=unique, parse_constant=invalid) + except (ValueError, UnicodeError, RecursionError): + require(False, 'qualification.fresh.invalid-json') + require(type(value) is dict, 'qualification.fresh.invalid-json') + return value + + +def subject(family, arguments, resources, action_commitment, recipe_digest): + reference = {'stripe-platform-refund-v1': stripe, + 'airtable-record-update-v1': airtable}.get(family) + require(reference is not None, 'qualification.fresh.family') + # Re-run the complete independent request oracle; invalid actions cannot + # acquire a subject merely by hashing arbitrary input. + require(type(resources) is dict, 'qualification.fresh.resources') + reference.resources(resources, resources.get('protected_run')) + request = reference.request(arguments, resources, action_commitment, recipe_digest) + return sha256(b'auths.qualification-read-back-subject/1\0' + canonical({ + 'family': family, 'arguments': arguments, 'request': request, + 'resources_sha256': sha256(canonical(resources)), + 'action_commitment': digest(action_commitment), + 'recipe_digest': digest(recipe_digest), + })) + + +def witness(family, arguments, resources, action_commitment, recipe_digest, response): + expected_subject = subject(family, arguments, resources, action_commitment, recipe_digest) + value = decode(response) + token = echo(arguments['operator_namespace'], arguments['operation_id'], action_commitment) + if family == stripe.FAMILY: + identifier(value.get('id'), r're_[A-Za-z0-9]{1,128}') + require(value.get('object') == 'refund' and value.get('livemode') is False + and value.get('payment_intent') == arguments['payment_intent'] + and type(value.get('amount')) is int and value['amount'] == arguments['amount'] + and value.get('currency') == arguments['currency'] + and value.get('status') == 'succeeded' + and type(value.get('metadata')) is dict + and value['metadata'].get('auths_echo') == token, + 'qualification.fresh.state-mismatch') + else: + require(value.get('id') == arguments['record_id'] + and type(value.get('fields')) is dict + and value['fields'].get('DemoStatus') == arguments['replacement'] + and value['fields'].get('auths_echo') == token, + 'qualification.fresh.state-mismatch') + return {'kind': 'independent-read-back', 'subject_sha256': expected_subject, + 'response_sha256': sha256(response)} diff --git a/qualification/reference/measure.py b/qualification/reference/measure.py new file mode 100644 index 000000000..6806690b7 --- /dev/null +++ b/qualification/reference/measure.py @@ -0,0 +1,44 @@ +"""Release-only validation of native process-local boundary measurements.""" + +from common import closed, identifier, integer, require + +FIELDS = ['schema', 'scope', 'credential_lease_calls', 'write_transport_entries', + 'read_transport_entries'] +MAXIMUM = (1 << 64) - 1 + + +def snapshot(value): + closed(value, FIELDS) + require(value['schema'] == 'auths.gateway-execution-witness/1', + 'qualification.measure.schema') + identifier(value['scope'], r'[0-9a-f]{32}') + for field in FIELDS[2:]: + # Saturation is unusable evidence; do not infer a zero delta from it. + integer(value[field], 0, MAXIMUM - 1) + return value + + +def delta(before, after): + before, after = snapshot(before), snapshot(after) + require(before['scope'] == after['scope'], 'qualification.measure.changed-scope') + result = {} + for field in FIELDS[2:]: + require(after[field] >= before[field], 'qualification.measure.decreasing-counter') + result[field] = after[field] - before[field] + return result + + +def aggregate(pairs): + require(type(pairs) is list and 1 <= len(pairs) <= 2, + 'qualification.measure.host-bound') + seen, result = set(), dict.fromkeys(FIELDS[2:], 0) + for pair in pairs: + require(type(pair) in [tuple, list] and len(pair) == 2, 'qualification.measure.host-bound') + before, after = pair + measured = delta(before, after) + require(before['scope'] not in seen, 'qualification.measure.duplicate-host') + seen.add(before['scope']) + for field, count in measured.items(): + result[field] += count + integer(result[field], 0, (1 << 32) - 1) + return result diff --git a/qualification/reference/tests/test_reference.py b/qualification/reference/tests/test_reference.py index 6fc388325..131639946 100644 --- a/qualification/reference/tests/test_reference.py +++ b/qualification/reference/tests/test_reference.py @@ -16,6 +16,8 @@ import stripe_platform as stripe from common import Refusal, echo, idempotency from common import canonical, sha256 +import measure +import fresh_evidence as fresh import expand as expansion from expand import decode, unique_object @@ -47,6 +49,56 @@ def airtable_arguments(self): 'recipe_digest': DIGEST, 'record_id': 'recTEST0000000001', 'replacement': 'Approved'} + def test_native_measurements_refuse_restart_wrap_and_duplicate_hosts(self): + before = {'schema': 'auths.gateway-execution-witness/1', 'scope': '1' * 32, + 'credential_lease_calls': 0, 'write_transport_entries': 0, + 'read_transport_entries': 0} + after = dict(before, credential_lease_calls=1, write_transport_entries=1, + read_transport_entries=2) + self.assertEqual(measure.delta(before, after)['write_transport_entries'], 1) + for bad in [dict(after, scope='2' * 32), + dict(after, credential_lease_calls=(1 << 64) - 1), + dict(after, credential_lease_calls=True), dict(after, reset=False)]: + with self.assertRaises(Refusal): measure.delta(before, bad) + with self.assertRaises(Refusal): measure.delta(after, before) + with self.assertRaises(Refusal): measure.aggregate([(before, after), (before, after)]) + other = dict(before, scope='2' * 32) + self.assertEqual(measure.aggregate([(before, after), (other, other)])['credential_lease_calls'], 1) + + def test_fresh_stripe_evidence_checks_state_echo_and_raw_bytes(self): + resources, arguments = self.stripe_resources(), self.stripe_arguments() + value = {'id': 're_TEST123', 'object': 'refund', 'livemode': False, + 'payment_intent': arguments['payment_intent'], 'amount': arguments['amount'], + 'currency': 'usd', 'status': 'succeeded', + 'metadata': {'auths_echo': echo(stripe.SERVICE, arguments['operation_id'], COMMITMENT)}} + response = canonical(value) + witness = fresh.witness(stripe.FAMILY, arguments, resources, COMMITMENT, DIGEST, response) + self.assertEqual(witness['response_sha256'], sha256(response)) + self.assertEqual(witness['subject_sha256'], fresh.subject(stripe.FAMILY, arguments, resources, COMMITMENT, DIGEST)) + for field, bad in [('amount', True), ('amount', 999), ('livemode', True), + ('payment_intent', 'pi_OTHER'), ('status', 'pending'), + ('metadata', {'auths_echo': 'forged'})]: + changed = dict(value, **{field: bad}) + with self.assertRaises(Refusal): + fresh.witness(stripe.FAMILY, arguments, resources, COMMITMENT, DIGEST, canonical(changed)) + # Equal semantic JSON with different bytes still has a different witness. + spaced = json.dumps(value).encode() + self.assertNotEqual(fresh.witness(stripe.FAMILY, arguments, resources, COMMITMENT, DIGEST, spaced)['response_sha256'], witness['response_sha256']) + + def test_fresh_airtable_evidence_requires_exact_known_record_and_value(self): + resources, arguments = self.airtable_resources(), self.airtable_arguments() + value = {'id': arguments['record_id'], 'fields': { + 'DemoStatus': arguments['replacement'], + 'auths_echo': echo('airtable-demo', arguments['operation_id'], COMMITMENT)}} + witness = fresh.witness(airtable.FAMILY, arguments, resources, COMMITMENT, DIGEST, canonical(value)) + self.assertEqual(witness['response_sha256'], sha256(canonical(value))) + for changed in [dict(value, id='recOTHER000000001'), dict(value, fields={}), + dict(value, fields=dict(value['fields'], DemoStatus='Pending'))]: + with self.assertRaises(Refusal): + fresh.witness(airtable.FAMILY, arguments, resources, COMMITMENT, DIGEST, canonical(changed)) + for raw in [b'{"id":"one","id":"two"}', b'{"id":NaN}', b' ' * 65537]: + with self.assertRaises(Refusal): fresh.decode(raw) + def test_stripe_boundary_and_exact_form_have_no_connect_header(self): resources = stripe.resources(self.stripe_resources(), RUN) arguments = self.stripe_arguments() diff --git a/release/semantic-freeze-versions.toml b/release/semantic-freeze-versions.toml index c5decd70d..1ba0d4cfc 100644 --- a/release/semantic-freeze-versions.toml +++ b/release/semantic-freeze-versions.toml @@ -1,4 +1,4 @@ -freeze_version = 376 +freeze_version = 377 # Semantic identity counters live outside the xtask source tree deliberately. # The formal source closure binds xtask's executable code, while the semantic @@ -45,7 +45,7 @@ freeze_version = 376 "auths.frozen-bytes/product/integrations/auths-stripe/fixtures/subscription-create/v1/manifest.sha256.json" = 1 "auths.frozen-bytes/product/integrations/auths-stripe/fixtures/subscription-modify/v1/manifest.sha256.json" = 1 "auths.frozen-bytes/product/integrations/auths-stripe/fixtures/v1/manifest.sha256.json" = 1 -"auths.identity.protocol" = 129 +"auths.identity.protocol" = 130 "auths.modular-components" = 20 "auths.portable-abi-bindings" = 121 "auths.product.bounded-domains" = 19 @@ -60,11 +60,11 @@ freeze_version = 376 "auths.product.mcp-closed-execution" = 31 "auths.product.mechanism-profile-conformance" = 12 "auths.product.operations" = 5 -"auths.product.public-sdk-contract" = 126 +"auths.product.public-sdk-contract" = 127 "auths.product.receipts" = 13 "auths.product.release-assurance" = 7 "auths.product.simplified-waist" = 19 "auths.product.vocabulary" = 24 "auths.release.benchmark-contract" = 1 "auths.release.evolution-contract" = 79 -"auths.release.public-surface" = 376 +"auths.release.public-surface" = 377 diff --git a/release/semantic-freeze.json b/release/semantic-freeze.json index 6abe4635f..7c9a96260 100644 --- a/release/semantic-freeze.json +++ b/release/semantic-freeze.json @@ -1,6 +1,6 @@ { "schema": "auths.semantic-freeze/1", - "freezeVersion": 376, + "freezeVersion": 377, "publicSurface": { "rustRoots": [ "auths", @@ -550,7 +550,7 @@ }, { "id": "auths.identity.protocol", - "version": 129, + "version": 130, "classification": "frozen-meaning", "categories": [ "identity-protocol-versions", @@ -573,7 +573,7 @@ "core/fixtures/identity/v1/vectors.json", "core/spec/identity/v1" ], - "sha256": "4eeec6390c1fc6e85b7f76279dd702ae301ac5f9e00bd7a0b5f062b491bc0ef0" + "sha256": "0826a5e79af86b77087b1e92415c3acb9a43ccc6c1e459d986cd961e6219e938" }, { "id": "auths.modular-components", @@ -871,7 +871,7 @@ }, { "id": "auths.product.public-sdk-contract", - "version": 126, + "version": 127, "classification": "frozen-meaning", "categories": [ "rust-sdk-contract", @@ -889,7 +889,7 @@ "product/runtime/auths-runtime/src", "product/sdk/auths-sdk/src" ], - "sha256": "576e0cabf2f50698660ffaf92a8a47e35d4c8ff935b6484f9d0953a3c0d862d9" + "sha256": "18a272acd5c0199948712fb3d488711040c36abdbf824bc42b00bdabfc6a2eb6" }, { "id": "auths.product.receipts", @@ -1011,7 +1011,7 @@ }, { "id": "auths.release.public-surface", - "version": 376, + "version": 377, "classification": "release-metadata", "categories": [ "package-names", @@ -1104,7 +1104,7 @@ "xtask/src/release_launch.rs", "xtask/src/semantic_freeze.rs" ], - "sha256": "ba482c91283ddab5b0f4ba89a8bbd4c76d7decde5206ae139ebd18f747c7488b" + "sha256": "86cd3062177bf244e1888b75f53bb9e79e40ab8c24419f5910becca6ceac4926" } ] } From 872ddc59fa8bea776e9f2881af40fdd3063e815b Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 05:10:14 +0100 Subject: [PATCH 061/108] Journal disposable provider setup and verify ownership before cleanup --- ...NDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md | 3 +- qualification/reference/README.md | 33 ++++ qualification/reference/airtable_resources.py | 139 +++++++++++++ qualification/reference/resource_io.py | 111 +++++++++++ qualification/reference/stripe_resources.py | 173 ++++++++++++++++ .../reference/tests/test_resources.py | 185 ++++++++++++++++++ 6 files changed, 643 insertions(+), 1 deletion(-) create mode 100644 qualification/reference/airtable_resources.py create mode 100644 qualification/reference/resource_io.py create mode 100644 qualification/reference/stripe_resources.py create mode 100644 qualification/reference/tests/test_resources.py diff --git a/docs/research/INDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md b/docs/research/INDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md index 90cff82ea..036e64e1c 100644 --- a/docs/research/INDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md +++ b/docs/research/INDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md @@ -12,7 +12,8 @@ audit or real-user trial is claimed. | The runner prohibited a legitimate read-only recovery lease on replay. | One lease may finish an unresolved entered attempt's observation. A replay cannot write again or reacquire after observation. Implemented with regression cases. | | A live provider response's exact digest cannot be predicted before creating the effect. | Implemented: corpus schema 3 declares a closed evidence source and reviewed subject; fresh provider-response/doctor witnesses must match the candidate digest and actual tuple. All remaining facts stay exact. Closed step observations are retained for the trace scan. | | The production CLI does not expose independently counted custody/transport boundary observations. | Implemented: private process-scoped counters at the actual custody lease call and HTTP execution boundaries, including failures. Commissioning commands return before/after snapshots; ordinary clients cannot reset them. Remote effects still require separate fresh read-back. | -| Existing AWS roles trust the `gateway-custody-live` environment, while the qualification template names separate family environments. | Next: use an explicitly reviewed protected-environment arrangement that matches the actual OIDC trust, with required reviewer, main-only policy and family-specific credential injection. No role trust or gate is weakened. | +| Disposable setup could leak resources after a lost creation response. | Implemented run-specific durable preparation journals, Stripe idempotent recovery and Airtable exact ownership discovery. Cleanup requires fresh ownership/state checks and leaves unrelated resources alone. Protected family orchestration still needs integration. | +| Existing AWS roles trust the `gateway-custody-live` environment, while the qualification template names separate family environments. | Inspected the existing reviewer-protected custody environment. Its branch policy is currently unset. Automatic approval review rejected tightening that shared environment and uploading local provider credentials there because that destination was not explicitly authorized. No environment change or provider-key upload occurred; protected orchestration remains pending. No role trust or gate is weakened. | | Main-only protected code must be deployed before the first protected qualification run. | A bounded prerequisite rollout of the completed runner is needed before collecting evidence. Epic acceptance stays open until actual runs, signed closure and CI are complete. | The public offline root ceremony and purpose-separated certificates are pinned. diff --git a/qualification/reference/README.md b/qualification/reference/README.md index 162021d6f..8b3fef3e0 100644 --- a/qualification/reference/README.md +++ b/qualification/reference/README.md @@ -60,3 +60,36 @@ or locator. Its subject binds the full reviewed request, resource ledger, action and expected state. The corpus runner compares this fresh witness with the candidate's own digest. Synthetic unit responses test refusals and exact bytes; they are not qualification evidence. + +### Disposable provider resource lifecycle + +`stripe_resources.py` prepares platform-account test payments with `pm_card_visa` +and the run marker `metadata.auths_qualification`. It requires separate test +setup and restricted runtime keys, supplied as closed JSON on private stdin +(`setup`, `runtime`). Each planned intent is journaled before POST and has a +run/index-specific idempotency key. A lost response can be recovered for one +hour with that same key. Cleanup verifies platform, test mode, exact payment, +run marker and charge, refunds only the remaining test balance and confirms +full retirement with a fresh read. Recovering a pending setup during cleanup +may create and immediately retire its one pre-journaled test fixture. It never +uses Connect or a `Stripe-Account` header. + +`airtable_resources.py` accepts a personal access token on private stdin +(`token`) and uses only the reviewed dedicated base/table. Before any creation, +it journals the complete run/index-specific `Name` predicate. Exact filtered +fresh reads recover lost creation responses and determine the public ledger; +duplicate names cannot produce a qualification input. Cleanup discovers all +records under that predicate, rechecks ownership immediately before each +delete and confirms their absence. Other records, the table and the base remain. + +Both commands take `prepare --protected-run --count <1..32> +--journal --out ` or `cleanup --journal `. The output parent +must already be owner-private mode 0700. Public ledgers never contain tokens, +provider response bodies or payment client secrets. Journals are bounded, +written atomically and retained after partial failure for cleanup. Existing +outputs cannot be replaced. TLS requests refuse redirects and ambient proxies; +provider error bodies never enter diagnostics. + +Unit cases use synthetic providers, including lost responses, changed ownership, +foreign resources, duplicate records and unsafe files. Actual setup/cleanup +rehearsals are recorded separately and confer no protected qualification. diff --git a/qualification/reference/airtable_resources.py b/qualification/reference/airtable_resources.py new file mode 100644 index 000000000..71c100e66 --- /dev/null +++ b/qualification/reference/airtable_resources.py @@ -0,0 +1,139 @@ +"""Prepare/retire owned records only in the reviewed disposable Airtable table.""" + +import argparse +from pathlib import Path +import urllib.parse + +from common import canonical, closed, identifier, integer, require +import airtable_record as reference +import resource_io as io + +SCHEMA = 'auths.airtable-resource-preparation/1' +TABLE_PATH = '/v0/' + reference.BASE + '/' + reference.TABLE + + +class Resources: + def __init__(self, token, api=None): + self.token = token + self.api = api or self.http + + def http(self, method, path, fields=None): + return io.request('https://api.airtable.com', method, path, self.token, + None if fields is None else canonical(fields), + {'Content-Type': 'application/json'} if fields is not None else None) + + @staticmethod + def names(run, count): + return ['Auths qualification ' + run + ' #' + str(index).zfill(2) + for index in range(count)] + + def discover(self, names): + # Names contain no quotes: run grammar is checked before constructing + # this exact predicate. No unrelated record is downloaded or selected. + formula = 'OR(' + ','.join("{Name}='" + name + "'" for name in names) + ')' + value = self.api('GET', TABLE_PATH + '?' + urllib.parse.urlencode({ + 'filterByFormula': formula, 'pageSize': 100, + })) + require(type(value.get('records')) is list and len(value['records']) <= 64 + and 'offset' not in value, 'qualification.resources.discovery-bound') + seen = set() + for record in value['records']: + record_id = identifier(record.get('id'), r'rec[A-Za-z0-9]{14}') + require(record_id not in seen and type(record.get('fields')) is dict + and record['fields'].get('Name') in names, + 'qualification.resources.record-binding') + seen.add(record_id) + return value['records'] + + def journal(self, path): + value = io.read(path) + closed(value, ['schema', 'protected_run', 'base', 'table', 'count', 'retired']) + require(value['schema'] == SCHEMA and value['base'] == reference.BASE + and value['table'] == reference.TABLE and type(value['retired']) is bool, + 'qualification.resources.ledger-binding') + io.run_id(value['protected_run']) + integer(value['count'], 1, 32) + return value + + def prepare(self, run, count, journal, output): + io.run_id(run) + integer(count, 1, 32) + journal, output = Path(journal), Path(output) + require(not output.exists(), 'qualification.resources.output-exists') + if journal.exists(): + value = self.journal(journal) + require(value['protected_run'] == run and value['count'] == count + and not value['retired'], 'qualification.resources.ledger-binding') + else: + value = {'schema': SCHEMA, 'protected_run': run, 'base': reference.BASE, + 'table': reference.TABLE, 'count': count, 'retired': False} + # The complete ownership predicate is durable before a POST. This + # also covers a lost creation response or interruption before save. + io.write(journal, value, new=True) + names = self.names(run, count) + existing = self.discover(names) + indexed = {} + for record in existing: + name = record['fields']['Name'] + require(name not in indexed, 'qualification.resources.ambiguous-record') + indexed[name] = record + for name in names: + if name in indexed: + continue + record = self.api('POST', TABLE_PATH, {'fields': {'Name': name, 'DemoStatus': 'Pending'}}) + identifier(record.get('id'), r'rec[A-Za-z0-9]{14}') + require(type(record.get('fields')) is dict and record['fields'].get('Name') == name + and record['fields'].get('DemoStatus') == 'Pending', + 'qualification.resources.record-binding') + # The fresh query, rather than a successful POST or remembered locator, + # determines the exact records the qualification ledger may expose. + fresh = self.discover(names) + require(len(fresh) == count and {record['fields']['Name'] for record in fresh} == set(names), + 'qualification.resources.ambiguous-record') + ledger = {'schema': 'auths.airtable-record-qualification-resources/1', + 'protected_run': run, 'base': reference.BASE, 'table': reference.TABLE, + 'records': [{'id': record['id'], 'run_metadata': run} + for record in sorted(fresh, key=lambda record: record['fields']['Name'])]} + reference.resources(ledger, run) + io.write(output, ledger, new=True) + + def cleanup(self, journal): + value = self.journal(journal) + if value['retired']: + return + names = self.names(value['protected_run'], value['count']) + # Includes ambiguous creations not retained in the public ledger. Even + # duplicate owned names are retired; no unrelated record is touched. + for record in self.discover(names): + fresh = self.api('GET', TABLE_PATH + '/' + record['id']) + require(fresh.get('id') == record['id'] and type(fresh.get('fields')) is dict + and fresh['fields'].get('Name') == record['fields']['Name'], + 'qualification.resources.record-binding') + removed = self.api('DELETE', TABLE_PATH + '/' + record['id']) + require(removed.get('id') == record['id'] and removed.get('deleted') is True, + 'qualification.resources.cleanup-refused') + require(not self.discover(names), 'qualification.resources.cleanup-unconfirmed') + value['retired'] = True + io.write(journal, value) + + +def main(): + parser = argparse.ArgumentParser() + sub = parser.add_subparsers(dest='command', required=True) + prepare = sub.add_parser('prepare') + prepare.add_argument('--protected-run', required=True) + prepare.add_argument('--count', type=int, default=1) + prepare.add_argument('--out', type=Path, required=True) + for command in [prepare, sub.add_parser('cleanup')]: + command.add_argument('--journal', type=Path, required=True) + args = parser.parse_args() + resources = Resources(io.credentials({'token': 'pat'})['token']) + if args.command == 'prepare': + resources.prepare(args.protected_run, args.count, args.journal, args.out) + else: + resources.cleanup(args.journal) + print('qualification.resources.' + args.command + '-complete') + + +if __name__ == '__main__': + io.finish(main) diff --git a/qualification/reference/resource_io.py b/qualification/reference/resource_io.py new file mode 100644 index 000000000..2f9eb1ac5 --- /dev/null +++ b/qualification/reference/resource_io.py @@ -0,0 +1,111 @@ +"""Private local I/O for disposable resource preparation; never shipping code.""" + +import json +import os +from pathlib import Path +import re +import stat +import sys +import urllib.error +import urllib.request + +from common import Refusal, canonical, closed, require +from fresh_evidence import decode + + +def run_id(value): + require(type(value) is str and re.fullmatch(r'[a-z][a-z0-9-]{0,63}/[0-9]{1,20}/[0-9]{1,20}', value), + 'qualification.resources.run-binding') + return value + + +def credentials(fields): + raw = sys.stdin.buffer.read(8193) + require(0 < len(raw) <= 8192, 'qualification.resources.credential-bound') + try: + value = decode(raw) + closed(value, fields) + for name, prefix in fields.items(): + key = value[name] + require(type(key) is str and key.startswith(prefix) and 20 <= len(key) <= 2048 + and all(33 <= ord(character) <= 126 for character in key), + 'qualification.resources.credential-kind') + return value + finally: + raw = b'' + + +class NoRedirect(urllib.request.HTTPRedirectHandler): + def redirect_request(self, req, fp, code, msg, headers, newurl): + raise Refusal('qualification.resources.redirect-refused') + + +def request(origin, method, path, key, body=None, headers=None): + require(path.startswith('/') and not path.startswith('//') and '\r' not in path and '\n' not in path, + 'qualification.resources.path-bound') + values = {'Authorization': 'Bearer ' + key, 'Accept': 'application/json'} + values.update(headers or {}) + outbound = urllib.request.Request(origin + path, method=method, data=body, headers=values) + try: + with urllib.request.build_opener(urllib.request.ProxyHandler({}), NoRedirect).open(outbound, timeout=25) as response: + require(200 <= response.status <= 299, 'qualification.resources.http-refused') + raw = response.read(65537) + return decode(raw) + except (urllib.error.HTTPError, urllib.error.URLError, TimeoutError, OSError): + # Provider errors can contain submitted credentials or resource data. + # They never become stdout, exception text or a saved report. + raise Refusal('qualification.resources.provider-unavailable') from None + + +def read(path): + fd = os.open(path, os.O_RDONLY | os.O_NOFOLLOW) + with os.fdopen(fd, 'rb') as stream: + info = os.fstat(stream.fileno()) + require(stat.S_ISREG(info.st_mode) and info.st_nlink == 1 and info.st_size <= 65536, + 'qualification.resources.ledger-bound') + return decode(stream.read(65537)) + + +def write(path, value, *, new=False): + path = Path(path) + parent = path.parent + info = os.lstat(parent) + require(stat.S_ISDIR(info.st_mode) and not stat.S_ISLNK(info.st_mode) + and info.st_uid == os.getuid() and stat.S_IMODE(info.st_mode) == 0o700, + 'qualification.resources.private-output') + payload = canonical(value) + require(len(payload) <= 65536, 'qualification.resources.ledger-bound') + if new: + fd = os.open(path, os.O_WRONLY | os.O_CREAT | os.O_EXCL | os.O_NOFOLLOW, 0o600) + with os.fdopen(fd, 'wb') as stream: + stream.write(payload) + stream.flush() + os.fsync(stream.fileno()) + else: + # A ledger is replaced atomically, never followed through a symlink. + existing = os.lstat(path) + require(stat.S_ISREG(existing.st_mode) and existing.st_nlink == 1 + and existing.st_uid == os.getuid(), 'qualification.resources.ledger-bound') + temporary = path.with_name(path.name + '.next-' + os.urandom(8).hex()) + fd = os.open(temporary, os.O_WRONLY | os.O_CREAT | os.O_EXCL | os.O_NOFOLLOW, 0o600) + try: + with os.fdopen(fd, 'wb') as stream: + stream.write(payload) + stream.flush() + os.fsync(stream.fileno()) + os.replace(temporary, path) + finally: + temporary.unlink(missing_ok=True) + fd = os.open(parent, os.O_RDONLY | os.O_DIRECTORY | os.O_NOFOLLOW) + try: + os.fsync(fd) + finally: + os.close(fd) + + +def finish(command): + try: + command() + except (Refusal, ValueError, OSError): + print('qualification.resources.refused', file=sys.stderr) + raise SystemExit(1) from None diff --git a/qualification/reference/stripe_resources.py b/qualification/reference/stripe_resources.py new file mode 100644 index 000000000..791c85b9c --- /dev/null +++ b/qualification/reference/stripe_resources.py @@ -0,0 +1,173 @@ +"""Create and retire only this run's platform-account Stripe test payments.""" + +import argparse +import hashlib +import time +import urllib.parse +from pathlib import Path + +from common import closed, identifier, integer, require +import resource_io as io +import stripe_platform as reference + +SCHEMA = 'auths.stripe-platform-resource-preparation/1' + + +def key(run, index, operation): + return 'auths-resource-' + hashlib.sha256( + (run + '\0' + str(index) + '\0' + operation).encode()).hexdigest() + + +class Resources: + def __init__(self, keys, api=None): + self.keys = keys + self.api = api or self.http + + def http(self, method, path, fields=None, idempotency=None, runtime=False): + headers = {'Stripe-Version': '2025-03-31.basil'} + if idempotency: + headers['Idempotency-Key'] = idempotency + body = None + if fields is not None: + body = urllib.parse.urlencode(fields).encode() + headers['Content-Type'] = 'application/x-www-form-urlencoded' + return io.request('https://api.stripe.com', method, path, + self.keys['runtime' if runtime else 'setup'], body, headers) + + def account(self): + platform = self.api('GET', '/v1/account', runtime=True).get('id') + identifier(platform, r'acct_[A-Za-z0-9]{1,64}') + require(self.api('GET', '/v1/account').get('id') == platform + and self.api('GET', '/v1/balance', runtime=True).get('livemode') is False, + 'qualification.resources.platform-binding') + return platform + + def create(self, run, index): + return self.api('POST', '/v1/payment_intents', { + 'amount': 2000, 'currency': 'usd', 'payment_method': 'pm_card_visa', + 'confirm': 'true', 'automatic_payment_methods[enabled]': 'true', + 'automatic_payment_methods[allow_redirects]': 'never', + 'metadata[auths_qualification]': run, + }, idempotency=key(run, index, 'prepare')) + + @staticmethod + def payment(value, run, payment_id): + require(value.get('id') == payment_id and value.get('livemode') is False + and value.get('status') == 'succeeded' and value.get('amount') == 2000 + and value.get('amount_received') == 2000 and value.get('currency') == 'usd' + and type(value.get('metadata')) is dict + and value['metadata'].get('auths_qualification') == run, + 'qualification.resources.payment-binding') + + def journal(self, path): + value = io.read(path) + closed(value, ['schema', 'protected_run', 'platform', 'created_at', 'entries']) + require(value['schema'] == SCHEMA and self.account() == value['platform'], + 'qualification.resources.ledger-binding') + io.run_id(value['protected_run']) + integer(value['created_at'], 1, int(time.time())) + require(type(value['entries']) is list and 1 <= len(value['entries']) <= 32, + 'qualification.resources.resource-bound') + seen = set() + for entry in value['entries']: + closed(entry, ['id', 'retired']) + require(type(entry['retired']) is bool, 'qualification.resources.ledger-binding') + if entry['id'] is not None: + identifier(entry['id'], r'pi_[A-Za-z0-9]{1,128}') + require(entry['id'] not in seen, 'qualification.resources.duplicate-payment') + seen.add(entry['id']) + return value + + def prepare(self, run, count, journal, output): + io.run_id(run) + integer(count, 1, 32) + journal, output = Path(journal), Path(output) + require(not output.exists(), 'qualification.resources.output-exists') + if journal.exists(): + value = self.journal(journal) + require(value['protected_run'] == run and len(value['entries']) == count + and not any(entry['retired'] for entry in value['entries']), + 'qualification.resources.ledger-binding') + else: + value = {'schema': SCHEMA, 'protected_run': run, 'platform': self.account(), + 'created_at': int(time.time()), + 'entries': [{'id': None, 'retired': False} for _ in range(count)]} + io.write(journal, value, new=True) + # A pending provider response may be recovered only within its finite + # idempotency window; an old journal must never create a duplicate. + require(int(time.time()) - value['created_at'] <= 3600, + 'qualification.resources.preparation-expired') + payments = [] + for index, entry in enumerate(value['entries']): + payment = self.create(run, index) if entry['id'] is None else self.api( + 'GET', '/v1/payment_intents/' + entry['id']) + payment_id = identifier(payment.get('id'), r'pi_[A-Za-z0-9]{1,128}') + entry['id'] = payment_id + io.write(journal, value) + self.payment(payment, run, payment_id) + payments.append({'id': payment_id, 'amount_received': 2000, 'currency': 'usd', + 'livemode': False, 'run_metadata': run}) + ledger = {'schema': 'auths.stripe-platform-qualification-resources/1', + 'protected_run': run, 'platform': value['platform'], 'payments': payments} + reference.resources(ledger, run) + io.write(output, ledger, new=True) + + def cleanup(self, journal): + value = self.journal(journal) + run = value['protected_run'] + for index, entry in enumerate(value['entries']): + if entry['retired']: + continue + if entry['id'] is None: + # Replay only this run's pre-journaled test intent after an + # ambiguous preparation response. It may create then retire + # that one test fixture; it never searches unrelated payments. + require(int(time.time()) - value['created_at'] <= 3600, + 'qualification.resources.preparation-expired') + created = self.create(run, index) + entry['id'] = identifier(created.get('id'), r'pi_[A-Za-z0-9]{1,128}') + io.write(journal, value) + payment = self.api('GET', '/v1/payment_intents/' + entry['id']) + self.payment(payment, run, entry['id']) + charge_id = identifier(payment.get('latest_charge'), r'ch_[A-Za-z0-9]{1,128}') + charge = self.api('GET', '/v1/charges/' + charge_id) + require(charge.get('id') == charge_id and charge.get('payment_intent') == entry['id'] + and charge.get('livemode') is False and charge.get('amount') == 2000, + 'qualification.resources.charge-binding') + remaining = 2000 - integer(charge.get('amount_refunded'), 0, 2000) + if remaining: + refund = self.api('POST', '/v1/refunds', { + 'payment_intent': entry['id'], 'amount': remaining, + 'metadata[auths_qualification_cleanup]': run, + }, idempotency=key(run, index, 'cleanup-' + str(remaining))) + require(refund.get('status') == 'succeeded' and refund.get('livemode') is False + and refund.get('payment_intent') == entry['id'], + 'qualification.resources.cleanup-refused') + fresh = self.api('GET', '/v1/charges/' + charge_id) + require(fresh.get('livemode') is False and fresh.get('payment_intent') == entry['id'] + and fresh.get('amount_refunded') == 2000 and fresh.get('refunded') is True, + 'qualification.resources.cleanup-unconfirmed') + entry['retired'] = True + io.write(journal, value) + + +def main(): + parser = argparse.ArgumentParser() + sub = parser.add_subparsers(dest='command', required=True) + prepare = sub.add_parser('prepare') + prepare.add_argument('--protected-run', required=True) + prepare.add_argument('--count', type=int, default=1) + prepare.add_argument('--out', type=Path, required=True) + for command in [prepare, sub.add_parser('cleanup')]: + command.add_argument('--journal', type=Path, required=True) + args = parser.parse_args() + resources = Resources(io.credentials({'setup': 'sk_test_', 'runtime': 'rk_test_'})) + if args.command == 'prepare': + resources.prepare(args.protected_run, args.count, args.journal, args.out) + else: + resources.cleanup(args.journal) + print('qualification.resources.' + args.command + '-complete') + + +if __name__ == '__main__': + io.finish(main) diff --git a/qualification/reference/tests/test_resources.py b/qualification/reference/tests/test_resources.py new file mode 100644 index 000000000..7a739007d --- /dev/null +++ b/qualification/reference/tests/test_resources.py @@ -0,0 +1,185 @@ +"""Disposable setup recovery and ownership boundaries; synthetic providers only.""" + +import copy +import json +import os +from pathlib import Path +import re +import sys +import tempfile +import unittest +import urllib.parse + +sys.path.insert(0, str(Path(__file__).resolve().parents[1])) +import airtable_resources as airtable +import resource_io +import stripe_resources as stripe +from common import Refusal + +RUN = 'recipe-qualification/123/1' + + +class Stripe: + def __init__(self): + self.payments = {} + self.charges = {} + self.keys = {} + self.refunds = 0 + self.lose_create = False + + def api(self, method, path, fields=None, idempotency=None, runtime=False): + if path == '/v1/account': + return {'id': 'acct_SYNTHETIC'} + if path == '/v1/balance': + return {'livemode': False} + if path == '/v1/payment_intents': + assert method == 'POST' and fields['payment_method'] == 'pm_card_visa' + if idempotency in self.keys: + return copy.deepcopy(self.payments[self.keys[idempotency]]) + number = str(len(self.payments) + 1) + payment_id, charge_id = 'pi_SYNTHETIC' + number, 'ch_SYNTHETIC' + number + payment = {'id': payment_id, 'livemode': False, 'status': 'succeeded', + 'amount': 2000, 'amount_received': 2000, 'currency': 'usd', + 'metadata': {'auths_qualification': fields['metadata[auths_qualification]']}, + 'latest_charge': charge_id} + self.payments[payment_id] = payment + self.keys[idempotency] = payment_id + self.charges[charge_id] = {'id': charge_id, 'payment_intent': payment_id, + 'livemode': False, 'amount': 2000, + 'amount_refunded': 0, 'refunded': False} + if self.lose_create: + self.lose_create = False + raise Refusal('synthetic-lost-response') + return copy.deepcopy(payment) + if path.startswith('/v1/payment_intents/'): + return copy.deepcopy(self.payments[path.rsplit('/', 1)[1]]) + if path.startswith('/v1/charges/'): + return copy.deepcopy(self.charges[path.rsplit('/', 1)[1]]) + assert method == 'POST' and path == '/v1/refunds' + payment = self.payments[fields['payment_intent']] + charge = self.charges[payment['latest_charge']] + assert 0 < fields['amount'] <= 2000 - charge['amount_refunded'] + self.refunds += 1 + charge['amount_refunded'] += fields['amount'] + charge['refunded'] = charge['amount_refunded'] == 2000 + return {'status': 'succeeded', 'livemode': False, 'payment_intent': payment['id']} + + +class Airtable: + def __init__(self): + self.records = {'recUNRELATED00001': {'id': 'recUNRELATED00001', + 'fields': {'Name': 'Unrelated owner record', 'DemoStatus': 'Pending'}}} + self.deleted = [] + self.lose_create = False + self.change_before_delete = False + + def api(self, method, path, fields=None): + assert path.startswith(airtable.TABLE_PATH) + if method == 'GET' and '?' in path: + query = urllib.parse.parse_qs(urllib.parse.urlsplit(path).query) + names = re.findall(r"\{Name\}='([^']+)'", query['filterByFormula'][0]) + assert names + return {'records': copy.deepcopy([record for record in self.records.values() + if record['fields']['Name'] in names])} + if method == 'POST': + record_id = 'recSYNTHETIC' + str(len(self.records)).zfill(5) + record = {'id': record_id, 'fields': copy.deepcopy(fields['fields'])} + self.records[record_id] = record + if self.lose_create: + self.lose_create = False + raise Refusal('synthetic-lost-response') + return copy.deepcopy(record) + record_id = path.rsplit('/', 1)[1] + if method == 'GET': + result = copy.deepcopy(self.records[record_id]) + if self.change_before_delete: + result['fields']['Name'] = 'Changed ownership' + return result + assert method == 'DELETE' + self.deleted.append(record_id) + del self.records[record_id] + return {'id': record_id, 'deleted': True} + + +class Resources(unittest.TestCase): + def workspace(self): + temporary = tempfile.TemporaryDirectory() + self.addCleanup(temporary.cleanup) + work = Path(temporary.name) + os.chmod(work, 0o700) + return work + + def test_stripe_lost_creation_response_replays_only_the_same_test_fixture(self): + work, provider = self.workspace(), Stripe() + resources = stripe.Resources({}, provider.api) + provider.lose_create = True + with self.assertRaises(Refusal): + resources.prepare(RUN, 1, work / 'journal.json', work / 'resources.json') + self.assertFalse((work / 'resources.json').exists()) + self.assertEqual(len(provider.payments), 1) + resources.cleanup(work / 'journal.json') + self.assertEqual(len(provider.payments), 1, 'same idempotency key recovers the pending response') + self.assertEqual(provider.refunds, 1) + resources.cleanup(work / 'journal.json') + self.assertEqual(provider.refunds, 1, 'retired cleanup is idempotent') + + def test_stripe_setup_and_cleanup_refuse_changed_owner_and_live_mode(self): + work, provider = self.workspace(), Stripe() + resources = stripe.Resources({}, provider.api) + resources.prepare(RUN, 2, work / 'journal.json', work / 'resources.json') + self.assertEqual(len(resource_io.read(work / 'resources.json')['payments']), 2) + payment = next(iter(provider.payments.values())) + payment['metadata']['auths_qualification'] = 'another-run' + with self.assertRaises(Refusal): resources.cleanup(work / 'journal.json') + self.assertEqual(provider.refunds, 0) + payment['metadata']['auths_qualification'] = RUN + payment['livemode'] = True + with self.assertRaises(Refusal): resources.cleanup(work / 'journal.json') + self.assertEqual(provider.refunds, 0) + payment['livemode'] = False + resources.cleanup(work / 'journal.json') + self.assertEqual(provider.refunds, 2) + + def test_airtable_partial_setup_cleanup_discovers_only_owned_records(self): + work, provider = self.workspace(), Airtable() + resources = airtable.Resources('synthetic', provider.api) + provider.lose_create = True + with self.assertRaises(Refusal): + resources.prepare(RUN, 2, work / 'journal.json', work / 'resources.json') + resources.cleanup(work / 'journal.json') + self.assertEqual(set(provider.records), {'recUNRELATED00001'}) + self.assertEqual(len(provider.deleted), 1) + resources.cleanup(work / 'journal.json') + self.assertEqual(len(provider.deleted), 1) + + def test_airtable_changed_ownership_and_duplicate_names_cannot_qualify(self): + work, provider = self.workspace(), Airtable() + resources = airtable.Resources('synthetic', provider.api) + resources.prepare(RUN, 1, work / 'journal.json', work / 'resources.json') + provider.change_before_delete = True + with self.assertRaises(Refusal): resources.cleanup(work / 'journal.json') + self.assertFalse(provider.deleted) + provider.change_before_delete = False + owned = next(record for record in provider.records.values() if record['fields']['Name'].startswith('Auths')) + provider.records['recDUPLICATE00001'] = dict(copy.deepcopy(owned), id='recDUPLICATE00001') + with self.assertRaises(Refusal): + resources.prepare(RUN, 1, work / 'journal.json', work / 'another-output.json') + self.assertFalse((work / 'another-output.json').exists()) + resources.cleanup(work / 'journal.json') + self.assertEqual(set(provider.records), {'recUNRELATED00001'}) + + def test_ledger_outputs_refuse_symlinks_public_directories_and_overwrite(self): + work = self.workspace() + target = work / 'target.json' + target.write_text('{}') + linked = work / 'linked.json' + linked.symlink_to(target) + with self.assertRaises(OSError): resource_io.read(linked) + with self.assertRaises(Refusal): resource_io.write(linked, {}) + with self.assertRaises(OSError): resource_io.write(target, {}, new=True) + os.chmod(work, 0o755) + with self.assertRaises(Refusal): resource_io.write(work / 'new.json', {}, new=True) + + +if __name__ == '__main__': + unittest.main() From 632e2791504bd92d33832a7e6b582f57d7c2f5b6 Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 05:13:26 +0100 Subject: [PATCH 062/108] Validate Stripe test mode through its documented payment and charge objects --- docs/research/INDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md | 1 + qualification/reference/README.md | 6 ++++++ qualification/reference/fresh_evidence.py | 2 +- qualification/reference/stripe_resources.py | 2 +- qualification/reference/tests/test_reference.py | 2 +- qualification/reference/tests/test_resources.py | 2 +- 6 files changed, 11 insertions(+), 4 deletions(-) diff --git a/docs/research/INDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md b/docs/research/INDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md index 036e64e1c..7bb0cb0c4 100644 --- a/docs/research/INDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md +++ b/docs/research/INDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md @@ -12,6 +12,7 @@ audit or real-user trial is claimed. | The runner prohibited a legitimate read-only recovery lease on replay. | One lease may finish an unresolved entered attempt's observation. A replay cannot write again or reacquire after observation. Implemented with regression cases. | | A live provider response's exact digest cannot be predicted before creating the effect. | Implemented: corpus schema 3 declares a closed evidence source and reviewed subject; fresh provider-response/doctor witnesses must match the candidate digest and actual tuple. All remaining facts stay exact. Closed step observations are retained for the trace scan. | | The production CLI does not expose independently counted custody/transport boundary observations. | Implemented: private process-scoped counters at the actual custody lease call and HTTP execution boundaries, including failures. Commissioning commands return before/after snapshots; ordinary clients cannot reset them. Remote effects still require separate fresh read-back. | +| Stripe Refund objects were incorrectly assumed to carry `livemode`. | Corrected against the provider API: require the exact test PaymentIntent/Charge and run marker; validate the refund's binding/success. Synthetic responses now follow the real object shape. Local resource rehearsal exposed this before protected qualification. | | Disposable setup could leak resources after a lost creation response. | Implemented run-specific durable preparation journals, Stripe idempotent recovery and Airtable exact ownership discovery. Cleanup requires fresh ownership/state checks and leaves unrelated resources alone. Protected family orchestration still needs integration. | | Existing AWS roles trust the `gateway-custody-live` environment, while the qualification template names separate family environments. | Inspected the existing reviewer-protected custody environment. Its branch policy is currently unset. Automatic approval review rejected tightening that shared environment and uploading local provider credentials there because that destination was not explicitly authorized. No environment change or provider-key upload occurred; protected orchestration remains pending. No role trust or gate is weakened. | | Main-only protected code must be deployed before the first protected qualification run. | A bounded prerequisite rollout of the completed runner is needed before collecting evidence. Epic acceptance stays open until actual runs, signed closure and CI are complete. | diff --git a/qualification/reference/README.md b/qualification/reference/README.md index 8b3fef3e0..631f03471 100644 --- a/qualification/reference/README.md +++ b/qualification/reference/README.md @@ -93,3 +93,9 @@ provider error bodies never enter diagnostics. Unit cases use synthetic providers, including lost responses, changed ownership, foreign resources, duplicate records and unsafe files. Actual setup/cleanup rehearsals are recorded separately and confer no protected qualification. + +Stripe's [Refund object](https://docs.stripe.com/api/refunds/object) has no +`livemode` attribute. Test mode is established by the test key/account balance +and the exact freshly checked PaymentIntent and Charge; the refund must bind +that same payment. An unexpected explicit live-mode marker is refused. Unit +responses follow the provider's actual Refund shape. diff --git a/qualification/reference/fresh_evidence.py b/qualification/reference/fresh_evidence.py index 5bcf5163b..fb95be53d 100644 --- a/qualification/reference/fresh_evidence.py +++ b/qualification/reference/fresh_evidence.py @@ -54,7 +54,7 @@ def witness(family, arguments, resources, action_commitment, recipe_digest, resp token = echo(arguments['operator_namespace'], arguments['operation_id'], action_commitment) if family == stripe.FAMILY: identifier(value.get('id'), r're_[A-Za-z0-9]{1,128}') - require(value.get('object') == 'refund' and value.get('livemode') is False + require(value.get('object') == 'refund' and value.get('livemode', False) is False and value.get('payment_intent') == arguments['payment_intent'] and type(value.get('amount')) is int and value['amount'] == arguments['amount'] and value.get('currency') == arguments['currency'] diff --git a/qualification/reference/stripe_resources.py b/qualification/reference/stripe_resources.py index 791c85b9c..ff54079aa 100644 --- a/qualification/reference/stripe_resources.py +++ b/qualification/reference/stripe_resources.py @@ -140,7 +140,7 @@ def cleanup(self, journal): 'payment_intent': entry['id'], 'amount': remaining, 'metadata[auths_qualification_cleanup]': run, }, idempotency=key(run, index, 'cleanup-' + str(remaining))) - require(refund.get('status') == 'succeeded' and refund.get('livemode') is False + require(refund.get('status') == 'succeeded' and refund.get('livemode', False) is False and refund.get('payment_intent') == entry['id'], 'qualification.resources.cleanup-refused') fresh = self.api('GET', '/v1/charges/' + charge_id) diff --git a/qualification/reference/tests/test_reference.py b/qualification/reference/tests/test_reference.py index 131639946..676f5c869 100644 --- a/qualification/reference/tests/test_reference.py +++ b/qualification/reference/tests/test_reference.py @@ -67,7 +67,7 @@ def test_native_measurements_refuse_restart_wrap_and_duplicate_hosts(self): def test_fresh_stripe_evidence_checks_state_echo_and_raw_bytes(self): resources, arguments = self.stripe_resources(), self.stripe_arguments() - value = {'id': 're_TEST123', 'object': 'refund', 'livemode': False, + value = {'id': 're_TEST123', 'object': 'refund', 'payment_intent': arguments['payment_intent'], 'amount': arguments['amount'], 'currency': 'usd', 'status': 'succeeded', 'metadata': {'auths_echo': echo(stripe.SERVICE, arguments['operation_id'], COMMITMENT)}} diff --git a/qualification/reference/tests/test_resources.py b/qualification/reference/tests/test_resources.py index 7a739007d..ed2b1975b 100644 --- a/qualification/reference/tests/test_resources.py +++ b/qualification/reference/tests/test_resources.py @@ -62,7 +62,7 @@ def api(self, method, path, fields=None, idempotency=None, runtime=False): self.refunds += 1 charge['amount_refunded'] += fields['amount'] charge['refunded'] = charge['amount_refunded'] == 2000 - return {'status': 'succeeded', 'livemode': False, 'payment_intent': payment['id']} + return {'status': 'succeeded', 'payment_intent': payment['id']} class Airtable: From af34eb6bbe7d51d8d176e53239df1968b444deb8 Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 05:23:14 +0100 Subject: [PATCH 063/108] Retain shipping candidates and the actual disposable resource lifecycle rehearsal --- .github/workflows/recipe-qualification.yml | 57 +++++++++++++++++++ ...NDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md | 2 +- qualification/README.md | 7 +++ qualification/reference/resource_io.py | 8 ++- .../reference/tests/test_resources.py | 15 +++++ .../report.json | 29 ++++++++++ 6 files changed, 116 insertions(+), 2 deletions(-) create mode 100644 qualification/simulation/evidence/provider-resource-lifecycle-2026-10-07/report.json diff --git a/.github/workflows/recipe-qualification.yml b/.github/workflows/recipe-qualification.yml index 51f1846cb..42d871fe5 100644 --- a/.github/workflows/recipe-qualification.yml +++ b/.github/workflows/recipe-qualification.yml @@ -29,6 +29,63 @@ concurrency: cancel-in-progress: false jobs: + candidate: + name: shipping gateway candidate without credentials + runs-on: ubuntu-latest + timeout-minutes: 60 + steps: + - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 + with: + persist-credentials: false + - uses: ./.github/actions/setup-rust-cache + with: + toolchain: 1.97.1 + - name: Build the shipping binaries without simulation features + run: | + cargo build --locked --release -p auths-gateway --bin auths-gateway + cargo build --locked --release -p auths-recipe-qualification-issuance --bin auths-qualification + mkdir -p target/qualification-shipping-candidate/bin + cp target/release/auths-gateway target/release/auths-qualification target/qualification-shipping-candidate/bin/ + - name: Review maintained recipes without installing or leasing custody + run: | + target/release/auths-gateway review \ + --recipe qualification/simulation/live/stripe-platform/recipe.json \ + --profile-lock qualification/simulation/live/stripe-platform/profile.lock.json \ + > target/qualification-shipping-candidate/stripe-review.json + target/release/auths-gateway review \ + --recipe bindings/fixtures/gateway/airtable/recipe.json \ + --profile-lock bindings/fixtures/gateway/airtable/profile.lock.json \ + > target/qualification-shipping-candidate/airtable-review.json + - name: Bind the retained bytes to this source and run + env: + SOURCE_COMMIT: ${{ github.sha }} + SOURCE_RUN: ${{ github.run_id }} + SOURCE_ATTEMPT: ${{ github.run_attempt }} + run: | + python3 - <<'PY' + import hashlib, json, os + from pathlib import Path + root = Path('target/qualification-shipping-candidate') + files = {} + for path in sorted(root.rglob('*')): + if path.is_file(): + files[str(path.relative_to(root))] = hashlib.sha256(path.read_bytes()).hexdigest() + (root / 'candidate.json').write_text(json.dumps({ + 'schema': 'auths.qualification-shipping-candidate/1', + 'source_commit': os.environ['SOURCE_COMMIT'], + 'run_id': os.environ['SOURCE_RUN'], 'run_attempt': os.environ['SOURCE_ATTEMPT'], + 'features': [], 'platform': 'linux-x86_64', + 'qualification_issued': False, 'stable_launch_ready': False, + 'files': files, + }, sort_keys=True, indent=2) + '\n') + PY + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 + with: + name: qualification-shipping-candidate-${{ github.run_id }}-${{ github.run_attempt }} + path: target/qualification-shipping-candidate + if-no-files-found: error + retention-days: 30 + simulation: name: disposable bootstrap and two provider simulations runs-on: ubuntu-latest diff --git a/docs/research/INDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md b/docs/research/INDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md index 7bb0cb0c4..9680d51a8 100644 --- a/docs/research/INDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md +++ b/docs/research/INDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md @@ -13,7 +13,7 @@ audit or real-user trial is claimed. | A live provider response's exact digest cannot be predicted before creating the effect. | Implemented: corpus schema 3 declares a closed evidence source and reviewed subject; fresh provider-response/doctor witnesses must match the candidate digest and actual tuple. All remaining facts stay exact. Closed step observations are retained for the trace scan. | | The production CLI does not expose independently counted custody/transport boundary observations. | Implemented: private process-scoped counters at the actual custody lease call and HTTP execution boundaries, including failures. Commissioning commands return before/after snapshots; ordinary clients cannot reset them. Remote effects still require separate fresh read-back. | | Stripe Refund objects were incorrectly assumed to carry `livemode`. | Corrected against the provider API: require the exact test PaymentIntent/Charge and run marker; validate the refund's binding/success. Synthetic responses now follow the real object shape. Local resource rehearsal exposed this before protected qualification. | -| Disposable setup could leak resources after a lost creation response. | Implemented run-specific durable preparation journals, Stripe idempotent recovery and Airtable exact ownership discovery. Cleanup requires fresh ownership/state checks and leaves unrelated resources alone. Protected family orchestration still needs integration. | +| Disposable setup could leak resources after a lost creation response. | Implemented run-specific durable preparation journals, Stripe idempotent recovery and Airtable exact ownership discovery. Cleanup requires fresh ownership/state checks and leaves unrelated resources alone. Local Docker CLI rehearsal passed for one actual test payment and one actual record; cleanup confirmed both retired. Public rehearsal report is retained under `qualification/simulation/evidence/provider-resource-lifecycle-2026-10-07`. Protected family orchestration still needs integration. | | Existing AWS roles trust the `gateway-custody-live` environment, while the qualification template names separate family environments. | Inspected the existing reviewer-protected custody environment. Its branch policy is currently unset. Automatic approval review rejected tightening that shared environment and uploading local provider credentials there because that destination was not explicitly authorized. No environment change or provider-key upload occurred; protected orchestration remains pending. No role trust or gate is weakened. | | Main-only protected code must be deployed before the first protected qualification run. | A bounded prerequisite rollout of the completed runner is needed before collecting evidence. Epic acceptance stays open until actual runs, signed closure and CI are complete. | diff --git a/qualification/README.md b/qualification/README.md index 6323fdc82..aee3592d0 100644 --- a/qualification/README.md +++ b/qualification/README.md @@ -269,3 +269,10 @@ witnesses, mismatched subjects/digests and extra fields fail closed. The runner retains closed actual observations under `scan/trace`, separately from the pass reports. They contain no provider body or secret and undergo the existing protected redaction scan before export. + +The credential-free `candidate` job builds and retains the actual shipping +Linux gateway and issuer without simulation features, even before a protected +family corpus is admitted. Its manifest binds exact file hashes, source commit +and workflow run. Native read-only recipe review exercises both maintained +recipes; no installation, custody lease or qualification is claimed. This +artifact is a candidate for operator inspection, not a GitHub release. diff --git a/qualification/reference/resource_io.py b/qualification/reference/resource_io.py index 2f9eb1ac5..aa8999530 100644 --- a/qualification/reference/resource_io.py +++ b/qualification/reference/resource_io.py @@ -106,6 +106,12 @@ def write(path, value, *, new=False): def finish(command): try: command() - except (Refusal, ValueError, OSError): + except Refusal as error: + code = str(error) + if not re.fullmatch(r'qualification\.[a-z0-9.-]{1,128}', code): + code = 'qualification.resources.refused' + print(code, file=sys.stderr) + raise SystemExit(1) from None + except (ValueError, OSError): print('qualification.resources.refused', file=sys.stderr) raise SystemExit(1) from None diff --git a/qualification/reference/tests/test_resources.py b/qualification/reference/tests/test_resources.py index ed2b1975b..c9abbf523 100644 --- a/qualification/reference/tests/test_resources.py +++ b/qualification/reference/tests/test_resources.py @@ -1,6 +1,8 @@ """Disposable setup recovery and ownership boundaries; synthetic providers only.""" import copy +import contextlib +import io import json import os from pathlib import Path @@ -168,6 +170,19 @@ def test_airtable_changed_ownership_and_duplicate_names_cannot_qualify(self): resources.cleanup(work / 'journal.json') self.assertEqual(set(provider.records), {'recUNRELATED00001'}) + def test_cli_reports_closed_domain_codes_without_external_exception_text(self): + for error, expected in [(Refusal('qualification.resources.payment-binding'), + 'qualification.resources.payment-binding'), + (ValueError('synthetic-sensitive-external-detail'), + 'qualification.resources.refused'), + (Refusal('synthetic-sensitive-external-detail'), + 'qualification.resources.refused')]: + def fail(): raise error + output = io.StringIO() + with contextlib.redirect_stderr(output), self.assertRaises(SystemExit): + resource_io.finish(fail) + self.assertEqual(output.getvalue().strip(), expected) + def test_ledger_outputs_refuse_symlinks_public_directories_and_overwrite(self): work = self.workspace() target = work / 'target.json' diff --git a/qualification/simulation/evidence/provider-resource-lifecycle-2026-10-07/report.json b/qualification/simulation/evidence/provider-resource-lifecycle-2026-10-07/report.json new file mode 100644 index 000000000..22f00f5b4 --- /dev/null +++ b/qualification/simulation/evidence/provider-resource-lifecycle-2026-10-07/report.json @@ -0,0 +1,29 @@ +{ + "deployment": "local-docker", + "production_gateway_exercised": false, + "protected_qualification": false, + "public_ledger_digests": { + "airtable/journal.json": "2914cc695d8d91b9dc9ca8d9e8564dfbeaf75c3aa47639f7441e89ca273ae98e", + "airtable/resources.json": "8cce10dc03cd6e2f4cf0113b6a834b4729e891ef3e0506f8d58ec27cb0c5917a", + "stripe/journal.json": "643efc1d141ebb761dde62d1dbca3d7e1ddd0ea373510ec200e6102bebf61db5", + "stripe/resources.json": "893a0159b8bd9c618d0991194a51df4b26e00641d734382166dfe178d4cacd0e" + }, + "results": [ + { + "family": "stripe", + "prepared": 1, + "protected_qualification": false, + "retired": true + }, + { + "family": "airtable", + "prepared": 1, + "protected_qualification": false, + "retired": true + } + ], + "schema": "auths.provider-resource-lifecycle-rehearsal/1", + "scope": "operator-resource-rehearsal/1791346245/1", + "source_commit": "632e2791504bd92d33832a7e6b582f57d7c2f5b6", + "stable_launch_ready": false +} From bbd9b5da7590901579f075e53b5d66fcde835aa5 Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 05:30:57 +0100 Subject: [PATCH 064/108] Keep offline differential verification credential-free and update measured scenario fixtures --- compliance.toml | 1 + ...gateway-polish-and-recipe-qualification.md | 11 ++++ .../src/execution.rs | 23 ++++++-- .../tests/common/mod.rs | 6 +- .../tests/execution.rs | 58 +++++++++++++++++++ .../auths-gateway/semantic-closure.json | 2 +- .../auths-gateway/src/scenario_tests.rs | 9 ++- .../auths-gateway/src/semantic_closure.rs | 2 +- qualification/README.md | 9 +++ release/semantic-freeze-versions.toml | 8 +-- release/semantic-freeze.json | 14 ++--- 11 files changed, 121 insertions(+), 22 deletions(-) diff --git a/compliance.toml b/compliance.toml index 890ac6c2d..103cb33fe 100644 --- a/compliance.toml +++ b/compliance.toml @@ -1229,6 +1229,7 @@ proof-author-or-assembler = [ "product/qualification/auths-recipe-qualification-issuance/tests/execution.rs#production_readiness_requires_a_read_only_live_probe_on_a_production_target", "product/qualification/auths-recipe-qualification-issuance/tests/execution.rs#commissioning_client_refusal_cannot_replace_an_ordinary_installed_effect", "product/qualification/auths-recipe-qualification-issuance/tests/execution.rs#fresh_evidence_is_closed_to_the_reviewed_subject_and_exact_candidate_digest", + "product/qualification/auths-recipe-qualification-issuance/tests/execution.rs#offline_differential_requires_native_review_without_custody_or_provider_entry", "product/qualification/auths-recipe-qualification-issuance/tests/execution.rs#a_dynamic_doctor_witness_must_match_the_actual_production_tuple", "product/qualification/auths-recipe-qualification-issuance/tests/execution.rs#replay_can_complete_an_unresolved_read_back_but_never_write_or_reacquire_after_observation", "product/qualification/auths-recipe-qualification-issuance/tests/execution.rs#observed_faults_and_changed_candidates_produce_no_passing_case", diff --git a/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md b/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md index 956c28135..70ff8040d 100644 --- a/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md +++ b/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md @@ -1817,3 +1817,14 @@ the subsequent phase can establish. Both scopes belong to the same reviewed manifest and exact tuple. This closes the second dependency cycle without opening ordinary application leases under a commissioning permit. The protected workflow and family corpora still must execute this sequence. + +#### 22.6 Credential-free differential review + +Offline `oracle-accepts` / `oracle-rejects` cases execute the reviewed pure +oracle followed by `review`, the candidate's native `review-submission` command. +They compare exact proof/action verdict and closed request commitments with +zero custody leases, provider entries and read-back confirmations. A permitted +mapping is `complete`, without an HTTP response or effect claim. `review` is +refused as a protected operation or a replacement for an application submission. +First commissioning therefore depends on offline native verification, without +requiring pre-existing qualification to collect that verification. diff --git a/product/qualification/auths-recipe-qualification-issuance/src/execution.rs b/product/qualification/auths-recipe-qualification-issuance/src/execution.rs index 4b0537925..1dc21ff9b 100644 --- a/product/qualification/auths-recipe-qualification-issuance/src/execution.rs +++ b/product/qualification/auths-recipe-qualification-issuance/src/execution.rs @@ -38,6 +38,8 @@ pub enum RunPhase { pub enum Operation { /// Evaluate the family's pure request/evidence oracle. Oracle, + /// Credential-free native proof/request review, only in offline differential cases. + Review, /// Submit through the candidate gateway's application socket. Submit, /// Replay the same logical operation, possibly with a fresh challenge. @@ -260,7 +262,7 @@ impl RunCase { _ => false, }; let required = match self.scenario { - S::OracleAccepts | S::OracleRejects => before(Op::Oracle, Op::Submit), + S::OracleAccepts | S::OracleRejects => before(Op::Oracle, Op::Review), S::ProofReplay | S::FreshChallengeReplay => before(Op::Submit, Op::Replay), S::TwoInstanceRace => has(Op::Race), S::Restart => before(Op::Submit, Op::Restart) && before(Op::Restart, Op::Replay), @@ -305,11 +307,24 @@ impl RunCase { ); if !harness_scenario(self.scenario) || self.steps.iter().any(|step| !step.valid_comparison(self)) + || self.steps.iter().any(|step| { + matches!(step.operation, Op::Oracle | Op::Review) + && (step.expected.credential_leases != 0 + || step.expected.provider_entries != 0 + || step.expected.confirmed_by_read_back != 0 + || !matches!( + step.expected.verdict.outcome, + RunOutcome::Complete | RunOutcome::Refused + )) + }) || !required || self.steps.is_empty() || self.steps.len() > MAX_CASE_STEPS || (live_only && self.phase == RunPhase::Offline) || (has(Op::Oracle) && self.phase != RunPhase::Offline) + || (has(Op::Review) + && (self.phase != RunPhase::Offline + || !matches!(self.scenario, S::OracleAccepts | S::OracleRejects))) || self .capabilities .iter() @@ -367,14 +382,14 @@ impl RunCase { || (actual.observed.confirmed_by_read_back > 0 && (actual.observed.verdict.outcome != RunOutcome::Observed || actual.observed.verdict.evidence_sha256.is_none())) - || (step.operation == Operation::Oracle + || (matches!(step.operation, Operation::Oracle | Operation::Review) && (actual.observed.credential_leases != 0 || actual.observed.provider_entries != 0 || actual.observed.confirmed_by_read_back != 0)) { return Err(IssuanceError::CaseFailed); } - if step.operation != Operation::Oracle { + if !matches!(step.operation, Operation::Oracle | Operation::Review) { effects.entered = effects .entered .checked_add(actual.observed.provider_entries) @@ -501,7 +516,7 @@ impl RunCase { .map(|(_, actual)| &actual.verdict) }; let oracle = verdict(Operation::Oracle).ok_or(IssuanceError::CaseFailed)?; - if Some(oracle) != verdict(Operation::Submit) + if Some(oracle) != verdict(Operation::Review) || (oracle.outcome == RunOutcome::Refused) != (self.scenario == S::OracleRejects) || (self.scenario == S::OracleAccepts && oracle.request_sha256.is_none()) { diff --git a/product/qualification/auths-recipe-qualification-issuance/tests/common/mod.rs b/product/qualification/auths-recipe-qualification-issuance/tests/common/mod.rs index fcff4af69..cce1734cc 100644 --- a/product/qualification/auths-recipe-qualification-issuance/tests/common/mod.rs +++ b/product/qualification/auths-recipe-qualification-issuance/tests/common/mod.rs @@ -153,12 +153,12 @@ pub fn executable_corpus() -> auths_recipe_qualification_issuance::execution::Ru } let mut steps = match scenario { Scenario::OracleAccepts => vec![ - step(Op::Oracle, Outcome::ResponseRecorded, 0, 0), - step(Op::Submit, Outcome::ResponseRecorded, 1, 0), + step(Op::Oracle, Outcome::Complete, 0, 0), + step(Op::Review, Outcome::Complete, 0, 0), ], Scenario::OracleRejects => vec![ step(Op::Oracle, Outcome::Refused, 0, 0), - step(Op::Submit, Outcome::Refused, 0, 0), + step(Op::Review, Outcome::Refused, 0, 0), ], Scenario::ProofReplay | Scenario::FreshChallengeReplay => vec![ step(Op::Submit, Outcome::ResponseRecorded, 1, 0), diff --git a/product/qualification/auths-recipe-qualification-issuance/tests/execution.rs b/product/qualification/auths-recipe-qualification-issuance/tests/execution.rs index 498d98bf0..1725d381c 100644 --- a/product/qualification/auths-recipe-qualification-issuance/tests/execution.rs +++ b/product/qualification/auths-recipe-qualification-issuance/tests/execution.rs @@ -507,3 +507,61 @@ fn a_dynamic_doctor_witness_must_match_the_actual_production_tuple() { case.phase = RunPhase::Commissioning; assert!(run(&case, |_, actual| set(actual)).is_err()); } + +#[test] +fn offline_differential_requires_native_review_without_custody_or_provider_entry() { + use auths_recipe_qualification_issuance::execution::{Operation, RunPhase}; + for scenario in [Scenario::OracleAccepts, Scenario::OracleRejects] { + let case = executable_corpus() + .cases + .into_iter() + .find(|case| case.scenario == scenario) + .expect("differential case"); + assert_eq!(case.steps[1].operation, Operation::Review); + assert_eq!( + run(&case, |_, _| {}).expect("read-only comparison").entered, + 0 + ); + let mut impossible = case.clone(); + impossible.steps[1].expected.credential_leases = 1; + let mut invoked = false; + assert!( + impossible + .execute(&tuple(), |_, _| { + invoked = true; + Err(IssuanceError::CaseFailed) + }) + .is_err() + ); + assert!(!invoked, "invalid corpus must not start the harness"); + let mut old_submission = case.clone(); + old_submission.steps[1].operation = Operation::Submit; + assert!(run(&old_submission, |_, _| {}).is_err()); + for index in 0..3 { + assert!( + run(&case, |step, actual| { + if step == 1 { + match index { + 0 => actual.observed.credential_leases = 1, + 1 => actual.observed.provider_entries = 1, + _ => actual.observed.confirmed_by_read_back = 1, + } + } + }) + .is_err() + ); + } + let mut protected = case.clone(); + protected.phase = RunPhase::Commissioning; + let mut invoked = false; + assert!( + protected + .execute(&tuple(), |_, _| { + invoked = true; + Err(IssuanceError::CaseFailed) + }) + .is_err() + ); + assert!(!invoked); + } +} diff --git a/product/runtime/auths-gateway/semantic-closure.json b/product/runtime/auths-gateway/semantic-closure.json index eef0bbdfa..4831ba22a 100644 --- a/product/runtime/auths-gateway/semantic-closure.json +++ b/product/runtime/auths-gateway/semantic-closure.json @@ -1 +1 @@ -{"files":[{"path":"Cargo.lock","sha256":"0e75e2fdef44e79e57797ac6661295ae58ddb8de4a1990a6fd22ce6c54f78604"},{"path":"Cargo.toml","sha256":"6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24"},{"path":"core/adapters/auths-did-keri/Cargo.toml","sha256":"86ba3e3f9a0a70d970568bfb3113b7ba7bbdd81c3eebbb52743dd574a0c0ecaa"},{"path":"core/adapters/auths-did-keri/src/lib.rs","sha256":"a75674842f8a7142004369ccd206ab43e476459293f0ff4bed4d4e659031b3e3"},{"path":"core/adapters/auths-did-key/Cargo.toml","sha256":"d5a3ae07ecde83f91eed4c3785051dd0f44eab6c891754f3309b6b40596707d7"},{"path":"core/adapters/auths-did-key/src/lib.rs","sha256":"b76a3f4528a725df53cfa9242e6e414e1d26caa48468aaed497e28b121f4497c"},{"path":"core/adapters/auths-raw-key/Cargo.toml","sha256":"f49616bc18c19e6aaa7e6a02ccebcdb9f5c1422c1278ef9869e0dbf22ceda7be"},{"path":"core/adapters/auths-raw-key/src/lib.rs","sha256":"45eec1b295dac3bed65cd79c942870b926b06b3f5d38eaebaeb6140ac69315fa"},{"path":"core/crates/auths-algebra-kernel/Cargo.toml","sha256":"0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba"},{"path":"core/crates/auths-algebra-kernel/src/generated.rs","sha256":"ae4bcbef42a408c7ffa0c6a74a42f7de177a6f14479e51d205acf830bda05960"},{"path":"core/crates/auths-algebra-kernel/src/lib.rs","sha256":"6654667eeb9b353d6648954c9fd2e8838462a82ce6b2803eb49e1366892c68c6"},{"path":"core/crates/auths-assurance/Cargo.toml","sha256":"afcb12a97ddd09d7a264b9ecd3fcaefc865ff2c9b4539ee85b00883420ba333a"},{"path":"core/crates/auths-assurance/src/lib.rs","sha256":"0fb2ec844d674b25a9e20b1601452c89c2454901fa506adfa9bb38ef9a7fa213"},{"path":"core/crates/auths-author/Cargo.toml","sha256":"1e6f0e3bc079ddb558decf0db26b291c6e72fc47327b6df1b7650d41689b215f"},{"path":"core/crates/auths-author/src/lib.rs","sha256":"e14475f2f49715a1869d5fa6b11ff1fbb72497e39097e09f833b0bae7e5b3f2b"},{"path":"core/crates/auths-author/src/observations.rs","sha256":"dda7d6bfa6f4bd7e95a480ca283c2c0e996f69c5c15cb0c7197af328131a7066"},{"path":"core/crates/auths-authority/Cargo.toml","sha256":"4f68212938029f79ebd857b4f3038494eb85d0163d49f07e51376715cf959815"},{"path":"core/crates/auths-authority/src/lib.rs","sha256":"da88d5194de4e17449e69972c0fb042afa3c39798a8f570f30771e77c384f1eb"},{"path":"core/crates/auths-codec/Cargo.toml","sha256":"e20e51826e17814effd9d8925d18d5fbdd6c0d37bf50231e743ec2611314722c"},{"path":"core/crates/auths-codec/src/approval.rs","sha256":"fbff43bf4d57f69f8b7738a8647751cde75c5a932dee65d924a1fe9c7202f91f"},{"path":"core/crates/auths-codec/src/bounded_policy.rs","sha256":"d21f6728be2d8a04b6d94921f2b683f7e61cbb42e0ac6866f1c88a49caa534c3"},{"path":"core/crates/auths-codec/src/decode.rs","sha256":"ba2999584cdf53b1b517ecb9c7ea50d39efee17c666a9a38e2ad1ac94379f778"},{"path":"core/crates/auths-codec/src/encode.rs","sha256":"8491192053e2e15d62b4d2a491de22405b7487ead69ab6f6bca40669ce7ca5f7"},{"path":"core/crates/auths-codec/src/error.rs","sha256":"fecb0737c16deb42d859f1dc7727c698438d9ac12064fd99e0024629642c390c"},{"path":"core/crates/auths-codec/src/hash.rs","sha256":"f88e111f1dbb2cef6b7b5e9c948cb45ff92e366710c8a5f5c636138aa748479e"},{"path":"core/crates/auths-codec/src/lib.rs","sha256":"3b0e5c94c6f34f750b88a9333e1d5c8145746d845d3a23e0d2f61807cf592ea7"},{"path":"core/crates/auths-codec/src/observation.rs","sha256":"38328b0c71ff97a4196eeade8b4faa889527ff1f80bb168468bcd49082a3987e"},{"path":"core/crates/auths-composition/Cargo.toml","sha256":"331e13025eb82588b5269ed3975929eb41c823d588c49e4c296273d85c6fe80e"},{"path":"core/crates/auths-composition/src/lib.rs","sha256":"e42e3b0b6a9985b73c533aeb23799c638979aa27a9ce7d0f10a8d60340570fb1"},{"path":"core/crates/auths-model/Cargo.toml","sha256":"565c15302b0cc9270db1e28efa3862804846850ba933cc17aea8abcec4a65987"},{"path":"core/crates/auths-model/src/approval.rs","sha256":"54cf44a9ef747ec21546a4086aecfb130bc7803b0d646430e6082df51e6e305f"},{"path":"core/crates/auths-model/src/bounded.rs","sha256":"f90496abc0a06c028b4d850af6ddab7d850bfafeaa3d042f1b1246a41d8bbbc9"},{"path":"core/crates/auths-model/src/bounded_policy.rs","sha256":"306a8f049cc7cfc7635fe0e4de47eb7813eed63d3c14c3be2b51586aa4eea450"},{"path":"core/crates/auths-model/src/lib.rs","sha256":"e7cfe6bb9574c6b016aa63e70658c31e0b90903ec6479a49f4a2ceb64f5bad97"},{"path":"core/crates/auths-model/src/observation.rs","sha256":"b3ed3e3cc090afca2896a7d3de7988afccc1ee1ea0ebd91b51a8bc0f20ad8dbb"},{"path":"core/crates/auths-multikey/Cargo.toml","sha256":"858756c1197befcada06134742bffe8d58cf674cadd6c046bf710570e96efaf2"},{"path":"core/crates/auths-multikey/src/lib.rs","sha256":"f5177fffb11e40eeaaa665ba886c541fc1f24d5eacdd6983fb03dc20148733f0"},{"path":"core/crates/auths-ports/Cargo.toml","sha256":"596a9b0f5af3717c16a6d13f7054d8a106bcd9f01f5f72c2235dd2afcf0ab16c"},{"path":"core/crates/auths-ports/src/binding.rs","sha256":"a16c012d40aa4249e3ec54372b9611006d0bfe8c7dc3c741911c2194ad17736d"},{"path":"core/crates/auths-ports/src/diagnostics.rs","sha256":"aa596572503b5a65a918bb2ff38281c144ff53821ee914e9325c852828d852df"},{"path":"core/crates/auths-ports/src/lib.rs","sha256":"8da1debf86f9532df0660155d04298beb1ba3a1204508f8586e2e67cd2fb3449"},{"path":"core/crates/auths-ports/src/path.rs","sha256":"b68fc547b4e4d97a60cbbc1cc1939fc6b34a8233b81f840bd396914a707e3ea1"},{"path":"core/crates/auths-raw-key-core/Cargo.toml","sha256":"98c0bc8527a537512e43a74dd6ba9658c6f0cdc16610cf938e3f9b43785d836d"},{"path":"core/crates/auths-raw-key-core/src/lib.rs","sha256":"98c0500c41697aae28708ad0bf970b9a97583d96a3d2c18d23e7fa351e0f7d12"},{"path":"core/crates/auths-registries/Cargo.toml","sha256":"590e49e58b0622d9d6274fea46796dcdb07dec9550eff295cce6a6427ffa51e2"},{"path":"core/crates/auths-registries/src/lib.rs","sha256":"450d3886d85ee333b7e046317fb5b47cde62483d5f3e41d46265e2caf4c373ec"},{"path":"core/crates/auths-registries/src/template.rs","sha256":"1224039dd2b3ce6fa8357613d8cafbae40400493da7176da202b9ade62fa05e4"},{"path":"core/crates/auths-signature-core/Cargo.toml","sha256":"6bee2230eb30af1be0bd5c2d57bd3e1903497a70028d47290d4ac6e9e0e8bca0"},{"path":"core/crates/auths-signature-core/src/lib.rs","sha256":"6e3f9311ded5e49ea50d445eb21e6d8fa12442aa4362a73e0cb6fda15b7cd865"},{"path":"core/crates/auths-signature/Cargo.toml","sha256":"7f7b5682466ba439d8c59579022cb61068cad9fb4bd2d73e1cc21327c902b450"},{"path":"core/crates/auths-signature/src/lib.rs","sha256":"b3d9ac4cc3ba0797b9e1c09f2d6ac05089b25dac4e285a5af28c0165b33d925b"},{"path":"core/crates/auths-verifier/Cargo.toml","sha256":"c43358e06a33324b41a8b93e5cc7279c55f7d21f1f6cfaa539a3fc7b4c27a38f"},{"path":"core/crates/auths-verifier/src/approval.rs","sha256":"c3cae6a49e169051eb555bb092b1069a4d422516d6a2114623a89e5f31ff923f"},{"path":"core/crates/auths-verifier/src/causal.rs","sha256":"9635230f33b13a263573d319ac8a1976addbcc07677514a43e3c7bf28dc04587"},{"path":"core/crates/auths-verifier/src/lib.rs","sha256":"f22dec38dfa47ced8da4f605390da8453273bee1da010f57fd1fdfcb10e0b389"},{"path":"core/crates/auths-verifier/src/observation.rs","sha256":"0bb07f06a0f9524c88427df1c972b1de8ba038a9eeeb15d3134c25125ae84b1e"},{"path":"core/crates/auths-verifier/src/trace.rs","sha256":"2213d72023a1d9e0413a2cf2c51c3dad9e04775d86033a0caaa9d29a8f0036f8"},{"path":"exchange/crates/auths-proof-exchange-model/Cargo.toml","sha256":"34b2db64f93a288e942b5a3918d28cdcbef906e0dc9074ce848018d3d5f7a1fa"},{"path":"exchange/crates/auths-proof-exchange-model/src/lib.rs","sha256":"49fac5aff2339d3a57c41cb8bb2a82852538e8f77ecc4b157c88e264ff31fb55"},{"path":"exchange/crates/auths-proof-exchange-port/Cargo.toml","sha256":"7ff660f1b7579dc570c791090aeb450404fbbf44c92781e289f5ccdde746d739"},{"path":"exchange/crates/auths-proof-exchange-port/src/lib.rs","sha256":"b408fb40c6432edc1facb3d8b3e9433a033f8dc73fe2e0ba5a88c972ca675021"},{"path":"product/config/auths-config/Cargo.toml","sha256":"e4b568ab9f6d84f7d7e6d66443fe825f360db9c27bc7c31d6ddc0647ba3ab304"},{"path":"product/config/auths-config/src/lib.rs","sha256":"fecf00ea65cef9018fda9af2063326d7065b869266d0d9e73a4f06816f1102cc"},{"path":"product/errors/auths-errors/Cargo.toml","sha256":"3b3a199b6460ba75bda84475bb5accd35e1485448a3981038db85bf4772dd350"},{"path":"product/errors/auths-errors/src/lib.rs","sha256":"7feeb9069fa4003f94f1f07c1c94619cf1c883e0dbaaf2187f04d0f742264bdd"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/Cargo.toml","sha256":"716f1f2a117d6d69d8effe9ee9057e24ba3502f20af6a602b06facb638cdabed"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/api.rs","sha256":"9ea61dd7ddd93282b073b98e453e6b75b26dc49689c04e9782435d06a3a09e48"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/clock.rs","sha256":"73f0a6e0f5903883329fa6683f5888288f759512ac69e5c87efd2b6b87f7d79f"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/http.rs","sha256":"14c1fce14e24c984b2a275563a29b6326fb08367922b6e8d37ba38b9cb81aa2b"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/identity.rs","sha256":"186de11230c8b33375951c4368609f8976bf9795f171af3fd7fac26207a94361"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs","sha256":"0b4617d044f5254a5ab22f5a2578f91cc025206a8c1845be39c1c56dcdf7a5df"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/names.rs","sha256":"41bb23572d6002e23ee103d6fe70ecd68764861c6f2e48a1c53af998270a4afa"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs","sha256":"39fed883f4802e68d3b41a68fea0aba0737810996b33d13577de70faba004c29"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/store.rs","sha256":"fc60ee9c49b2f4f063c449b4c78100c5c4872779e94ca168f796603b380ef6e4"},{"path":"product/integrations/auths-custody/Cargo.toml","sha256":"1e14034185ad1ec24a977fd5f41d0abee219606245c046ce2a82287fadef448b"},{"path":"product/integrations/auths-custody/src/conformance.rs","sha256":"8ed1afd58f18fc6becc268908aa6419c9aa404c79da0197963eb2599df44acf6"},{"path":"product/integrations/auths-custody/src/key.rs","sha256":"70cbb0fd21b6f5652157845a22c35be2d0f6c05b3d138fc4b9bb6dbdc3d81c40"},{"path":"product/integrations/auths-custody/src/lib.rs","sha256":"8ee593c1f59b0fd2126bdda9138026f5bc531beb64d4489a99785842e7b98b43"},{"path":"product/operations/auths-operations/Cargo.toml","sha256":"73dde1e914ba5e1386f8d49c0d730423cc72ae77ec44c6554a6a75cc8e8922b1"},{"path":"product/operations/auths-operations/src/explanation.rs","sha256":"b4a39bcbd5712cb9e735ee7deeb281f3fa6af5ddca973735bf3d87dce427ef11"},{"path":"product/operations/auths-operations/src/lib.rs","sha256":"3f401a56555113b98f57bca172a2660eaecedf76247b83a3fdbb089c133a29cd"},{"path":"product/operations/auths-operations/src/render/json.rs","sha256":"2ae042639960afee123730e945d373bc5dda1d2b3af20ae16c939a7e99b9e418"},{"path":"product/operations/auths-operations/src/render/mod.rs","sha256":"b3b7f6fe473f49227ace5a68bfc3d8dc14b5db8dd9888fd9e207070337b1b8bf"},{"path":"product/operations/auths-operations/src/render/text.rs","sha256":"f216cf3bdb00e264523271b16e7059535ac6b1aabf271cebd7935af155e4bfec"},{"path":"product/policy/auths-bounded-policy/Cargo.toml","sha256":"babd5d200923137ead71d8c2528f847cea323ce98da942a1320b054436612c47"},{"path":"product/policy/auths-bounded-policy/src/arithmetic.rs","sha256":"75e43c5d4eab8d1f71c1daf53839f5f9fe45a400afc1f63a30c6f55ce3632627"},{"path":"product/policy/auths-bounded-policy/src/commitment.rs","sha256":"c5706f2d583454e1a7f570f7ada138d4d864bef0205dfae7c1296774f396bb3f"},{"path":"product/policy/auths-bounded-policy/src/eligibility.rs","sha256":"c9acdfb793074e687fc36efad506be27dbd99ffbf40387bc66c8de39ef238432"},{"path":"product/policy/auths-bounded-policy/src/identifier.rs","sha256":"0006a32bae9eb16c4178cf797df418d2b0a781f2bc6474b741dc1a908141831c"},{"path":"product/policy/auths-bounded-policy/src/kernel.rs","sha256":"99187c28b161ac70bee1afed60711f7f645adb4d1671a01863f9849b369811d5"},{"path":"product/policy/auths-bounded-policy/src/lib.rs","sha256":"76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c"},{"path":"product/policy/auths-bounded-policy/src/receipt.rs","sha256":"3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad"},{"path":"product/policy/auths-bounded-policy/src/registry.rs","sha256":"4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0"},{"path":"product/profiles/auths-profile-api/Cargo.toml","sha256":"7ae85761f58625b5d678f961fd052eebf3e000ef565c7312e3ac857763c0017f"},{"path":"product/profiles/auths-profile-api/src/lib.rs","sha256":"a194b82b20bf8aa864c2334ef6c6aec30b2154ded972862252d5dcefa488ab95"},{"path":"product/profiles/auths-profile-mcp/Cargo.toml","sha256":"db264fc25242f7b7e4133cbe5782545b3107b406c87168ae072683cfb59eac66"},{"path":"product/profiles/auths-profile-mcp/src/arguments.rs","sha256":"a5de696586d507e2aee4a49fee99ef1ef4c51a2e46603f8838f1af6d9009833f"},{"path":"product/profiles/auths-profile-mcp/src/lib.rs","sha256":"d0f8b733a09ef8408336cdebc8948d6a5861012ce6878598b11be7084dfd4280"},{"path":"product/profiles/auths-profile-mcp/src/session.rs","sha256":"166c281fa66333388e4760d6098dad02d3359e1d5de4b8f93312c014f97abb03"},{"path":"product/qualification/auths-recipe-qualification/Cargo.toml","sha256":"b7b15b30b9a3d96d4f089d514266d3a892de6608d30707aa44be31cca89ca9fe"},{"path":"product/qualification/auths-recipe-qualification/src/canonical.rs","sha256":"30a9b50777f0dcb4b606abfee2467d5a975d9f6ad941ab6c13ca3df5b359f667"},{"path":"product/qualification/auths-recipe-qualification/src/closure.rs","sha256":"0ad6aee9bd981e2863fa725f209ec84031db2ff12f4c7ac3aaf5120f0bb86039"},{"path":"product/qualification/auths-recipe-qualification/src/commissioning.rs","sha256":"66ea49f96887c4642139a48d259c270816e2267ee8cf6344a1340fe47afda9da"},{"path":"product/qualification/auths-recipe-qualification/src/commissioning/tests.rs","sha256":"5a226725c2ad7ce920d0bd62d427185e007f4d0949b0f0ec1260aa161d3114d0"},{"path":"product/qualification/auths-recipe-qualification/src/error.rs","sha256":"52d5cf720a1e4579008fdda90a3ac2c31f0b8db57985f121f65e54b4da2b7dd1"},{"path":"product/qualification/auths-recipe-qualification/src/evidence.rs","sha256":"ba45a7409d67a8af26ab811af306412014557477a101ab2a8eb0faf8f2bd4b91"},{"path":"product/qualification/auths-recipe-qualification/src/ids.rs","sha256":"e81a906d571497ab2da753e1532d4443706410e0b75fdd59a7d2d788c7aec403"},{"path":"product/qualification/auths-recipe-qualification/src/launch.rs","sha256":"41f2e2de90e1e7d6440a66eda3eb9bea8d5e0741bc232305a76a363ab5f813c1"},{"path":"product/qualification/auths-recipe-qualification/src/lib.rs","sha256":"7d26c5bfe9769daebf90c5c2280e0d75742e4cc70d0e608408e0665e3f516a2b"},{"path":"product/qualification/auths-recipe-qualification/src/model.rs","sha256":"3484eb0ec287b23d4682ade7b1b0f8d1335985b3fb180f06fc28716076957d5f"},{"path":"product/qualification/auths-recipe-qualification/src/release.rs","sha256":"ec478e53f70052e566aac7e15be2f9e1b1cd46837ac6990ae955fa864d311586"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/mod.rs","sha256":"fa23a962fd90331152eed5edbcdf271955f7aed79b8da1e065bfe69a20b487a9"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/schemas.rs","sha256":"c59feec2805621f341a90f81fc005e2c12f7a70f9d264fdeacccb2be4fe1c046"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/verification.rs","sha256":"6a6b5834c5dae10af1ba8939b2deae43b85db71544dc8f077ff63b7fe68ac8a8"},{"path":"product/qualification/auths-recipe-qualification/src/verify.rs","sha256":"2ec2784435d11e07295de77b2ee1b2c48b2fcf9609a00454c6e7374b621aed5c"},{"path":"product/receipts/auths-receipts/Cargo.toml","sha256":"6001fa1375899953aafcb07c23a6da0c8f57ea7ec08bb9c950b12a60a8cc6f0f"},{"path":"product/receipts/auths-receipts/src/disclosure.rs","sha256":"ba9ed439be0a320c8a01f5b6e9b51361c1a37e076947490d8e4a484ba6bb119c"},{"path":"product/receipts/auths-receipts/src/lib.rs","sha256":"547a57c4160256719cafb7d0ab972d9fc80b0da14fbbce4148c70c414070ff36"},{"path":"product/runtime/auths-connections/Cargo.toml","sha256":"babeb6e1dda3dfb66291713ce1e43dce5c349833d0b50ea4dccbf986030026b2"},{"path":"product/runtime/auths-connections/src/credential.rs","sha256":"82921413bb053f0f6c7931fbd4e6a86c8cc1d8c6b51debd9c2cef33a8d5b1c51"},{"path":"product/runtime/auths-connections/src/kernel.rs","sha256":"a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8"},{"path":"product/runtime/auths-connections/src/lib.rs","sha256":"79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22"},{"path":"product/runtime/auths-connections/src/model.rs","sha256":"de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77"},{"path":"product/runtime/auths-connections/src/registry.rs","sha256":"e57640e003e72ad3235c567c2bb944a262bd64e673f023b62ea091094cc7e946"},{"path":"product/runtime/auths-gateway-kernel/Cargo.toml","sha256":"34f864e67656af4ac7e5c7a347a23f01fc8ab31365b8e23c0ef474483b14a183"},{"path":"product/runtime/auths-gateway-kernel/src/construct.rs","sha256":"e9d65744bae273d65face4285e5d2da75c06a92ab48f7b8333d496604e31c63c"},{"path":"product/runtime/auths-gateway-kernel/src/lib.rs","sha256":"cfda6f8453426564c085475f183b6f790b438768a19668f1b65d33ba59dc8632"},{"path":"product/runtime/auths-gateway-kernel/src/order.rs","sha256":"e0045f877c4b7fe3860c291039853885064ddcdebba7c9b345ab65e81e646dda"},{"path":"product/runtime/auths-gateway-kernel/src/outcome.rs","sha256":"e9785b1afe70788c89b51b18655bcd5acff7b0c8e3d12fb79c6f05a202e67e6b"},{"path":"product/runtime/auths-gateway-kernel/src/ratio.rs","sha256":"7ace22264812e6fc1ef3a62afee402cf43494bb71ae0d3de219ad1b39d690bcb"},{"path":"product/runtime/auths-gateway-kernel/src/recovery.rs","sha256":"9f46dcd1685ab6e4d1ba04a3fc286a9f3afee8fb47829be1fbc670a7926a2dc6"},{"path":"product/runtime/auths-gateway-kernel/src/transition.rs","sha256":"cefb8f01d915880f6921f2501ff881ad94b9de61072c34d9cd19220992f97374"},{"path":"product/runtime/auths-gateway/Cargo.toml","sha256":"00b28be86921dcdc0ad90cce0c62c2961cafefe96ea6c2edf0e926c3d405ccad"},{"path":"product/runtime/auths-gateway/src/admin.rs","sha256":"0dee40a9fb67c5de10142fc37a7bbabdd8979fb0199fb26caf4bdb024e0a5a40"},{"path":"product/runtime/auths-gateway/src/app.rs","sha256":"6f80f63833ea0815bb44fbf3b0cc54624a08e9fb578b035819f2980dc04e8256"},{"path":"product/runtime/auths-gateway/src/audit.rs","sha256":"0edb2037eb7b5d6f13acfce85c54f62a82bf7fdd31bc7e626c4fec183cef61dd"},{"path":"product/runtime/auths-gateway/src/audit_tests.rs","sha256":"990969384a52d75bc2489d9d412a9e7dd814bca1c8f65c701d6205fae62a15d5"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway-harness.rs","sha256":"12b0c24d36b2e6a3be392d3c081a783b355fdd67dc5b54bacc0410e803116b8c"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway.rs","sha256":"24d4224f03c680ee1fc3f3441cca8707fe002ce2c78588e8c337f2f150ea2e44"},{"path":"product/runtime/auths-gateway/src/binding.rs","sha256":"663b0ce878319511aa7d05722ab4ab2fa9be18817884ffb2ee9f131ff1e382d1"},{"path":"product/runtime/auths-gateway/src/bounds.rs","sha256":"38251ad6f22f9d07ef9a219c79fa265ca36f1526eca5f147d7efa46b52ad609d"},{"path":"product/runtime/auths-gateway/src/bounds_aggregate_tests.rs","sha256":"ab34f227b7c8692ba1da88ccb32bb3687a66adf8353d8282fae905d4a88eb612"},{"path":"product/runtime/auths-gateway/src/bounds_tests.rs","sha256":"74136bc570da7b9338b5a1a1ed9d3fd892c55135160964f9d3ac0e2cf5741375"},{"path":"product/runtime/auths-gateway/src/commissioning_budget.rs","sha256":"fab29da3269438cc62330f3eab7b5bd4dc482b4db8af243aae47df5d3aa1deb8"},{"path":"product/runtime/auths-gateway/src/commissioning_budget/tests.rs","sha256":"ad182c391b70450582c6ca06e3dadc221409bb3cdbc3c7668dbfc7fbedf63505"},{"path":"product/runtime/auths-gateway/src/commissioning_floor.rs","sha256":"7fa6991c5ccd5ae1403be84b3da390323fab09f36e15ac01fd7a38ea350c6fdb"},{"path":"product/runtime/auths-gateway/src/commissioning_floor/tests.rs","sha256":"5f7868252dfccb787d26f63ea6d5c3701c72d52c0ff0bc656dd5895f8cbed551"},{"path":"product/runtime/auths-gateway/src/commissioning_session.rs","sha256":"24b48d5eaeaaa3c620e2dfc7ee1f9255fc4519a1eb404b8608cea7af6a910ee2"},{"path":"product/runtime/auths-gateway/src/commissioning_session/tests.rs","sha256":"531510bbd1bb0a7544c2bfd14f68b028f523bd4ed25dc4a68521fd0d8418a440"},{"path":"product/runtime/auths-gateway/src/connection.rs","sha256":"7b5d049c258a26ed1c93ecf860f51d051a8a65f9b93554af0b1ea93862398ec9"},{"path":"product/runtime/auths-gateway/src/credential_journal.rs","sha256":"7297fccaee5cd8622928e8e0a42bba50da7941970a6f682ecd300c41ee6509da"},{"path":"product/runtime/auths-gateway/src/echo_verify.rs","sha256":"6d453051665f823abd7354d5c50031d9524cf47d6092d2f09080ae814e3b9575"},{"path":"product/runtime/auths-gateway/src/engine.rs","sha256":"1abff20b98bc894c45bfc5c4414c81a99966d1ec95d924a5b0cd6f4c5626ca24"},{"path":"product/runtime/auths-gateway/src/execution_witness.rs","sha256":"e8b1a8e41d5e3fa309760067849d390ef065feeb46701a83391832645a2f000c"},{"path":"product/runtime/auths-gateway/src/fuzzing.rs","sha256":"ed3b0028487eb546a3b0a91d115aa8f18bcea324b61620bfe8e35a9e6ab18758"},{"path":"product/runtime/auths-gateway/src/generation_floor.rs","sha256":"fe1510ec96ce0f67e9a78edbfa94b33eb7df64c0ac4d0a67901124dcd0164777"},{"path":"product/runtime/auths-gateway/src/harness.rs","sha256":"c87e479f3eb281960f6c9c80d43c7560d7ccb654b0154ec823d3fcec4884ac05"},{"path":"product/runtime/auths-gateway/src/lib.rs","sha256":"fad95d031f88072dd024c78facf0bb0267562b1ac743ddd7219fce47e64024f0"},{"path":"product/runtime/auths-gateway/src/listener.rs","sha256":"aa08239bcbc1fcb55e8a212fbdf6a84f12985b0d436dcb51dc58b06e59e435f2"},{"path":"product/runtime/auths-gateway/src/observed_tests.rs","sha256":"a22be071695f89ca2578a4d82fd80d9cb82289213c9bdb8f0470f6b2dc3d9201"},{"path":"product/runtime/auths-gateway/src/observer.rs","sha256":"562ffcaea071c3856e0708dc2fe33516917e145d2438aabb75af0a2b6ba01046"},{"path":"product/runtime/auths-gateway/src/onboarding.rs","sha256":"0dfd7d67e7f02f18a28d1c86ca1b7751d7463f5efcdbe3825de0ad8cbccb3891"},{"path":"product/runtime/auths-gateway/src/operator.rs","sha256":"c3c36954a3e86723df035b47f43b85fc8ab3a6292983522b6258d5c6b4e6c4e4"},{"path":"product/runtime/auths-gateway/src/pending_vectors/attempts.rs","sha256":"47ef3c8cb1c5504d47ae9a0088705ce6715fe86bac1671a34a56fb38a64d0dd3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/bounds.rs","sha256":"e612217307e1da5b0eb5ee6582a7458bb064b8aa8a529fc6555b1b334127ab68"},{"path":"product/runtime/auths-gateway/src/pending_vectors/codes.rs","sha256":"e00670a5ef24eb856cc2c6dcda8e5a263842f55c76bb939c0c27bd9df37e5522"},{"path":"product/runtime/auths-gateway/src/pending_vectors/keys.rs","sha256":"f84c56f2ea9cb34b2b79c72d13fbf2c6585010ec1ed450af58a78c80c1ea1edd"},{"path":"product/runtime/auths-gateway/src/pending_vectors/mod.rs","sha256":"5de8340f0ef71a0b57a09e323fefe473d3160c6ae952b9ba46f714825fbacafc"},{"path":"product/runtime/auths-gateway/src/pending_vectors/outcomes.rs","sha256":"8ec07b9511b48913af36ac999d2aa0e82924289f6acb23ddaeb9f00f99815166"},{"path":"product/runtime/auths-gateway/src/pending_vectors/production.rs","sha256":"772d032e0a0d9c924fb6d6c188528db85a97e71c9e466ddc19eee277baf83614"},{"path":"product/runtime/auths-gateway/src/pending_vectors/recipes.rs","sha256":"51693208270231c25c3aef2a32151d5962114c71e86b88cb9df83181c7af83d9"},{"path":"product/runtime/auths-gateway/src/pre_entry.rs","sha256":"06ea78ca140468bfaba17d9ab04912ad68673954c3203c98fed28272ff2a00c0"},{"path":"product/runtime/auths-gateway/src/property_tests.rs","sha256":"939c081e2e154aaf10186754044bdd65608932c899b970a04a71d0afaa999a93"},{"path":"product/runtime/auths-gateway/src/qualification.rs","sha256":"c597c83de2b94f0374ae54e40a8b57c2a64ec6e254704dca32185f448a908aca"},{"path":"product/runtime/auths-gateway/src/qualification_simulation.rs","sha256":"4ee7cadfb5f46a92713c80f3e55f499cb074d04d8b21ea89d57762af38642bfa"},{"path":"product/runtime/auths-gateway/src/qualification_tests.rs","sha256":"a9178a2e58eea459d5e5dafc53a3999ea7c84dbbffefe6e5eb1f3d098827f028"},{"path":"product/runtime/auths-gateway/src/quorum_tests.rs","sha256":"a78380b019104d688c11a4410082c7e08ded3106aab099954c4f8a1b4ae0fd89"},{"path":"product/runtime/auths-gateway/src/readiness.rs","sha256":"911c3f11892f94641574375e2da4c671c802738f71082f12c39832331052d43d"},{"path":"product/runtime/auths-gateway/src/recipe.rs","sha256":"fecf9af67e7afc48d080e9f8f55f8ce28e49d0e08988717a27908bbda461d6b6"},{"path":"product/runtime/auths-gateway/src/recipe/lower.rs","sha256":"8088b8751ed831dbb48247af953c6290ac95e2a438ccd5bd65eff54be06a1fd1"},{"path":"product/runtime/auths-gateway/src/recipe/review.rs","sha256":"c3eb7d9fdd98dacf52750b14b67ad7b7faaecbbdeafff1e0b049f67d0a2d0139"},{"path":"product/runtime/auths-gateway/src/recipe/runtime.rs","sha256":"c286f0d15f974402822c0810d8e97f98411dc1c557755cc23e540d85e2bb42d9"},{"path":"product/runtime/auths-gateway/src/recipe/source.rs","sha256":"1af50298fb1461e1b24cbdf560d43124d6b1c4c529586c911b1c4797214a69ff"},{"path":"product/runtime/auths-gateway/src/recipe/tests.rs","sha256":"aac551a2481bbc60864c64079bc667dcb232e45a0f41a04073ed84ab5dbe1fce"},{"path":"product/runtime/auths-gateway/src/recipe/validate.rs","sha256":"3711b17605cb7b0d639bc1b180449231f5882a306cab20e2c7782155cc63b0d4"},{"path":"product/runtime/auths-gateway/src/scenario_tests.rs","sha256":"a8ea1e3a7bf6b0274455bd790ace3ffb9c8716609cde92248920945c61634685"},{"path":"product/runtime/auths-gateway/src/separation.rs","sha256":"be9306848ca5d801767cf6aa14247c8618312ef0e202f00ce0c24c4844491061"},{"path":"product/runtime/auths-gateway/src/simulation_attestation.rs","sha256":"88705e5d45415f760f1e3c3a065c35c48f4f4065bf7b3feb7882246983814d6f"},{"path":"product/runtime/auths-gateway/src/store.rs","sha256":"884bcad4d70d53e12eae9c8517f6ecd0643068ee0be0370015119d04d6cc2516"},{"path":"product/runtime/auths-gateway/src/store_testkit.rs","sha256":"88d82fee42f1b8ef521e8deef0216e938ebeaad822eb2f5020e70b89d145ea70"},{"path":"product/runtime/auths-gateway/src/submit.rs","sha256":"fe2eacb5ad8152eeecbd232c47a356fc72db0098e34fda99532bdf6ef0cf895c"},{"path":"product/runtime/auths-gateway/src/support.rs","sha256":"9fd979029793a22b15d9776a7fc172476fd7c126a80d4080c65d720845becbcb"},{"path":"product/runtime/auths-gateway/src/transport.rs","sha256":"978fc9fb34a33b3db265b5d1c3ce11696a5b9f08529e46dd2a1e7bb62afb9220"},{"path":"product/runtime/auths-kernel-runtime/Cargo.toml","sha256":"926bcd0053e5edd703be8f0027ad009e2982db013c8174c1366edbf38b48087d"},{"path":"product/runtime/auths-kernel-runtime/src/lib.rs","sha256":"7108faae9ca4bc32dc093ddaf885ac8f74f3c9b8d317b7c7d0ed00d1d0ab5972"},{"path":"product/runtime/auths-lifecycle/Cargo.toml","sha256":"c5053c705f8d5554b44e432fe75287a2faf11d644e5a2552e45ad6cd94176af5"},{"path":"product/runtime/auths-lifecycle/src/codec.rs","sha256":"51c4b746749150e8bfcd8ff972b3f6c1ef40bec15583448ec1b471d9ad737dc0"},{"path":"product/runtime/auths-lifecycle/src/digest.rs","sha256":"55282cd7d8aba37713c2dcb5357c9877819edb72a30eadefb860d28d7d3a3eb7"},{"path":"product/runtime/auths-lifecycle/src/identifier.rs","sha256":"31620e8c16de68d3d2d3b84d6353c1a5b9d4151d8247f91fa389b906a8e660f1"},{"path":"product/runtime/auths-lifecycle/src/kernel.rs","sha256":"2abb8c094b36d35b364e74d78091d14c5d6f3d1eb6552cca3b5538dbd017ce23"},{"path":"product/runtime/auths-lifecycle/src/lib.rs","sha256":"afe5a345cd309b5a4f08ffba3170a6d7f16ff914892b3f2006d5208ed24ec736"},{"path":"product/runtime/auths-lifecycle/src/model.rs","sha256":"1af12bbeeeaa65ec02ddcebd7d2c8c92ec1e339fa40ae85b45ab9b01a722a4fa"},{"path":"product/runtime/auths-lifecycle/src/operation.rs","sha256":"78e6d05fcf5d7ea4f148032a3fa26fdfcab77eb346019effe927b08e0d64d732"},{"path":"product/runtime/auths-lifecycle/src/registry.rs","sha256":"53495fe6f7a77422593a41623e28716f1c140dcc1e00f87f6b0ffbfb93a5ef90"},{"path":"product/runtime/auths-lifecycle/src/sealed.rs","sha256":"2e0c03b5813c926c159598bb7890d1523825edbe57cd687d42a5dfb3374a0c19"},{"path":"product/runtime/auths-lifecycle/src/test_support.rs","sha256":"221d9a5c5ef8e1f9f8fd66927484eaf813571d0568470278ecd8fa08a5eec8cd"},{"path":"product/runtime/auths-lifecycle/src/transition.rs","sha256":"011805a28efdd541f44ccea54dd0e34a1e58f4004447ee58013703b4fb6b2822"},{"path":"product/runtime/auths-runtime/Cargo.toml","sha256":"dd29d80a8b4bb56c869f036a6c9998f6e6d1c0383ac5dc03fa42b24abe2a7ff7"},{"path":"product/runtime/auths-runtime/src/lib.rs","sha256":"132ca03d58c14905d3a822a4972f42a22a5ad33a45f2ba9ca44f3a57d810b4b0"},{"path":"product/runtime/auths-runtime/src/production.rs","sha256":"fd4eff4270c571c10fcff6cf27df28961ebf074de8a1a028f500fda1ca376820"},{"path":"product/sdk/auths-approval-quorum/Cargo.toml","sha256":"df904971fca87a24194c5816738a331588fe8f164acb5d70839a35dca5f57114"},{"path":"product/sdk/auths-approval-quorum/src/lib.rs","sha256":"72e4086088a1c0912e4e1a9e980f26a5c280bf5ab16ea39c9f0f58d5096ac2ce"},{"path":"product/sdk/auths-approval-quorum/src/remote.rs","sha256":"9fa029c7c63003adf260f8aec55160c545681c60c1bace0d934e7525862aac7b"},{"path":"product/sdk/auths-approval-quorum/src/remote_tests.rs","sha256":"8a09ce17cfee82a035a74edd535f3ebeb3db0e078784740d3997b17dbdb10197"},{"path":"product/sdk/auths-approval-quorum/src/tests.rs","sha256":"0acbf12be3e497dcc6c2d8f29c9af3b1a7ed8e11b75f6399570d4f217a785060"},{"path":"product/stores/auths-stores/Cargo.toml","sha256":"a32c4b76d17b264be5d40d24497ff237e1ed87822e8bab86229b3db93106dbe3"},{"path":"product/stores/auths-stores/src/gateway_attempt.rs","sha256":"218841602d3d9b23b44625f50e5b54cf275ccedc2d5c89f02d2482b8524472af"},{"path":"product/stores/auths-stores/src/lib.rs","sha256":"e721262edf8a9ab5568ddc27639176312d4a366203b5f73e2d7c11fde2c554e9"},{"path":"product/stores/auths-stores/src/lifecycle.rs","sha256":"3f2cecfda13fdcd7c4a944518646bcc8abd1237f900c0332d5822281f8f9f1cd"}],"schema":"auths.gateway-semantic-closure/1"} \ No newline at end of file +{"files":[{"path":"Cargo.lock","sha256":"0e75e2fdef44e79e57797ac6661295ae58ddb8de4a1990a6fd22ce6c54f78604"},{"path":"Cargo.toml","sha256":"6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24"},{"path":"core/adapters/auths-did-keri/Cargo.toml","sha256":"86ba3e3f9a0a70d970568bfb3113b7ba7bbdd81c3eebbb52743dd574a0c0ecaa"},{"path":"core/adapters/auths-did-keri/src/lib.rs","sha256":"a75674842f8a7142004369ccd206ab43e476459293f0ff4bed4d4e659031b3e3"},{"path":"core/adapters/auths-did-key/Cargo.toml","sha256":"d5a3ae07ecde83f91eed4c3785051dd0f44eab6c891754f3309b6b40596707d7"},{"path":"core/adapters/auths-did-key/src/lib.rs","sha256":"b76a3f4528a725df53cfa9242e6e414e1d26caa48468aaed497e28b121f4497c"},{"path":"core/adapters/auths-raw-key/Cargo.toml","sha256":"f49616bc18c19e6aaa7e6a02ccebcdb9f5c1422c1278ef9869e0dbf22ceda7be"},{"path":"core/adapters/auths-raw-key/src/lib.rs","sha256":"45eec1b295dac3bed65cd79c942870b926b06b3f5d38eaebaeb6140ac69315fa"},{"path":"core/crates/auths-algebra-kernel/Cargo.toml","sha256":"0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba"},{"path":"core/crates/auths-algebra-kernel/src/generated.rs","sha256":"ae4bcbef42a408c7ffa0c6a74a42f7de177a6f14479e51d205acf830bda05960"},{"path":"core/crates/auths-algebra-kernel/src/lib.rs","sha256":"6654667eeb9b353d6648954c9fd2e8838462a82ce6b2803eb49e1366892c68c6"},{"path":"core/crates/auths-assurance/Cargo.toml","sha256":"afcb12a97ddd09d7a264b9ecd3fcaefc865ff2c9b4539ee85b00883420ba333a"},{"path":"core/crates/auths-assurance/src/lib.rs","sha256":"0fb2ec844d674b25a9e20b1601452c89c2454901fa506adfa9bb38ef9a7fa213"},{"path":"core/crates/auths-author/Cargo.toml","sha256":"1e6f0e3bc079ddb558decf0db26b291c6e72fc47327b6df1b7650d41689b215f"},{"path":"core/crates/auths-author/src/lib.rs","sha256":"e14475f2f49715a1869d5fa6b11ff1fbb72497e39097e09f833b0bae7e5b3f2b"},{"path":"core/crates/auths-author/src/observations.rs","sha256":"dda7d6bfa6f4bd7e95a480ca283c2c0e996f69c5c15cb0c7197af328131a7066"},{"path":"core/crates/auths-authority/Cargo.toml","sha256":"4f68212938029f79ebd857b4f3038494eb85d0163d49f07e51376715cf959815"},{"path":"core/crates/auths-authority/src/lib.rs","sha256":"da88d5194de4e17449e69972c0fb042afa3c39798a8f570f30771e77c384f1eb"},{"path":"core/crates/auths-codec/Cargo.toml","sha256":"e20e51826e17814effd9d8925d18d5fbdd6c0d37bf50231e743ec2611314722c"},{"path":"core/crates/auths-codec/src/approval.rs","sha256":"fbff43bf4d57f69f8b7738a8647751cde75c5a932dee65d924a1fe9c7202f91f"},{"path":"core/crates/auths-codec/src/bounded_policy.rs","sha256":"d21f6728be2d8a04b6d94921f2b683f7e61cbb42e0ac6866f1c88a49caa534c3"},{"path":"core/crates/auths-codec/src/decode.rs","sha256":"ba2999584cdf53b1b517ecb9c7ea50d39efee17c666a9a38e2ad1ac94379f778"},{"path":"core/crates/auths-codec/src/encode.rs","sha256":"8491192053e2e15d62b4d2a491de22405b7487ead69ab6f6bca40669ce7ca5f7"},{"path":"core/crates/auths-codec/src/error.rs","sha256":"fecb0737c16deb42d859f1dc7727c698438d9ac12064fd99e0024629642c390c"},{"path":"core/crates/auths-codec/src/hash.rs","sha256":"f88e111f1dbb2cef6b7b5e9c948cb45ff92e366710c8a5f5c636138aa748479e"},{"path":"core/crates/auths-codec/src/lib.rs","sha256":"3b0e5c94c6f34f750b88a9333e1d5c8145746d845d3a23e0d2f61807cf592ea7"},{"path":"core/crates/auths-codec/src/observation.rs","sha256":"38328b0c71ff97a4196eeade8b4faa889527ff1f80bb168468bcd49082a3987e"},{"path":"core/crates/auths-composition/Cargo.toml","sha256":"331e13025eb82588b5269ed3975929eb41c823d588c49e4c296273d85c6fe80e"},{"path":"core/crates/auths-composition/src/lib.rs","sha256":"e42e3b0b6a9985b73c533aeb23799c638979aa27a9ce7d0f10a8d60340570fb1"},{"path":"core/crates/auths-model/Cargo.toml","sha256":"565c15302b0cc9270db1e28efa3862804846850ba933cc17aea8abcec4a65987"},{"path":"core/crates/auths-model/src/approval.rs","sha256":"54cf44a9ef747ec21546a4086aecfb130bc7803b0d646430e6082df51e6e305f"},{"path":"core/crates/auths-model/src/bounded.rs","sha256":"f90496abc0a06c028b4d850af6ddab7d850bfafeaa3d042f1b1246a41d8bbbc9"},{"path":"core/crates/auths-model/src/bounded_policy.rs","sha256":"306a8f049cc7cfc7635fe0e4de47eb7813eed63d3c14c3be2b51586aa4eea450"},{"path":"core/crates/auths-model/src/lib.rs","sha256":"e7cfe6bb9574c6b016aa63e70658c31e0b90903ec6479a49f4a2ceb64f5bad97"},{"path":"core/crates/auths-model/src/observation.rs","sha256":"b3ed3e3cc090afca2896a7d3de7988afccc1ee1ea0ebd91b51a8bc0f20ad8dbb"},{"path":"core/crates/auths-multikey/Cargo.toml","sha256":"858756c1197befcada06134742bffe8d58cf674cadd6c046bf710570e96efaf2"},{"path":"core/crates/auths-multikey/src/lib.rs","sha256":"f5177fffb11e40eeaaa665ba886c541fc1f24d5eacdd6983fb03dc20148733f0"},{"path":"core/crates/auths-ports/Cargo.toml","sha256":"596a9b0f5af3717c16a6d13f7054d8a106bcd9f01f5f72c2235dd2afcf0ab16c"},{"path":"core/crates/auths-ports/src/binding.rs","sha256":"a16c012d40aa4249e3ec54372b9611006d0bfe8c7dc3c741911c2194ad17736d"},{"path":"core/crates/auths-ports/src/diagnostics.rs","sha256":"aa596572503b5a65a918bb2ff38281c144ff53821ee914e9325c852828d852df"},{"path":"core/crates/auths-ports/src/lib.rs","sha256":"8da1debf86f9532df0660155d04298beb1ba3a1204508f8586e2e67cd2fb3449"},{"path":"core/crates/auths-ports/src/path.rs","sha256":"b68fc547b4e4d97a60cbbc1cc1939fc6b34a8233b81f840bd396914a707e3ea1"},{"path":"core/crates/auths-raw-key-core/Cargo.toml","sha256":"98c0bc8527a537512e43a74dd6ba9658c6f0cdc16610cf938e3f9b43785d836d"},{"path":"core/crates/auths-raw-key-core/src/lib.rs","sha256":"98c0500c41697aae28708ad0bf970b9a97583d96a3d2c18d23e7fa351e0f7d12"},{"path":"core/crates/auths-registries/Cargo.toml","sha256":"590e49e58b0622d9d6274fea46796dcdb07dec9550eff295cce6a6427ffa51e2"},{"path":"core/crates/auths-registries/src/lib.rs","sha256":"450d3886d85ee333b7e046317fb5b47cde62483d5f3e41d46265e2caf4c373ec"},{"path":"core/crates/auths-registries/src/template.rs","sha256":"1224039dd2b3ce6fa8357613d8cafbae40400493da7176da202b9ade62fa05e4"},{"path":"core/crates/auths-signature-core/Cargo.toml","sha256":"6bee2230eb30af1be0bd5c2d57bd3e1903497a70028d47290d4ac6e9e0e8bca0"},{"path":"core/crates/auths-signature-core/src/lib.rs","sha256":"6e3f9311ded5e49ea50d445eb21e6d8fa12442aa4362a73e0cb6fda15b7cd865"},{"path":"core/crates/auths-signature/Cargo.toml","sha256":"7f7b5682466ba439d8c59579022cb61068cad9fb4bd2d73e1cc21327c902b450"},{"path":"core/crates/auths-signature/src/lib.rs","sha256":"b3d9ac4cc3ba0797b9e1c09f2d6ac05089b25dac4e285a5af28c0165b33d925b"},{"path":"core/crates/auths-verifier/Cargo.toml","sha256":"c43358e06a33324b41a8b93e5cc7279c55f7d21f1f6cfaa539a3fc7b4c27a38f"},{"path":"core/crates/auths-verifier/src/approval.rs","sha256":"c3cae6a49e169051eb555bb092b1069a4d422516d6a2114623a89e5f31ff923f"},{"path":"core/crates/auths-verifier/src/causal.rs","sha256":"9635230f33b13a263573d319ac8a1976addbcc07677514a43e3c7bf28dc04587"},{"path":"core/crates/auths-verifier/src/lib.rs","sha256":"f22dec38dfa47ced8da4f605390da8453273bee1da010f57fd1fdfcb10e0b389"},{"path":"core/crates/auths-verifier/src/observation.rs","sha256":"0bb07f06a0f9524c88427df1c972b1de8ba038a9eeeb15d3134c25125ae84b1e"},{"path":"core/crates/auths-verifier/src/trace.rs","sha256":"2213d72023a1d9e0413a2cf2c51c3dad9e04775d86033a0caaa9d29a8f0036f8"},{"path":"exchange/crates/auths-proof-exchange-model/Cargo.toml","sha256":"34b2db64f93a288e942b5a3918d28cdcbef906e0dc9074ce848018d3d5f7a1fa"},{"path":"exchange/crates/auths-proof-exchange-model/src/lib.rs","sha256":"49fac5aff2339d3a57c41cb8bb2a82852538e8f77ecc4b157c88e264ff31fb55"},{"path":"exchange/crates/auths-proof-exchange-port/Cargo.toml","sha256":"7ff660f1b7579dc570c791090aeb450404fbbf44c92781e289f5ccdde746d739"},{"path":"exchange/crates/auths-proof-exchange-port/src/lib.rs","sha256":"b408fb40c6432edc1facb3d8b3e9433a033f8dc73fe2e0ba5a88c972ca675021"},{"path":"product/config/auths-config/Cargo.toml","sha256":"e4b568ab9f6d84f7d7e6d66443fe825f360db9c27bc7c31d6ddc0647ba3ab304"},{"path":"product/config/auths-config/src/lib.rs","sha256":"fecf00ea65cef9018fda9af2063326d7065b869266d0d9e73a4f06816f1102cc"},{"path":"product/errors/auths-errors/Cargo.toml","sha256":"3b3a199b6460ba75bda84475bb5accd35e1485448a3981038db85bf4772dd350"},{"path":"product/errors/auths-errors/src/lib.rs","sha256":"7feeb9069fa4003f94f1f07c1c94619cf1c883e0dbaaf2187f04d0f742264bdd"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/Cargo.toml","sha256":"716f1f2a117d6d69d8effe9ee9057e24ba3502f20af6a602b06facb638cdabed"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/api.rs","sha256":"9ea61dd7ddd93282b073b98e453e6b75b26dc49689c04e9782435d06a3a09e48"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/clock.rs","sha256":"73f0a6e0f5903883329fa6683f5888288f759512ac69e5c87efd2b6b87f7d79f"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/http.rs","sha256":"14c1fce14e24c984b2a275563a29b6326fb08367922b6e8d37ba38b9cb81aa2b"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/identity.rs","sha256":"186de11230c8b33375951c4368609f8976bf9795f171af3fd7fac26207a94361"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs","sha256":"0b4617d044f5254a5ab22f5a2578f91cc025206a8c1845be39c1c56dcdf7a5df"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/names.rs","sha256":"41bb23572d6002e23ee103d6fe70ecd68764861c6f2e48a1c53af998270a4afa"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs","sha256":"39fed883f4802e68d3b41a68fea0aba0737810996b33d13577de70faba004c29"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/store.rs","sha256":"fc60ee9c49b2f4f063c449b4c78100c5c4872779e94ca168f796603b380ef6e4"},{"path":"product/integrations/auths-custody/Cargo.toml","sha256":"1e14034185ad1ec24a977fd5f41d0abee219606245c046ce2a82287fadef448b"},{"path":"product/integrations/auths-custody/src/conformance.rs","sha256":"8ed1afd58f18fc6becc268908aa6419c9aa404c79da0197963eb2599df44acf6"},{"path":"product/integrations/auths-custody/src/key.rs","sha256":"70cbb0fd21b6f5652157845a22c35be2d0f6c05b3d138fc4b9bb6dbdc3d81c40"},{"path":"product/integrations/auths-custody/src/lib.rs","sha256":"8ee593c1f59b0fd2126bdda9138026f5bc531beb64d4489a99785842e7b98b43"},{"path":"product/operations/auths-operations/Cargo.toml","sha256":"73dde1e914ba5e1386f8d49c0d730423cc72ae77ec44c6554a6a75cc8e8922b1"},{"path":"product/operations/auths-operations/src/explanation.rs","sha256":"b4a39bcbd5712cb9e735ee7deeb281f3fa6af5ddca973735bf3d87dce427ef11"},{"path":"product/operations/auths-operations/src/lib.rs","sha256":"3f401a56555113b98f57bca172a2660eaecedf76247b83a3fdbb089c133a29cd"},{"path":"product/operations/auths-operations/src/render/json.rs","sha256":"2ae042639960afee123730e945d373bc5dda1d2b3af20ae16c939a7e99b9e418"},{"path":"product/operations/auths-operations/src/render/mod.rs","sha256":"b3b7f6fe473f49227ace5a68bfc3d8dc14b5db8dd9888fd9e207070337b1b8bf"},{"path":"product/operations/auths-operations/src/render/text.rs","sha256":"f216cf3bdb00e264523271b16e7059535ac6b1aabf271cebd7935af155e4bfec"},{"path":"product/policy/auths-bounded-policy/Cargo.toml","sha256":"babd5d200923137ead71d8c2528f847cea323ce98da942a1320b054436612c47"},{"path":"product/policy/auths-bounded-policy/src/arithmetic.rs","sha256":"75e43c5d4eab8d1f71c1daf53839f5f9fe45a400afc1f63a30c6f55ce3632627"},{"path":"product/policy/auths-bounded-policy/src/commitment.rs","sha256":"c5706f2d583454e1a7f570f7ada138d4d864bef0205dfae7c1296774f396bb3f"},{"path":"product/policy/auths-bounded-policy/src/eligibility.rs","sha256":"c9acdfb793074e687fc36efad506be27dbd99ffbf40387bc66c8de39ef238432"},{"path":"product/policy/auths-bounded-policy/src/identifier.rs","sha256":"0006a32bae9eb16c4178cf797df418d2b0a781f2bc6474b741dc1a908141831c"},{"path":"product/policy/auths-bounded-policy/src/kernel.rs","sha256":"99187c28b161ac70bee1afed60711f7f645adb4d1671a01863f9849b369811d5"},{"path":"product/policy/auths-bounded-policy/src/lib.rs","sha256":"76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c"},{"path":"product/policy/auths-bounded-policy/src/receipt.rs","sha256":"3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad"},{"path":"product/policy/auths-bounded-policy/src/registry.rs","sha256":"4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0"},{"path":"product/profiles/auths-profile-api/Cargo.toml","sha256":"7ae85761f58625b5d678f961fd052eebf3e000ef565c7312e3ac857763c0017f"},{"path":"product/profiles/auths-profile-api/src/lib.rs","sha256":"a194b82b20bf8aa864c2334ef6c6aec30b2154ded972862252d5dcefa488ab95"},{"path":"product/profiles/auths-profile-mcp/Cargo.toml","sha256":"db264fc25242f7b7e4133cbe5782545b3107b406c87168ae072683cfb59eac66"},{"path":"product/profiles/auths-profile-mcp/src/arguments.rs","sha256":"a5de696586d507e2aee4a49fee99ef1ef4c51a2e46603f8838f1af6d9009833f"},{"path":"product/profiles/auths-profile-mcp/src/lib.rs","sha256":"d0f8b733a09ef8408336cdebc8948d6a5861012ce6878598b11be7084dfd4280"},{"path":"product/profiles/auths-profile-mcp/src/session.rs","sha256":"166c281fa66333388e4760d6098dad02d3359e1d5de4b8f93312c014f97abb03"},{"path":"product/qualification/auths-recipe-qualification/Cargo.toml","sha256":"b7b15b30b9a3d96d4f089d514266d3a892de6608d30707aa44be31cca89ca9fe"},{"path":"product/qualification/auths-recipe-qualification/src/canonical.rs","sha256":"30a9b50777f0dcb4b606abfee2467d5a975d9f6ad941ab6c13ca3df5b359f667"},{"path":"product/qualification/auths-recipe-qualification/src/closure.rs","sha256":"0ad6aee9bd981e2863fa725f209ec84031db2ff12f4c7ac3aaf5120f0bb86039"},{"path":"product/qualification/auths-recipe-qualification/src/commissioning.rs","sha256":"66ea49f96887c4642139a48d259c270816e2267ee8cf6344a1340fe47afda9da"},{"path":"product/qualification/auths-recipe-qualification/src/commissioning/tests.rs","sha256":"5a226725c2ad7ce920d0bd62d427185e007f4d0949b0f0ec1260aa161d3114d0"},{"path":"product/qualification/auths-recipe-qualification/src/error.rs","sha256":"52d5cf720a1e4579008fdda90a3ac2c31f0b8db57985f121f65e54b4da2b7dd1"},{"path":"product/qualification/auths-recipe-qualification/src/evidence.rs","sha256":"ba45a7409d67a8af26ab811af306412014557477a101ab2a8eb0faf8f2bd4b91"},{"path":"product/qualification/auths-recipe-qualification/src/ids.rs","sha256":"e81a906d571497ab2da753e1532d4443706410e0b75fdd59a7d2d788c7aec403"},{"path":"product/qualification/auths-recipe-qualification/src/launch.rs","sha256":"41f2e2de90e1e7d6440a66eda3eb9bea8d5e0741bc232305a76a363ab5f813c1"},{"path":"product/qualification/auths-recipe-qualification/src/lib.rs","sha256":"7d26c5bfe9769daebf90c5c2280e0d75742e4cc70d0e608408e0665e3f516a2b"},{"path":"product/qualification/auths-recipe-qualification/src/model.rs","sha256":"3484eb0ec287b23d4682ade7b1b0f8d1335985b3fb180f06fc28716076957d5f"},{"path":"product/qualification/auths-recipe-qualification/src/release.rs","sha256":"ec478e53f70052e566aac7e15be2f9e1b1cd46837ac6990ae955fa864d311586"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/mod.rs","sha256":"fa23a962fd90331152eed5edbcdf271955f7aed79b8da1e065bfe69a20b487a9"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/schemas.rs","sha256":"c59feec2805621f341a90f81fc005e2c12f7a70f9d264fdeacccb2be4fe1c046"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/verification.rs","sha256":"6a6b5834c5dae10af1ba8939b2deae43b85db71544dc8f077ff63b7fe68ac8a8"},{"path":"product/qualification/auths-recipe-qualification/src/verify.rs","sha256":"2ec2784435d11e07295de77b2ee1b2c48b2fcf9609a00454c6e7374b621aed5c"},{"path":"product/receipts/auths-receipts/Cargo.toml","sha256":"6001fa1375899953aafcb07c23a6da0c8f57ea7ec08bb9c950b12a60a8cc6f0f"},{"path":"product/receipts/auths-receipts/src/disclosure.rs","sha256":"ba9ed439be0a320c8a01f5b6e9b51361c1a37e076947490d8e4a484ba6bb119c"},{"path":"product/receipts/auths-receipts/src/lib.rs","sha256":"547a57c4160256719cafb7d0ab972d9fc80b0da14fbbce4148c70c414070ff36"},{"path":"product/runtime/auths-connections/Cargo.toml","sha256":"babeb6e1dda3dfb66291713ce1e43dce5c349833d0b50ea4dccbf986030026b2"},{"path":"product/runtime/auths-connections/src/credential.rs","sha256":"82921413bb053f0f6c7931fbd4e6a86c8cc1d8c6b51debd9c2cef33a8d5b1c51"},{"path":"product/runtime/auths-connections/src/kernel.rs","sha256":"a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8"},{"path":"product/runtime/auths-connections/src/lib.rs","sha256":"79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22"},{"path":"product/runtime/auths-connections/src/model.rs","sha256":"de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77"},{"path":"product/runtime/auths-connections/src/registry.rs","sha256":"e57640e003e72ad3235c567c2bb944a262bd64e673f023b62ea091094cc7e946"},{"path":"product/runtime/auths-gateway-kernel/Cargo.toml","sha256":"34f864e67656af4ac7e5c7a347a23f01fc8ab31365b8e23c0ef474483b14a183"},{"path":"product/runtime/auths-gateway-kernel/src/construct.rs","sha256":"e9d65744bae273d65face4285e5d2da75c06a92ab48f7b8333d496604e31c63c"},{"path":"product/runtime/auths-gateway-kernel/src/lib.rs","sha256":"cfda6f8453426564c085475f183b6f790b438768a19668f1b65d33ba59dc8632"},{"path":"product/runtime/auths-gateway-kernel/src/order.rs","sha256":"e0045f877c4b7fe3860c291039853885064ddcdebba7c9b345ab65e81e646dda"},{"path":"product/runtime/auths-gateway-kernel/src/outcome.rs","sha256":"e9785b1afe70788c89b51b18655bcd5acff7b0c8e3d12fb79c6f05a202e67e6b"},{"path":"product/runtime/auths-gateway-kernel/src/ratio.rs","sha256":"7ace22264812e6fc1ef3a62afee402cf43494bb71ae0d3de219ad1b39d690bcb"},{"path":"product/runtime/auths-gateway-kernel/src/recovery.rs","sha256":"9f46dcd1685ab6e4d1ba04a3fc286a9f3afee8fb47829be1fbc670a7926a2dc6"},{"path":"product/runtime/auths-gateway-kernel/src/transition.rs","sha256":"cefb8f01d915880f6921f2501ff881ad94b9de61072c34d9cd19220992f97374"},{"path":"product/runtime/auths-gateway/Cargo.toml","sha256":"00b28be86921dcdc0ad90cce0c62c2961cafefe96ea6c2edf0e926c3d405ccad"},{"path":"product/runtime/auths-gateway/src/admin.rs","sha256":"0dee40a9fb67c5de10142fc37a7bbabdd8979fb0199fb26caf4bdb024e0a5a40"},{"path":"product/runtime/auths-gateway/src/app.rs","sha256":"6f80f63833ea0815bb44fbf3b0cc54624a08e9fb578b035819f2980dc04e8256"},{"path":"product/runtime/auths-gateway/src/audit.rs","sha256":"0edb2037eb7b5d6f13acfce85c54f62a82bf7fdd31bc7e626c4fec183cef61dd"},{"path":"product/runtime/auths-gateway/src/audit_tests.rs","sha256":"990969384a52d75bc2489d9d412a9e7dd814bca1c8f65c701d6205fae62a15d5"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway-harness.rs","sha256":"12b0c24d36b2e6a3be392d3c081a783b355fdd67dc5b54bacc0410e803116b8c"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway.rs","sha256":"24d4224f03c680ee1fc3f3441cca8707fe002ce2c78588e8c337f2f150ea2e44"},{"path":"product/runtime/auths-gateway/src/binding.rs","sha256":"663b0ce878319511aa7d05722ab4ab2fa9be18817884ffb2ee9f131ff1e382d1"},{"path":"product/runtime/auths-gateway/src/bounds.rs","sha256":"38251ad6f22f9d07ef9a219c79fa265ca36f1526eca5f147d7efa46b52ad609d"},{"path":"product/runtime/auths-gateway/src/bounds_aggregate_tests.rs","sha256":"ab34f227b7c8692ba1da88ccb32bb3687a66adf8353d8282fae905d4a88eb612"},{"path":"product/runtime/auths-gateway/src/bounds_tests.rs","sha256":"74136bc570da7b9338b5a1a1ed9d3fd892c55135160964f9d3ac0e2cf5741375"},{"path":"product/runtime/auths-gateway/src/commissioning_budget.rs","sha256":"fab29da3269438cc62330f3eab7b5bd4dc482b4db8af243aae47df5d3aa1deb8"},{"path":"product/runtime/auths-gateway/src/commissioning_budget/tests.rs","sha256":"ad182c391b70450582c6ca06e3dadc221409bb3cdbc3c7668dbfc7fbedf63505"},{"path":"product/runtime/auths-gateway/src/commissioning_floor.rs","sha256":"7fa6991c5ccd5ae1403be84b3da390323fab09f36e15ac01fd7a38ea350c6fdb"},{"path":"product/runtime/auths-gateway/src/commissioning_floor/tests.rs","sha256":"5f7868252dfccb787d26f63ea6d5c3701c72d52c0ff0bc656dd5895f8cbed551"},{"path":"product/runtime/auths-gateway/src/commissioning_session.rs","sha256":"24b48d5eaeaaa3c620e2dfc7ee1f9255fc4519a1eb404b8608cea7af6a910ee2"},{"path":"product/runtime/auths-gateway/src/commissioning_session/tests.rs","sha256":"531510bbd1bb0a7544c2bfd14f68b028f523bd4ed25dc4a68521fd0d8418a440"},{"path":"product/runtime/auths-gateway/src/connection.rs","sha256":"7b5d049c258a26ed1c93ecf860f51d051a8a65f9b93554af0b1ea93862398ec9"},{"path":"product/runtime/auths-gateway/src/credential_journal.rs","sha256":"7297fccaee5cd8622928e8e0a42bba50da7941970a6f682ecd300c41ee6509da"},{"path":"product/runtime/auths-gateway/src/echo_verify.rs","sha256":"6d453051665f823abd7354d5c50031d9524cf47d6092d2f09080ae814e3b9575"},{"path":"product/runtime/auths-gateway/src/engine.rs","sha256":"1abff20b98bc894c45bfc5c4414c81a99966d1ec95d924a5b0cd6f4c5626ca24"},{"path":"product/runtime/auths-gateway/src/execution_witness.rs","sha256":"e8b1a8e41d5e3fa309760067849d390ef065feeb46701a83391832645a2f000c"},{"path":"product/runtime/auths-gateway/src/fuzzing.rs","sha256":"ed3b0028487eb546a3b0a91d115aa8f18bcea324b61620bfe8e35a9e6ab18758"},{"path":"product/runtime/auths-gateway/src/generation_floor.rs","sha256":"fe1510ec96ce0f67e9a78edbfa94b33eb7df64c0ac4d0a67901124dcd0164777"},{"path":"product/runtime/auths-gateway/src/harness.rs","sha256":"c87e479f3eb281960f6c9c80d43c7560d7ccb654b0154ec823d3fcec4884ac05"},{"path":"product/runtime/auths-gateway/src/lib.rs","sha256":"fad95d031f88072dd024c78facf0bb0267562b1ac743ddd7219fce47e64024f0"},{"path":"product/runtime/auths-gateway/src/listener.rs","sha256":"aa08239bcbc1fcb55e8a212fbdf6a84f12985b0d436dcb51dc58b06e59e435f2"},{"path":"product/runtime/auths-gateway/src/observed_tests.rs","sha256":"a22be071695f89ca2578a4d82fd80d9cb82289213c9bdb8f0470f6b2dc3d9201"},{"path":"product/runtime/auths-gateway/src/observer.rs","sha256":"562ffcaea071c3856e0708dc2fe33516917e145d2438aabb75af0a2b6ba01046"},{"path":"product/runtime/auths-gateway/src/onboarding.rs","sha256":"0dfd7d67e7f02f18a28d1c86ca1b7751d7463f5efcdbe3825de0ad8cbccb3891"},{"path":"product/runtime/auths-gateway/src/operator.rs","sha256":"c3c36954a3e86723df035b47f43b85fc8ab3a6292983522b6258d5c6b4e6c4e4"},{"path":"product/runtime/auths-gateway/src/pending_vectors/attempts.rs","sha256":"47ef3c8cb1c5504d47ae9a0088705ce6715fe86bac1671a34a56fb38a64d0dd3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/bounds.rs","sha256":"e612217307e1da5b0eb5ee6582a7458bb064b8aa8a529fc6555b1b334127ab68"},{"path":"product/runtime/auths-gateway/src/pending_vectors/codes.rs","sha256":"e00670a5ef24eb856cc2c6dcda8e5a263842f55c76bb939c0c27bd9df37e5522"},{"path":"product/runtime/auths-gateway/src/pending_vectors/keys.rs","sha256":"f84c56f2ea9cb34b2b79c72d13fbf2c6585010ec1ed450af58a78c80c1ea1edd"},{"path":"product/runtime/auths-gateway/src/pending_vectors/mod.rs","sha256":"5de8340f0ef71a0b57a09e323fefe473d3160c6ae952b9ba46f714825fbacafc"},{"path":"product/runtime/auths-gateway/src/pending_vectors/outcomes.rs","sha256":"8ec07b9511b48913af36ac999d2aa0e82924289f6acb23ddaeb9f00f99815166"},{"path":"product/runtime/auths-gateway/src/pending_vectors/production.rs","sha256":"772d032e0a0d9c924fb6d6c188528db85a97e71c9e466ddc19eee277baf83614"},{"path":"product/runtime/auths-gateway/src/pending_vectors/recipes.rs","sha256":"51693208270231c25c3aef2a32151d5962114c71e86b88cb9df83181c7af83d9"},{"path":"product/runtime/auths-gateway/src/pre_entry.rs","sha256":"06ea78ca140468bfaba17d9ab04912ad68673954c3203c98fed28272ff2a00c0"},{"path":"product/runtime/auths-gateway/src/property_tests.rs","sha256":"939c081e2e154aaf10186754044bdd65608932c899b970a04a71d0afaa999a93"},{"path":"product/runtime/auths-gateway/src/qualification.rs","sha256":"c597c83de2b94f0374ae54e40a8b57c2a64ec6e254704dca32185f448a908aca"},{"path":"product/runtime/auths-gateway/src/qualification_simulation.rs","sha256":"4ee7cadfb5f46a92713c80f3e55f499cb074d04d8b21ea89d57762af38642bfa"},{"path":"product/runtime/auths-gateway/src/qualification_tests.rs","sha256":"a9178a2e58eea459d5e5dafc53a3999ea7c84dbbffefe6e5eb1f3d098827f028"},{"path":"product/runtime/auths-gateway/src/quorum_tests.rs","sha256":"a78380b019104d688c11a4410082c7e08ded3106aab099954c4f8a1b4ae0fd89"},{"path":"product/runtime/auths-gateway/src/readiness.rs","sha256":"911c3f11892f94641574375e2da4c671c802738f71082f12c39832331052d43d"},{"path":"product/runtime/auths-gateway/src/recipe.rs","sha256":"fecf9af67e7afc48d080e9f8f55f8ce28e49d0e08988717a27908bbda461d6b6"},{"path":"product/runtime/auths-gateway/src/recipe/lower.rs","sha256":"8088b8751ed831dbb48247af953c6290ac95e2a438ccd5bd65eff54be06a1fd1"},{"path":"product/runtime/auths-gateway/src/recipe/review.rs","sha256":"c3eb7d9fdd98dacf52750b14b67ad7b7faaecbbdeafff1e0b049f67d0a2d0139"},{"path":"product/runtime/auths-gateway/src/recipe/runtime.rs","sha256":"c286f0d15f974402822c0810d8e97f98411dc1c557755cc23e540d85e2bb42d9"},{"path":"product/runtime/auths-gateway/src/recipe/source.rs","sha256":"1af50298fb1461e1b24cbdf560d43124d6b1c4c529586c911b1c4797214a69ff"},{"path":"product/runtime/auths-gateway/src/recipe/tests.rs","sha256":"aac551a2481bbc60864c64079bc667dcb232e45a0f41a04073ed84ab5dbe1fce"},{"path":"product/runtime/auths-gateway/src/recipe/validate.rs","sha256":"3711b17605cb7b0d639bc1b180449231f5882a306cab20e2c7782155cc63b0d4"},{"path":"product/runtime/auths-gateway/src/scenario_tests.rs","sha256":"025b53473b3af6900e03bc2fee91aa63ed26a8778bc8c8296fe08f5540794c39"},{"path":"product/runtime/auths-gateway/src/separation.rs","sha256":"be9306848ca5d801767cf6aa14247c8618312ef0e202f00ce0c24c4844491061"},{"path":"product/runtime/auths-gateway/src/simulation_attestation.rs","sha256":"88705e5d45415f760f1e3c3a065c35c48f4f4065bf7b3feb7882246983814d6f"},{"path":"product/runtime/auths-gateway/src/store.rs","sha256":"884bcad4d70d53e12eae9c8517f6ecd0643068ee0be0370015119d04d6cc2516"},{"path":"product/runtime/auths-gateway/src/store_testkit.rs","sha256":"88d82fee42f1b8ef521e8deef0216e938ebeaad822eb2f5020e70b89d145ea70"},{"path":"product/runtime/auths-gateway/src/submit.rs","sha256":"fe2eacb5ad8152eeecbd232c47a356fc72db0098e34fda99532bdf6ef0cf895c"},{"path":"product/runtime/auths-gateway/src/support.rs","sha256":"9fd979029793a22b15d9776a7fc172476fd7c126a80d4080c65d720845becbcb"},{"path":"product/runtime/auths-gateway/src/transport.rs","sha256":"978fc9fb34a33b3db265b5d1c3ce11696a5b9f08529e46dd2a1e7bb62afb9220"},{"path":"product/runtime/auths-kernel-runtime/Cargo.toml","sha256":"926bcd0053e5edd703be8f0027ad009e2982db013c8174c1366edbf38b48087d"},{"path":"product/runtime/auths-kernel-runtime/src/lib.rs","sha256":"7108faae9ca4bc32dc093ddaf885ac8f74f3c9b8d317b7c7d0ed00d1d0ab5972"},{"path":"product/runtime/auths-lifecycle/Cargo.toml","sha256":"c5053c705f8d5554b44e432fe75287a2faf11d644e5a2552e45ad6cd94176af5"},{"path":"product/runtime/auths-lifecycle/src/codec.rs","sha256":"51c4b746749150e8bfcd8ff972b3f6c1ef40bec15583448ec1b471d9ad737dc0"},{"path":"product/runtime/auths-lifecycle/src/digest.rs","sha256":"55282cd7d8aba37713c2dcb5357c9877819edb72a30eadefb860d28d7d3a3eb7"},{"path":"product/runtime/auths-lifecycle/src/identifier.rs","sha256":"31620e8c16de68d3d2d3b84d6353c1a5b9d4151d8247f91fa389b906a8e660f1"},{"path":"product/runtime/auths-lifecycle/src/kernel.rs","sha256":"2abb8c094b36d35b364e74d78091d14c5d6f3d1eb6552cca3b5538dbd017ce23"},{"path":"product/runtime/auths-lifecycle/src/lib.rs","sha256":"afe5a345cd309b5a4f08ffba3170a6d7f16ff914892b3f2006d5208ed24ec736"},{"path":"product/runtime/auths-lifecycle/src/model.rs","sha256":"1af12bbeeeaa65ec02ddcebd7d2c8c92ec1e339fa40ae85b45ab9b01a722a4fa"},{"path":"product/runtime/auths-lifecycle/src/operation.rs","sha256":"78e6d05fcf5d7ea4f148032a3fa26fdfcab77eb346019effe927b08e0d64d732"},{"path":"product/runtime/auths-lifecycle/src/registry.rs","sha256":"53495fe6f7a77422593a41623e28716f1c140dcc1e00f87f6b0ffbfb93a5ef90"},{"path":"product/runtime/auths-lifecycle/src/sealed.rs","sha256":"2e0c03b5813c926c159598bb7890d1523825edbe57cd687d42a5dfb3374a0c19"},{"path":"product/runtime/auths-lifecycle/src/test_support.rs","sha256":"221d9a5c5ef8e1f9f8fd66927484eaf813571d0568470278ecd8fa08a5eec8cd"},{"path":"product/runtime/auths-lifecycle/src/transition.rs","sha256":"011805a28efdd541f44ccea54dd0e34a1e58f4004447ee58013703b4fb6b2822"},{"path":"product/runtime/auths-runtime/Cargo.toml","sha256":"dd29d80a8b4bb56c869f036a6c9998f6e6d1c0383ac5dc03fa42b24abe2a7ff7"},{"path":"product/runtime/auths-runtime/src/lib.rs","sha256":"132ca03d58c14905d3a822a4972f42a22a5ad33a45f2ba9ca44f3a57d810b4b0"},{"path":"product/runtime/auths-runtime/src/production.rs","sha256":"fd4eff4270c571c10fcff6cf27df28961ebf074de8a1a028f500fda1ca376820"},{"path":"product/sdk/auths-approval-quorum/Cargo.toml","sha256":"df904971fca87a24194c5816738a331588fe8f164acb5d70839a35dca5f57114"},{"path":"product/sdk/auths-approval-quorum/src/lib.rs","sha256":"72e4086088a1c0912e4e1a9e980f26a5c280bf5ab16ea39c9f0f58d5096ac2ce"},{"path":"product/sdk/auths-approval-quorum/src/remote.rs","sha256":"9fa029c7c63003adf260f8aec55160c545681c60c1bace0d934e7525862aac7b"},{"path":"product/sdk/auths-approval-quorum/src/remote_tests.rs","sha256":"8a09ce17cfee82a035a74edd535f3ebeb3db0e078784740d3997b17dbdb10197"},{"path":"product/sdk/auths-approval-quorum/src/tests.rs","sha256":"0acbf12be3e497dcc6c2d8f29c9af3b1a7ed8e11b75f6399570d4f217a785060"},{"path":"product/stores/auths-stores/Cargo.toml","sha256":"a32c4b76d17b264be5d40d24497ff237e1ed87822e8bab86229b3db93106dbe3"},{"path":"product/stores/auths-stores/src/gateway_attempt.rs","sha256":"218841602d3d9b23b44625f50e5b54cf275ccedc2d5c89f02d2482b8524472af"},{"path":"product/stores/auths-stores/src/lib.rs","sha256":"e721262edf8a9ab5568ddc27639176312d4a366203b5f73e2d7c11fde2c554e9"},{"path":"product/stores/auths-stores/src/lifecycle.rs","sha256":"3f2cecfda13fdcd7c4a944518646bcc8abd1237f900c0332d5822281f8f9f1cd"}],"schema":"auths.gateway-semantic-closure/1"} \ No newline at end of file diff --git a/product/runtime/auths-gateway/src/scenario_tests.rs b/product/runtime/auths-gateway/src/scenario_tests.rs index afa3e9f07..c2c147152 100644 --- a/product/runtime/auths-gateway/src/scenario_tests.rs +++ b/product/runtime/auths-gateway/src/scenario_tests.rs @@ -1395,8 +1395,8 @@ async fn qualification_stages_use_gateway_replay_and_recovery_witnesses() { BoundedText, CapabilityKind, QualificationTuple, Scenario, Sha256Digest, }; use auths_recipe_qualification_issuance::execution::{ - ExpectedObservation, Operation, RunCase, RunObservation, RunOutcome, RunPhase, RunStep, - RunVerdict, + EvidenceComparison, ExpectedObservation, Operation, RunCase, RunObservation, RunOutcome, + RunPhase, RunStep, RunVerdict, }; for scenario in [ Scenario::ProofReplay, @@ -1442,10 +1442,12 @@ async fn qualification_stages_use_gateway_replay_and_recovery_witnesses() { vec![ RunStep { operation: Operation::DropResponse, + evidence_comparison: EvidenceComparison::Static {}, expected: expected(RunOutcome::Unknown, "unknown", 1, 1, 0), }, RunStep { operation: Operation::ReadBack, + evidence_comparison: EvidenceComparison::Static {}, expected: expected(RunOutcome::Observed, "observed-by-provider", 1, 0, 1), }, ] @@ -1453,10 +1455,12 @@ async fn qualification_stages_use_gateway_replay_and_recovery_witnesses() { vec![ RunStep { operation: Operation::Submit, + evidence_comparison: EvidenceComparison::Static {}, expected: expected(RunOutcome::Observed, "observed-by-provider", 2, 1, 1), }, RunStep { operation: Operation::Replay, + evidence_comparison: EvidenceComparison::Static {}, expected: expected(RunOutcome::Refused, "gateway.attempt.replay", 0, 0, 0), }, ] @@ -1494,6 +1498,7 @@ async fn qualification_stages_use_gateway_replay_and_recovery_witnesses() { other => panic!("unexpected result: {other:?}"), }; observations.push(RunObservation { + fresh_evidence: None, tuple_sha256: tuple.digest().expect("tuple digest"), observed: ExpectedObservation { verdict: RunVerdict { diff --git a/product/runtime/auths-gateway/src/semantic_closure.rs b/product/runtime/auths-gateway/src/semantic_closure.rs index 544ddb306..e095aec74 100644 --- a/product/runtime/auths-gateway/src/semantic_closure.rs +++ b/product/runtime/auths-gateway/src/semantic_closure.rs @@ -10,7 +10,7 @@ /// SHA-256 of the schema, a NUL byte, and `semantic-closure.json`. /// Regenerate through `semantic_closure_is_current` with `AUTHS_UPDATE_FIXTURES=1`. pub const GATEWAY_SEMANTIC_CLOSURE_SHA256: &str = - "a136eb511dba4f9cd37fbfe75e7ca6a58d179dc24ff06d4198778ec875e41cf7"; + "7bc04fab6552c105167a354f578f69893d0cab60f3732140d4edea5f4eca4786"; #[cfg(test)] mod tests { diff --git a/qualification/README.md b/qualification/README.md index aee3592d0..fdda016e7 100644 --- a/qualification/README.md +++ b/qualification/README.md @@ -276,3 +276,12 @@ family corpus is admitted. Its manifest binds exact file hashes, source commit and workflow run. Native read-only recipe review exercises both maintained recipes; no installation, custody lease or qualification is claimed. This artifact is a candidate for operator inspection, not a GitHub release. + +Offline differential cases use the closed `review` operation after the pure +`oracle`. The candidate's `review-submission` checks native proof, actor, action +and exact request without installing or consulting qualification/custody. A +successful mapping is `complete`, never an HTTP response or effect. Both +operations must show zero leases, writes and read-back confirmations, and their +exact verdict/request commitments must agree. `review` cannot replace a submit +in a protected case. This avoids requiring first qualification merely to +collect the offline evidence needed to issue its finite commissioning permit. diff --git a/release/semantic-freeze-versions.toml b/release/semantic-freeze-versions.toml index 1ba0d4cfc..b95082eac 100644 --- a/release/semantic-freeze-versions.toml +++ b/release/semantic-freeze-versions.toml @@ -1,4 +1,4 @@ -freeze_version = 377 +freeze_version = 378 # Semantic identity counters live outside the xtask source tree deliberately. # The formal source closure binds xtask's executable code, while the semantic @@ -45,7 +45,7 @@ freeze_version = 377 "auths.frozen-bytes/product/integrations/auths-stripe/fixtures/subscription-create/v1/manifest.sha256.json" = 1 "auths.frozen-bytes/product/integrations/auths-stripe/fixtures/subscription-modify/v1/manifest.sha256.json" = 1 "auths.frozen-bytes/product/integrations/auths-stripe/fixtures/v1/manifest.sha256.json" = 1 -"auths.identity.protocol" = 130 +"auths.identity.protocol" = 131 "auths.modular-components" = 20 "auths.portable-abi-bindings" = 121 "auths.product.bounded-domains" = 19 @@ -60,11 +60,11 @@ freeze_version = 377 "auths.product.mcp-closed-execution" = 31 "auths.product.mechanism-profile-conformance" = 12 "auths.product.operations" = 5 -"auths.product.public-sdk-contract" = 127 +"auths.product.public-sdk-contract" = 128 "auths.product.receipts" = 13 "auths.product.release-assurance" = 7 "auths.product.simplified-waist" = 19 "auths.product.vocabulary" = 24 "auths.release.benchmark-contract" = 1 "auths.release.evolution-contract" = 79 -"auths.release.public-surface" = 377 +"auths.release.public-surface" = 378 diff --git a/release/semantic-freeze.json b/release/semantic-freeze.json index 7c9a96260..2bc2a6242 100644 --- a/release/semantic-freeze.json +++ b/release/semantic-freeze.json @@ -1,6 +1,6 @@ { "schema": "auths.semantic-freeze/1", - "freezeVersion": 377, + "freezeVersion": 378, "publicSurface": { "rustRoots": [ "auths", @@ -550,7 +550,7 @@ }, { "id": "auths.identity.protocol", - "version": 130, + "version": 131, "classification": "frozen-meaning", "categories": [ "identity-protocol-versions", @@ -573,7 +573,7 @@ "core/fixtures/identity/v1/vectors.json", "core/spec/identity/v1" ], - "sha256": "0826a5e79af86b77087b1e92415c3acb9a43ccc6c1e459d986cd961e6219e938" + "sha256": "b26d8563f6a4423918cf0f649810d1e697bf7681dcc60d7dab0f78d1e398c199" }, { "id": "auths.modular-components", @@ -871,7 +871,7 @@ }, { "id": "auths.product.public-sdk-contract", - "version": 127, + "version": 128, "classification": "frozen-meaning", "categories": [ "rust-sdk-contract", @@ -889,7 +889,7 @@ "product/runtime/auths-runtime/src", "product/sdk/auths-sdk/src" ], - "sha256": "18a272acd5c0199948712fb3d488711040c36abdbf824bc42b00bdabfc6a2eb6" + "sha256": "b0972f8fe6a4c73e49963eff448367c1ce2d7c94b79e0e9e8c8d9fe4e91548d7" }, { "id": "auths.product.receipts", @@ -1011,7 +1011,7 @@ }, { "id": "auths.release.public-surface", - "version": 377, + "version": 378, "classification": "release-metadata", "categories": [ "package-names", @@ -1104,7 +1104,7 @@ "xtask/src/release_launch.rs", "xtask/src/semantic_freeze.rs" ], - "sha256": "86cd3062177bf244e1888b75f53bb9e79e40ab8c24419f5910becca6ceac4926" + "sha256": "a37039df54c57b8d24bc0349317462349387932f6780cffc918bec17528e1007" } ] } From 0e5ad336fc86647402d426f9b9537ef5e7d7443f Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 05:49:00 +0100 Subject: [PATCH 065/108] Fix strict lint in qualification witness regressions --- .../auths-recipe-qualification-issuance/tests/execution.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/product/qualification/auths-recipe-qualification-issuance/tests/execution.rs b/product/qualification/auths-recipe-qualification-issuance/tests/execution.rs index 1725d381c..19c134b45 100644 --- a/product/qualification/auths-recipe-qualification-issuance/tests/execution.rs +++ b/product/qualification/auths-recipe-qualification-issuance/tests/execution.rs @@ -116,7 +116,7 @@ fn commissioning_client_refusal_cannot_replace_an_ordinary_installed_effect() { 1 => changed.steps[0].expected.provider_entries = 1, 2 => { changed.steps[0].expected.verdict.code = - BoundedText::parse("gateway.qualification.expired").expect("code") + BoundedText::parse("gateway.qualification.expired").expect("code"); } _ => changed.steps[0].expected.verdict.outcome = RunOutcome::Complete, } @@ -427,13 +427,13 @@ fn fresh_evidence_is_closed_to_the_reviewed_subject_and_exact_candidate_digest() actual.fresh_evidence = Some(FreshEvidenceWitness::IndependentReadBack { subject_sha256: response, response_sha256: response, - }) + }); } 4 => { actual.fresh_evidence = Some(FreshEvidenceWitness::ProductionDoctor { tuple_sha256: tuple().digest().expect("tuple"), report_sha256: response, - }) + }); } _ => actual.observed.provider_entries += 1, } From d6c3cd77d75629019225a15722393cd83224a649 Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 06:02:13 +0100 Subject: [PATCH 066/108] Keep installed qualification author isolated and refresh exact bounded actions --- .github/workflows/recipe-qualification.yml | 48 +++++ ...NDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md | 1 + qualification/reference/README.md | 40 +++- qualification/reference/author_packets.py | 183 ++++++++++++++++++ qualification/reference/check_packets.py | 128 ++++++++++++ qualification/reference/expand.py | 12 +- qualification/reference/packet_plan.py | 142 ++++++++++++++ qualification/reference/resource_io.py | 15 +- qualification/reference/tests/test_packets.py | 62 ++++++ .../reference/tests/test_reference.py | 6 +- 10 files changed, 627 insertions(+), 10 deletions(-) create mode 100644 qualification/reference/author_packets.py create mode 100644 qualification/reference/check_packets.py create mode 100644 qualification/reference/packet_plan.py create mode 100644 qualification/reference/tests/test_packets.py diff --git a/.github/workflows/recipe-qualification.yml b/.github/workflows/recipe-qualification.yml index 42d871fe5..e35485419 100644 --- a/.github/workflows/recipe-qualification.yml +++ b/.github/workflows/recipe-qualification.yml @@ -86,6 +86,54 @@ jobs: if-no-files-found: error retention-days: 30 + packet-author: + name: installed packet author and shipping native review + needs: candidate + runs-on: ubuntu-latest + timeout-minutes: 45 + steps: + - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 + with: + persist-credentials: false + - uses: ./.github/actions/setup-rust-cache + with: + toolchain: 1.97.1 + - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 + with: + python-version: "3.12" + - name: Build the installed SDK artifact + run: | + python -m pip install maturin==1.9.6 + maturin build --profile python-extension --locked \ + --manifest-path bindings/python/Cargo.toml --out target/qualification-wheels + python -m venv "${RUNNER_TEMP}/packet-consumer" + "${RUNNER_TEMP}/packet-consumer/bin/python" -m pip install target/qualification-wheels/*.whl + - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 + with: + name: qualification-shipping-candidate-${{ github.run_id }}-${{ github.run_attempt }} + path: ${{ runner.temp }}/packet-candidate + - name: Run the author without a checkout or provider credential + shell: bash + run: | + set -euo pipefail + kit="${RUNNER_TEMP}/packet-kit" + mkdir -p "${kit}/qualification/simulation/live" "${kit}/bindings/fixtures/gateway" + cp -R qualification/reference "${kit}/qualification/" + cp -R qualification/simulation/live/stripe-platform "${kit}/qualification/simulation/live/" + cp -R bindings/fixtures/gateway/airtable "${kit}/bindings/fixtures/gateway/" + chmod +x "${RUNNER_TEMP}/packet-candidate/bin/auths-gateway" + cd "${RUNNER_TEMP}" + python "${kit}/qualification/reference/check_packets.py" \ + --gateway "${RUNNER_TEMP}/packet-candidate/bin/auths-gateway" \ + --python "${RUNNER_TEMP}/packet-consumer/bin/python" \ + --work "${RUNNER_TEMP}/packet-operator" + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 + with: + name: qualification-packet-author-${{ github.run_id }}-${{ github.run_attempt }} + path: ${{ runner.temp }}/packet-operator/report.json + if-no-files-found: error + retention-days: 30 + simulation: name: disposable bootstrap and two provider simulations runs-on: ubuntu-latest diff --git a/docs/research/INDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md b/docs/research/INDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md index 9680d51a8..1c1422eb6 100644 --- a/docs/research/INDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md +++ b/docs/research/INDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md @@ -16,6 +16,7 @@ audit or real-user trial is claimed. | Disposable setup could leak resources after a lost creation response. | Implemented run-specific durable preparation journals, Stripe idempotent recovery and Airtable exact ownership discovery. Cleanup requires fresh ownership/state checks and leaves unrelated resources alone. Local Docker CLI rehearsal passed for one actual test payment and one actual record; cleanup confirmed both retired. Public rehearsal report is retained under `qualification/simulation/evidence/provider-resource-lifecycle-2026-10-07`. Protected family orchestration still needs integration. | | Existing AWS roles trust the `gateway-custody-live` environment, while the qualification template names separate family environments. | Inspected the existing reviewer-protected custody environment. Its branch policy is currently unset. Automatic approval review rejected tightening that shared environment and uploading local provider credentials there because that destination was not explicitly authorized. No environment change or provider-key upload occurred; protected orchestration remains pending. No role trust or gate is weakened. | | Main-only protected code must be deployed before the first protected qualification run. | A bounded prerequisite rollout of the completed runner is needed before collecting evidence. Epic acceptance stays open until actual runs, signed closure and CI are complete. | +| Normal authored actions expire while a protected signing job waits. | Keep the installed author in an isolated process for a bounded two-hour grant/session. Refresh only the same predeclared action just before submission; native signatures keep the ordinary five-minute action limit, exact actor/action/request and installation trust. No private key enters artifacts. Both native Docker rehearsals passed with synthetic resources and no network; protected sequencing still needs integration. | The public offline root ceremony and purpose-separated certificates are pinned. Both signer keys are provisioned in the existing reviewer-protected main-only diff --git a/qualification/reference/README.md b/qualification/reference/README.md index 631f03471..240db6a48 100644 --- a/qualification/reference/README.md +++ b/qualification/reference/README.md @@ -37,8 +37,11 @@ python qualification/reference/expand.py \ --out-dir ``` -The public packet carrier is `auths.qualification-public-packets/1`, with -`protected_run`, `trusted_context` (one adjacent filename), and 1–64 `packets`. +The public packet carrier is `auths.qualification-public-packets/2`, with +`protected_run`, `evaluated_at`, `not_after`, `trusted_context` (one adjacent +filename), and 1–64 `packets`. Packet validity is at most five minutes; the +signing expansion reviews native proofs at their recorded offline evaluation +time, within the last two hours. This grants no production clock override. Each packet contains `label`, `proof`, `action` (adjacent filenames), and its expected `arguments`. Unknown fields, path traversal, changed source, wrong production targets, resource widening, actor changes or an oracle mismatch @@ -99,3 +102,36 @@ Stripe's [Refund object](https://docs.stripe.com/api/refunds/object) has no and the exact freshly checked PaymentIntent and Charge; the refund must bind that same payment. An unexpected explicit live-mode marker is refused. Unit responses follow the provider's actual Refund shape. + +### Installed author and delayed signing + +`packet_plan.py` derives public arguments for separate commissioning/live +operations on each closed resource. It preserves the exact reviewed lock and +the approved recipe substitutions, obtains the native verifier pin and Stripe +bounded extension, and scopes the Stripe grant to these payment identifiers. +No provider credential or caller-supplied argument enters the installed author. + +`author_packets.py` must run outside the checkout from an installed wheel, with +only `PATH`, `PYTHONNOUSERSITE` and optional locale variables. It refuses any +additional environment variable before importing the SDK. A fresh native key +authors the single actor, grant, challenge and trust; no private key is exported. +The grant/session lasts at most two hours. Every action keeps the ordinary SDK +maximum of 300 seconds; a protected signing wait must not extend that limit. + +With `--serve`, the same isolated process holds its key in memory and accepts +bounded newline-delimited commands on private stdin. A refresh names only an +existing label and the next integer generation (1–1024); it cannot supply new +arguments, authority, actor, challenge or a destination path. It writes into a +new private `refresh-NNNN` directory. The refreshed proof uses current time, +while the canonical action, action commitment, exact grant, request and +installation context remain unchanged. Native context normalization preserves +the installation's request evaluation input; the gateway always rebinds its +own trusted current time. EOF, `close`, expiry, rollback or malformed commands +terminate the process. Keys and tokens are never transferred through artifacts. + +`check_packets.py` exercises the real installed author and shipping gateway with +explicitly synthetic resource carriers and no network/provider credential. It +checks both independent request mappings, original five-minute expiry, and an +actual refreshed native proof with the same actor/action/request/trust. CI +retains only its closed report. This is operator/release-tool evidence, not +protected live qualification. diff --git a/qualification/reference/author_packets.py b/qualification/reference/author_packets.py new file mode 100644 index 000000000..33fa0927d --- /dev/null +++ b/qualification/reference/author_packets.py @@ -0,0 +1,183 @@ +#!/usr/bin/env python3 +"""Author public qualification packets with an installed SDK and no credential. + +Run with an empty environment outside the checkout. Native SDK primitives own +every grant, context, signature, challenge and canonical protocol commitment. +No private signing key is written, exported or reused across author runs. +""" + +import argparse +import importlib.metadata +import os +from pathlib import Path +import select +import sys +import sysconfig +import time + +from common import Refusal, canonical, closed, integer, require, sha256 +from expand import decode, read +from packet_plan import REFERENCES, validate +from resource_io import finish, write, write_bytes + + +def installed_native(): + # Environment is a positive allowlist, so an unanticipated credential name + # cannot silently reach this process. Callers must construct its environment. + require(set(os.environ) <= {'PATH', 'PYTHONNOUSERSITE', 'LC_CTYPE', 'LANG'}, + 'qualification.packets.consumer-environment') + try: + import auths + from auths import _native as native + except ImportError: + raise Refusal('qualification.packets.sdk-unavailable') from None + package = Path(auths.__file__).resolve() + installed_roots = [Path(sysconfig.get_path(name)).resolve() for name in ['purelib', 'platlib']] + require(any(package.is_relative_to(root) for root in installed_roots) + and 'site-packages' in package.parts, 'qualification.packets.repository-import') + require(Path(native.__file__).resolve().parent == package.parent, + 'qualification.packets.native-package') + return native, importlib.metadata.version('auths') + + +def create_session(plan_path): + plan = validate(decode(read(plan_path, 65536))) + now = int(time.time()) + require(plan['evaluated_at'] <= now <= plan['evaluated_at'] + 60, + 'qualification.packets.stale-plan') + native, version = installed_native() + reference = REFERENCES[plan['family']] + current, end = plan['evaluated_at'], plan['not_after'] + audience = 'mcp://' + reference.SERVICE + resource = audience + '/tools/' + reference.TOOL + key = native.DevelopmentEd25519Key.generate() + actor = native.Principal(key.principal) + extension = plan['extension'] + extensions = [] if extension is None else [(extension['extension_id'], bytes.fromhex(extension['extension_body_hex']))] + request = native.GrantRequest(actor, 'auths.mcp', 2, [('tools/call', resource)], + current - 60, end, [audience], None, None, 0, None, 'raw-key-baseline', extensions) + unsigned = native.root_grant(actor, request) + signing = native.prepare_signing(unsigned, key.principal_method, key.verification_method, key.suite) + grant = signing.complete(key.sign(signing.signing_preimage)) + challenge = native.generate_challenge_v1() + anchor = native.TrustAnchor(actor.value, actor, [key.principal_method], [('auths.mcp', 2)], + [('tools/call', resource)], [audience], [audience], current - 60, end, + None, 1, 'raw-key-baseline', None) + assurance = native.AssurancePolicy('raw-key-baseline', [ + ('root', 'every', 'self-certifying-identifier', None), + ('actor', 'every', 'self-certifying-identifier', None), + ('actor', 'every', 'offline-verifiable', None)]) + template = native.compile_trusted_context(bytes.fromhex(plan['configuration']), None, 1, 1, 1, + [anchor], assurance, None, None, 'none-v1', [key.evidence_type], + [] if extension is None else [extension['extension_id']]) + context = template.bind_request(audience, challenge, current) + evidence = (key.evidence_type, key.media_type, key.evidence) + # The closure alone retains this native key. A refresh accepts a known + # label, never caller-supplied arguments, a new grant, actor or challenge. + retained_context, last_time = None, current + def emit(work, label=None): + nonlocal retained_context, last_time + current = int(time.time()) + require(last_time <= current < end, 'qualification.packets.session-expired') + last_time = current + validity = min(300, end - current) + selected = [packet for packet in plan['packets'] if label is None or packet['label'] == label] + require(bool(selected), 'qualification.packets.unknown-label') + packets = [] + for packet in selected: + label, arguments = packet['label'], packet['arguments'] + call = native.mcp_call(reference.SERVICE, reference.TOOL, canonical(arguments)) + prepared = native.prepare_mcp_call_action(call, actor, grant, challenge, current, validity) + signing = native.prepare_signing(prepared.unsigned, key.principal_method, key.verification_method, key.suite) + signed_action = signing.complete(key.sign(signing.signing_preimage)) + proof, action, trust = native.assemble_mcp_proof(prepared, signed_action, [grant], + [[evidence]], [evidence], context) + # Assembly binds its returned context to the fresh envelope time. + # Keep one exact installation context: native normalization changes + # only the request evaluation input. The gateway always supplies + # its own synchronized current time when verifying this proof. + trust = bytes(native.inspect_trusted_context(native.parse_trusted_context(trust) + .bind_request(audience, challenge, plan['evaluated_at']))) + require(retained_context is None or retained_context == trust, + 'qualification.packets.context-binding') + retained_context = bytes(trust) + write_bytes(work / (label + '.proof'), bytes(proof), new=True) + write_bytes(work / (label + '.action'), bytes(action), new=True) + packets.append({'label': label, 'proof': label + '.proof', 'action': label + '.action', + 'arguments': arguments}) + write_bytes(work / 'context.cbor', retained_context, new=True) + write(work / 'public-packets.json', {'schema': 'auths.qualification-public-packets/2', + 'protected_run': plan['protected_run'], 'evaluated_at': current, 'not_after': current + validity, + 'trusted_context': 'context.cbor', 'packets': packets}, new=True) + write(work / 'author-report.json', {'schema': 'auths.qualification-packet-author/1', + 'family': plan['family'], 'protected_run': plan['protected_run'], 'sdk_version': version, + 'packet_count': len(packets), 'trusted_context_sha256': sha256(retained_context), + 'private_key_exported': False, 'provider_token_received': False, + 'repository_imported': False, 'qualification_issued': False}, new=True) + return emit, end + + +def command(raw, generation): + require(0 < len(raw) <= 512 and raw.endswith(b'\n'), 'qualification.packets.command-bound') + value = decode(raw) + require(type(value) is dict, 'qualification.packets.command-bound') + if value.get('command') == 'close': + closed(value, ['command']) + return None + closed(value, ['command', 'label', 'generation']) + require(value['command'] == 'refresh' and type(value['label']) is str, + 'qualification.packets.command-bound') + require(integer(value['generation'], 1, 1024) == generation + 1, + 'qualification.packets.generation') + return value + + +def author(plan_path, work, serve=False): + emit, end = create_session(plan_path) + emit(work) + if not serve: + return + print('{"schema":"auths.qualification-author-session/1","state":"ready"}', flush=True) + generation = 0 + # Bounded pipe reads use os.read rather than buffered readline: select + # must not miss an already-buffered second command. Partial frames have + # the same finite grant deadline and cannot extend the process lifetime. + pending = b'' + while True: + remaining = end - time.time() + require(remaining > 0, 'qualification.packets.session-expired') + ready, _, _ = select.select([sys.stdin.fileno()], [], [], remaining) + require(bool(ready), 'qualification.packets.session-expired') + chunk = os.read(sys.stdin.fileno(), 513) + if not chunk: + require(not pending, 'qualification.packets.command-bound') + return + pending += chunk + require(len(pending) <= 512, 'qualification.packets.command-bound') + if b'\n' not in pending: + continue + require(pending.count(b'\n') == 1 and pending.endswith(b'\n'), + 'qualification.packets.command-bound') + value = command(pending, generation) + pending = b'' + if value is None: + return + generation = value['generation'] + destination = work / ('refresh-' + str(generation).zfill(4)) + destination.mkdir(mode=0o700) + emit(destination, value['label']) + print(canonical({'schema': 'auths.qualification-author-session/1', + 'state': 'refreshed', 'generation': generation, 'label': value['label']}).decode(), flush=True) + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--plan', type=lambda value: Path(value).absolute(), required=True) + parser.add_argument('--work', type=lambda value: Path(value).absolute(), required=True) + parser.add_argument('--serve', action='store_true') + args = parser.parse_args() + finish(lambda: author(args.plan, args.work, args.serve)) + + +if __name__ == '__main__': + main() diff --git a/qualification/reference/check_packets.py b/qualification/reference/check_packets.py new file mode 100644 index 000000000..794798b52 --- /dev/null +++ b/qualification/reference/check_packets.py @@ -0,0 +1,128 @@ +#!/usr/bin/env python3 +"""Credential-free installed-author/native-review operator check. + +The resource carriers are explicitly synthetic; no provider is contacted and +no qualification is issued. The shipping gateway and installed SDK are real. +""" + +import argparse +import json +import os +from pathlib import Path +import select +import re +import subprocess +import time + +import airtable_record +import stripe_platform +from common import Refusal, canonical, require, sha256 +from expand import child, decode, read +from packet_plan import prepare +from resource_io import finish, write + + +def response(process): + require(bool(select.select([process.stdout], [], [], 30)[0]), 'qualification.packets.author-timeout') + raw = process.stdout.readline(513) + if not raw: + _, stderr = process.communicate(timeout=10) + codes = re.findall(rb'qualification\.[a-z0-9.-]{1,128}', stderr[:65536]) + raise Refusal(codes[-1].decode() if codes else 'qualification.packets.author-refused') + require(0 < len(raw) <= 512 and raw.endswith(b'\n'), 'qualification.packets.author-response') + return decode(raw) + + +def review(binary, work, packet, evaluated_at): + return child(binary, ['review-submission', '--recipe', work / 'recipe.json', + '--profile-lock', work / 'profile.lock.json', '--trusted-context', work / 'context.cbor', + '--proof', work / packet['proof'], '--action', work / packet['action'], + '--evaluated-at', str(evaluated_at)]) + + +def check(args): + require(not args.work.exists(), 'qualification.packets.output-exists') + args.work.mkdir(mode=0o700) + run = 'packet-operator-rehearsal/' + str(int(time.time())) + '/1' + reports = [] + for reference in [stripe_platform, airtable_record]: + work = args.work / reference.FAMILY + work.mkdir(mode=0o700) + resources = {'schema': 'auths.stripe-platform-qualification-resources/1', + 'protected_run': run, 'platform': 'acct_SYNTHETIC', 'payments': [ + {'id': 'pi_SYNTHETIC', 'amount_received': 2000, 'currency': 'usd', + 'livemode': False, 'run_metadata': run}]} if reference is stripe_platform else { + 'schema': 'auths.airtable-record-qualification-resources/1', 'protected_run': run, + 'base': airtable_record.BASE, 'table': airtable_record.TABLE, 'records': [ + {'id': 'recTEST0000000001', 'run_metadata': run}]} + write(work / 'resources.json', resources, new=True) + prepare(argparse.Namespace(family=reference.FAMILY, resources=work / 'resources.json', + gateway=args.gateway, work=work)) + # Python runs outside the checkout, with no editable package, provider + # token, home directory, ambient PYTHONPATH or repository import path. + process = subprocess.Popen([str(args.python), str(Path(__file__).with_name('author_packets.py')), + '--plan', str(work / 'packet-plan.json'), '--work', str(work), '--serve'], + stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, + cwd='/', env={'PATH': '/usr/bin:/bin', 'PYTHONNOUSERSITE': '1'}) + try: + require(response(process) == {'schema': 'auths.qualification-author-session/1', 'state': 'ready'}, + 'qualification.packets.author-response') + plan = decode(read(work / 'public-packets.json', 65536)) + reviewed = [] + for packet in plan['packets']: + value = review(args.gateway, work, packet, plan['evaluated_at']) + expected = reference.request(packet['arguments'], resources, value['action_commitment'], + packet['arguments']['recipe_digest']) + require(value['schema'] == 'auths.gateway-submission-review/1' + and value['arguments'] == packet['arguments'] and value['request'] == expected, + 'qualification.packets.oracle-mismatch') + reviewed.append(value) + # The old proof must really expire at the ordinary five-minute + # bound. This is offline review, never a production clock override. + expired = review(args.gateway, work, plan['packets'][0], plan['not_after'] + 1) + require(expired.get('schema') != 'auths.gateway-submission-review/1', + 'qualification.packets.expiry-not-enforced') + time.sleep(1.05) + process.stdin.write(canonical({'command': 'refresh', 'label': plan['packets'][0]['label'], + 'generation': 1}) + b'\n') + process.stdin.flush() + require(response(process)['state'] == 'refreshed', 'qualification.packets.author-response') + fresh = work / 'refresh-0001' + # Refresh uses the same reviewed recipe and exact installed trust. + for name in ['recipe.json', 'profile.lock.json']: + (fresh / name).write_bytes(read(work / name, 65536)) + fresh_plan = decode(read(fresh / 'public-packets.json', 65536)) + actual = review(args.gateway, fresh, fresh_plan['packets'][0], fresh_plan['evaluated_at']) + require(actual == reviewed[0] + and read(fresh / 'context.cbor', 4 * 1024 * 1024) == read(work / 'context.cbor', 4 * 1024 * 1024) + and read(fresh / plan['packets'][0]['action'], 65536) == read(work / plan['packets'][0]['action'], 65536) + and read(fresh / plan['packets'][0]['proof'], 4 * 1024 * 1024) != read(work / plan['packets'][0]['proof'], 4 * 1024 * 1024), + 'qualification.packets.refresh-binding') + process.stdin.write(b'{"command":"close"}\n') + process.stdin.flush() + _, stderr = process.communicate(timeout=10) + require(process.returncode == 0 and not stderr, 'qualification.packets.author-refused') + reports.append({'family': reference.FAMILY, 'packet_count': len(reviewed), + 'same_actor_action_request_and_trust_after_refresh': True, + 'original_five_minute_expiry_enforced': True, + 'author': decode(read(work / 'author-report.json', 65536))}) + finally: + if process.poll() is None: + process.terminate() + process.communicate(timeout=10) + write(args.work / 'report.json', {'schema': 'auths.qualification-packet-operator-rehearsal/1', + 'gateway_sha256': sha256(read(args.gateway, 256 * 1024 * 1024)), + 'synthetic_resources': True, 'provider_contacted': False, 'protected_qualification': False, + 'qualification_issued': False, 'stable_launch_ready': False, 'families': reports}, new=True) + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + for name in ['gateway', 'python', 'work']: + parser.add_argument('--' + name, type=lambda value: Path(value).absolute(), required=True) + args = parser.parse_args() + finish(lambda: check(args)) + + +if __name__ == '__main__': + main() diff --git a/qualification/reference/expand.py b/qualification/reference/expand.py index 780735ab2..1de0a7161 100644 --- a/qualification/reference/expand.py +++ b/qualification/reference/expand.py @@ -14,6 +14,7 @@ import stat import subprocess import sys +import time import airtable_record import stripe_platform @@ -115,9 +116,13 @@ def expand(args): and read(args.profile_lock, 65536) == read(source / 'profile.lock.json', 65536), 'qualification.reference.reviewed-source') plan = decode(read(args.packets, 65536)) - closed(plan, ['schema', 'protected_run', 'trusted_context', 'packets']) - require(plan['schema'] == 'auths.qualification-public-packets/1' + closed(plan, ['schema', 'protected_run', 'evaluated_at', 'not_after', 'trusted_context', 'packets']) + require(plan['schema'] == 'auths.qualification-public-packets/2' and plan['protected_run'] == protected_run + and type(plan['evaluated_at']) is int and 60 <= plan['evaluated_at'] <= 253402300499 + and type(plan['not_after']) is int + and plan['evaluated_at'] < plan['not_after'] <= plan['evaluated_at'] + 300 + and int(time.time()) - 7200 <= plan['evaluated_at'] <= int(time.time()) + 60 and type(plan['packets']) is list and 1 <= len(plan['packets']) <= 64, 'qualification.reference.packet-bound') work = args.packets.parent @@ -134,7 +139,8 @@ def expand(args): read(action, 65536) reviewed = child(args.reviewer, ['review-submission', '--recipe', args.recipe, '--profile-lock', args.profile_lock, '--trusted-context', context, - '--proof', proof, '--action', action]) + '--proof', proof, '--action', action, + '--evaluated-at', str(plan['evaluated_at'])]) require(reviewed.get('schema') == 'auths.gateway-submission-review/1' and len(reviewed['actors']) == 1 and reviewed['arguments'] == packet['arguments'], 'qualification.reference.proof-binding') diff --git a/qualification/reference/packet_plan.py b/qualification/reference/packet_plan.py new file mode 100644 index 000000000..7cec8abd2 --- /dev/null +++ b/qualification/reference/packet_plan.py @@ -0,0 +1,142 @@ +#!/usr/bin/env python3 +"""Prepare public packet inputs from the two reviewed resource carriers. + +No credential is accepted. The installed author receives only the recipe pin, +closed bounded arguments and a public grant extension from the native gateway. +""" + +import argparse +from pathlib import Path +import time + +import airtable_record +import stripe_platform +from common import canonical, closed, digest, require, sha256 +from expand import child, decode, read, SOURCES +from resource_io import finish, run_id, write, write_bytes + +REFERENCES = {reference.FAMILY: reference for reference in [stripe_platform, airtable_record]} +PACKET_VALIDITY = 7200 + + +def arguments(family, resources, recipe_digest): + """One separate operation per resource and phase; reuse never adds a write.""" + reference = REFERENCES.get(family) + require(reference is not None, 'qualification.packets.family') + reference.resources(resources, run_id(resources['protected_run'])) + recipe_digest = digest(recipe_digest) + namespace = reference.SERVICE if reference is stripe_platform else 'airtable-demo' + values = resources['payments'] if reference is stripe_platform else resources['records'] + packets = [] + for phase in ['commissioning', 'live']: + for index, resource in enumerate(values): + label = phase + '-' + str(index).zfill(2) + # The run marker makes logical operation identities distinct across + # reruns, while an exact replay retains the original operation ID. + operation = 'qlf-' + sha256(canonical([family, resources['protected_run'], label]))[:48] + value = {'operator_namespace': namespace, 'operation_id': operation, + 'recipe_digest': recipe_digest} + if reference is stripe_platform: + require(resource['amount_received'] == 2000, 'qualification.packets.payment-bound') + value.update(payment_intent=resource['id'], amount=500, currency='usd') + else: + value.update(record_id=resource['id'], replacement='Approved' if phase == 'commissioning' else 'Pending') + # This checks the full resource/action request contract before the + # author can turn these inputs into signed action bytes. + reference.request(value, resources, '0' * 64, recipe_digest) + packets.append({'label': label, 'arguments': value}) + return packets + + +def validate(plan): + closed(plan, ['schema', 'family', 'protected_run', 'evaluated_at', 'not_after', + 'configuration', 'extension', 'resources', 'packets']) + require(plan['schema'] == 'auths.qualification-packet-plan/1' + and type(plan['family']) is str and plan['family'] in REFERENCES, + 'qualification.packets.schema') + run_id(plan['protected_run']) + require(type(plan['evaluated_at']) is int and 60 <= plan['evaluated_at'] <= 253402293599 + and type(plan['not_after']) is int + and plan['not_after'] == plan['evaluated_at'] + PACKET_VALIDITY, + 'qualification.packets.time-bound') + digest(plan['configuration']) + packets = plan['packets'] + require(type(packets) is list and 2 <= len(packets) <= 64, + 'qualification.packets.packet-bound') + labels, operations = set(), set() + for packet in packets: + closed(packet, ['label', 'arguments']) + require(type(packet['label']) is str and packet['label'] not in labels + and packet['label'] in {phase + '-' + str(index).zfill(2) + for phase in ['commissioning', 'live'] for index in range(32)}, + 'qualification.packets.packet-bound') + labels.add(packet['label']) + value = packet['arguments'] + fields = ['operator_namespace', 'operation_id', 'recipe_digest'] + fields += ['payment_intent', 'amount', 'currency'] if plan['family'] == stripe_platform.FAMILY else ['record_id', 'replacement'] + closed(value, fields) + operation = 'qlf-' + sha256(canonical([plan['family'], plan['protected_run'], packet['label']]))[:48] + require(value['operation_id'] == operation and operation not in operations, + 'qualification.packets.operation-binding') + digest(value['recipe_digest']) + operations.add(operation) + require(len({packet['arguments']['recipe_digest'] for packet in packets}) == 1, + 'qualification.packets.recipe-binding') + require(packets == arguments(plan['family'], plan['resources'], packets[0]['arguments']['recipe_digest']) + and plan['resources']['protected_run'] == plan['protected_run'], + 'qualification.packets.resource-binding') + extension = plan['extension'] + if plan['family'] == stripe_platform.FAMILY: + closed(extension, ['extension_id', 'extension_body_hex']) + require(extension['extension_id'] == 'bounded-policy-commitment-v1' + and type(extension['extension_body_hex']) is str + and 0 < len(extension['extension_body_hex']) <= 8192 + and len(extension['extension_body_hex']) % 2 == 0 + and all(character in '0123456789abcdef' for character in extension['extension_body_hex']), + 'qualification.packets.extension-bound') + else: + require(extension is None, 'qualification.packets.extension-bound') + return plan + + +def prepare(args): + reference = REFERENCES.get(args.family) + require(reference is not None, 'qualification.packets.family') + resources = decode(read(args.resources, 65536)) + reference.resources(resources, run_id(resources['protected_run'])) + source = SOURCES[args.family] + recipe = reference.recipe(decode(read(source / 'recipe.json', 65536)), resources) + # The private output directory must already exist. No private author key + # or credential is ever created here, and existing outputs are refused. + write(args.work / 'recipe.json', recipe, new=True) + lock = read(source / 'profile.lock.json', 65536) + write_bytes(args.work / 'profile.lock.json', lock, new=True) + review = child(args.gateway, ['review', '--recipe', args.work / 'recipe.json', + '--profile-lock', args.work / 'profile.lock.json']) + require(review.get('schema') == 'auths.gateway-recipe-review/2', 'qualification.packets.native-review') + extension = None + if reference is stripe_platform: + derived = child(args.gateway, ['bound-extension', '--argument', 'amount', '--ceiling', '10000', + '--window-seconds', '86400', '--max-count', '64', '--sum-limit', '32000', '--partition', 'currency=usd', + '--scope', 'payment_intent=' + ','.join(payment['id'] for payment in resources['payments'])]) + extension = {name: derived[name] for name in ['extension_id', 'extension_body_hex']} + evaluated_at = int(time.time()) + plan = validate({'schema': 'auths.qualification-packet-plan/1', 'family': args.family, + 'protected_run': resources['protected_run'], 'evaluated_at': evaluated_at, + 'not_after': evaluated_at + PACKET_VALIDITY, 'configuration': review['verifier_configuration'], + 'extension': extension, 'resources': resources, + 'packets': arguments(args.family, resources, review['recipe_digest'])}) + write(args.work / 'packet-plan.json', plan, new=True) + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--family', choices=sorted(REFERENCES), required=True) + for name in ['resources', 'gateway', 'work']: + parser.add_argument('--' + name, type=lambda value: Path(value).absolute(), required=True) + args = parser.parse_args() + finish(lambda: prepare(args)) + + +if __name__ == '__main__': + main() diff --git a/qualification/reference/resource_io.py b/qualification/reference/resource_io.py index aa8999530..7445cd702 100644 --- a/qualification/reference/resource_io.py +++ b/qualification/reference/resource_io.py @@ -5,6 +5,7 @@ from pathlib import Path import re import stat +import subprocess import sys import urllib.error import urllib.request @@ -67,14 +68,21 @@ def read(path): def write(path, value, *, new=False): + payload = canonical(value) + require(len(payload) <= 65536, 'qualification.resources.ledger-bound') + write_bytes(path, payload, new=new) + + +def write_bytes(path, payload, *, new=False): + """Durably write bounded public protocol bytes in an owner-private parent.""" + require(type(payload) is bytes and 0 < len(payload) <= 4 * 1024 * 1024, + 'qualification.resources.ledger-bound') path = Path(path) parent = path.parent info = os.lstat(parent) require(stat.S_ISDIR(info.st_mode) and not stat.S_ISLNK(info.st_mode) and info.st_uid == os.getuid() and stat.S_IMODE(info.st_mode) == 0o700, 'qualification.resources.private-output') - payload = canonical(value) - require(len(payload) <= 65536, 'qualification.resources.ledger-bound') if new: fd = os.open(path, os.O_WRONLY | os.O_CREAT | os.O_EXCL | os.O_NOFOLLOW, 0o600) with os.fdopen(fd, 'wb') as stream: @@ -112,6 +120,7 @@ def finish(command): code = 'qualification.resources.refused' print(code, file=sys.stderr) raise SystemExit(1) from None - except (ValueError, OSError): + except (ValueError, OSError, KeyError, TypeError, ImportError, OverflowError, + RecursionError, subprocess.SubprocessError): print('qualification.resources.refused', file=sys.stderr) raise SystemExit(1) from None diff --git a/qualification/reference/tests/test_packets.py b/qualification/reference/tests/test_packets.py new file mode 100644 index 000000000..23f677795 --- /dev/null +++ b/qualification/reference/tests/test_packets.py @@ -0,0 +1,62 @@ +"""Packet confinement and refresh protocol; no protected evidence is claimed.""" + +import copy +import os +from pathlib import Path +import sys +import unittest +from unittest.mock import patch + +sys.path.insert(0, str(Path(__file__).resolve().parents[1])) +import airtable_record +import author_packets +import packet_plan +from common import Refusal, canonical + + +class Packets(unittest.TestCase): + def plan(self): + resources = {'schema': 'auths.airtable-record-qualification-resources/1', + 'protected_run': 'recipe-qualification/123/1', 'base': airtable_record.BASE, + 'table': airtable_record.TABLE, 'records': [ + {'id': 'recTEST0000000001', 'run_metadata': 'recipe-qualification/123/1'}]} + return {'schema': 'auths.qualification-packet-plan/1', 'family': airtable_record.FAMILY, + 'protected_run': resources['protected_run'], 'evaluated_at': 1000, 'not_after': 8200, + 'configuration': '1' * 64, 'extension': None, 'resources': resources, + 'packets': packet_plan.arguments(airtable_record.FAMILY, resources, '2' * 64)} + + def test_resource_action_and_phase_changes_cannot_choose_refresh_authority(self): + plan = self.plan() + self.assertEqual(packet_plan.validate(plan), plan) + changes = [lambda p: p['packets'][0]['arguments'].update(record_id='recOTHER000000001'), + lambda p: p['packets'][0]['arguments'].update(replacement='Deleted'), + lambda p: p['packets'][0]['arguments'].update(operation_id='another-run'), + lambda p: p['packets'][0].update(label='../../provider-secret'), + lambda p: p['resources'].update(base='appOTHER'), + lambda p: p.update(not_after=9000), lambda p: p.update(evaluated_at=True), + lambda p: p.update(credential='synthetic-forbidden-input'), + lambda p: p['packets'].reverse(), lambda p: p['packets'].pop()] + for change in changes: + changed = copy.deepcopy(plan) + change(changed) + with self.assertRaises(Refusal): packet_plan.validate(changed) + + def test_refresh_input_is_closed_bounded_and_monotonic(self): + value = {'command': 'refresh', 'label': 'live-00', 'generation': 1} + self.assertEqual(author_packets.command(canonical(value) + b'\n', 0), value) + self.assertIsNone(author_packets.command(b'{"command":"close"}\n', 0)) + for changed in [dict(value, generation=2), dict(value, generation=True), + dict(value, arguments={}), dict(value, credential='synthetic-forbidden-input'), + dict(value, label=[]), dict(value, command='sign-arbitrary')]: + with self.assertRaises(Refusal): author_packets.command(canonical(changed) + b'\n', 0) + for raw in [canonical(value), b' ' * 513 + b'\n', b'{"command":"close","command":"refresh"}\n']: + with self.assertRaises(Refusal): author_packets.command(raw, 0) + + def test_an_unanticipated_credential_name_refuses_before_importing_the_sdk(self): + with patch.dict(os.environ, {'UNANTICIPATED_PROVIDER_KEY': 'synthetic-forbidden-input'}, clear=True): + with self.assertRaisesRegex(Refusal, 'consumer-environment'): + author_packets.installed_native() + + +if __name__ == '__main__': + unittest.main() diff --git a/qualification/reference/tests/test_reference.py b/qualification/reference/tests/test_reference.py index 676f5c869..1187df3e4 100644 --- a/qualification/reference/tests/test_reference.py +++ b/qualification/reference/tests/test_reference.py @@ -189,7 +189,8 @@ def test_binding_is_rederived_and_altered_source_or_native_observations_refuse(s (work / 'action.cbor').write_bytes(b'synthetic test-only action') (work / 'resources.json').write_bytes(canonical(self.stripe_resources())) (work / 'packets.json').write_bytes(canonical({ - 'schema': 'auths.qualification-public-packets/1', 'protected_run': RUN, + 'schema': 'auths.qualification-public-packets/2', 'protected_run': RUN, + 'evaluated_at': 1000, 'not_after': 1300, 'trusted_context': 'context.cbor', 'packets': [{'label': 'normal', 'proof': 'proof.cbor', 'action': 'action.cbor', 'arguments': self.stripe_arguments()}]})) @@ -220,7 +221,8 @@ def review(_binary, arguments): 'arguments': self.stripe_arguments(), 'request': stripe.request(self.stripe_arguments(), self.stripe_resources(), COMMITMENT, DIGEST)} with patch.dict(os.environ, {'GITHUB_SHA': '1' * 40, 'GITHUB_RUN_ID': '123', - 'GITHUB_RUN_ATTEMPT': '1'}), patch('expand.child', side_effect=review): + 'GITHUB_RUN_ATTEMPT': '1'}), patch('expand.child', side_effect=review), \ + patch('expand.time.time', return_value=1000): expansion.expand(args) binding = json.loads((args.out_dir / 'binding.json').read_bytes()) self.assertEqual(binding['allowed_actions'], [COMMITMENT]) From 47dfc3ca00de2ddf1656698ad257d00d8ef24877 Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 06:14:17 +0100 Subject: [PATCH 067/108] Scan the complete qualification publication tree before retaining evidence --- .github/workflows/recipe-qualification.yml | 27 ++-- ...NDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md | 1 + .../tests/script_pipeline.rs | 33 ++++- .../reference/tests/test_publication.py | 66 ++++++++++ qualification/run/offline.sh | 12 +- qualification/run/redact.sh | 36 ++---- qualification/run/scan_publication.py | 122 ++++++++++++++++++ 7 files changed, 254 insertions(+), 43 deletions(-) create mode 100644 qualification/reference/tests/test_publication.py create mode 100644 qualification/run/scan_publication.py diff --git a/.github/workflows/recipe-qualification.yml b/.github/workflows/recipe-qualification.yml index e35485419..fef795a72 100644 --- a/.github/workflows/recipe-qualification.yml +++ b/.github/workflows/recipe-qualification.yml @@ -198,7 +198,7 @@ jobs: offline: name: candidate and offline evidence (${{ matrix.family }}) - needs: families + needs: [families, candidate] if: needs.families.outputs.list != '[]' runs-on: ubuntu-latest timeout-minutes: 60 @@ -213,17 +213,20 @@ jobs: - uses: ./.github/actions/setup-rust-cache with: toolchain: 1.97.1 - - name: Build the candidate and run the offline stages + - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 + with: + name: qualification-shipping-candidate-${{ github.run_id }}-${{ github.run_attempt }} + path: ${{ runner.temp }}/candidate + - name: Run offline stages on the exact shipping candidate shell: bash env: FAMILY: ${{ matrix.family }} - run: qualification/run/offline.sh "${FAMILY}" "${RUNNER_TEMP}/work" - - name: Keep the candidate's binaries with its evidence - shell: bash run: | set -euo pipefail - mkdir -p "${RUNNER_TEMP}/work/bin" - cp target/release/auths-gateway target/release/auths-qualification "${RUNNER_TEMP}/work/bin/" + chmod +x "${RUNNER_TEMP}/candidate/bin/"* + export AUTHS_GATEWAY="${RUNNER_TEMP}/candidate/bin/auths-gateway" + export AUTHS_QUALIFICATION="${RUNNER_TEMP}/candidate/bin/auths-qualification" + qualification/run/offline.sh "${FAMILY}" "${RUNNER_TEMP}/work" - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: name: offline-${{ matrix.family }} @@ -236,7 +239,7 @@ jobs: # family has its own protected environment holding only that family's # qualification credential, which is not a production credential. name: live evidence (${{ matrix.family }}) - needs: [families, offline] + needs: [families, candidate, offline] if: github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main' runs-on: ubuntu-latest timeout-minutes: 90 @@ -261,6 +264,10 @@ jobs: with: name: offline-${{ matrix.family }} path: ${{ runner.temp }}/work + - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 + with: + name: qualification-shipping-candidate-${{ github.run_id }}-${{ github.run_attempt }} + path: ${{ runner.temp }}/candidate - name: Run the family's live harness shell: bash env: @@ -268,8 +275,8 @@ jobs: AUTHS_QUALIFICATION_PROVIDER_CREDENTIAL: ${{ secrets.QUALIFICATION_PROVIDER_CREDENTIAL }} run: | set -euo pipefail - chmod +x "${RUNNER_TEMP}/work/bin/"* - export AUTHS_GATEWAY="${RUNNER_TEMP}/work/bin/auths-gateway" + chmod +x "${RUNNER_TEMP}/candidate/bin/"* + export AUTHS_GATEWAY="${RUNNER_TEMP}/candidate/bin/auths-gateway" export AUTHS_QUALIFICATION="${GITHUB_WORKSPACE}/target/release/auths-qualification" qualification/run/live.sh "${FAMILY}" "${RUNNER_TEMP}/work" - name: Scan what the run kept, then remove the canaries diff --git a/docs/research/INDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md b/docs/research/INDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md index 1c1422eb6..85a101095 100644 --- a/docs/research/INDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md +++ b/docs/research/INDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md @@ -17,6 +17,7 @@ audit or real-user trial is claimed. | Existing AWS roles trust the `gateway-custody-live` environment, while the qualification template names separate family environments. | Inspected the existing reviewer-protected custody environment. Its branch policy is currently unset. Automatic approval review rejected tightening that shared environment and uploading local provider credentials there because that destination was not explicitly authorized. No environment change or provider-key upload occurred; protected orchestration remains pending. No role trust or gate is weakened. | | Main-only protected code must be deployed before the first protected qualification run. | A bounded prerequisite rollout of the completed runner is needed before collecting evidence. Epic acceptance stays open until actual runs, signed closure and CI are complete. | | Normal authored actions expire while a protected signing job waits. | Keep the installed author in an isolated process for a bounded two-hour grant/session. Refresh only the same predeclared action just before submission; native signatures keep the ordinary five-minute action limit, exact actor/action/request and installation trust. No private key enters artifacts. Both native Docker rehearsals passed with synthetic resources and no network; protected sequencing still needs integration. | +| Publication scanning omitted newly added commissioning files and other unlisted outputs. | Replace the filename allowlist with a bounded complete-tree scan. Refuse symbolic/hard links, special or oversized files and concurrent changes; keep canaries private and outside artifacts. Move shipping executables outside the evidence tree and use one credential-free candidate build. Native pipeline regressions plant leaks in commissioning effects, source facts and an unexpected filename. | The public offline root ceremony and purpose-separated certificates are pinned. Both signer keys are provisioned in the existing reviewer-protected main-only diff --git a/product/qualification/auths-recipe-qualification-issuance/tests/script_pipeline.rs b/product/qualification/auths-recipe-qualification-issuance/tests/script_pipeline.rs index 0068ada1f..61e16bf41 100644 --- a/product/qualification/auths-recipe-qualification-issuance/tests/script_pipeline.rs +++ b/product/qualification/auths-recipe-qualification-issuance/tests/script_pipeline.rs @@ -6,7 +6,7 @@ mod common; -use std::{fs, path::Path, process::Command}; +use std::{fs, os::unix::fs::PermissionsExt, path::Path, process::Command}; fn succeed(command: &mut Command) { let output = command.output().expect("command"); @@ -93,12 +93,43 @@ fn stage_reports_flow_through_redaction_and_assembly_and_missing_execution_refus }); fs::write(work.join("facts.json"), facts.to_string()).expect("facts"); fs::write(work.join("canaries"), "synthetic-canary-not-a-credential\n").expect("canaries"); + fs::set_permissions(work.join("canaries"), fs::Permissions::from_mode(0o600)) + .expect("private canaries"); for kind in ["log", "trace", "metric", "support-bundle"] { let directory = work.join("scan").join(kind); fs::create_dir_all(&directory).expect("scan directory"); fs::write(directory.join("test-output"), "closed test states only").expect("output"); } let scripts = Path::new(env!("CARGO_MANIFEST_DIR")).join("../../../qualification/run"); + for name in [ + "commissioning-effects.json", + "facts.json", + "unexpected-public-output", + ] { + let path = work.join(name); + let original = fs::read(&path).ok(); + fs::write(&path, "synthetic-canary-not-a-credential").expect("planted leak"); + let refused = Command::new("bash") + .arg(scripts.join("redact.sh")) + .arg(&work) + .env("AUTHS_QUALIFICATION", tool) + .current_dir(&root) + .output() + .expect("redaction refusal"); + assert!(!refused.status.success(), "unlisted output must be scanned"); + assert!( + work.join("canaries").exists(), + "retain private scan inputs on failure" + ); + assert!(!work.join("cases/redaction.scan.json").exists()); + assert!( + !String::from_utf8_lossy(&refused.stderr).contains("synthetic-canary-not-a-credential") + ); + match original { + Some(bytes) => fs::write(path, bytes).expect("restore public fact"), + None => fs::remove_file(path).expect("remove leak"), + } + } succeed( Command::new("bash") .arg(scripts.join("redact.sh")) diff --git a/qualification/reference/tests/test_publication.py b/qualification/reference/tests/test_publication.py new file mode 100644 index 000000000..f59acb27a --- /dev/null +++ b/qualification/reference/tests/test_publication.py @@ -0,0 +1,66 @@ +"""Publication-tree confinement; native leak decisions run in the Rust pipeline.""" + +import importlib.util +import os +from pathlib import Path +import tempfile +import unittest + +path = Path(__file__).resolve().parents[2] / 'run/scan_publication.py' +spec = importlib.util.spec_from_file_location('scan_publication', path) +publication = importlib.util.module_from_spec(spec) +spec.loader.exec_module(publication) + + +class Publication(unittest.TestCase): + def workspace(self): + temporary = tempfile.TemporaryDirectory() + self.addCleanup(temporary.cleanup) + work = Path(temporary.name).resolve() + (work / 'cases').mkdir() + (work / 'canaries').write_bytes(b'synthetic-private-scan-canary\n') + (work / 'canaries').chmod(0o600) + (work / 'commissioning-effects.json').write_bytes(b'closed synthetic facts') + return work + + def test_unlisted_phase_files_and_all_output_kinds_enter_the_scan(self): + work = self.workspace() + for kind in ['log', 'trace', 'metric', 'support-bundle']: + directory = work / 'scan' / kind + directory.mkdir(parents=True) + (directory / 'retained-output').write_bytes(b'closed synthetic state') + (work / 'unexpected-output').write_bytes(b'closed synthetic public data') + values = publication.sources(work) + self.assertEqual(len(values), 6) + self.assertEqual({kind for _, kind, _ in values}, + {'log', 'trace', 'metric', 'support-bundle', 'evidence'}) + self.assertIn('commissioning-effects.json', {name for name, _, _ in values}) + self.assertIn('unexpected-output', {name for name, _, _ in values}) + self.assertNotIn('canaries', {name for name, _, _ in values}) + + def test_links_special_files_and_public_canaries_refuse(self): + for mode in ['file-link', 'directory-link', 'hard-link', 'fifo', 'public-canary']: + work = self.workspace() + if mode == 'file-link': + (work / 'linked-output').symlink_to(work / 'canaries') + elif mode == 'directory-link': + (work / 'linked-directory').symlink_to(work / 'cases', target_is_directory=True) + elif mode == 'hard-link': + os.link(work / 'canaries', work / 'linked-output') + elif mode == 'fifo': + os.mkfifo(work / 'fifo') + else: + (work / 'canaries').chmod(0o644) + with self.assertRaises(publication.Refusal, msg=mode): publication.sources(work) + + def test_no_executable_or_oversized_source_is_silently_excluded(self): + work = self.workspace() + binary = work / 'bin/auths-gateway' + binary.parent.mkdir() + with binary.open('wb') as stream: + stream.truncate(publication.MAX_BYTES + 1) + with self.assertRaises(publication.Refusal): publication.sources(work) + + +if __name__ == '__main__': + unittest.main() diff --git a/qualification/run/offline.sh b/qualification/run/offline.sh index fe6aa68f1..80be28ed8 100755 --- a/qualification/run/offline.sh +++ b/qualification/run/offline.sh @@ -3,8 +3,8 @@ # # offline.sh # -# Builds the release candidate from a clean tree, runs the family's offline -# harness, and runs the trust stages for the tuple the harness reported. +# Uses the credential-free job's exact candidate from a clean source revision, +# runs the family harness and runs the trust stages for its reported tuple. # Writes into : tuple.json, packages.json, cases/*.json, facts.json. set -euo pipefail @@ -23,10 +23,10 @@ if [ -n "$(git -C "${root}" status --porcelain)" ]; then fi mkdir -p "${work}/cases" -cargo build --locked --release -p auths-gateway --bin auths-gateway -cargo build --locked --release -p auths-recipe-qualification-issuance --bin auths-qualification -export AUTHS_GATEWAY="${root}/target/release/auths-gateway" -export AUTHS_QUALIFICATION="${root}/target/release/auths-qualification" +export AUTHS_GATEWAY="${AUTHS_GATEWAY:?qualification.candidate-not-supplied}" +export AUTHS_QUALIFICATION="${AUTHS_QUALIFICATION:?qualification.issuer-not-supplied}" +# Candidate bytes are built once by the credential-free job and kept outside +# the public evidence directory; the tuple binds that exact executable. "${directory}/harness" prepare "${work}" # Derive the planned production identity without custody or provider access. diff --git a/qualification/run/redact.sh b/qualification/run/redact.sh index a6a300fef..278b782bb 100755 --- a/qualification/run/redact.sh +++ b/qualification/run/redact.sh @@ -3,38 +3,22 @@ # the canaries. Runs in the live job, the only place the canaries exist, so # nothing unscanned and no canary leaves that job. # -# redact.sh +# redact.sh [commissioning|live] # # Writes /cases/redaction.scan.json and deletes /canaries. set -euo pipefail work="${1:?usage: redact.sh }" +phase="${2:-live}" +[[ "${phase}" = commissioning || "${phase}" = live ]] \ + || { echo "qualification.invalid-stage" >&2; exit 1; } root="$(git rev-parse --show-toplevel)" tool="${AUTHS_QUALIFICATION:-${root}/target/release/auths-qualification}" [ -s "${work}/canaries" ] || { echo "qualification.evidence-incomplete canaries" >&2; exit 1; } -# One canary per line; a carriage return is not part of a canary. -tr -d '\r' < "${work}/canaries" > "${work}/canaries.clean" -mv "${work}/canaries.clean" "${work}/canaries" - -sources=() -for kind in log trace metric support-bundle; do - while IFS= read -r -d '' file; do - sources+=(--source "${kind}=${file}") - done < <(find "${work}/scan/${kind}" -type f -print0 2>/dev/null | sort -z) -done -# Everything else the run publishes: the case reports and the facts that -# enter the record. -while IFS= read -r -d '' file; do - sources+=(--source "evidence=${file}") -done < <(find "${work}/cases" -type f -name '*.json' -print0 | sort -z) -for published in tuple.json packages.json resources.json live-effects.json; do - [ -s "${work}/${published}" ] && sources+=(--source "evidence=${work}/${published}") -done - -rm -f "${work}/cases/redaction.scan.json" -"${tool}" stage-redaction --canaries "${work}/canaries" "${sources[@]}" \ - --out "${work}/redaction.cases.json" -mv "${work}/redaction.cases.json" "${work}/cases/redaction.scan.json" -rm -f "${work}/canaries" -echo "redaction scan passed; canaries removed" +arguments=(--work "${work}" --tool "${tool}") +if [[ "${phase}" = commissioning ]]; then + arguments+=(--keep-canaries) +fi +python3 "$(dirname "${BASH_SOURCE[0]}")/scan_publication.py" "${arguments[@]}" +echo "redaction scan passed for ${phase}" diff --git a/qualification/run/scan_publication.py b/qualification/run/scan_publication.py new file mode 100644 index 000000000..4a07138a0 --- /dev/null +++ b/qualification/run/scan_publication.py @@ -0,0 +1,122 @@ +#!/usr/bin/env python3 +"""Scan every retained public file, including newly added phase evidence. + +The one private canary file is excluded and never published. Executables and +other private inputs belong outside this publication tree. Symbolic/hard links, +special files, oversized sources and concurrent changes refuse publication. +""" + +import argparse +import hashlib +import os +from pathlib import Path +import stat +import subprocess +import sys + +MAX_FILES = 256 +MAX_BYTES = 2 * 1024 * 1024 +MAX_TOTAL_BYTES = 32 * 1024 * 1024 +KINDS = {'log', 'trace', 'metric', 'support-bundle'} + + +class Refusal(ValueError): + pass + + +def require(value): + if not value: + raise Refusal('qualification.publication.refused') + + +def contents(path): + descriptor = os.open(path, os.O_RDONLY | os.O_NOFOLLOW) + with os.fdopen(descriptor, 'rb') as stream: + info = os.fstat(stream.fileno()) + require(stat.S_ISREG(info.st_mode) and info.st_nlink == 1 and info.st_size <= MAX_BYTES) + payload = stream.read(MAX_BYTES + 1) + require(len(payload) <= MAX_BYTES) + return payload + + +def sources(work): + require(stat.S_ISDIR(os.lstat(work).st_mode)) + work = work.resolve() + result, total = [], 0 + for parent, directories, files in os.walk(work, followlinks=False): + for name in directories: + require(stat.S_ISDIR(os.lstat(Path(parent) / name).st_mode)) + for name in files: + path = Path(parent) / name + info = os.lstat(path) + require(stat.S_ISREG(info.st_mode) and info.st_nlink == 1) + relative = path.relative_to(work) + if relative == Path('canaries'): + require(info.st_uid == os.getuid() and stat.S_IMODE(info.st_mode) & 0o077 == 0) + continue + require(relative != Path('cases/redaction.scan.json')) + payload = contents(path) + total += len(payload) + require(total <= MAX_TOTAL_BYTES and len(result) < MAX_FILES) + kind = relative.parts[1] if len(relative.parts) >= 3 and relative.parts[0] == 'scan' \ + and relative.parts[1] in KINDS else 'evidence' + result.append((relative.as_posix(), kind, hashlib.sha256(payload).hexdigest())) + require(result) + return sorted(result) + + +def scan(work, tool, keep_canaries=False): + require(stat.S_ISDIR(os.lstat(work).st_mode)) + work = work.resolve() + require(stat.S_ISDIR(os.lstat(work / 'cases').st_mode)) + report = work / 'cases/redaction.scan.json' + report.unlink(missing_ok=True) + before = sources(work) + arguments = [str(tool), 'stage-redaction', '--canaries', str(work / 'canaries')] + for name, kind, _digest in before: + arguments += ['--source', kind + '=' + str(work / name)] + arguments += ['--out', str(report)] + try: + result = subprocess.run(arguments, capture_output=True, timeout=120, + cwd='/', env={'PATH': '/usr/bin:/bin'}) + except subprocess.SubprocessError: + report.unlink(missing_ok=True) + raise + # Native diagnostics may contain input paths. They never enter job logs. + if result.returncode != 0: + report.unlink(missing_ok=True) + raise Refusal('qualification.publication.refused') + require(len(result.stdout) <= MAX_BYTES and len(result.stderr) <= MAX_BYTES) + # Recheck the complete tree, including unanticipated added files. A report + # is the only output allowed between the pre-scan and post-scan inventories. + report_bytes = contents(report) + report.unlink() + try: + require(sources(work) == before) + descriptor = os.open(report, os.O_WRONLY | os.O_CREAT | os.O_EXCL | os.O_NOFOLLOW, 0o600) + with os.fdopen(descriptor, 'wb') as stream: + stream.write(report_bytes) + stream.flush() + os.fsync(stream.fileno()) + except (ValueError, OSError): + report.unlink(missing_ok=True) + raise + if not keep_canaries: + (work / 'canaries').unlink() + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--work', type=lambda value: Path(value).absolute(), required=True) + parser.add_argument('--tool', type=lambda value: Path(value).absolute(), required=True) + parser.add_argument('--keep-canaries', action='store_true') + args = parser.parse_args() + try: + scan(args.work, args.tool, args.keep_canaries) + except (ValueError, OSError, subprocess.SubprocessError): + print('qualification.publication.refused', file=sys.stderr) + raise SystemExit(1) from None + + +if __name__ == '__main__': + main() From 84eb5e389db322e448be9746aade2746875885d3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 7 Oct 2026 06:18:05 +0000 Subject: [PATCH 068/108] chore(formal): regenerate qualification artifacts Source-SHA: 47dfc3ca00de2ddf1656698ad257d00d8ef24877 Workflow-Run: 37575326551 --- formal/assurance-manifest-v1.toml | 118 +++++++++++++++--------------- 1 file changed, 59 insertions(+), 59 deletions(-) diff --git a/formal/assurance-manifest-v1.toml b/formal/assurance-manifest-v1.toml index f1195d0ed..cce988bec 100644 --- a/formal/assurance-manifest-v1.toml +++ b/formal/assurance-manifest-v1.toml @@ -8733,7 +8733,7 @@ sha256 = "2bb401ffca0136622cd79bb14a5a38852061649a06cc46100503870c22d300c7" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" +sha256 = "b9545f8e955554f32a852d87029fab3d96a6faa5ebe07667b83c0b1b209b4439" [[claims]] claim_id = "AP-FORMAL-RICH-055" @@ -8854,7 +8854,7 @@ sha256 = "2bb401ffca0136622cd79bb14a5a38852061649a06cc46100503870c22d300c7" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" +sha256 = "b9545f8e955554f32a852d87029fab3d96a6faa5ebe07667b83c0b1b209b4439" [[claims]] claim_id = "AP-FORMAL-RICH-056" @@ -8989,7 +8989,7 @@ sha256 = "2bb401ffca0136622cd79bb14a5a38852061649a06cc46100503870c22d300c7" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" +sha256 = "b9545f8e955554f32a852d87029fab3d96a6faa5ebe07667b83c0b1b209b4439" [[claims]] claim_id = "AP-FORMAL-RICH-104" @@ -10463,7 +10463,7 @@ sha256 = "ba7aea214063b8a698fbd2c9c8cd95a717bf0ec0eaef70a92844444bf7e9f22e" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" +sha256 = "b9545f8e955554f32a852d87029fab3d96a6faa5ebe07667b83c0b1b209b4439" [[claims]] claim_id = "AP-FORMAL-RICH-263" @@ -10559,7 +10559,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" +sha256 = "b9545f8e955554f32a852d87029fab3d96a6faa5ebe07667b83c0b1b209b4439" [[claims]] claim_id = "AP-FORMAL-RICH-264" @@ -10658,7 +10658,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" +sha256 = "b9545f8e955554f32a852d87029fab3d96a6faa5ebe07667b83c0b1b209b4439" [[claims]] claim_id = "AP-FORMAL-RICH-186" @@ -10918,7 +10918,7 @@ sha256 = "ba7aea214063b8a698fbd2c9c8cd95a717bf0ec0eaef70a92844444bf7e9f22e" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" +sha256 = "b9545f8e955554f32a852d87029fab3d96a6faa5ebe07667b83c0b1b209b4439" [[claims]] claim_id = "AP-FORMAL-RICH-237" @@ -11014,7 +11014,7 @@ sha256 = "ba7aea214063b8a698fbd2c9c8cd95a717bf0ec0eaef70a92844444bf7e9f22e" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" +sha256 = "b9545f8e955554f32a852d87029fab3d96a6faa5ebe07667b83c0b1b209b4439" [[claims]] claim_id = "AP-FORMAL-RICH-238" @@ -11113,7 +11113,7 @@ sha256 = "ba7aea214063b8a698fbd2c9c8cd95a717bf0ec0eaef70a92844444bf7e9f22e" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" +sha256 = "b9545f8e955554f32a852d87029fab3d96a6faa5ebe07667b83c0b1b209b4439" [[claims]] claim_id = "AP-FORMAL-RICH-175" @@ -15048,7 +15048,7 @@ sha256 = "c8c86db058f313ab46ee86370d79ee70130c1ead3860dd7dabd49f2a89af1636" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" +sha256 = "b9545f8e955554f32a852d87029fab3d96a6faa5ebe07667b83c0b1b209b4439" [[claims]] claim_id = "AP-FORMAL-RICH-211" @@ -15143,7 +15143,7 @@ sha256 = "c8c86db058f313ab46ee86370d79ee70130c1ead3860dd7dabd49f2a89af1636" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" +sha256 = "b9545f8e955554f32a852d87029fab3d96a6faa5ebe07667b83c0b1b209b4439" [[claims]] claim_id = "AP-FORMAL-RICH-212" @@ -15239,7 +15239,7 @@ sha256 = "c8c86db058f313ab46ee86370d79ee70130c1ead3860dd7dabd49f2a89af1636" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" +sha256 = "b9545f8e955554f32a852d87029fab3d96a6faa5ebe07667b83c0b1b209b4439" [[claims]] claim_id = "AP-FORMAL-RICH-213" @@ -15335,7 +15335,7 @@ sha256 = "c8c86db058f313ab46ee86370d79ee70130c1ead3860dd7dabd49f2a89af1636" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" +sha256 = "b9545f8e955554f32a852d87029fab3d96a6faa5ebe07667b83c0b1b209b4439" [[claims]] claim_id = "AP-FORMAL-RICH-214" @@ -15431,7 +15431,7 @@ sha256 = "c8c86db058f313ab46ee86370d79ee70130c1ead3860dd7dabd49f2a89af1636" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" +sha256 = "b9545f8e955554f32a852d87029fab3d96a6faa5ebe07667b83c0b1b209b4439" [[claims]] claim_id = "AP-FORMAL-RICH-232" @@ -15530,7 +15530,7 @@ sha256 = "c8c86db058f313ab46ee86370d79ee70130c1ead3860dd7dabd49f2a89af1636" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" +sha256 = "b9545f8e955554f32a852d87029fab3d96a6faa5ebe07667b83c0b1b209b4439" [[claims]] claim_id = "AP-FORMAL-RICH-233" @@ -15626,7 +15626,7 @@ sha256 = "c8c86db058f313ab46ee86370d79ee70130c1ead3860dd7dabd49f2a89af1636" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" +sha256 = "b9545f8e955554f32a852d87029fab3d96a6faa5ebe07667b83c0b1b209b4439" [[claims]] claim_id = "AP-FORMAL-RICH-234" @@ -15722,7 +15722,7 @@ sha256 = "c8c86db058f313ab46ee86370d79ee70130c1ead3860dd7dabd49f2a89af1636" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" +sha256 = "b9545f8e955554f32a852d87029fab3d96a6faa5ebe07667b83c0b1b209b4439" [[claims]] claim_id = "AP-FORMAL-RICH-235" @@ -15818,7 +15818,7 @@ sha256 = "c8c86db058f313ab46ee86370d79ee70130c1ead3860dd7dabd49f2a89af1636" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" +sha256 = "b9545f8e955554f32a852d87029fab3d96a6faa5ebe07667b83c0b1b209b4439" [[claims]] claim_id = "AP-FORMAL-RICH-249" @@ -16485,7 +16485,7 @@ sha256 = "dfa1998e3506f06dce142222dc383116d0952155517edc399f5d94e688e22912" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" +sha256 = "b9545f8e955554f32a852d87029fab3d96a6faa5ebe07667b83c0b1b209b4439" [[claims]] claim_id = "AP-FORMAL-RICH-257" @@ -16584,7 +16584,7 @@ sha256 = "dfa1998e3506f06dce142222dc383116d0952155517edc399f5d94e688e22912" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" +sha256 = "b9545f8e955554f32a852d87029fab3d96a6faa5ebe07667b83c0b1b209b4439" [[claims]] claim_id = "AP-FORMAL-RICH-258" @@ -16683,7 +16683,7 @@ sha256 = "dfa1998e3506f06dce142222dc383116d0952155517edc399f5d94e688e22912" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" +sha256 = "b9545f8e955554f32a852d87029fab3d96a6faa5ebe07667b83c0b1b209b4439" [[claims]] claim_id = "AP-FORMAL-RICH-259" @@ -16779,7 +16779,7 @@ sha256 = "dfa1998e3506f06dce142222dc383116d0952155517edc399f5d94e688e22912" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" +sha256 = "b9545f8e955554f32a852d87029fab3d96a6faa5ebe07667b83c0b1b209b4439" [[claims]] claim_id = "AP-FORMAL-RICH-260" @@ -16878,7 +16878,7 @@ sha256 = "dfa1998e3506f06dce142222dc383116d0952155517edc399f5d94e688e22912" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" +sha256 = "b9545f8e955554f32a852d87029fab3d96a6faa5ebe07667b83c0b1b209b4439" [[claims]] claim_id = "AP-FORMAL-RICH-070" @@ -23876,7 +23876,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" +sha256 = "b9545f8e955554f32a852d87029fab3d96a6faa5ebe07667b83c0b1b209b4439" [[claims]] claim_id = "AP-FORMAL-RICH-189" @@ -23972,7 +23972,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" +sha256 = "b9545f8e955554f32a852d87029fab3d96a6faa5ebe07667b83c0b1b209b4439" [[claims]] claim_id = "AP-FORMAL-RICH-190" @@ -24068,7 +24068,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" +sha256 = "b9545f8e955554f32a852d87029fab3d96a6faa5ebe07667b83c0b1b209b4439" [[claims]] claim_id = "AP-FORMAL-RICH-191" @@ -24164,7 +24164,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" +sha256 = "b9545f8e955554f32a852d87029fab3d96a6faa5ebe07667b83c0b1b209b4439" [[claims]] claim_id = "AP-FORMAL-RICH-192" @@ -24259,7 +24259,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" +sha256 = "b9545f8e955554f32a852d87029fab3d96a6faa5ebe07667b83c0b1b209b4439" [[claims]] claim_id = "AP-FORMAL-RICH-193" @@ -24358,7 +24358,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" +sha256 = "b9545f8e955554f32a852d87029fab3d96a6faa5ebe07667b83c0b1b209b4439" [[claims]] claim_id = "AP-FORMAL-RICH-194" @@ -24457,7 +24457,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" +sha256 = "b9545f8e955554f32a852d87029fab3d96a6faa5ebe07667b83c0b1b209b4439" [[claims]] claim_id = "AP-FORMAL-RICH-195" @@ -24558,7 +24558,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" +sha256 = "b9545f8e955554f32a852d87029fab3d96a6faa5ebe07667b83c0b1b209b4439" [[claims]] claim_id = "AP-FORMAL-RICH-196" @@ -24662,7 +24662,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" +sha256 = "b9545f8e955554f32a852d87029fab3d96a6faa5ebe07667b83c0b1b209b4439" [[claims]] claim_id = "AP-FORMAL-RICH-197" @@ -24767,7 +24767,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" +sha256 = "b9545f8e955554f32a852d87029fab3d96a6faa5ebe07667b83c0b1b209b4439" [[claims]] claim_id = "AP-FORMAL-RICH-198" @@ -24863,7 +24863,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" +sha256 = "b9545f8e955554f32a852d87029fab3d96a6faa5ebe07667b83c0b1b209b4439" [[claims]] claim_id = "AP-FORMAL-RICH-199" @@ -24968,7 +24968,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" +sha256 = "b9545f8e955554f32a852d87029fab3d96a6faa5ebe07667b83c0b1b209b4439" [[claims]] claim_id = "AP-FORMAL-RICH-200" @@ -25063,7 +25063,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" +sha256 = "b9545f8e955554f32a852d87029fab3d96a6faa5ebe07667b83c0b1b209b4439" [[claims]] claim_id = "AP-FORMAL-RICH-201" @@ -25158,7 +25158,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" +sha256 = "b9545f8e955554f32a852d87029fab3d96a6faa5ebe07667b83c0b1b209b4439" [[claims]] claim_id = "AP-FORMAL-RICH-271" @@ -25254,7 +25254,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" +sha256 = "b9545f8e955554f32a852d87029fab3d96a6faa5ebe07667b83c0b1b209b4439" [[claims]] claim_id = "AP-FORMAL-RICH-272" @@ -25350,7 +25350,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" +sha256 = "b9545f8e955554f32a852d87029fab3d96a6faa5ebe07667b83c0b1b209b4439" [[claims]] claim_id = "AP-FORMAL-RICH-273" @@ -25449,7 +25449,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" +sha256 = "b9545f8e955554f32a852d87029fab3d96a6faa5ebe07667b83c0b1b209b4439" [[claims]] claim_id = "AP-FORMAL-RICH-274" @@ -25548,7 +25548,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" +sha256 = "b9545f8e955554f32a852d87029fab3d96a6faa5ebe07667b83c0b1b209b4439" [[claims]] claim_id = "AP-FORMAL-RICH-275" @@ -25649,7 +25649,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" +sha256 = "b9545f8e955554f32a852d87029fab3d96a6faa5ebe07667b83c0b1b209b4439" [[claims]] claim_id = "AP-FORMAL-RICH-276" @@ -25749,7 +25749,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" +sha256 = "b9545f8e955554f32a852d87029fab3d96a6faa5ebe07667b83c0b1b209b4439" [[claims]] claim_id = "AP-FORMAL-RICH-277" @@ -25848,7 +25848,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" +sha256 = "b9545f8e955554f32a852d87029fab3d96a6faa5ebe07667b83c0b1b209b4439" [[claims]] claim_id = "AP-FORMAL-RICH-278" @@ -25948,7 +25948,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" +sha256 = "b9545f8e955554f32a852d87029fab3d96a6faa5ebe07667b83c0b1b209b4439" [[claims]] claim_id = "AP-FORMAL-RICH-279" @@ -26047,7 +26047,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" +sha256 = "b9545f8e955554f32a852d87029fab3d96a6faa5ebe07667b83c0b1b209b4439" [[claims]] claim_id = "AP-FORMAL-RICH-280" @@ -26148,7 +26148,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" +sha256 = "b9545f8e955554f32a852d87029fab3d96a6faa5ebe07667b83c0b1b209b4439" [[claims]] claim_id = "AP-FORMAL-RICH-281" @@ -26248,7 +26248,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" +sha256 = "b9545f8e955554f32a852d87029fab3d96a6faa5ebe07667b83c0b1b209b4439" [[claims]] claim_id = "AP-FORMAL-RICH-282" @@ -26348,7 +26348,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" +sha256 = "b9545f8e955554f32a852d87029fab3d96a6faa5ebe07667b83c0b1b209b4439" [[claims]] claim_id = "AP-FORMAL-RICH-283" @@ -26448,7 +26448,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" +sha256 = "b9545f8e955554f32a852d87029fab3d96a6faa5ebe07667b83c0b1b209b4439" [[claims]] claim_id = "AP-FORMAL-RICH-284" @@ -26547,7 +26547,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" +sha256 = "b9545f8e955554f32a852d87029fab3d96a6faa5ebe07667b83c0b1b209b4439" [[claims]] claim_id = "AP-FORMAL-RICH-285" @@ -26649,7 +26649,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" +sha256 = "b9545f8e955554f32a852d87029fab3d96a6faa5ebe07667b83c0b1b209b4439" [[claims]] claim_id = "AP-FORMAL-RICH-306" @@ -26745,7 +26745,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" +sha256 = "b9545f8e955554f32a852d87029fab3d96a6faa5ebe07667b83c0b1b209b4439" [[claims]] claim_id = "AP-FORMAL-RICH-307" @@ -26844,7 +26844,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" +sha256 = "b9545f8e955554f32a852d87029fab3d96a6faa5ebe07667b83c0b1b209b4439" [[claims]] claim_id = "AP-FORMAL-RICH-308" @@ -26940,7 +26940,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" +sha256 = "b9545f8e955554f32a852d87029fab3d96a6faa5ebe07667b83c0b1b209b4439" [[claims]] claim_id = "AP-FORMAL-RICH-309" @@ -27039,7 +27039,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" +sha256 = "b9545f8e955554f32a852d87029fab3d96a6faa5ebe07667b83c0b1b209b4439" [[claims]] claim_id = "AP-FORMAL-RICH-310" @@ -27139,7 +27139,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" +sha256 = "b9545f8e955554f32a852d87029fab3d96a6faa5ebe07667b83c0b1b209b4439" [[claims]] claim_id = "AP-FORMAL-RICH-311" @@ -27238,7 +27238,7 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" +sha256 = "b9545f8e955554f32a852d87029fab3d96a6faa5ebe07667b83c0b1b209b4439" [[claims]] claim_id = "AP-FORMAL-RICH-312" @@ -27339,4 +27339,4 @@ sha256 = "d4d36b72718a4076b7c0561abfa2edc006a1f9a4491762979f86c3dd99a71fdc" [[claims.evidence]] kind = "source-closure" artifact = "formal/qualification/aeneas/source-closure.json" -sha256 = "9751d4995d89245a06ad2713c49edf2f2578b4c2d4f23e80e5006548671c3ee7" +sha256 = "b9545f8e955554f32a852d87029fab3d96a6faa5ebe07667b83c0b1b209b4439" From 77ec9c2bbed5b4426fcf37d3444d9fde2a2808b4 Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 10:38:03 +0100 Subject: [PATCH 069/108] Version the regenerated formal assurance inventory --- release/semantic-freeze-versions.toml | 6 +++--- release/semantic-freeze.json | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/release/semantic-freeze-versions.toml b/release/semantic-freeze-versions.toml index b95082eac..aebc692eb 100644 --- a/release/semantic-freeze-versions.toml +++ b/release/semantic-freeze-versions.toml @@ -1,4 +1,4 @@ -freeze_version = 378 +freeze_version = 379 # Semantic identity counters live outside the xtask source tree deliberately. # The formal source closure binds xtask's executable code, while the semantic @@ -16,7 +16,7 @@ freeze_version = 378 "auths.frozen-bytes/core/fixtures/v1/manifest.json" = 15 "auths.frozen-bytes/core/formal-vectors/v1/manifest.json" = 1 "auths.frozen-bytes/demos/benchmarks/profiles/release.toml" = 1 -"auths.frozen-bytes/formal/assurance-manifest-v1.toml" = 58 +"auths.frozen-bytes/formal/assurance-manifest-v1.toml" = 59 "auths.frozen-bytes/formal/qualification/aeneas/generated" = 19 "auths.frozen-bytes/formal/qualification/aeneas/qualification.toml" = 16 "auths.frozen-bytes/formal/qualification/aeneas/source-closure.json" = 99 @@ -67,4 +67,4 @@ freeze_version = 378 "auths.product.vocabulary" = 24 "auths.release.benchmark-contract" = 1 "auths.release.evolution-contract" = 79 -"auths.release.public-surface" = 378 +"auths.release.public-surface" = 379 diff --git a/release/semantic-freeze.json b/release/semantic-freeze.json index 2bc2a6242..5b1003510 100644 --- a/release/semantic-freeze.json +++ b/release/semantic-freeze.json @@ -1,6 +1,6 @@ { "schema": "auths.semantic-freeze/1", - "freezeVersion": 378, + "freezeVersion": 379, "publicSurface": { "rustRoots": [ "auths", @@ -202,7 +202,7 @@ }, { "id": "auths.frozen-bytes/formal/assurance-manifest-v1.toml", - "version": 58, + "version": 59, "classification": "frozen-bytes", "categories": [ "canonical-generated-evidence" @@ -210,7 +210,7 @@ "owners": [ "formal/assurance-manifest-v1.toml" ], - "sha256": "cc87f4480cc9eb559c810eba8534b844d05616e7e74c8732b39b5315616c65c3" + "sha256": "5f68f8b25a0294042ccfa121a2a13fbfcb5d3200f31bc55995c05f538d216cae" }, { "id": "auths.frozen-bytes/formal/qualification/aeneas/generated", @@ -1011,7 +1011,7 @@ }, { "id": "auths.release.public-surface", - "version": 378, + "version": 379, "classification": "release-metadata", "categories": [ "package-names", @@ -1104,7 +1104,7 @@ "xtask/src/release_launch.rs", "xtask/src/semantic_freeze.rs" ], - "sha256": "a37039df54c57b8d24bc0349317462349387932f6780cffc918bec17528e1007" + "sha256": "25cbd70c3906606c0556d54caaee0e53205646d5209ba431b9b60e73633606ed" } ] } From d149ba4c393097d308b9cea0888175657f937ef4 Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 10:43:05 +0100 Subject: [PATCH 070/108] Retain disposable resources across the complete protected journey --- .github/workflows/recipe-qualification.yml | 3 +- ...NDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md | 1 + .../tests/script_pipeline.rs | 40 +++++++++++++++- qualification/run/live.sh | 24 ++-------- qualification/run/resource-session.sh | 47 +++++++++++++++++++ 5 files changed, 91 insertions(+), 24 deletions(-) create mode 100644 qualification/run/resource-session.sh diff --git a/.github/workflows/recipe-qualification.yml b/.github/workflows/recipe-qualification.yml index fef795a72..6602b45be 100644 --- a/.github/workflows/recipe-qualification.yml +++ b/.github/workflows/recipe-qualification.yml @@ -278,7 +278,8 @@ jobs: chmod +x "${RUNNER_TEMP}/candidate/bin/"* export AUTHS_GATEWAY="${RUNNER_TEMP}/candidate/bin/auths-gateway" export AUTHS_QUALIFICATION="${GITHUB_WORKSPACE}/target/release/auths-qualification" - qualification/run/live.sh "${FAMILY}" "${RUNNER_TEMP}/work" + bash qualification/run/resource-session.sh "${FAMILY}" "${RUNNER_TEMP}/work" \ + bash qualification/run/live.sh "${FAMILY}" "${RUNNER_TEMP}/work" - name: Scan what the run kept, then remove the canaries # The scan runs here because the canaries exist only here. A failed # scan fails the job before anything is uploaded. diff --git a/docs/research/INDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md b/docs/research/INDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md index 85a101095..f8e3a84aa 100644 --- a/docs/research/INDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md +++ b/docs/research/INDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md @@ -18,6 +18,7 @@ audit or real-user trial is claimed. | Main-only protected code must be deployed before the first protected qualification run. | A bounded prerequisite rollout of the completed runner is needed before collecting evidence. Epic acceptance stays open until actual runs, signed closure and CI are complete. | | Normal authored actions expire while a protected signing job waits. | Keep the installed author in an isolated process for a bounded two-hour grant/session. Refresh only the same predeclared action just before submission; native signatures keep the ordinary five-minute action limit, exact actor/action/request and installation trust. No private key enters artifacts. Both native Docker rehearsals passed with synthetic resources and no network; protected sequencing still needs integration. | | Publication scanning omitted newly added commissioning files and other unlisted outputs. | Replace the filename allowlist with a bounded complete-tree scan. Refuse symbolic/hard links, special or oversized files and concurrent changes; keep canaries private and outside artifacts. Move shipping executables outside the evidence tree and use one credential-free candidate build. Native pipeline regressions plant leaks in commissioning effects, source facts and an unexpected filename. | +| A phase's cleanup would destroy the resources needed by the subsequent ordinary qualified phase. | Resource setup/cleanup now belongs to one whole source-owned journey; individual phase runners only execute their phase. Setup runs once, resources stay present across sequential commands, and setup/stage/cleanup failure invalidates both protected phase outputs and the final proposal. Source pipeline tests use explicit doubles; the complete protected signing/qualification sequence still needs integration. | The public offline root ceremony and purpose-separated certificates are pinned. Both signer keys are provisioned in the existing reviewer-protected main-only diff --git a/product/qualification/auths-recipe-qualification-issuance/tests/script_pipeline.rs b/product/qualification/auths-recipe-qualification-issuance/tests/script_pipeline.rs index 61e16bf41..6f9e0d3be 100644 --- a/product/qualification/auths-recipe-qualification-issuance/tests/script_pipeline.rs +++ b/product/qualification/auths-recipe-qualification-issuance/tests/script_pipeline.rs @@ -168,6 +168,10 @@ fn stage_reports_flow_through_redaction_and_assembly_and_missing_execution_refus } #[test] +#[allow( + clippy::too_many_lines, + reason = "the four resource-session exits and stale phase outputs are checked together" +)] fn live_script_cleans_up_after_success_setup_failure_and_stage_failure() { let temporary = tempfile::tempdir().expect("directory"); let root = temporary.path().join("repository"); @@ -182,13 +186,36 @@ fn live_script_cleans_up_after_success_setup_failure_and_stage_failure() { family.join("corpus-manifest.json"), ) .expect("corpus"); - let script = Path::new(env!("CARGO_MANIFEST_DIR")).join("../../../qualification/run/live.sh"); + let scripts = Path::new(env!("CARGO_MANIFEST_DIR")).join("../../../qualification/run"); for mode in ["success", "setup-failed", "failed", "cleanup-failed"] { fs::write(work.join("fault"), mode).expect("fault"); + // A prior phase's outputs must also become unusable if the overall + // resource session fails. These are synthetic orchestration fixtures. + fs::write( + work.join("commissioning-effects.json"), + r#"{"entered":1,"confirmed_by_read_back":1}"#, + ) + .expect("earlier phase effects"); + fs::write(work.join("cases/live.commissioning.json"), "[]").expect("earlier phase report"); let output = Command::new("bash") - .arg(&script) + .arg(scripts.join("resource-session.sh")) .arg("example-refund-v1") .arg(&work) + .arg("bash") + .arg("-c") + .arg( + r#"set -e +test -f "$1/disposable-resource" +bash "$2" "$3" "$1" +test -f "$1/disposable-resource" +bash "$2" "$3" "$1" +test -f "$1/disposable-resource" +"#, + ) + .arg("protected-journey-test") + .arg(&work) + .arg(scripts.join("live.sh")) + .arg("example-refund-v1") .env( "AUTHS_QUALIFICATION", env!("CARGO_BIN_EXE_auths-qualification"), @@ -207,6 +234,15 @@ fn live_script_cleans_up_after_success_setup_failure_and_stage_failure() { mode == "cleanup-failed", "teardown runs even after partial setup or a refused stage" ); + assert_eq!( + work.join("cases/live.commissioning.json").exists(), + mode == "success", + "a failed resource session invalidates earlier commissioning evidence" + ); + assert_eq!( + work.join("commissioning-effects.json").exists(), + mode == "success" + ); assert!( !String::from_utf8_lossy(&output.stderr) .contains("synthetic-canary-must-not-leave-child"), diff --git a/qualification/run/live.sh b/qualification/run/live.sh index 23148f212..9931caf03 100755 --- a/qualification/run/live.sh +++ b/qualification/run/live.sh @@ -1,6 +1,7 @@ #!/usr/bin/env bash -# Execute protected live stages and tear down disposable resources on every -# exit, including a failed setup or runner. Cleanup must be idempotent. +# Execute one protected phase inside resource-session.sh. Resource preparation +# and cleanup belong to the complete journey, so commissioning cannot destroy +# the resources or author session needed by ordinary qualified execution. set -euo pipefail family="${1:?usage: live.sh }" @@ -16,25 +17,6 @@ harness="${root}/qualification/families/${family}/harness" tool="${AUTHS_QUALIFICATION:-${root}/target/release/auths-qualification}" rm -f "${work}/${stage}-effects.json" "${work}/cases/"*."${stage}".json -cleanup() { - status=$? - # The family writes scan sources privately. Never relay child output, - # which may contain credentials, to Actions logs. - if ! "${harness}" cleanup "${work}" >/dev/null 2>&1; then - echo "qualification.cleanup-failed" >&2 - status=1 - fi - if [ "${status}" -ne 0 ]; then - rm -f "${work}/${stage}-effects.json" "${work}/cases/"*."${stage}".json - fi - exit "${status}" -} -trap cleanup EXIT - -if ! "${harness}" prepare-live "${work}" >/dev/null 2>&1; then - echo "qualification.live-setup-failed" >&2 - exit 1 -fi "${tool}" run-stage --phase "${stage}" \ --corpus "${root}/qualification/families/${family}/corpus-manifest.json" \ --harness "${harness}" --tuple "${work}/tuple.json" --work-dir "${work}" diff --git a/qualification/run/resource-session.sh b/qualification/run/resource-session.sh new file mode 100644 index 000000000..093406511 --- /dev/null +++ b/qualification/run/resource-session.sh @@ -0,0 +1,47 @@ +#!/usr/bin/env bash +# Hold disposable resources across the source-owned protected journey. The +# command and its arguments come from the reviewed workflow, never an artifact. +# Setup runs once and cleanup runs after the complete journey on every exit. +# +# resource-session.sh [arguments...] +set -euo pipefail + +family="${1:?usage: resource-session.sh [arguments...]}" +work="${2:?}" +shift 2 +[ "$#" -gt 0 ] || { echo "qualification.journey-missing" >&2; exit 1; } +root="$(git rev-parse --show-toplevel)" +[[ "${family}" =~ ^[a-z][a-z0-9-]{0,63}$ ]] || { echo "qualification.invalid-family" >&2; exit 1; } +harness="${root}/qualification/families/${family}/harness" +[ -x "${harness}" ] || { echo "qualification.family-unknown" >&2; exit 1; } + +invalidate() { + for phase in commissioning live; do + rm -f "${work}/${phase}-effects.json" "${work}/cases/"*."${phase}".json + done + rm -rf "${work}/proposal" "${work}/evidence" +} + +cleanup() { + status=$? + trap - EXIT + # Provider error bodies and private setup/cleanup diagnostics never enter + # the Actions log. A failed cleanup cannot leave a passing final proposal. + if ! "${harness}" cleanup "${work}" >/dev/null 2>&1; then + echo "qualification.cleanup-failed" >&2 + status=1 + fi + if [ "${status}" -ne 0 ]; then + invalidate + fi + exit "${status}" +} +trap cleanup EXIT +trap 'exit 130' INT +trap 'exit 143' TERM + +if ! "${harness}" prepare-live "${work}" >/dev/null 2>&1; then + echo "qualification.live-setup-failed" >&2 + exit 1 +fi +"$@" From 56e2c421b7f6fc17fad7d8a879715536ac5c334b Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 10:55:35 +0100 Subject: [PATCH 071/108] Keep the installed qualification author isolated across runner steps --- .github/workflows/recipe-qualification.yml | 17 +- qualification/reference/README.md | 16 ++ qualification/reference/author_socket.py | 190 ++++++++++++++++++ qualification/reference/check_socket.py | 120 +++++++++++ .../reference/tests/test_author_socket.py | 84 ++++++++ 5 files changed, 426 insertions(+), 1 deletion(-) create mode 100644 qualification/reference/author_socket.py create mode 100644 qualification/reference/check_socket.py create mode 100644 qualification/reference/tests/test_author_socket.py diff --git a/.github/workflows/recipe-qualification.yml b/.github/workflows/recipe-qualification.yml index 6602b45be..06b8d2b48 100644 --- a/.github/workflows/recipe-qualification.yml +++ b/.github/workflows/recipe-qualification.yml @@ -127,10 +127,25 @@ jobs: --gateway "${RUNNER_TEMP}/packet-candidate/bin/auths-gateway" \ --python "${RUNNER_TEMP}/packet-consumer/bin/python" \ --work "${RUNNER_TEMP}/packet-operator" + - name: Reconnect to the installed author under a separate UID + shell: bash + run: | + set -euo pipefail + sudo -n mkdir -m 0700 "${RUNNER_TEMP}/socket-report" + sudo -n "${RUNNER_TEMP}/packet-consumer/bin/python" \ + "${RUNNER_TEMP}/packet-kit/qualification/reference/check_socket.py" \ + --gateway "${RUNNER_TEMP}/packet-candidate/bin/auths-gateway" \ + --python "${RUNNER_TEMP}/packet-consumer/bin/python" \ + --work "${RUNNER_TEMP}/socket-operator" \ + --report "${RUNNER_TEMP}/socket-report/report.json" + sudo -n cp "${RUNNER_TEMP}/socket-report/report.json" "${RUNNER_TEMP}/packet-operator/socket-report.json" + sudo -n chown "$(id -u):$(id -g)" "${RUNNER_TEMP}/packet-operator/socket-report.json" - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: name: qualification-packet-author-${{ github.run_id }}-${{ github.run_attempt }} - path: ${{ runner.temp }}/packet-operator/report.json + path: | + ${{ runner.temp }}/packet-operator/report.json + ${{ runner.temp }}/packet-operator/socket-report.json if-no-files-found: error retention-days: 30 diff --git a/qualification/reference/README.md b/qualification/reference/README.md index 240db6a48..3c13a4787 100644 --- a/qualification/reference/README.md +++ b/qualification/reference/README.md @@ -135,3 +135,19 @@ checks both independent request mappings, original five-minute expiry, and an actual refreshed native proof with the same actor/action/request/trust. CI retains only its closed report. This is operator/release-tool evidence, not protected live qualification. + +`author_socket.py serve` is the Linux runner connection for that same installed +author. It runs under a dedicated non-root UID, in an owner-private directory, +with the same empty-environment requirement. Its fixed `author.sock` has mode +0600, authenticates kernel peer credentials and accepts only the root operator +controller. `inspect`, `refresh` and `close` reconnect across runner steps; +generation state and the native key stay in the one process. A duplicate launch +cannot replace an existing socket. Refresh accepts only an original label and +copies public proof/action/context bytes into a new private controller directory, +after checking exact original arguments, action bytes, trust and normal validity. +An expired session, changed handoff or malformed command cannot export a packet. + +Keep the author's directory outside the publication tree; sockets and private +inputs are never artifacts. `check_socket.py` exercises the actual installed SDK +and shipping gateway under separate Linux UIDs, using synthetic resources and +no provider access. Its report explicitly confers no protected qualification. diff --git a/qualification/reference/author_socket.py b/qualification/reference/author_socket.py new file mode 100644 index 000000000..9633d7f7b --- /dev/null +++ b/qualification/reference/author_socket.py @@ -0,0 +1,190 @@ +#!/usr/bin/env python3 +"""Keep the isolated installed author alive across protected runner steps. + +Linux only. The author runs under a dedicated unprivileged UID with an empty +environment; only the root operator controller may connect. This is a local +release tool, never a gateway channel or an executable artifact for a signer. +""" + +import argparse +import os +from pathlib import Path +import socket +import stat +import struct +import time + +from author_packets import command, create_session +from common import canonical, closed, require +from expand import decode, read +from resource_io import finish, write_bytes + +SCHEMA = 'auths.qualification-author-socket/1' + + +def private_work(work, *, author): + info = os.lstat(work) + require(stat.S_ISDIR(info.st_mode) and stat.S_IMODE(info.st_mode) == 0o700 + and (info.st_uid == os.getuid() if author else info.st_uid != 0), + 'qualification.packets.socket-directory') + require(hasattr(socket, 'SO_PEERCRED') and (os.getuid() != 0 if author else os.getuid() == 0), + 'qualification.packets.socket-isolation') + + +def peer_uid(connection): + return struct.unpack('3i', connection.getsockopt(socket.SOL_SOCKET, socket.SO_PEERCRED, 12))[1] + + +def receive(connection, deadline): + pending = b'' + while b'\n' not in pending: + remaining = min(30, deadline - time.time()) + require(remaining > 0, 'qualification.packets.session-expired') + connection.settimeout(remaining) + chunk = connection.recv(513 - len(pending)) + require(bool(chunk), 'qualification.packets.command-bound') + pending += chunk + require(len(pending) <= 512, 'qualification.packets.command-bound') + require(pending.count(b'\n') == 1 and pending.endswith(b'\n'), + 'qualification.packets.command-bound') + return pending + + +def send(connection, value): + payload = canonical(value) + b'\n' + require(len(payload) <= 512, 'qualification.packets.command-bound') + connection.sendall(payload) + + +def serve(plan, work): + private_work(work, author=True) + endpoint = work / 'author.sock' + # bind refuses an existing path. Nothing unlinks an unknown socket, file + # or symlink; a second launch cannot replace the first author's authority. + with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as server: + server.bind(str(endpoint)) + os.chmod(endpoint, 0o600) + identity = os.lstat(endpoint) + try: + server.listen(1) + emit, end = create_session(plan) + emit(work) + generation = 0 + while True: + remaining = end - time.time() + require(remaining > 0, 'qualification.packets.session-expired') + server.settimeout(remaining) + connection, _ = server.accept() + with connection: + require(peer_uid(connection) == 0, 'qualification.packets.socket-peer') + connection.settimeout(min(30, remaining)) + send(connection, {'schema': SCHEMA, 'state': 'ready', 'generation': generation}) + raw = receive(connection, end) + if decode(raw) == {'command': 'inspect'}: + send(connection, {'schema': SCHEMA, 'state': 'ready', 'generation': generation}) + continue + value = command(raw, generation) + if value is None: + send(connection, {'schema': SCHEMA, 'state': 'closed'}) + return + generation = value['generation'] + destination = work / ('refresh-' + str(generation).zfill(4)) + destination.mkdir(mode=0o700) + emit(destination, value['label']) + send(connection, {'schema': SCHEMA, 'state': 'refreshed', + 'generation': generation, 'label': value['label']}) + finally: + # Only remove the exact socket we bound, even during failed setup. + if endpoint.exists(): + current = os.lstat(endpoint) + if stat.S_ISSOCK(current.st_mode) and (current.st_dev, current.st_ino) == (identity.st_dev, identity.st_ino): + endpoint.unlink() + + +def exchange(work, action, label=None): + private_work(work, author=False) + endpoint = work / 'author.sock' + info = os.lstat(endpoint) + require(stat.S_ISSOCK(info.st_mode) and stat.S_IMODE(info.st_mode) == 0o600 + and info.st_uid == os.lstat(work).st_uid, 'qualification.packets.socket-identity') + with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as connection: + connection.settimeout(30) + connection.connect(str(endpoint)) + require(peer_uid(connection) == info.st_uid, 'qualification.packets.socket-peer') + ready = decode(receive(connection, time.time() + 30)) + closed(ready, ['schema', 'state', 'generation']) + require(ready['schema'] == SCHEMA and ready['state'] == 'ready' + and type(ready['generation']) is int and 0 <= ready['generation'] <= 1024, + 'qualification.packets.socket-response') + value = {'command': action} + if action == 'refresh': + value.update(label=label, generation=ready['generation'] + 1) + else: + require(action in ['inspect', 'close'], 'qualification.packets.command-bound') + send(connection, value) + result = decode(receive(connection, time.time() + 30)) + expected = dict(ready) if action == 'inspect' else {'schema': SCHEMA, 'state': 'closed'} + if action == 'refresh': + expected = {'schema': SCHEMA, 'state': 'refreshed', + 'generation': value['generation'], 'label': label} + require(result == expected, 'qualification.packets.socket-response') + return result + + +def refresh(work, label, destination): + # A label can select only an original source-derived action. Check it + # before contacting the key holder; no caller-supplied arguments or paths + # enter its protocol. The root controller copies only public bytes out. + original = decode(read(work / 'public-packets.json', 65536)) + matches = [packet for packet in original['packets'] if packet['label'] == label] + require(len(matches) == 1, 'qualification.packets.unknown-label') + packet = matches[0] + require(packet['proof'] == label + '.proof' and packet['action'] == label + '.action' + and original['trusted_context'] == 'context.cbor', 'qualification.packets.socket-response') + require(not destination.exists(), 'qualification.packets.output-exists') + result = exchange(work, 'refresh', label) + source = work / ('refresh-' + str(result['generation']).zfill(4)) + fresh = decode(read(source / 'public-packets.json', 65536)) + now = int(time.time()) + require(set(fresh) == set(original) and fresh['schema'] == original['schema'] + and fresh['protected_run'] == original['protected_run'] + and fresh['trusted_context'] == 'context.cbor' and fresh['packets'] == [packet] + and type(fresh['evaluated_at']) is int and type(fresh['not_after']) is int + and now - 30 <= fresh['evaluated_at'] <= now + and now + 60 <= fresh['not_after'] <= fresh['evaluated_at'] + 300, + 'qualification.packets.refresh-binding') + payloads = {name: read(source / name, bound) for name, bound in [ + (packet['proof'], 4 * 1024 * 1024), (packet['action'], 65536), + ('context.cbor', 4 * 1024 * 1024), ('public-packets.json', 65536)]} + require(payloads[packet['action']] == read(work / packet['action'], 65536) + and payloads['context.cbor'] == read(work / 'context.cbor', 4 * 1024 * 1024), + 'qualification.packets.refresh-binding') + destination.mkdir(mode=0o700) + for name, payload in payloads.items(): + write_bytes(destination / name, payload, new=True) + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + subparsers = parser.add_subparsers(dest='command', required=True) + for action in ['serve', 'inspect', 'refresh', 'close']: + command_parser = subparsers.add_parser(action) + command_parser.add_argument('--work', type=lambda value: Path(value).absolute(), required=True) + if action == 'serve': + command_parser.add_argument('--plan', type=lambda value: Path(value).absolute(), required=True) + if action == 'refresh': + command_parser.add_argument('--label', required=True) + command_parser.add_argument('--out', type=lambda value: Path(value).absolute(), required=True) + args = parser.parse_args() + def execute(): + if args.command == 'serve': + serve(args.plan, args.work) + elif args.command == 'refresh': + refresh(args.work, args.label, args.out) + else: + exchange(args.work, args.command) + finish(execute) + + +if __name__ == '__main__': + main() diff --git a/qualification/reference/check_socket.py b/qualification/reference/check_socket.py new file mode 100644 index 000000000..0ff02a802 --- /dev/null +++ b/qualification/reference/check_socket.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python3 +"""Exercise the real installed author under a separate Linux UID. + +Uses synthetic resources and no provider/network/qualification authority. +The root controller reconnects between steps, as a protected Actions runner +will after waiting for a signing artifact. Only public bytes leave the author. +""" + +import argparse +import os +from pathlib import Path +import subprocess +import time + +import airtable_record +import stripe_platform +from author_socket import exchange, refresh +from check_packets import review +from common import require, sha256 +from expand import decode, read +from packet_plan import prepare +from resource_io import finish, write + +AUTHOR_UID = 62002 + + +def isolate(): + os.setgroups([]) + os.setgid(AUTHOR_UID) + os.setuid(AUTHOR_UID) + + +def ready(process, work): + deadline = time.monotonic() + 30 + while time.monotonic() < deadline: + require(process.poll() is None, 'qualification.packets.author-refused') + if (work / 'author.sock').exists(): + exchange(work, 'inspect') + return + time.sleep(0.1) + require(False, 'qualification.packets.author-timeout') + + +def check(args): + require(os.getuid() == 0 and not args.work.exists(), 'qualification.packets.socket-isolation') + args.work.mkdir(mode=0o700) + reports = [] + for reference in [stripe_platform, airtable_record]: + work = args.work / reference.FAMILY + work.mkdir(mode=0o700) + run = 'socket-operator-rehearsal/' + str(int(time.time())) + '/1' + resources = {'schema': 'auths.stripe-platform-qualification-resources/1', + 'protected_run': run, 'platform': 'acct_SYNTHETIC', 'payments': [ + {'id': 'pi_SYNTHETIC', 'amount_received': 2000, 'currency': 'usd', + 'livemode': False, 'run_metadata': run}]} if reference is stripe_platform else { + 'schema': 'auths.airtable-record-qualification-resources/1', 'protected_run': run, + 'base': airtable_record.BASE, 'table': airtable_record.TABLE, 'records': [ + {'id': 'recTEST0000000001', 'run_metadata': run}]} + write(work / 'resources.json', resources, new=True) + prepare(argparse.Namespace(family=reference.FAMILY, resources=work / 'resources.json', + gateway=args.gateway, work=work)) + # All author inputs are public, and every private ancestor belongs to + # the dedicated author. Its UID has no access to the controller's + # root-owned credential files or process environment. + for path in work.iterdir(): + os.chown(path, AUTHOR_UID, AUTHOR_UID) + os.chown(work, AUTHOR_UID, AUTHOR_UID) + os.chown(args.work, AUTHOR_UID, AUTHOR_UID) + process = subprocess.Popen([str(args.python), str(Path(__file__).with_name('author_socket.py')), + 'serve', '--plan', str(work / 'packet-plan.json'), '--work', str(work)], + stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, + cwd='/', env={'PATH': '/usr/bin:/bin', 'PYTHONNOUSERSITE': '1'}, preexec_fn=isolate) + try: + ready(process, work) + original = decode(read(work / 'public-packets.json', 65536)) + initial = review(args.gateway, work, original['packets'][0], original['evaluated_at']) + # Separate connections and fresh output directories simulate the + # runner handing public packets across independent job steps. + for generation, packet in enumerate(original['packets'], 1): + destination = args.work / (reference.FAMILY + '-public-' + str(generation)) + refresh(work, packet['label'], destination) + fresh = decode(read(destination / 'public-packets.json', 65536)) + for name in ['recipe.json', 'profile.lock.json']: + (destination / name).write_bytes(read(work / name, 65536)) + actual = review(args.gateway, destination, fresh['packets'][0], fresh['evaluated_at']) + expected = reference.request(packet['arguments'], resources, + actual['action_commitment'], packet['arguments']['recipe_digest']) + require(actual['request'] == expected and actual['actors'] == initial['actors'], + 'qualification.packets.refresh-binding') + require(exchange(work, 'inspect')['generation'] == generation, + 'qualification.packets.generation') + exchange(work, 'close') + process.wait(timeout=10) + require(process.returncode == 0 and not (work / 'author.sock').exists(), + 'qualification.packets.author-refused') + reports.append({'family': reference.FAMILY, 'author_uid': AUTHOR_UID, + 'controller_uid': 0, 'separate_connections': len(original['packets']), + 'same_actor_action_request_and_trust': True, 'socket_removed_on_close': True}) + finally: + if process.poll() is None: + process.terminate() + process.wait(timeout=10) + os.chown(args.work, 0, 0) + write(args.report, {'schema': 'auths.qualification-author-socket-rehearsal/1', + 'gateway_sha256': sha256(read(args.gateway, 256 * 1024 * 1024)), + 'synthetic_resources': True, 'provider_contacted': False, + 'protected_qualification': False, 'qualification_issued': False, + 'stable_launch_ready': False, 'families': reports}, new=True) + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + for name in ['gateway', 'python', 'work', 'report']: + parser.add_argument('--' + name, type=lambda value: Path(value).absolute(), required=True) + args = parser.parse_args() + finish(lambda: check(args)) + + +if __name__ == '__main__': + main() diff --git a/qualification/reference/tests/test_author_socket.py b/qualification/reference/tests/test_author_socket.py new file mode 100644 index 000000000..7e7c45bb2 --- /dev/null +++ b/qualification/reference/tests/test_author_socket.py @@ -0,0 +1,84 @@ +"""Local author channel refuses peers, framing and changed public handoffs.""" + +import os +from pathlib import Path +import socket +import sys +import tempfile +import time +import unittest +from unittest.mock import patch + +sys.path.insert(0, str(Path(__file__).resolve().parents[1])) +import author_socket +from common import Refusal, canonical +from resource_io import write, write_bytes + + +class AuthorSocket(unittest.TestCase): + def test_frames_are_bounded_complete_and_serial(self): + for raw in [b'{"command":"inspect"}\n', b'x' * 512]: + sender, receiver = socket.socketpair() + with sender, receiver: + sender.sendall(raw) + sender.shutdown(socket.SHUT_WR) + if raw.endswith(b'\n'): + self.assertEqual(author_socket.receive(receiver, time.time() + 2), raw) + else: + with self.assertRaises(Refusal): author_socket.receive(receiver, time.time() + 2) + for raw in [b'x' * 513, b'one\ntwo\n', b'one\nunfinished']: + sender, receiver = socket.socketpair() + with sender, receiver: + sender.sendall(raw) + with self.assertRaises(Refusal): author_socket.receive(receiver, time.time() + 2) + + @unittest.skipUnless(hasattr(socket, 'SO_PEERCRED'), 'Linux peer credentials required') + def test_peer_credentials_come_from_the_kernel(self): + first, second = socket.socketpair() + with first, second: + self.assertEqual(author_socket.peer_uid(first), os.getuid()) + self.assertEqual(author_socket.peer_uid(second), os.getuid()) + + def test_private_directory_checks_refuse_symlinks_shared_modes_and_root_authors(self): + with tempfile.TemporaryDirectory() as temporary: + work = Path(temporary) + work.chmod(0o755) + with self.assertRaises(Refusal): author_socket.private_work(work, author=True) + work.chmod(0o700) + with patch('author_socket.os.getuid', return_value=0): + with self.assertRaises(Refusal): author_socket.private_work(work, author=True) + link = work / 'link' + link.symlink_to(work, target_is_directory=True) + with self.assertRaises(Refusal): author_socket.private_work(link, author=True) + + def test_refresh_never_exports_a_changed_action_context_or_aged_packet(self): + for change in ['action', 'context', 'arguments', 'age', 'extra-field']: + with tempfile.TemporaryDirectory() as temporary: + work = Path(temporary) + work.chmod(0o700) + packet = {'label': 'live-00', 'proof': 'live-00.proof', + 'action': 'live-00.action', 'arguments': {'closed': 'source'}} + now = int(time.time()) + original = {'schema': 'auths.qualification-public-packets/2', + 'protected_run': 'recipe-qualification/123/1', 'evaluated_at': now, + 'not_after': now + 300, 'trusted_context': 'context.cbor', 'packets': [packet]} + write(work / 'public-packets.json', original, new=True) + write_bytes(work / 'live-00.action', b'source-action', new=True) + write_bytes(work / 'context.cbor', b'source-context', new=True) + fresh = work / 'refresh-0001' + fresh.mkdir(mode=0o700) + value = dict(original) + if change == 'arguments': value['packets'] = [dict(packet, arguments={'closed': 'changed'})] + if change == 'age': value.update(evaluated_at=now-120, not_after=now+30) + if change == 'extra-field': value['credential'] = 'synthetic-forbidden-input' + write(fresh / 'public-packets.json', value, new=True) + write_bytes(fresh / 'live-00.action', b'changed' if change == 'action' else b'source-action', new=True) + write_bytes(fresh / 'context.cbor', b'changed' if change == 'context' else b'source-context', new=True) + write_bytes(fresh / 'live-00.proof', b'public-proof', new=True) + with patch('author_socket.exchange', return_value={'generation': 1}): + with self.assertRaises(Refusal): author_socket.refresh(work, 'live-00', work / 'output') + self.assertFalse((work / 'output').exists()) + + +if __name__ == '__main__': + unittest.main() From 9d66eda59314434714cbc92050a6ee37fe80ed47 Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 11:00:25 +0100 Subject: [PATCH 072/108] Bound author sessions with monotonic deadlines --- qualification/reference/author_packets.py | 7 ++++++- qualification/reference/author_socket.py | 15 ++++++++++----- .../reference/tests/test_author_socket.py | 6 +++--- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/qualification/reference/author_packets.py b/qualification/reference/author_packets.py index 33fa0927d..be9d46bbd 100644 --- a/qualification/reference/author_packets.py +++ b/qualification/reference/author_packets.py @@ -139,12 +139,17 @@ def author(plan_path, work, serve=False): return print('{"schema":"auths.qualification-author-session/1","state":"ready"}', flush=True) generation = 0 + deadline = time.monotonic() + max(0, end - time.time()) + last_clock = time.time() # Bounded pipe reads use os.read rather than buffered readline: select # must not miss an already-buffered second command. Partial frames have # the same finite grant deadline and cannot extend the process lifetime. pending = b'' while True: - remaining = end - time.time() + now = time.time() + require(now >= last_clock, 'qualification.packets.session-expired') + last_clock = now + remaining = min(end - now, deadline - time.monotonic()) require(remaining > 0, 'qualification.packets.session-expired') ready, _, _ = select.select([sys.stdin.fileno()], [], [], remaining) require(bool(ready), 'qualification.packets.session-expired') diff --git a/qualification/reference/author_socket.py b/qualification/reference/author_socket.py index 9633d7f7b..9f33df473 100644 --- a/qualification/reference/author_socket.py +++ b/qualification/reference/author_socket.py @@ -38,7 +38,7 @@ def peer_uid(connection): def receive(connection, deadline): pending = b'' while b'\n' not in pending: - remaining = min(30, deadline - time.time()) + remaining = min(30, deadline - time.monotonic()) require(remaining > 0, 'qualification.packets.session-expired') connection.settimeout(remaining) chunk = connection.recv(513 - len(pending)) @@ -69,9 +69,14 @@ def serve(plan, work): server.listen(1) emit, end = create_session(plan) emit(work) + deadline = time.monotonic() + max(0, end - time.time()) + last_clock = time.time() generation = 0 while True: - remaining = end - time.time() + now = time.time() + require(now >= last_clock, 'qualification.packets.session-expired') + last_clock = now + remaining = min(end - now, deadline - time.monotonic()) require(remaining > 0, 'qualification.packets.session-expired') server.settimeout(remaining) connection, _ = server.accept() @@ -79,7 +84,7 @@ def serve(plan, work): require(peer_uid(connection) == 0, 'qualification.packets.socket-peer') connection.settimeout(min(30, remaining)) send(connection, {'schema': SCHEMA, 'state': 'ready', 'generation': generation}) - raw = receive(connection, end) + raw = receive(connection, deadline) if decode(raw) == {'command': 'inspect'}: send(connection, {'schema': SCHEMA, 'state': 'ready', 'generation': generation}) continue @@ -111,7 +116,7 @@ def exchange(work, action, label=None): connection.settimeout(30) connection.connect(str(endpoint)) require(peer_uid(connection) == info.st_uid, 'qualification.packets.socket-peer') - ready = decode(receive(connection, time.time() + 30)) + ready = decode(receive(connection, time.monotonic() + 30)) closed(ready, ['schema', 'state', 'generation']) require(ready['schema'] == SCHEMA and ready['state'] == 'ready' and type(ready['generation']) is int and 0 <= ready['generation'] <= 1024, @@ -122,7 +127,7 @@ def exchange(work, action, label=None): else: require(action in ['inspect', 'close'], 'qualification.packets.command-bound') send(connection, value) - result = decode(receive(connection, time.time() + 30)) + result = decode(receive(connection, time.monotonic() + 30)) expected = dict(ready) if action == 'inspect' else {'schema': SCHEMA, 'state': 'closed'} if action == 'refresh': expected = {'schema': SCHEMA, 'state': 'refreshed', diff --git a/qualification/reference/tests/test_author_socket.py b/qualification/reference/tests/test_author_socket.py index 7e7c45bb2..a01bd406c 100644 --- a/qualification/reference/tests/test_author_socket.py +++ b/qualification/reference/tests/test_author_socket.py @@ -23,14 +23,14 @@ def test_frames_are_bounded_complete_and_serial(self): sender.sendall(raw) sender.shutdown(socket.SHUT_WR) if raw.endswith(b'\n'): - self.assertEqual(author_socket.receive(receiver, time.time() + 2), raw) + self.assertEqual(author_socket.receive(receiver, time.monotonic() + 2), raw) else: - with self.assertRaises(Refusal): author_socket.receive(receiver, time.time() + 2) + with self.assertRaises(Refusal): author_socket.receive(receiver, time.monotonic() + 2) for raw in [b'x' * 513, b'one\ntwo\n', b'one\nunfinished']: sender, receiver = socket.socketpair() with sender, receiver: sender.sendall(raw) - with self.assertRaises(Refusal): author_socket.receive(receiver, time.time() + 2) + with self.assertRaises(Refusal): author_socket.receive(receiver, time.monotonic() + 2) @unittest.skipUnless(hasattr(socket, 'SO_PEERCRED'), 'Linux peer credentials required') def test_peer_credentials_come_from_the_kernel(self): From 1ba15950af06ce463dff2a68259c070711a46a4f Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 11:04:43 +0100 Subject: [PATCH 073/108] Confine qualification artifact waits to the exact protected run --- qualification/reference/README.md | 13 ++ .../reference/tests/test_artifact_wait.py | 104 +++++++++ qualification/run/artifact_wait.py | 209 ++++++++++++++++++ 3 files changed, 326 insertions(+) create mode 100644 qualification/reference/tests/test_artifact_wait.py create mode 100644 qualification/run/artifact_wait.py diff --git a/qualification/reference/README.md b/qualification/reference/README.md index 3c13a4787..d79df9272 100644 --- a/qualification/reference/README.md +++ b/qualification/reference/README.md @@ -151,3 +151,16 @@ Keep the author's directory outside the publication tree; sockets and private inputs are never artifacts. `check_socket.py` exercises the actual installed SDK and shipping gateway under separate Linux UIDs, using synthetic resources and no provider access. Its report explicitly confers no protected qualification. + +`run/artifact_wait.py` is the public mailbox reader for the protected sequence. +It accepts only this repository's main-branch manual qualification workflow, +exact source SHA, run and attempt, and five source-owned artifact roles. It +checks the authenticated run metadata and GitHub archive SHA-256, refuses +duplicates, expired artifacts, another attempt/repository, links, executable +files, traversal and oversized archives, and extracts only bounded public +protocol files with private permissions. Partial extraction is removed. +Missing artifacts are checked every ten minutes within a fixed two-hour +deadline. Only the GitHub Actions token enters the GitHub client; provider and +signer keys are absent from that child's environment. The native issuer/gateway +must still verify every permit/record: a transported artifact grants no authority. +The protected workflow has not yet connected this mailbox to admitted corpora. diff --git a/qualification/reference/tests/test_artifact_wait.py b/qualification/reference/tests/test_artifact_wait.py new file mode 100644 index 000000000..cd41e60de --- /dev/null +++ b/qualification/reference/tests/test_artifact_wait.py @@ -0,0 +1,104 @@ +"""Artifact transport cannot choose code, another run or unbounded input.""" + +import copy +import hashlib +import io +import os +from pathlib import Path +import stat +import sys +import tempfile +import unittest +import zipfile + +sys.path.insert(0, str(Path(__file__).resolve().parents[1])) +sys.path.insert(0, str(Path(__file__).resolve().parents[2] / 'run')) +import artifact_wait +from common import Refusal + + +class ArtifactWait(unittest.TestCase): + def artifact(self): + return {'id': 12, 'name': 'qualification-first-release-airtable-record-update-v1-123-1', + 'expired': False, 'size_in_bytes': 1024, 'digest': 'sha256:' + '1' * 64, + 'workflow_run': {'id': 123, 'head_sha': '2' * 40, 'head_branch': 'main', + 'repository_id': artifact_wait.REPOSITORY_ID, + 'head_repository_id': artifact_wait.REPOSITORY_ID}} + + def test_an_artifact_binds_exact_name_run_source_and_repository(self): + artifact = self.artifact() + def select(value): + return artifact_wait.select_artifact({'total_count': 1, 'artifacts': [value]}, + artifact['name'], '123', '2' * 40) + self.assertEqual(select(artifact), artifact) + for change in [lambda a: a.update(expired=True), lambda a: a.update(id=True), + lambda a: a.update(digest='1' * 64), + lambda a: a.update(size_in_bytes=artifact_wait.MAX_ARCHIVE + 1), + lambda a: a['workflow_run'].update(id=124), + lambda a: a['workflow_run'].update(head_sha='3' * 40), + lambda a: a['workflow_run'].update(head_branch='codex/unreviewed'), + lambda a: a['workflow_run'].update(head_repository_id=42)]: + changed = copy.deepcopy(artifact) + change(changed) + with self.assertRaises(Refusal): select(changed) + self.assertIsNone(select(dict(artifact, name='another-attempt'))) + with self.assertRaises(Refusal): + artifact_wait.select_artifact({'total_count': 2, 'artifacts': [artifact, artifact]}, + artifact['name'], '123', '2' * 40) + + def test_only_main_dispatch_of_the_exact_attempt_and_workflow_is_allowed(self): + environment = {'GITHUB_REPOSITORY': artifact_wait.REPOSITORY, 'GITHUB_EVENT_NAME': 'workflow_dispatch', + 'GITHUB_REF': 'refs/heads/main', 'GITHUB_RUN_ID': '123', 'GITHUB_RUN_ATTEMPT': '1', + 'GITHUB_SHA': '2' * 40} + self.assertEqual(artifact_wait.identity(environment), ('123', '1', '2' * 40)) + for name, value in [('GITHUB_REPOSITORY', 'fork/unreviewed'), ('GITHUB_EVENT_NAME', 'pull_request'), + ('GITHUB_REF', 'refs/pull/206/merge'), ('GITHUB_RUN_ATTEMPT', '01')]: + with self.assertRaises(Refusal): artifact_wait.identity(dict(environment, **{name: value})) + run = {'id': 123, 'run_attempt': 1, 'head_sha': '2' * 40, 'head_branch': 'main', + 'event': 'workflow_dispatch', 'path': artifact_wait.WORKFLOW, + 'repository': {'id': artifact_wait.REPOSITORY_ID}, + 'head_repository': {'id': artifact_wait.REPOSITORY_ID}} + artifact_wait.check_run(run, '123', '1', '2' * 40) + for name, value in [('run_attempt', 2), ('path', '.github/workflows/unreviewed.yml'), + ('event', 'pull_request')]: + with self.assertRaises(Refusal): artifact_wait.check_run(dict(run, **{name: value}), '123', '1', '2' * 40) + + def archive(self, entries): + output = io.BytesIO() + with zipfile.ZipFile(output, 'w') as archive: + for name, value in entries: + archive.writestr(name, value) + return output.getvalue() + + def test_archive_paths_links_executables_duplicates_and_decompression_are_refused(self): + link = zipfile.ZipInfo('linked.json') + link.create_system = 3 + link.external_attr = (stat.S_IFLNK | 0o777) << 16 + invalid = [[('../record.json', b'{}')], [('/record.json', b'{}')], + [('a//record.json', b'{}')], [('record.json', b'{}'), ('record.json', b'{}')], + [('a.json', b'{}'), ('a.json/record.json', b'{}')], [(link, b'root.key')], + [('harness.py', b'pass')], [('hidden/.key.json', b'{}')], [('empty.json', b'')], + [('huge.json', b'x' * (artifact_wait.MAX_FILE + 1))], [('dir///', b'')]] + for entries in invalid: + with zipfile.ZipFile(io.BytesIO(self.archive(entries))) as archive: + with self.assertRaises(Refusal): artifact_wait.members(archive) + + def test_digest_checked_extraction_publishes_only_private_public_bytes(self): + with tempfile.TemporaryDirectory() as temporary: + work = Path(temporary) + work.chmod(0o700) + path = work / 'public.zip' + payload = self.archive([('record.json', b'{"source":"reviewed"}'), + ('evidence/conformance.json', b'{}')]) + path.write_bytes(payload) + artifact = {'digest': 'sha256:' + hashlib.sha256(payload).hexdigest()} + with self.assertRaises(Refusal): artifact_wait.unpack(path, {'digest': 'sha256:' + '0' * 64}, work / 'bad') + self.assertFalse((work / 'bad').exists()) + artifact_wait.unpack(path, artifact, work / 'accepted') + for file in ['record.json', 'evidence/conformance.json']: + self.assertEqual(stat.S_IMODE(os.lstat(work / 'accepted' / file).st_mode), 0o600) + self.assertEqual(stat.S_IMODE(os.lstat(work / 'accepted/evidence').st_mode), 0o700) + + +if __name__ == '__main__': + unittest.main() diff --git a/qualification/run/artifact_wait.py b/qualification/run/artifact_wait.py new file mode 100644 index 000000000..c58599909 --- /dev/null +++ b/qualification/run/artifact_wait.py @@ -0,0 +1,209 @@ +#!/usr/bin/env python3 +"""Wait for one public artifact from this exact protected qualification run. + +No uploaded program is executed. Run/source/attempt identities and GitHub's +archive digest are checked before bounded public files are extracted. Native +permit/record verification is still mandatory: transport identity is not +qualification authority. The only credential passed to gh is its Actions token. +""" + +import argparse +import hashlib +import os +from pathlib import Path, PurePosixPath +import re +import shutil +import stat +import subprocess +import sys +import tempfile +import time +import zipfile + +sys.path.insert(0, str(Path(__file__).resolve().parents[1] / 'reference')) +from common import Refusal, require +from expand import decode +from resource_io import finish, write_bytes + +REPOSITORY = 'auths-dev/auths-proof' +REPOSITORY_ID = 1310728509 +WORKFLOW = '.github/workflows/recipe-qualification.yml' +KINDS = ['commissioning-inputs', 'commissioning-permit', 'first-proposal', 'first-release', 'final-proposal'] +MAX_ARCHIVE = 32 * 1024 * 1024 +MAX_FILES = 256 +MAX_FILE = 2 * 1024 * 1024 +POLL_SECONDS = 600 + + +def identity(environment): + require(environment.get('GITHUB_REPOSITORY') == REPOSITORY + and environment.get('GITHUB_EVENT_NAME') == 'workflow_dispatch' + and environment.get('GITHUB_REF') == 'refs/heads/main', + 'qualification.artifact.protected-run') + run, attempt, commit = [environment.get(name, '') for name in + ['GITHUB_RUN_ID', 'GITHUB_RUN_ATTEMPT', 'GITHUB_SHA']] + require(re.fullmatch(r'[1-9][0-9]{0,19}', run) and re.fullmatch(r'[1-9][0-9]{0,9}', attempt) + and re.fullmatch(r'[0-9a-f]{40}', commit), 'qualification.artifact.run-identity') + return run, attempt, commit + + +def api(path, destination=None): + # Never inherit provider keys, signer keys, proxy settings, alternate API + # hosts or GitHub configuration. gh handles the authenticated archive + # redirect; its token is for GitHub, not a provider or signing input. + token = os.environ.get('GH_TOKEN', '') + require(bool(token), 'qualification.artifact.token-missing') + environment = {'PATH': os.environ.get('PATH', '/usr/bin:/bin'), 'GH_TOKEN': token, + 'GH_PROMPT_DISABLED': '1', 'GH_CONFIG_DIR': '/nonexistent-auths-gh-config'} + arguments = ['gh', 'api', '--hostname', 'github.com', '-H', 'X-GitHub-Api-Version: 2022-11-28', + 'repos/' + REPOSITORY + '/' + path] + result = subprocess.run(arguments, env=environment, cwd='/', stdin=subprocess.DEVNULL, + stdout=destination if destination is not None else subprocess.PIPE, + stderr=subprocess.DEVNULL, timeout=60) + require(result.returncode == 0, 'qualification.artifact.transport-refused') + if destination is None: + require(0 < len(result.stdout) <= 256 * 1024, 'qualification.artifact.metadata-bound') + return decode(result.stdout) + + +def check_run(value, run, attempt, commit): + require(value.get('id') == int(run) and value.get('run_attempt') == int(attempt) + and value.get('head_sha') == commit and value.get('head_branch') == 'main' + and value.get('event') == 'workflow_dispatch' and value.get('path') == WORKFLOW + and value.get('repository', {}).get('id') == REPOSITORY_ID + and value.get('head_repository', {}).get('id') == REPOSITORY_ID, + 'qualification.artifact.run-binding') + + +def select_artifact(value, name, run, commit): + require(type(value) is dict and type(value.get('total_count')) is int + and 0 <= value['total_count'] <= 100 and type(value.get('artifacts')) is list + and len(value['artifacts']) == value['total_count'], 'qualification.artifact.metadata-bound') + selected = [artifact for artifact in value['artifacts'] if artifact.get('name') == name] + require(len(selected) <= 1, 'qualification.artifact.duplicate-name') + if not selected: + return None + artifact = selected[0] + source = artifact.get('workflow_run', {}) + require(type(artifact.get('id')) is int and artifact['id'] > 0 + and artifact.get('expired') is False + and type(artifact.get('size_in_bytes')) is int and 0 < artifact['size_in_bytes'] <= MAX_ARCHIVE + and type(artifact.get('digest')) is str + and re.fullmatch(r'sha256:[0-9a-f]{64}', artifact['digest']) + and source.get('id') == int(run) and source.get('head_sha') == commit + and source.get('head_branch') == 'main' + and source.get('repository_id') == REPOSITORY_ID + and source.get('head_repository_id') == REPOSITORY_ID, + 'qualification.artifact.source-binding') + return artifact + + +def members(archive): + entries = archive.infolist() + require(0 < len(entries) <= MAX_FILES * 2, 'qualification.artifact.archive-bound') + files, names, total = [], set(), 0 + for entry in entries: + name = entry.filename + path = PurePosixPath(name) + require(not path.is_absolute() and 1 <= len(path.parts) <= 4 + and all(re.fullmatch(r'[A-Za-z0-9][A-Za-z0-9_.-]{0,95}', part) for part in path.parts) + and '\\' not in name and name == str(path) + ('/' if entry.is_dir() else '') + and str(path) not in names and not entry.flag_bits & 1, + 'qualification.artifact.archive-path') + names.add(str(path)) + mode = entry.external_attr >> 16 + kind = stat.S_IFMT(mode) + require(kind in [0, stat.S_IFDIR if entry.is_dir() else stat.S_IFREG], + 'qualification.artifact.archive-kind') + if entry.is_dir(): + require(entry.file_size == 0, 'qualification.artifact.archive-bound') + continue + require(path.suffix in ['.json', '.cbor', '.proof', '.action'] + and 0 < entry.file_size <= MAX_FILE, 'qualification.artifact.public-file') + total += entry.file_size + require(total <= MAX_ARCHIVE and len(files) < MAX_FILES, 'qualification.artifact.archive-bound') + files.append((entry, path)) + require(bool(files), 'qualification.artifact.archive-bound') + file_names = {str(path) for _, path in files} + require(all(str(parent) not in file_names for _, path in files + for parent in path.parents if str(parent) != '.'), 'qualification.artifact.archive-path') + return files + + +def unpack(path, artifact, destination): + info = os.lstat(path) + require(stat.S_ISREG(info.st_mode) and 0 < info.st_size <= MAX_ARCHIVE, + 'qualification.artifact.archive-bound') + with path.open('rb') as stream: + actual = hashlib.file_digest(stream, 'sha256').hexdigest() + require(artifact['digest'] == 'sha256:' + actual, 'qualification.artifact.archive-digest') + require(not destination.exists(), 'qualification.artifact.output-exists') + parent = os.lstat(destination.parent) + require(stat.S_ISDIR(parent.st_mode) and stat.S_IMODE(parent.st_mode) == 0o700 + and parent.st_uid == os.getuid(), 'qualification.artifact.private-output') + complete = False + try: + with zipfile.ZipFile(path) as archive: + files = members(archive) + destination.mkdir(mode=0o700) + for entry, relative in files: + output = destination / str(relative) + output.parent.mkdir(mode=0o700, parents=True, exist_ok=True) + with archive.open(entry) as stream: + payload = stream.read(MAX_FILE + 1) + require(len(payload) == entry.file_size, 'qualification.artifact.archive-bound') + write_bytes(output, payload, new=True) + complete = True + except (zipfile.BadZipFile, RuntimeError, NotImplementedError): + raise Refusal('qualification.artifact.archive-refused') from None + finally: + # A partial extraction, including a CRC/format/write failure, never + # becomes input to the native authority verifier. + if not complete and destination.exists(): + shutil.rmtree(destination) + + +def wait(args): + run, attempt, commit = identity(os.environ) + require(args.kind in KINDS and re.fullmatch(r'[a-z][a-z0-9-]{0,63}', args.family), + 'qualification.artifact.name') + name = 'qualification-' + args.kind + '-' + args.family + '-' + run + '-' + attempt + now = int(time.time()) + require(now < args.not_after <= now + 7200, 'qualification.artifact.deadline') + deadline = time.monotonic() + args.not_after - now + last_clock = time.time() + check_run(api('actions/runs/' + run), run, attempt, commit) + while True: + now = time.time() + require(now >= last_clock and now < args.not_after and time.monotonic() < deadline, + 'qualification.artifact.deadline') + last_clock = now + artifact = select_artifact(api('actions/runs/' + run + '/artifacts?per_page=100'), name, run, commit) + if artifact is not None: + # The current attempt must still be the one being operated on; + # rerunning a workflow cannot import the earlier attempt's mailbox. + check_run(api('actions/runs/' + run), run, attempt, commit) + with tempfile.TemporaryDirectory(prefix='auths-qualification-artifact-') as temporary: + path = Path(temporary) / 'public.zip' + with path.open('xb') as output: + os.chmod(path, 0o600) + api('actions/artifacts/' + str(artifact['id']) + '/zip', output) + require(last_clock <= time.time() < args.not_after and time.monotonic() < deadline, + 'qualification.artifact.deadline') + unpack(path, artifact, args.out) + return + time.sleep(min(POLL_SECONDS, max(0, deadline - time.monotonic()))) + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--kind', choices=KINDS, required=True) + parser.add_argument('--family', required=True) + parser.add_argument('--not-after', type=int, required=True) + parser.add_argument('--out', type=lambda value: Path(value).absolute(), required=True) + args = parser.parse_args() + finish(lambda: wait(args)) + + +if __name__ == '__main__': + main() From 3871a567171c1d0efa1ab98ba77d5fd341310807 Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 11:13:25 +0100 Subject: [PATCH 074/108] Support the operator Python baseline for artifact verification --- docs/research/INDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md | 2 ++ qualification/run/artifact_wait.py | 6 ++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/research/INDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md b/docs/research/INDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md index f8e3a84aa..1d5957378 100644 --- a/docs/research/INDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md +++ b/docs/research/INDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md @@ -19,6 +19,8 @@ audit or real-user trial is claimed. | Normal authored actions expire while a protected signing job waits. | Keep the installed author in an isolated process for a bounded two-hour grant/session. Refresh only the same predeclared action just before submission; native signatures keep the ordinary five-minute action limit, exact actor/action/request and installation trust. No private key enters artifacts. Both native Docker rehearsals passed with synthetic resources and no network; protected sequencing still needs integration. | | Publication scanning omitted newly added commissioning files and other unlisted outputs. | Replace the filename allowlist with a bounded complete-tree scan. Refuse symbolic/hard links, special or oversized files and concurrent changes; keep canaries private and outside artifacts. Move shipping executables outside the evidence tree and use one credential-free candidate build. Native pipeline regressions plant leaks in commissioning effects, source facts and an unexpected filename. | | A phase's cleanup would destroy the resources needed by the subsequent ordinary qualified phase. | Resource setup/cleanup now belongs to one whole source-owned journey; individual phase runners only execute their phase. Setup runs once, resources stay present across sequential commands, and setup/stage/cleanup failure invalidates both protected phase outputs and the final proposal. Source pipeline tests use explicit doubles; the complete protected signing/qualification sequence still needs integration. | +| An in-memory author connected only by stdin could not survive separate runner steps. | Added a fixed private Unix socket, authenticated Linux peer credentials, a dedicated non-root author UID and root-only controller. Reconnection preserves one key and monotonic refresh generation; changed action/trust bytes or stale packets prevent public handoff. Actual Docker rehearsals passed for both synthetic recipe families with the installed wheel and shipping gateway; no provider or protected qualification was involved. | +| Artifact waits needed exact run identity and safe public extraction. | Added a source-owned reader that pins repository, main/manual workflow, source SHA, run/attempt and artifact role; checks the actual GitHub archive digest; refuses code, links, traversal, duplicates and oversized members; removes partial output. The actual retained native-author report was downloaded and successfully extracted against GitHub's digest. The first local run exposed an unnecessary Python 3.11 hashing API; bounded streaming hashing now works on the operator's Python 3.9. Protected workflow integration remains pending. | The public offline root ceremony and purpose-separated certificates are pinned. Both signer keys are provisioned in the existing reviewer-protected main-only diff --git a/qualification/run/artifact_wait.py b/qualification/run/artifact_wait.py index c58599909..f233f2ab1 100644 --- a/qualification/run/artifact_wait.py +++ b/qualification/run/artifact_wait.py @@ -134,9 +134,11 @@ def unpack(path, artifact, destination): info = os.lstat(path) require(stat.S_ISREG(info.st_mode) and 0 < info.st_size <= MAX_ARCHIVE, 'qualification.artifact.archive-bound') + digest = hashlib.sha256() with path.open('rb') as stream: - actual = hashlib.file_digest(stream, 'sha256').hexdigest() - require(artifact['digest'] == 'sha256:' + actual, 'qualification.artifact.archive-digest') + for chunk in iter(lambda: stream.read(256 * 1024), b''): + digest.update(chunk) + require(artifact['digest'] == 'sha256:' + digest.hexdigest(), 'qualification.artifact.archive-digest') require(not destination.exists(), 'qualification.artifact.output-exists') parent = os.lstat(destination.parent) require(stat.S_ISDIR(parent.st_mode) and stat.S_IMODE(parent.st_mode) == 0o700 From 4d0f1511ae365689922fb3c6c5bb26a2f94612a7 Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 11:30:25 +0100 Subject: [PATCH 075/108] Bind finite commissioning contexts to one shared lifetime budget --- .github/workflows/recipe-qualification.yml | 15 ++++++--- ...ssioning-v1.json => commissioning-v2.json} | 9 +++--- compliance.toml | 6 ++-- ...d-qualification-commissioning-authority.md | 17 ++++++++-- ...NDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md | 2 ++ .../tests/cli.rs | 2 +- .../tests/commissioning.rs | 22 ++++++------- .../src/commissioning.rs | 21 +++++++++--- .../src/commissioning/tests.rs | 32 ++++++++++++++++--- .../auths-recipe-qualification/src/lib.rs | 5 +-- .../auths-gateway/semantic-closure.json | 2 +- .../src/commissioning_budget/tests.rs | 25 ++++++++++++--- .../src/commissioning_floor/tests.rs | 4 +-- .../src/commissioning_session/tests.rs | 7 ++-- .../auths-gateway/src/semantic_closure.rs | 2 +- qualification/reference/README.md | 9 ++++++ qualification/reference/expand.py | 2 +- .../reference/tests/test_reference.py | 4 +-- release/semantic-freeze-versions.toml | 8 ++--- release/semantic-freeze.json | 14 ++++---- 20 files changed, 147 insertions(+), 61 deletions(-) rename bindings/fixtures/qualification/{commissioning-v1.json => commissioning-v2.json} (57%) diff --git a/.github/workflows/recipe-qualification.yml b/.github/workflows/recipe-qualification.yml index 06b8d2b48..b72fb86e9 100644 --- a/.github/workflows/recipe-qualification.yml +++ b/.github/workflows/recipe-qualification.yml @@ -132,11 +132,18 @@ jobs: run: | set -euo pipefail sudo -n mkdir -m 0700 "${RUNNER_TEMP}/socket-report" - sudo -n "${RUNNER_TEMP}/packet-consumer/bin/python" \ - "${RUNNER_TEMP}/packet-kit/qualification/reference/check_socket.py" \ + # The runner's temp ancestors may be private to its login UID. + # Copy only the credential-free kit and installed wheel environment + # into public-readable /opt inputs; keep author output private in /tmp. + sudo -n mkdir -m 0755 /opt/auths-packet-kit /opt/auths-packet-consumer + sudo -n cp -R "${RUNNER_TEMP}/packet-kit/." /opt/auths-packet-kit/ + sudo -n cp -R "${RUNNER_TEMP}/packet-consumer/." /opt/auths-packet-consumer/ + sudo -n chmod -R a+rX /opt/auths-packet-kit /opt/auths-packet-consumer + sudo -n /opt/auths-packet-consumer/bin/python \ + /opt/auths-packet-kit/qualification/reference/check_socket.py \ --gateway "${RUNNER_TEMP}/packet-candidate/bin/auths-gateway" \ - --python "${RUNNER_TEMP}/packet-consumer/bin/python" \ - --work "${RUNNER_TEMP}/socket-operator" \ + --python /opt/auths-packet-consumer/bin/python \ + --work "/tmp/auths-socket-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}" \ --report "${RUNNER_TEMP}/socket-report/report.json" sudo -n cp "${RUNNER_TEMP}/socket-report/report.json" "${RUNNER_TEMP}/packet-operator/socket-report.json" sudo -n chown "$(id -u):$(id -g)" "${RUNNER_TEMP}/packet-operator/socket-report.json" diff --git a/bindings/fixtures/qualification/commissioning-v1.json b/bindings/fixtures/qualification/commissioning-v2.json similarity index 57% rename from bindings/fixtures/qualification/commissioning-v1.json rename to bindings/fixtures/qualification/commissioning-v2.json index 220a9a6c8..5f5a48043 100644 --- a/bindings/fixtures/qualification/commissioning-v1.json +++ b/bindings/fixtures/qualification/commissioning-v2.json @@ -1,15 +1,16 @@ { - "schema": "auths.qualification-commissioning-vectors/1", + "schema": "auths.qualification-commissioning-vectors/2", "synthetic": true, "trust_root": "{\"public_key_b64\":\"0EqyMnQrtKs6E2i9RhXk5tAiSrcaAWuvhSCjMsl3hzc\",\"root_id\":\"test-root\",\"schema\":\"auths.qualification-trust-root/1\",\"signature_suite\":\"ed25519-v1\"}", "signer_certificate": "{\"root_signature_b64\":\"CbNmJUTovHK87FHlPhOC2TtvjfxmR5FHDvg4EAsNSjLR5bjqqG4zBOhDwbwXlNN97La1kMEVU57h3ApQVI_MCg\",\"statement\":{\"issued_at\":1789913600,\"not_after\":1790086400,\"not_before\":1789913600,\"permitted_artifact_kinds\":[\"qualification-commissioning-permit\"],\"public_key_b64\":\"oJql9HpnWYAv-VX43C0qFKXJnSO-l_hkEn_5ODRVpPA\",\"root_id\":\"test-root\",\"schema\":\"auths.qualification-signer-certificate/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"test-commissioner\",\"signer_kind\":\"protected-software-release-key-v1\"}}", "revocation_list": "{\"root_signature_b64\":\"sAtYxcGQsy05npek7vQrBcpqiHKWqcEV-g4EowFJhxs4guxt73ual7FEngULuO3H15qIZLIy4HrbJdyISzJVAA\",\"statement\":{\"issued_at\":1789996400,\"next_update\":1790086400,\"revoked_qualifications\":[],\"revoked_signers\":[],\"root_id\":\"test-root\",\"schema\":\"auths.qualification-revocation-list/1\",\"sequence\":1}}", - "permit": "{\"signature_b64\":\"3FmM2kWZfmUu0xmRVN3C_CYddjGCeOxm3dd7iHL16oawbDBh6TqOwGqc639oYL63ATmYCxh6e3HsPRqQkS1DAQ\",\"statement\":{\"binding\":{\"allowed_actions\":[\"6363636363636363636363636363636363636363636363636363636363636363\",\"6464646464646464646464646464646464646464646464646464646464646464\"],\"maximum_credential_leases\":32,\"offline_evidence\":{\"conformance_sha256\":\"8749fb03dc89fe583529f59c613c78319e893898118092c61344812be78d1b5c\",\"differential_sha256\":\"5f22f2e011050cbabf1f58bdf92a2912fa489353309b594b4db327865e82cd7f\"},\"principal_sha256\":\"6060606060606060606060606060606060606060606060606060606060606060\",\"protected_run\":\"github.com/auths-dev/auths-proof/actions/runs/1/attempts/1\",\"provider_environment_class\":\"provider-test-mode\",\"resources_sha256\":\"6262626262626262626262626262626262626262626262626262626262626262\",\"source_commit\":\"0123456789abcdef0123456789abcdef01234567\",\"trusted_context_sha256\":\"6161616161616161616161616161616161616161616161616161616161616161\",\"tuple\":{\"compiled_recipe_sha256\":\"1111111111111111111111111111111111111111111111111111111111111111\",\"gateway_semantic_closure_sha256\":\"4444444444444444444444444444444444444444444444444444444444444444\",\"profile_lock_sha256\":\"2222222222222222222222222222222222222222222222222222222222222222\",\"provider_contract_id\":\"3333333333333333333333333333333333333333333333333333333333333333\",\"recipe_family\":\"example-refund-v1\",\"target\":{\"arch\":\"x86_64\",\"credential_store_kind\":\"aws-secrets-manager-v1\",\"gateway_build_sha256\":\"5555555555555555555555555555555555555555555555555555555555555555\",\"gateway_package\":\"auths-gateway\",\"gateway_version\":\"1.0.0-rc.1\",\"os\":\"linux\",\"store_kind\":\"postgresql-v1\",\"store_schema\":\"auths.gateway-store/1\"}}},\"issued_at\":1790000000,\"not_after\":1790007200,\"not_before\":1790000000,\"schema\":\"auths.qualification-commissioning-permit/1\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"test-commissioner\"}}", - "permit_digest": "1d4f2378f8514c4697d7eeee3d4c5c33c82046d5b80b44ba84c8f5d47e84632b", + "permit": "{\"signature_b64\":\"0nrpp-Hm34Xnj5fGodRMJJDp6ifsNFCvFJ4M3j7aS9Jz73Y7HkXjYi1GfhzQWLTh6tRTP-VhzSHoukbmeTN6Bg\",\"statement\":{\"binding\":{\"allowed_actions\":[\"6363636363636363636363636363636363636363636363636363636363636363\",\"6464646464646464646464646464646464646464646464646464646464646464\"],\"maximum_credential_leases\":32,\"offline_evidence\":{\"conformance_sha256\":\"8749fb03dc89fe583529f59c613c78319e893898118092c61344812be78d1b5c\",\"differential_sha256\":\"5f22f2e011050cbabf1f58bdf92a2912fa489353309b594b4db327865e82cd7f\"},\"principal_sha256\":\"6060606060606060606060606060606060606060606060606060606060606060\",\"protected_run\":\"github.com/auths-dev/auths-proof/actions/runs/1/attempts/1\",\"provider_environment_class\":\"provider-test-mode\",\"resources_sha256\":\"6262626262626262626262626262626262626262626262626262626262626262\",\"source_commit\":\"0123456789abcdef0123456789abcdef01234567\",\"trusted_contexts_sha256\":[\"6161616161616161616161616161616161616161616161616161616161616161\",\"6565656565656565656565656565656565656565656565656565656565656565\"],\"tuple\":{\"compiled_recipe_sha256\":\"1111111111111111111111111111111111111111111111111111111111111111\",\"gateway_semantic_closure_sha256\":\"4444444444444444444444444444444444444444444444444444444444444444\",\"profile_lock_sha256\":\"2222222222222222222222222222222222222222222222222222222222222222\",\"provider_contract_id\":\"3333333333333333333333333333333333333333333333333333333333333333\",\"recipe_family\":\"example-refund-v1\",\"target\":{\"arch\":\"x86_64\",\"credential_store_kind\":\"aws-secrets-manager-v1\",\"gateway_build_sha256\":\"5555555555555555555555555555555555555555555555555555555555555555\",\"gateway_package\":\"auths-gateway\",\"gateway_version\":\"1.0.0-rc.1\",\"os\":\"linux\",\"store_kind\":\"postgresql-v1\",\"store_schema\":\"auths.gateway-store/1\"}}},\"issued_at\":1790000000,\"not_after\":1790007200,\"not_before\":1790000000,\"schema\":\"auths.qualification-commissioning-permit/2\",\"signature_suite\":\"ed25519-v1\",\"signer_id\":\"test-commissioner\"}}", + "permit_digest": "6023cdfdc1af437745f506196bfb853dc10e9d9e53be86337d230a8934a44480", "budget_scope_sha256": "01640eb7b447d8b909e6955a186f95e3c7bc6765174ee23d8b3dbd0db1c845e5", - "budget_binding_sha256": "b31130f5b9daf728bac55ca8591eedc844919f460e0852f5a5db8febec3c1da0", + "budget_binding_sha256": "d6782163617e1f1aa54cd272fb776fc70426a90fade59718b24306cbfe2275c0", "limits": { "actions": 256, + "contexts": 4, "leases": 1024, "seconds": 7200, "bytes": 32768 diff --git a/compliance.toml b/compliance.toml index 103cb33fe..c6bceae0a 100644 --- a/compliance.toml +++ b/compliance.toml @@ -1161,7 +1161,7 @@ kind = "cargo" layer = "product" path = "product/qualification/auths-recipe-qualification" core_apis = [] -protocol_versions = ["auths.provider-contract/1", "auths.recipe-qualification/1", "auths.recipe-qualification-attestation/1", "auths.qualification-commissioning-permit/1", "auths.qualification-commissioning-budget-key/1", "auths.qualification-commissioning-budget-binding/1", "auths.qualification-commissioning-vectors/1", "auths.qualification-trust-root/1", "auths.qualification-signer-certificate/1", "auths.qualification-revocation-list/1", "auths.qualification-release-index/1", "auths.qualification-evidence/1", "auths.qualification-tuple/1", "auths.gateway-semantic-closure/1", "auths.qualification-schema-vectors/1", "auths.qualification-verification-vectors/1"] +protocol_versions = ["auths.provider-contract/1", "auths.recipe-qualification/1", "auths.recipe-qualification-attestation/1", "auths.qualification-commissioning-permit/2", "auths.qualification-commissioning-budget-key/1", "auths.qualification-commissioning-budget-binding/2", "auths.qualification-commissioning-vectors/2", "auths.qualification-trust-root/1", "auths.qualification-signer-certificate/1", "auths.qualification-revocation-list/1", "auths.qualification-release-index/1", "auths.qualification-evidence/1", "auths.qualification-tuple/1", "auths.gateway-semantic-closure/1", "auths.qualification-schema-vectors/1", "auths.qualification-verification-vectors/1"] wire_objects = ["QualificationCommissioningPermit", "GatewaySemanticClosure", "ProviderContract", "QualificationEvidence", "QualificationReleaseIndex", "QualificationRevocationList", "QualificationSignerCertificate", "QualificationTrustRoot", "RecipeQualificationAttestation", "RecipeQualificationRecord"] fixture_suites = ["bindings/fixtures/qualification"] principal_families = [] @@ -1190,7 +1190,7 @@ kind = "cargo" layer = "product" path = "product/qualification/auths-recipe-qualification-issuance" core_apis = [] -protocol_versions = ["auths.recipe-qualification/1", "auths.recipe-qualification-attestation/1", "auths.qualification-commissioning-permit/1", "auths.qualification-commissioning-budget-key/1", "auths.qualification-commissioning-budget-binding/1", "auths.qualification-commissioning-vectors/1", "auths.qualification-trust-root/1", "auths.qualification-signer-certificate/1", "auths.qualification-revocation-list/1", "auths.qualification-release-index/1", "auths.qualification-evidence/1"] +protocol_versions = ["auths.recipe-qualification/1", "auths.recipe-qualification-attestation/1", "auths.qualification-commissioning-permit/2", "auths.qualification-commissioning-budget-key/1", "auths.qualification-commissioning-budget-binding/2", "auths.qualification-commissioning-vectors/2", "auths.qualification-trust-root/1", "auths.qualification-signer-certificate/1", "auths.qualification-revocation-list/1", "auths.qualification-release-index/1", "auths.qualification-evidence/1"] wire_objects = ["QualificationCommissioningPermit", "QualificationEvidence", "QualificationReleaseIndex", "QualificationRevocationList", "QualificationSignerCertificate", "QualificationTrustRoot", "RecipeQualificationAttestation", "RecipeQualificationRecord"] fixture_suites = [] principal_families = [] @@ -1600,7 +1600,7 @@ kind = "cargo" layer = "product" path = "product/runtime/auths-gateway" core_apis = ["auths-author", "auths-codec", "auths-did-keri", "auths-did-key", "auths-model", "auths-multikey", "auths-ports", "auths-raw-key", "auths-raw-key-core", "auths-registries", "auths-signature", "auths-verifier"] -protocol_versions = ["auths.gateway-commissioning-budget/1", "auths.qualification-commissioning-permit/1", "auths.qualification-commissioning-budget-key/1", "auths.qualification-commissioning-budget-binding/1", "auths.gateway-credential-journal/1", "auths.gateway-credential-collection/1", "auths.gateway-readiness/1", "auths.gateway-support-bundle/1", "auths.gateway-generation-floor/1", "auths.gateway-emergency-stop/1", "auths.gateway-installation/5", "auths.recipe-qualification/1", "auths.recipe-qualification-attestation/1", "auths.qualification-trust-root/1", "auths.qualification-signer-certificate/1", "auths.qualification-revocation-list/1", "auths.qualification-release-index/1", "auths.gateway-semantic-closure/1", "auths.qualification-verification-vectors/1", "auths.gateway-operator-attestation/1", "auths.gateway-admin-request/1", "auths.gateway-admin-response/1", "auths.gateway-connection/1", "auths.provider-connection/2", "auths.gateway-key-identity/1", "auths.lifecycle.transactional-store/4", "auths.gateway-recipe-source/2", "auths.gateway-compiled-recipe/2", "auths.gateway-recipe-review/2", "auths.gateway-recovery-capability/1", "auths.gateway-connection-descriptor/1", "auths.gateway-attempt/3", "auths.gateway-pre-entry/1", "auths.lifecycle.postgresql/6", "auths.gateway-echo/1", "auths.gateway-idempotency-key/1", "auths.gateway-observe/2", "auths.gateway-outcome/2", "auths.gateway-readback/1", "auths.self-hosted-profile-lock/1", "mcp-arguments-v1", "auths.gateway-audit-bundle/2", "auths.gateway-audit-report/3", "auths.gateway-counter-set/1", "auths.gateway-echo-verification/1", "auths.gateway-codes/1", "auths.gateway-production-codes/1", "auths.gateway-custody-vectors/1", "auths.gateway-outcome-vectors/1", "bounded-policy-commitment-v1", "auths.approval-response/1", "auths.gateway-bounded-count/2", "auths.gateway-bounded-sum/1", "auths.gateway.argument-ceiling-window-count/2", "auths.gateway.argument-ceiling-policy/2"] +protocol_versions = ["auths.gateway-commissioning-budget/1", "auths.qualification-commissioning-permit/2", "auths.qualification-commissioning-budget-key/1", "auths.qualification-commissioning-budget-binding/2", "auths.gateway-credential-journal/1", "auths.gateway-credential-collection/1", "auths.gateway-readiness/1", "auths.gateway-support-bundle/1", "auths.gateway-generation-floor/1", "auths.gateway-emergency-stop/1", "auths.gateway-installation/5", "auths.recipe-qualification/1", "auths.recipe-qualification-attestation/1", "auths.qualification-trust-root/1", "auths.qualification-signer-certificate/1", "auths.qualification-revocation-list/1", "auths.qualification-release-index/1", "auths.gateway-semantic-closure/1", "auths.qualification-verification-vectors/1", "auths.gateway-operator-attestation/1", "auths.gateway-admin-request/1", "auths.gateway-admin-response/1", "auths.gateway-connection/1", "auths.provider-connection/2", "auths.gateway-key-identity/1", "auths.lifecycle.transactional-store/4", "auths.gateway-recipe-source/2", "auths.gateway-compiled-recipe/2", "auths.gateway-recipe-review/2", "auths.gateway-recovery-capability/1", "auths.gateway-connection-descriptor/1", "auths.gateway-attempt/3", "auths.gateway-pre-entry/1", "auths.lifecycle.postgresql/6", "auths.gateway-echo/1", "auths.gateway-idempotency-key/1", "auths.gateway-observe/2", "auths.gateway-outcome/2", "auths.gateway-readback/1", "auths.self-hosted-profile-lock/1", "mcp-arguments-v1", "auths.gateway-audit-bundle/2", "auths.gateway-audit-report/3", "auths.gateway-counter-set/1", "auths.gateway-echo-verification/1", "auths.gateway-codes/1", "auths.gateway-production-codes/1", "auths.gateway-custody-vectors/1", "auths.gateway-outcome-vectors/1", "bounded-policy-commitment-v1", "auths.approval-response/1", "auths.gateway-bounded-count/2", "auths.gateway-bounded-sum/1", "auths.gateway.argument-ceiling-window-count/2", "auths.gateway.argument-ceiling-policy/2"] wire_objects = ["CommissioningBudgetSnapshot", "CompiledRecipe", "ClosedProviderRequest", "ClosedCredentialReads", "RecipeReview", "RecoveryCapability", "GatewayAttemptSnapshot", "GatewayPreEntry", "GatewayRecordEntry", "GatewayConnectionDescriptor", "ConnectionRecord", "OperatorAttestation", "OperatorStatement", "GatewayAdminStatus", "GatewayEvidenceSummary", "GatewayObserveRequest", "GatewayObserveResult", "GatewayProviderEvidence", "GatewaySubmitResult", "SignedObservation", "ArgumentCeilingPolicy", "BoundedPolicyCommitment", "AuditReport", "ProviderResult", "AuditedPreEntry", "EchoVerification", "AdminRequestCommand", "ListedValues"] fixture_suites = ["bindings/fixtures/approval", "bindings/fixtures/gateway", "bindings/fixtures/qualification"] principal_families = ["raw-key-v1", "did-key-v1", "did-keri-v1"] diff --git a/docs/adr/0016-bounded-qualification-commissioning-authority.md b/docs/adr/0016-bounded-qualification-commissioning-authority.md index dd45af582..2b8b2c836 100644 --- a/docs/adr/0016-bounded-qualification-commissioning-authority.md +++ b/docs/adr/0016-bounded-qualification-commissioning-authority.md @@ -42,7 +42,8 @@ Every permit must bind: - the exact candidate commit, executable digest, semantic closure and production tuple, including PostgreSQL schema and custody kind; -- the reviewed provider contract, recipe, lock and trusted-context digests; +- the reviewed provider contract, recipe, lock and finite exact trusted-context + digests; - one protected workflow run and one ephemeral proof-authoring principal; - reviewed disposable resource bindings and a precomputed finite set of exact canonical action commitments; @@ -65,6 +66,18 @@ rollback, unavailable shared state or any mismatch refuses before a lease. Unknown provider outcomes retain ordinary uncertainty and cannot gain a second write through permit renewal. A denied input is terminal for those inputs. +Permit schema 2 fixes a fresh-challenge coverage problem in schema 1: pinning +only one installed challenge prevented a valid new-challenge replay from reaching +the durable claim. The signer now binds a sorted unique set of at most four exact +canonical context hashes. Each installation still needs its own authenticated +operator attestation for its actual context, and every proof still verifies +against that installed challenge. The complete set is immutable at the one +run/family budget key; another context, set change, renewal or host cannot reset +capacity. There is no wildcard context, context-template normalization or old +permit reader. Reviewed author/reference support must create and independently +review the exact contexts before signing; adding the schema alone does not +establish protected replay evidence. + ## Evidence and bootstrap sequence 1. Build and install the exact production candidate with ordinary qualification @@ -116,7 +129,7 @@ commissioning certificates carry no attestation or index permission. A mixed-purpose certificate is refused by the commissioning verifier. The public synthetic vector is -`bindings/fixtures/qualification/commissioning-v1.json`. Native tests consume +`bindings/fixtures/qualification/commissioning-v2.json`. Native tests consume these frozen bytes without issuance code. They cover strict decoding and every single-bit signature mutation; issuance tests additionally cover purpose/root/ domain separation, exact runtime bindings, time/revocation boundaries, finite diff --git a/docs/research/INDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md b/docs/research/INDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md index 1d5957378..d64135668 100644 --- a/docs/research/INDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md +++ b/docs/research/INDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md @@ -21,6 +21,8 @@ audit or real-user trial is claimed. | A phase's cleanup would destroy the resources needed by the subsequent ordinary qualified phase. | Resource setup/cleanup now belongs to one whole source-owned journey; individual phase runners only execute their phase. Setup runs once, resources stay present across sequential commands, and setup/stage/cleanup failure invalidates both protected phase outputs and the final proposal. Source pipeline tests use explicit doubles; the complete protected signing/qualification sequence still needs integration. | | An in-memory author connected only by stdin could not survive separate runner steps. | Added a fixed private Unix socket, authenticated Linux peer credentials, a dedicated non-root author UID and root-only controller. Reconnection preserves one key and monotonic refresh generation; changed action/trust bytes or stale packets prevent public handoff. Actual Docker rehearsals passed for both synthetic recipe families with the installed wheel and shipping gateway; no provider or protected qualification was involved. | | Artifact waits needed exact run identity and safe public extraction. | Added a source-owned reader that pins repository, main/manual workflow, source SHA, run/attempt and artifact role; checks the actual GitHub archive digest; refuses code, links, traversal, duplicates and oversized members; removes partial output. The actual retained native-author report was downloaded and successfully extracted against GitHub's digest. The first local run exposed an unnecessary Python 3.11 hashing API; bounded streaming hashing now works on the operator's Python 3.9. Protected workflow integration remains pending. | +| A dedicated author UID could not launch the SDK beneath the hosted runner's private temporary ancestors. | The hosted author job failed. A Docker reproduction confirmed the private-parent launcher refusal and then passed with public-readable copied SDK inputs. CI now copies only the credential-free kit and installed wheel environment to `/opt`; author output remains owner-private under `/tmp`. Hosted verification of this correction is pending. | +| A permit pinned one challenge, preventing a valid fresh-challenge replay from reaching the durable claim. | Native permit schema 2 binds 1–4 exact sorted context hashes; every context still needs its own operator attestation and native challenge verification. The full set shares one immutable run/family budget. Frozen vectors cover both listed contexts and an outsider; the durable final-unit race uses different contexts, and a set change cannot register new capacity. The current author still emits one context; source-owned fresh-challenge packet and protected corpus integration remain pending. | The public offline root ceremony and purpose-separated certificates are pinned. Both signer keys are provisioned in the existing reviewer-protected main-only diff --git a/product/qualification/auths-recipe-qualification-issuance/tests/cli.rs b/product/qualification/auths-recipe-qualification-issuance/tests/cli.rs index 5f06bc170..65e2fabab 100644 --- a/product/qualification/auths-recipe-qualification-issuance/tests/cli.rs +++ b/product/qualification/auths-recipe-qualification-issuance/tests/cli.rs @@ -145,7 +145,7 @@ fn commissioning_cli_requires_its_own_purpose_and_rechecks_offline_evidence() { source_commit: common::commit(), tuple: common::tuple(), principal_sha256: Sha256Digest::from_bytes([0x61; 32]), - trusted_context_sha256: Sha256Digest::from_bytes([0x62; 32]), + trusted_contexts_sha256: vec![Sha256Digest::from_bytes([0x62; 32])], resources_sha256: Sha256Digest::from_bytes([0x63; 32]), provider_environment_class: ProviderEnvironmentClass::ProviderTestMode, offline_evidence: CommissioningOfflineEvidence { diff --git a/product/qualification/auths-recipe-qualification-issuance/tests/commissioning.rs b/product/qualification/auths-recipe-qualification-issuance/tests/commissioning.rs index f48f449bf..44cc79ce1 100644 --- a/product/qualification/auths-recipe-qualification-issuance/tests/commissioning.rs +++ b/product/qualification/auths-recipe-qualification-issuance/tests/commissioning.rs @@ -9,11 +9,11 @@ mod common; use auths_recipe_qualification::{ BoundedText, ClosureFault, CommissioningBinding, CommissioningInputs, CommissioningOfflineEvidence, CommissioningRefusal, CommissioningRequest, EvidenceMemberKind, - GitCommit, MAX_COMMISSIONING_ACTIONS, MAX_COMMISSIONING_LEASES, MAX_COMMISSIONING_PERMIT_BYTES, - MAX_COMMISSIONING_SECONDS, ProviderEnvironmentClass, QualificationArtifactKind, - QualificationCommissioningPermit, QualificationEvidence, QualificationFormatError, - QualificationInputs, QualificationRevocationList, QualificationRootId, - QualificationSignerCertificate, QualificationSignerId, QualificationTuple, + GitCommit, MAX_COMMISSIONING_ACTIONS, MAX_COMMISSIONING_CONTEXTS, MAX_COMMISSIONING_LEASES, + MAX_COMMISSIONING_PERMIT_BYTES, MAX_COMMISSIONING_SECONDS, ProviderEnvironmentClass, + QualificationArtifactKind, QualificationCommissioningPermit, QualificationEvidence, + QualificationFormatError, QualificationInputs, QualificationRevocationList, + QualificationRootId, QualificationSignerCertificate, QualificationSignerId, QualificationTuple, RecipeQualificationState, Scenario, Sha256Digest, SignatureB64, VerifiedCommissioningPermit, VerifiedQualifications, VerifierState, }; @@ -70,7 +70,7 @@ fn binding() -> CommissioningBinding { source_commit: commit(), tuple: tuple(), principal_sha256: digest(0x60), - trusted_context_sha256: digest(0x61), + trusted_contexts_sha256: vec![digest(0x61), digest(0x65)], resources_sha256: digest(0x62), provider_environment_class: ProviderEnvironmentClass::ProviderTestMode, offline_evidence: CommissioningOfflineEvidence { @@ -124,7 +124,7 @@ fn request(binding: &CommissioningBinding) -> CommissioningRequest<'_> { tuple: &binding.tuple, protected_run: &binding.protected_run, principal_sha256: binding.principal_sha256, - trusted_context_sha256: binding.trusted_context_sha256, + trusted_context_sha256: binding.trusted_contexts_sha256[0], resources_sha256: binding.resources_sha256, canonical_action_sha256: binding.allowed_actions[0], } @@ -690,7 +690,7 @@ fn renewal_cannot_change_the_durable_budget_identity_or_binding() { ..original.clone() }, CommissioningBinding { - trusted_context_sha256: digest(0x70), + trusted_contexts_sha256: vec![digest(0x70)], ..original.clone() }, ] { @@ -713,7 +713,7 @@ fn commissioning_artifact_fixture_is_current() { let permit = permit(&signer); let list = revocations(&root, 1); let document = json!({ - "schema": "auths.qualification-commissioning-vectors/1", + "schema": "auths.qualification-commissioning-vectors/2", "synthetic": true, "trust_root": std::str::from_utf8(root.trust_root().canonical_bytes()).expect("UTF-8"), "signer_certificate": std::str::from_utf8(signer.certificate().canonical_bytes()).expect("UTF-8"), @@ -722,12 +722,12 @@ fn commissioning_artifact_fixture_is_current() { "permit_digest": permit.digest(), "budget_scope_sha256": permit.body().statement.binding.budget_key().expect("key"), "budget_binding_sha256": permit.body().statement.binding.budget_binding().expect("binding"), - "limits": { "actions": MAX_COMMISSIONING_ACTIONS, + "limits": { "actions": MAX_COMMISSIONING_ACTIONS, "contexts": MAX_COMMISSIONING_CONTEXTS, "leases": MAX_COMMISSIONING_LEASES, "seconds": MAX_COMMISSIONING_SECONDS, "bytes": MAX_COMMISSIONING_PERMIT_BYTES }, }); let path = std::path::Path::new(env!("CARGO_MANIFEST_DIR")) - .join("../../../bindings/fixtures/qualification/commissioning-v1.json"); + .join("../../../bindings/fixtures/qualification/commissioning-v2.json"); let mut encoded = serde_json::to_vec_pretty(&document).expect("fixture"); encoded.push(b'\n'); if std::env::var_os("AUTHS_UPDATE_FIXTURES").is_some() { diff --git a/product/qualification/auths-recipe-qualification/src/commissioning.rs b/product/qualification/auths-recipe-qualification/src/commissioning.rs index 35a923681..07a796713 100644 --- a/product/qualification/auths-recipe-qualification/src/commissioning.rs +++ b/product/qualification/auths-recipe-qualification/src/commissioning.rs @@ -20,18 +20,22 @@ use serde::{Deserialize, Serialize}; mod tests; /// The separate signature domain of a commissioning permit. -pub const COMMISSIONING_PERMIT_SCHEMA: &str = "auths.qualification-commissioning-permit/1"; +pub const COMMISSIONING_PERMIT_SCHEMA: &str = "auths.qualification-commissioning-permit/2"; /// Public file within a protected commissioning artifact directory. pub const COMMISSIONING_PERMIT_FILE: &str = "commissioning-permit.json"; /// The domain of the stable run/family budget key. pub const COMMISSIONING_BUDGET_KEY_DOMAIN: &str = "auths.qualification-commissioning-budget-key/1"; /// The domain of the immutable budget binding, including its ceiling. pub const COMMISSIONING_BUDGET_BINDING_DOMAIN: &str = - "auths.qualification-commissioning-budget-binding/1"; + "auths.qualification-commissioning-budget-binding/2"; /// The largest commissioning permit accepted before parsing. pub const MAX_COMMISSIONING_PERMIT_BYTES: usize = 32 * 1024; /// The maximum distinct exact actions one permit may authorize. pub const MAX_COMMISSIONING_ACTIONS: usize = 256; +/// The maximum distinct operator-approved contexts in one immutable permit. +/// Fresh-challenge replay may change the request challenge, but cannot admit +/// an unlisted context or register a new lifetime budget. +pub const MAX_COMMISSIONING_CONTEXTS: usize = 4; /// The maximum custody acquisitions one permit may authorize. pub const MAX_COMMISSIONING_LEASES: u64 = 1024; /// A commissioning permit lasts at most two hours. @@ -63,8 +67,9 @@ pub struct CommissioningBinding { pub tuple: QualificationTuple, /// Commitment to the ephemeral proof-authoring principal's canonical bytes. pub principal_sha256: Sha256Digest, - /// Commitment to the operator-approved canonical trusted context. - pub trusted_context_sha256: Sha256Digest, + /// Exact canonical operator-approved context commitments, sorted and unique. + /// The complete finite set is part of the immutable shared budget binding. + pub trusted_contexts_sha256: Vec, /// Commitment to the reviewed disposable provider resource bindings. pub resources_sha256: Sha256Digest, /// What kind of disposable provider environment is actually exercised. @@ -128,10 +133,13 @@ impl CommissioningBinding { } if self.allowed_actions.is_empty() || self.allowed_actions.len() > MAX_COMMISSIONING_ACTIONS + || self.trusted_contexts_sha256.is_empty() + || self.trusted_contexts_sha256.len() > MAX_COMMISSIONING_CONTEXTS || !(1..=MAX_COMMISSIONING_LEASES).contains(&self.maximum_credential_leases) { return Err(QualificationFormatError::ListBound); } + canonical::strictly_ascending(&self.trusted_contexts_sha256)?; canonical::strictly_ascending(&self.allowed_actions) } } @@ -418,7 +426,10 @@ impl VerifiedCommissioningPermit { || binding.tuple != *request.tuple || binding.protected_run != *request.protected_run || binding.principal_sha256 != request.principal_sha256 - || binding.trusted_context_sha256 != request.trusted_context_sha256 + || binding + .trusted_contexts_sha256 + .binary_search(&request.trusted_context_sha256) + .is_err() || binding.resources_sha256 != request.resources_sha256 || binding .allowed_actions diff --git a/product/qualification/auths-recipe-qualification/src/commissioning/tests.rs b/product/qualification/auths-recipe-qualification/src/commissioning/tests.rs index 566af472b..65a29e910 100644 --- a/product/qualification/auths-recipe-qualification/src/commissioning/tests.rs +++ b/product/qualification/auths-recipe-qualification/src/commissioning/tests.rs @@ -4,7 +4,7 @@ use super::*; fn fixture() -> serde_json::Value { let path = std::path::Path::new(env!("CARGO_MANIFEST_DIR")) - .join("../../../bindings/fixtures/qualification/commissioning-v1.json"); + .join("../../../bindings/fixtures/qualification/commissioning-v2.json"); serde_json::from_slice(&std::fs::read(path).expect("fixture")).expect("fixture JSON") } @@ -38,15 +38,24 @@ fn frozen_commissioning_bytes_authenticate_only_their_exact_binding() { tuple: &binding.tuple, protected_run: &binding.protected_run, principal_sha256: binding.principal_sha256, - trusted_context_sha256: binding.trusted_context_sha256, + trusted_context_sha256: binding.trusted_contexts_sha256[0], resources_sha256: binding.resources_sha256, canonical_action_sha256: binding.allowed_actions[0], }; let now = permit.body().statement.not_before; + for context in &binding.trusted_contexts_sha256 { + request.trusted_context_sha256 = *context; + assert_eq!( + verified.evaluate(&request, now, true, &VerifierState::default()), + Ok(()) + ); + } + request.trusted_context_sha256 = Sha256Digest::from_bytes([0xfe; 32]); assert_eq!( verified.evaluate(&request, now, true, &VerifierState::default()), - Ok(()) + Err(CommissioningRefusal::BindingMismatch) ); + request.trusted_context_sha256 = binding.trusted_contexts_sha256[0]; request.principal_sha256 = Sha256Digest::from_bytes([0xff; 32]); assert_eq!( verified.evaluate(&request, now, true, &VerifierState::default()), @@ -117,9 +126,24 @@ fn unsigned_shape_never_accepts_extra_duplicate_or_unknown_members() { Err(QualificationFormatError::Malformed) ); let mut body = permit.body().clone(); - body.statement.schema = "auths.qualification-commissioning-permit/0".to_owned(); + body.statement.schema = "auths.qualification-commissioning-permit/1".to_owned(); assert_eq!( QualificationCommissioningPermit::from_body(&body).map(|_| ()), Err(QualificationFormatError::UnknownSchema) ); + for contexts in [ + vec![], + vec![Sha256Digest::from_bytes([0x61; 32]); 2], + vec![ + Sha256Digest::from_bytes([0x65; 32]), + Sha256Digest::from_bytes([0x61; 32]), + ], + (0..=MAX_COMMISSIONING_CONTEXTS) + .map(|index| Sha256Digest::from_bytes([u8::try_from(index).expect("bound"); 32])) + .collect(), + ] { + let mut body = permit.body().clone(); + body.statement.binding.trusted_contexts_sha256 = contexts; + assert!(QualificationCommissioningPermit::from_body(&body).is_err()); + } } diff --git a/product/qualification/auths-recipe-qualification/src/lib.rs b/product/qualification/auths-recipe-qualification/src/lib.rs index a73218320..52f80fbda 100644 --- a/product/qualification/auths-recipe-qualification/src/lib.rs +++ b/product/qualification/auths-recipe-qualification/src/lib.rs @@ -53,8 +53,9 @@ pub use commissioning::{ COMMISSIONING_PERMIT_FILE, COMMISSIONING_PERMIT_SCHEMA, CommissioningBinding, CommissioningInputs, CommissioningOfflineEvidence, CommissioningPermitBody, CommissioningPermitStatement, CommissioningRefusal, CommissioningRequest, - MAX_COMMISSIONING_ACTIONS, MAX_COMMISSIONING_LEASES, MAX_COMMISSIONING_PERMIT_BYTES, - MAX_COMMISSIONING_SECONDS, QualificationCommissioningPermit, VerifiedCommissioningPermit, + MAX_COMMISSIONING_ACTIONS, MAX_COMMISSIONING_CONTEXTS, MAX_COMMISSIONING_LEASES, + MAX_COMMISSIONING_PERMIT_BYTES, MAX_COMMISSIONING_SECONDS, QualificationCommissioningPermit, + VerifiedCommissioningPermit, }; pub use error::QualificationFormatError; pub use evidence::{ diff --git a/product/runtime/auths-gateway/semantic-closure.json b/product/runtime/auths-gateway/semantic-closure.json index 4831ba22a..841341526 100644 --- a/product/runtime/auths-gateway/semantic-closure.json +++ b/product/runtime/auths-gateway/semantic-closure.json @@ -1 +1 @@ -{"files":[{"path":"Cargo.lock","sha256":"0e75e2fdef44e79e57797ac6661295ae58ddb8de4a1990a6fd22ce6c54f78604"},{"path":"Cargo.toml","sha256":"6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24"},{"path":"core/adapters/auths-did-keri/Cargo.toml","sha256":"86ba3e3f9a0a70d970568bfb3113b7ba7bbdd81c3eebbb52743dd574a0c0ecaa"},{"path":"core/adapters/auths-did-keri/src/lib.rs","sha256":"a75674842f8a7142004369ccd206ab43e476459293f0ff4bed4d4e659031b3e3"},{"path":"core/adapters/auths-did-key/Cargo.toml","sha256":"d5a3ae07ecde83f91eed4c3785051dd0f44eab6c891754f3309b6b40596707d7"},{"path":"core/adapters/auths-did-key/src/lib.rs","sha256":"b76a3f4528a725df53cfa9242e6e414e1d26caa48468aaed497e28b121f4497c"},{"path":"core/adapters/auths-raw-key/Cargo.toml","sha256":"f49616bc18c19e6aaa7e6a02ccebcdb9f5c1422c1278ef9869e0dbf22ceda7be"},{"path":"core/adapters/auths-raw-key/src/lib.rs","sha256":"45eec1b295dac3bed65cd79c942870b926b06b3f5d38eaebaeb6140ac69315fa"},{"path":"core/crates/auths-algebra-kernel/Cargo.toml","sha256":"0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba"},{"path":"core/crates/auths-algebra-kernel/src/generated.rs","sha256":"ae4bcbef42a408c7ffa0c6a74a42f7de177a6f14479e51d205acf830bda05960"},{"path":"core/crates/auths-algebra-kernel/src/lib.rs","sha256":"6654667eeb9b353d6648954c9fd2e8838462a82ce6b2803eb49e1366892c68c6"},{"path":"core/crates/auths-assurance/Cargo.toml","sha256":"afcb12a97ddd09d7a264b9ecd3fcaefc865ff2c9b4539ee85b00883420ba333a"},{"path":"core/crates/auths-assurance/src/lib.rs","sha256":"0fb2ec844d674b25a9e20b1601452c89c2454901fa506adfa9bb38ef9a7fa213"},{"path":"core/crates/auths-author/Cargo.toml","sha256":"1e6f0e3bc079ddb558decf0db26b291c6e72fc47327b6df1b7650d41689b215f"},{"path":"core/crates/auths-author/src/lib.rs","sha256":"e14475f2f49715a1869d5fa6b11ff1fbb72497e39097e09f833b0bae7e5b3f2b"},{"path":"core/crates/auths-author/src/observations.rs","sha256":"dda7d6bfa6f4bd7e95a480ca283c2c0e996f69c5c15cb0c7197af328131a7066"},{"path":"core/crates/auths-authority/Cargo.toml","sha256":"4f68212938029f79ebd857b4f3038494eb85d0163d49f07e51376715cf959815"},{"path":"core/crates/auths-authority/src/lib.rs","sha256":"da88d5194de4e17449e69972c0fb042afa3c39798a8f570f30771e77c384f1eb"},{"path":"core/crates/auths-codec/Cargo.toml","sha256":"e20e51826e17814effd9d8925d18d5fbdd6c0d37bf50231e743ec2611314722c"},{"path":"core/crates/auths-codec/src/approval.rs","sha256":"fbff43bf4d57f69f8b7738a8647751cde75c5a932dee65d924a1fe9c7202f91f"},{"path":"core/crates/auths-codec/src/bounded_policy.rs","sha256":"d21f6728be2d8a04b6d94921f2b683f7e61cbb42e0ac6866f1c88a49caa534c3"},{"path":"core/crates/auths-codec/src/decode.rs","sha256":"ba2999584cdf53b1b517ecb9c7ea50d39efee17c666a9a38e2ad1ac94379f778"},{"path":"core/crates/auths-codec/src/encode.rs","sha256":"8491192053e2e15d62b4d2a491de22405b7487ead69ab6f6bca40669ce7ca5f7"},{"path":"core/crates/auths-codec/src/error.rs","sha256":"fecb0737c16deb42d859f1dc7727c698438d9ac12064fd99e0024629642c390c"},{"path":"core/crates/auths-codec/src/hash.rs","sha256":"f88e111f1dbb2cef6b7b5e9c948cb45ff92e366710c8a5f5c636138aa748479e"},{"path":"core/crates/auths-codec/src/lib.rs","sha256":"3b0e5c94c6f34f750b88a9333e1d5c8145746d845d3a23e0d2f61807cf592ea7"},{"path":"core/crates/auths-codec/src/observation.rs","sha256":"38328b0c71ff97a4196eeade8b4faa889527ff1f80bb168468bcd49082a3987e"},{"path":"core/crates/auths-composition/Cargo.toml","sha256":"331e13025eb82588b5269ed3975929eb41c823d588c49e4c296273d85c6fe80e"},{"path":"core/crates/auths-composition/src/lib.rs","sha256":"e42e3b0b6a9985b73c533aeb23799c638979aa27a9ce7d0f10a8d60340570fb1"},{"path":"core/crates/auths-model/Cargo.toml","sha256":"565c15302b0cc9270db1e28efa3862804846850ba933cc17aea8abcec4a65987"},{"path":"core/crates/auths-model/src/approval.rs","sha256":"54cf44a9ef747ec21546a4086aecfb130bc7803b0d646430e6082df51e6e305f"},{"path":"core/crates/auths-model/src/bounded.rs","sha256":"f90496abc0a06c028b4d850af6ddab7d850bfafeaa3d042f1b1246a41d8bbbc9"},{"path":"core/crates/auths-model/src/bounded_policy.rs","sha256":"306a8f049cc7cfc7635fe0e4de47eb7813eed63d3c14c3be2b51586aa4eea450"},{"path":"core/crates/auths-model/src/lib.rs","sha256":"e7cfe6bb9574c6b016aa63e70658c31e0b90903ec6479a49f4a2ceb64f5bad97"},{"path":"core/crates/auths-model/src/observation.rs","sha256":"b3ed3e3cc090afca2896a7d3de7988afccc1ee1ea0ebd91b51a8bc0f20ad8dbb"},{"path":"core/crates/auths-multikey/Cargo.toml","sha256":"858756c1197befcada06134742bffe8d58cf674cadd6c046bf710570e96efaf2"},{"path":"core/crates/auths-multikey/src/lib.rs","sha256":"f5177fffb11e40eeaaa665ba886c541fc1f24d5eacdd6983fb03dc20148733f0"},{"path":"core/crates/auths-ports/Cargo.toml","sha256":"596a9b0f5af3717c16a6d13f7054d8a106bcd9f01f5f72c2235dd2afcf0ab16c"},{"path":"core/crates/auths-ports/src/binding.rs","sha256":"a16c012d40aa4249e3ec54372b9611006d0bfe8c7dc3c741911c2194ad17736d"},{"path":"core/crates/auths-ports/src/diagnostics.rs","sha256":"aa596572503b5a65a918bb2ff38281c144ff53821ee914e9325c852828d852df"},{"path":"core/crates/auths-ports/src/lib.rs","sha256":"8da1debf86f9532df0660155d04298beb1ba3a1204508f8586e2e67cd2fb3449"},{"path":"core/crates/auths-ports/src/path.rs","sha256":"b68fc547b4e4d97a60cbbc1cc1939fc6b34a8233b81f840bd396914a707e3ea1"},{"path":"core/crates/auths-raw-key-core/Cargo.toml","sha256":"98c0bc8527a537512e43a74dd6ba9658c6f0cdc16610cf938e3f9b43785d836d"},{"path":"core/crates/auths-raw-key-core/src/lib.rs","sha256":"98c0500c41697aae28708ad0bf970b9a97583d96a3d2c18d23e7fa351e0f7d12"},{"path":"core/crates/auths-registries/Cargo.toml","sha256":"590e49e58b0622d9d6274fea46796dcdb07dec9550eff295cce6a6427ffa51e2"},{"path":"core/crates/auths-registries/src/lib.rs","sha256":"450d3886d85ee333b7e046317fb5b47cde62483d5f3e41d46265e2caf4c373ec"},{"path":"core/crates/auths-registries/src/template.rs","sha256":"1224039dd2b3ce6fa8357613d8cafbae40400493da7176da202b9ade62fa05e4"},{"path":"core/crates/auths-signature-core/Cargo.toml","sha256":"6bee2230eb30af1be0bd5c2d57bd3e1903497a70028d47290d4ac6e9e0e8bca0"},{"path":"core/crates/auths-signature-core/src/lib.rs","sha256":"6e3f9311ded5e49ea50d445eb21e6d8fa12442aa4362a73e0cb6fda15b7cd865"},{"path":"core/crates/auths-signature/Cargo.toml","sha256":"7f7b5682466ba439d8c59579022cb61068cad9fb4bd2d73e1cc21327c902b450"},{"path":"core/crates/auths-signature/src/lib.rs","sha256":"b3d9ac4cc3ba0797b9e1c09f2d6ac05089b25dac4e285a5af28c0165b33d925b"},{"path":"core/crates/auths-verifier/Cargo.toml","sha256":"c43358e06a33324b41a8b93e5cc7279c55f7d21f1f6cfaa539a3fc7b4c27a38f"},{"path":"core/crates/auths-verifier/src/approval.rs","sha256":"c3cae6a49e169051eb555bb092b1069a4d422516d6a2114623a89e5f31ff923f"},{"path":"core/crates/auths-verifier/src/causal.rs","sha256":"9635230f33b13a263573d319ac8a1976addbcc07677514a43e3c7bf28dc04587"},{"path":"core/crates/auths-verifier/src/lib.rs","sha256":"f22dec38dfa47ced8da4f605390da8453273bee1da010f57fd1fdfcb10e0b389"},{"path":"core/crates/auths-verifier/src/observation.rs","sha256":"0bb07f06a0f9524c88427df1c972b1de8ba038a9eeeb15d3134c25125ae84b1e"},{"path":"core/crates/auths-verifier/src/trace.rs","sha256":"2213d72023a1d9e0413a2cf2c51c3dad9e04775d86033a0caaa9d29a8f0036f8"},{"path":"exchange/crates/auths-proof-exchange-model/Cargo.toml","sha256":"34b2db64f93a288e942b5a3918d28cdcbef906e0dc9074ce848018d3d5f7a1fa"},{"path":"exchange/crates/auths-proof-exchange-model/src/lib.rs","sha256":"49fac5aff2339d3a57c41cb8bb2a82852538e8f77ecc4b157c88e264ff31fb55"},{"path":"exchange/crates/auths-proof-exchange-port/Cargo.toml","sha256":"7ff660f1b7579dc570c791090aeb450404fbbf44c92781e289f5ccdde746d739"},{"path":"exchange/crates/auths-proof-exchange-port/src/lib.rs","sha256":"b408fb40c6432edc1facb3d8b3e9433a033f8dc73fe2e0ba5a88c972ca675021"},{"path":"product/config/auths-config/Cargo.toml","sha256":"e4b568ab9f6d84f7d7e6d66443fe825f360db9c27bc7c31d6ddc0647ba3ab304"},{"path":"product/config/auths-config/src/lib.rs","sha256":"fecf00ea65cef9018fda9af2063326d7065b869266d0d9e73a4f06816f1102cc"},{"path":"product/errors/auths-errors/Cargo.toml","sha256":"3b3a199b6460ba75bda84475bb5accd35e1485448a3981038db85bf4772dd350"},{"path":"product/errors/auths-errors/src/lib.rs","sha256":"7feeb9069fa4003f94f1f07c1c94619cf1c883e0dbaaf2187f04d0f742264bdd"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/Cargo.toml","sha256":"716f1f2a117d6d69d8effe9ee9057e24ba3502f20af6a602b06facb638cdabed"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/api.rs","sha256":"9ea61dd7ddd93282b073b98e453e6b75b26dc49689c04e9782435d06a3a09e48"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/clock.rs","sha256":"73f0a6e0f5903883329fa6683f5888288f759512ac69e5c87efd2b6b87f7d79f"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/http.rs","sha256":"14c1fce14e24c984b2a275563a29b6326fb08367922b6e8d37ba38b9cb81aa2b"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/identity.rs","sha256":"186de11230c8b33375951c4368609f8976bf9795f171af3fd7fac26207a94361"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs","sha256":"0b4617d044f5254a5ab22f5a2578f91cc025206a8c1845be39c1c56dcdf7a5df"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/names.rs","sha256":"41bb23572d6002e23ee103d6fe70ecd68764861c6f2e48a1c53af998270a4afa"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs","sha256":"39fed883f4802e68d3b41a68fea0aba0737810996b33d13577de70faba004c29"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/store.rs","sha256":"fc60ee9c49b2f4f063c449b4c78100c5c4872779e94ca168f796603b380ef6e4"},{"path":"product/integrations/auths-custody/Cargo.toml","sha256":"1e14034185ad1ec24a977fd5f41d0abee219606245c046ce2a82287fadef448b"},{"path":"product/integrations/auths-custody/src/conformance.rs","sha256":"8ed1afd58f18fc6becc268908aa6419c9aa404c79da0197963eb2599df44acf6"},{"path":"product/integrations/auths-custody/src/key.rs","sha256":"70cbb0fd21b6f5652157845a22c35be2d0f6c05b3d138fc4b9bb6dbdc3d81c40"},{"path":"product/integrations/auths-custody/src/lib.rs","sha256":"8ee593c1f59b0fd2126bdda9138026f5bc531beb64d4489a99785842e7b98b43"},{"path":"product/operations/auths-operations/Cargo.toml","sha256":"73dde1e914ba5e1386f8d49c0d730423cc72ae77ec44c6554a6a75cc8e8922b1"},{"path":"product/operations/auths-operations/src/explanation.rs","sha256":"b4a39bcbd5712cb9e735ee7deeb281f3fa6af5ddca973735bf3d87dce427ef11"},{"path":"product/operations/auths-operations/src/lib.rs","sha256":"3f401a56555113b98f57bca172a2660eaecedf76247b83a3fdbb089c133a29cd"},{"path":"product/operations/auths-operations/src/render/json.rs","sha256":"2ae042639960afee123730e945d373bc5dda1d2b3af20ae16c939a7e99b9e418"},{"path":"product/operations/auths-operations/src/render/mod.rs","sha256":"b3b7f6fe473f49227ace5a68bfc3d8dc14b5db8dd9888fd9e207070337b1b8bf"},{"path":"product/operations/auths-operations/src/render/text.rs","sha256":"f216cf3bdb00e264523271b16e7059535ac6b1aabf271cebd7935af155e4bfec"},{"path":"product/policy/auths-bounded-policy/Cargo.toml","sha256":"babd5d200923137ead71d8c2528f847cea323ce98da942a1320b054436612c47"},{"path":"product/policy/auths-bounded-policy/src/arithmetic.rs","sha256":"75e43c5d4eab8d1f71c1daf53839f5f9fe45a400afc1f63a30c6f55ce3632627"},{"path":"product/policy/auths-bounded-policy/src/commitment.rs","sha256":"c5706f2d583454e1a7f570f7ada138d4d864bef0205dfae7c1296774f396bb3f"},{"path":"product/policy/auths-bounded-policy/src/eligibility.rs","sha256":"c9acdfb793074e687fc36efad506be27dbd99ffbf40387bc66c8de39ef238432"},{"path":"product/policy/auths-bounded-policy/src/identifier.rs","sha256":"0006a32bae9eb16c4178cf797df418d2b0a781f2bc6474b741dc1a908141831c"},{"path":"product/policy/auths-bounded-policy/src/kernel.rs","sha256":"99187c28b161ac70bee1afed60711f7f645adb4d1671a01863f9849b369811d5"},{"path":"product/policy/auths-bounded-policy/src/lib.rs","sha256":"76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c"},{"path":"product/policy/auths-bounded-policy/src/receipt.rs","sha256":"3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad"},{"path":"product/policy/auths-bounded-policy/src/registry.rs","sha256":"4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0"},{"path":"product/profiles/auths-profile-api/Cargo.toml","sha256":"7ae85761f58625b5d678f961fd052eebf3e000ef565c7312e3ac857763c0017f"},{"path":"product/profiles/auths-profile-api/src/lib.rs","sha256":"a194b82b20bf8aa864c2334ef6c6aec30b2154ded972862252d5dcefa488ab95"},{"path":"product/profiles/auths-profile-mcp/Cargo.toml","sha256":"db264fc25242f7b7e4133cbe5782545b3107b406c87168ae072683cfb59eac66"},{"path":"product/profiles/auths-profile-mcp/src/arguments.rs","sha256":"a5de696586d507e2aee4a49fee99ef1ef4c51a2e46603f8838f1af6d9009833f"},{"path":"product/profiles/auths-profile-mcp/src/lib.rs","sha256":"d0f8b733a09ef8408336cdebc8948d6a5861012ce6878598b11be7084dfd4280"},{"path":"product/profiles/auths-profile-mcp/src/session.rs","sha256":"166c281fa66333388e4760d6098dad02d3359e1d5de4b8f93312c014f97abb03"},{"path":"product/qualification/auths-recipe-qualification/Cargo.toml","sha256":"b7b15b30b9a3d96d4f089d514266d3a892de6608d30707aa44be31cca89ca9fe"},{"path":"product/qualification/auths-recipe-qualification/src/canonical.rs","sha256":"30a9b50777f0dcb4b606abfee2467d5a975d9f6ad941ab6c13ca3df5b359f667"},{"path":"product/qualification/auths-recipe-qualification/src/closure.rs","sha256":"0ad6aee9bd981e2863fa725f209ec84031db2ff12f4c7ac3aaf5120f0bb86039"},{"path":"product/qualification/auths-recipe-qualification/src/commissioning.rs","sha256":"66ea49f96887c4642139a48d259c270816e2267ee8cf6344a1340fe47afda9da"},{"path":"product/qualification/auths-recipe-qualification/src/commissioning/tests.rs","sha256":"5a226725c2ad7ce920d0bd62d427185e007f4d0949b0f0ec1260aa161d3114d0"},{"path":"product/qualification/auths-recipe-qualification/src/error.rs","sha256":"52d5cf720a1e4579008fdda90a3ac2c31f0b8db57985f121f65e54b4da2b7dd1"},{"path":"product/qualification/auths-recipe-qualification/src/evidence.rs","sha256":"ba45a7409d67a8af26ab811af306412014557477a101ab2a8eb0faf8f2bd4b91"},{"path":"product/qualification/auths-recipe-qualification/src/ids.rs","sha256":"e81a906d571497ab2da753e1532d4443706410e0b75fdd59a7d2d788c7aec403"},{"path":"product/qualification/auths-recipe-qualification/src/launch.rs","sha256":"41f2e2de90e1e7d6440a66eda3eb9bea8d5e0741bc232305a76a363ab5f813c1"},{"path":"product/qualification/auths-recipe-qualification/src/lib.rs","sha256":"7d26c5bfe9769daebf90c5c2280e0d75742e4cc70d0e608408e0665e3f516a2b"},{"path":"product/qualification/auths-recipe-qualification/src/model.rs","sha256":"3484eb0ec287b23d4682ade7b1b0f8d1335985b3fb180f06fc28716076957d5f"},{"path":"product/qualification/auths-recipe-qualification/src/release.rs","sha256":"ec478e53f70052e566aac7e15be2f9e1b1cd46837ac6990ae955fa864d311586"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/mod.rs","sha256":"fa23a962fd90331152eed5edbcdf271955f7aed79b8da1e065bfe69a20b487a9"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/schemas.rs","sha256":"c59feec2805621f341a90f81fc005e2c12f7a70f9d264fdeacccb2be4fe1c046"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/verification.rs","sha256":"6a6b5834c5dae10af1ba8939b2deae43b85db71544dc8f077ff63b7fe68ac8a8"},{"path":"product/qualification/auths-recipe-qualification/src/verify.rs","sha256":"2ec2784435d11e07295de77b2ee1b2c48b2fcf9609a00454c6e7374b621aed5c"},{"path":"product/receipts/auths-receipts/Cargo.toml","sha256":"6001fa1375899953aafcb07c23a6da0c8f57ea7ec08bb9c950b12a60a8cc6f0f"},{"path":"product/receipts/auths-receipts/src/disclosure.rs","sha256":"ba9ed439be0a320c8a01f5b6e9b51361c1a37e076947490d8e4a484ba6bb119c"},{"path":"product/receipts/auths-receipts/src/lib.rs","sha256":"547a57c4160256719cafb7d0ab972d9fc80b0da14fbbce4148c70c414070ff36"},{"path":"product/runtime/auths-connections/Cargo.toml","sha256":"babeb6e1dda3dfb66291713ce1e43dce5c349833d0b50ea4dccbf986030026b2"},{"path":"product/runtime/auths-connections/src/credential.rs","sha256":"82921413bb053f0f6c7931fbd4e6a86c8cc1d8c6b51debd9c2cef33a8d5b1c51"},{"path":"product/runtime/auths-connections/src/kernel.rs","sha256":"a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8"},{"path":"product/runtime/auths-connections/src/lib.rs","sha256":"79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22"},{"path":"product/runtime/auths-connections/src/model.rs","sha256":"de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77"},{"path":"product/runtime/auths-connections/src/registry.rs","sha256":"e57640e003e72ad3235c567c2bb944a262bd64e673f023b62ea091094cc7e946"},{"path":"product/runtime/auths-gateway-kernel/Cargo.toml","sha256":"34f864e67656af4ac7e5c7a347a23f01fc8ab31365b8e23c0ef474483b14a183"},{"path":"product/runtime/auths-gateway-kernel/src/construct.rs","sha256":"e9d65744bae273d65face4285e5d2da75c06a92ab48f7b8333d496604e31c63c"},{"path":"product/runtime/auths-gateway-kernel/src/lib.rs","sha256":"cfda6f8453426564c085475f183b6f790b438768a19668f1b65d33ba59dc8632"},{"path":"product/runtime/auths-gateway-kernel/src/order.rs","sha256":"e0045f877c4b7fe3860c291039853885064ddcdebba7c9b345ab65e81e646dda"},{"path":"product/runtime/auths-gateway-kernel/src/outcome.rs","sha256":"e9785b1afe70788c89b51b18655bcd5acff7b0c8e3d12fb79c6f05a202e67e6b"},{"path":"product/runtime/auths-gateway-kernel/src/ratio.rs","sha256":"7ace22264812e6fc1ef3a62afee402cf43494bb71ae0d3de219ad1b39d690bcb"},{"path":"product/runtime/auths-gateway-kernel/src/recovery.rs","sha256":"9f46dcd1685ab6e4d1ba04a3fc286a9f3afee8fb47829be1fbc670a7926a2dc6"},{"path":"product/runtime/auths-gateway-kernel/src/transition.rs","sha256":"cefb8f01d915880f6921f2501ff881ad94b9de61072c34d9cd19220992f97374"},{"path":"product/runtime/auths-gateway/Cargo.toml","sha256":"00b28be86921dcdc0ad90cce0c62c2961cafefe96ea6c2edf0e926c3d405ccad"},{"path":"product/runtime/auths-gateway/src/admin.rs","sha256":"0dee40a9fb67c5de10142fc37a7bbabdd8979fb0199fb26caf4bdb024e0a5a40"},{"path":"product/runtime/auths-gateway/src/app.rs","sha256":"6f80f63833ea0815bb44fbf3b0cc54624a08e9fb578b035819f2980dc04e8256"},{"path":"product/runtime/auths-gateway/src/audit.rs","sha256":"0edb2037eb7b5d6f13acfce85c54f62a82bf7fdd31bc7e626c4fec183cef61dd"},{"path":"product/runtime/auths-gateway/src/audit_tests.rs","sha256":"990969384a52d75bc2489d9d412a9e7dd814bca1c8f65c701d6205fae62a15d5"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway-harness.rs","sha256":"12b0c24d36b2e6a3be392d3c081a783b355fdd67dc5b54bacc0410e803116b8c"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway.rs","sha256":"24d4224f03c680ee1fc3f3441cca8707fe002ce2c78588e8c337f2f150ea2e44"},{"path":"product/runtime/auths-gateway/src/binding.rs","sha256":"663b0ce878319511aa7d05722ab4ab2fa9be18817884ffb2ee9f131ff1e382d1"},{"path":"product/runtime/auths-gateway/src/bounds.rs","sha256":"38251ad6f22f9d07ef9a219c79fa265ca36f1526eca5f147d7efa46b52ad609d"},{"path":"product/runtime/auths-gateway/src/bounds_aggregate_tests.rs","sha256":"ab34f227b7c8692ba1da88ccb32bb3687a66adf8353d8282fae905d4a88eb612"},{"path":"product/runtime/auths-gateway/src/bounds_tests.rs","sha256":"74136bc570da7b9338b5a1a1ed9d3fd892c55135160964f9d3ac0e2cf5741375"},{"path":"product/runtime/auths-gateway/src/commissioning_budget.rs","sha256":"fab29da3269438cc62330f3eab7b5bd4dc482b4db8af243aae47df5d3aa1deb8"},{"path":"product/runtime/auths-gateway/src/commissioning_budget/tests.rs","sha256":"ad182c391b70450582c6ca06e3dadc221409bb3cdbc3c7668dbfc7fbedf63505"},{"path":"product/runtime/auths-gateway/src/commissioning_floor.rs","sha256":"7fa6991c5ccd5ae1403be84b3da390323fab09f36e15ac01fd7a38ea350c6fdb"},{"path":"product/runtime/auths-gateway/src/commissioning_floor/tests.rs","sha256":"5f7868252dfccb787d26f63ea6d5c3701c72d52c0ff0bc656dd5895f8cbed551"},{"path":"product/runtime/auths-gateway/src/commissioning_session.rs","sha256":"24b48d5eaeaaa3c620e2dfc7ee1f9255fc4519a1eb404b8608cea7af6a910ee2"},{"path":"product/runtime/auths-gateway/src/commissioning_session/tests.rs","sha256":"531510bbd1bb0a7544c2bfd14f68b028f523bd4ed25dc4a68521fd0d8418a440"},{"path":"product/runtime/auths-gateway/src/connection.rs","sha256":"7b5d049c258a26ed1c93ecf860f51d051a8a65f9b93554af0b1ea93862398ec9"},{"path":"product/runtime/auths-gateway/src/credential_journal.rs","sha256":"7297fccaee5cd8622928e8e0a42bba50da7941970a6f682ecd300c41ee6509da"},{"path":"product/runtime/auths-gateway/src/echo_verify.rs","sha256":"6d453051665f823abd7354d5c50031d9524cf47d6092d2f09080ae814e3b9575"},{"path":"product/runtime/auths-gateway/src/engine.rs","sha256":"1abff20b98bc894c45bfc5c4414c81a99966d1ec95d924a5b0cd6f4c5626ca24"},{"path":"product/runtime/auths-gateway/src/execution_witness.rs","sha256":"e8b1a8e41d5e3fa309760067849d390ef065feeb46701a83391832645a2f000c"},{"path":"product/runtime/auths-gateway/src/fuzzing.rs","sha256":"ed3b0028487eb546a3b0a91d115aa8f18bcea324b61620bfe8e35a9e6ab18758"},{"path":"product/runtime/auths-gateway/src/generation_floor.rs","sha256":"fe1510ec96ce0f67e9a78edbfa94b33eb7df64c0ac4d0a67901124dcd0164777"},{"path":"product/runtime/auths-gateway/src/harness.rs","sha256":"c87e479f3eb281960f6c9c80d43c7560d7ccb654b0154ec823d3fcec4884ac05"},{"path":"product/runtime/auths-gateway/src/lib.rs","sha256":"fad95d031f88072dd024c78facf0bb0267562b1ac743ddd7219fce47e64024f0"},{"path":"product/runtime/auths-gateway/src/listener.rs","sha256":"aa08239bcbc1fcb55e8a212fbdf6a84f12985b0d436dcb51dc58b06e59e435f2"},{"path":"product/runtime/auths-gateway/src/observed_tests.rs","sha256":"a22be071695f89ca2578a4d82fd80d9cb82289213c9bdb8f0470f6b2dc3d9201"},{"path":"product/runtime/auths-gateway/src/observer.rs","sha256":"562ffcaea071c3856e0708dc2fe33516917e145d2438aabb75af0a2b6ba01046"},{"path":"product/runtime/auths-gateway/src/onboarding.rs","sha256":"0dfd7d67e7f02f18a28d1c86ca1b7751d7463f5efcdbe3825de0ad8cbccb3891"},{"path":"product/runtime/auths-gateway/src/operator.rs","sha256":"c3c36954a3e86723df035b47f43b85fc8ab3a6292983522b6258d5c6b4e6c4e4"},{"path":"product/runtime/auths-gateway/src/pending_vectors/attempts.rs","sha256":"47ef3c8cb1c5504d47ae9a0088705ce6715fe86bac1671a34a56fb38a64d0dd3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/bounds.rs","sha256":"e612217307e1da5b0eb5ee6582a7458bb064b8aa8a529fc6555b1b334127ab68"},{"path":"product/runtime/auths-gateway/src/pending_vectors/codes.rs","sha256":"e00670a5ef24eb856cc2c6dcda8e5a263842f55c76bb939c0c27bd9df37e5522"},{"path":"product/runtime/auths-gateway/src/pending_vectors/keys.rs","sha256":"f84c56f2ea9cb34b2b79c72d13fbf2c6585010ec1ed450af58a78c80c1ea1edd"},{"path":"product/runtime/auths-gateway/src/pending_vectors/mod.rs","sha256":"5de8340f0ef71a0b57a09e323fefe473d3160c6ae952b9ba46f714825fbacafc"},{"path":"product/runtime/auths-gateway/src/pending_vectors/outcomes.rs","sha256":"8ec07b9511b48913af36ac999d2aa0e82924289f6acb23ddaeb9f00f99815166"},{"path":"product/runtime/auths-gateway/src/pending_vectors/production.rs","sha256":"772d032e0a0d9c924fb6d6c188528db85a97e71c9e466ddc19eee277baf83614"},{"path":"product/runtime/auths-gateway/src/pending_vectors/recipes.rs","sha256":"51693208270231c25c3aef2a32151d5962114c71e86b88cb9df83181c7af83d9"},{"path":"product/runtime/auths-gateway/src/pre_entry.rs","sha256":"06ea78ca140468bfaba17d9ab04912ad68673954c3203c98fed28272ff2a00c0"},{"path":"product/runtime/auths-gateway/src/property_tests.rs","sha256":"939c081e2e154aaf10186754044bdd65608932c899b970a04a71d0afaa999a93"},{"path":"product/runtime/auths-gateway/src/qualification.rs","sha256":"c597c83de2b94f0374ae54e40a8b57c2a64ec6e254704dca32185f448a908aca"},{"path":"product/runtime/auths-gateway/src/qualification_simulation.rs","sha256":"4ee7cadfb5f46a92713c80f3e55f499cb074d04d8b21ea89d57762af38642bfa"},{"path":"product/runtime/auths-gateway/src/qualification_tests.rs","sha256":"a9178a2e58eea459d5e5dafc53a3999ea7c84dbbffefe6e5eb1f3d098827f028"},{"path":"product/runtime/auths-gateway/src/quorum_tests.rs","sha256":"a78380b019104d688c11a4410082c7e08ded3106aab099954c4f8a1b4ae0fd89"},{"path":"product/runtime/auths-gateway/src/readiness.rs","sha256":"911c3f11892f94641574375e2da4c671c802738f71082f12c39832331052d43d"},{"path":"product/runtime/auths-gateway/src/recipe.rs","sha256":"fecf9af67e7afc48d080e9f8f55f8ce28e49d0e08988717a27908bbda461d6b6"},{"path":"product/runtime/auths-gateway/src/recipe/lower.rs","sha256":"8088b8751ed831dbb48247af953c6290ac95e2a438ccd5bd65eff54be06a1fd1"},{"path":"product/runtime/auths-gateway/src/recipe/review.rs","sha256":"c3eb7d9fdd98dacf52750b14b67ad7b7faaecbbdeafff1e0b049f67d0a2d0139"},{"path":"product/runtime/auths-gateway/src/recipe/runtime.rs","sha256":"c286f0d15f974402822c0810d8e97f98411dc1c557755cc23e540d85e2bb42d9"},{"path":"product/runtime/auths-gateway/src/recipe/source.rs","sha256":"1af50298fb1461e1b24cbdf560d43124d6b1c4c529586c911b1c4797214a69ff"},{"path":"product/runtime/auths-gateway/src/recipe/tests.rs","sha256":"aac551a2481bbc60864c64079bc667dcb232e45a0f41a04073ed84ab5dbe1fce"},{"path":"product/runtime/auths-gateway/src/recipe/validate.rs","sha256":"3711b17605cb7b0d639bc1b180449231f5882a306cab20e2c7782155cc63b0d4"},{"path":"product/runtime/auths-gateway/src/scenario_tests.rs","sha256":"025b53473b3af6900e03bc2fee91aa63ed26a8778bc8c8296fe08f5540794c39"},{"path":"product/runtime/auths-gateway/src/separation.rs","sha256":"be9306848ca5d801767cf6aa14247c8618312ef0e202f00ce0c24c4844491061"},{"path":"product/runtime/auths-gateway/src/simulation_attestation.rs","sha256":"88705e5d45415f760f1e3c3a065c35c48f4f4065bf7b3feb7882246983814d6f"},{"path":"product/runtime/auths-gateway/src/store.rs","sha256":"884bcad4d70d53e12eae9c8517f6ecd0643068ee0be0370015119d04d6cc2516"},{"path":"product/runtime/auths-gateway/src/store_testkit.rs","sha256":"88d82fee42f1b8ef521e8deef0216e938ebeaad822eb2f5020e70b89d145ea70"},{"path":"product/runtime/auths-gateway/src/submit.rs","sha256":"fe2eacb5ad8152eeecbd232c47a356fc72db0098e34fda99532bdf6ef0cf895c"},{"path":"product/runtime/auths-gateway/src/support.rs","sha256":"9fd979029793a22b15d9776a7fc172476fd7c126a80d4080c65d720845becbcb"},{"path":"product/runtime/auths-gateway/src/transport.rs","sha256":"978fc9fb34a33b3db265b5d1c3ce11696a5b9f08529e46dd2a1e7bb62afb9220"},{"path":"product/runtime/auths-kernel-runtime/Cargo.toml","sha256":"926bcd0053e5edd703be8f0027ad009e2982db013c8174c1366edbf38b48087d"},{"path":"product/runtime/auths-kernel-runtime/src/lib.rs","sha256":"7108faae9ca4bc32dc093ddaf885ac8f74f3c9b8d317b7c7d0ed00d1d0ab5972"},{"path":"product/runtime/auths-lifecycle/Cargo.toml","sha256":"c5053c705f8d5554b44e432fe75287a2faf11d644e5a2552e45ad6cd94176af5"},{"path":"product/runtime/auths-lifecycle/src/codec.rs","sha256":"51c4b746749150e8bfcd8ff972b3f6c1ef40bec15583448ec1b471d9ad737dc0"},{"path":"product/runtime/auths-lifecycle/src/digest.rs","sha256":"55282cd7d8aba37713c2dcb5357c9877819edb72a30eadefb860d28d7d3a3eb7"},{"path":"product/runtime/auths-lifecycle/src/identifier.rs","sha256":"31620e8c16de68d3d2d3b84d6353c1a5b9d4151d8247f91fa389b906a8e660f1"},{"path":"product/runtime/auths-lifecycle/src/kernel.rs","sha256":"2abb8c094b36d35b364e74d78091d14c5d6f3d1eb6552cca3b5538dbd017ce23"},{"path":"product/runtime/auths-lifecycle/src/lib.rs","sha256":"afe5a345cd309b5a4f08ffba3170a6d7f16ff914892b3f2006d5208ed24ec736"},{"path":"product/runtime/auths-lifecycle/src/model.rs","sha256":"1af12bbeeeaa65ec02ddcebd7d2c8c92ec1e339fa40ae85b45ab9b01a722a4fa"},{"path":"product/runtime/auths-lifecycle/src/operation.rs","sha256":"78e6d05fcf5d7ea4f148032a3fa26fdfcab77eb346019effe927b08e0d64d732"},{"path":"product/runtime/auths-lifecycle/src/registry.rs","sha256":"53495fe6f7a77422593a41623e28716f1c140dcc1e00f87f6b0ffbfb93a5ef90"},{"path":"product/runtime/auths-lifecycle/src/sealed.rs","sha256":"2e0c03b5813c926c159598bb7890d1523825edbe57cd687d42a5dfb3374a0c19"},{"path":"product/runtime/auths-lifecycle/src/test_support.rs","sha256":"221d9a5c5ef8e1f9f8fd66927484eaf813571d0568470278ecd8fa08a5eec8cd"},{"path":"product/runtime/auths-lifecycle/src/transition.rs","sha256":"011805a28efdd541f44ccea54dd0e34a1e58f4004447ee58013703b4fb6b2822"},{"path":"product/runtime/auths-runtime/Cargo.toml","sha256":"dd29d80a8b4bb56c869f036a6c9998f6e6d1c0383ac5dc03fa42b24abe2a7ff7"},{"path":"product/runtime/auths-runtime/src/lib.rs","sha256":"132ca03d58c14905d3a822a4972f42a22a5ad33a45f2ba9ca44f3a57d810b4b0"},{"path":"product/runtime/auths-runtime/src/production.rs","sha256":"fd4eff4270c571c10fcff6cf27df28961ebf074de8a1a028f500fda1ca376820"},{"path":"product/sdk/auths-approval-quorum/Cargo.toml","sha256":"df904971fca87a24194c5816738a331588fe8f164acb5d70839a35dca5f57114"},{"path":"product/sdk/auths-approval-quorum/src/lib.rs","sha256":"72e4086088a1c0912e4e1a9e980f26a5c280bf5ab16ea39c9f0f58d5096ac2ce"},{"path":"product/sdk/auths-approval-quorum/src/remote.rs","sha256":"9fa029c7c63003adf260f8aec55160c545681c60c1bace0d934e7525862aac7b"},{"path":"product/sdk/auths-approval-quorum/src/remote_tests.rs","sha256":"8a09ce17cfee82a035a74edd535f3ebeb3db0e078784740d3997b17dbdb10197"},{"path":"product/sdk/auths-approval-quorum/src/tests.rs","sha256":"0acbf12be3e497dcc6c2d8f29c9af3b1a7ed8e11b75f6399570d4f217a785060"},{"path":"product/stores/auths-stores/Cargo.toml","sha256":"a32c4b76d17b264be5d40d24497ff237e1ed87822e8bab86229b3db93106dbe3"},{"path":"product/stores/auths-stores/src/gateway_attempt.rs","sha256":"218841602d3d9b23b44625f50e5b54cf275ccedc2d5c89f02d2482b8524472af"},{"path":"product/stores/auths-stores/src/lib.rs","sha256":"e721262edf8a9ab5568ddc27639176312d4a366203b5f73e2d7c11fde2c554e9"},{"path":"product/stores/auths-stores/src/lifecycle.rs","sha256":"3f2cecfda13fdcd7c4a944518646bcc8abd1237f900c0332d5822281f8f9f1cd"}],"schema":"auths.gateway-semantic-closure/1"} \ No newline at end of file +{"files":[{"path":"Cargo.lock","sha256":"0e75e2fdef44e79e57797ac6661295ae58ddb8de4a1990a6fd22ce6c54f78604"},{"path":"Cargo.toml","sha256":"6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24"},{"path":"core/adapters/auths-did-keri/Cargo.toml","sha256":"86ba3e3f9a0a70d970568bfb3113b7ba7bbdd81c3eebbb52743dd574a0c0ecaa"},{"path":"core/adapters/auths-did-keri/src/lib.rs","sha256":"a75674842f8a7142004369ccd206ab43e476459293f0ff4bed4d4e659031b3e3"},{"path":"core/adapters/auths-did-key/Cargo.toml","sha256":"d5a3ae07ecde83f91eed4c3785051dd0f44eab6c891754f3309b6b40596707d7"},{"path":"core/adapters/auths-did-key/src/lib.rs","sha256":"b76a3f4528a725df53cfa9242e6e414e1d26caa48468aaed497e28b121f4497c"},{"path":"core/adapters/auths-raw-key/Cargo.toml","sha256":"f49616bc18c19e6aaa7e6a02ccebcdb9f5c1422c1278ef9869e0dbf22ceda7be"},{"path":"core/adapters/auths-raw-key/src/lib.rs","sha256":"45eec1b295dac3bed65cd79c942870b926b06b3f5d38eaebaeb6140ac69315fa"},{"path":"core/crates/auths-algebra-kernel/Cargo.toml","sha256":"0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba"},{"path":"core/crates/auths-algebra-kernel/src/generated.rs","sha256":"ae4bcbef42a408c7ffa0c6a74a42f7de177a6f14479e51d205acf830bda05960"},{"path":"core/crates/auths-algebra-kernel/src/lib.rs","sha256":"6654667eeb9b353d6648954c9fd2e8838462a82ce6b2803eb49e1366892c68c6"},{"path":"core/crates/auths-assurance/Cargo.toml","sha256":"afcb12a97ddd09d7a264b9ecd3fcaefc865ff2c9b4539ee85b00883420ba333a"},{"path":"core/crates/auths-assurance/src/lib.rs","sha256":"0fb2ec844d674b25a9e20b1601452c89c2454901fa506adfa9bb38ef9a7fa213"},{"path":"core/crates/auths-author/Cargo.toml","sha256":"1e6f0e3bc079ddb558decf0db26b291c6e72fc47327b6df1b7650d41689b215f"},{"path":"core/crates/auths-author/src/lib.rs","sha256":"e14475f2f49715a1869d5fa6b11ff1fbb72497e39097e09f833b0bae7e5b3f2b"},{"path":"core/crates/auths-author/src/observations.rs","sha256":"dda7d6bfa6f4bd7e95a480ca283c2c0e996f69c5c15cb0c7197af328131a7066"},{"path":"core/crates/auths-authority/Cargo.toml","sha256":"4f68212938029f79ebd857b4f3038494eb85d0163d49f07e51376715cf959815"},{"path":"core/crates/auths-authority/src/lib.rs","sha256":"da88d5194de4e17449e69972c0fb042afa3c39798a8f570f30771e77c384f1eb"},{"path":"core/crates/auths-codec/Cargo.toml","sha256":"e20e51826e17814effd9d8925d18d5fbdd6c0d37bf50231e743ec2611314722c"},{"path":"core/crates/auths-codec/src/approval.rs","sha256":"fbff43bf4d57f69f8b7738a8647751cde75c5a932dee65d924a1fe9c7202f91f"},{"path":"core/crates/auths-codec/src/bounded_policy.rs","sha256":"d21f6728be2d8a04b6d94921f2b683f7e61cbb42e0ac6866f1c88a49caa534c3"},{"path":"core/crates/auths-codec/src/decode.rs","sha256":"ba2999584cdf53b1b517ecb9c7ea50d39efee17c666a9a38e2ad1ac94379f778"},{"path":"core/crates/auths-codec/src/encode.rs","sha256":"8491192053e2e15d62b4d2a491de22405b7487ead69ab6f6bca40669ce7ca5f7"},{"path":"core/crates/auths-codec/src/error.rs","sha256":"fecb0737c16deb42d859f1dc7727c698438d9ac12064fd99e0024629642c390c"},{"path":"core/crates/auths-codec/src/hash.rs","sha256":"f88e111f1dbb2cef6b7b5e9c948cb45ff92e366710c8a5f5c636138aa748479e"},{"path":"core/crates/auths-codec/src/lib.rs","sha256":"3b0e5c94c6f34f750b88a9333e1d5c8145746d845d3a23e0d2f61807cf592ea7"},{"path":"core/crates/auths-codec/src/observation.rs","sha256":"38328b0c71ff97a4196eeade8b4faa889527ff1f80bb168468bcd49082a3987e"},{"path":"core/crates/auths-composition/Cargo.toml","sha256":"331e13025eb82588b5269ed3975929eb41c823d588c49e4c296273d85c6fe80e"},{"path":"core/crates/auths-composition/src/lib.rs","sha256":"e42e3b0b6a9985b73c533aeb23799c638979aa27a9ce7d0f10a8d60340570fb1"},{"path":"core/crates/auths-model/Cargo.toml","sha256":"565c15302b0cc9270db1e28efa3862804846850ba933cc17aea8abcec4a65987"},{"path":"core/crates/auths-model/src/approval.rs","sha256":"54cf44a9ef747ec21546a4086aecfb130bc7803b0d646430e6082df51e6e305f"},{"path":"core/crates/auths-model/src/bounded.rs","sha256":"f90496abc0a06c028b4d850af6ddab7d850bfafeaa3d042f1b1246a41d8bbbc9"},{"path":"core/crates/auths-model/src/bounded_policy.rs","sha256":"306a8f049cc7cfc7635fe0e4de47eb7813eed63d3c14c3be2b51586aa4eea450"},{"path":"core/crates/auths-model/src/lib.rs","sha256":"e7cfe6bb9574c6b016aa63e70658c31e0b90903ec6479a49f4a2ceb64f5bad97"},{"path":"core/crates/auths-model/src/observation.rs","sha256":"b3ed3e3cc090afca2896a7d3de7988afccc1ee1ea0ebd91b51a8bc0f20ad8dbb"},{"path":"core/crates/auths-multikey/Cargo.toml","sha256":"858756c1197befcada06134742bffe8d58cf674cadd6c046bf710570e96efaf2"},{"path":"core/crates/auths-multikey/src/lib.rs","sha256":"f5177fffb11e40eeaaa665ba886c541fc1f24d5eacdd6983fb03dc20148733f0"},{"path":"core/crates/auths-ports/Cargo.toml","sha256":"596a9b0f5af3717c16a6d13f7054d8a106bcd9f01f5f72c2235dd2afcf0ab16c"},{"path":"core/crates/auths-ports/src/binding.rs","sha256":"a16c012d40aa4249e3ec54372b9611006d0bfe8c7dc3c741911c2194ad17736d"},{"path":"core/crates/auths-ports/src/diagnostics.rs","sha256":"aa596572503b5a65a918bb2ff38281c144ff53821ee914e9325c852828d852df"},{"path":"core/crates/auths-ports/src/lib.rs","sha256":"8da1debf86f9532df0660155d04298beb1ba3a1204508f8586e2e67cd2fb3449"},{"path":"core/crates/auths-ports/src/path.rs","sha256":"b68fc547b4e4d97a60cbbc1cc1939fc6b34a8233b81f840bd396914a707e3ea1"},{"path":"core/crates/auths-raw-key-core/Cargo.toml","sha256":"98c0bc8527a537512e43a74dd6ba9658c6f0cdc16610cf938e3f9b43785d836d"},{"path":"core/crates/auths-raw-key-core/src/lib.rs","sha256":"98c0500c41697aae28708ad0bf970b9a97583d96a3d2c18d23e7fa351e0f7d12"},{"path":"core/crates/auths-registries/Cargo.toml","sha256":"590e49e58b0622d9d6274fea46796dcdb07dec9550eff295cce6a6427ffa51e2"},{"path":"core/crates/auths-registries/src/lib.rs","sha256":"450d3886d85ee333b7e046317fb5b47cde62483d5f3e41d46265e2caf4c373ec"},{"path":"core/crates/auths-registries/src/template.rs","sha256":"1224039dd2b3ce6fa8357613d8cafbae40400493da7176da202b9ade62fa05e4"},{"path":"core/crates/auths-signature-core/Cargo.toml","sha256":"6bee2230eb30af1be0bd5c2d57bd3e1903497a70028d47290d4ac6e9e0e8bca0"},{"path":"core/crates/auths-signature-core/src/lib.rs","sha256":"6e3f9311ded5e49ea50d445eb21e6d8fa12442aa4362a73e0cb6fda15b7cd865"},{"path":"core/crates/auths-signature/Cargo.toml","sha256":"7f7b5682466ba439d8c59579022cb61068cad9fb4bd2d73e1cc21327c902b450"},{"path":"core/crates/auths-signature/src/lib.rs","sha256":"b3d9ac4cc3ba0797b9e1c09f2d6ac05089b25dac4e285a5af28c0165b33d925b"},{"path":"core/crates/auths-verifier/Cargo.toml","sha256":"c43358e06a33324b41a8b93e5cc7279c55f7d21f1f6cfaa539a3fc7b4c27a38f"},{"path":"core/crates/auths-verifier/src/approval.rs","sha256":"c3cae6a49e169051eb555bb092b1069a4d422516d6a2114623a89e5f31ff923f"},{"path":"core/crates/auths-verifier/src/causal.rs","sha256":"9635230f33b13a263573d319ac8a1976addbcc07677514a43e3c7bf28dc04587"},{"path":"core/crates/auths-verifier/src/lib.rs","sha256":"f22dec38dfa47ced8da4f605390da8453273bee1da010f57fd1fdfcb10e0b389"},{"path":"core/crates/auths-verifier/src/observation.rs","sha256":"0bb07f06a0f9524c88427df1c972b1de8ba038a9eeeb15d3134c25125ae84b1e"},{"path":"core/crates/auths-verifier/src/trace.rs","sha256":"2213d72023a1d9e0413a2cf2c51c3dad9e04775d86033a0caaa9d29a8f0036f8"},{"path":"exchange/crates/auths-proof-exchange-model/Cargo.toml","sha256":"34b2db64f93a288e942b5a3918d28cdcbef906e0dc9074ce848018d3d5f7a1fa"},{"path":"exchange/crates/auths-proof-exchange-model/src/lib.rs","sha256":"49fac5aff2339d3a57c41cb8bb2a82852538e8f77ecc4b157c88e264ff31fb55"},{"path":"exchange/crates/auths-proof-exchange-port/Cargo.toml","sha256":"7ff660f1b7579dc570c791090aeb450404fbbf44c92781e289f5ccdde746d739"},{"path":"exchange/crates/auths-proof-exchange-port/src/lib.rs","sha256":"b408fb40c6432edc1facb3d8b3e9433a033f8dc73fe2e0ba5a88c972ca675021"},{"path":"product/config/auths-config/Cargo.toml","sha256":"e4b568ab9f6d84f7d7e6d66443fe825f360db9c27bc7c31d6ddc0647ba3ab304"},{"path":"product/config/auths-config/src/lib.rs","sha256":"fecf00ea65cef9018fda9af2063326d7065b869266d0d9e73a4f06816f1102cc"},{"path":"product/errors/auths-errors/Cargo.toml","sha256":"3b3a199b6460ba75bda84475bb5accd35e1485448a3981038db85bf4772dd350"},{"path":"product/errors/auths-errors/src/lib.rs","sha256":"7feeb9069fa4003f94f1f07c1c94619cf1c883e0dbaaf2187f04d0f742264bdd"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/Cargo.toml","sha256":"716f1f2a117d6d69d8effe9ee9057e24ba3502f20af6a602b06facb638cdabed"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/api.rs","sha256":"9ea61dd7ddd93282b073b98e453e6b75b26dc49689c04e9782435d06a3a09e48"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/clock.rs","sha256":"73f0a6e0f5903883329fa6683f5888288f759512ac69e5c87efd2b6b87f7d79f"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/http.rs","sha256":"14c1fce14e24c984b2a275563a29b6326fb08367922b6e8d37ba38b9cb81aa2b"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/identity.rs","sha256":"186de11230c8b33375951c4368609f8976bf9795f171af3fd7fac26207a94361"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs","sha256":"0b4617d044f5254a5ab22f5a2578f91cc025206a8c1845be39c1c56dcdf7a5df"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/names.rs","sha256":"41bb23572d6002e23ee103d6fe70ecd68764861c6f2e48a1c53af998270a4afa"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs","sha256":"39fed883f4802e68d3b41a68fea0aba0737810996b33d13577de70faba004c29"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/store.rs","sha256":"fc60ee9c49b2f4f063c449b4c78100c5c4872779e94ca168f796603b380ef6e4"},{"path":"product/integrations/auths-custody/Cargo.toml","sha256":"1e14034185ad1ec24a977fd5f41d0abee219606245c046ce2a82287fadef448b"},{"path":"product/integrations/auths-custody/src/conformance.rs","sha256":"8ed1afd58f18fc6becc268908aa6419c9aa404c79da0197963eb2599df44acf6"},{"path":"product/integrations/auths-custody/src/key.rs","sha256":"70cbb0fd21b6f5652157845a22c35be2d0f6c05b3d138fc4b9bb6dbdc3d81c40"},{"path":"product/integrations/auths-custody/src/lib.rs","sha256":"8ee593c1f59b0fd2126bdda9138026f5bc531beb64d4489a99785842e7b98b43"},{"path":"product/operations/auths-operations/Cargo.toml","sha256":"73dde1e914ba5e1386f8d49c0d730423cc72ae77ec44c6554a6a75cc8e8922b1"},{"path":"product/operations/auths-operations/src/explanation.rs","sha256":"b4a39bcbd5712cb9e735ee7deeb281f3fa6af5ddca973735bf3d87dce427ef11"},{"path":"product/operations/auths-operations/src/lib.rs","sha256":"3f401a56555113b98f57bca172a2660eaecedf76247b83a3fdbb089c133a29cd"},{"path":"product/operations/auths-operations/src/render/json.rs","sha256":"2ae042639960afee123730e945d373bc5dda1d2b3af20ae16c939a7e99b9e418"},{"path":"product/operations/auths-operations/src/render/mod.rs","sha256":"b3b7f6fe473f49227ace5a68bfc3d8dc14b5db8dd9888fd9e207070337b1b8bf"},{"path":"product/operations/auths-operations/src/render/text.rs","sha256":"f216cf3bdb00e264523271b16e7059535ac6b1aabf271cebd7935af155e4bfec"},{"path":"product/policy/auths-bounded-policy/Cargo.toml","sha256":"babd5d200923137ead71d8c2528f847cea323ce98da942a1320b054436612c47"},{"path":"product/policy/auths-bounded-policy/src/arithmetic.rs","sha256":"75e43c5d4eab8d1f71c1daf53839f5f9fe45a400afc1f63a30c6f55ce3632627"},{"path":"product/policy/auths-bounded-policy/src/commitment.rs","sha256":"c5706f2d583454e1a7f570f7ada138d4d864bef0205dfae7c1296774f396bb3f"},{"path":"product/policy/auths-bounded-policy/src/eligibility.rs","sha256":"c9acdfb793074e687fc36efad506be27dbd99ffbf40387bc66c8de39ef238432"},{"path":"product/policy/auths-bounded-policy/src/identifier.rs","sha256":"0006a32bae9eb16c4178cf797df418d2b0a781f2bc6474b741dc1a908141831c"},{"path":"product/policy/auths-bounded-policy/src/kernel.rs","sha256":"99187c28b161ac70bee1afed60711f7f645adb4d1671a01863f9849b369811d5"},{"path":"product/policy/auths-bounded-policy/src/lib.rs","sha256":"76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c"},{"path":"product/policy/auths-bounded-policy/src/receipt.rs","sha256":"3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad"},{"path":"product/policy/auths-bounded-policy/src/registry.rs","sha256":"4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0"},{"path":"product/profiles/auths-profile-api/Cargo.toml","sha256":"7ae85761f58625b5d678f961fd052eebf3e000ef565c7312e3ac857763c0017f"},{"path":"product/profiles/auths-profile-api/src/lib.rs","sha256":"a194b82b20bf8aa864c2334ef6c6aec30b2154ded972862252d5dcefa488ab95"},{"path":"product/profiles/auths-profile-mcp/Cargo.toml","sha256":"db264fc25242f7b7e4133cbe5782545b3107b406c87168ae072683cfb59eac66"},{"path":"product/profiles/auths-profile-mcp/src/arguments.rs","sha256":"a5de696586d507e2aee4a49fee99ef1ef4c51a2e46603f8838f1af6d9009833f"},{"path":"product/profiles/auths-profile-mcp/src/lib.rs","sha256":"d0f8b733a09ef8408336cdebc8948d6a5861012ce6878598b11be7084dfd4280"},{"path":"product/profiles/auths-profile-mcp/src/session.rs","sha256":"166c281fa66333388e4760d6098dad02d3359e1d5de4b8f93312c014f97abb03"},{"path":"product/qualification/auths-recipe-qualification/Cargo.toml","sha256":"b7b15b30b9a3d96d4f089d514266d3a892de6608d30707aa44be31cca89ca9fe"},{"path":"product/qualification/auths-recipe-qualification/src/canonical.rs","sha256":"30a9b50777f0dcb4b606abfee2467d5a975d9f6ad941ab6c13ca3df5b359f667"},{"path":"product/qualification/auths-recipe-qualification/src/closure.rs","sha256":"0ad6aee9bd981e2863fa725f209ec84031db2ff12f4c7ac3aaf5120f0bb86039"},{"path":"product/qualification/auths-recipe-qualification/src/commissioning.rs","sha256":"db135c55e4e3079a73253ebae275536523eb36b545d1c152b4d7dce3c6b76828"},{"path":"product/qualification/auths-recipe-qualification/src/commissioning/tests.rs","sha256":"4dde3736d206099b1bea4c14e0092c6c1287d1af9065958777d7c54331dd8686"},{"path":"product/qualification/auths-recipe-qualification/src/error.rs","sha256":"52d5cf720a1e4579008fdda90a3ac2c31f0b8db57985f121f65e54b4da2b7dd1"},{"path":"product/qualification/auths-recipe-qualification/src/evidence.rs","sha256":"ba45a7409d67a8af26ab811af306412014557477a101ab2a8eb0faf8f2bd4b91"},{"path":"product/qualification/auths-recipe-qualification/src/ids.rs","sha256":"e81a906d571497ab2da753e1532d4443706410e0b75fdd59a7d2d788c7aec403"},{"path":"product/qualification/auths-recipe-qualification/src/launch.rs","sha256":"41f2e2de90e1e7d6440a66eda3eb9bea8d5e0741bc232305a76a363ab5f813c1"},{"path":"product/qualification/auths-recipe-qualification/src/lib.rs","sha256":"0e24b0f81191df0d078c7f4d73ced784ba9472372bfcdff3c7d0e2fb1687b323"},{"path":"product/qualification/auths-recipe-qualification/src/model.rs","sha256":"3484eb0ec287b23d4682ade7b1b0f8d1335985b3fb180f06fc28716076957d5f"},{"path":"product/qualification/auths-recipe-qualification/src/release.rs","sha256":"ec478e53f70052e566aac7e15be2f9e1b1cd46837ac6990ae955fa864d311586"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/mod.rs","sha256":"fa23a962fd90331152eed5edbcdf271955f7aed79b8da1e065bfe69a20b487a9"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/schemas.rs","sha256":"c59feec2805621f341a90f81fc005e2c12f7a70f9d264fdeacccb2be4fe1c046"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/verification.rs","sha256":"6a6b5834c5dae10af1ba8939b2deae43b85db71544dc8f077ff63b7fe68ac8a8"},{"path":"product/qualification/auths-recipe-qualification/src/verify.rs","sha256":"2ec2784435d11e07295de77b2ee1b2c48b2fcf9609a00454c6e7374b621aed5c"},{"path":"product/receipts/auths-receipts/Cargo.toml","sha256":"6001fa1375899953aafcb07c23a6da0c8f57ea7ec08bb9c950b12a60a8cc6f0f"},{"path":"product/receipts/auths-receipts/src/disclosure.rs","sha256":"ba9ed439be0a320c8a01f5b6e9b51361c1a37e076947490d8e4a484ba6bb119c"},{"path":"product/receipts/auths-receipts/src/lib.rs","sha256":"547a57c4160256719cafb7d0ab972d9fc80b0da14fbbce4148c70c414070ff36"},{"path":"product/runtime/auths-connections/Cargo.toml","sha256":"babeb6e1dda3dfb66291713ce1e43dce5c349833d0b50ea4dccbf986030026b2"},{"path":"product/runtime/auths-connections/src/credential.rs","sha256":"82921413bb053f0f6c7931fbd4e6a86c8cc1d8c6b51debd9c2cef33a8d5b1c51"},{"path":"product/runtime/auths-connections/src/kernel.rs","sha256":"a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8"},{"path":"product/runtime/auths-connections/src/lib.rs","sha256":"79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22"},{"path":"product/runtime/auths-connections/src/model.rs","sha256":"de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77"},{"path":"product/runtime/auths-connections/src/registry.rs","sha256":"e57640e003e72ad3235c567c2bb944a262bd64e673f023b62ea091094cc7e946"},{"path":"product/runtime/auths-gateway-kernel/Cargo.toml","sha256":"34f864e67656af4ac7e5c7a347a23f01fc8ab31365b8e23c0ef474483b14a183"},{"path":"product/runtime/auths-gateway-kernel/src/construct.rs","sha256":"e9d65744bae273d65face4285e5d2da75c06a92ab48f7b8333d496604e31c63c"},{"path":"product/runtime/auths-gateway-kernel/src/lib.rs","sha256":"cfda6f8453426564c085475f183b6f790b438768a19668f1b65d33ba59dc8632"},{"path":"product/runtime/auths-gateway-kernel/src/order.rs","sha256":"e0045f877c4b7fe3860c291039853885064ddcdebba7c9b345ab65e81e646dda"},{"path":"product/runtime/auths-gateway-kernel/src/outcome.rs","sha256":"e9785b1afe70788c89b51b18655bcd5acff7b0c8e3d12fb79c6f05a202e67e6b"},{"path":"product/runtime/auths-gateway-kernel/src/ratio.rs","sha256":"7ace22264812e6fc1ef3a62afee402cf43494bb71ae0d3de219ad1b39d690bcb"},{"path":"product/runtime/auths-gateway-kernel/src/recovery.rs","sha256":"9f46dcd1685ab6e4d1ba04a3fc286a9f3afee8fb47829be1fbc670a7926a2dc6"},{"path":"product/runtime/auths-gateway-kernel/src/transition.rs","sha256":"cefb8f01d915880f6921f2501ff881ad94b9de61072c34d9cd19220992f97374"},{"path":"product/runtime/auths-gateway/Cargo.toml","sha256":"00b28be86921dcdc0ad90cce0c62c2961cafefe96ea6c2edf0e926c3d405ccad"},{"path":"product/runtime/auths-gateway/src/admin.rs","sha256":"0dee40a9fb67c5de10142fc37a7bbabdd8979fb0199fb26caf4bdb024e0a5a40"},{"path":"product/runtime/auths-gateway/src/app.rs","sha256":"6f80f63833ea0815bb44fbf3b0cc54624a08e9fb578b035819f2980dc04e8256"},{"path":"product/runtime/auths-gateway/src/audit.rs","sha256":"0edb2037eb7b5d6f13acfce85c54f62a82bf7fdd31bc7e626c4fec183cef61dd"},{"path":"product/runtime/auths-gateway/src/audit_tests.rs","sha256":"990969384a52d75bc2489d9d412a9e7dd814bca1c8f65c701d6205fae62a15d5"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway-harness.rs","sha256":"12b0c24d36b2e6a3be392d3c081a783b355fdd67dc5b54bacc0410e803116b8c"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway.rs","sha256":"24d4224f03c680ee1fc3f3441cca8707fe002ce2c78588e8c337f2f150ea2e44"},{"path":"product/runtime/auths-gateway/src/binding.rs","sha256":"663b0ce878319511aa7d05722ab4ab2fa9be18817884ffb2ee9f131ff1e382d1"},{"path":"product/runtime/auths-gateway/src/bounds.rs","sha256":"38251ad6f22f9d07ef9a219c79fa265ca36f1526eca5f147d7efa46b52ad609d"},{"path":"product/runtime/auths-gateway/src/bounds_aggregate_tests.rs","sha256":"ab34f227b7c8692ba1da88ccb32bb3687a66adf8353d8282fae905d4a88eb612"},{"path":"product/runtime/auths-gateway/src/bounds_tests.rs","sha256":"74136bc570da7b9338b5a1a1ed9d3fd892c55135160964f9d3ac0e2cf5741375"},{"path":"product/runtime/auths-gateway/src/commissioning_budget.rs","sha256":"fab29da3269438cc62330f3eab7b5bd4dc482b4db8af243aae47df5d3aa1deb8"},{"path":"product/runtime/auths-gateway/src/commissioning_budget/tests.rs","sha256":"da104a1643c37515deec6397bca6db2054f2c9158ec3d230a1b1ec9c7d0f659f"},{"path":"product/runtime/auths-gateway/src/commissioning_floor.rs","sha256":"7fa6991c5ccd5ae1403be84b3da390323fab09f36e15ac01fd7a38ea350c6fdb"},{"path":"product/runtime/auths-gateway/src/commissioning_floor/tests.rs","sha256":"6b663d6e556adc0b455b81845bc4394d82c6c4de0c5f43e1310f3ddc6e4e40f7"},{"path":"product/runtime/auths-gateway/src/commissioning_session.rs","sha256":"24b48d5eaeaaa3c620e2dfc7ee1f9255fc4519a1eb404b8608cea7af6a910ee2"},{"path":"product/runtime/auths-gateway/src/commissioning_session/tests.rs","sha256":"703d8970d0b3c1d01516dea784ff690e33788861bf1ab34fbb1432cf0d21117a"},{"path":"product/runtime/auths-gateway/src/connection.rs","sha256":"7b5d049c258a26ed1c93ecf860f51d051a8a65f9b93554af0b1ea93862398ec9"},{"path":"product/runtime/auths-gateway/src/credential_journal.rs","sha256":"7297fccaee5cd8622928e8e0a42bba50da7941970a6f682ecd300c41ee6509da"},{"path":"product/runtime/auths-gateway/src/echo_verify.rs","sha256":"6d453051665f823abd7354d5c50031d9524cf47d6092d2f09080ae814e3b9575"},{"path":"product/runtime/auths-gateway/src/engine.rs","sha256":"1abff20b98bc894c45bfc5c4414c81a99966d1ec95d924a5b0cd6f4c5626ca24"},{"path":"product/runtime/auths-gateway/src/execution_witness.rs","sha256":"e8b1a8e41d5e3fa309760067849d390ef065feeb46701a83391832645a2f000c"},{"path":"product/runtime/auths-gateway/src/fuzzing.rs","sha256":"ed3b0028487eb546a3b0a91d115aa8f18bcea324b61620bfe8e35a9e6ab18758"},{"path":"product/runtime/auths-gateway/src/generation_floor.rs","sha256":"fe1510ec96ce0f67e9a78edbfa94b33eb7df64c0ac4d0a67901124dcd0164777"},{"path":"product/runtime/auths-gateway/src/harness.rs","sha256":"c87e479f3eb281960f6c9c80d43c7560d7ccb654b0154ec823d3fcec4884ac05"},{"path":"product/runtime/auths-gateway/src/lib.rs","sha256":"fad95d031f88072dd024c78facf0bb0267562b1ac743ddd7219fce47e64024f0"},{"path":"product/runtime/auths-gateway/src/listener.rs","sha256":"aa08239bcbc1fcb55e8a212fbdf6a84f12985b0d436dcb51dc58b06e59e435f2"},{"path":"product/runtime/auths-gateway/src/observed_tests.rs","sha256":"a22be071695f89ca2578a4d82fd80d9cb82289213c9bdb8f0470f6b2dc3d9201"},{"path":"product/runtime/auths-gateway/src/observer.rs","sha256":"562ffcaea071c3856e0708dc2fe33516917e145d2438aabb75af0a2b6ba01046"},{"path":"product/runtime/auths-gateway/src/onboarding.rs","sha256":"0dfd7d67e7f02f18a28d1c86ca1b7751d7463f5efcdbe3825de0ad8cbccb3891"},{"path":"product/runtime/auths-gateway/src/operator.rs","sha256":"c3c36954a3e86723df035b47f43b85fc8ab3a6292983522b6258d5c6b4e6c4e4"},{"path":"product/runtime/auths-gateway/src/pending_vectors/attempts.rs","sha256":"47ef3c8cb1c5504d47ae9a0088705ce6715fe86bac1671a34a56fb38a64d0dd3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/bounds.rs","sha256":"e612217307e1da5b0eb5ee6582a7458bb064b8aa8a529fc6555b1b334127ab68"},{"path":"product/runtime/auths-gateway/src/pending_vectors/codes.rs","sha256":"e00670a5ef24eb856cc2c6dcda8e5a263842f55c76bb939c0c27bd9df37e5522"},{"path":"product/runtime/auths-gateway/src/pending_vectors/keys.rs","sha256":"f84c56f2ea9cb34b2b79c72d13fbf2c6585010ec1ed450af58a78c80c1ea1edd"},{"path":"product/runtime/auths-gateway/src/pending_vectors/mod.rs","sha256":"5de8340f0ef71a0b57a09e323fefe473d3160c6ae952b9ba46f714825fbacafc"},{"path":"product/runtime/auths-gateway/src/pending_vectors/outcomes.rs","sha256":"8ec07b9511b48913af36ac999d2aa0e82924289f6acb23ddaeb9f00f99815166"},{"path":"product/runtime/auths-gateway/src/pending_vectors/production.rs","sha256":"772d032e0a0d9c924fb6d6c188528db85a97e71c9e466ddc19eee277baf83614"},{"path":"product/runtime/auths-gateway/src/pending_vectors/recipes.rs","sha256":"51693208270231c25c3aef2a32151d5962114c71e86b88cb9df83181c7af83d9"},{"path":"product/runtime/auths-gateway/src/pre_entry.rs","sha256":"06ea78ca140468bfaba17d9ab04912ad68673954c3203c98fed28272ff2a00c0"},{"path":"product/runtime/auths-gateway/src/property_tests.rs","sha256":"939c081e2e154aaf10186754044bdd65608932c899b970a04a71d0afaa999a93"},{"path":"product/runtime/auths-gateway/src/qualification.rs","sha256":"c597c83de2b94f0374ae54e40a8b57c2a64ec6e254704dca32185f448a908aca"},{"path":"product/runtime/auths-gateway/src/qualification_simulation.rs","sha256":"4ee7cadfb5f46a92713c80f3e55f499cb074d04d8b21ea89d57762af38642bfa"},{"path":"product/runtime/auths-gateway/src/qualification_tests.rs","sha256":"a9178a2e58eea459d5e5dafc53a3999ea7c84dbbffefe6e5eb1f3d098827f028"},{"path":"product/runtime/auths-gateway/src/quorum_tests.rs","sha256":"a78380b019104d688c11a4410082c7e08ded3106aab099954c4f8a1b4ae0fd89"},{"path":"product/runtime/auths-gateway/src/readiness.rs","sha256":"911c3f11892f94641574375e2da4c671c802738f71082f12c39832331052d43d"},{"path":"product/runtime/auths-gateway/src/recipe.rs","sha256":"fecf9af67e7afc48d080e9f8f55f8ce28e49d0e08988717a27908bbda461d6b6"},{"path":"product/runtime/auths-gateway/src/recipe/lower.rs","sha256":"8088b8751ed831dbb48247af953c6290ac95e2a438ccd5bd65eff54be06a1fd1"},{"path":"product/runtime/auths-gateway/src/recipe/review.rs","sha256":"c3eb7d9fdd98dacf52750b14b67ad7b7faaecbbdeafff1e0b049f67d0a2d0139"},{"path":"product/runtime/auths-gateway/src/recipe/runtime.rs","sha256":"c286f0d15f974402822c0810d8e97f98411dc1c557755cc23e540d85e2bb42d9"},{"path":"product/runtime/auths-gateway/src/recipe/source.rs","sha256":"1af50298fb1461e1b24cbdf560d43124d6b1c4c529586c911b1c4797214a69ff"},{"path":"product/runtime/auths-gateway/src/recipe/tests.rs","sha256":"aac551a2481bbc60864c64079bc667dcb232e45a0f41a04073ed84ab5dbe1fce"},{"path":"product/runtime/auths-gateway/src/recipe/validate.rs","sha256":"3711b17605cb7b0d639bc1b180449231f5882a306cab20e2c7782155cc63b0d4"},{"path":"product/runtime/auths-gateway/src/scenario_tests.rs","sha256":"025b53473b3af6900e03bc2fee91aa63ed26a8778bc8c8296fe08f5540794c39"},{"path":"product/runtime/auths-gateway/src/separation.rs","sha256":"be9306848ca5d801767cf6aa14247c8618312ef0e202f00ce0c24c4844491061"},{"path":"product/runtime/auths-gateway/src/simulation_attestation.rs","sha256":"88705e5d45415f760f1e3c3a065c35c48f4f4065bf7b3feb7882246983814d6f"},{"path":"product/runtime/auths-gateway/src/store.rs","sha256":"884bcad4d70d53e12eae9c8517f6ecd0643068ee0be0370015119d04d6cc2516"},{"path":"product/runtime/auths-gateway/src/store_testkit.rs","sha256":"88d82fee42f1b8ef521e8deef0216e938ebeaad822eb2f5020e70b89d145ea70"},{"path":"product/runtime/auths-gateway/src/submit.rs","sha256":"fe2eacb5ad8152eeecbd232c47a356fc72db0098e34fda99532bdf6ef0cf895c"},{"path":"product/runtime/auths-gateway/src/support.rs","sha256":"9fd979029793a22b15d9776a7fc172476fd7c126a80d4080c65d720845becbcb"},{"path":"product/runtime/auths-gateway/src/transport.rs","sha256":"978fc9fb34a33b3db265b5d1c3ce11696a5b9f08529e46dd2a1e7bb62afb9220"},{"path":"product/runtime/auths-kernel-runtime/Cargo.toml","sha256":"926bcd0053e5edd703be8f0027ad009e2982db013c8174c1366edbf38b48087d"},{"path":"product/runtime/auths-kernel-runtime/src/lib.rs","sha256":"7108faae9ca4bc32dc093ddaf885ac8f74f3c9b8d317b7c7d0ed00d1d0ab5972"},{"path":"product/runtime/auths-lifecycle/Cargo.toml","sha256":"c5053c705f8d5554b44e432fe75287a2faf11d644e5a2552e45ad6cd94176af5"},{"path":"product/runtime/auths-lifecycle/src/codec.rs","sha256":"51c4b746749150e8bfcd8ff972b3f6c1ef40bec15583448ec1b471d9ad737dc0"},{"path":"product/runtime/auths-lifecycle/src/digest.rs","sha256":"55282cd7d8aba37713c2dcb5357c9877819edb72a30eadefb860d28d7d3a3eb7"},{"path":"product/runtime/auths-lifecycle/src/identifier.rs","sha256":"31620e8c16de68d3d2d3b84d6353c1a5b9d4151d8247f91fa389b906a8e660f1"},{"path":"product/runtime/auths-lifecycle/src/kernel.rs","sha256":"2abb8c094b36d35b364e74d78091d14c5d6f3d1eb6552cca3b5538dbd017ce23"},{"path":"product/runtime/auths-lifecycle/src/lib.rs","sha256":"afe5a345cd309b5a4f08ffba3170a6d7f16ff914892b3f2006d5208ed24ec736"},{"path":"product/runtime/auths-lifecycle/src/model.rs","sha256":"1af12bbeeeaa65ec02ddcebd7d2c8c92ec1e339fa40ae85b45ab9b01a722a4fa"},{"path":"product/runtime/auths-lifecycle/src/operation.rs","sha256":"78e6d05fcf5d7ea4f148032a3fa26fdfcab77eb346019effe927b08e0d64d732"},{"path":"product/runtime/auths-lifecycle/src/registry.rs","sha256":"53495fe6f7a77422593a41623e28716f1c140dcc1e00f87f6b0ffbfb93a5ef90"},{"path":"product/runtime/auths-lifecycle/src/sealed.rs","sha256":"2e0c03b5813c926c159598bb7890d1523825edbe57cd687d42a5dfb3374a0c19"},{"path":"product/runtime/auths-lifecycle/src/test_support.rs","sha256":"221d9a5c5ef8e1f9f8fd66927484eaf813571d0568470278ecd8fa08a5eec8cd"},{"path":"product/runtime/auths-lifecycle/src/transition.rs","sha256":"011805a28efdd541f44ccea54dd0e34a1e58f4004447ee58013703b4fb6b2822"},{"path":"product/runtime/auths-runtime/Cargo.toml","sha256":"dd29d80a8b4bb56c869f036a6c9998f6e6d1c0383ac5dc03fa42b24abe2a7ff7"},{"path":"product/runtime/auths-runtime/src/lib.rs","sha256":"132ca03d58c14905d3a822a4972f42a22a5ad33a45f2ba9ca44f3a57d810b4b0"},{"path":"product/runtime/auths-runtime/src/production.rs","sha256":"fd4eff4270c571c10fcff6cf27df28961ebf074de8a1a028f500fda1ca376820"},{"path":"product/sdk/auths-approval-quorum/Cargo.toml","sha256":"df904971fca87a24194c5816738a331588fe8f164acb5d70839a35dca5f57114"},{"path":"product/sdk/auths-approval-quorum/src/lib.rs","sha256":"72e4086088a1c0912e4e1a9e980f26a5c280bf5ab16ea39c9f0f58d5096ac2ce"},{"path":"product/sdk/auths-approval-quorum/src/remote.rs","sha256":"9fa029c7c63003adf260f8aec55160c545681c60c1bace0d934e7525862aac7b"},{"path":"product/sdk/auths-approval-quorum/src/remote_tests.rs","sha256":"8a09ce17cfee82a035a74edd535f3ebeb3db0e078784740d3997b17dbdb10197"},{"path":"product/sdk/auths-approval-quorum/src/tests.rs","sha256":"0acbf12be3e497dcc6c2d8f29c9af3b1a7ed8e11b75f6399570d4f217a785060"},{"path":"product/stores/auths-stores/Cargo.toml","sha256":"a32c4b76d17b264be5d40d24497ff237e1ed87822e8bab86229b3db93106dbe3"},{"path":"product/stores/auths-stores/src/gateway_attempt.rs","sha256":"218841602d3d9b23b44625f50e5b54cf275ccedc2d5c89f02d2482b8524472af"},{"path":"product/stores/auths-stores/src/lib.rs","sha256":"e721262edf8a9ab5568ddc27639176312d4a366203b5f73e2d7c11fde2c554e9"},{"path":"product/stores/auths-stores/src/lifecycle.rs","sha256":"3f2cecfda13fdcd7c4a944518646bcc8abd1237f900c0332d5822281f8f9f1cd"}],"schema":"auths.gateway-semantic-closure/1"} \ No newline at end of file diff --git a/product/runtime/auths-gateway/src/commissioning_budget/tests.rs b/product/runtime/auths-gateway/src/commissioning_budget/tests.rs index 97cf05551..a2faec7d2 100644 --- a/product/runtime/auths-gateway/src/commissioning_budget/tests.rs +++ b/product/runtime/auths-gateway/src/commissioning_budget/tests.rs @@ -23,7 +23,7 @@ struct Fixture { impl Fixture { fn load() -> Self { let path = std::path::Path::new(env!("CARGO_MANIFEST_DIR")) - .join("../../../bindings/fixtures/qualification/commissioning-v1.json"); + .join("../../../bindings/fixtures/qualification/commissioning-v2.json"); let document: serde_json::Value = serde_json::from_slice(&std::fs::read(path).expect("fixture")).expect("JSON"); let text = |name: &str| document[name].as_str().expect("artifact").as_bytes(); @@ -67,7 +67,7 @@ impl Fixture { tuple: &binding.tuple, protected_run: &binding.protected_run, principal_sha256: binding.principal_sha256, - trusted_context_sha256: binding.trusted_context_sha256, + trusted_context_sha256: binding.trusted_contexts_sha256[0], resources_sha256: binding.resources_sha256, canonical_action_sha256: binding.allowed_actions[0], } @@ -155,7 +155,7 @@ fn final_unit_race(backend: Backend) { } let barrier = Arc::new(Barrier::new(2)); let handles: Vec<_> = (0..2) - .map(|_| { + .map(|context_index| { // Distinct file handles or PostgreSQL pools model independent hosts. let budget = CommissioningBudget::new(store.raw(), fixture.binding().clone()) .expect("second host"); @@ -170,7 +170,7 @@ fn final_unit_race(backend: Backend) { tuple: &binding.tuple, protected_run: &binding.protected_run, principal_sha256: binding.principal_sha256, - trusted_context_sha256: binding.trusted_context_sha256, + trusted_context_sha256: binding.trusted_contexts_sha256[context_index], resources_sha256: binding.resources_sha256, canonical_action_sha256: binding.allowed_actions[0], }; @@ -256,6 +256,23 @@ fn renewal_binding_and_rollback(backend: Backend) { changed.load(), Err(CommissioningBudgetRefusal::BindingMismatch) ); + let mut changed_contexts = fixture.binding().clone(); + changed_contexts + .trusted_contexts_sha256 + .push(Sha256Digest::from_bytes([0x70; 32])); + let changed_contexts = CommissioningBudget::new(store.raw(), changed_contexts) + .expect("bounded changed context set"); + assert_eq!( + changed_contexts.initialize(), + Err(CommissioningBudgetRefusal::BindingMismatch) + ); + assert_eq!( + budget + .load() + .expect("original budget") + .consumed_credential_leases(), + 2 + ); // Inject a restored older database record while retaining the host's // separately persisted accepted snapshot. Opening never repairs it. let raw = store.raw(); diff --git a/product/runtime/auths-gateway/src/commissioning_floor/tests.rs b/product/runtime/auths-gateway/src/commissioning_floor/tests.rs index bcbb77d6a..218790654 100644 --- a/product/runtime/auths-gateway/src/commissioning_floor/tests.rs +++ b/product/runtime/auths-gateway/src/commissioning_floor/tests.rs @@ -5,7 +5,7 @@ use std::sync::{Arc, Barrier}; fn fixture() -> VerifiedCommissioningPermit { let document: serde_json::Value = serde_json::from_slice(include_bytes!( - "../../../../../bindings/fixtures/qualification/commissioning-v1.json" + "../../../../../bindings/fixtures/qualification/commissioning-v2.json" )) .expect("public synthetic fixture"); let text = |name: &str| document[name].as_str().expect("artifact").as_bytes(); @@ -26,7 +26,7 @@ fn request(binding: &CommissioningBinding) -> CommissioningRequest<'_> { tuple: &binding.tuple, protected_run: &binding.protected_run, principal_sha256: binding.principal_sha256, - trusted_context_sha256: binding.trusted_context_sha256, + trusted_context_sha256: binding.trusted_contexts_sha256[0], resources_sha256: binding.resources_sha256, canonical_action_sha256: binding.allowed_actions[0], } diff --git a/product/runtime/auths-gateway/src/commissioning_session/tests.rs b/product/runtime/auths-gateway/src/commissioning_session/tests.rs index f440adb96..b0ea654ae 100644 --- a/product/runtime/auths-gateway/src/commissioning_session/tests.rs +++ b/product/runtime/auths-gateway/src/commissioning_session/tests.rs @@ -113,7 +113,7 @@ impl Setup { .expect("native fixture authorization"); assert_eq!(verified.actors.len(), 1); let artifacts: Value = serde_json::from_slice(include_bytes!( - "../../../../../bindings/fixtures/qualification/commissioning-v1.json" + "../../../../../bindings/fixtures/qualification/commissioning-v2.json" )) .expect("authority fixture"); let text = |name: &str| artifacts[name].as_str().expect("artifact").as_bytes(); @@ -125,7 +125,7 @@ impl Setup { Sha256Digest::from_bytes(*engine.recipe.digest()); body.statement.binding.tuple.target.store_schema = BoundedText::parse(crate::POSTGRES_STORE_SCHEMA).expect("schema"); - body.statement.binding.trusted_context_sha256 = engine.trusted_context_sha256; + body.statement.binding.trusted_contexts_sha256 = vec![engine.trusted_context_sha256]; body.statement.binding.principal_sha256 = commissioning_principal_sha256(&verified.actors[0]); body.statement.binding.resources_sha256 = @@ -375,7 +375,8 @@ async fn changed_resources_run_operator_or_context_cannot_open_a_session() { for change in ["resources", "run", "operator", "context"] { let mut inputs = setup.inputs(); let mut changed = setup.permit.body().clone(); - changed.statement.binding.trusted_context_sha256 = Sha256Digest::from_bytes([0x61; 32]); + changed.statement.binding.trusted_contexts_sha256 = + vec![Sha256Digest::from_bytes([0x61; 32])]; let different_context = signed(changed); match change { "resources" => inputs.resources = b"different resources", diff --git a/product/runtime/auths-gateway/src/semantic_closure.rs b/product/runtime/auths-gateway/src/semantic_closure.rs index e095aec74..197519d69 100644 --- a/product/runtime/auths-gateway/src/semantic_closure.rs +++ b/product/runtime/auths-gateway/src/semantic_closure.rs @@ -10,7 +10,7 @@ /// SHA-256 of the schema, a NUL byte, and `semantic-closure.json`. /// Regenerate through `semantic_closure_is_current` with `AUTHS_UPDATE_FIXTURES=1`. pub const GATEWAY_SEMANTIC_CLOSURE_SHA256: &str = - "7bc04fab6552c105167a354f578f69893d0cab60f3732140d4edea5f4eca4786"; + "454aa47752e69f8642445ffa744f1a5dcf5ae130cbbe9c5b911f359049502a3d"; #[cfg(test)] mod tests { diff --git a/qualification/reference/README.md b/qualification/reference/README.md index d79df9272..e66eeeefd 100644 --- a/qualification/reference/README.md +++ b/qualification/reference/README.md @@ -50,6 +50,15 @@ prevent output. Filenames never select code. Private author keys are absent. The protected family setup, complete corpus and live workflow still need to use these references. No family is qualified by landing this code. +The native commissioning permit is now schema 2. Its closed +`trusted_contexts_sha256` list contains 1–4 sorted unique exact canonical context +hashes. Every installation still authenticates its actual context separately; +all listed contexts share one immutable run/family lease budget. An unlisted +context, duplicate or reordered list, changed set, or schema 1 permit refuses. +The current public packet author supplies one context to this list. Fresh-challenge +authoring and its protected corpus cases still need integration; native support +for the bounded list is not replay qualification evidence. + `measure.py` validates and subtracts native execution snapshots: matching fresh scope, no saturation/decrease, no duplicate host in an aggregate. Restarted engines must be measured separately. Budget consumption is never substituted diff --git a/qualification/reference/expand.py b/qualification/reference/expand.py index 1de0a7161..59df74a67 100644 --- a/qualification/reference/expand.py +++ b/qualification/reference/expand.py @@ -157,7 +157,7 @@ def expand(args): binding = { 'protected_run': protected_run, 'source_commit': commit, 'tuple': tuple_value, 'principal_sha256': sha256(next(iter(actors)).encode()), - 'trusted_context_sha256': sha256(context_bytes), 'resources_sha256': sha256(resources_raw), + 'trusted_contexts_sha256': [sha256(context_bytes)], 'resources_sha256': sha256(resources_raw), 'provider_environment_class': reference.ENVIRONMENT, 'offline_evidence': { 'conformance_sha256': member(args.conformance, 'conformance', commit, tuple_digest), diff --git a/qualification/reference/tests/test_reference.py b/qualification/reference/tests/test_reference.py index 1187df3e4..13960db2c 100644 --- a/qualification/reference/tests/test_reference.py +++ b/qualification/reference/tests/test_reference.py @@ -194,7 +194,7 @@ def test_binding_is_rederived_and_altered_source_or_native_observations_refuse(s 'trusted_context': 'context.cbor', 'packets': [{'label': 'normal', 'proof': 'proof.cbor', 'action': 'action.cbor', 'arguments': self.stripe_arguments()}]})) - artifacts = json.loads((root / 'bindings/fixtures/qualification/commissioning-v1.json').read_bytes()) + artifacts = json.loads((root / 'bindings/fixtures/qualification/commissioning-v2.json').read_bytes()) tuple_value = json.loads(artifacts['permit'])['statement']['binding']['tuple'] tuple_value['recipe_family'] = stripe.FAMILY tuple_value['compiled_recipe_sha256'] = DIGEST @@ -229,7 +229,7 @@ def review(_binary, arguments): self.assertEqual(binding['maximum_credential_leases'], 64) self.assertEqual(binding['principal_sha256'], sha256(b'raw:synthetic-test-only-actor')) self.assertEqual(binding['resources_sha256'], sha256((work / 'resources.json').read_bytes())) - self.assertEqual(binding['trusted_context_sha256'], sha256(b'synthetic test-only context')) + self.assertEqual(binding['trusted_contexts_sha256'], [sha256(b'synthetic test-only context')]) self.assertFalse(json.loads((args.out_dir / 'oracle-commitments.json').read_bytes())['qualification_issued']) args.out_dir = work / 'changed' recipe = json.loads((work / 'recipe.json').read_bytes()) diff --git a/release/semantic-freeze-versions.toml b/release/semantic-freeze-versions.toml index aebc692eb..6c2307406 100644 --- a/release/semantic-freeze-versions.toml +++ b/release/semantic-freeze-versions.toml @@ -1,4 +1,4 @@ -freeze_version = 379 +freeze_version = 380 # Semantic identity counters live outside the xtask source tree deliberately. # The formal source closure binds xtask's executable code, while the semantic @@ -45,7 +45,7 @@ freeze_version = 379 "auths.frozen-bytes/product/integrations/auths-stripe/fixtures/subscription-create/v1/manifest.sha256.json" = 1 "auths.frozen-bytes/product/integrations/auths-stripe/fixtures/subscription-modify/v1/manifest.sha256.json" = 1 "auths.frozen-bytes/product/integrations/auths-stripe/fixtures/v1/manifest.sha256.json" = 1 -"auths.identity.protocol" = 131 +"auths.identity.protocol" = 132 "auths.modular-components" = 20 "auths.portable-abi-bindings" = 121 "auths.product.bounded-domains" = 19 @@ -60,11 +60,11 @@ freeze_version = 379 "auths.product.mcp-closed-execution" = 31 "auths.product.mechanism-profile-conformance" = 12 "auths.product.operations" = 5 -"auths.product.public-sdk-contract" = 128 +"auths.product.public-sdk-contract" = 129 "auths.product.receipts" = 13 "auths.product.release-assurance" = 7 "auths.product.simplified-waist" = 19 "auths.product.vocabulary" = 24 "auths.release.benchmark-contract" = 1 "auths.release.evolution-contract" = 79 -"auths.release.public-surface" = 379 +"auths.release.public-surface" = 380 diff --git a/release/semantic-freeze.json b/release/semantic-freeze.json index 5b1003510..fc7bd096d 100644 --- a/release/semantic-freeze.json +++ b/release/semantic-freeze.json @@ -1,6 +1,6 @@ { "schema": "auths.semantic-freeze/1", - "freezeVersion": 379, + "freezeVersion": 380, "publicSurface": { "rustRoots": [ "auths", @@ -550,7 +550,7 @@ }, { "id": "auths.identity.protocol", - "version": 131, + "version": 132, "classification": "frozen-meaning", "categories": [ "identity-protocol-versions", @@ -573,7 +573,7 @@ "core/fixtures/identity/v1/vectors.json", "core/spec/identity/v1" ], - "sha256": "b26d8563f6a4423918cf0f649810d1e697bf7681dcc60d7dab0f78d1e398c199" + "sha256": "ce403bf8c8be69014095d2806a3e530fbf44f515feef5322ab8d6e8cb5880f34" }, { "id": "auths.modular-components", @@ -871,7 +871,7 @@ }, { "id": "auths.product.public-sdk-contract", - "version": 128, + "version": 129, "classification": "frozen-meaning", "categories": [ "rust-sdk-contract", @@ -889,7 +889,7 @@ "product/runtime/auths-runtime/src", "product/sdk/auths-sdk/src" ], - "sha256": "b0972f8fe6a4c73e49963eff448367c1ce2d7c94b79e0e9e8c8d9fe4e91548d7" + "sha256": "f4aaff15cbdcf812cb419b61d5556fbe42543984275d2cc8dd22a128ca8d5217" }, { "id": "auths.product.receipts", @@ -1011,7 +1011,7 @@ }, { "id": "auths.release.public-surface", - "version": 379, + "version": 380, "classification": "release-metadata", "categories": [ "package-names", @@ -1104,7 +1104,7 @@ "xtask/src/release_launch.rs", "xtask/src/semantic_freeze.rs" ], - "sha256": "25cbd70c3906606c0556d54caaee0e53205646d5209ba431b9b60e73633606ed" + "sha256": "3a4379a19742b90206425ce79719bfaf6386a7d0948a38c5ab16f58daf029a07" } ] } From 4a5c9b513dd4293a3b239c7c0c625ef33c559060 Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 11:39:10 +0100 Subject: [PATCH 076/108] Author finite fresh-challenge replay packets with the installed SDK --- qualification/reference/README.md | 17 +++++---- qualification/reference/author_packets.py | 36 +++++++++++-------- qualification/reference/author_socket.py | 9 ++--- qualification/reference/check_packets.py | 18 ++++++++-- qualification/reference/expand.py | 25 ++++++++----- qualification/reference/packet_plan.py | 29 +++++++++------ .../reference/tests/test_author_socket.py | 9 ++--- qualification/reference/tests/test_packets.py | 4 ++- .../reference/tests/test_reference.py | 21 +++++++++-- 9 files changed, 115 insertions(+), 53 deletions(-) diff --git a/qualification/reference/README.md b/qualification/reference/README.md index e66eeeefd..a3a6a6a0b 100644 --- a/qualification/reference/README.md +++ b/qualification/reference/README.md @@ -37,12 +37,12 @@ python qualification/reference/expand.py \ --out-dir ``` -The public packet carrier is `auths.qualification-public-packets/2`, with -`protected_run`, `evaluated_at`, `not_after`, `trusted_context` (one adjacent -filename), and 1–64 `packets`. Packet validity is at most five minutes; the +The public packet carrier is `auths.qualification-public-packets/3`, with +`protected_run`, `evaluated_at`, `not_after`, `trusted_contexts` (1–4 sorted +unique adjacent filenames), and 1–64 `packets`. Packet validity is at most five minutes; the signing expansion reviews native proofs at their recorded offline evaluation time, within the last two hours. This grants no production clock override. -Each packet contains `label`, `proof`, `action` (adjacent filenames), and its +Each packet contains `label`, `proof`, `action`, `trusted_context` (adjacent filenames), and its expected `arguments`. Unknown fields, path traversal, changed source, wrong production targets, resource widening, actor changes or an oracle mismatch prevent output. Filenames never select code. Private author keys are absent. @@ -55,9 +55,12 @@ The native commissioning permit is now schema 2. Its closed hashes. Every installation still authenticates its actual context separately; all listed contexts share one immutable run/family lease budget. An unlisted context, duplicate or reordered list, changed set, or schema 1 permit refuses. -The current public packet author supplies one context to this list. Fresh-challenge -authoring and its protected corpus cases still need integration; native support -for the bounded list is not replay qualification evidence. +The public packet author supplies two native challenges under one exact actor +and grant. Each phase's first resource has a `-fresh` replay packet with the same +logical operation and arguments, under the second context. Refresh never changes +that packet's assigned challenge, action or context. At most 31 resources fit +the finite 64-packet ceiling including both replay packets. The source-owned +protected corpus and native durable replay evidence still need integration. `measure.py` validates and subtracts native execution snapshots: matching fresh scope, no saturation/decrease, no duplicate host in an aggregate. Restarted diff --git a/qualification/reference/author_packets.py b/qualification/reference/author_packets.py index be9d46bbd..0c1544957 100644 --- a/qualification/reference/author_packets.py +++ b/qualification/reference/author_packets.py @@ -59,7 +59,8 @@ def create_session(plan_path): unsigned = native.root_grant(actor, request) signing = native.prepare_signing(unsigned, key.principal_method, key.verification_method, key.suite) grant = signing.complete(key.sign(signing.signing_preimage)) - challenge = native.generate_challenge_v1() + challenges = {name: native.generate_challenge_v1() for name in ['initial', 'fresh']} + require(challenges['initial'] != challenges['fresh'], 'qualification.packets.challenge-binding') anchor = native.TrustAnchor(actor.value, actor, [key.principal_method], [('auths.mcp', 2)], [('tools/call', resource)], [audience], [audience], current - 60, end, None, 1, 'raw-key-baseline', None) @@ -70,22 +71,26 @@ def create_session(plan_path): template = native.compile_trusted_context(bytes.fromhex(plan['configuration']), None, 1, 1, 1, [anchor], assurance, None, None, 'none-v1', [key.evidence_type], [] if extension is None else [extension['extension_id']]) - context = template.bind_request(audience, challenge, current) + contexts = {name: template.bind_request(audience, challenge, current) + for name, challenge in challenges.items()} evidence = (key.evidence_type, key.media_type, key.evidence) # The closure alone retains this native key. A refresh accepts a known # label, never caller-supplied arguments, a new grant, actor or challenge. - retained_context, last_time = None, current + retained_contexts, last_time = {}, current def emit(work, label=None): - nonlocal retained_context, last_time + nonlocal last_time current = int(time.time()) require(last_time <= current < end, 'qualification.packets.session-expired') last_time = current validity = min(300, end - current) selected = [packet for packet in plan['packets'] if label is None or packet['label'] == label] require(bool(selected), 'qualification.packets.unknown-label') - packets = [] + packets, emitted_contexts = [], set() for packet in selected: label, arguments = packet['label'], packet['arguments'] + context_name = packet['context'] + challenge, context = challenges[context_name], contexts[context_name] + context_file = 'context-' + str(['initial', 'fresh'].index(context_name)) + '.cbor' call = native.mcp_call(reference.SERVICE, reference.TOOL, canonical(arguments)) prepared = native.prepare_mcp_call_action(call, actor, grant, challenge, current, validity) signing = native.prepare_signing(prepared.unsigned, key.principal_method, key.verification_method, key.suite) @@ -93,25 +98,28 @@ def emit(work, label=None): proof, action, trust = native.assemble_mcp_proof(prepared, signed_action, [grant], [[evidence]], [evidence], context) # Assembly binds its returned context to the fresh envelope time. - # Keep one exact installation context: native normalization changes + # Keep each declared installation context exact: native normalization changes # only the request evaluation input. The gateway always supplies # its own synchronized current time when verifying this proof. trust = bytes(native.inspect_trusted_context(native.parse_trusted_context(trust) .bind_request(audience, challenge, plan['evaluated_at']))) - require(retained_context is None or retained_context == trust, + require(context_name not in retained_contexts or retained_contexts[context_name] == trust, 'qualification.packets.context-binding') - retained_context = bytes(trust) + retained_contexts[context_name] = bytes(trust) write_bytes(work / (label + '.proof'), bytes(proof), new=True) write_bytes(work / (label + '.action'), bytes(action), new=True) + if context_file not in emitted_contexts: + write_bytes(work / context_file, retained_contexts[context_name], new=True) + emitted_contexts.add(context_file) packets.append({'label': label, 'proof': label + '.proof', 'action': label + '.action', - 'arguments': arguments}) - write_bytes(work / 'context.cbor', retained_context, new=True) - write(work / 'public-packets.json', {'schema': 'auths.qualification-public-packets/2', + 'trusted_context': context_file, 'arguments': arguments}) + write(work / 'public-packets.json', {'schema': 'auths.qualification-public-packets/3', 'protected_run': plan['protected_run'], 'evaluated_at': current, 'not_after': current + validity, - 'trusted_context': 'context.cbor', 'packets': packets}, new=True) - write(work / 'author-report.json', {'schema': 'auths.qualification-packet-author/1', + 'trusted_contexts': sorted(emitted_contexts), 'packets': packets}, new=True) + write(work / 'author-report.json', {'schema': 'auths.qualification-packet-author/2', 'family': plan['family'], 'protected_run': plan['protected_run'], 'sdk_version': version, - 'packet_count': len(packets), 'trusted_context_sha256': sha256(retained_context), + 'packet_count': len(packets), 'trusted_contexts_sha256': { + name: sha256(read(work / name, 4 * 1024 * 1024)) for name in sorted(emitted_contexts)}, 'private_key_exported': False, 'provider_token_received': False, 'repository_imported': False, 'qualification_issued': False}, new=True) return emit, end diff --git a/qualification/reference/author_socket.py b/qualification/reference/author_socket.py index 9f33df473..3c3e95bdd 100644 --- a/qualification/reference/author_socket.py +++ b/qualification/reference/author_socket.py @@ -145,7 +145,8 @@ def refresh(work, label, destination): require(len(matches) == 1, 'qualification.packets.unknown-label') packet = matches[0] require(packet['proof'] == label + '.proof' and packet['action'] == label + '.action' - and original['trusted_context'] == 'context.cbor', 'qualification.packets.socket-response') + and packet['trusted_context'] in ['context-0.cbor', 'context-1.cbor'] + and packet['trusted_context'] in original['trusted_contexts'], 'qualification.packets.socket-response') require(not destination.exists(), 'qualification.packets.output-exists') result = exchange(work, 'refresh', label) source = work / ('refresh-' + str(result['generation']).zfill(4)) @@ -153,16 +154,16 @@ def refresh(work, label, destination): now = int(time.time()) require(set(fresh) == set(original) and fresh['schema'] == original['schema'] and fresh['protected_run'] == original['protected_run'] - and fresh['trusted_context'] == 'context.cbor' and fresh['packets'] == [packet] + and fresh['trusted_contexts'] == [packet['trusted_context']] and fresh['packets'] == [packet] and type(fresh['evaluated_at']) is int and type(fresh['not_after']) is int and now - 30 <= fresh['evaluated_at'] <= now and now + 60 <= fresh['not_after'] <= fresh['evaluated_at'] + 300, 'qualification.packets.refresh-binding') payloads = {name: read(source / name, bound) for name, bound in [ (packet['proof'], 4 * 1024 * 1024), (packet['action'], 65536), - ('context.cbor', 4 * 1024 * 1024), ('public-packets.json', 65536)]} + (packet['trusted_context'], 4 * 1024 * 1024), ('public-packets.json', 65536)]} require(payloads[packet['action']] == read(work / packet['action'], 65536) - and payloads['context.cbor'] == read(work / 'context.cbor', 4 * 1024 * 1024), + and payloads[packet['trusted_context']] == read(work / packet['trusted_context'], 4 * 1024 * 1024), 'qualification.packets.refresh-binding') destination.mkdir(mode=0o700) for name, payload in payloads.items(): diff --git a/qualification/reference/check_packets.py b/qualification/reference/check_packets.py index 794798b52..585c15be3 100644 --- a/qualification/reference/check_packets.py +++ b/qualification/reference/check_packets.py @@ -35,7 +35,7 @@ def response(process): def review(binary, work, packet, evaluated_at): return child(binary, ['review-submission', '--recipe', work / 'recipe.json', - '--profile-lock', work / 'profile.lock.json', '--trusted-context', work / 'context.cbor', + '--profile-lock', work / 'profile.lock.json', '--trusted-context', work / packet['trusted_context'], '--proof', work / packet['proof'], '--action', work / packet['action'], '--evaluated-at', str(evaluated_at)]) @@ -77,6 +77,18 @@ def check(args): and value['arguments'] == packet['arguments'] and value['request'] == expected, 'qualification.packets.oracle-mismatch') reviewed.append(value) + require(plan['trusted_contexts'] == ['context-0.cbor', 'context-1.cbor'] + and read(work / 'context-0.cbor', 4 * 1024 * 1024) + != read(work / 'context-1.cbor', 4 * 1024 * 1024), + 'qualification.packets.challenge-binding') + by_label = {packet['label']: (packet, actual) for packet, actual in zip(plan['packets'], reviewed)} + for phase in ['commissioning', 'live']: + original_packet, original_review = by_label[phase + '-00'] + fresh_packet, fresh_review = by_label[phase + '-00-fresh'] + require(original_packet['arguments'] == fresh_packet['arguments'] + and original_packet['trusted_context'] != fresh_packet['trusted_context'] + and original_review['actors'] == fresh_review['actors'], + 'qualification.packets.challenge-binding') # The old proof must really expire at the ordinary five-minute # bound. This is offline review, never a production clock override. expired = review(args.gateway, work, plan['packets'][0], plan['not_after'] + 1) @@ -94,7 +106,8 @@ def check(args): fresh_plan = decode(read(fresh / 'public-packets.json', 65536)) actual = review(args.gateway, fresh, fresh_plan['packets'][0], fresh_plan['evaluated_at']) require(actual == reviewed[0] - and read(fresh / 'context.cbor', 4 * 1024 * 1024) == read(work / 'context.cbor', 4 * 1024 * 1024) + and read(fresh / plan['packets'][0]['trusted_context'], 4 * 1024 * 1024) + == read(work / plan['packets'][0]['trusted_context'], 4 * 1024 * 1024) and read(fresh / plan['packets'][0]['action'], 65536) == read(work / plan['packets'][0]['action'], 65536) and read(fresh / plan['packets'][0]['proof'], 4 * 1024 * 1024) != read(work / plan['packets'][0]['proof'], 4 * 1024 * 1024), 'qualification.packets.refresh-binding') @@ -104,6 +117,7 @@ def check(args): require(process.returncode == 0 and not stderr, 'qualification.packets.author-refused') reports.append({'family': reference.FAMILY, 'packet_count': len(reviewed), 'same_actor_action_request_and_trust_after_refresh': True, + 'fresh_challenges_keep_exact_actor_and_logical_operation': True, 'original_five_minute_expiry_enforced': True, 'author': decode(read(work / 'author-report.json', 65536))}) finally: diff --git a/qualification/reference/expand.py b/qualification/reference/expand.py index 59df74a67..11ea03055 100644 --- a/qualification/reference/expand.py +++ b/qualification/reference/expand.py @@ -116,8 +116,8 @@ def expand(args): and read(args.profile_lock, 65536) == read(source / 'profile.lock.json', 65536), 'qualification.reference.reviewed-source') plan = decode(read(args.packets, 65536)) - closed(plan, ['schema', 'protected_run', 'evaluated_at', 'not_after', 'trusted_context', 'packets']) - require(plan['schema'] == 'auths.qualification-public-packets/2' + closed(plan, ['schema', 'protected_run', 'evaluated_at', 'not_after', 'trusted_contexts', 'packets']) + require(plan['schema'] == 'auths.qualification-public-packets/3' and plan['protected_run'] == protected_run and type(plan['evaluated_at']) is int and 60 <= plan['evaluated_at'] <= 253402300499 and type(plan['not_after']) is int @@ -126,17 +126,25 @@ def expand(args): and type(plan['packets']) is list and 1 <= len(plan['packets']) <= 64, 'qualification.reference.packet-bound') work = args.packets.parent - context = relative(work, plan['trusted_context']) - context_bytes = read(context, 4 * 1024 * 1024) - actors, commitments, labels, oracle = set(), set(), set(), [] + context_names = plan['trusted_contexts'] + require(type(context_names) is list and 1 <= len(context_names) <= 4 + and all(type(name) is str and name in ['context-' + str(index) + '.cbor' for index in range(4)] + for name in context_names) + and context_names == sorted(set(context_names)), 'qualification.reference.context-bound') + context_hashes = {name: sha256(read(relative(work, name), 4 * 1024 * 1024)) for name in context_names} + require(len(set(context_hashes.values())) == len(context_names), 'qualification.reference.context-bound') + actors, commitments, labels, used_contexts, oracle = set(), set(), set(), set(), [] for packet in plan['packets']: - closed(packet, ['label', 'proof', 'action', 'arguments']) + closed(packet, ['label', 'proof', 'action', 'trusted_context', 'arguments']) label = identifier(packet['label'], r'[a-z][a-z0-9-]{0,63}') require(label not in labels, 'qualification.reference.packet-bound') labels.add(label) proof, action = relative(work, packet['proof']), relative(work, packet['action']) read(proof, 4 * 1024 * 1024) read(action, 65536) + require(packet['trusted_context'] in context_names, 'qualification.reference.context-bound') + context = relative(work, packet['trusted_context']) + used_contexts.add(packet['trusted_context']) reviewed = child(args.reviewer, ['review-submission', '--recipe', args.recipe, '--profile-lock', args.profile_lock, '--trusted-context', context, '--proof', proof, '--action', action, @@ -151,13 +159,14 @@ def expand(args): actors.add(reviewed['actors'][0]) commitments.add(commitment) oracle.append({'label': label, 'request_sha256': sha256(canonical(expected)), - 'action_commitment': commitment}) + 'action_commitment': commitment, 'trusted_context_sha256': context_hashes[packet['trusted_context']]}) require(len(actors) == 1, 'qualification.reference.principal-binding') + require(used_contexts == set(context_names), 'qualification.reference.context-bound') tuple_digest = sha256(b'auths.qualification-tuple/1\0' + canonical(tuple_value)) binding = { 'protected_run': protected_run, 'source_commit': commit, 'tuple': tuple_value, 'principal_sha256': sha256(next(iter(actors)).encode()), - 'trusted_contexts_sha256': [sha256(context_bytes)], 'resources_sha256': sha256(resources_raw), + 'trusted_contexts_sha256': sorted(context_hashes.values()), 'resources_sha256': sha256(resources_raw), 'provider_environment_class': reference.ENVIRONMENT, 'offline_evidence': { 'conformance_sha256': member(args.conformance, 'conformance', commit, tuple_digest), diff --git a/qualification/reference/packet_plan.py b/qualification/reference/packet_plan.py index 7cec8abd2..e2c14974f 100644 --- a/qualification/reference/packet_plan.py +++ b/qualification/reference/packet_plan.py @@ -44,14 +44,19 @@ def arguments(family, resources, recipe_digest): # This checks the full resource/action request contract before the # author can turn these inputs into signed action bytes. reference.request(value, resources, '0' * 64, recipe_digest) - packets.append({'label': label, 'arguments': value}) + packets.append({'label': label, 'context': 'initial', 'arguments': value}) + if index == 0: + # Same logical operation and exact arguments, under the other + # predeclared challenge. It is replay evidence, never a second + # planned write or caller-selected authoring authority. + packets.append({'label': label + '-fresh', 'context': 'fresh', 'arguments': dict(value)}) return packets def validate(plan): closed(plan, ['schema', 'family', 'protected_run', 'evaluated_at', 'not_after', 'configuration', 'extension', 'resources', 'packets']) - require(plan['schema'] == 'auths.qualification-packet-plan/1' + require(plan['schema'] == 'auths.qualification-packet-plan/2' and type(plan['family']) is str and plan['family'] in REFERENCES, 'qualification.packets.schema') run_id(plan['protected_run']) @@ -61,25 +66,29 @@ def validate(plan): 'qualification.packets.time-bound') digest(plan['configuration']) packets = plan['packets'] - require(type(packets) is list and 2 <= len(packets) <= 64, + require(type(packets) is list and 4 <= len(packets) <= 64, 'qualification.packets.packet-bound') labels, operations = set(), set() for packet in packets: - closed(packet, ['label', 'arguments']) + closed(packet, ['label', 'context', 'arguments']) require(type(packet['label']) is str and packet['label'] not in labels - and packet['label'] in {phase + '-' + str(index).zfill(2) - for phase in ['commissioning', 'live'] for index in range(32)}, + and packet['label'] in {phase + '-' + str(index).zfill(2) + suffix + for phase in ['commissioning', 'live'] for index in range(32) + for suffix in (['', '-fresh'] if index == 0 else [''])} + and packet['context'] == ('fresh' if packet['label'].endswith('-fresh') else 'initial'), 'qualification.packets.packet-bound') labels.add(packet['label']) value = packet['arguments'] fields = ['operator_namespace', 'operation_id', 'recipe_digest'] fields += ['payment_intent', 'amount', 'currency'] if plan['family'] == stripe_platform.FAMILY else ['record_id', 'replacement'] closed(value, fields) - operation = 'qlf-' + sha256(canonical([plan['family'], plan['protected_run'], packet['label']]))[:48] - require(value['operation_id'] == operation and operation not in operations, + operation = 'qlf-' + sha256(canonical([plan['family'], plan['protected_run'], + packet['label'].removesuffix('-fresh')]))[:48] + require(value['operation_id'] == operation + and (operation, packet['context']) not in operations, 'qualification.packets.operation-binding') digest(value['recipe_digest']) - operations.add(operation) + operations.add((operation, packet['context'])) require(len({packet['arguments']['recipe_digest'] for packet in packets}) == 1, 'qualification.packets.recipe-binding') require(packets == arguments(plan['family'], plan['resources'], packets[0]['arguments']['recipe_digest']) @@ -121,7 +130,7 @@ def prepare(args): '--scope', 'payment_intent=' + ','.join(payment['id'] for payment in resources['payments'])]) extension = {name: derived[name] for name in ['extension_id', 'extension_body_hex']} evaluated_at = int(time.time()) - plan = validate({'schema': 'auths.qualification-packet-plan/1', 'family': args.family, + plan = validate({'schema': 'auths.qualification-packet-plan/2', 'family': args.family, 'protected_run': resources['protected_run'], 'evaluated_at': evaluated_at, 'not_after': evaluated_at + PACKET_VALIDITY, 'configuration': review['verifier_configuration'], 'extension': extension, 'resources': resources, diff --git a/qualification/reference/tests/test_author_socket.py b/qualification/reference/tests/test_author_socket.py index a01bd406c..bb658ee64 100644 --- a/qualification/reference/tests/test_author_socket.py +++ b/qualification/reference/tests/test_author_socket.py @@ -57,14 +57,15 @@ def test_refresh_never_exports_a_changed_action_context_or_aged_packet(self): work = Path(temporary) work.chmod(0o700) packet = {'label': 'live-00', 'proof': 'live-00.proof', + 'trusted_context': 'context-0.cbor', 'action': 'live-00.action', 'arguments': {'closed': 'source'}} now = int(time.time()) - original = {'schema': 'auths.qualification-public-packets/2', + original = {'schema': 'auths.qualification-public-packets/3', 'protected_run': 'recipe-qualification/123/1', 'evaluated_at': now, - 'not_after': now + 300, 'trusted_context': 'context.cbor', 'packets': [packet]} + 'not_after': now + 300, 'trusted_contexts': ['context-0.cbor'], 'packets': [packet]} write(work / 'public-packets.json', original, new=True) write_bytes(work / 'live-00.action', b'source-action', new=True) - write_bytes(work / 'context.cbor', b'source-context', new=True) + write_bytes(work / 'context-0.cbor', b'source-context', new=True) fresh = work / 'refresh-0001' fresh.mkdir(mode=0o700) value = dict(original) @@ -73,7 +74,7 @@ def test_refresh_never_exports_a_changed_action_context_or_aged_packet(self): if change == 'extra-field': value['credential'] = 'synthetic-forbidden-input' write(fresh / 'public-packets.json', value, new=True) write_bytes(fresh / 'live-00.action', b'changed' if change == 'action' else b'source-action', new=True) - write_bytes(fresh / 'context.cbor', b'changed' if change == 'context' else b'source-context', new=True) + write_bytes(fresh / 'context-0.cbor', b'changed' if change == 'context' else b'source-context', new=True) write_bytes(fresh / 'live-00.proof', b'public-proof', new=True) with patch('author_socket.exchange', return_value={'generation': 1}): with self.assertRaises(Refusal): author_socket.refresh(work, 'live-00', work / 'output') diff --git a/qualification/reference/tests/test_packets.py b/qualification/reference/tests/test_packets.py index 23f677795..0e73c22b8 100644 --- a/qualification/reference/tests/test_packets.py +++ b/qualification/reference/tests/test_packets.py @@ -20,7 +20,7 @@ def plan(self): 'protected_run': 'recipe-qualification/123/1', 'base': airtable_record.BASE, 'table': airtable_record.TABLE, 'records': [ {'id': 'recTEST0000000001', 'run_metadata': 'recipe-qualification/123/1'}]} - return {'schema': 'auths.qualification-packet-plan/1', 'family': airtable_record.FAMILY, + return {'schema': 'auths.qualification-packet-plan/2', 'family': airtable_record.FAMILY, 'protected_run': resources['protected_run'], 'evaluated_at': 1000, 'not_after': 8200, 'configuration': '1' * 64, 'extension': None, 'resources': resources, 'packets': packet_plan.arguments(airtable_record.FAMILY, resources, '2' * 64)} @@ -35,6 +35,8 @@ def test_resource_action_and_phase_changes_cannot_choose_refresh_authority(self) lambda p: p['resources'].update(base='appOTHER'), lambda p: p.update(not_after=9000), lambda p: p.update(evaluated_at=True), lambda p: p.update(credential='synthetic-forbidden-input'), + lambda p: p['packets'][0].update(context='fresh'), + lambda p: p['packets'][1]['arguments'].update(operation_id='new-operation'), lambda p: p['packets'].reverse(), lambda p: p['packets'].pop()] for change in changes: changed = copy.deepcopy(plan) diff --git a/qualification/reference/tests/test_reference.py b/qualification/reference/tests/test_reference.py index 13960db2c..ebb0f1fb8 100644 --- a/qualification/reference/tests/test_reference.py +++ b/qualification/reference/tests/test_reference.py @@ -184,14 +184,15 @@ def test_binding_is_rederived_and_altered_source_or_native_observations_refuse(s for name in ['recipe.json', 'profile.lock.json']: (work / name).write_bytes((source / name).read_bytes()) (work / 'candidate').write_bytes(b'synthetic test-only candidate, not an executable') - (work / 'context.cbor').write_bytes(b'synthetic test-only context') + (work / 'context-0.cbor').write_bytes(b'synthetic test-only context') (work / 'proof.cbor').write_bytes(b'synthetic test-only proof') (work / 'action.cbor').write_bytes(b'synthetic test-only action') (work / 'resources.json').write_bytes(canonical(self.stripe_resources())) (work / 'packets.json').write_bytes(canonical({ - 'schema': 'auths.qualification-public-packets/2', 'protected_run': RUN, + 'schema': 'auths.qualification-public-packets/3', 'protected_run': RUN, 'evaluated_at': 1000, 'not_after': 1300, - 'trusted_context': 'context.cbor', 'packets': [{'label': 'normal', + 'trusted_contexts': ['context-0.cbor'], 'packets': [{'label': 'normal', + 'trusted_context': 'context-0.cbor', 'proof': 'proof.cbor', 'action': 'action.cbor', 'arguments': self.stripe_arguments()}]})) artifacts = json.loads((root / 'bindings/fixtures/qualification/commissioning-v2.json').read_bytes()) @@ -231,6 +232,20 @@ def review(_binary, arguments): self.assertEqual(binding['resources_sha256'], sha256((work / 'resources.json').read_bytes())) self.assertEqual(binding['trusted_contexts_sha256'], [sha256(b'synthetic test-only context')]) self.assertFalse(json.loads((args.out_dir / 'oracle-commitments.json').read_bytes())['qualification_issued']) + original_packets = json.loads(args.packets.read_bytes()) + (work / 'context-1.cbor').write_bytes(b'synthetic second test-only context') + for problem in ['unused', 'duplicate', 'unknown', 'empty', 'obsolete']: + changed = copy.deepcopy(original_packets) + if problem == 'unused': changed['trusted_contexts'].append('context-1.cbor') + if problem == 'duplicate': changed['trusted_contexts'].append('context-0.cbor') + if problem == 'unknown': changed['packets'][0]['trusted_context'] = 'context-2.cbor' + if problem == 'empty': changed['trusted_contexts'] = [] + if problem == 'obsolete': changed['schema'] = 'auths.qualification-public-packets/2' + args.packets.write_bytes(canonical(changed)) + args.out_dir = work / ('refused-context-' + problem) + with self.assertRaises(Refusal): expansion.expand(args) + self.assertFalse(args.out_dir.exists()) + args.packets.write_bytes(canonical(original_packets)) args.out_dir = work / 'changed' recipe = json.loads((work / 'recipe.json').read_bytes()) del recipe['credential']['guard'] From 70508743a60fece1b419e57c8b3ff2195f014d45 Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 12:11:10 +0100 Subject: [PATCH 077/108] Stream private commissioning counters without cancelling entered attempts --- .../qualification/verification-vectors.json | 2 +- ...d-qualification-commissioning-authority.md | 5 +- ...NDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md | 5 +- .../src/vectors/verification.rs | 2 +- .../auths-gateway/semantic-closure.json | 2 +- .../auths-gateway/src/bin/auths-gateway.rs | 188 +++++++++++++++++- .../src/commissioning_session/tests.rs | 2 +- .../auths-gateway/src/semantic_closure.rs | 2 +- qualification/README.md | 16 +- release/semantic-freeze-versions.toml | 4 +- release/semantic-freeze.json | 6 +- 11 files changed, 215 insertions(+), 19 deletions(-) diff --git a/bindings/fixtures/qualification/verification-vectors.json b/bindings/fixtures/qualification/verification-vectors.json index 5d2176dbe..62d5ad446 100644 --- a/bindings/fixtures/qualification/verification-vectors.json +++ b/bindings/fixtures/qualification/verification-vectors.json @@ -1048,7 +1048,7 @@ "gateway_version": "1.0.0-rc.1", "gateway_build_sha256": "42194bc83fbd821aaede008519091b4516baf914f8c2e27f3f2ac7a25f7485c3", "store_kind": "postgresql-v1", - "store_schema": "auths.lifecycle.postgresql/6", + "store_schema": "auths.lifecycle.postgresql/0", "credential_store_kind": "aws-secrets-manager-v1" } } diff --git a/docs/adr/0016-bounded-qualification-commissioning-authority.md b/docs/adr/0016-bounded-qualification-commissioning-authority.md index 2b8b2c836..41f67ee76 100644 --- a/docs/adr/0016-bounded-qualification-commissioning-authority.md +++ b/docs/adr/0016-bounded-qualification-commissioning-authority.md @@ -171,7 +171,10 @@ installation and its signed operator attestation. The directory passed with `--from` contains `commissioning-permit.json`, `signer-certificate.json` and `revocation-list.json`. `--protected-run` identifies the exact workflow run and attempt; `--resource-binding` supplies the exact public resource file reviewed -before issuance. A submit additionally names only `--proof` and `--action`. +before issuance. A submit additionally names `--proof` and `--action`; optional +`--witness-file` records bounded secret-free counters in a new owner-private +file. Recording never grants authority or pauses execution; any recording +failure is reported after the native attempt completes. The root, production tuple, installed context and synchronized clock come from the installation, with no command-line root or policy override. diff --git a/docs/research/INDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md b/docs/research/INDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md index d64135668..9af6a5002 100644 --- a/docs/research/INDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md +++ b/docs/research/INDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md @@ -20,9 +20,10 @@ audit or real-user trial is claimed. | Publication scanning omitted newly added commissioning files and other unlisted outputs. | Replace the filename allowlist with a bounded complete-tree scan. Refuse symbolic/hard links, special or oversized files and concurrent changes; keep canaries private and outside artifacts. Move shipping executables outside the evidence tree and use one credential-free candidate build. Native pipeline regressions plant leaks in commissioning effects, source facts and an unexpected filename. | | A phase's cleanup would destroy the resources needed by the subsequent ordinary qualified phase. | Resource setup/cleanup now belongs to one whole source-owned journey; individual phase runners only execute their phase. Setup runs once, resources stay present across sequential commands, and setup/stage/cleanup failure invalidates both protected phase outputs and the final proposal. Source pipeline tests use explicit doubles; the complete protected signing/qualification sequence still needs integration. | | An in-memory author connected only by stdin could not survive separate runner steps. | Added a fixed private Unix socket, authenticated Linux peer credentials, a dedicated non-root author UID and root-only controller. Reconnection preserves one key and monotonic refresh generation; changed action/trust bytes or stale packets prevent public handoff. Actual Docker rehearsals passed for both synthetic recipe families with the installed wheel and shipping gateway; no provider or protected qualification was involved. | -| Artifact waits needed exact run identity and safe public extraction. | Added a source-owned reader that pins repository, main/manual workflow, source SHA, run/attempt and artifact role; checks the actual GitHub archive digest; refuses code, links, traversal, duplicates and oversized members; removes partial output. The actual retained native-author report was downloaded and successfully extracted against GitHub's digest. The first local run exposed an unnecessary Python 3.11 hashing API; bounded streaming hashing now works on the operator's Python 3.9. Protected workflow integration remains pending. | +| Artifact waits needed exact run identity and safe public extraction. | Added a source-owned reader that pins repository, main/manual workflow, source SHA, run/attempt and artifact role; checks the actual GitHub archive digest; refuses code, links, traversal, duplicates and oversized members; removes partial output. The actual retained native-author report was downloaded and successfully extracted against GitHub's digest. The first local run exposed an unnecessary Python 3.11 hashing API; bounded streaming hashing now works on Python before 3.11, including the supported 3.9 baseline. Protected workflow integration remains pending. | | A dedicated author UID could not launch the SDK beneath the hosted runner's private temporary ancestors. | The hosted author job failed. A Docker reproduction confirmed the private-parent launcher refusal and then passed with public-readable copied SDK inputs. CI now copies only the credential-free kit and installed wheel environment to `/opt`; author output remains owner-private under `/tmp`. Hosted verification of this correction is pending. | -| A permit pinned one challenge, preventing a valid fresh-challenge replay from reaching the durable claim. | Native permit schema 2 binds 1–4 exact sorted context hashes; every context still needs its own operator attestation and native challenge verification. The full set shares one immutable run/family budget. Frozen vectors cover both listed contexts and an outsider; the durable final-unit race uses different contexts, and a set change cannot register new capacity. The current author still emits one context; source-owned fresh-challenge packet and protected corpus integration remain pending. | +| A permit pinned one challenge, preventing a valid fresh-challenge replay from reaching the durable claim. | Native permit schema 2 binds 1–4 exact sorted context hashes; every context still needs its own operator attestation and native challenge verification. The full set shares one immutable run/family budget. Frozen vectors cover both listed contexts and an outsider; the durable final-unit race uses different contexts, and a set change cannot register new capacity. The installed author emits two challenges for one actor and identical declared operations. Actual pipe and isolated-socket Docker rehearsals passed native review of both contexts and preserved exact action/context bytes across refresh. Protected durable replay evidence remains pending. | +| Real response-loss testing needs visibility into a short-lived commissioning process. | Added optional owner-private, bounded read-only counter streaming. A stream failure never cancels an entered native attempt. Counters indicate local execution boundaries; the family harness still needs actual external network faults and independent provider read-back. | The public offline root ceremony and purpose-separated certificates are pinned. Both signer keys are provisioned in the existing reviewer-protected main-only diff --git a/product/qualification/auths-recipe-qualification/src/vectors/verification.rs b/product/qualification/auths-recipe-qualification/src/vectors/verification.rs index 8bdb1d134..8c5b62a6e 100644 --- a/product/qualification/auths-recipe-qualification/src/vectors/verification.rs +++ b/product/qualification/auths-recipe-qualification/src/vectors/verification.rs @@ -687,7 +687,7 @@ fn target_cases() -> Vec { deployed.target.store_kind = LifecycleStoreKind::SharedFileV1; }), drifted("wrong-store-schema", "wrong-store", |deployed| { - deployed.target.store_schema = super::bounded("auths.lifecycle.postgresql/6"); + deployed.target.store_schema = super::bounded("auths.lifecycle.postgresql/0"); }), drifted( "wrong-credential-store", diff --git a/product/runtime/auths-gateway/semantic-closure.json b/product/runtime/auths-gateway/semantic-closure.json index 841341526..904714fb4 100644 --- a/product/runtime/auths-gateway/semantic-closure.json +++ b/product/runtime/auths-gateway/semantic-closure.json @@ -1 +1 @@ -{"files":[{"path":"Cargo.lock","sha256":"0e75e2fdef44e79e57797ac6661295ae58ddb8de4a1990a6fd22ce6c54f78604"},{"path":"Cargo.toml","sha256":"6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24"},{"path":"core/adapters/auths-did-keri/Cargo.toml","sha256":"86ba3e3f9a0a70d970568bfb3113b7ba7bbdd81c3eebbb52743dd574a0c0ecaa"},{"path":"core/adapters/auths-did-keri/src/lib.rs","sha256":"a75674842f8a7142004369ccd206ab43e476459293f0ff4bed4d4e659031b3e3"},{"path":"core/adapters/auths-did-key/Cargo.toml","sha256":"d5a3ae07ecde83f91eed4c3785051dd0f44eab6c891754f3309b6b40596707d7"},{"path":"core/adapters/auths-did-key/src/lib.rs","sha256":"b76a3f4528a725df53cfa9242e6e414e1d26caa48468aaed497e28b121f4497c"},{"path":"core/adapters/auths-raw-key/Cargo.toml","sha256":"f49616bc18c19e6aaa7e6a02ccebcdb9f5c1422c1278ef9869e0dbf22ceda7be"},{"path":"core/adapters/auths-raw-key/src/lib.rs","sha256":"45eec1b295dac3bed65cd79c942870b926b06b3f5d38eaebaeb6140ac69315fa"},{"path":"core/crates/auths-algebra-kernel/Cargo.toml","sha256":"0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba"},{"path":"core/crates/auths-algebra-kernel/src/generated.rs","sha256":"ae4bcbef42a408c7ffa0c6a74a42f7de177a6f14479e51d205acf830bda05960"},{"path":"core/crates/auths-algebra-kernel/src/lib.rs","sha256":"6654667eeb9b353d6648954c9fd2e8838462a82ce6b2803eb49e1366892c68c6"},{"path":"core/crates/auths-assurance/Cargo.toml","sha256":"afcb12a97ddd09d7a264b9ecd3fcaefc865ff2c9b4539ee85b00883420ba333a"},{"path":"core/crates/auths-assurance/src/lib.rs","sha256":"0fb2ec844d674b25a9e20b1601452c89c2454901fa506adfa9bb38ef9a7fa213"},{"path":"core/crates/auths-author/Cargo.toml","sha256":"1e6f0e3bc079ddb558decf0db26b291c6e72fc47327b6df1b7650d41689b215f"},{"path":"core/crates/auths-author/src/lib.rs","sha256":"e14475f2f49715a1869d5fa6b11ff1fbb72497e39097e09f833b0bae7e5b3f2b"},{"path":"core/crates/auths-author/src/observations.rs","sha256":"dda7d6bfa6f4bd7e95a480ca283c2c0e996f69c5c15cb0c7197af328131a7066"},{"path":"core/crates/auths-authority/Cargo.toml","sha256":"4f68212938029f79ebd857b4f3038494eb85d0163d49f07e51376715cf959815"},{"path":"core/crates/auths-authority/src/lib.rs","sha256":"da88d5194de4e17449e69972c0fb042afa3c39798a8f570f30771e77c384f1eb"},{"path":"core/crates/auths-codec/Cargo.toml","sha256":"e20e51826e17814effd9d8925d18d5fbdd6c0d37bf50231e743ec2611314722c"},{"path":"core/crates/auths-codec/src/approval.rs","sha256":"fbff43bf4d57f69f8b7738a8647751cde75c5a932dee65d924a1fe9c7202f91f"},{"path":"core/crates/auths-codec/src/bounded_policy.rs","sha256":"d21f6728be2d8a04b6d94921f2b683f7e61cbb42e0ac6866f1c88a49caa534c3"},{"path":"core/crates/auths-codec/src/decode.rs","sha256":"ba2999584cdf53b1b517ecb9c7ea50d39efee17c666a9a38e2ad1ac94379f778"},{"path":"core/crates/auths-codec/src/encode.rs","sha256":"8491192053e2e15d62b4d2a491de22405b7487ead69ab6f6bca40669ce7ca5f7"},{"path":"core/crates/auths-codec/src/error.rs","sha256":"fecb0737c16deb42d859f1dc7727c698438d9ac12064fd99e0024629642c390c"},{"path":"core/crates/auths-codec/src/hash.rs","sha256":"f88e111f1dbb2cef6b7b5e9c948cb45ff92e366710c8a5f5c636138aa748479e"},{"path":"core/crates/auths-codec/src/lib.rs","sha256":"3b0e5c94c6f34f750b88a9333e1d5c8145746d845d3a23e0d2f61807cf592ea7"},{"path":"core/crates/auths-codec/src/observation.rs","sha256":"38328b0c71ff97a4196eeade8b4faa889527ff1f80bb168468bcd49082a3987e"},{"path":"core/crates/auths-composition/Cargo.toml","sha256":"331e13025eb82588b5269ed3975929eb41c823d588c49e4c296273d85c6fe80e"},{"path":"core/crates/auths-composition/src/lib.rs","sha256":"e42e3b0b6a9985b73c533aeb23799c638979aa27a9ce7d0f10a8d60340570fb1"},{"path":"core/crates/auths-model/Cargo.toml","sha256":"565c15302b0cc9270db1e28efa3862804846850ba933cc17aea8abcec4a65987"},{"path":"core/crates/auths-model/src/approval.rs","sha256":"54cf44a9ef747ec21546a4086aecfb130bc7803b0d646430e6082df51e6e305f"},{"path":"core/crates/auths-model/src/bounded.rs","sha256":"f90496abc0a06c028b4d850af6ddab7d850bfafeaa3d042f1b1246a41d8bbbc9"},{"path":"core/crates/auths-model/src/bounded_policy.rs","sha256":"306a8f049cc7cfc7635fe0e4de47eb7813eed63d3c14c3be2b51586aa4eea450"},{"path":"core/crates/auths-model/src/lib.rs","sha256":"e7cfe6bb9574c6b016aa63e70658c31e0b90903ec6479a49f4a2ceb64f5bad97"},{"path":"core/crates/auths-model/src/observation.rs","sha256":"b3ed3e3cc090afca2896a7d3de7988afccc1ee1ea0ebd91b51a8bc0f20ad8dbb"},{"path":"core/crates/auths-multikey/Cargo.toml","sha256":"858756c1197befcada06134742bffe8d58cf674cadd6c046bf710570e96efaf2"},{"path":"core/crates/auths-multikey/src/lib.rs","sha256":"f5177fffb11e40eeaaa665ba886c541fc1f24d5eacdd6983fb03dc20148733f0"},{"path":"core/crates/auths-ports/Cargo.toml","sha256":"596a9b0f5af3717c16a6d13f7054d8a106bcd9f01f5f72c2235dd2afcf0ab16c"},{"path":"core/crates/auths-ports/src/binding.rs","sha256":"a16c012d40aa4249e3ec54372b9611006d0bfe8c7dc3c741911c2194ad17736d"},{"path":"core/crates/auths-ports/src/diagnostics.rs","sha256":"aa596572503b5a65a918bb2ff38281c144ff53821ee914e9325c852828d852df"},{"path":"core/crates/auths-ports/src/lib.rs","sha256":"8da1debf86f9532df0660155d04298beb1ba3a1204508f8586e2e67cd2fb3449"},{"path":"core/crates/auths-ports/src/path.rs","sha256":"b68fc547b4e4d97a60cbbc1cc1939fc6b34a8233b81f840bd396914a707e3ea1"},{"path":"core/crates/auths-raw-key-core/Cargo.toml","sha256":"98c0bc8527a537512e43a74dd6ba9658c6f0cdc16610cf938e3f9b43785d836d"},{"path":"core/crates/auths-raw-key-core/src/lib.rs","sha256":"98c0500c41697aae28708ad0bf970b9a97583d96a3d2c18d23e7fa351e0f7d12"},{"path":"core/crates/auths-registries/Cargo.toml","sha256":"590e49e58b0622d9d6274fea46796dcdb07dec9550eff295cce6a6427ffa51e2"},{"path":"core/crates/auths-registries/src/lib.rs","sha256":"450d3886d85ee333b7e046317fb5b47cde62483d5f3e41d46265e2caf4c373ec"},{"path":"core/crates/auths-registries/src/template.rs","sha256":"1224039dd2b3ce6fa8357613d8cafbae40400493da7176da202b9ade62fa05e4"},{"path":"core/crates/auths-signature-core/Cargo.toml","sha256":"6bee2230eb30af1be0bd5c2d57bd3e1903497a70028d47290d4ac6e9e0e8bca0"},{"path":"core/crates/auths-signature-core/src/lib.rs","sha256":"6e3f9311ded5e49ea50d445eb21e6d8fa12442aa4362a73e0cb6fda15b7cd865"},{"path":"core/crates/auths-signature/Cargo.toml","sha256":"7f7b5682466ba439d8c59579022cb61068cad9fb4bd2d73e1cc21327c902b450"},{"path":"core/crates/auths-signature/src/lib.rs","sha256":"b3d9ac4cc3ba0797b9e1c09f2d6ac05089b25dac4e285a5af28c0165b33d925b"},{"path":"core/crates/auths-verifier/Cargo.toml","sha256":"c43358e06a33324b41a8b93e5cc7279c55f7d21f1f6cfaa539a3fc7b4c27a38f"},{"path":"core/crates/auths-verifier/src/approval.rs","sha256":"c3cae6a49e169051eb555bb092b1069a4d422516d6a2114623a89e5f31ff923f"},{"path":"core/crates/auths-verifier/src/causal.rs","sha256":"9635230f33b13a263573d319ac8a1976addbcc07677514a43e3c7bf28dc04587"},{"path":"core/crates/auths-verifier/src/lib.rs","sha256":"f22dec38dfa47ced8da4f605390da8453273bee1da010f57fd1fdfcb10e0b389"},{"path":"core/crates/auths-verifier/src/observation.rs","sha256":"0bb07f06a0f9524c88427df1c972b1de8ba038a9eeeb15d3134c25125ae84b1e"},{"path":"core/crates/auths-verifier/src/trace.rs","sha256":"2213d72023a1d9e0413a2cf2c51c3dad9e04775d86033a0caaa9d29a8f0036f8"},{"path":"exchange/crates/auths-proof-exchange-model/Cargo.toml","sha256":"34b2db64f93a288e942b5a3918d28cdcbef906e0dc9074ce848018d3d5f7a1fa"},{"path":"exchange/crates/auths-proof-exchange-model/src/lib.rs","sha256":"49fac5aff2339d3a57c41cb8bb2a82852538e8f77ecc4b157c88e264ff31fb55"},{"path":"exchange/crates/auths-proof-exchange-port/Cargo.toml","sha256":"7ff660f1b7579dc570c791090aeb450404fbbf44c92781e289f5ccdde746d739"},{"path":"exchange/crates/auths-proof-exchange-port/src/lib.rs","sha256":"b408fb40c6432edc1facb3d8b3e9433a033f8dc73fe2e0ba5a88c972ca675021"},{"path":"product/config/auths-config/Cargo.toml","sha256":"e4b568ab9f6d84f7d7e6d66443fe825f360db9c27bc7c31d6ddc0647ba3ab304"},{"path":"product/config/auths-config/src/lib.rs","sha256":"fecf00ea65cef9018fda9af2063326d7065b869266d0d9e73a4f06816f1102cc"},{"path":"product/errors/auths-errors/Cargo.toml","sha256":"3b3a199b6460ba75bda84475bb5accd35e1485448a3981038db85bf4772dd350"},{"path":"product/errors/auths-errors/src/lib.rs","sha256":"7feeb9069fa4003f94f1f07c1c94619cf1c883e0dbaaf2187f04d0f742264bdd"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/Cargo.toml","sha256":"716f1f2a117d6d69d8effe9ee9057e24ba3502f20af6a602b06facb638cdabed"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/api.rs","sha256":"9ea61dd7ddd93282b073b98e453e6b75b26dc49689c04e9782435d06a3a09e48"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/clock.rs","sha256":"73f0a6e0f5903883329fa6683f5888288f759512ac69e5c87efd2b6b87f7d79f"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/http.rs","sha256":"14c1fce14e24c984b2a275563a29b6326fb08367922b6e8d37ba38b9cb81aa2b"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/identity.rs","sha256":"186de11230c8b33375951c4368609f8976bf9795f171af3fd7fac26207a94361"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs","sha256":"0b4617d044f5254a5ab22f5a2578f91cc025206a8c1845be39c1c56dcdf7a5df"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/names.rs","sha256":"41bb23572d6002e23ee103d6fe70ecd68764861c6f2e48a1c53af998270a4afa"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs","sha256":"39fed883f4802e68d3b41a68fea0aba0737810996b33d13577de70faba004c29"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/store.rs","sha256":"fc60ee9c49b2f4f063c449b4c78100c5c4872779e94ca168f796603b380ef6e4"},{"path":"product/integrations/auths-custody/Cargo.toml","sha256":"1e14034185ad1ec24a977fd5f41d0abee219606245c046ce2a82287fadef448b"},{"path":"product/integrations/auths-custody/src/conformance.rs","sha256":"8ed1afd58f18fc6becc268908aa6419c9aa404c79da0197963eb2599df44acf6"},{"path":"product/integrations/auths-custody/src/key.rs","sha256":"70cbb0fd21b6f5652157845a22c35be2d0f6c05b3d138fc4b9bb6dbdc3d81c40"},{"path":"product/integrations/auths-custody/src/lib.rs","sha256":"8ee593c1f59b0fd2126bdda9138026f5bc531beb64d4489a99785842e7b98b43"},{"path":"product/operations/auths-operations/Cargo.toml","sha256":"73dde1e914ba5e1386f8d49c0d730423cc72ae77ec44c6554a6a75cc8e8922b1"},{"path":"product/operations/auths-operations/src/explanation.rs","sha256":"b4a39bcbd5712cb9e735ee7deeb281f3fa6af5ddca973735bf3d87dce427ef11"},{"path":"product/operations/auths-operations/src/lib.rs","sha256":"3f401a56555113b98f57bca172a2660eaecedf76247b83a3fdbb089c133a29cd"},{"path":"product/operations/auths-operations/src/render/json.rs","sha256":"2ae042639960afee123730e945d373bc5dda1d2b3af20ae16c939a7e99b9e418"},{"path":"product/operations/auths-operations/src/render/mod.rs","sha256":"b3b7f6fe473f49227ace5a68bfc3d8dc14b5db8dd9888fd9e207070337b1b8bf"},{"path":"product/operations/auths-operations/src/render/text.rs","sha256":"f216cf3bdb00e264523271b16e7059535ac6b1aabf271cebd7935af155e4bfec"},{"path":"product/policy/auths-bounded-policy/Cargo.toml","sha256":"babd5d200923137ead71d8c2528f847cea323ce98da942a1320b054436612c47"},{"path":"product/policy/auths-bounded-policy/src/arithmetic.rs","sha256":"75e43c5d4eab8d1f71c1daf53839f5f9fe45a400afc1f63a30c6f55ce3632627"},{"path":"product/policy/auths-bounded-policy/src/commitment.rs","sha256":"c5706f2d583454e1a7f570f7ada138d4d864bef0205dfae7c1296774f396bb3f"},{"path":"product/policy/auths-bounded-policy/src/eligibility.rs","sha256":"c9acdfb793074e687fc36efad506be27dbd99ffbf40387bc66c8de39ef238432"},{"path":"product/policy/auths-bounded-policy/src/identifier.rs","sha256":"0006a32bae9eb16c4178cf797df418d2b0a781f2bc6474b741dc1a908141831c"},{"path":"product/policy/auths-bounded-policy/src/kernel.rs","sha256":"99187c28b161ac70bee1afed60711f7f645adb4d1671a01863f9849b369811d5"},{"path":"product/policy/auths-bounded-policy/src/lib.rs","sha256":"76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c"},{"path":"product/policy/auths-bounded-policy/src/receipt.rs","sha256":"3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad"},{"path":"product/policy/auths-bounded-policy/src/registry.rs","sha256":"4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0"},{"path":"product/profiles/auths-profile-api/Cargo.toml","sha256":"7ae85761f58625b5d678f961fd052eebf3e000ef565c7312e3ac857763c0017f"},{"path":"product/profiles/auths-profile-api/src/lib.rs","sha256":"a194b82b20bf8aa864c2334ef6c6aec30b2154ded972862252d5dcefa488ab95"},{"path":"product/profiles/auths-profile-mcp/Cargo.toml","sha256":"db264fc25242f7b7e4133cbe5782545b3107b406c87168ae072683cfb59eac66"},{"path":"product/profiles/auths-profile-mcp/src/arguments.rs","sha256":"a5de696586d507e2aee4a49fee99ef1ef4c51a2e46603f8838f1af6d9009833f"},{"path":"product/profiles/auths-profile-mcp/src/lib.rs","sha256":"d0f8b733a09ef8408336cdebc8948d6a5861012ce6878598b11be7084dfd4280"},{"path":"product/profiles/auths-profile-mcp/src/session.rs","sha256":"166c281fa66333388e4760d6098dad02d3359e1d5de4b8f93312c014f97abb03"},{"path":"product/qualification/auths-recipe-qualification/Cargo.toml","sha256":"b7b15b30b9a3d96d4f089d514266d3a892de6608d30707aa44be31cca89ca9fe"},{"path":"product/qualification/auths-recipe-qualification/src/canonical.rs","sha256":"30a9b50777f0dcb4b606abfee2467d5a975d9f6ad941ab6c13ca3df5b359f667"},{"path":"product/qualification/auths-recipe-qualification/src/closure.rs","sha256":"0ad6aee9bd981e2863fa725f209ec84031db2ff12f4c7ac3aaf5120f0bb86039"},{"path":"product/qualification/auths-recipe-qualification/src/commissioning.rs","sha256":"db135c55e4e3079a73253ebae275536523eb36b545d1c152b4d7dce3c6b76828"},{"path":"product/qualification/auths-recipe-qualification/src/commissioning/tests.rs","sha256":"4dde3736d206099b1bea4c14e0092c6c1287d1af9065958777d7c54331dd8686"},{"path":"product/qualification/auths-recipe-qualification/src/error.rs","sha256":"52d5cf720a1e4579008fdda90a3ac2c31f0b8db57985f121f65e54b4da2b7dd1"},{"path":"product/qualification/auths-recipe-qualification/src/evidence.rs","sha256":"ba45a7409d67a8af26ab811af306412014557477a101ab2a8eb0faf8f2bd4b91"},{"path":"product/qualification/auths-recipe-qualification/src/ids.rs","sha256":"e81a906d571497ab2da753e1532d4443706410e0b75fdd59a7d2d788c7aec403"},{"path":"product/qualification/auths-recipe-qualification/src/launch.rs","sha256":"41f2e2de90e1e7d6440a66eda3eb9bea8d5e0741bc232305a76a363ab5f813c1"},{"path":"product/qualification/auths-recipe-qualification/src/lib.rs","sha256":"0e24b0f81191df0d078c7f4d73ced784ba9472372bfcdff3c7d0e2fb1687b323"},{"path":"product/qualification/auths-recipe-qualification/src/model.rs","sha256":"3484eb0ec287b23d4682ade7b1b0f8d1335985b3fb180f06fc28716076957d5f"},{"path":"product/qualification/auths-recipe-qualification/src/release.rs","sha256":"ec478e53f70052e566aac7e15be2f9e1b1cd46837ac6990ae955fa864d311586"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/mod.rs","sha256":"fa23a962fd90331152eed5edbcdf271955f7aed79b8da1e065bfe69a20b487a9"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/schemas.rs","sha256":"c59feec2805621f341a90f81fc005e2c12f7a70f9d264fdeacccb2be4fe1c046"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/verification.rs","sha256":"6a6b5834c5dae10af1ba8939b2deae43b85db71544dc8f077ff63b7fe68ac8a8"},{"path":"product/qualification/auths-recipe-qualification/src/verify.rs","sha256":"2ec2784435d11e07295de77b2ee1b2c48b2fcf9609a00454c6e7374b621aed5c"},{"path":"product/receipts/auths-receipts/Cargo.toml","sha256":"6001fa1375899953aafcb07c23a6da0c8f57ea7ec08bb9c950b12a60a8cc6f0f"},{"path":"product/receipts/auths-receipts/src/disclosure.rs","sha256":"ba9ed439be0a320c8a01f5b6e9b51361c1a37e076947490d8e4a484ba6bb119c"},{"path":"product/receipts/auths-receipts/src/lib.rs","sha256":"547a57c4160256719cafb7d0ab972d9fc80b0da14fbbce4148c70c414070ff36"},{"path":"product/runtime/auths-connections/Cargo.toml","sha256":"babeb6e1dda3dfb66291713ce1e43dce5c349833d0b50ea4dccbf986030026b2"},{"path":"product/runtime/auths-connections/src/credential.rs","sha256":"82921413bb053f0f6c7931fbd4e6a86c8cc1d8c6b51debd9c2cef33a8d5b1c51"},{"path":"product/runtime/auths-connections/src/kernel.rs","sha256":"a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8"},{"path":"product/runtime/auths-connections/src/lib.rs","sha256":"79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22"},{"path":"product/runtime/auths-connections/src/model.rs","sha256":"de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77"},{"path":"product/runtime/auths-connections/src/registry.rs","sha256":"e57640e003e72ad3235c567c2bb944a262bd64e673f023b62ea091094cc7e946"},{"path":"product/runtime/auths-gateway-kernel/Cargo.toml","sha256":"34f864e67656af4ac7e5c7a347a23f01fc8ab31365b8e23c0ef474483b14a183"},{"path":"product/runtime/auths-gateway-kernel/src/construct.rs","sha256":"e9d65744bae273d65face4285e5d2da75c06a92ab48f7b8333d496604e31c63c"},{"path":"product/runtime/auths-gateway-kernel/src/lib.rs","sha256":"cfda6f8453426564c085475f183b6f790b438768a19668f1b65d33ba59dc8632"},{"path":"product/runtime/auths-gateway-kernel/src/order.rs","sha256":"e0045f877c4b7fe3860c291039853885064ddcdebba7c9b345ab65e81e646dda"},{"path":"product/runtime/auths-gateway-kernel/src/outcome.rs","sha256":"e9785b1afe70788c89b51b18655bcd5acff7b0c8e3d12fb79c6f05a202e67e6b"},{"path":"product/runtime/auths-gateway-kernel/src/ratio.rs","sha256":"7ace22264812e6fc1ef3a62afee402cf43494bb71ae0d3de219ad1b39d690bcb"},{"path":"product/runtime/auths-gateway-kernel/src/recovery.rs","sha256":"9f46dcd1685ab6e4d1ba04a3fc286a9f3afee8fb47829be1fbc670a7926a2dc6"},{"path":"product/runtime/auths-gateway-kernel/src/transition.rs","sha256":"cefb8f01d915880f6921f2501ff881ad94b9de61072c34d9cd19220992f97374"},{"path":"product/runtime/auths-gateway/Cargo.toml","sha256":"00b28be86921dcdc0ad90cce0c62c2961cafefe96ea6c2edf0e926c3d405ccad"},{"path":"product/runtime/auths-gateway/src/admin.rs","sha256":"0dee40a9fb67c5de10142fc37a7bbabdd8979fb0199fb26caf4bdb024e0a5a40"},{"path":"product/runtime/auths-gateway/src/app.rs","sha256":"6f80f63833ea0815bb44fbf3b0cc54624a08e9fb578b035819f2980dc04e8256"},{"path":"product/runtime/auths-gateway/src/audit.rs","sha256":"0edb2037eb7b5d6f13acfce85c54f62a82bf7fdd31bc7e626c4fec183cef61dd"},{"path":"product/runtime/auths-gateway/src/audit_tests.rs","sha256":"990969384a52d75bc2489d9d412a9e7dd814bca1c8f65c701d6205fae62a15d5"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway-harness.rs","sha256":"12b0c24d36b2e6a3be392d3c081a783b355fdd67dc5b54bacc0410e803116b8c"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway.rs","sha256":"24d4224f03c680ee1fc3f3441cca8707fe002ce2c78588e8c337f2f150ea2e44"},{"path":"product/runtime/auths-gateway/src/binding.rs","sha256":"663b0ce878319511aa7d05722ab4ab2fa9be18817884ffb2ee9f131ff1e382d1"},{"path":"product/runtime/auths-gateway/src/bounds.rs","sha256":"38251ad6f22f9d07ef9a219c79fa265ca36f1526eca5f147d7efa46b52ad609d"},{"path":"product/runtime/auths-gateway/src/bounds_aggregate_tests.rs","sha256":"ab34f227b7c8692ba1da88ccb32bb3687a66adf8353d8282fae905d4a88eb612"},{"path":"product/runtime/auths-gateway/src/bounds_tests.rs","sha256":"74136bc570da7b9338b5a1a1ed9d3fd892c55135160964f9d3ac0e2cf5741375"},{"path":"product/runtime/auths-gateway/src/commissioning_budget.rs","sha256":"fab29da3269438cc62330f3eab7b5bd4dc482b4db8af243aae47df5d3aa1deb8"},{"path":"product/runtime/auths-gateway/src/commissioning_budget/tests.rs","sha256":"da104a1643c37515deec6397bca6db2054f2c9158ec3d230a1b1ec9c7d0f659f"},{"path":"product/runtime/auths-gateway/src/commissioning_floor.rs","sha256":"7fa6991c5ccd5ae1403be84b3da390323fab09f36e15ac01fd7a38ea350c6fdb"},{"path":"product/runtime/auths-gateway/src/commissioning_floor/tests.rs","sha256":"6b663d6e556adc0b455b81845bc4394d82c6c4de0c5f43e1310f3ddc6e4e40f7"},{"path":"product/runtime/auths-gateway/src/commissioning_session.rs","sha256":"24b48d5eaeaaa3c620e2dfc7ee1f9255fc4519a1eb404b8608cea7af6a910ee2"},{"path":"product/runtime/auths-gateway/src/commissioning_session/tests.rs","sha256":"703d8970d0b3c1d01516dea784ff690e33788861bf1ab34fbb1432cf0d21117a"},{"path":"product/runtime/auths-gateway/src/connection.rs","sha256":"7b5d049c258a26ed1c93ecf860f51d051a8a65f9b93554af0b1ea93862398ec9"},{"path":"product/runtime/auths-gateway/src/credential_journal.rs","sha256":"7297fccaee5cd8622928e8e0a42bba50da7941970a6f682ecd300c41ee6509da"},{"path":"product/runtime/auths-gateway/src/echo_verify.rs","sha256":"6d453051665f823abd7354d5c50031d9524cf47d6092d2f09080ae814e3b9575"},{"path":"product/runtime/auths-gateway/src/engine.rs","sha256":"1abff20b98bc894c45bfc5c4414c81a99966d1ec95d924a5b0cd6f4c5626ca24"},{"path":"product/runtime/auths-gateway/src/execution_witness.rs","sha256":"e8b1a8e41d5e3fa309760067849d390ef065feeb46701a83391832645a2f000c"},{"path":"product/runtime/auths-gateway/src/fuzzing.rs","sha256":"ed3b0028487eb546a3b0a91d115aa8f18bcea324b61620bfe8e35a9e6ab18758"},{"path":"product/runtime/auths-gateway/src/generation_floor.rs","sha256":"fe1510ec96ce0f67e9a78edbfa94b33eb7df64c0ac4d0a67901124dcd0164777"},{"path":"product/runtime/auths-gateway/src/harness.rs","sha256":"c87e479f3eb281960f6c9c80d43c7560d7ccb654b0154ec823d3fcec4884ac05"},{"path":"product/runtime/auths-gateway/src/lib.rs","sha256":"fad95d031f88072dd024c78facf0bb0267562b1ac743ddd7219fce47e64024f0"},{"path":"product/runtime/auths-gateway/src/listener.rs","sha256":"aa08239bcbc1fcb55e8a212fbdf6a84f12985b0d436dcb51dc58b06e59e435f2"},{"path":"product/runtime/auths-gateway/src/observed_tests.rs","sha256":"a22be071695f89ca2578a4d82fd80d9cb82289213c9bdb8f0470f6b2dc3d9201"},{"path":"product/runtime/auths-gateway/src/observer.rs","sha256":"562ffcaea071c3856e0708dc2fe33516917e145d2438aabb75af0a2b6ba01046"},{"path":"product/runtime/auths-gateway/src/onboarding.rs","sha256":"0dfd7d67e7f02f18a28d1c86ca1b7751d7463f5efcdbe3825de0ad8cbccb3891"},{"path":"product/runtime/auths-gateway/src/operator.rs","sha256":"c3c36954a3e86723df035b47f43b85fc8ab3a6292983522b6258d5c6b4e6c4e4"},{"path":"product/runtime/auths-gateway/src/pending_vectors/attempts.rs","sha256":"47ef3c8cb1c5504d47ae9a0088705ce6715fe86bac1671a34a56fb38a64d0dd3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/bounds.rs","sha256":"e612217307e1da5b0eb5ee6582a7458bb064b8aa8a529fc6555b1b334127ab68"},{"path":"product/runtime/auths-gateway/src/pending_vectors/codes.rs","sha256":"e00670a5ef24eb856cc2c6dcda8e5a263842f55c76bb939c0c27bd9df37e5522"},{"path":"product/runtime/auths-gateway/src/pending_vectors/keys.rs","sha256":"f84c56f2ea9cb34b2b79c72d13fbf2c6585010ec1ed450af58a78c80c1ea1edd"},{"path":"product/runtime/auths-gateway/src/pending_vectors/mod.rs","sha256":"5de8340f0ef71a0b57a09e323fefe473d3160c6ae952b9ba46f714825fbacafc"},{"path":"product/runtime/auths-gateway/src/pending_vectors/outcomes.rs","sha256":"8ec07b9511b48913af36ac999d2aa0e82924289f6acb23ddaeb9f00f99815166"},{"path":"product/runtime/auths-gateway/src/pending_vectors/production.rs","sha256":"772d032e0a0d9c924fb6d6c188528db85a97e71c9e466ddc19eee277baf83614"},{"path":"product/runtime/auths-gateway/src/pending_vectors/recipes.rs","sha256":"51693208270231c25c3aef2a32151d5962114c71e86b88cb9df83181c7af83d9"},{"path":"product/runtime/auths-gateway/src/pre_entry.rs","sha256":"06ea78ca140468bfaba17d9ab04912ad68673954c3203c98fed28272ff2a00c0"},{"path":"product/runtime/auths-gateway/src/property_tests.rs","sha256":"939c081e2e154aaf10186754044bdd65608932c899b970a04a71d0afaa999a93"},{"path":"product/runtime/auths-gateway/src/qualification.rs","sha256":"c597c83de2b94f0374ae54e40a8b57c2a64ec6e254704dca32185f448a908aca"},{"path":"product/runtime/auths-gateway/src/qualification_simulation.rs","sha256":"4ee7cadfb5f46a92713c80f3e55f499cb074d04d8b21ea89d57762af38642bfa"},{"path":"product/runtime/auths-gateway/src/qualification_tests.rs","sha256":"a9178a2e58eea459d5e5dafc53a3999ea7c84dbbffefe6e5eb1f3d098827f028"},{"path":"product/runtime/auths-gateway/src/quorum_tests.rs","sha256":"a78380b019104d688c11a4410082c7e08ded3106aab099954c4f8a1b4ae0fd89"},{"path":"product/runtime/auths-gateway/src/readiness.rs","sha256":"911c3f11892f94641574375e2da4c671c802738f71082f12c39832331052d43d"},{"path":"product/runtime/auths-gateway/src/recipe.rs","sha256":"fecf9af67e7afc48d080e9f8f55f8ce28e49d0e08988717a27908bbda461d6b6"},{"path":"product/runtime/auths-gateway/src/recipe/lower.rs","sha256":"8088b8751ed831dbb48247af953c6290ac95e2a438ccd5bd65eff54be06a1fd1"},{"path":"product/runtime/auths-gateway/src/recipe/review.rs","sha256":"c3eb7d9fdd98dacf52750b14b67ad7b7faaecbbdeafff1e0b049f67d0a2d0139"},{"path":"product/runtime/auths-gateway/src/recipe/runtime.rs","sha256":"c286f0d15f974402822c0810d8e97f98411dc1c557755cc23e540d85e2bb42d9"},{"path":"product/runtime/auths-gateway/src/recipe/source.rs","sha256":"1af50298fb1461e1b24cbdf560d43124d6b1c4c529586c911b1c4797214a69ff"},{"path":"product/runtime/auths-gateway/src/recipe/tests.rs","sha256":"aac551a2481bbc60864c64079bc667dcb232e45a0f41a04073ed84ab5dbe1fce"},{"path":"product/runtime/auths-gateway/src/recipe/validate.rs","sha256":"3711b17605cb7b0d639bc1b180449231f5882a306cab20e2c7782155cc63b0d4"},{"path":"product/runtime/auths-gateway/src/scenario_tests.rs","sha256":"025b53473b3af6900e03bc2fee91aa63ed26a8778bc8c8296fe08f5540794c39"},{"path":"product/runtime/auths-gateway/src/separation.rs","sha256":"be9306848ca5d801767cf6aa14247c8618312ef0e202f00ce0c24c4844491061"},{"path":"product/runtime/auths-gateway/src/simulation_attestation.rs","sha256":"88705e5d45415f760f1e3c3a065c35c48f4f4065bf7b3feb7882246983814d6f"},{"path":"product/runtime/auths-gateway/src/store.rs","sha256":"884bcad4d70d53e12eae9c8517f6ecd0643068ee0be0370015119d04d6cc2516"},{"path":"product/runtime/auths-gateway/src/store_testkit.rs","sha256":"88d82fee42f1b8ef521e8deef0216e938ebeaad822eb2f5020e70b89d145ea70"},{"path":"product/runtime/auths-gateway/src/submit.rs","sha256":"fe2eacb5ad8152eeecbd232c47a356fc72db0098e34fda99532bdf6ef0cf895c"},{"path":"product/runtime/auths-gateway/src/support.rs","sha256":"9fd979029793a22b15d9776a7fc172476fd7c126a80d4080c65d720845becbcb"},{"path":"product/runtime/auths-gateway/src/transport.rs","sha256":"978fc9fb34a33b3db265b5d1c3ce11696a5b9f08529e46dd2a1e7bb62afb9220"},{"path":"product/runtime/auths-kernel-runtime/Cargo.toml","sha256":"926bcd0053e5edd703be8f0027ad009e2982db013c8174c1366edbf38b48087d"},{"path":"product/runtime/auths-kernel-runtime/src/lib.rs","sha256":"7108faae9ca4bc32dc093ddaf885ac8f74f3c9b8d317b7c7d0ed00d1d0ab5972"},{"path":"product/runtime/auths-lifecycle/Cargo.toml","sha256":"c5053c705f8d5554b44e432fe75287a2faf11d644e5a2552e45ad6cd94176af5"},{"path":"product/runtime/auths-lifecycle/src/codec.rs","sha256":"51c4b746749150e8bfcd8ff972b3f6c1ef40bec15583448ec1b471d9ad737dc0"},{"path":"product/runtime/auths-lifecycle/src/digest.rs","sha256":"55282cd7d8aba37713c2dcb5357c9877819edb72a30eadefb860d28d7d3a3eb7"},{"path":"product/runtime/auths-lifecycle/src/identifier.rs","sha256":"31620e8c16de68d3d2d3b84d6353c1a5b9d4151d8247f91fa389b906a8e660f1"},{"path":"product/runtime/auths-lifecycle/src/kernel.rs","sha256":"2abb8c094b36d35b364e74d78091d14c5d6f3d1eb6552cca3b5538dbd017ce23"},{"path":"product/runtime/auths-lifecycle/src/lib.rs","sha256":"afe5a345cd309b5a4f08ffba3170a6d7f16ff914892b3f2006d5208ed24ec736"},{"path":"product/runtime/auths-lifecycle/src/model.rs","sha256":"1af12bbeeeaa65ec02ddcebd7d2c8c92ec1e339fa40ae85b45ab9b01a722a4fa"},{"path":"product/runtime/auths-lifecycle/src/operation.rs","sha256":"78e6d05fcf5d7ea4f148032a3fa26fdfcab77eb346019effe927b08e0d64d732"},{"path":"product/runtime/auths-lifecycle/src/registry.rs","sha256":"53495fe6f7a77422593a41623e28716f1c140dcc1e00f87f6b0ffbfb93a5ef90"},{"path":"product/runtime/auths-lifecycle/src/sealed.rs","sha256":"2e0c03b5813c926c159598bb7890d1523825edbe57cd687d42a5dfb3374a0c19"},{"path":"product/runtime/auths-lifecycle/src/test_support.rs","sha256":"221d9a5c5ef8e1f9f8fd66927484eaf813571d0568470278ecd8fa08a5eec8cd"},{"path":"product/runtime/auths-lifecycle/src/transition.rs","sha256":"011805a28efdd541f44ccea54dd0e34a1e58f4004447ee58013703b4fb6b2822"},{"path":"product/runtime/auths-runtime/Cargo.toml","sha256":"dd29d80a8b4bb56c869f036a6c9998f6e6d1c0383ac5dc03fa42b24abe2a7ff7"},{"path":"product/runtime/auths-runtime/src/lib.rs","sha256":"132ca03d58c14905d3a822a4972f42a22a5ad33a45f2ba9ca44f3a57d810b4b0"},{"path":"product/runtime/auths-runtime/src/production.rs","sha256":"fd4eff4270c571c10fcff6cf27df28961ebf074de8a1a028f500fda1ca376820"},{"path":"product/sdk/auths-approval-quorum/Cargo.toml","sha256":"df904971fca87a24194c5816738a331588fe8f164acb5d70839a35dca5f57114"},{"path":"product/sdk/auths-approval-quorum/src/lib.rs","sha256":"72e4086088a1c0912e4e1a9e980f26a5c280bf5ab16ea39c9f0f58d5096ac2ce"},{"path":"product/sdk/auths-approval-quorum/src/remote.rs","sha256":"9fa029c7c63003adf260f8aec55160c545681c60c1bace0d934e7525862aac7b"},{"path":"product/sdk/auths-approval-quorum/src/remote_tests.rs","sha256":"8a09ce17cfee82a035a74edd535f3ebeb3db0e078784740d3997b17dbdb10197"},{"path":"product/sdk/auths-approval-quorum/src/tests.rs","sha256":"0acbf12be3e497dcc6c2d8f29c9af3b1a7ed8e11b75f6399570d4f217a785060"},{"path":"product/stores/auths-stores/Cargo.toml","sha256":"a32c4b76d17b264be5d40d24497ff237e1ed87822e8bab86229b3db93106dbe3"},{"path":"product/stores/auths-stores/src/gateway_attempt.rs","sha256":"218841602d3d9b23b44625f50e5b54cf275ccedc2d5c89f02d2482b8524472af"},{"path":"product/stores/auths-stores/src/lib.rs","sha256":"e721262edf8a9ab5568ddc27639176312d4a366203b5f73e2d7c11fde2c554e9"},{"path":"product/stores/auths-stores/src/lifecycle.rs","sha256":"3f2cecfda13fdcd7c4a944518646bcc8abd1237f900c0332d5822281f8f9f1cd"}],"schema":"auths.gateway-semantic-closure/1"} \ No newline at end of file +{"files":[{"path":"Cargo.lock","sha256":"0e75e2fdef44e79e57797ac6661295ae58ddb8de4a1990a6fd22ce6c54f78604"},{"path":"Cargo.toml","sha256":"6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24"},{"path":"core/adapters/auths-did-keri/Cargo.toml","sha256":"86ba3e3f9a0a70d970568bfb3113b7ba7bbdd81c3eebbb52743dd574a0c0ecaa"},{"path":"core/adapters/auths-did-keri/src/lib.rs","sha256":"a75674842f8a7142004369ccd206ab43e476459293f0ff4bed4d4e659031b3e3"},{"path":"core/adapters/auths-did-key/Cargo.toml","sha256":"d5a3ae07ecde83f91eed4c3785051dd0f44eab6c891754f3309b6b40596707d7"},{"path":"core/adapters/auths-did-key/src/lib.rs","sha256":"b76a3f4528a725df53cfa9242e6e414e1d26caa48468aaed497e28b121f4497c"},{"path":"core/adapters/auths-raw-key/Cargo.toml","sha256":"f49616bc18c19e6aaa7e6a02ccebcdb9f5c1422c1278ef9869e0dbf22ceda7be"},{"path":"core/adapters/auths-raw-key/src/lib.rs","sha256":"45eec1b295dac3bed65cd79c942870b926b06b3f5d38eaebaeb6140ac69315fa"},{"path":"core/crates/auths-algebra-kernel/Cargo.toml","sha256":"0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba"},{"path":"core/crates/auths-algebra-kernel/src/generated.rs","sha256":"ae4bcbef42a408c7ffa0c6a74a42f7de177a6f14479e51d205acf830bda05960"},{"path":"core/crates/auths-algebra-kernel/src/lib.rs","sha256":"6654667eeb9b353d6648954c9fd2e8838462a82ce6b2803eb49e1366892c68c6"},{"path":"core/crates/auths-assurance/Cargo.toml","sha256":"afcb12a97ddd09d7a264b9ecd3fcaefc865ff2c9b4539ee85b00883420ba333a"},{"path":"core/crates/auths-assurance/src/lib.rs","sha256":"0fb2ec844d674b25a9e20b1601452c89c2454901fa506adfa9bb38ef9a7fa213"},{"path":"core/crates/auths-author/Cargo.toml","sha256":"1e6f0e3bc079ddb558decf0db26b291c6e72fc47327b6df1b7650d41689b215f"},{"path":"core/crates/auths-author/src/lib.rs","sha256":"e14475f2f49715a1869d5fa6b11ff1fbb72497e39097e09f833b0bae7e5b3f2b"},{"path":"core/crates/auths-author/src/observations.rs","sha256":"dda7d6bfa6f4bd7e95a480ca283c2c0e996f69c5c15cb0c7197af328131a7066"},{"path":"core/crates/auths-authority/Cargo.toml","sha256":"4f68212938029f79ebd857b4f3038494eb85d0163d49f07e51376715cf959815"},{"path":"core/crates/auths-authority/src/lib.rs","sha256":"da88d5194de4e17449e69972c0fb042afa3c39798a8f570f30771e77c384f1eb"},{"path":"core/crates/auths-codec/Cargo.toml","sha256":"e20e51826e17814effd9d8925d18d5fbdd6c0d37bf50231e743ec2611314722c"},{"path":"core/crates/auths-codec/src/approval.rs","sha256":"fbff43bf4d57f69f8b7738a8647751cde75c5a932dee65d924a1fe9c7202f91f"},{"path":"core/crates/auths-codec/src/bounded_policy.rs","sha256":"d21f6728be2d8a04b6d94921f2b683f7e61cbb42e0ac6866f1c88a49caa534c3"},{"path":"core/crates/auths-codec/src/decode.rs","sha256":"ba2999584cdf53b1b517ecb9c7ea50d39efee17c666a9a38e2ad1ac94379f778"},{"path":"core/crates/auths-codec/src/encode.rs","sha256":"8491192053e2e15d62b4d2a491de22405b7487ead69ab6f6bca40669ce7ca5f7"},{"path":"core/crates/auths-codec/src/error.rs","sha256":"fecb0737c16deb42d859f1dc7727c698438d9ac12064fd99e0024629642c390c"},{"path":"core/crates/auths-codec/src/hash.rs","sha256":"f88e111f1dbb2cef6b7b5e9c948cb45ff92e366710c8a5f5c636138aa748479e"},{"path":"core/crates/auths-codec/src/lib.rs","sha256":"3b0e5c94c6f34f750b88a9333e1d5c8145746d845d3a23e0d2f61807cf592ea7"},{"path":"core/crates/auths-codec/src/observation.rs","sha256":"38328b0c71ff97a4196eeade8b4faa889527ff1f80bb168468bcd49082a3987e"},{"path":"core/crates/auths-composition/Cargo.toml","sha256":"331e13025eb82588b5269ed3975929eb41c823d588c49e4c296273d85c6fe80e"},{"path":"core/crates/auths-composition/src/lib.rs","sha256":"e42e3b0b6a9985b73c533aeb23799c638979aa27a9ce7d0f10a8d60340570fb1"},{"path":"core/crates/auths-model/Cargo.toml","sha256":"565c15302b0cc9270db1e28efa3862804846850ba933cc17aea8abcec4a65987"},{"path":"core/crates/auths-model/src/approval.rs","sha256":"54cf44a9ef747ec21546a4086aecfb130bc7803b0d646430e6082df51e6e305f"},{"path":"core/crates/auths-model/src/bounded.rs","sha256":"f90496abc0a06c028b4d850af6ddab7d850bfafeaa3d042f1b1246a41d8bbbc9"},{"path":"core/crates/auths-model/src/bounded_policy.rs","sha256":"306a8f049cc7cfc7635fe0e4de47eb7813eed63d3c14c3be2b51586aa4eea450"},{"path":"core/crates/auths-model/src/lib.rs","sha256":"e7cfe6bb9574c6b016aa63e70658c31e0b90903ec6479a49f4a2ceb64f5bad97"},{"path":"core/crates/auths-model/src/observation.rs","sha256":"b3ed3e3cc090afca2896a7d3de7988afccc1ee1ea0ebd91b51a8bc0f20ad8dbb"},{"path":"core/crates/auths-multikey/Cargo.toml","sha256":"858756c1197befcada06134742bffe8d58cf674cadd6c046bf710570e96efaf2"},{"path":"core/crates/auths-multikey/src/lib.rs","sha256":"f5177fffb11e40eeaaa665ba886c541fc1f24d5eacdd6983fb03dc20148733f0"},{"path":"core/crates/auths-ports/Cargo.toml","sha256":"596a9b0f5af3717c16a6d13f7054d8a106bcd9f01f5f72c2235dd2afcf0ab16c"},{"path":"core/crates/auths-ports/src/binding.rs","sha256":"a16c012d40aa4249e3ec54372b9611006d0bfe8c7dc3c741911c2194ad17736d"},{"path":"core/crates/auths-ports/src/diagnostics.rs","sha256":"aa596572503b5a65a918bb2ff38281c144ff53821ee914e9325c852828d852df"},{"path":"core/crates/auths-ports/src/lib.rs","sha256":"8da1debf86f9532df0660155d04298beb1ba3a1204508f8586e2e67cd2fb3449"},{"path":"core/crates/auths-ports/src/path.rs","sha256":"b68fc547b4e4d97a60cbbc1cc1939fc6b34a8233b81f840bd396914a707e3ea1"},{"path":"core/crates/auths-raw-key-core/Cargo.toml","sha256":"98c0bc8527a537512e43a74dd6ba9658c6f0cdc16610cf938e3f9b43785d836d"},{"path":"core/crates/auths-raw-key-core/src/lib.rs","sha256":"98c0500c41697aae28708ad0bf970b9a97583d96a3d2c18d23e7fa351e0f7d12"},{"path":"core/crates/auths-registries/Cargo.toml","sha256":"590e49e58b0622d9d6274fea46796dcdb07dec9550eff295cce6a6427ffa51e2"},{"path":"core/crates/auths-registries/src/lib.rs","sha256":"450d3886d85ee333b7e046317fb5b47cde62483d5f3e41d46265e2caf4c373ec"},{"path":"core/crates/auths-registries/src/template.rs","sha256":"1224039dd2b3ce6fa8357613d8cafbae40400493da7176da202b9ade62fa05e4"},{"path":"core/crates/auths-signature-core/Cargo.toml","sha256":"6bee2230eb30af1be0bd5c2d57bd3e1903497a70028d47290d4ac6e9e0e8bca0"},{"path":"core/crates/auths-signature-core/src/lib.rs","sha256":"6e3f9311ded5e49ea50d445eb21e6d8fa12442aa4362a73e0cb6fda15b7cd865"},{"path":"core/crates/auths-signature/Cargo.toml","sha256":"7f7b5682466ba439d8c59579022cb61068cad9fb4bd2d73e1cc21327c902b450"},{"path":"core/crates/auths-signature/src/lib.rs","sha256":"b3d9ac4cc3ba0797b9e1c09f2d6ac05089b25dac4e285a5af28c0165b33d925b"},{"path":"core/crates/auths-verifier/Cargo.toml","sha256":"c43358e06a33324b41a8b93e5cc7279c55f7d21f1f6cfaa539a3fc7b4c27a38f"},{"path":"core/crates/auths-verifier/src/approval.rs","sha256":"c3cae6a49e169051eb555bb092b1069a4d422516d6a2114623a89e5f31ff923f"},{"path":"core/crates/auths-verifier/src/causal.rs","sha256":"9635230f33b13a263573d319ac8a1976addbcc07677514a43e3c7bf28dc04587"},{"path":"core/crates/auths-verifier/src/lib.rs","sha256":"f22dec38dfa47ced8da4f605390da8453273bee1da010f57fd1fdfcb10e0b389"},{"path":"core/crates/auths-verifier/src/observation.rs","sha256":"0bb07f06a0f9524c88427df1c972b1de8ba038a9eeeb15d3134c25125ae84b1e"},{"path":"core/crates/auths-verifier/src/trace.rs","sha256":"2213d72023a1d9e0413a2cf2c51c3dad9e04775d86033a0caaa9d29a8f0036f8"},{"path":"exchange/crates/auths-proof-exchange-model/Cargo.toml","sha256":"34b2db64f93a288e942b5a3918d28cdcbef906e0dc9074ce848018d3d5f7a1fa"},{"path":"exchange/crates/auths-proof-exchange-model/src/lib.rs","sha256":"49fac5aff2339d3a57c41cb8bb2a82852538e8f77ecc4b157c88e264ff31fb55"},{"path":"exchange/crates/auths-proof-exchange-port/Cargo.toml","sha256":"7ff660f1b7579dc570c791090aeb450404fbbf44c92781e289f5ccdde746d739"},{"path":"exchange/crates/auths-proof-exchange-port/src/lib.rs","sha256":"b408fb40c6432edc1facb3d8b3e9433a033f8dc73fe2e0ba5a88c972ca675021"},{"path":"product/config/auths-config/Cargo.toml","sha256":"e4b568ab9f6d84f7d7e6d66443fe825f360db9c27bc7c31d6ddc0647ba3ab304"},{"path":"product/config/auths-config/src/lib.rs","sha256":"fecf00ea65cef9018fda9af2063326d7065b869266d0d9e73a4f06816f1102cc"},{"path":"product/errors/auths-errors/Cargo.toml","sha256":"3b3a199b6460ba75bda84475bb5accd35e1485448a3981038db85bf4772dd350"},{"path":"product/errors/auths-errors/src/lib.rs","sha256":"7feeb9069fa4003f94f1f07c1c94619cf1c883e0dbaaf2187f04d0f742264bdd"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/Cargo.toml","sha256":"716f1f2a117d6d69d8effe9ee9057e24ba3502f20af6a602b06facb638cdabed"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/api.rs","sha256":"9ea61dd7ddd93282b073b98e453e6b75b26dc49689c04e9782435d06a3a09e48"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/clock.rs","sha256":"73f0a6e0f5903883329fa6683f5888288f759512ac69e5c87efd2b6b87f7d79f"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/http.rs","sha256":"14c1fce14e24c984b2a275563a29b6326fb08367922b6e8d37ba38b9cb81aa2b"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/identity.rs","sha256":"186de11230c8b33375951c4368609f8976bf9795f171af3fd7fac26207a94361"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs","sha256":"0b4617d044f5254a5ab22f5a2578f91cc025206a8c1845be39c1c56dcdf7a5df"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/names.rs","sha256":"41bb23572d6002e23ee103d6fe70ecd68764861c6f2e48a1c53af998270a4afa"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs","sha256":"39fed883f4802e68d3b41a68fea0aba0737810996b33d13577de70faba004c29"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/store.rs","sha256":"fc60ee9c49b2f4f063c449b4c78100c5c4872779e94ca168f796603b380ef6e4"},{"path":"product/integrations/auths-custody/Cargo.toml","sha256":"1e14034185ad1ec24a977fd5f41d0abee219606245c046ce2a82287fadef448b"},{"path":"product/integrations/auths-custody/src/conformance.rs","sha256":"8ed1afd58f18fc6becc268908aa6419c9aa404c79da0197963eb2599df44acf6"},{"path":"product/integrations/auths-custody/src/key.rs","sha256":"70cbb0fd21b6f5652157845a22c35be2d0f6c05b3d138fc4b9bb6dbdc3d81c40"},{"path":"product/integrations/auths-custody/src/lib.rs","sha256":"8ee593c1f59b0fd2126bdda9138026f5bc531beb64d4489a99785842e7b98b43"},{"path":"product/operations/auths-operations/Cargo.toml","sha256":"73dde1e914ba5e1386f8d49c0d730423cc72ae77ec44c6554a6a75cc8e8922b1"},{"path":"product/operations/auths-operations/src/explanation.rs","sha256":"b4a39bcbd5712cb9e735ee7deeb281f3fa6af5ddca973735bf3d87dce427ef11"},{"path":"product/operations/auths-operations/src/lib.rs","sha256":"3f401a56555113b98f57bca172a2660eaecedf76247b83a3fdbb089c133a29cd"},{"path":"product/operations/auths-operations/src/render/json.rs","sha256":"2ae042639960afee123730e945d373bc5dda1d2b3af20ae16c939a7e99b9e418"},{"path":"product/operations/auths-operations/src/render/mod.rs","sha256":"b3b7f6fe473f49227ace5a68bfc3d8dc14b5db8dd9888fd9e207070337b1b8bf"},{"path":"product/operations/auths-operations/src/render/text.rs","sha256":"f216cf3bdb00e264523271b16e7059535ac6b1aabf271cebd7935af155e4bfec"},{"path":"product/policy/auths-bounded-policy/Cargo.toml","sha256":"babd5d200923137ead71d8c2528f847cea323ce98da942a1320b054436612c47"},{"path":"product/policy/auths-bounded-policy/src/arithmetic.rs","sha256":"75e43c5d4eab8d1f71c1daf53839f5f9fe45a400afc1f63a30c6f55ce3632627"},{"path":"product/policy/auths-bounded-policy/src/commitment.rs","sha256":"c5706f2d583454e1a7f570f7ada138d4d864bef0205dfae7c1296774f396bb3f"},{"path":"product/policy/auths-bounded-policy/src/eligibility.rs","sha256":"c9acdfb793074e687fc36efad506be27dbd99ffbf40387bc66c8de39ef238432"},{"path":"product/policy/auths-bounded-policy/src/identifier.rs","sha256":"0006a32bae9eb16c4178cf797df418d2b0a781f2bc6474b741dc1a908141831c"},{"path":"product/policy/auths-bounded-policy/src/kernel.rs","sha256":"99187c28b161ac70bee1afed60711f7f645adb4d1671a01863f9849b369811d5"},{"path":"product/policy/auths-bounded-policy/src/lib.rs","sha256":"76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c"},{"path":"product/policy/auths-bounded-policy/src/receipt.rs","sha256":"3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad"},{"path":"product/policy/auths-bounded-policy/src/registry.rs","sha256":"4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0"},{"path":"product/profiles/auths-profile-api/Cargo.toml","sha256":"7ae85761f58625b5d678f961fd052eebf3e000ef565c7312e3ac857763c0017f"},{"path":"product/profiles/auths-profile-api/src/lib.rs","sha256":"a194b82b20bf8aa864c2334ef6c6aec30b2154ded972862252d5dcefa488ab95"},{"path":"product/profiles/auths-profile-mcp/Cargo.toml","sha256":"db264fc25242f7b7e4133cbe5782545b3107b406c87168ae072683cfb59eac66"},{"path":"product/profiles/auths-profile-mcp/src/arguments.rs","sha256":"a5de696586d507e2aee4a49fee99ef1ef4c51a2e46603f8838f1af6d9009833f"},{"path":"product/profiles/auths-profile-mcp/src/lib.rs","sha256":"d0f8b733a09ef8408336cdebc8948d6a5861012ce6878598b11be7084dfd4280"},{"path":"product/profiles/auths-profile-mcp/src/session.rs","sha256":"166c281fa66333388e4760d6098dad02d3359e1d5de4b8f93312c014f97abb03"},{"path":"product/qualification/auths-recipe-qualification/Cargo.toml","sha256":"b7b15b30b9a3d96d4f089d514266d3a892de6608d30707aa44be31cca89ca9fe"},{"path":"product/qualification/auths-recipe-qualification/src/canonical.rs","sha256":"30a9b50777f0dcb4b606abfee2467d5a975d9f6ad941ab6c13ca3df5b359f667"},{"path":"product/qualification/auths-recipe-qualification/src/closure.rs","sha256":"0ad6aee9bd981e2863fa725f209ec84031db2ff12f4c7ac3aaf5120f0bb86039"},{"path":"product/qualification/auths-recipe-qualification/src/commissioning.rs","sha256":"db135c55e4e3079a73253ebae275536523eb36b545d1c152b4d7dce3c6b76828"},{"path":"product/qualification/auths-recipe-qualification/src/commissioning/tests.rs","sha256":"4dde3736d206099b1bea4c14e0092c6c1287d1af9065958777d7c54331dd8686"},{"path":"product/qualification/auths-recipe-qualification/src/error.rs","sha256":"52d5cf720a1e4579008fdda90a3ac2c31f0b8db57985f121f65e54b4da2b7dd1"},{"path":"product/qualification/auths-recipe-qualification/src/evidence.rs","sha256":"ba45a7409d67a8af26ab811af306412014557477a101ab2a8eb0faf8f2bd4b91"},{"path":"product/qualification/auths-recipe-qualification/src/ids.rs","sha256":"e81a906d571497ab2da753e1532d4443706410e0b75fdd59a7d2d788c7aec403"},{"path":"product/qualification/auths-recipe-qualification/src/launch.rs","sha256":"41f2e2de90e1e7d6440a66eda3eb9bea8d5e0741bc232305a76a363ab5f813c1"},{"path":"product/qualification/auths-recipe-qualification/src/lib.rs","sha256":"0e24b0f81191df0d078c7f4d73ced784ba9472372bfcdff3c7d0e2fb1687b323"},{"path":"product/qualification/auths-recipe-qualification/src/model.rs","sha256":"3484eb0ec287b23d4682ade7b1b0f8d1335985b3fb180f06fc28716076957d5f"},{"path":"product/qualification/auths-recipe-qualification/src/release.rs","sha256":"ec478e53f70052e566aac7e15be2f9e1b1cd46837ac6990ae955fa864d311586"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/mod.rs","sha256":"fa23a962fd90331152eed5edbcdf271955f7aed79b8da1e065bfe69a20b487a9"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/schemas.rs","sha256":"c59feec2805621f341a90f81fc005e2c12f7a70f9d264fdeacccb2be4fe1c046"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/verification.rs","sha256":"bdf5746fed4d10a7f577f7878619a917d29aa8b7d522f00d9f774e53eff4c8c1"},{"path":"product/qualification/auths-recipe-qualification/src/verify.rs","sha256":"2ec2784435d11e07295de77b2ee1b2c48b2fcf9609a00454c6e7374b621aed5c"},{"path":"product/receipts/auths-receipts/Cargo.toml","sha256":"6001fa1375899953aafcb07c23a6da0c8f57ea7ec08bb9c950b12a60a8cc6f0f"},{"path":"product/receipts/auths-receipts/src/disclosure.rs","sha256":"ba9ed439be0a320c8a01f5b6e9b51361c1a37e076947490d8e4a484ba6bb119c"},{"path":"product/receipts/auths-receipts/src/lib.rs","sha256":"547a57c4160256719cafb7d0ab972d9fc80b0da14fbbce4148c70c414070ff36"},{"path":"product/runtime/auths-connections/Cargo.toml","sha256":"babeb6e1dda3dfb66291713ce1e43dce5c349833d0b50ea4dccbf986030026b2"},{"path":"product/runtime/auths-connections/src/credential.rs","sha256":"82921413bb053f0f6c7931fbd4e6a86c8cc1d8c6b51debd9c2cef33a8d5b1c51"},{"path":"product/runtime/auths-connections/src/kernel.rs","sha256":"a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8"},{"path":"product/runtime/auths-connections/src/lib.rs","sha256":"79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22"},{"path":"product/runtime/auths-connections/src/model.rs","sha256":"de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77"},{"path":"product/runtime/auths-connections/src/registry.rs","sha256":"e57640e003e72ad3235c567c2bb944a262bd64e673f023b62ea091094cc7e946"},{"path":"product/runtime/auths-gateway-kernel/Cargo.toml","sha256":"34f864e67656af4ac7e5c7a347a23f01fc8ab31365b8e23c0ef474483b14a183"},{"path":"product/runtime/auths-gateway-kernel/src/construct.rs","sha256":"e9d65744bae273d65face4285e5d2da75c06a92ab48f7b8333d496604e31c63c"},{"path":"product/runtime/auths-gateway-kernel/src/lib.rs","sha256":"cfda6f8453426564c085475f183b6f790b438768a19668f1b65d33ba59dc8632"},{"path":"product/runtime/auths-gateway-kernel/src/order.rs","sha256":"e0045f877c4b7fe3860c291039853885064ddcdebba7c9b345ab65e81e646dda"},{"path":"product/runtime/auths-gateway-kernel/src/outcome.rs","sha256":"e9785b1afe70788c89b51b18655bcd5acff7b0c8e3d12fb79c6f05a202e67e6b"},{"path":"product/runtime/auths-gateway-kernel/src/ratio.rs","sha256":"7ace22264812e6fc1ef3a62afee402cf43494bb71ae0d3de219ad1b39d690bcb"},{"path":"product/runtime/auths-gateway-kernel/src/recovery.rs","sha256":"9f46dcd1685ab6e4d1ba04a3fc286a9f3afee8fb47829be1fbc670a7926a2dc6"},{"path":"product/runtime/auths-gateway-kernel/src/transition.rs","sha256":"cefb8f01d915880f6921f2501ff881ad94b9de61072c34d9cd19220992f97374"},{"path":"product/runtime/auths-gateway/Cargo.toml","sha256":"00b28be86921dcdc0ad90cce0c62c2961cafefe96ea6c2edf0e926c3d405ccad"},{"path":"product/runtime/auths-gateway/src/admin.rs","sha256":"0dee40a9fb67c5de10142fc37a7bbabdd8979fb0199fb26caf4bdb024e0a5a40"},{"path":"product/runtime/auths-gateway/src/app.rs","sha256":"6f80f63833ea0815bb44fbf3b0cc54624a08e9fb578b035819f2980dc04e8256"},{"path":"product/runtime/auths-gateway/src/audit.rs","sha256":"0edb2037eb7b5d6f13acfce85c54f62a82bf7fdd31bc7e626c4fec183cef61dd"},{"path":"product/runtime/auths-gateway/src/audit_tests.rs","sha256":"990969384a52d75bc2489d9d412a9e7dd814bca1c8f65c701d6205fae62a15d5"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway-harness.rs","sha256":"12b0c24d36b2e6a3be392d3c081a783b355fdd67dc5b54bacc0410e803116b8c"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway.rs","sha256":"77a041ac461704a4e61e24c704eb63e7bc1499d5a54a9b282e133ff5099696ba"},{"path":"product/runtime/auths-gateway/src/binding.rs","sha256":"663b0ce878319511aa7d05722ab4ab2fa9be18817884ffb2ee9f131ff1e382d1"},{"path":"product/runtime/auths-gateway/src/bounds.rs","sha256":"38251ad6f22f9d07ef9a219c79fa265ca36f1526eca5f147d7efa46b52ad609d"},{"path":"product/runtime/auths-gateway/src/bounds_aggregate_tests.rs","sha256":"ab34f227b7c8692ba1da88ccb32bb3687a66adf8353d8282fae905d4a88eb612"},{"path":"product/runtime/auths-gateway/src/bounds_tests.rs","sha256":"74136bc570da7b9338b5a1a1ed9d3fd892c55135160964f9d3ac0e2cf5741375"},{"path":"product/runtime/auths-gateway/src/commissioning_budget.rs","sha256":"fab29da3269438cc62330f3eab7b5bd4dc482b4db8af243aae47df5d3aa1deb8"},{"path":"product/runtime/auths-gateway/src/commissioning_budget/tests.rs","sha256":"da104a1643c37515deec6397bca6db2054f2c9158ec3d230a1b1ec9c7d0f659f"},{"path":"product/runtime/auths-gateway/src/commissioning_floor.rs","sha256":"7fa6991c5ccd5ae1403be84b3da390323fab09f36e15ac01fd7a38ea350c6fdb"},{"path":"product/runtime/auths-gateway/src/commissioning_floor/tests.rs","sha256":"6b663d6e556adc0b455b81845bc4394d82c6c4de0c5f43e1310f3ddc6e4e40f7"},{"path":"product/runtime/auths-gateway/src/commissioning_session.rs","sha256":"24b48d5eaeaaa3c620e2dfc7ee1f9255fc4519a1eb404b8608cea7af6a910ee2"},{"path":"product/runtime/auths-gateway/src/commissioning_session/tests.rs","sha256":"37a097fc8a9261d3fffdaef3f905f40b22e3e6601bb5101fadd9414f963c0824"},{"path":"product/runtime/auths-gateway/src/connection.rs","sha256":"7b5d049c258a26ed1c93ecf860f51d051a8a65f9b93554af0b1ea93862398ec9"},{"path":"product/runtime/auths-gateway/src/credential_journal.rs","sha256":"7297fccaee5cd8622928e8e0a42bba50da7941970a6f682ecd300c41ee6509da"},{"path":"product/runtime/auths-gateway/src/echo_verify.rs","sha256":"6d453051665f823abd7354d5c50031d9524cf47d6092d2f09080ae814e3b9575"},{"path":"product/runtime/auths-gateway/src/engine.rs","sha256":"1abff20b98bc894c45bfc5c4414c81a99966d1ec95d924a5b0cd6f4c5626ca24"},{"path":"product/runtime/auths-gateway/src/execution_witness.rs","sha256":"e8b1a8e41d5e3fa309760067849d390ef065feeb46701a83391832645a2f000c"},{"path":"product/runtime/auths-gateway/src/fuzzing.rs","sha256":"ed3b0028487eb546a3b0a91d115aa8f18bcea324b61620bfe8e35a9e6ab18758"},{"path":"product/runtime/auths-gateway/src/generation_floor.rs","sha256":"fe1510ec96ce0f67e9a78edbfa94b33eb7df64c0ac4d0a67901124dcd0164777"},{"path":"product/runtime/auths-gateway/src/harness.rs","sha256":"c87e479f3eb281960f6c9c80d43c7560d7ccb654b0154ec823d3fcec4884ac05"},{"path":"product/runtime/auths-gateway/src/lib.rs","sha256":"fad95d031f88072dd024c78facf0bb0267562b1ac743ddd7219fce47e64024f0"},{"path":"product/runtime/auths-gateway/src/listener.rs","sha256":"aa08239bcbc1fcb55e8a212fbdf6a84f12985b0d436dcb51dc58b06e59e435f2"},{"path":"product/runtime/auths-gateway/src/observed_tests.rs","sha256":"a22be071695f89ca2578a4d82fd80d9cb82289213c9bdb8f0470f6b2dc3d9201"},{"path":"product/runtime/auths-gateway/src/observer.rs","sha256":"562ffcaea071c3856e0708dc2fe33516917e145d2438aabb75af0a2b6ba01046"},{"path":"product/runtime/auths-gateway/src/onboarding.rs","sha256":"0dfd7d67e7f02f18a28d1c86ca1b7751d7463f5efcdbe3825de0ad8cbccb3891"},{"path":"product/runtime/auths-gateway/src/operator.rs","sha256":"c3c36954a3e86723df035b47f43b85fc8ab3a6292983522b6258d5c6b4e6c4e4"},{"path":"product/runtime/auths-gateway/src/pending_vectors/attempts.rs","sha256":"47ef3c8cb1c5504d47ae9a0088705ce6715fe86bac1671a34a56fb38a64d0dd3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/bounds.rs","sha256":"e612217307e1da5b0eb5ee6582a7458bb064b8aa8a529fc6555b1b334127ab68"},{"path":"product/runtime/auths-gateway/src/pending_vectors/codes.rs","sha256":"e00670a5ef24eb856cc2c6dcda8e5a263842f55c76bb939c0c27bd9df37e5522"},{"path":"product/runtime/auths-gateway/src/pending_vectors/keys.rs","sha256":"f84c56f2ea9cb34b2b79c72d13fbf2c6585010ec1ed450af58a78c80c1ea1edd"},{"path":"product/runtime/auths-gateway/src/pending_vectors/mod.rs","sha256":"5de8340f0ef71a0b57a09e323fefe473d3160c6ae952b9ba46f714825fbacafc"},{"path":"product/runtime/auths-gateway/src/pending_vectors/outcomes.rs","sha256":"8ec07b9511b48913af36ac999d2aa0e82924289f6acb23ddaeb9f00f99815166"},{"path":"product/runtime/auths-gateway/src/pending_vectors/production.rs","sha256":"772d032e0a0d9c924fb6d6c188528db85a97e71c9e466ddc19eee277baf83614"},{"path":"product/runtime/auths-gateway/src/pending_vectors/recipes.rs","sha256":"51693208270231c25c3aef2a32151d5962114c71e86b88cb9df83181c7af83d9"},{"path":"product/runtime/auths-gateway/src/pre_entry.rs","sha256":"06ea78ca140468bfaba17d9ab04912ad68673954c3203c98fed28272ff2a00c0"},{"path":"product/runtime/auths-gateway/src/property_tests.rs","sha256":"939c081e2e154aaf10186754044bdd65608932c899b970a04a71d0afaa999a93"},{"path":"product/runtime/auths-gateway/src/qualification.rs","sha256":"c597c83de2b94f0374ae54e40a8b57c2a64ec6e254704dca32185f448a908aca"},{"path":"product/runtime/auths-gateway/src/qualification_simulation.rs","sha256":"4ee7cadfb5f46a92713c80f3e55f499cb074d04d8b21ea89d57762af38642bfa"},{"path":"product/runtime/auths-gateway/src/qualification_tests.rs","sha256":"a9178a2e58eea459d5e5dafc53a3999ea7c84dbbffefe6e5eb1f3d098827f028"},{"path":"product/runtime/auths-gateway/src/quorum_tests.rs","sha256":"a78380b019104d688c11a4410082c7e08ded3106aab099954c4f8a1b4ae0fd89"},{"path":"product/runtime/auths-gateway/src/readiness.rs","sha256":"911c3f11892f94641574375e2da4c671c802738f71082f12c39832331052d43d"},{"path":"product/runtime/auths-gateway/src/recipe.rs","sha256":"fecf9af67e7afc48d080e9f8f55f8ce28e49d0e08988717a27908bbda461d6b6"},{"path":"product/runtime/auths-gateway/src/recipe/lower.rs","sha256":"8088b8751ed831dbb48247af953c6290ac95e2a438ccd5bd65eff54be06a1fd1"},{"path":"product/runtime/auths-gateway/src/recipe/review.rs","sha256":"c3eb7d9fdd98dacf52750b14b67ad7b7faaecbbdeafff1e0b049f67d0a2d0139"},{"path":"product/runtime/auths-gateway/src/recipe/runtime.rs","sha256":"c286f0d15f974402822c0810d8e97f98411dc1c557755cc23e540d85e2bb42d9"},{"path":"product/runtime/auths-gateway/src/recipe/source.rs","sha256":"1af50298fb1461e1b24cbdf560d43124d6b1c4c529586c911b1c4797214a69ff"},{"path":"product/runtime/auths-gateway/src/recipe/tests.rs","sha256":"aac551a2481bbc60864c64079bc667dcb232e45a0f41a04073ed84ab5dbe1fce"},{"path":"product/runtime/auths-gateway/src/recipe/validate.rs","sha256":"3711b17605cb7b0d639bc1b180449231f5882a306cab20e2c7782155cc63b0d4"},{"path":"product/runtime/auths-gateway/src/scenario_tests.rs","sha256":"025b53473b3af6900e03bc2fee91aa63ed26a8778bc8c8296fe08f5540794c39"},{"path":"product/runtime/auths-gateway/src/separation.rs","sha256":"be9306848ca5d801767cf6aa14247c8618312ef0e202f00ce0c24c4844491061"},{"path":"product/runtime/auths-gateway/src/simulation_attestation.rs","sha256":"88705e5d45415f760f1e3c3a065c35c48f4f4065bf7b3feb7882246983814d6f"},{"path":"product/runtime/auths-gateway/src/store.rs","sha256":"884bcad4d70d53e12eae9c8517f6ecd0643068ee0be0370015119d04d6cc2516"},{"path":"product/runtime/auths-gateway/src/store_testkit.rs","sha256":"88d82fee42f1b8ef521e8deef0216e938ebeaad822eb2f5020e70b89d145ea70"},{"path":"product/runtime/auths-gateway/src/submit.rs","sha256":"fe2eacb5ad8152eeecbd232c47a356fc72db0098e34fda99532bdf6ef0cf895c"},{"path":"product/runtime/auths-gateway/src/support.rs","sha256":"9fd979029793a22b15d9776a7fc172476fd7c126a80d4080c65d720845becbcb"},{"path":"product/runtime/auths-gateway/src/transport.rs","sha256":"978fc9fb34a33b3db265b5d1c3ce11696a5b9f08529e46dd2a1e7bb62afb9220"},{"path":"product/runtime/auths-kernel-runtime/Cargo.toml","sha256":"926bcd0053e5edd703be8f0027ad009e2982db013c8174c1366edbf38b48087d"},{"path":"product/runtime/auths-kernel-runtime/src/lib.rs","sha256":"7108faae9ca4bc32dc093ddaf885ac8f74f3c9b8d317b7c7d0ed00d1d0ab5972"},{"path":"product/runtime/auths-lifecycle/Cargo.toml","sha256":"c5053c705f8d5554b44e432fe75287a2faf11d644e5a2552e45ad6cd94176af5"},{"path":"product/runtime/auths-lifecycle/src/codec.rs","sha256":"51c4b746749150e8bfcd8ff972b3f6c1ef40bec15583448ec1b471d9ad737dc0"},{"path":"product/runtime/auths-lifecycle/src/digest.rs","sha256":"55282cd7d8aba37713c2dcb5357c9877819edb72a30eadefb860d28d7d3a3eb7"},{"path":"product/runtime/auths-lifecycle/src/identifier.rs","sha256":"31620e8c16de68d3d2d3b84d6353c1a5b9d4151d8247f91fa389b906a8e660f1"},{"path":"product/runtime/auths-lifecycle/src/kernel.rs","sha256":"2abb8c094b36d35b364e74d78091d14c5d6f3d1eb6552cca3b5538dbd017ce23"},{"path":"product/runtime/auths-lifecycle/src/lib.rs","sha256":"afe5a345cd309b5a4f08ffba3170a6d7f16ff914892b3f2006d5208ed24ec736"},{"path":"product/runtime/auths-lifecycle/src/model.rs","sha256":"1af12bbeeeaa65ec02ddcebd7d2c8c92ec1e339fa40ae85b45ab9b01a722a4fa"},{"path":"product/runtime/auths-lifecycle/src/operation.rs","sha256":"78e6d05fcf5d7ea4f148032a3fa26fdfcab77eb346019effe927b08e0d64d732"},{"path":"product/runtime/auths-lifecycle/src/registry.rs","sha256":"53495fe6f7a77422593a41623e28716f1c140dcc1e00f87f6b0ffbfb93a5ef90"},{"path":"product/runtime/auths-lifecycle/src/sealed.rs","sha256":"2e0c03b5813c926c159598bb7890d1523825edbe57cd687d42a5dfb3374a0c19"},{"path":"product/runtime/auths-lifecycle/src/test_support.rs","sha256":"221d9a5c5ef8e1f9f8fd66927484eaf813571d0568470278ecd8fa08a5eec8cd"},{"path":"product/runtime/auths-lifecycle/src/transition.rs","sha256":"011805a28efdd541f44ccea54dd0e34a1e58f4004447ee58013703b4fb6b2822"},{"path":"product/runtime/auths-runtime/Cargo.toml","sha256":"dd29d80a8b4bb56c869f036a6c9998f6e6d1c0383ac5dc03fa42b24abe2a7ff7"},{"path":"product/runtime/auths-runtime/src/lib.rs","sha256":"132ca03d58c14905d3a822a4972f42a22a5ad33a45f2ba9ca44f3a57d810b4b0"},{"path":"product/runtime/auths-runtime/src/production.rs","sha256":"fd4eff4270c571c10fcff6cf27df28961ebf074de8a1a028f500fda1ca376820"},{"path":"product/sdk/auths-approval-quorum/Cargo.toml","sha256":"df904971fca87a24194c5816738a331588fe8f164acb5d70839a35dca5f57114"},{"path":"product/sdk/auths-approval-quorum/src/lib.rs","sha256":"72e4086088a1c0912e4e1a9e980f26a5c280bf5ab16ea39c9f0f58d5096ac2ce"},{"path":"product/sdk/auths-approval-quorum/src/remote.rs","sha256":"9fa029c7c63003adf260f8aec55160c545681c60c1bace0d934e7525862aac7b"},{"path":"product/sdk/auths-approval-quorum/src/remote_tests.rs","sha256":"8a09ce17cfee82a035a74edd535f3ebeb3db0e078784740d3997b17dbdb10197"},{"path":"product/sdk/auths-approval-quorum/src/tests.rs","sha256":"0acbf12be3e497dcc6c2d8f29c9af3b1a7ed8e11b75f6399570d4f217a785060"},{"path":"product/stores/auths-stores/Cargo.toml","sha256":"a32c4b76d17b264be5d40d24497ff237e1ed87822e8bab86229b3db93106dbe3"},{"path":"product/stores/auths-stores/src/gateway_attempt.rs","sha256":"218841602d3d9b23b44625f50e5b54cf275ccedc2d5c89f02d2482b8524472af"},{"path":"product/stores/auths-stores/src/lib.rs","sha256":"e721262edf8a9ab5568ddc27639176312d4a366203b5f73e2d7c11fde2c554e9"},{"path":"product/stores/auths-stores/src/lifecycle.rs","sha256":"3f2cecfda13fdcd7c4a944518646bcc8abd1237f900c0332d5822281f8f9f1cd"}],"schema":"auths.gateway-semantic-closure/1"} \ No newline at end of file diff --git a/product/runtime/auths-gateway/src/bin/auths-gateway.rs b/product/runtime/auths-gateway/src/bin/auths-gateway.rs index a03f7601d..5d05fc0d8 100644 --- a/product/runtime/auths-gateway/src/bin/auths-gateway.rs +++ b/product/runtime/auths-gateway/src/bin/auths-gateway.rs @@ -401,6 +401,10 @@ mod unix { proof: PathBuf, #[arg(long)] action: PathBuf, + /// Optional new owner-private file of bounded, secret-free counter + /// snapshots. Read-only diagnostics; never a remote effect claim. + #[arg(long)] + witness_file: Option, }, /// Write a redacted archive for a support request: versions, /// digests, closed states, stable codes, and the digest and stage of @@ -2667,10 +2671,91 @@ mod unix { .map_err(|error| Failure::at(code, socket, error)) } + /// A bounded diagnostic stream. Opening refuses an existing file or a + /// shared directory before submission; a subsequent recording failure + /// must never cancel a submission that may have entered a provider write. + struct CommissioningWitnessFile { + file: File, + last: Option, + frames: usize, + } + + impl CommissioningWitnessFile { + fn open(path: &Path) -> Result { + let parent = path + .parent() + .filter(|_| path.is_absolute() && path.file_name().is_some()) + .ok_or("gateway.commissioning.unsafe-witness-file")?; + check_private_directory(parent) + .map_err(|_| "gateway.commissioning.unsafe-witness-file")?; + if path + .components() + .any(|part| !matches!(part, Component::RootDir | Component::Normal(_))) + { + return Err("gateway.commissioning.unsafe-witness-file"); + } + let file = OpenOptions::new() + .write(true) + .create_new(true) + .mode(0o600) + .custom_flags(i32::from_ne_bytes( + rustix::fs::OFlags::NOFOLLOW.bits().to_ne_bytes(), + )) + .open(path) + .map_err(|_| "gateway.commissioning.unsafe-witness-file")?; + let metadata = file + .metadata() + .map_err(|_| "gateway.commissioning.unsafe-witness-file")?; + if !metadata.is_file() + || metadata.uid() != rustix::process::geteuid().as_raw() + || metadata.nlink() != 1 + || metadata.permissions().mode() & 0o077 != 0 + { + return Err("gateway.commissioning.unsafe-witness-file"); + } + Ok(Self { + file, + last: None, + frames: 0, + }) + } + + fn record( + &mut self, + snapshot: auths_gateway::GatewayExecutionWitness, + ) -> Result<(), &'static str> { + if self.last.as_ref() == Some(&snapshot) { + return Ok(()); + } + if self.frames >= 256 { + return Err("gateway.commissioning.witness-limit"); + } + let mut bytes = serde_json::to_vec(&snapshot) + .map_err(|_| "gateway.commissioning.witness-unavailable")?; + if bytes.len() >= 1024 { + return Err("gateway.commissioning.witness-limit"); + } + bytes.push(b'\n'); + self.file + .write_all(&bytes) + .map_err(|_| "gateway.commissioning.witness-unavailable")?; + self.frames += 1; + self.last = Some(snapshot); + Ok(()) + } + + fn finish(&self) -> Result<(), &'static str> { + self.file + .sync_all() + .map_err(|_| "gateway.commissioning.witness-unavailable") + } + } + /// Direct operator process; ordinary application handlers never call this. async fn commissioning( options: &CommissioningOptions, command: Option<(&Path, &Path)>, + witness_file: Option<&Path>, ) -> Result<(), Failure> { use auths_recipe_qualification::{ BoundedText, COMMISSIONING_PERMIT_FILE, CommissioningInputs, @@ -2726,7 +2811,34 @@ mod unix { let proof = read_bounded(proof, 4 * 1024 * 1024)?; let action = read_bounded(action, 64 * 1024)?; let before = engine.execution_witness(); - let result = session.submit(&proof, &action).await; + let mut witness = witness_file + .map(CommissioningWitnessFile::open) + .transpose()?; + if let Some(witness) = &mut witness { + witness.record(before.clone())?; + } + let submission = session.submit(&proof, &action); + tokio::pin!(submission); + let mut interval = tokio::time::interval(Duration::from_millis(10)); + interval.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip); + let mut diagnostic_failure = None; + let result = loop { + tokio::select! { + result = &mut submission => break result, + _ = interval.tick(), if witness.is_some() && diagnostic_failure.is_none() => { + if let Some(witness) = &mut witness { + diagnostic_failure = witness.record(engine.execution_witness()).err(); + } + } + } + }; + if let Some(witness) = &mut witness { + // Even a full or broken stream cannot interrupt an entered + // attempt. Report diagnostic failure only after it finishes. + let final_record = witness.record(engine.execution_witness()); + diagnostic_failure = diagnostic_failure.or(final_record.err()); + diagnostic_failure = diagnostic_failure.or(witness.finish().err()); + } let measured = serde_json::json!({ "schema": "auths.gateway-commissioning-execution/1", "result": result, @@ -2738,6 +2850,9 @@ mod unix { serde_json::to_string(&measured) .map_err(|_| "gateway.submit.invalid-response")? ); + if let Some(code) = diagnostic_failure { + return Err(code.into()); + } } } Ok(()) @@ -3531,12 +3646,13 @@ mod unix { ); Ok(()) } - Command::CommissioningInit { session } => commissioning(&session, None).await, + Command::CommissioningInit { session } => commissioning(&session, None, None).await, Command::CommissioningSubmit { session, proof, action, - } => commissioning(&session, Some((&proof, &action))).await, + witness_file, + } => commissioning(&session, Some((&proof, &action)), witness_file.as_deref()).await, #[cfg(feature = "loopback-provider")] Command::Serve { state_dir, @@ -3842,6 +3958,72 @@ mod unix { mod tests { use super::*; + #[test] + fn commissioning_witness_refuses_shared_existing_and_linked_outputs() { + let directory = tempfile::tempdir().expect("private output"); + let parent = fs::canonicalize(directory.path()).expect("canonical output"); + let path = parent.join("counters.jsonl"); + fs::set_permissions(&parent, fs::Permissions::from_mode(0o755)).expect("shared"); + assert!(CommissioningWitnessFile::open(&path).is_err()); + assert!(!path.exists()); + fs::set_permissions(&parent, fs::Permissions::from_mode(0o700)).expect("private"); + fs::write(&path, b"retain existing output").expect("existing"); + assert!(CommissioningWitnessFile::open(&path).is_err()); + assert_eq!( + fs::read(&path).expect("retained"), + b"retain existing output" + ); + let link = parent.join("linked.jsonl"); + std::os::unix::fs::symlink(&path, &link).expect("symbolic link"); + assert!(CommissioningWitnessFile::open(&link).is_err()); + assert!(CommissioningWitnessFile::open(Path::new("relative.jsonl")).is_err()); + } + + #[test] + fn commissioning_witness_bounds_changed_counter_frames_without_secret_fields() { + let directory = tempfile::tempdir().expect("private output"); + let parent = fs::canonicalize(directory.path()).expect("canonical output"); + fs::set_permissions(&parent, fs::Permissions::from_mode(0o700)).expect("private"); + let path = parent.join("counters.jsonl"); + let mut stream = CommissioningWitnessFile::open(&path).expect("new output"); + let mut snapshot = auths_gateway::GatewayExecutionWitness { + schema: "auths.gateway-execution-witness/1".to_owned(), + scope: "00112233445566778899aabbccddeeff".to_owned(), + credential_lease_calls: 0, + write_transport_entries: 0, + read_transport_entries: 0, + }; + for reads in 0..256 { + snapshot.read_transport_entries = reads; + stream.record(snapshot.clone()).expect("changed snapshot"); + stream.record(snapshot.clone()).expect("duplicate omitted"); + } + snapshot.read_transport_entries = 256; + assert_eq!( + stream.record(snapshot), + Err("gateway.commissioning.witness-limit") + ); + stream.finish().expect("finished output"); + let bytes = fs::read(&path).expect("counter frames"); + assert!(bytes.len() <= 256 * 1024); + let lines = bytes + .split(|byte| *byte == b'\n') + .filter(|line| !line.is_empty()); + let snapshots: Vec = lines + .map(|line| serde_json::from_slice(line).expect("closed typed snapshot")) + .collect(); + assert_eq!(snapshots.len(), 256); + assert!(snapshots.iter().enumerate().all(|(index, snapshot)| { + snapshot.read_transport_entries == index as u64 + && snapshot.credential_lease_calls == 0 + && snapshot.write_transport_entries == 0 + })); + assert_eq!( + fs::metadata(path).expect("mode").permissions().mode() & 0o777, + 0o600 + ); + } + #[test] fn candidate_identity_needs_no_installation_and_binds_the_running_bytes() { let directory = tempfile::tempdir().expect("candidate input"); diff --git a/product/runtime/auths-gateway/src/commissioning_session/tests.rs b/product/runtime/auths-gateway/src/commissioning_session/tests.rs index b0ea654ae..0a27f81ac 100644 --- a/product/runtime/auths-gateway/src/commissioning_session/tests.rs +++ b/product/runtime/auths-gateway/src/commissioning_session/tests.rs @@ -44,7 +44,7 @@ async fn offline_review_verifies_exact_actors_and_requests_without_custody() { setup.permit.body().statement.binding.allowed_actions[0].to_hex() ); let serialized = serde_json::to_value(&reviewed).expect("public projection"); - assert_eq!(serialized["request"]["method"], "POST"); + assert_eq!(serialized["request"]["method"], "PATCH"); assert!( serialized["request"]["headers"] .as_array() diff --git a/product/runtime/auths-gateway/src/semantic_closure.rs b/product/runtime/auths-gateway/src/semantic_closure.rs index 197519d69..ffef9763a 100644 --- a/product/runtime/auths-gateway/src/semantic_closure.rs +++ b/product/runtime/auths-gateway/src/semantic_closure.rs @@ -10,7 +10,7 @@ /// SHA-256 of the schema, a NUL byte, and `semantic-closure.json`. /// Regenerate through `semantic_closure_is_current` with `AUTHS_UPDATE_FIXTURES=1`. pub const GATEWAY_SEMANTIC_CLOSURE_SHA256: &str = - "454aa47752e69f8642445ffa744f1a5dcf5ae130cbbe9c5b911f359049502a3d"; + "a5ac19cd47f7e6b2c9c6b537a923756e8592784b11e4642e3f46915c84ae9974"; #[cfg(test)] mod tests { diff --git a/qualification/README.md b/qualification/README.md index fdda016e7..0fb69b21c 100644 --- a/qualification/README.md +++ b/qualification/README.md @@ -122,9 +122,11 @@ prints its planned production `tuple.json` through `qualification-candidate`, without custody or provider access; the release tool checks the declared contract ID against `contract.json`. `prepare-live` installs production custody for the disposable resources and compares `qualification-status --tuple` with that planned tuple before any -permit import or submission. A changed installation fails closed. `run/live.sh` always calls `cleanup`, including after setup or stage -failure; cleanup must remove disposable resources idempotently, and its failure -fails the run. Both setup commands receive `AUTHS_GATEWAY` and +permit import or submission. A changed installation fails closed. The whole +`run/resource-session.sh` journey calls `cleanup`, including after setup or +stage failure; individual phase runners retain resources for the next phase. +Cleanup must remove disposable resources idempotently, and its failure fails +the run. Both setup commands receive `AUTHS_GATEWAY` and `AUTHS_QUALIFICATION`. Only the protected live environment supplies `AUTHS_QUALIFICATION_PROVIDER_CREDENTIAL`. @@ -248,6 +250,14 @@ Neither is a claim that a provider received or performed a mutation. Reads, including credential probes, are counted separately. First qualification must still independently read back the reviewed disposable resource. +The optional private `commissioning-submit --witness-file` names a new file in +an existing owner-private directory. During submission it appends only changed +typed counter snapshots, at most 256 frames of 1 KiB each; it never contains +proofs, actions, credentials or provider responses. Ten-millisecond sampling +is diagnostic and may skip intermediate states. A recording failure is +reported only after the native attempt completes, so it cannot cancel an +entered write. This stream adds no pause, fault injection or execution authority. + ### Fresh evidence comparisons Every corpus step declares `evidence_comparison`: `static`, diff --git a/release/semantic-freeze-versions.toml b/release/semantic-freeze-versions.toml index 6c2307406..a6a0b3109 100644 --- a/release/semantic-freeze-versions.toml +++ b/release/semantic-freeze-versions.toml @@ -1,4 +1,4 @@ -freeze_version = 380 +freeze_version = 381 # Semantic identity counters live outside the xtask source tree deliberately. # The formal source closure binds xtask's executable code, while the semantic @@ -67,4 +67,4 @@ freeze_version = 380 "auths.product.vocabulary" = 24 "auths.release.benchmark-contract" = 1 "auths.release.evolution-contract" = 79 -"auths.release.public-surface" = 380 +"auths.release.public-surface" = 381 diff --git a/release/semantic-freeze.json b/release/semantic-freeze.json index fc7bd096d..d0d58155c 100644 --- a/release/semantic-freeze.json +++ b/release/semantic-freeze.json @@ -1,6 +1,6 @@ { "schema": "auths.semantic-freeze/1", - "freezeVersion": 380, + "freezeVersion": 381, "publicSurface": { "rustRoots": [ "auths", @@ -1011,7 +1011,7 @@ }, { "id": "auths.release.public-surface", - "version": 380, + "version": 381, "classification": "release-metadata", "categories": [ "package-names", @@ -1104,7 +1104,7 @@ "xtask/src/release_launch.rs", "xtask/src/semantic_freeze.rs" ], - "sha256": "3a4379a19742b90206425ce79719bfaf6386a7d0948a38c5ab16f58daf029a07" + "sha256": "840bd445df50aeece21207fa9d5533005b7d62af14ff623ccdb6320902a57672" } ] } From c7d837b32b760e5115e9dc4eefc41fef3ac0f9de Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 12:56:13 +0100 Subject: [PATCH 078/108] Bind qualification packet pools and measured provider observations --- compliance.toml | 8 +- ...d-qualification-commissioning-authority.md | 8 + ...NDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md | 2 + .../tests/commissioning.rs | 4 + .../auths-gateway/semantic-closure.json | 2 +- .../auths-gateway/src/bin/auths-gateway.rs | 71 +++++---- .../auths-gateway/src/semantic_closure.rs | 2 +- qualification/reference/README.md | 26 +++- qualification/reference/check_packets.py | 3 +- qualification/reference/check_socket.py | 3 +- qualification/reference/expand.py | 10 +- qualification/reference/native_observation.py | 137 ++++++++++++++++++ qualification/reference/packet_plan.py | 44 +++++- qualification/reference/stripe_platform.py | 21 ++- .../tests/test_native_observation.py | 112 ++++++++++++++ qualification/reference/tests/test_packets.py | 56 ++++++- .../reference/tests/test_reference.py | 42 ++++-- release/semantic-freeze-versions.toml | 8 +- release/semantic-freeze.json | 14 +- 19 files changed, 500 insertions(+), 73 deletions(-) create mode 100644 qualification/reference/native_observation.py create mode 100644 qualification/reference/tests/test_native_observation.py diff --git a/compliance.toml b/compliance.toml index c6bceae0a..c9673c0bc 100644 --- a/compliance.toml +++ b/compliance.toml @@ -1600,14 +1600,14 @@ kind = "cargo" layer = "product" path = "product/runtime/auths-gateway" core_apis = ["auths-author", "auths-codec", "auths-did-keri", "auths-did-key", "auths-model", "auths-multikey", "auths-ports", "auths-raw-key", "auths-raw-key-core", "auths-registries", "auths-signature", "auths-verifier"] -protocol_versions = ["auths.gateway-commissioning-budget/1", "auths.qualification-commissioning-permit/2", "auths.qualification-commissioning-budget-key/1", "auths.qualification-commissioning-budget-binding/2", "auths.gateway-credential-journal/1", "auths.gateway-credential-collection/1", "auths.gateway-readiness/1", "auths.gateway-support-bundle/1", "auths.gateway-generation-floor/1", "auths.gateway-emergency-stop/1", "auths.gateway-installation/5", "auths.recipe-qualification/1", "auths.recipe-qualification-attestation/1", "auths.qualification-trust-root/1", "auths.qualification-signer-certificate/1", "auths.qualification-revocation-list/1", "auths.qualification-release-index/1", "auths.gateway-semantic-closure/1", "auths.qualification-verification-vectors/1", "auths.gateway-operator-attestation/1", "auths.gateway-admin-request/1", "auths.gateway-admin-response/1", "auths.gateway-connection/1", "auths.provider-connection/2", "auths.gateway-key-identity/1", "auths.lifecycle.transactional-store/4", "auths.gateway-recipe-source/2", "auths.gateway-compiled-recipe/2", "auths.gateway-recipe-review/2", "auths.gateway-recovery-capability/1", "auths.gateway-connection-descriptor/1", "auths.gateway-attempt/3", "auths.gateway-pre-entry/1", "auths.lifecycle.postgresql/6", "auths.gateway-echo/1", "auths.gateway-idempotency-key/1", "auths.gateway-observe/2", "auths.gateway-outcome/2", "auths.gateway-readback/1", "auths.self-hosted-profile-lock/1", "mcp-arguments-v1", "auths.gateway-audit-bundle/2", "auths.gateway-audit-report/3", "auths.gateway-counter-set/1", "auths.gateway-echo-verification/1", "auths.gateway-codes/1", "auths.gateway-production-codes/1", "auths.gateway-custody-vectors/1", "auths.gateway-outcome-vectors/1", "bounded-policy-commitment-v1", "auths.approval-response/1", "auths.gateway-bounded-count/2", "auths.gateway-bounded-sum/1", "auths.gateway.argument-ceiling-window-count/2", "auths.gateway.argument-ceiling-policy/2"] -wire_objects = ["CommissioningBudgetSnapshot", "CompiledRecipe", "ClosedProviderRequest", "ClosedCredentialReads", "RecipeReview", "RecoveryCapability", "GatewayAttemptSnapshot", "GatewayPreEntry", "GatewayRecordEntry", "GatewayConnectionDescriptor", "ConnectionRecord", "OperatorAttestation", "OperatorStatement", "GatewayAdminStatus", "GatewayEvidenceSummary", "GatewayObserveRequest", "GatewayObserveResult", "GatewayProviderEvidence", "GatewaySubmitResult", "SignedObservation", "ArgumentCeilingPolicy", "BoundedPolicyCommitment", "AuditReport", "ProviderResult", "AuditedPreEntry", "EchoVerification", "AdminRequestCommand", "ListedValues"] +protocol_versions = ["auths.gateway-execution-witness/1", "auths.gateway-commissioning-execution/1", "auths.gateway-commissioning-budget/1", "auths.qualification-commissioning-permit/2", "auths.qualification-commissioning-budget-key/1", "auths.qualification-commissioning-budget-binding/2", "auths.gateway-credential-journal/1", "auths.gateway-credential-collection/1", "auths.gateway-readiness/1", "auths.gateway-support-bundle/1", "auths.gateway-generation-floor/1", "auths.gateway-emergency-stop/1", "auths.gateway-installation/5", "auths.recipe-qualification/1", "auths.recipe-qualification-attestation/1", "auths.qualification-trust-root/1", "auths.qualification-signer-certificate/1", "auths.qualification-revocation-list/1", "auths.qualification-release-index/1", "auths.gateway-semantic-closure/1", "auths.qualification-verification-vectors/1", "auths.gateway-operator-attestation/1", "auths.gateway-admin-request/1", "auths.gateway-admin-response/1", "auths.gateway-connection/1", "auths.provider-connection/2", "auths.gateway-key-identity/1", "auths.lifecycle.transactional-store/4", "auths.gateway-recipe-source/2", "auths.gateway-compiled-recipe/2", "auths.gateway-recipe-review/2", "auths.gateway-recovery-capability/1", "auths.gateway-connection-descriptor/1", "auths.gateway-attempt/3", "auths.gateway-pre-entry/1", "auths.lifecycle.postgresql/6", "auths.gateway-echo/1", "auths.gateway-idempotency-key/1", "auths.gateway-observe/2", "auths.gateway-outcome/2", "auths.gateway-readback/1", "auths.self-hosted-profile-lock/1", "mcp-arguments-v1", "auths.gateway-audit-bundle/2", "auths.gateway-audit-report/3", "auths.gateway-counter-set/1", "auths.gateway-echo-verification/1", "auths.gateway-codes/1", "auths.gateway-production-codes/1", "auths.gateway-custody-vectors/1", "auths.gateway-outcome-vectors/1", "bounded-policy-commitment-v1", "auths.approval-response/1", "auths.gateway-bounded-count/2", "auths.gateway-bounded-sum/1", "auths.gateway.argument-ceiling-window-count/2", "auths.gateway.argument-ceiling-policy/2"] +wire_objects = ["GatewayExecutionWitness", "CommissioningBudgetSnapshot", "CompiledRecipe", "ClosedProviderRequest", "ClosedCredentialReads", "RecipeReview", "RecoveryCapability", "GatewayAttemptSnapshot", "GatewayPreEntry", "GatewayRecordEntry", "GatewayConnectionDescriptor", "ConnectionRecord", "OperatorAttestation", "OperatorStatement", "GatewayAdminStatus", "GatewayEvidenceSummary", "GatewayObserveRequest", "GatewayObserveResult", "GatewayProviderEvidence", "GatewaySubmitResult", "SignedObservation", "ArgumentCeilingPolicy", "BoundedPolicyCommitment", "AuditReport", "ProviderResult", "AuditedPreEntry", "EchoVerification", "AdminRequestCommand", "ListedValues"] fixture_suites = ["bindings/fixtures/approval", "bindings/fixtures/gateway", "bindings/fixtures/qualification"] principal_families = ["raw-key-v1", "did-key-v1", "did-keri-v1"] signature_families = ["ed25519-v1", "p256-sha256-v1"] profiles = ["auths.mcp/2"] transports = ["bounded-https", "postgresql-tls", "loopback-http-development"] -configuration_inputs = ["commissioning-binding", "commissioning-permit", "retained-commissioning-budget-floor", "operator-approved-recipe", "profile-lock", "independently-provisioned-trust", "connection-binding", "observer-anchor", "observer-signing-key", "deployment-kind", "operator-attestation", "app-capacity", "development-shared-file-store", "postgresql-store-configuration", "audit-trust-and-observer-pins", "qualification-policy", "recipe-family", "provider-contract-id", "qualification-release-inputs", "deployment-clock"] +configuration_inputs = ["commissioning-witness-file", "commissioning-binding", "commissioning-permit", "retained-commissioning-budget-floor", "operator-approved-recipe", "profile-lock", "independently-provisioned-trust", "connection-binding", "observer-anchor", "observer-signing-key", "deployment-kind", "operator-attestation", "app-capacity", "development-shared-file-store", "postgresql-store-configuration", "audit-trust-and-observer-pins", "qualification-policy", "recipe-family", "provider-contract-id", "qualification-release-inputs", "deployment-clock"] security_state = ["permanent-commissioning-consumption", "commissioning-revocation-and-time-floor", "durable-credential-cleanup-notes", "host-generation-floor", "recipe-digest", "logical-operation-claims", "credential-reference-generation", "shared-connection-record", "credential-generation", "in-flight-entry-count", "echo-bound-provider-evidence", "observer-signing-seed", "custody-held-observer-key", "principal-separation", "key-identity-separation", "pre-entry-evidence", "relative-ceiling-basis", "gateway-record-batches", "link-subject-count-and-sum-slots", "verified-qualification-index", "remembered-revocations", "accepted-revocation-sequence", "gateway-semantic-closure"] [packages.auths-gateway.claims] @@ -1776,6 +1776,8 @@ stateful-replay-budget-component = [ "product/runtime/auths-gateway/src/commissioning_session/tests.rs#ordinary_submission_cannot_select_commissioning_authority", "product/runtime/auths-gateway/src/commissioning_session/tests.rs#offline_review_verifies_exact_actors_and_requests_without_custody", "product/runtime/auths-gateway/src/commissioning_session/tests.rs#execution_witness_measures_custody_calls_even_when_a_charged_call_fails", + "product/runtime/auths-gateway/src/bin/auths-gateway.rs#commissioning_witness_refuses_shared_existing_and_linked_outputs", + "product/runtime/auths-gateway/src/bin/auths-gateway.rs#commissioning_witness_bounds_changed_counter_frames_without_secret_fields", "product/runtime/auths-gateway/src/commissioning_session/tests.rs#exact_native_actor_and_action_require_a_durable_unit_before_custody", "product/runtime/auths-gateway/src/commissioning_session/tests.rs#absent_registration_and_expiry_after_preparation_never_lease", "product/runtime/auths-gateway/src/commissioning_session/tests.rs#another_signed_actor_or_action_is_refused_before_custody", diff --git a/docs/adr/0016-bounded-qualification-commissioning-authority.md b/docs/adr/0016-bounded-qualification-commissioning-authority.md index 41f67ee76..427067a8b 100644 --- a/docs/adr/0016-bounded-qualification-commissioning-authority.md +++ b/docs/adr/0016-bounded-qualification-commissioning-authority.md @@ -52,6 +52,14 @@ Every permit must bind: - a signed validity window of at most two hours, current signer certification and a current root-signed revocation list. +The reviewed finite pool may include exact provider-read refusal probes. The +Stripe platform reference includes an amount above the relative ceiling and +a currency mismatch; both proofs are native-valid and both require the real +guard's post-lease refusal with zero write entries. The permit never replaces +that guard or grants a callback. Signing reconstructs the entire source pool; +an additional action, changed probe or omitted/reordered packet refuses. Each +probe consumes the same finite credential budget as a successful submission. + Resource acquisition, action authoring and independent oracle expansion happen before permit issuance. Expected request/evidence commitments are derived from the reviewed reference and bounded resource binding, not candidate answers. diff --git a/docs/research/INDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md b/docs/research/INDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md index 9af6a5002..32af3e95a 100644 --- a/docs/research/INDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md +++ b/docs/research/INDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md @@ -24,6 +24,8 @@ audit or real-user trial is claimed. | A dedicated author UID could not launch the SDK beneath the hosted runner's private temporary ancestors. | The hosted author job failed. A Docker reproduction confirmed the private-parent launcher refusal and then passed with public-readable copied SDK inputs. CI now copies only the credential-free kit and installed wheel environment to `/opt`; author output remains owner-private under `/tmp`. Hosted verification of this correction is pending. | | A permit pinned one challenge, preventing a valid fresh-challenge replay from reaching the durable claim. | Native permit schema 2 binds 1–4 exact sorted context hashes; every context still needs its own operator attestation and native challenge verification. The full set shares one immutable run/family budget. Frozen vectors cover both listed contexts and an outsider; the durable final-unit race uses different contexts, and a set change cannot register new capacity. The installed author emits two challenges for one actor and identical declared operations. Actual pipe and isolated-socket Docker rehearsals passed native review of both contexts and preserved exact action/context bytes across refresh. Protected durable replay evidence remains pending. | | Real response-loss testing needs visibility into a short-lived commissioning process. | Added optional owner-private, bounded read-only counter streaming. A stream failure never cancels an entered native attempt. Counters indicate local execution boundaries; the family harness still needs actual external network faults and independent provider read-back. | +| Signing checked packets individually without requiring the complete reviewed operation pool. | Signing now rederives the entire pool, exact filenames, contexts, arguments and order. Added source-fixed Stripe relative-ceiling and currency refusal probes so real guard tests can reach custody without using an unlisted action. Actual installed-wheel Docker pipe/socket rehearsals passed native review of all eight Stripe and four Airtable packets with no network or credentials. Real protected guard refusals and the complete corpus remain pending. | +| Repeated read-back needed explicit accounting for previously confirmed writes. | Added closed projection of actual native result/counter facts and a bounded journey ledger. Only linked evidence matched to independently fetched exact provider bytes can confirm an entered write; read-only recovery confirms its earlier measured entry once. Tuple/action/scope drift, duplicate writes, unmeasured effects and extra result fields refuse. Source unit regressions cover these boundaries; protected harness integration remains pending. | The public offline root ceremony and purpose-separated certificates are pinned. Both signer keys are provisioned in the existing reviewer-protected main-only diff --git a/product/qualification/auths-recipe-qualification-issuance/tests/commissioning.rs b/product/qualification/auths-recipe-qualification-issuance/tests/commissioning.rs index 44cc79ce1..4cd220b08 100644 --- a/product/qualification/auths-recipe-qualification-issuance/tests/commissioning.rs +++ b/product/qualification/auths-recipe-qualification-issuance/tests/commissioning.rs @@ -602,6 +602,10 @@ fn action_and_lease_bounds_are_exact_and_never_silently_repaired() { QualificationCommissioningPermit::from_body(&body).map(|_| ()), if (1..=MAX_COMMISSIONING_LEASES).contains(&leases) { Ok(()) + } else if leases == u64::MAX { + // RFC 8785 serialization cannot round-trip this number as + // the typed u64. It refuses before the closed lease bound. + Err(QualificationFormatError::Malformed) } else { Err(QualificationFormatError::ListBound) }, diff --git a/product/runtime/auths-gateway/semantic-closure.json b/product/runtime/auths-gateway/semantic-closure.json index 904714fb4..b76e8d3aa 100644 --- a/product/runtime/auths-gateway/semantic-closure.json +++ b/product/runtime/auths-gateway/semantic-closure.json @@ -1 +1 @@ -{"files":[{"path":"Cargo.lock","sha256":"0e75e2fdef44e79e57797ac6661295ae58ddb8de4a1990a6fd22ce6c54f78604"},{"path":"Cargo.toml","sha256":"6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24"},{"path":"core/adapters/auths-did-keri/Cargo.toml","sha256":"86ba3e3f9a0a70d970568bfb3113b7ba7bbdd81c3eebbb52743dd574a0c0ecaa"},{"path":"core/adapters/auths-did-keri/src/lib.rs","sha256":"a75674842f8a7142004369ccd206ab43e476459293f0ff4bed4d4e659031b3e3"},{"path":"core/adapters/auths-did-key/Cargo.toml","sha256":"d5a3ae07ecde83f91eed4c3785051dd0f44eab6c891754f3309b6b40596707d7"},{"path":"core/adapters/auths-did-key/src/lib.rs","sha256":"b76a3f4528a725df53cfa9242e6e414e1d26caa48468aaed497e28b121f4497c"},{"path":"core/adapters/auths-raw-key/Cargo.toml","sha256":"f49616bc18c19e6aaa7e6a02ccebcdb9f5c1422c1278ef9869e0dbf22ceda7be"},{"path":"core/adapters/auths-raw-key/src/lib.rs","sha256":"45eec1b295dac3bed65cd79c942870b926b06b3f5d38eaebaeb6140ac69315fa"},{"path":"core/crates/auths-algebra-kernel/Cargo.toml","sha256":"0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba"},{"path":"core/crates/auths-algebra-kernel/src/generated.rs","sha256":"ae4bcbef42a408c7ffa0c6a74a42f7de177a6f14479e51d205acf830bda05960"},{"path":"core/crates/auths-algebra-kernel/src/lib.rs","sha256":"6654667eeb9b353d6648954c9fd2e8838462a82ce6b2803eb49e1366892c68c6"},{"path":"core/crates/auths-assurance/Cargo.toml","sha256":"afcb12a97ddd09d7a264b9ecd3fcaefc865ff2c9b4539ee85b00883420ba333a"},{"path":"core/crates/auths-assurance/src/lib.rs","sha256":"0fb2ec844d674b25a9e20b1601452c89c2454901fa506adfa9bb38ef9a7fa213"},{"path":"core/crates/auths-author/Cargo.toml","sha256":"1e6f0e3bc079ddb558decf0db26b291c6e72fc47327b6df1b7650d41689b215f"},{"path":"core/crates/auths-author/src/lib.rs","sha256":"e14475f2f49715a1869d5fa6b11ff1fbb72497e39097e09f833b0bae7e5b3f2b"},{"path":"core/crates/auths-author/src/observations.rs","sha256":"dda7d6bfa6f4bd7e95a480ca283c2c0e996f69c5c15cb0c7197af328131a7066"},{"path":"core/crates/auths-authority/Cargo.toml","sha256":"4f68212938029f79ebd857b4f3038494eb85d0163d49f07e51376715cf959815"},{"path":"core/crates/auths-authority/src/lib.rs","sha256":"da88d5194de4e17449e69972c0fb042afa3c39798a8f570f30771e77c384f1eb"},{"path":"core/crates/auths-codec/Cargo.toml","sha256":"e20e51826e17814effd9d8925d18d5fbdd6c0d37bf50231e743ec2611314722c"},{"path":"core/crates/auths-codec/src/approval.rs","sha256":"fbff43bf4d57f69f8b7738a8647751cde75c5a932dee65d924a1fe9c7202f91f"},{"path":"core/crates/auths-codec/src/bounded_policy.rs","sha256":"d21f6728be2d8a04b6d94921f2b683f7e61cbb42e0ac6866f1c88a49caa534c3"},{"path":"core/crates/auths-codec/src/decode.rs","sha256":"ba2999584cdf53b1b517ecb9c7ea50d39efee17c666a9a38e2ad1ac94379f778"},{"path":"core/crates/auths-codec/src/encode.rs","sha256":"8491192053e2e15d62b4d2a491de22405b7487ead69ab6f6bca40669ce7ca5f7"},{"path":"core/crates/auths-codec/src/error.rs","sha256":"fecb0737c16deb42d859f1dc7727c698438d9ac12064fd99e0024629642c390c"},{"path":"core/crates/auths-codec/src/hash.rs","sha256":"f88e111f1dbb2cef6b7b5e9c948cb45ff92e366710c8a5f5c636138aa748479e"},{"path":"core/crates/auths-codec/src/lib.rs","sha256":"3b0e5c94c6f34f750b88a9333e1d5c8145746d845d3a23e0d2f61807cf592ea7"},{"path":"core/crates/auths-codec/src/observation.rs","sha256":"38328b0c71ff97a4196eeade8b4faa889527ff1f80bb168468bcd49082a3987e"},{"path":"core/crates/auths-composition/Cargo.toml","sha256":"331e13025eb82588b5269ed3975929eb41c823d588c49e4c296273d85c6fe80e"},{"path":"core/crates/auths-composition/src/lib.rs","sha256":"e42e3b0b6a9985b73c533aeb23799c638979aa27a9ce7d0f10a8d60340570fb1"},{"path":"core/crates/auths-model/Cargo.toml","sha256":"565c15302b0cc9270db1e28efa3862804846850ba933cc17aea8abcec4a65987"},{"path":"core/crates/auths-model/src/approval.rs","sha256":"54cf44a9ef747ec21546a4086aecfb130bc7803b0d646430e6082df51e6e305f"},{"path":"core/crates/auths-model/src/bounded.rs","sha256":"f90496abc0a06c028b4d850af6ddab7d850bfafeaa3d042f1b1246a41d8bbbc9"},{"path":"core/crates/auths-model/src/bounded_policy.rs","sha256":"306a8f049cc7cfc7635fe0e4de47eb7813eed63d3c14c3be2b51586aa4eea450"},{"path":"core/crates/auths-model/src/lib.rs","sha256":"e7cfe6bb9574c6b016aa63e70658c31e0b90903ec6479a49f4a2ceb64f5bad97"},{"path":"core/crates/auths-model/src/observation.rs","sha256":"b3ed3e3cc090afca2896a7d3de7988afccc1ee1ea0ebd91b51a8bc0f20ad8dbb"},{"path":"core/crates/auths-multikey/Cargo.toml","sha256":"858756c1197befcada06134742bffe8d58cf674cadd6c046bf710570e96efaf2"},{"path":"core/crates/auths-multikey/src/lib.rs","sha256":"f5177fffb11e40eeaaa665ba886c541fc1f24d5eacdd6983fb03dc20148733f0"},{"path":"core/crates/auths-ports/Cargo.toml","sha256":"596a9b0f5af3717c16a6d13f7054d8a106bcd9f01f5f72c2235dd2afcf0ab16c"},{"path":"core/crates/auths-ports/src/binding.rs","sha256":"a16c012d40aa4249e3ec54372b9611006d0bfe8c7dc3c741911c2194ad17736d"},{"path":"core/crates/auths-ports/src/diagnostics.rs","sha256":"aa596572503b5a65a918bb2ff38281c144ff53821ee914e9325c852828d852df"},{"path":"core/crates/auths-ports/src/lib.rs","sha256":"8da1debf86f9532df0660155d04298beb1ba3a1204508f8586e2e67cd2fb3449"},{"path":"core/crates/auths-ports/src/path.rs","sha256":"b68fc547b4e4d97a60cbbc1cc1939fc6b34a8233b81f840bd396914a707e3ea1"},{"path":"core/crates/auths-raw-key-core/Cargo.toml","sha256":"98c0bc8527a537512e43a74dd6ba9658c6f0cdc16610cf938e3f9b43785d836d"},{"path":"core/crates/auths-raw-key-core/src/lib.rs","sha256":"98c0500c41697aae28708ad0bf970b9a97583d96a3d2c18d23e7fa351e0f7d12"},{"path":"core/crates/auths-registries/Cargo.toml","sha256":"590e49e58b0622d9d6274fea46796dcdb07dec9550eff295cce6a6427ffa51e2"},{"path":"core/crates/auths-registries/src/lib.rs","sha256":"450d3886d85ee333b7e046317fb5b47cde62483d5f3e41d46265e2caf4c373ec"},{"path":"core/crates/auths-registries/src/template.rs","sha256":"1224039dd2b3ce6fa8357613d8cafbae40400493da7176da202b9ade62fa05e4"},{"path":"core/crates/auths-signature-core/Cargo.toml","sha256":"6bee2230eb30af1be0bd5c2d57bd3e1903497a70028d47290d4ac6e9e0e8bca0"},{"path":"core/crates/auths-signature-core/src/lib.rs","sha256":"6e3f9311ded5e49ea50d445eb21e6d8fa12442aa4362a73e0cb6fda15b7cd865"},{"path":"core/crates/auths-signature/Cargo.toml","sha256":"7f7b5682466ba439d8c59579022cb61068cad9fb4bd2d73e1cc21327c902b450"},{"path":"core/crates/auths-signature/src/lib.rs","sha256":"b3d9ac4cc3ba0797b9e1c09f2d6ac05089b25dac4e285a5af28c0165b33d925b"},{"path":"core/crates/auths-verifier/Cargo.toml","sha256":"c43358e06a33324b41a8b93e5cc7279c55f7d21f1f6cfaa539a3fc7b4c27a38f"},{"path":"core/crates/auths-verifier/src/approval.rs","sha256":"c3cae6a49e169051eb555bb092b1069a4d422516d6a2114623a89e5f31ff923f"},{"path":"core/crates/auths-verifier/src/causal.rs","sha256":"9635230f33b13a263573d319ac8a1976addbcc07677514a43e3c7bf28dc04587"},{"path":"core/crates/auths-verifier/src/lib.rs","sha256":"f22dec38dfa47ced8da4f605390da8453273bee1da010f57fd1fdfcb10e0b389"},{"path":"core/crates/auths-verifier/src/observation.rs","sha256":"0bb07f06a0f9524c88427df1c972b1de8ba038a9eeeb15d3134c25125ae84b1e"},{"path":"core/crates/auths-verifier/src/trace.rs","sha256":"2213d72023a1d9e0413a2cf2c51c3dad9e04775d86033a0caaa9d29a8f0036f8"},{"path":"exchange/crates/auths-proof-exchange-model/Cargo.toml","sha256":"34b2db64f93a288e942b5a3918d28cdcbef906e0dc9074ce848018d3d5f7a1fa"},{"path":"exchange/crates/auths-proof-exchange-model/src/lib.rs","sha256":"49fac5aff2339d3a57c41cb8bb2a82852538e8f77ecc4b157c88e264ff31fb55"},{"path":"exchange/crates/auths-proof-exchange-port/Cargo.toml","sha256":"7ff660f1b7579dc570c791090aeb450404fbbf44c92781e289f5ccdde746d739"},{"path":"exchange/crates/auths-proof-exchange-port/src/lib.rs","sha256":"b408fb40c6432edc1facb3d8b3e9433a033f8dc73fe2e0ba5a88c972ca675021"},{"path":"product/config/auths-config/Cargo.toml","sha256":"e4b568ab9f6d84f7d7e6d66443fe825f360db9c27bc7c31d6ddc0647ba3ab304"},{"path":"product/config/auths-config/src/lib.rs","sha256":"fecf00ea65cef9018fda9af2063326d7065b869266d0d9e73a4f06816f1102cc"},{"path":"product/errors/auths-errors/Cargo.toml","sha256":"3b3a199b6460ba75bda84475bb5accd35e1485448a3981038db85bf4772dd350"},{"path":"product/errors/auths-errors/src/lib.rs","sha256":"7feeb9069fa4003f94f1f07c1c94619cf1c883e0dbaaf2187f04d0f742264bdd"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/Cargo.toml","sha256":"716f1f2a117d6d69d8effe9ee9057e24ba3502f20af6a602b06facb638cdabed"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/api.rs","sha256":"9ea61dd7ddd93282b073b98e453e6b75b26dc49689c04e9782435d06a3a09e48"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/clock.rs","sha256":"73f0a6e0f5903883329fa6683f5888288f759512ac69e5c87efd2b6b87f7d79f"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/http.rs","sha256":"14c1fce14e24c984b2a275563a29b6326fb08367922b6e8d37ba38b9cb81aa2b"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/identity.rs","sha256":"186de11230c8b33375951c4368609f8976bf9795f171af3fd7fac26207a94361"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs","sha256":"0b4617d044f5254a5ab22f5a2578f91cc025206a8c1845be39c1c56dcdf7a5df"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/names.rs","sha256":"41bb23572d6002e23ee103d6fe70ecd68764861c6f2e48a1c53af998270a4afa"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs","sha256":"39fed883f4802e68d3b41a68fea0aba0737810996b33d13577de70faba004c29"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/store.rs","sha256":"fc60ee9c49b2f4f063c449b4c78100c5c4872779e94ca168f796603b380ef6e4"},{"path":"product/integrations/auths-custody/Cargo.toml","sha256":"1e14034185ad1ec24a977fd5f41d0abee219606245c046ce2a82287fadef448b"},{"path":"product/integrations/auths-custody/src/conformance.rs","sha256":"8ed1afd58f18fc6becc268908aa6419c9aa404c79da0197963eb2599df44acf6"},{"path":"product/integrations/auths-custody/src/key.rs","sha256":"70cbb0fd21b6f5652157845a22c35be2d0f6c05b3d138fc4b9bb6dbdc3d81c40"},{"path":"product/integrations/auths-custody/src/lib.rs","sha256":"8ee593c1f59b0fd2126bdda9138026f5bc531beb64d4489a99785842e7b98b43"},{"path":"product/operations/auths-operations/Cargo.toml","sha256":"73dde1e914ba5e1386f8d49c0d730423cc72ae77ec44c6554a6a75cc8e8922b1"},{"path":"product/operations/auths-operations/src/explanation.rs","sha256":"b4a39bcbd5712cb9e735ee7deeb281f3fa6af5ddca973735bf3d87dce427ef11"},{"path":"product/operations/auths-operations/src/lib.rs","sha256":"3f401a56555113b98f57bca172a2660eaecedf76247b83a3fdbb089c133a29cd"},{"path":"product/operations/auths-operations/src/render/json.rs","sha256":"2ae042639960afee123730e945d373bc5dda1d2b3af20ae16c939a7e99b9e418"},{"path":"product/operations/auths-operations/src/render/mod.rs","sha256":"b3b7f6fe473f49227ace5a68bfc3d8dc14b5db8dd9888fd9e207070337b1b8bf"},{"path":"product/operations/auths-operations/src/render/text.rs","sha256":"f216cf3bdb00e264523271b16e7059535ac6b1aabf271cebd7935af155e4bfec"},{"path":"product/policy/auths-bounded-policy/Cargo.toml","sha256":"babd5d200923137ead71d8c2528f847cea323ce98da942a1320b054436612c47"},{"path":"product/policy/auths-bounded-policy/src/arithmetic.rs","sha256":"75e43c5d4eab8d1f71c1daf53839f5f9fe45a400afc1f63a30c6f55ce3632627"},{"path":"product/policy/auths-bounded-policy/src/commitment.rs","sha256":"c5706f2d583454e1a7f570f7ada138d4d864bef0205dfae7c1296774f396bb3f"},{"path":"product/policy/auths-bounded-policy/src/eligibility.rs","sha256":"c9acdfb793074e687fc36efad506be27dbd99ffbf40387bc66c8de39ef238432"},{"path":"product/policy/auths-bounded-policy/src/identifier.rs","sha256":"0006a32bae9eb16c4178cf797df418d2b0a781f2bc6474b741dc1a908141831c"},{"path":"product/policy/auths-bounded-policy/src/kernel.rs","sha256":"99187c28b161ac70bee1afed60711f7f645adb4d1671a01863f9849b369811d5"},{"path":"product/policy/auths-bounded-policy/src/lib.rs","sha256":"76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c"},{"path":"product/policy/auths-bounded-policy/src/receipt.rs","sha256":"3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad"},{"path":"product/policy/auths-bounded-policy/src/registry.rs","sha256":"4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0"},{"path":"product/profiles/auths-profile-api/Cargo.toml","sha256":"7ae85761f58625b5d678f961fd052eebf3e000ef565c7312e3ac857763c0017f"},{"path":"product/profiles/auths-profile-api/src/lib.rs","sha256":"a194b82b20bf8aa864c2334ef6c6aec30b2154ded972862252d5dcefa488ab95"},{"path":"product/profiles/auths-profile-mcp/Cargo.toml","sha256":"db264fc25242f7b7e4133cbe5782545b3107b406c87168ae072683cfb59eac66"},{"path":"product/profiles/auths-profile-mcp/src/arguments.rs","sha256":"a5de696586d507e2aee4a49fee99ef1ef4c51a2e46603f8838f1af6d9009833f"},{"path":"product/profiles/auths-profile-mcp/src/lib.rs","sha256":"d0f8b733a09ef8408336cdebc8948d6a5861012ce6878598b11be7084dfd4280"},{"path":"product/profiles/auths-profile-mcp/src/session.rs","sha256":"166c281fa66333388e4760d6098dad02d3359e1d5de4b8f93312c014f97abb03"},{"path":"product/qualification/auths-recipe-qualification/Cargo.toml","sha256":"b7b15b30b9a3d96d4f089d514266d3a892de6608d30707aa44be31cca89ca9fe"},{"path":"product/qualification/auths-recipe-qualification/src/canonical.rs","sha256":"30a9b50777f0dcb4b606abfee2467d5a975d9f6ad941ab6c13ca3df5b359f667"},{"path":"product/qualification/auths-recipe-qualification/src/closure.rs","sha256":"0ad6aee9bd981e2863fa725f209ec84031db2ff12f4c7ac3aaf5120f0bb86039"},{"path":"product/qualification/auths-recipe-qualification/src/commissioning.rs","sha256":"db135c55e4e3079a73253ebae275536523eb36b545d1c152b4d7dce3c6b76828"},{"path":"product/qualification/auths-recipe-qualification/src/commissioning/tests.rs","sha256":"4dde3736d206099b1bea4c14e0092c6c1287d1af9065958777d7c54331dd8686"},{"path":"product/qualification/auths-recipe-qualification/src/error.rs","sha256":"52d5cf720a1e4579008fdda90a3ac2c31f0b8db57985f121f65e54b4da2b7dd1"},{"path":"product/qualification/auths-recipe-qualification/src/evidence.rs","sha256":"ba45a7409d67a8af26ab811af306412014557477a101ab2a8eb0faf8f2bd4b91"},{"path":"product/qualification/auths-recipe-qualification/src/ids.rs","sha256":"e81a906d571497ab2da753e1532d4443706410e0b75fdd59a7d2d788c7aec403"},{"path":"product/qualification/auths-recipe-qualification/src/launch.rs","sha256":"41f2e2de90e1e7d6440a66eda3eb9bea8d5e0741bc232305a76a363ab5f813c1"},{"path":"product/qualification/auths-recipe-qualification/src/lib.rs","sha256":"0e24b0f81191df0d078c7f4d73ced784ba9472372bfcdff3c7d0e2fb1687b323"},{"path":"product/qualification/auths-recipe-qualification/src/model.rs","sha256":"3484eb0ec287b23d4682ade7b1b0f8d1335985b3fb180f06fc28716076957d5f"},{"path":"product/qualification/auths-recipe-qualification/src/release.rs","sha256":"ec478e53f70052e566aac7e15be2f9e1b1cd46837ac6990ae955fa864d311586"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/mod.rs","sha256":"fa23a962fd90331152eed5edbcdf271955f7aed79b8da1e065bfe69a20b487a9"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/schemas.rs","sha256":"c59feec2805621f341a90f81fc005e2c12f7a70f9d264fdeacccb2be4fe1c046"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/verification.rs","sha256":"bdf5746fed4d10a7f577f7878619a917d29aa8b7d522f00d9f774e53eff4c8c1"},{"path":"product/qualification/auths-recipe-qualification/src/verify.rs","sha256":"2ec2784435d11e07295de77b2ee1b2c48b2fcf9609a00454c6e7374b621aed5c"},{"path":"product/receipts/auths-receipts/Cargo.toml","sha256":"6001fa1375899953aafcb07c23a6da0c8f57ea7ec08bb9c950b12a60a8cc6f0f"},{"path":"product/receipts/auths-receipts/src/disclosure.rs","sha256":"ba9ed439be0a320c8a01f5b6e9b51361c1a37e076947490d8e4a484ba6bb119c"},{"path":"product/receipts/auths-receipts/src/lib.rs","sha256":"547a57c4160256719cafb7d0ab972d9fc80b0da14fbbce4148c70c414070ff36"},{"path":"product/runtime/auths-connections/Cargo.toml","sha256":"babeb6e1dda3dfb66291713ce1e43dce5c349833d0b50ea4dccbf986030026b2"},{"path":"product/runtime/auths-connections/src/credential.rs","sha256":"82921413bb053f0f6c7931fbd4e6a86c8cc1d8c6b51debd9c2cef33a8d5b1c51"},{"path":"product/runtime/auths-connections/src/kernel.rs","sha256":"a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8"},{"path":"product/runtime/auths-connections/src/lib.rs","sha256":"79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22"},{"path":"product/runtime/auths-connections/src/model.rs","sha256":"de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77"},{"path":"product/runtime/auths-connections/src/registry.rs","sha256":"e57640e003e72ad3235c567c2bb944a262bd64e673f023b62ea091094cc7e946"},{"path":"product/runtime/auths-gateway-kernel/Cargo.toml","sha256":"34f864e67656af4ac7e5c7a347a23f01fc8ab31365b8e23c0ef474483b14a183"},{"path":"product/runtime/auths-gateway-kernel/src/construct.rs","sha256":"e9d65744bae273d65face4285e5d2da75c06a92ab48f7b8333d496604e31c63c"},{"path":"product/runtime/auths-gateway-kernel/src/lib.rs","sha256":"cfda6f8453426564c085475f183b6f790b438768a19668f1b65d33ba59dc8632"},{"path":"product/runtime/auths-gateway-kernel/src/order.rs","sha256":"e0045f877c4b7fe3860c291039853885064ddcdebba7c9b345ab65e81e646dda"},{"path":"product/runtime/auths-gateway-kernel/src/outcome.rs","sha256":"e9785b1afe70788c89b51b18655bcd5acff7b0c8e3d12fb79c6f05a202e67e6b"},{"path":"product/runtime/auths-gateway-kernel/src/ratio.rs","sha256":"7ace22264812e6fc1ef3a62afee402cf43494bb71ae0d3de219ad1b39d690bcb"},{"path":"product/runtime/auths-gateway-kernel/src/recovery.rs","sha256":"9f46dcd1685ab6e4d1ba04a3fc286a9f3afee8fb47829be1fbc670a7926a2dc6"},{"path":"product/runtime/auths-gateway-kernel/src/transition.rs","sha256":"cefb8f01d915880f6921f2501ff881ad94b9de61072c34d9cd19220992f97374"},{"path":"product/runtime/auths-gateway/Cargo.toml","sha256":"00b28be86921dcdc0ad90cce0c62c2961cafefe96ea6c2edf0e926c3d405ccad"},{"path":"product/runtime/auths-gateway/src/admin.rs","sha256":"0dee40a9fb67c5de10142fc37a7bbabdd8979fb0199fb26caf4bdb024e0a5a40"},{"path":"product/runtime/auths-gateway/src/app.rs","sha256":"6f80f63833ea0815bb44fbf3b0cc54624a08e9fb578b035819f2980dc04e8256"},{"path":"product/runtime/auths-gateway/src/audit.rs","sha256":"0edb2037eb7b5d6f13acfce85c54f62a82bf7fdd31bc7e626c4fec183cef61dd"},{"path":"product/runtime/auths-gateway/src/audit_tests.rs","sha256":"990969384a52d75bc2489d9d412a9e7dd814bca1c8f65c701d6205fae62a15d5"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway-harness.rs","sha256":"12b0c24d36b2e6a3be392d3c081a783b355fdd67dc5b54bacc0410e803116b8c"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway.rs","sha256":"77a041ac461704a4e61e24c704eb63e7bc1499d5a54a9b282e133ff5099696ba"},{"path":"product/runtime/auths-gateway/src/binding.rs","sha256":"663b0ce878319511aa7d05722ab4ab2fa9be18817884ffb2ee9f131ff1e382d1"},{"path":"product/runtime/auths-gateway/src/bounds.rs","sha256":"38251ad6f22f9d07ef9a219c79fa265ca36f1526eca5f147d7efa46b52ad609d"},{"path":"product/runtime/auths-gateway/src/bounds_aggregate_tests.rs","sha256":"ab34f227b7c8692ba1da88ccb32bb3687a66adf8353d8282fae905d4a88eb612"},{"path":"product/runtime/auths-gateway/src/bounds_tests.rs","sha256":"74136bc570da7b9338b5a1a1ed9d3fd892c55135160964f9d3ac0e2cf5741375"},{"path":"product/runtime/auths-gateway/src/commissioning_budget.rs","sha256":"fab29da3269438cc62330f3eab7b5bd4dc482b4db8af243aae47df5d3aa1deb8"},{"path":"product/runtime/auths-gateway/src/commissioning_budget/tests.rs","sha256":"da104a1643c37515deec6397bca6db2054f2c9158ec3d230a1b1ec9c7d0f659f"},{"path":"product/runtime/auths-gateway/src/commissioning_floor.rs","sha256":"7fa6991c5ccd5ae1403be84b3da390323fab09f36e15ac01fd7a38ea350c6fdb"},{"path":"product/runtime/auths-gateway/src/commissioning_floor/tests.rs","sha256":"6b663d6e556adc0b455b81845bc4394d82c6c4de0c5f43e1310f3ddc6e4e40f7"},{"path":"product/runtime/auths-gateway/src/commissioning_session.rs","sha256":"24b48d5eaeaaa3c620e2dfc7ee1f9255fc4519a1eb404b8608cea7af6a910ee2"},{"path":"product/runtime/auths-gateway/src/commissioning_session/tests.rs","sha256":"37a097fc8a9261d3fffdaef3f905f40b22e3e6601bb5101fadd9414f963c0824"},{"path":"product/runtime/auths-gateway/src/connection.rs","sha256":"7b5d049c258a26ed1c93ecf860f51d051a8a65f9b93554af0b1ea93862398ec9"},{"path":"product/runtime/auths-gateway/src/credential_journal.rs","sha256":"7297fccaee5cd8622928e8e0a42bba50da7941970a6f682ecd300c41ee6509da"},{"path":"product/runtime/auths-gateway/src/echo_verify.rs","sha256":"6d453051665f823abd7354d5c50031d9524cf47d6092d2f09080ae814e3b9575"},{"path":"product/runtime/auths-gateway/src/engine.rs","sha256":"1abff20b98bc894c45bfc5c4414c81a99966d1ec95d924a5b0cd6f4c5626ca24"},{"path":"product/runtime/auths-gateway/src/execution_witness.rs","sha256":"e8b1a8e41d5e3fa309760067849d390ef065feeb46701a83391832645a2f000c"},{"path":"product/runtime/auths-gateway/src/fuzzing.rs","sha256":"ed3b0028487eb546a3b0a91d115aa8f18bcea324b61620bfe8e35a9e6ab18758"},{"path":"product/runtime/auths-gateway/src/generation_floor.rs","sha256":"fe1510ec96ce0f67e9a78edbfa94b33eb7df64c0ac4d0a67901124dcd0164777"},{"path":"product/runtime/auths-gateway/src/harness.rs","sha256":"c87e479f3eb281960f6c9c80d43c7560d7ccb654b0154ec823d3fcec4884ac05"},{"path":"product/runtime/auths-gateway/src/lib.rs","sha256":"fad95d031f88072dd024c78facf0bb0267562b1ac743ddd7219fce47e64024f0"},{"path":"product/runtime/auths-gateway/src/listener.rs","sha256":"aa08239bcbc1fcb55e8a212fbdf6a84f12985b0d436dcb51dc58b06e59e435f2"},{"path":"product/runtime/auths-gateway/src/observed_tests.rs","sha256":"a22be071695f89ca2578a4d82fd80d9cb82289213c9bdb8f0470f6b2dc3d9201"},{"path":"product/runtime/auths-gateway/src/observer.rs","sha256":"562ffcaea071c3856e0708dc2fe33516917e145d2438aabb75af0a2b6ba01046"},{"path":"product/runtime/auths-gateway/src/onboarding.rs","sha256":"0dfd7d67e7f02f18a28d1c86ca1b7751d7463f5efcdbe3825de0ad8cbccb3891"},{"path":"product/runtime/auths-gateway/src/operator.rs","sha256":"c3c36954a3e86723df035b47f43b85fc8ab3a6292983522b6258d5c6b4e6c4e4"},{"path":"product/runtime/auths-gateway/src/pending_vectors/attempts.rs","sha256":"47ef3c8cb1c5504d47ae9a0088705ce6715fe86bac1671a34a56fb38a64d0dd3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/bounds.rs","sha256":"e612217307e1da5b0eb5ee6582a7458bb064b8aa8a529fc6555b1b334127ab68"},{"path":"product/runtime/auths-gateway/src/pending_vectors/codes.rs","sha256":"e00670a5ef24eb856cc2c6dcda8e5a263842f55c76bb939c0c27bd9df37e5522"},{"path":"product/runtime/auths-gateway/src/pending_vectors/keys.rs","sha256":"f84c56f2ea9cb34b2b79c72d13fbf2c6585010ec1ed450af58a78c80c1ea1edd"},{"path":"product/runtime/auths-gateway/src/pending_vectors/mod.rs","sha256":"5de8340f0ef71a0b57a09e323fefe473d3160c6ae952b9ba46f714825fbacafc"},{"path":"product/runtime/auths-gateway/src/pending_vectors/outcomes.rs","sha256":"8ec07b9511b48913af36ac999d2aa0e82924289f6acb23ddaeb9f00f99815166"},{"path":"product/runtime/auths-gateway/src/pending_vectors/production.rs","sha256":"772d032e0a0d9c924fb6d6c188528db85a97e71c9e466ddc19eee277baf83614"},{"path":"product/runtime/auths-gateway/src/pending_vectors/recipes.rs","sha256":"51693208270231c25c3aef2a32151d5962114c71e86b88cb9df83181c7af83d9"},{"path":"product/runtime/auths-gateway/src/pre_entry.rs","sha256":"06ea78ca140468bfaba17d9ab04912ad68673954c3203c98fed28272ff2a00c0"},{"path":"product/runtime/auths-gateway/src/property_tests.rs","sha256":"939c081e2e154aaf10186754044bdd65608932c899b970a04a71d0afaa999a93"},{"path":"product/runtime/auths-gateway/src/qualification.rs","sha256":"c597c83de2b94f0374ae54e40a8b57c2a64ec6e254704dca32185f448a908aca"},{"path":"product/runtime/auths-gateway/src/qualification_simulation.rs","sha256":"4ee7cadfb5f46a92713c80f3e55f499cb074d04d8b21ea89d57762af38642bfa"},{"path":"product/runtime/auths-gateway/src/qualification_tests.rs","sha256":"a9178a2e58eea459d5e5dafc53a3999ea7c84dbbffefe6e5eb1f3d098827f028"},{"path":"product/runtime/auths-gateway/src/quorum_tests.rs","sha256":"a78380b019104d688c11a4410082c7e08ded3106aab099954c4f8a1b4ae0fd89"},{"path":"product/runtime/auths-gateway/src/readiness.rs","sha256":"911c3f11892f94641574375e2da4c671c802738f71082f12c39832331052d43d"},{"path":"product/runtime/auths-gateway/src/recipe.rs","sha256":"fecf9af67e7afc48d080e9f8f55f8ce28e49d0e08988717a27908bbda461d6b6"},{"path":"product/runtime/auths-gateway/src/recipe/lower.rs","sha256":"8088b8751ed831dbb48247af953c6290ac95e2a438ccd5bd65eff54be06a1fd1"},{"path":"product/runtime/auths-gateway/src/recipe/review.rs","sha256":"c3eb7d9fdd98dacf52750b14b67ad7b7faaecbbdeafff1e0b049f67d0a2d0139"},{"path":"product/runtime/auths-gateway/src/recipe/runtime.rs","sha256":"c286f0d15f974402822c0810d8e97f98411dc1c557755cc23e540d85e2bb42d9"},{"path":"product/runtime/auths-gateway/src/recipe/source.rs","sha256":"1af50298fb1461e1b24cbdf560d43124d6b1c4c529586c911b1c4797214a69ff"},{"path":"product/runtime/auths-gateway/src/recipe/tests.rs","sha256":"aac551a2481bbc60864c64079bc667dcb232e45a0f41a04073ed84ab5dbe1fce"},{"path":"product/runtime/auths-gateway/src/recipe/validate.rs","sha256":"3711b17605cb7b0d639bc1b180449231f5882a306cab20e2c7782155cc63b0d4"},{"path":"product/runtime/auths-gateway/src/scenario_tests.rs","sha256":"025b53473b3af6900e03bc2fee91aa63ed26a8778bc8c8296fe08f5540794c39"},{"path":"product/runtime/auths-gateway/src/separation.rs","sha256":"be9306848ca5d801767cf6aa14247c8618312ef0e202f00ce0c24c4844491061"},{"path":"product/runtime/auths-gateway/src/simulation_attestation.rs","sha256":"88705e5d45415f760f1e3c3a065c35c48f4f4065bf7b3feb7882246983814d6f"},{"path":"product/runtime/auths-gateway/src/store.rs","sha256":"884bcad4d70d53e12eae9c8517f6ecd0643068ee0be0370015119d04d6cc2516"},{"path":"product/runtime/auths-gateway/src/store_testkit.rs","sha256":"88d82fee42f1b8ef521e8deef0216e938ebeaad822eb2f5020e70b89d145ea70"},{"path":"product/runtime/auths-gateway/src/submit.rs","sha256":"fe2eacb5ad8152eeecbd232c47a356fc72db0098e34fda99532bdf6ef0cf895c"},{"path":"product/runtime/auths-gateway/src/support.rs","sha256":"9fd979029793a22b15d9776a7fc172476fd7c126a80d4080c65d720845becbcb"},{"path":"product/runtime/auths-gateway/src/transport.rs","sha256":"978fc9fb34a33b3db265b5d1c3ce11696a5b9f08529e46dd2a1e7bb62afb9220"},{"path":"product/runtime/auths-kernel-runtime/Cargo.toml","sha256":"926bcd0053e5edd703be8f0027ad009e2982db013c8174c1366edbf38b48087d"},{"path":"product/runtime/auths-kernel-runtime/src/lib.rs","sha256":"7108faae9ca4bc32dc093ddaf885ac8f74f3c9b8d317b7c7d0ed00d1d0ab5972"},{"path":"product/runtime/auths-lifecycle/Cargo.toml","sha256":"c5053c705f8d5554b44e432fe75287a2faf11d644e5a2552e45ad6cd94176af5"},{"path":"product/runtime/auths-lifecycle/src/codec.rs","sha256":"51c4b746749150e8bfcd8ff972b3f6c1ef40bec15583448ec1b471d9ad737dc0"},{"path":"product/runtime/auths-lifecycle/src/digest.rs","sha256":"55282cd7d8aba37713c2dcb5357c9877819edb72a30eadefb860d28d7d3a3eb7"},{"path":"product/runtime/auths-lifecycle/src/identifier.rs","sha256":"31620e8c16de68d3d2d3b84d6353c1a5b9d4151d8247f91fa389b906a8e660f1"},{"path":"product/runtime/auths-lifecycle/src/kernel.rs","sha256":"2abb8c094b36d35b364e74d78091d14c5d6f3d1eb6552cca3b5538dbd017ce23"},{"path":"product/runtime/auths-lifecycle/src/lib.rs","sha256":"afe5a345cd309b5a4f08ffba3170a6d7f16ff914892b3f2006d5208ed24ec736"},{"path":"product/runtime/auths-lifecycle/src/model.rs","sha256":"1af12bbeeeaa65ec02ddcebd7d2c8c92ec1e339fa40ae85b45ab9b01a722a4fa"},{"path":"product/runtime/auths-lifecycle/src/operation.rs","sha256":"78e6d05fcf5d7ea4f148032a3fa26fdfcab77eb346019effe927b08e0d64d732"},{"path":"product/runtime/auths-lifecycle/src/registry.rs","sha256":"53495fe6f7a77422593a41623e28716f1c140dcc1e00f87f6b0ffbfb93a5ef90"},{"path":"product/runtime/auths-lifecycle/src/sealed.rs","sha256":"2e0c03b5813c926c159598bb7890d1523825edbe57cd687d42a5dfb3374a0c19"},{"path":"product/runtime/auths-lifecycle/src/test_support.rs","sha256":"221d9a5c5ef8e1f9f8fd66927484eaf813571d0568470278ecd8fa08a5eec8cd"},{"path":"product/runtime/auths-lifecycle/src/transition.rs","sha256":"011805a28efdd541f44ccea54dd0e34a1e58f4004447ee58013703b4fb6b2822"},{"path":"product/runtime/auths-runtime/Cargo.toml","sha256":"dd29d80a8b4bb56c869f036a6c9998f6e6d1c0383ac5dc03fa42b24abe2a7ff7"},{"path":"product/runtime/auths-runtime/src/lib.rs","sha256":"132ca03d58c14905d3a822a4972f42a22a5ad33a45f2ba9ca44f3a57d810b4b0"},{"path":"product/runtime/auths-runtime/src/production.rs","sha256":"fd4eff4270c571c10fcff6cf27df28961ebf074de8a1a028f500fda1ca376820"},{"path":"product/sdk/auths-approval-quorum/Cargo.toml","sha256":"df904971fca87a24194c5816738a331588fe8f164acb5d70839a35dca5f57114"},{"path":"product/sdk/auths-approval-quorum/src/lib.rs","sha256":"72e4086088a1c0912e4e1a9e980f26a5c280bf5ab16ea39c9f0f58d5096ac2ce"},{"path":"product/sdk/auths-approval-quorum/src/remote.rs","sha256":"9fa029c7c63003adf260f8aec55160c545681c60c1bace0d934e7525862aac7b"},{"path":"product/sdk/auths-approval-quorum/src/remote_tests.rs","sha256":"8a09ce17cfee82a035a74edd535f3ebeb3db0e078784740d3997b17dbdb10197"},{"path":"product/sdk/auths-approval-quorum/src/tests.rs","sha256":"0acbf12be3e497dcc6c2d8f29c9af3b1a7ed8e11b75f6399570d4f217a785060"},{"path":"product/stores/auths-stores/Cargo.toml","sha256":"a32c4b76d17b264be5d40d24497ff237e1ed87822e8bab86229b3db93106dbe3"},{"path":"product/stores/auths-stores/src/gateway_attempt.rs","sha256":"218841602d3d9b23b44625f50e5b54cf275ccedc2d5c89f02d2482b8524472af"},{"path":"product/stores/auths-stores/src/lib.rs","sha256":"e721262edf8a9ab5568ddc27639176312d4a366203b5f73e2d7c11fde2c554e9"},{"path":"product/stores/auths-stores/src/lifecycle.rs","sha256":"3f2cecfda13fdcd7c4a944518646bcc8abd1237f900c0332d5822281f8f9f1cd"}],"schema":"auths.gateway-semantic-closure/1"} \ No newline at end of file +{"files":[{"path":"Cargo.lock","sha256":"0e75e2fdef44e79e57797ac6661295ae58ddb8de4a1990a6fd22ce6c54f78604"},{"path":"Cargo.toml","sha256":"6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24"},{"path":"core/adapters/auths-did-keri/Cargo.toml","sha256":"86ba3e3f9a0a70d970568bfb3113b7ba7bbdd81c3eebbb52743dd574a0c0ecaa"},{"path":"core/adapters/auths-did-keri/src/lib.rs","sha256":"a75674842f8a7142004369ccd206ab43e476459293f0ff4bed4d4e659031b3e3"},{"path":"core/adapters/auths-did-key/Cargo.toml","sha256":"d5a3ae07ecde83f91eed4c3785051dd0f44eab6c891754f3309b6b40596707d7"},{"path":"core/adapters/auths-did-key/src/lib.rs","sha256":"b76a3f4528a725df53cfa9242e6e414e1d26caa48468aaed497e28b121f4497c"},{"path":"core/adapters/auths-raw-key/Cargo.toml","sha256":"f49616bc18c19e6aaa7e6a02ccebcdb9f5c1422c1278ef9869e0dbf22ceda7be"},{"path":"core/adapters/auths-raw-key/src/lib.rs","sha256":"45eec1b295dac3bed65cd79c942870b926b06b3f5d38eaebaeb6140ac69315fa"},{"path":"core/crates/auths-algebra-kernel/Cargo.toml","sha256":"0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba"},{"path":"core/crates/auths-algebra-kernel/src/generated.rs","sha256":"ae4bcbef42a408c7ffa0c6a74a42f7de177a6f14479e51d205acf830bda05960"},{"path":"core/crates/auths-algebra-kernel/src/lib.rs","sha256":"6654667eeb9b353d6648954c9fd2e8838462a82ce6b2803eb49e1366892c68c6"},{"path":"core/crates/auths-assurance/Cargo.toml","sha256":"afcb12a97ddd09d7a264b9ecd3fcaefc865ff2c9b4539ee85b00883420ba333a"},{"path":"core/crates/auths-assurance/src/lib.rs","sha256":"0fb2ec844d674b25a9e20b1601452c89c2454901fa506adfa9bb38ef9a7fa213"},{"path":"core/crates/auths-author/Cargo.toml","sha256":"1e6f0e3bc079ddb558decf0db26b291c6e72fc47327b6df1b7650d41689b215f"},{"path":"core/crates/auths-author/src/lib.rs","sha256":"e14475f2f49715a1869d5fa6b11ff1fbb72497e39097e09f833b0bae7e5b3f2b"},{"path":"core/crates/auths-author/src/observations.rs","sha256":"dda7d6bfa6f4bd7e95a480ca283c2c0e996f69c5c15cb0c7197af328131a7066"},{"path":"core/crates/auths-authority/Cargo.toml","sha256":"4f68212938029f79ebd857b4f3038494eb85d0163d49f07e51376715cf959815"},{"path":"core/crates/auths-authority/src/lib.rs","sha256":"da88d5194de4e17449e69972c0fb042afa3c39798a8f570f30771e77c384f1eb"},{"path":"core/crates/auths-codec/Cargo.toml","sha256":"e20e51826e17814effd9d8925d18d5fbdd6c0d37bf50231e743ec2611314722c"},{"path":"core/crates/auths-codec/src/approval.rs","sha256":"fbff43bf4d57f69f8b7738a8647751cde75c5a932dee65d924a1fe9c7202f91f"},{"path":"core/crates/auths-codec/src/bounded_policy.rs","sha256":"d21f6728be2d8a04b6d94921f2b683f7e61cbb42e0ac6866f1c88a49caa534c3"},{"path":"core/crates/auths-codec/src/decode.rs","sha256":"ba2999584cdf53b1b517ecb9c7ea50d39efee17c666a9a38e2ad1ac94379f778"},{"path":"core/crates/auths-codec/src/encode.rs","sha256":"8491192053e2e15d62b4d2a491de22405b7487ead69ab6f6bca40669ce7ca5f7"},{"path":"core/crates/auths-codec/src/error.rs","sha256":"fecb0737c16deb42d859f1dc7727c698438d9ac12064fd99e0024629642c390c"},{"path":"core/crates/auths-codec/src/hash.rs","sha256":"f88e111f1dbb2cef6b7b5e9c948cb45ff92e366710c8a5f5c636138aa748479e"},{"path":"core/crates/auths-codec/src/lib.rs","sha256":"3b0e5c94c6f34f750b88a9333e1d5c8145746d845d3a23e0d2f61807cf592ea7"},{"path":"core/crates/auths-codec/src/observation.rs","sha256":"38328b0c71ff97a4196eeade8b4faa889527ff1f80bb168468bcd49082a3987e"},{"path":"core/crates/auths-composition/Cargo.toml","sha256":"331e13025eb82588b5269ed3975929eb41c823d588c49e4c296273d85c6fe80e"},{"path":"core/crates/auths-composition/src/lib.rs","sha256":"e42e3b0b6a9985b73c533aeb23799c638979aa27a9ce7d0f10a8d60340570fb1"},{"path":"core/crates/auths-model/Cargo.toml","sha256":"565c15302b0cc9270db1e28efa3862804846850ba933cc17aea8abcec4a65987"},{"path":"core/crates/auths-model/src/approval.rs","sha256":"54cf44a9ef747ec21546a4086aecfb130bc7803b0d646430e6082df51e6e305f"},{"path":"core/crates/auths-model/src/bounded.rs","sha256":"f90496abc0a06c028b4d850af6ddab7d850bfafeaa3d042f1b1246a41d8bbbc9"},{"path":"core/crates/auths-model/src/bounded_policy.rs","sha256":"306a8f049cc7cfc7635fe0e4de47eb7813eed63d3c14c3be2b51586aa4eea450"},{"path":"core/crates/auths-model/src/lib.rs","sha256":"e7cfe6bb9574c6b016aa63e70658c31e0b90903ec6479a49f4a2ceb64f5bad97"},{"path":"core/crates/auths-model/src/observation.rs","sha256":"b3ed3e3cc090afca2896a7d3de7988afccc1ee1ea0ebd91b51a8bc0f20ad8dbb"},{"path":"core/crates/auths-multikey/Cargo.toml","sha256":"858756c1197befcada06134742bffe8d58cf674cadd6c046bf710570e96efaf2"},{"path":"core/crates/auths-multikey/src/lib.rs","sha256":"f5177fffb11e40eeaaa665ba886c541fc1f24d5eacdd6983fb03dc20148733f0"},{"path":"core/crates/auths-ports/Cargo.toml","sha256":"596a9b0f5af3717c16a6d13f7054d8a106bcd9f01f5f72c2235dd2afcf0ab16c"},{"path":"core/crates/auths-ports/src/binding.rs","sha256":"a16c012d40aa4249e3ec54372b9611006d0bfe8c7dc3c741911c2194ad17736d"},{"path":"core/crates/auths-ports/src/diagnostics.rs","sha256":"aa596572503b5a65a918bb2ff38281c144ff53821ee914e9325c852828d852df"},{"path":"core/crates/auths-ports/src/lib.rs","sha256":"8da1debf86f9532df0660155d04298beb1ba3a1204508f8586e2e67cd2fb3449"},{"path":"core/crates/auths-ports/src/path.rs","sha256":"b68fc547b4e4d97a60cbbc1cc1939fc6b34a8233b81f840bd396914a707e3ea1"},{"path":"core/crates/auths-raw-key-core/Cargo.toml","sha256":"98c0bc8527a537512e43a74dd6ba9658c6f0cdc16610cf938e3f9b43785d836d"},{"path":"core/crates/auths-raw-key-core/src/lib.rs","sha256":"98c0500c41697aae28708ad0bf970b9a97583d96a3d2c18d23e7fa351e0f7d12"},{"path":"core/crates/auths-registries/Cargo.toml","sha256":"590e49e58b0622d9d6274fea46796dcdb07dec9550eff295cce6a6427ffa51e2"},{"path":"core/crates/auths-registries/src/lib.rs","sha256":"450d3886d85ee333b7e046317fb5b47cde62483d5f3e41d46265e2caf4c373ec"},{"path":"core/crates/auths-registries/src/template.rs","sha256":"1224039dd2b3ce6fa8357613d8cafbae40400493da7176da202b9ade62fa05e4"},{"path":"core/crates/auths-signature-core/Cargo.toml","sha256":"6bee2230eb30af1be0bd5c2d57bd3e1903497a70028d47290d4ac6e9e0e8bca0"},{"path":"core/crates/auths-signature-core/src/lib.rs","sha256":"6e3f9311ded5e49ea50d445eb21e6d8fa12442aa4362a73e0cb6fda15b7cd865"},{"path":"core/crates/auths-signature/Cargo.toml","sha256":"7f7b5682466ba439d8c59579022cb61068cad9fb4bd2d73e1cc21327c902b450"},{"path":"core/crates/auths-signature/src/lib.rs","sha256":"b3d9ac4cc3ba0797b9e1c09f2d6ac05089b25dac4e285a5af28c0165b33d925b"},{"path":"core/crates/auths-verifier/Cargo.toml","sha256":"c43358e06a33324b41a8b93e5cc7279c55f7d21f1f6cfaa539a3fc7b4c27a38f"},{"path":"core/crates/auths-verifier/src/approval.rs","sha256":"c3cae6a49e169051eb555bb092b1069a4d422516d6a2114623a89e5f31ff923f"},{"path":"core/crates/auths-verifier/src/causal.rs","sha256":"9635230f33b13a263573d319ac8a1976addbcc07677514a43e3c7bf28dc04587"},{"path":"core/crates/auths-verifier/src/lib.rs","sha256":"f22dec38dfa47ced8da4f605390da8453273bee1da010f57fd1fdfcb10e0b389"},{"path":"core/crates/auths-verifier/src/observation.rs","sha256":"0bb07f06a0f9524c88427df1c972b1de8ba038a9eeeb15d3134c25125ae84b1e"},{"path":"core/crates/auths-verifier/src/trace.rs","sha256":"2213d72023a1d9e0413a2cf2c51c3dad9e04775d86033a0caaa9d29a8f0036f8"},{"path":"exchange/crates/auths-proof-exchange-model/Cargo.toml","sha256":"34b2db64f93a288e942b5a3918d28cdcbef906e0dc9074ce848018d3d5f7a1fa"},{"path":"exchange/crates/auths-proof-exchange-model/src/lib.rs","sha256":"49fac5aff2339d3a57c41cb8bb2a82852538e8f77ecc4b157c88e264ff31fb55"},{"path":"exchange/crates/auths-proof-exchange-port/Cargo.toml","sha256":"7ff660f1b7579dc570c791090aeb450404fbbf44c92781e289f5ccdde746d739"},{"path":"exchange/crates/auths-proof-exchange-port/src/lib.rs","sha256":"b408fb40c6432edc1facb3d8b3e9433a033f8dc73fe2e0ba5a88c972ca675021"},{"path":"product/config/auths-config/Cargo.toml","sha256":"e4b568ab9f6d84f7d7e6d66443fe825f360db9c27bc7c31d6ddc0647ba3ab304"},{"path":"product/config/auths-config/src/lib.rs","sha256":"fecf00ea65cef9018fda9af2063326d7065b869266d0d9e73a4f06816f1102cc"},{"path":"product/errors/auths-errors/Cargo.toml","sha256":"3b3a199b6460ba75bda84475bb5accd35e1485448a3981038db85bf4772dd350"},{"path":"product/errors/auths-errors/src/lib.rs","sha256":"7feeb9069fa4003f94f1f07c1c94619cf1c883e0dbaaf2187f04d0f742264bdd"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/Cargo.toml","sha256":"716f1f2a117d6d69d8effe9ee9057e24ba3502f20af6a602b06facb638cdabed"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/api.rs","sha256":"9ea61dd7ddd93282b073b98e453e6b75b26dc49689c04e9782435d06a3a09e48"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/clock.rs","sha256":"73f0a6e0f5903883329fa6683f5888288f759512ac69e5c87efd2b6b87f7d79f"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/http.rs","sha256":"14c1fce14e24c984b2a275563a29b6326fb08367922b6e8d37ba38b9cb81aa2b"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/identity.rs","sha256":"186de11230c8b33375951c4368609f8976bf9795f171af3fd7fac26207a94361"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs","sha256":"0b4617d044f5254a5ab22f5a2578f91cc025206a8c1845be39c1c56dcdf7a5df"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/names.rs","sha256":"41bb23572d6002e23ee103d6fe70ecd68764861c6f2e48a1c53af998270a4afa"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs","sha256":"39fed883f4802e68d3b41a68fea0aba0737810996b33d13577de70faba004c29"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/store.rs","sha256":"fc60ee9c49b2f4f063c449b4c78100c5c4872779e94ca168f796603b380ef6e4"},{"path":"product/integrations/auths-custody/Cargo.toml","sha256":"1e14034185ad1ec24a977fd5f41d0abee219606245c046ce2a82287fadef448b"},{"path":"product/integrations/auths-custody/src/conformance.rs","sha256":"8ed1afd58f18fc6becc268908aa6419c9aa404c79da0197963eb2599df44acf6"},{"path":"product/integrations/auths-custody/src/key.rs","sha256":"70cbb0fd21b6f5652157845a22c35be2d0f6c05b3d138fc4b9bb6dbdc3d81c40"},{"path":"product/integrations/auths-custody/src/lib.rs","sha256":"8ee593c1f59b0fd2126bdda9138026f5bc531beb64d4489a99785842e7b98b43"},{"path":"product/operations/auths-operations/Cargo.toml","sha256":"73dde1e914ba5e1386f8d49c0d730423cc72ae77ec44c6554a6a75cc8e8922b1"},{"path":"product/operations/auths-operations/src/explanation.rs","sha256":"b4a39bcbd5712cb9e735ee7deeb281f3fa6af5ddca973735bf3d87dce427ef11"},{"path":"product/operations/auths-operations/src/lib.rs","sha256":"3f401a56555113b98f57bca172a2660eaecedf76247b83a3fdbb089c133a29cd"},{"path":"product/operations/auths-operations/src/render/json.rs","sha256":"2ae042639960afee123730e945d373bc5dda1d2b3af20ae16c939a7e99b9e418"},{"path":"product/operations/auths-operations/src/render/mod.rs","sha256":"b3b7f6fe473f49227ace5a68bfc3d8dc14b5db8dd9888fd9e207070337b1b8bf"},{"path":"product/operations/auths-operations/src/render/text.rs","sha256":"f216cf3bdb00e264523271b16e7059535ac6b1aabf271cebd7935af155e4bfec"},{"path":"product/policy/auths-bounded-policy/Cargo.toml","sha256":"babd5d200923137ead71d8c2528f847cea323ce98da942a1320b054436612c47"},{"path":"product/policy/auths-bounded-policy/src/arithmetic.rs","sha256":"75e43c5d4eab8d1f71c1daf53839f5f9fe45a400afc1f63a30c6f55ce3632627"},{"path":"product/policy/auths-bounded-policy/src/commitment.rs","sha256":"c5706f2d583454e1a7f570f7ada138d4d864bef0205dfae7c1296774f396bb3f"},{"path":"product/policy/auths-bounded-policy/src/eligibility.rs","sha256":"c9acdfb793074e687fc36efad506be27dbd99ffbf40387bc66c8de39ef238432"},{"path":"product/policy/auths-bounded-policy/src/identifier.rs","sha256":"0006a32bae9eb16c4178cf797df418d2b0a781f2bc6474b741dc1a908141831c"},{"path":"product/policy/auths-bounded-policy/src/kernel.rs","sha256":"99187c28b161ac70bee1afed60711f7f645adb4d1671a01863f9849b369811d5"},{"path":"product/policy/auths-bounded-policy/src/lib.rs","sha256":"76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c"},{"path":"product/policy/auths-bounded-policy/src/receipt.rs","sha256":"3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad"},{"path":"product/policy/auths-bounded-policy/src/registry.rs","sha256":"4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0"},{"path":"product/profiles/auths-profile-api/Cargo.toml","sha256":"7ae85761f58625b5d678f961fd052eebf3e000ef565c7312e3ac857763c0017f"},{"path":"product/profiles/auths-profile-api/src/lib.rs","sha256":"a194b82b20bf8aa864c2334ef6c6aec30b2154ded972862252d5dcefa488ab95"},{"path":"product/profiles/auths-profile-mcp/Cargo.toml","sha256":"db264fc25242f7b7e4133cbe5782545b3107b406c87168ae072683cfb59eac66"},{"path":"product/profiles/auths-profile-mcp/src/arguments.rs","sha256":"a5de696586d507e2aee4a49fee99ef1ef4c51a2e46603f8838f1af6d9009833f"},{"path":"product/profiles/auths-profile-mcp/src/lib.rs","sha256":"d0f8b733a09ef8408336cdebc8948d6a5861012ce6878598b11be7084dfd4280"},{"path":"product/profiles/auths-profile-mcp/src/session.rs","sha256":"166c281fa66333388e4760d6098dad02d3359e1d5de4b8f93312c014f97abb03"},{"path":"product/qualification/auths-recipe-qualification/Cargo.toml","sha256":"b7b15b30b9a3d96d4f089d514266d3a892de6608d30707aa44be31cca89ca9fe"},{"path":"product/qualification/auths-recipe-qualification/src/canonical.rs","sha256":"30a9b50777f0dcb4b606abfee2467d5a975d9f6ad941ab6c13ca3df5b359f667"},{"path":"product/qualification/auths-recipe-qualification/src/closure.rs","sha256":"0ad6aee9bd981e2863fa725f209ec84031db2ff12f4c7ac3aaf5120f0bb86039"},{"path":"product/qualification/auths-recipe-qualification/src/commissioning.rs","sha256":"db135c55e4e3079a73253ebae275536523eb36b545d1c152b4d7dce3c6b76828"},{"path":"product/qualification/auths-recipe-qualification/src/commissioning/tests.rs","sha256":"4dde3736d206099b1bea4c14e0092c6c1287d1af9065958777d7c54331dd8686"},{"path":"product/qualification/auths-recipe-qualification/src/error.rs","sha256":"52d5cf720a1e4579008fdda90a3ac2c31f0b8db57985f121f65e54b4da2b7dd1"},{"path":"product/qualification/auths-recipe-qualification/src/evidence.rs","sha256":"ba45a7409d67a8af26ab811af306412014557477a101ab2a8eb0faf8f2bd4b91"},{"path":"product/qualification/auths-recipe-qualification/src/ids.rs","sha256":"e81a906d571497ab2da753e1532d4443706410e0b75fdd59a7d2d788c7aec403"},{"path":"product/qualification/auths-recipe-qualification/src/launch.rs","sha256":"41f2e2de90e1e7d6440a66eda3eb9bea8d5e0741bc232305a76a363ab5f813c1"},{"path":"product/qualification/auths-recipe-qualification/src/lib.rs","sha256":"0e24b0f81191df0d078c7f4d73ced784ba9472372bfcdff3c7d0e2fb1687b323"},{"path":"product/qualification/auths-recipe-qualification/src/model.rs","sha256":"3484eb0ec287b23d4682ade7b1b0f8d1335985b3fb180f06fc28716076957d5f"},{"path":"product/qualification/auths-recipe-qualification/src/release.rs","sha256":"ec478e53f70052e566aac7e15be2f9e1b1cd46837ac6990ae955fa864d311586"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/mod.rs","sha256":"fa23a962fd90331152eed5edbcdf271955f7aed79b8da1e065bfe69a20b487a9"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/schemas.rs","sha256":"c59feec2805621f341a90f81fc005e2c12f7a70f9d264fdeacccb2be4fe1c046"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/verification.rs","sha256":"bdf5746fed4d10a7f577f7878619a917d29aa8b7d522f00d9f774e53eff4c8c1"},{"path":"product/qualification/auths-recipe-qualification/src/verify.rs","sha256":"2ec2784435d11e07295de77b2ee1b2c48b2fcf9609a00454c6e7374b621aed5c"},{"path":"product/receipts/auths-receipts/Cargo.toml","sha256":"6001fa1375899953aafcb07c23a6da0c8f57ea7ec08bb9c950b12a60a8cc6f0f"},{"path":"product/receipts/auths-receipts/src/disclosure.rs","sha256":"ba9ed439be0a320c8a01f5b6e9b51361c1a37e076947490d8e4a484ba6bb119c"},{"path":"product/receipts/auths-receipts/src/lib.rs","sha256":"547a57c4160256719cafb7d0ab972d9fc80b0da14fbbce4148c70c414070ff36"},{"path":"product/runtime/auths-connections/Cargo.toml","sha256":"babeb6e1dda3dfb66291713ce1e43dce5c349833d0b50ea4dccbf986030026b2"},{"path":"product/runtime/auths-connections/src/credential.rs","sha256":"82921413bb053f0f6c7931fbd4e6a86c8cc1d8c6b51debd9c2cef33a8d5b1c51"},{"path":"product/runtime/auths-connections/src/kernel.rs","sha256":"a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8"},{"path":"product/runtime/auths-connections/src/lib.rs","sha256":"79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22"},{"path":"product/runtime/auths-connections/src/model.rs","sha256":"de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77"},{"path":"product/runtime/auths-connections/src/registry.rs","sha256":"e57640e003e72ad3235c567c2bb944a262bd64e673f023b62ea091094cc7e946"},{"path":"product/runtime/auths-gateway-kernel/Cargo.toml","sha256":"34f864e67656af4ac7e5c7a347a23f01fc8ab31365b8e23c0ef474483b14a183"},{"path":"product/runtime/auths-gateway-kernel/src/construct.rs","sha256":"e9d65744bae273d65face4285e5d2da75c06a92ab48f7b8333d496604e31c63c"},{"path":"product/runtime/auths-gateway-kernel/src/lib.rs","sha256":"cfda6f8453426564c085475f183b6f790b438768a19668f1b65d33ba59dc8632"},{"path":"product/runtime/auths-gateway-kernel/src/order.rs","sha256":"e0045f877c4b7fe3860c291039853885064ddcdebba7c9b345ab65e81e646dda"},{"path":"product/runtime/auths-gateway-kernel/src/outcome.rs","sha256":"e9785b1afe70788c89b51b18655bcd5acff7b0c8e3d12fb79c6f05a202e67e6b"},{"path":"product/runtime/auths-gateway-kernel/src/ratio.rs","sha256":"7ace22264812e6fc1ef3a62afee402cf43494bb71ae0d3de219ad1b39d690bcb"},{"path":"product/runtime/auths-gateway-kernel/src/recovery.rs","sha256":"9f46dcd1685ab6e4d1ba04a3fc286a9f3afee8fb47829be1fbc670a7926a2dc6"},{"path":"product/runtime/auths-gateway-kernel/src/transition.rs","sha256":"cefb8f01d915880f6921f2501ff881ad94b9de61072c34d9cd19220992f97374"},{"path":"product/runtime/auths-gateway/Cargo.toml","sha256":"00b28be86921dcdc0ad90cce0c62c2961cafefe96ea6c2edf0e926c3d405ccad"},{"path":"product/runtime/auths-gateway/src/admin.rs","sha256":"0dee40a9fb67c5de10142fc37a7bbabdd8979fb0199fb26caf4bdb024e0a5a40"},{"path":"product/runtime/auths-gateway/src/app.rs","sha256":"6f80f63833ea0815bb44fbf3b0cc54624a08e9fb578b035819f2980dc04e8256"},{"path":"product/runtime/auths-gateway/src/audit.rs","sha256":"0edb2037eb7b5d6f13acfce85c54f62a82bf7fdd31bc7e626c4fec183cef61dd"},{"path":"product/runtime/auths-gateway/src/audit_tests.rs","sha256":"990969384a52d75bc2489d9d412a9e7dd814bca1c8f65c701d6205fae62a15d5"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway-harness.rs","sha256":"12b0c24d36b2e6a3be392d3c081a783b355fdd67dc5b54bacc0410e803116b8c"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway.rs","sha256":"b06a4c94bb349237b1941e7e2bc760bf779323fb4c1a2910e05a559ab638ec85"},{"path":"product/runtime/auths-gateway/src/binding.rs","sha256":"663b0ce878319511aa7d05722ab4ab2fa9be18817884ffb2ee9f131ff1e382d1"},{"path":"product/runtime/auths-gateway/src/bounds.rs","sha256":"38251ad6f22f9d07ef9a219c79fa265ca36f1526eca5f147d7efa46b52ad609d"},{"path":"product/runtime/auths-gateway/src/bounds_aggregate_tests.rs","sha256":"ab34f227b7c8692ba1da88ccb32bb3687a66adf8353d8282fae905d4a88eb612"},{"path":"product/runtime/auths-gateway/src/bounds_tests.rs","sha256":"74136bc570da7b9338b5a1a1ed9d3fd892c55135160964f9d3ac0e2cf5741375"},{"path":"product/runtime/auths-gateway/src/commissioning_budget.rs","sha256":"fab29da3269438cc62330f3eab7b5bd4dc482b4db8af243aae47df5d3aa1deb8"},{"path":"product/runtime/auths-gateway/src/commissioning_budget/tests.rs","sha256":"da104a1643c37515deec6397bca6db2054f2c9158ec3d230a1b1ec9c7d0f659f"},{"path":"product/runtime/auths-gateway/src/commissioning_floor.rs","sha256":"7fa6991c5ccd5ae1403be84b3da390323fab09f36e15ac01fd7a38ea350c6fdb"},{"path":"product/runtime/auths-gateway/src/commissioning_floor/tests.rs","sha256":"6b663d6e556adc0b455b81845bc4394d82c6c4de0c5f43e1310f3ddc6e4e40f7"},{"path":"product/runtime/auths-gateway/src/commissioning_session.rs","sha256":"24b48d5eaeaaa3c620e2dfc7ee1f9255fc4519a1eb404b8608cea7af6a910ee2"},{"path":"product/runtime/auths-gateway/src/commissioning_session/tests.rs","sha256":"37a097fc8a9261d3fffdaef3f905f40b22e3e6601bb5101fadd9414f963c0824"},{"path":"product/runtime/auths-gateway/src/connection.rs","sha256":"7b5d049c258a26ed1c93ecf860f51d051a8a65f9b93554af0b1ea93862398ec9"},{"path":"product/runtime/auths-gateway/src/credential_journal.rs","sha256":"7297fccaee5cd8622928e8e0a42bba50da7941970a6f682ecd300c41ee6509da"},{"path":"product/runtime/auths-gateway/src/echo_verify.rs","sha256":"6d453051665f823abd7354d5c50031d9524cf47d6092d2f09080ae814e3b9575"},{"path":"product/runtime/auths-gateway/src/engine.rs","sha256":"1abff20b98bc894c45bfc5c4414c81a99966d1ec95d924a5b0cd6f4c5626ca24"},{"path":"product/runtime/auths-gateway/src/execution_witness.rs","sha256":"e8b1a8e41d5e3fa309760067849d390ef065feeb46701a83391832645a2f000c"},{"path":"product/runtime/auths-gateway/src/fuzzing.rs","sha256":"ed3b0028487eb546a3b0a91d115aa8f18bcea324b61620bfe8e35a9e6ab18758"},{"path":"product/runtime/auths-gateway/src/generation_floor.rs","sha256":"fe1510ec96ce0f67e9a78edbfa94b33eb7df64c0ac4d0a67901124dcd0164777"},{"path":"product/runtime/auths-gateway/src/harness.rs","sha256":"c87e479f3eb281960f6c9c80d43c7560d7ccb654b0154ec823d3fcec4884ac05"},{"path":"product/runtime/auths-gateway/src/lib.rs","sha256":"fad95d031f88072dd024c78facf0bb0267562b1ac743ddd7219fce47e64024f0"},{"path":"product/runtime/auths-gateway/src/listener.rs","sha256":"aa08239bcbc1fcb55e8a212fbdf6a84f12985b0d436dcb51dc58b06e59e435f2"},{"path":"product/runtime/auths-gateway/src/observed_tests.rs","sha256":"a22be071695f89ca2578a4d82fd80d9cb82289213c9bdb8f0470f6b2dc3d9201"},{"path":"product/runtime/auths-gateway/src/observer.rs","sha256":"562ffcaea071c3856e0708dc2fe33516917e145d2438aabb75af0a2b6ba01046"},{"path":"product/runtime/auths-gateway/src/onboarding.rs","sha256":"0dfd7d67e7f02f18a28d1c86ca1b7751d7463f5efcdbe3825de0ad8cbccb3891"},{"path":"product/runtime/auths-gateway/src/operator.rs","sha256":"c3c36954a3e86723df035b47f43b85fc8ab3a6292983522b6258d5c6b4e6c4e4"},{"path":"product/runtime/auths-gateway/src/pending_vectors/attempts.rs","sha256":"47ef3c8cb1c5504d47ae9a0088705ce6715fe86bac1671a34a56fb38a64d0dd3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/bounds.rs","sha256":"e612217307e1da5b0eb5ee6582a7458bb064b8aa8a529fc6555b1b334127ab68"},{"path":"product/runtime/auths-gateway/src/pending_vectors/codes.rs","sha256":"e00670a5ef24eb856cc2c6dcda8e5a263842f55c76bb939c0c27bd9df37e5522"},{"path":"product/runtime/auths-gateway/src/pending_vectors/keys.rs","sha256":"f84c56f2ea9cb34b2b79c72d13fbf2c6585010ec1ed450af58a78c80c1ea1edd"},{"path":"product/runtime/auths-gateway/src/pending_vectors/mod.rs","sha256":"5de8340f0ef71a0b57a09e323fefe473d3160c6ae952b9ba46f714825fbacafc"},{"path":"product/runtime/auths-gateway/src/pending_vectors/outcomes.rs","sha256":"8ec07b9511b48913af36ac999d2aa0e82924289f6acb23ddaeb9f00f99815166"},{"path":"product/runtime/auths-gateway/src/pending_vectors/production.rs","sha256":"772d032e0a0d9c924fb6d6c188528db85a97e71c9e466ddc19eee277baf83614"},{"path":"product/runtime/auths-gateway/src/pending_vectors/recipes.rs","sha256":"51693208270231c25c3aef2a32151d5962114c71e86b88cb9df83181c7af83d9"},{"path":"product/runtime/auths-gateway/src/pre_entry.rs","sha256":"06ea78ca140468bfaba17d9ab04912ad68673954c3203c98fed28272ff2a00c0"},{"path":"product/runtime/auths-gateway/src/property_tests.rs","sha256":"939c081e2e154aaf10186754044bdd65608932c899b970a04a71d0afaa999a93"},{"path":"product/runtime/auths-gateway/src/qualification.rs","sha256":"c597c83de2b94f0374ae54e40a8b57c2a64ec6e254704dca32185f448a908aca"},{"path":"product/runtime/auths-gateway/src/qualification_simulation.rs","sha256":"4ee7cadfb5f46a92713c80f3e55f499cb074d04d8b21ea89d57762af38642bfa"},{"path":"product/runtime/auths-gateway/src/qualification_tests.rs","sha256":"a9178a2e58eea459d5e5dafc53a3999ea7c84dbbffefe6e5eb1f3d098827f028"},{"path":"product/runtime/auths-gateway/src/quorum_tests.rs","sha256":"a78380b019104d688c11a4410082c7e08ded3106aab099954c4f8a1b4ae0fd89"},{"path":"product/runtime/auths-gateway/src/readiness.rs","sha256":"911c3f11892f94641574375e2da4c671c802738f71082f12c39832331052d43d"},{"path":"product/runtime/auths-gateway/src/recipe.rs","sha256":"fecf9af67e7afc48d080e9f8f55f8ce28e49d0e08988717a27908bbda461d6b6"},{"path":"product/runtime/auths-gateway/src/recipe/lower.rs","sha256":"8088b8751ed831dbb48247af953c6290ac95e2a438ccd5bd65eff54be06a1fd1"},{"path":"product/runtime/auths-gateway/src/recipe/review.rs","sha256":"c3eb7d9fdd98dacf52750b14b67ad7b7faaecbbdeafff1e0b049f67d0a2d0139"},{"path":"product/runtime/auths-gateway/src/recipe/runtime.rs","sha256":"c286f0d15f974402822c0810d8e97f98411dc1c557755cc23e540d85e2bb42d9"},{"path":"product/runtime/auths-gateway/src/recipe/source.rs","sha256":"1af50298fb1461e1b24cbdf560d43124d6b1c4c529586c911b1c4797214a69ff"},{"path":"product/runtime/auths-gateway/src/recipe/tests.rs","sha256":"aac551a2481bbc60864c64079bc667dcb232e45a0f41a04073ed84ab5dbe1fce"},{"path":"product/runtime/auths-gateway/src/recipe/validate.rs","sha256":"3711b17605cb7b0d639bc1b180449231f5882a306cab20e2c7782155cc63b0d4"},{"path":"product/runtime/auths-gateway/src/scenario_tests.rs","sha256":"025b53473b3af6900e03bc2fee91aa63ed26a8778bc8c8296fe08f5540794c39"},{"path":"product/runtime/auths-gateway/src/separation.rs","sha256":"be9306848ca5d801767cf6aa14247c8618312ef0e202f00ce0c24c4844491061"},{"path":"product/runtime/auths-gateway/src/simulation_attestation.rs","sha256":"88705e5d45415f760f1e3c3a065c35c48f4f4065bf7b3feb7882246983814d6f"},{"path":"product/runtime/auths-gateway/src/store.rs","sha256":"884bcad4d70d53e12eae9c8517f6ecd0643068ee0be0370015119d04d6cc2516"},{"path":"product/runtime/auths-gateway/src/store_testkit.rs","sha256":"88d82fee42f1b8ef521e8deef0216e938ebeaad822eb2f5020e70b89d145ea70"},{"path":"product/runtime/auths-gateway/src/submit.rs","sha256":"fe2eacb5ad8152eeecbd232c47a356fc72db0098e34fda99532bdf6ef0cf895c"},{"path":"product/runtime/auths-gateway/src/support.rs","sha256":"9fd979029793a22b15d9776a7fc172476fd7c126a80d4080c65d720845becbcb"},{"path":"product/runtime/auths-gateway/src/transport.rs","sha256":"978fc9fb34a33b3db265b5d1c3ce11696a5b9f08529e46dd2a1e7bb62afb9220"},{"path":"product/runtime/auths-kernel-runtime/Cargo.toml","sha256":"926bcd0053e5edd703be8f0027ad009e2982db013c8174c1366edbf38b48087d"},{"path":"product/runtime/auths-kernel-runtime/src/lib.rs","sha256":"7108faae9ca4bc32dc093ddaf885ac8f74f3c9b8d317b7c7d0ed00d1d0ab5972"},{"path":"product/runtime/auths-lifecycle/Cargo.toml","sha256":"c5053c705f8d5554b44e432fe75287a2faf11d644e5a2552e45ad6cd94176af5"},{"path":"product/runtime/auths-lifecycle/src/codec.rs","sha256":"51c4b746749150e8bfcd8ff972b3f6c1ef40bec15583448ec1b471d9ad737dc0"},{"path":"product/runtime/auths-lifecycle/src/digest.rs","sha256":"55282cd7d8aba37713c2dcb5357c9877819edb72a30eadefb860d28d7d3a3eb7"},{"path":"product/runtime/auths-lifecycle/src/identifier.rs","sha256":"31620e8c16de68d3d2d3b84d6353c1a5b9d4151d8247f91fa389b906a8e660f1"},{"path":"product/runtime/auths-lifecycle/src/kernel.rs","sha256":"2abb8c094b36d35b364e74d78091d14c5d6f3d1eb6552cca3b5538dbd017ce23"},{"path":"product/runtime/auths-lifecycle/src/lib.rs","sha256":"afe5a345cd309b5a4f08ffba3170a6d7f16ff914892b3f2006d5208ed24ec736"},{"path":"product/runtime/auths-lifecycle/src/model.rs","sha256":"1af12bbeeeaa65ec02ddcebd7d2c8c92ec1e339fa40ae85b45ab9b01a722a4fa"},{"path":"product/runtime/auths-lifecycle/src/operation.rs","sha256":"78e6d05fcf5d7ea4f148032a3fa26fdfcab77eb346019effe927b08e0d64d732"},{"path":"product/runtime/auths-lifecycle/src/registry.rs","sha256":"53495fe6f7a77422593a41623e28716f1c140dcc1e00f87f6b0ffbfb93a5ef90"},{"path":"product/runtime/auths-lifecycle/src/sealed.rs","sha256":"2e0c03b5813c926c159598bb7890d1523825edbe57cd687d42a5dfb3374a0c19"},{"path":"product/runtime/auths-lifecycle/src/test_support.rs","sha256":"221d9a5c5ef8e1f9f8fd66927484eaf813571d0568470278ecd8fa08a5eec8cd"},{"path":"product/runtime/auths-lifecycle/src/transition.rs","sha256":"011805a28efdd541f44ccea54dd0e34a1e58f4004447ee58013703b4fb6b2822"},{"path":"product/runtime/auths-runtime/Cargo.toml","sha256":"dd29d80a8b4bb56c869f036a6c9998f6e6d1c0383ac5dc03fa42b24abe2a7ff7"},{"path":"product/runtime/auths-runtime/src/lib.rs","sha256":"132ca03d58c14905d3a822a4972f42a22a5ad33a45f2ba9ca44f3a57d810b4b0"},{"path":"product/runtime/auths-runtime/src/production.rs","sha256":"fd4eff4270c571c10fcff6cf27df28961ebf074de8a1a028f500fda1ca376820"},{"path":"product/sdk/auths-approval-quorum/Cargo.toml","sha256":"df904971fca87a24194c5816738a331588fe8f164acb5d70839a35dca5f57114"},{"path":"product/sdk/auths-approval-quorum/src/lib.rs","sha256":"72e4086088a1c0912e4e1a9e980f26a5c280bf5ab16ea39c9f0f58d5096ac2ce"},{"path":"product/sdk/auths-approval-quorum/src/remote.rs","sha256":"9fa029c7c63003adf260f8aec55160c545681c60c1bace0d934e7525862aac7b"},{"path":"product/sdk/auths-approval-quorum/src/remote_tests.rs","sha256":"8a09ce17cfee82a035a74edd535f3ebeb3db0e078784740d3997b17dbdb10197"},{"path":"product/sdk/auths-approval-quorum/src/tests.rs","sha256":"0acbf12be3e497dcc6c2d8f29c9af3b1a7ed8e11b75f6399570d4f217a785060"},{"path":"product/stores/auths-stores/Cargo.toml","sha256":"a32c4b76d17b264be5d40d24497ff237e1ed87822e8bab86229b3db93106dbe3"},{"path":"product/stores/auths-stores/src/gateway_attempt.rs","sha256":"218841602d3d9b23b44625f50e5b54cf275ccedc2d5c89f02d2482b8524472af"},{"path":"product/stores/auths-stores/src/lib.rs","sha256":"e721262edf8a9ab5568ddc27639176312d4a366203b5f73e2d7c11fde2c554e9"},{"path":"product/stores/auths-stores/src/lifecycle.rs","sha256":"3f2cecfda13fdcd7c4a944518646bcc8abd1237f900c0332d5822281f8f9f1cd"}],"schema":"auths.gateway-semantic-closure/1"} \ No newline at end of file diff --git a/product/runtime/auths-gateway/src/bin/auths-gateway.rs b/product/runtime/auths-gateway/src/bin/auths-gateway.rs index 5d05fc0d8..221f02f6f 100644 --- a/product/runtime/auths-gateway/src/bin/auths-gateway.rs +++ b/product/runtime/auths-gateway/src/bin/auths-gateway.rs @@ -2751,6 +2751,40 @@ mod unix { } } + async fn commissioned_submission( + session: &auths_gateway::CommissioningSession<'_>, + engine: &GatewayEngine, + proof: &[u8], + action: &[u8], + witness_file: Option<&Path>, + before: &auths_gateway::GatewayExecutionWitness, + ) -> Result<(GatewaySubmitResult, Option<&'static str>), Failure> { + let Some(path) = witness_file else { + return Ok((session.submit(proof, action).await, None)); + }; + let mut witness = CommissioningWitnessFile::open(path)?; + witness.record(before.clone())?; + let submission = session.submit(proof, action); + tokio::pin!(submission); + let mut interval = tokio::time::interval(Duration::from_millis(10)); + interval.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip); + let mut diagnostic_failure = None; + let result = loop { + tokio::select! { + result = &mut submission => break result, + _ = interval.tick(), if diagnostic_failure.is_none() => { + diagnostic_failure = witness.record(engine.execution_witness()).err(); + } + } + }; + // A full or broken stream cannot interrupt an entered attempt. + // Report diagnostic failure only after that native attempt finishes. + let final_record = witness.record(engine.execution_witness()); + diagnostic_failure = diagnostic_failure.or(final_record.err()); + diagnostic_failure = diagnostic_failure.or(witness.finish().err()); + Ok((result, diagnostic_failure)) + } + /// Direct operator process; ordinary application handlers never call this. async fn commissioning( options: &CommissioningOptions, @@ -2811,34 +2845,15 @@ mod unix { let proof = read_bounded(proof, 4 * 1024 * 1024)?; let action = read_bounded(action, 64 * 1024)?; let before = engine.execution_witness(); - let mut witness = witness_file - .map(CommissioningWitnessFile::open) - .transpose()?; - if let Some(witness) = &mut witness { - witness.record(before.clone())?; - } - let submission = session.submit(&proof, &action); - tokio::pin!(submission); - let mut interval = tokio::time::interval(Duration::from_millis(10)); - interval.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip); - let mut diagnostic_failure = None; - let result = loop { - tokio::select! { - result = &mut submission => break result, - _ = interval.tick(), if witness.is_some() && diagnostic_failure.is_none() => { - if let Some(witness) = &mut witness { - diagnostic_failure = witness.record(engine.execution_witness()).err(); - } - } - } - }; - if let Some(witness) = &mut witness { - // Even a full or broken stream cannot interrupt an entered - // attempt. Report diagnostic failure only after it finishes. - let final_record = witness.record(engine.execution_witness()); - diagnostic_failure = diagnostic_failure.or(final_record.err()); - diagnostic_failure = diagnostic_failure.or(witness.finish().err()); - } + let (result, diagnostic_failure) = commissioned_submission( + &session, + &engine, + &proof, + &action, + witness_file, + &before, + ) + .await?; let measured = serde_json::json!({ "schema": "auths.gateway-commissioning-execution/1", "result": result, diff --git a/product/runtime/auths-gateway/src/semantic_closure.rs b/product/runtime/auths-gateway/src/semantic_closure.rs index ffef9763a..83c7af04c 100644 --- a/product/runtime/auths-gateway/src/semantic_closure.rs +++ b/product/runtime/auths-gateway/src/semantic_closure.rs @@ -10,7 +10,7 @@ /// SHA-256 of the schema, a NUL byte, and `semantic-closure.json`. /// Regenerate through `semantic_closure_is_current` with `AUTHS_UPDATE_FIXTURES=1`. pub const GATEWAY_SEMANTIC_CLOSURE_SHA256: &str = - "a5ac19cd47f7e6b2c9c6b537a923756e8592784b11e4642e3f46915c84ae9974"; + "e493fbb956c834cb3ae5cc20c6b33dfadb18d0343e81fcb9171956814dde3997"; #[cfg(test)] mod tests { diff --git a/qualification/reference/README.md b/qualification/reference/README.md index a3a6a6a0b..10320b4fb 100644 --- a/qualification/reference/README.md +++ b/qualification/reference/README.md @@ -46,6 +46,10 @@ Each packet contains `label`, `proof`, `action`, `trusted_context` (adjacent fil expected `arguments`. Unknown fields, path traversal, changed source, wrong production targets, resource widening, actor changes or an oracle mismatch prevent output. Filenames never select code. Private author keys are absent. +The signing expansion reconstructs the entire original source-owned packet +pool, including both phase operations and both fresh-challenge replays. Missing, +additional, reordered or rebound packets cannot receive a permit. A one-packet +refresh is a private execution handoff, never a new signing input. The protected family setup, complete corpus and live workflow still need to use these references. No family is qualified by landing this code. @@ -58,8 +62,15 @@ context, duplicate or reordered list, changed set, or schema 1 permit refuses. The public packet author supplies two native challenges under one exact actor and grant. Each phase's first resource has a `-fresh` replay packet with the same logical operation and arguments, under the second context. Refresh never changes -that packet's assigned challenge, action or context. At most 31 resources fit -the finite 64-packet ceiling including both replay packets. The source-owned +that packet's assigned challenge, action or context. At most 31 Airtable or 29 +Stripe resources fit the finite 64-packet ceiling. Stripe also has two exact +guard probes per phase: 1001 cents against a 2000-cent payment, and EUR against +that USD payment. Their native proofs authorize request construction; the real +relative-ceiling read must refuse them after one custody lease and before any +write. A permit never replaces that guard. The grant has bounded USD/EUR sum +partitions so the currency probe can reach the provider-read guard; every +payment remains scoped to the exact reviewed test ledger. Source plan schema 3 +refuses obsolete plans. The source-owned protected corpus and native durable replay evidence still need integration. `measure.py` validates and subtracts native execution snapshots: matching fresh @@ -67,6 +78,17 @@ scope, no saturation/decrease, no duplicate host in an aggregate. Restarted engines must be measured separately. Budget consumption is never substituted for actual custody calls. +`native_observation.py` projects actual native results and measured counter +deltas into corpus facts. A recorded HTTP response or unlinked value match +cannot become a confirmed effect. Linked evidence requires a new independent +provider read with the reviewed exact state/echo and identical raw response +digest. Its bounded journey ledger counts each measured entered write once; +read-only recovery can confirm that earlier write, and subsequent observations +cannot count it again. Changed tuples/actions, scope drift, duplicate entries, +unmeasured effects and additional result fields refuse. The helper does not +assert isolation, installed-consumer provenance or a passing wall; the family +harness must measure those separately and the native runner decides the case. + `fresh_evidence.py` is the separate response oracle for the reviewed Stripe refund and Airtable update. It validates the approved resource, exact intended value, test-mode success (Stripe) and the action-derived echo, then hashes the diff --git a/qualification/reference/check_packets.py b/qualification/reference/check_packets.py index 585c15be3..3d43597ff 100644 --- a/qualification/reference/check_packets.py +++ b/qualification/reference/check_packets.py @@ -18,7 +18,7 @@ import stripe_platform from common import Refusal, canonical, require, sha256 from expand import child, decode, read -from packet_plan import prepare +from packet_plan import prepare, public_pool from resource_io import finish, write @@ -68,6 +68,7 @@ def check(args): require(response(process) == {'schema': 'auths.qualification-author-session/1', 'state': 'ready'}, 'qualification.packets.author-response') plan = decode(read(work / 'public-packets.json', 65536)) + public_pool(reference.FAMILY, resources, plan['packets'][0]['arguments']['recipe_digest'], plan) reviewed = [] for packet in plan['packets']: value = review(args.gateway, work, packet, plan['evaluated_at']) diff --git a/qualification/reference/check_socket.py b/qualification/reference/check_socket.py index 0ff02a802..32bd83a24 100644 --- a/qualification/reference/check_socket.py +++ b/qualification/reference/check_socket.py @@ -18,7 +18,7 @@ from check_packets import review from common import require, sha256 from expand import decode, read -from packet_plan import prepare +from packet_plan import prepare, public_pool from resource_io import finish, write AUTHOR_UID = 62002 @@ -73,6 +73,7 @@ def check(args): try: ready(process, work) original = decode(read(work / 'public-packets.json', 65536)) + public_pool(reference.FAMILY, resources, original['packets'][0]['arguments']['recipe_digest'], original) initial = review(args.gateway, work, original['packets'][0], original['evaluated_at']) # Separate connections and fresh output directories simulate the # runner handing public packets across independent job steps. diff --git a/qualification/reference/expand.py b/qualification/reference/expand.py index 11ea03055..026354169 100644 --- a/qualification/reference/expand.py +++ b/qualification/reference/expand.py @@ -116,6 +116,10 @@ def expand(args): and read(args.profile_lock, 65536) == read(source / 'profile.lock.json', 65536), 'qualification.reference.reviewed-source') plan = decode(read(args.packets, 65536)) + # Import after this module's byte/I/O helpers are defined: the packet + # planner also uses them when constructing the installed author's input. + from packet_plan import public_pool + public_pool(reference.FAMILY, bound_resources, tuple_value['compiled_recipe_sha256'], plan) closed(plan, ['schema', 'protected_run', 'evaluated_at', 'not_after', 'trusted_contexts', 'packets']) require(plan['schema'] == 'auths.qualification-public-packets/3' and plan['protected_run'] == protected_run @@ -159,7 +163,9 @@ def expand(args): actors.add(reviewed['actors'][0]) commitments.add(commitment) oracle.append({'label': label, 'request_sha256': sha256(canonical(expected)), - 'action_commitment': commitment, 'trusted_context_sha256': context_hashes[packet['trusted_context']]}) + 'action_commitment': commitment, 'trusted_context_sha256': context_hashes[packet['trusted_context']], + 'entry_policy_code': reference.entry_policy(packet['arguments'], bound_resources) + if reference is stripe_platform else None}) require(len(actors) == 1, 'qualification.reference.principal-binding') require(used_contexts == set(context_names), 'qualification.reference.context-bound') tuple_digest = sha256(b'auths.qualification-tuple/1\0' + canonical(tuple_value)) @@ -178,7 +184,7 @@ def expand(args): args.out_dir.mkdir(mode=0o700) (args.out_dir / 'binding.json').write_bytes(canonical(binding)) (args.out_dir / 'oracle-commitments.json').write_bytes(canonical({ - 'schema': 'auths.qualification-reference-expansion/1', + 'schema': 'auths.qualification-reference-expansion/2', 'protected_run': protected_run, 'source_commit': commit, 'binding_sha256': sha256(canonical(binding)), 'oracle': oracle, 'qualification_issued': False, diff --git a/qualification/reference/native_observation.py b/qualification/reference/native_observation.py new file mode 100644 index 000000000..7658e2636 --- /dev/null +++ b/qualification/reference/native_observation.py @@ -0,0 +1,137 @@ +"""Release-only projection of actual native results and independent read-back. + +No passed flag, expected verdict, budget consumption or HTTP success can +substitute for native execution counters or provider evidence. This helper +returns measured facts only; the native corpus runner compares them with the +source-owned case. It grants no authority and never performs provider I/O. +""" + +import re + +import airtable_record +import stripe_platform +from common import canonical, closed, digest, echo, integer, require, sha256, text +import fresh_evidence +import measure + + +REFERENCES = {reference.FAMILY: reference for reference in [stripe_platform, airtable_record]} + + +def result(value): + """Decode exactly one native result, retaining every meaningful distinction.""" + require(type(value) is dict and type(value.get('outcome')) is str, + 'qualification.observation.result') + kind = value['outcome'] + if kind in ['denied', 'indeterminate', 'not-entered']: + closed(value, ['outcome', 'code']) + code = text(value['code'], maximum=96) + require(re.fullmatch(r'[a-zA-Z0-9][a-zA-Z0-9._-]{0,95}', code) is not None, + 'qualification.observation.code') + return 'refused', code, None + if kind == 'unknown': + closed(value, ['outcome']) + return 'unknown', kind, None + if kind == 'response-recorded': + closed(value, ['outcome', 'status']) + integer(value['status'], 100, 599) + return 'response-recorded', kind, None + if kind == 'observed': + # Value equality alone cannot produce the linked evidence required + # by these two reviewed families. Retain no positive effect claim. + closed(value, ['outcome', 'status', 'matched']) + integer(value['status'], 100, 599) + require(type(value['matched']) is bool, 'qualification.observation.result') + return 'response-recorded', 'unlinked-observation', None + require(kind == 'observed-by-provider', 'qualification.observation.result') + closed(value, ['outcome', 'status', 'evidence']) + if value['status'] is not None: + integer(value['status'], 100, 599) + evidence = value['evidence'] + closed(evidence, ['channel', 'echo', 'evidence_digest', 'observed_at']) + require(evidence['channel'] == 'read-back', 'qualification.observation.channel') + digest(evidence['evidence_digest']) + integer(evidence['observed_at'], 0, 253402300799) + text(evidence['echo'], maximum=128) + return 'observed', kind, evidence + + +class Effects: + """One journey's measured entries and confirmations, keyed by exact action. + + A read-only recovery can confirm the previously measured entered write. + Further read-backs cannot count that write again. A fresh engine scope + still needs its own before/after measurement; native scope validation is + never replaced by this ledger. + """ + + def __init__(self): + self.entries = {} + self.tuple_sha256 = None + + def project(self, tuple_value, reviewed, resources, native_result, before, after, response=None): + tuple_sha256 = sha256(b'auths.qualification-tuple/1\0' + canonical(tuple_value)) + require(self.tuple_sha256 in [None, tuple_sha256], 'qualification.observation.changed-tuple') + family = tuple_value['recipe_family'] + reference = REFERENCES.get(family) + require(reference is not None, 'qualification.observation.family') + reference.resources(resources, resources['protected_run']) + closed(reviewed, ['schema', 'actors', 'action_commitment', 'arguments', 'request']) + require(reviewed['schema'] == 'auths.gateway-submission-review/1' + and type(reviewed['actors']) is list and len(reviewed['actors']) == 1, + 'qualification.observation.review') + text(reviewed['actors'][0], maximum=1024) + commitment = digest(reviewed['action_commitment']) + recipe_digest = digest(tuple_value['compiled_recipe_sha256']) + arguments = reviewed['arguments'] + expected_request = reference.request(arguments, resources, commitment, recipe_digest) + require(reviewed['request'] == expected_request, 'qualification.observation.request') + counted = measure.delta(before, after) + leases = integer(counted['credential_lease_calls'], 0, (1 << 32) - 1) + writes = integer(counted['write_transport_entries'], 0, 1) + outcome, code, evidence = result(native_result) + require(outcome != 'refused' or writes == 0, 'qualification.observation.refused-entry') + key = (family, resources['protected_run'], arguments['operator_namespace'], arguments['operation_id']) + binding = sha256(canonical({'arguments': arguments, 'action_commitment': commitment, + 'resources': resources, 'recipe_digest': recipe_digest})) + prior = self.entries.get(key) + require(writes == 0 or prior is None, 'qualification.observation.duplicate-entry') + require(writes == 0 or len(self.entries) < 64, 'qualification.observation.entry-bound') + require(writes == 0 or leases > 0, 'qualification.observation.entry-without-lease') + require(outcome == 'refused' or prior is None or prior['binding'] == binding, + 'qualification.observation.changed-action') + fresh, confirmed = None, 0 + if evidence is None: + require(response is None, 'qualification.observation.unexpected-response') + else: + require(type(response) is bytes and (writes == 1 or prior is not None), + 'qualification.observation.unmeasured-effect') + require(native_result['status'] == 200 + or (native_result['status'] is None and reference is airtable_record), + 'qualification.observation.status') + require(evidence['echo'] == echo(arguments['operator_namespace'], arguments['operation_id'], commitment), + 'qualification.observation.echo') + fresh = fresh_evidence.witness(family, arguments, resources, commitment, recipe_digest, response) + require(fresh['response_sha256'] == evidence['evidence_digest'], + 'qualification.observation.response-digest') + confirmed = int(prior is None or not prior['confirmed']) + # Refusals, malformed results and evidence disagreements leave the + # ledger untouched. There is no usable projection on those failures. + if writes == 1: + self.entries[key] = {'binding': binding, 'confirmed': evidence is not None} + self.tuple_sha256 = tuple_sha256 + elif evidence is not None: + prior['confirmed'] = True + return {'verdict': {'outcome': outcome, 'code': code, + 'request_sha256': None if outcome == 'refused' else sha256(canonical(reviewed['request'])), + 'evidence_sha256': None if evidence is None else evidence['evidence_digest']}, + 'credential_leases': leases, 'provider_entries': writes, + 'confirmed_by_read_back': confirmed}, fresh + + def commissioning(self, tuple_value, reviewed, resources, execution, response=None): + """Read the private command's actual final envelope, not a report flag.""" + closed(execution, ['schema', 'result', 'before', 'after']) + require(execution['schema'] == 'auths.gateway-commissioning-execution/1', + 'qualification.observation.schema') + return self.project(tuple_value, reviewed, resources, execution['result'], + execution['before'], execution['after'], response) diff --git a/qualification/reference/packet_plan.py b/qualification/reference/packet_plan.py index e2c14974f..858e6fe28 100644 --- a/qualification/reference/packet_plan.py +++ b/qualification/reference/packet_plan.py @@ -50,13 +50,47 @@ def arguments(family, resources, recipe_digest): # predeclared challenge. It is replay evidence, never a second # planned write or caller-selected authoring authority. packets.append({'label': label + '-fresh', 'context': 'fresh', 'arguments': dict(value)}) + if reference is stripe_platform: + for kind, changed in [('ceiling', {'amount': 1001}), ('currency', {'currency': 'eur'})]: + label = phase + '-guard-' + kind + probe = dict(value, **changed) + probe['operation_id'] = 'qlf-' + sha256(canonical([family, resources['protected_run'], label]))[:48] + # These valid native actions are deliberately outside the + # provider's relative guard, so the corpus can measure its + # real post-lease refusal rather than a permit refusal. + reference.request(probe, resources, '0' * 64, recipe_digest) + require(reference.entry_policy(probe, resources) is not None, + 'qualification.packets.probe-binding') + packets.append({'label': label, 'context': 'initial', 'arguments': probe}) return packets +def public_pool(family, resources, recipe_digest, carrier): + """Reconstruct the entire source-owned pool before signing any authority. + + This checks the original carrier, not a one-packet refresh. Native review + still authenticates each proof and both distinct context byte strings. + """ + closed(carrier, ['schema', 'protected_run', 'evaluated_at', 'not_after', + 'trusted_contexts', 'packets']) + require(carrier['schema'] == 'auths.qualification-public-packets/3' + and carrier['protected_run'] == resources['protected_run'] + and carrier['trusted_contexts'] == ['context-0.cbor', 'context-1.cbor'], + 'qualification.packets.pool-binding') + planned = arguments(family, resources, recipe_digest) + expected = [{'label': packet['label'], 'proof': packet['label'] + '.proof', + 'action': packet['label'] + '.action', + 'trusted_context': 'context-' + str(['initial', 'fresh'].index(packet['context'])) + '.cbor', + 'arguments': packet['arguments']} for packet in planned] + require(4 <= len(expected) <= 64 and carrier['packets'] == expected, + 'qualification.packets.pool-binding') + return expected + + def validate(plan): closed(plan, ['schema', 'family', 'protected_run', 'evaluated_at', 'not_after', 'configuration', 'extension', 'resources', 'packets']) - require(plan['schema'] == 'auths.qualification-packet-plan/2' + require(plan['schema'] == 'auths.qualification-packet-plan/3' and type(plan['family']) is str and plan['family'] in REFERENCES, 'qualification.packets.schema') run_id(plan['protected_run']) @@ -72,9 +106,11 @@ def validate(plan): for packet in packets: closed(packet, ['label', 'context', 'arguments']) require(type(packet['label']) is str and packet['label'] not in labels - and packet['label'] in {phase + '-' + str(index).zfill(2) + suffix + and packet['label'] in ({phase + '-' + str(index).zfill(2) + suffix for phase in ['commissioning', 'live'] for index in range(32) for suffix in (['', '-fresh'] if index == 0 else [''])} + | ({phase + '-guard-' + kind for phase in ['commissioning', 'live'] + for kind in ['ceiling', 'currency']} if plan['family'] == stripe_platform.FAMILY else set())) and packet['context'] == ('fresh' if packet['label'].endswith('-fresh') else 'initial'), 'qualification.packets.packet-bound') labels.add(packet['label']) @@ -126,11 +162,11 @@ def prepare(args): extension = None if reference is stripe_platform: derived = child(args.gateway, ['bound-extension', '--argument', 'amount', '--ceiling', '10000', - '--window-seconds', '86400', '--max-count', '64', '--sum-limit', '32000', '--partition', 'currency=usd', + '--window-seconds', '86400', '--max-count', '64', '--sum-limit', '32000', '--partition', 'currency=usd,eur', '--scope', 'payment_intent=' + ','.join(payment['id'] for payment in resources['payments'])]) extension = {name: derived[name] for name in ['extension_id', 'extension_body_hex']} evaluated_at = int(time.time()) - plan = validate({'schema': 'auths.qualification-packet-plan/2', 'family': args.family, + plan = validate({'schema': 'auths.qualification-packet-plan/3', 'family': args.family, 'protected_run': resources['protected_run'], 'evaluated_at': evaluated_at, 'not_after': evaluated_at + PACKET_VALIDITY, 'configuration': review['verifier_configuration'], 'extension': extension, 'resources': resources, diff --git a/qualification/reference/stripe_platform.py b/qualification/reference/stripe_platform.py index 972532f66..727a342da 100644 --- a/qualification/reference/stripe_platform.py +++ b/qualification/reference/stripe_platform.py @@ -39,13 +39,14 @@ def request(arguments, bound_resources, action_commitment, recipe_digest): 'qualification.reference.recipe-binding') operation = text(arguments['operation_id'], maximum=128) amount = integer(arguments['amount'], 1, 99999999) - require(arguments['currency'] == 'usd', 'qualification.reference.currency-binding') + require(arguments['currency'] in ['usd', 'eur'], 'qualification.reference.currency-binding') payment = next((item for item in bound_resources['payments'] if item['id'] == arguments['payment_intent']), None) require(payment is not None, 'qualification.reference.resource-binding') - # Only bounded actions that the reviewed live run may actually execute - # enter a permit. Rejected boundary vectors stay in the offline corpus. - require(amount <= 10000 and amount * 10000 <= payment['amount_received'] * 5000, + # Request mapping also covers the two source-owned provider-read refusal + # probes. The native guard, not this encoder or the permit, must refuse + # them after custody and before write entry. No caller chooses their values. + require(amount <= 10000, 'qualification.reference.ceiling') token = echo(SERVICE, operation, action_commitment) key = idempotency(SERVICE, operation) @@ -61,6 +62,18 @@ def request(arguments, bound_resources, action_commitment, recipe_digest): } +def entry_policy(arguments, bound_resources): + """Independent expected decision over the reviewed fresh payment facts.""" + request(arguments, bound_resources, '0' * 64, arguments['recipe_digest']) + payment = next(item for item in bound_resources['payments'] + if item['id'] == arguments['payment_intent']) + if arguments['currency'] != payment['currency']: + return 'gateway.relative-ceiling.binding-mismatch' + if arguments['amount'] * 10000 > payment['amount_received'] * 5000: + return 'gateway.relative-ceiling.above' + return None + + def recipe(template, bound_resources): # No resource or platform header is substituted into this family. require(template['service'] == SERVICE and template['tool'] == TOOL diff --git a/qualification/reference/tests/test_native_observation.py b/qualification/reference/tests/test_native_observation.py new file mode 100644 index 000000000..eab6f31d2 --- /dev/null +++ b/qualification/reference/tests/test_native_observation.py @@ -0,0 +1,112 @@ +"""Closed native/result projection boundaries; synthetic, never qualification.""" + +import copy +from pathlib import Path +import sys +import unittest + +sys.path.insert(0, str(Path(__file__).resolve().parents[1])) +import airtable_record as airtable +from common import Refusal, canonical, echo, sha256 +from native_observation import Effects, result + + +class Observations(unittest.TestCase): + def setUp(self): + self.run = 'recipe-qualification/123/1' + self.resources = {'schema': 'auths.airtable-record-qualification-resources/1', + 'protected_run': self.run, 'base': airtable.BASE, 'table': airtable.TABLE, + 'records': [{'id': 'recTEST0000000001', 'run_metadata': self.run}]} + self.tuple = {'recipe_family': airtable.FAMILY, 'compiled_recipe_sha256': '1' * 64} + self.arguments = {'operator_namespace': 'airtable-demo', 'operation_id': 'qualified-1', + 'recipe_digest': '1' * 64, 'record_id': 'recTEST0000000001', 'replacement': 'Approved'} + self.review = {'schema': 'auths.gateway-submission-review/1', + 'actors': ['raw:synthetic-test-only-actor'], 'action_commitment': '2' * 64, + 'arguments': self.arguments, + 'request': airtable.request(self.arguments, self.resources, '2' * 64, '1' * 64)} + self.before = {'schema': 'auths.gateway-execution-witness/1', 'scope': '1' * 32, + 'credential_lease_calls': 0, 'write_transport_entries': 0, 'read_transport_entries': 0} + self.after = dict(self.before, credential_lease_calls=1, write_transport_entries=1, + read_transport_entries=1) + token = echo('airtable-demo', 'qualified-1', '2' * 64) + self.response = canonical({'id': 'recTEST0000000001', + 'fields': {'DemoStatus': 'Approved', 'auths_echo': token}}) + self.observed = {'outcome': 'observed-by-provider', 'status': 200, + 'evidence': {'channel': 'read-back', 'echo': token, + 'evidence_digest': sha256(self.response), 'observed_at': 1000}} + + def project(self, ledger, value, before=None, after=None, response=None, review=None): + return ledger.project(self.tuple, review or self.review, self.resources, value, + before or self.before, after or self.after, response) + + def test_http_success_never_becomes_a_confirmed_effect(self): + facts, fresh = self.project(Effects(), {'outcome': 'response-recorded', 'status': 200}) + self.assertEqual(facts['verdict']['outcome'], 'response-recorded') + self.assertEqual(facts['confirmed_by_read_back'], 0) + self.assertIsNone(fresh) + self.assertEqual(result({'outcome': 'observed', 'status': 200, 'matched': True})[0], 'response-recorded') + for value in [{'outcome': 'observed-by-provider', 'status': 200}, + {'outcome': 'unknown', 'passed': True}, + {'outcome': 'response-recorded', 'status': True}, + {'outcome': 'refused', 'code': 'pretend-success'}]: + with self.assertRaises(Refusal): result(value) + + def test_only_one_actual_entered_write_can_be_confirmed_once(self): + ledger = Effects() + facts, fresh = self.project(ledger, self.observed, response=self.response) + self.assertEqual((facts['provider_entries'], facts['confirmed_by_read_back']), (1, 1)) + self.assertEqual(fresh['response_sha256'], sha256(self.response)) + repeated, _ = self.project(ledger, self.observed, before=self.after, after=self.after, + response=self.response) + self.assertEqual((repeated['provider_entries'], repeated['confirmed_by_read_back']), (0, 0)) + with self.assertRaisesRegex(Refusal, 'duplicate-entry'): + self.project(ledger, self.observed, response=self.response) + with self.assertRaisesRegex(Refusal, 'unmeasured-effect'): + self.project(Effects(), self.observed, before=self.after, after=self.after, response=self.response) + + def test_a_read_only_recovery_confirms_only_its_measured_unknown_write(self): + ledger = Effects() + unknown, fresh = self.project(ledger, {'outcome': 'unknown'}) + self.assertEqual(unknown['confirmed_by_read_back'], 0) + self.assertIsNone(fresh) + resumed = dict(self.after, credential_lease_calls=2, read_transport_entries=2) + recovered, _ = self.project(ledger, dict(self.observed, status=None), + before=self.after, after=resumed, response=self.response) + self.assertEqual((recovered['credential_leases'], recovered['provider_entries'], + recovered['confirmed_by_read_back']), (1, 0, 1)) + again, _ = self.project(ledger, self.observed, before=resumed, after=resumed, + response=self.response) + self.assertEqual(again['confirmed_by_read_back'], 0) + + def test_wrong_response_echo_request_scope_and_ambiguous_claims_refuse(self): + for problem in ['raw-bytes', 'echo', 'request', 'scope', 'extra-field', 'refused-entry']: + ledger, value, review = Effects(), copy.deepcopy(self.observed), copy.deepcopy(self.review) + after, response = dict(self.after), self.response + if problem == 'raw-bytes': response += b' ' + if problem == 'echo': value['evidence']['echo'] = 'forged-echo' + if problem == 'request': review['request']['url'] = 'https://attacker.invalid/write' + if problem == 'scope': after['scope'] = '2' * 32 + if problem == 'extra-field': value['evidence']['provider_token'] = 'synthetic-forbidden-input' + if problem == 'refused-entry': value = {'outcome': 'not-entered', 'code': 'gateway.attempt.replay'}; response = None + with self.subTest(problem=problem), self.assertRaises(Refusal): + self.project(ledger, value, after=after, response=response, review=review) + self.assertEqual(ledger.entries, {}) + + def test_candidate_or_action_drift_cannot_confirm_an_earlier_measured_entry(self): + ledger = Effects() + self.project(ledger, {'outcome': 'unknown'}) + changed_tuple = dict(self.tuple, gateway_semantic_closure_sha256='3' * 64) + with self.assertRaisesRegex(Refusal, 'changed-tuple'): + ledger.project(changed_tuple, self.review, self.resources, self.observed, + self.after, self.after, self.response) + changed = copy.deepcopy(self.review) + changed['action_commitment'] = '3' * 64 + changed['request'] = airtable.request(self.arguments, self.resources, '3' * 64, '1' * 64) + with self.assertRaisesRegex(Refusal, 'changed-action'): + self.project(ledger, self.observed, before=self.after, after=self.after, + response=self.response, review=changed) + self.assertFalse(next(iter(ledger.entries.values()))['confirmed']) + + +if __name__ == '__main__': + unittest.main() diff --git a/qualification/reference/tests/test_packets.py b/qualification/reference/tests/test_packets.py index 0e73c22b8..4dc4fdcb5 100644 --- a/qualification/reference/tests/test_packets.py +++ b/qualification/reference/tests/test_packets.py @@ -11,6 +11,7 @@ import airtable_record import author_packets import packet_plan +import stripe_platform from common import Refusal, canonical @@ -20,7 +21,7 @@ def plan(self): 'protected_run': 'recipe-qualification/123/1', 'base': airtable_record.BASE, 'table': airtable_record.TABLE, 'records': [ {'id': 'recTEST0000000001', 'run_metadata': 'recipe-qualification/123/1'}]} - return {'schema': 'auths.qualification-packet-plan/2', 'family': airtable_record.FAMILY, + return {'schema': 'auths.qualification-packet-plan/3', 'family': airtable_record.FAMILY, 'protected_run': resources['protected_run'], 'evaluated_at': 1000, 'not_after': 8200, 'configuration': '1' * 64, 'extension': None, 'resources': resources, 'packets': packet_plan.arguments(airtable_record.FAMILY, resources, '2' * 64)} @@ -35,6 +36,7 @@ def test_resource_action_and_phase_changes_cannot_choose_refresh_authority(self) lambda p: p['resources'].update(base='appOTHER'), lambda p: p.update(not_after=9000), lambda p: p.update(evaluated_at=True), lambda p: p.update(credential='synthetic-forbidden-input'), + lambda p: p.update(schema='auths.qualification-packet-plan/2'), lambda p: p['packets'][0].update(context='fresh'), lambda p: p['packets'][1]['arguments'].update(operation_id='new-operation'), lambda p: p['packets'].reverse(), lambda p: p['packets'].pop()] @@ -54,6 +56,58 @@ def test_refresh_input_is_closed_bounded_and_monotonic(self): for raw in [canonical(value), b' ' * 513 + b'\n', b'{"command":"close","command":"refresh"}\n']: with self.assertRaises(Refusal): author_packets.command(raw, 0) + def test_signing_pool_refuses_omitted_added_rebound_and_reordered_actions(self): + plan = self.plan() + packets = [{'label': item['label'], 'proof': item['label'] + '.proof', + 'action': item['label'] + '.action', + 'trusted_context': 'context-' + str(['initial', 'fresh'].index(item['context'])) + '.cbor', + 'arguments': item['arguments']} for item in plan['packets']] + carrier = {'schema': 'auths.qualification-public-packets/3', + 'protected_run': plan['protected_run'], 'evaluated_at': 1000, 'not_after': 1300, + 'trusted_contexts': ['context-0.cbor', 'context-1.cbor'], 'packets': packets} + self.assertEqual(packet_plan.public_pool(plan['family'], plan['resources'], '2' * 64, carrier), packets) + changes = [lambda c: c['packets'].pop(), lambda c: c['packets'].reverse(), + lambda c: c['packets'].append(copy.deepcopy(c['packets'][0])), + lambda c: c['packets'][0].update(proof='another.proof'), + lambda c: c['packets'][1].update(trusted_context='context-0.cbor'), + lambda c: c['packets'][0]['arguments'].update(operation_id='different-operation'), + lambda c: c['trusted_contexts'].pop(), lambda c: c.update(protected_run='recipe-qualification/999/1')] + for change in changes: + changed = copy.deepcopy(carrier) + change(changed) + with self.assertRaises(Refusal): + packet_plan.public_pool(plan['family'], plan['resources'], '2' * 64, changed) + + def test_stripe_guard_probes_are_fixed_valid_requests_with_independent_refusals(self): + run = 'recipe-qualification/123/1' + resources = {'schema': 'auths.stripe-platform-qualification-resources/1', + 'protected_run': run, 'platform': 'acct_TEST123', 'payments': [ + {'id': 'pi_TEST123', 'amount_received': 2000, 'currency': 'usd', + 'livemode': False, 'run_metadata': run}]} + packets = packet_plan.arguments(stripe_platform.FAMILY, resources, '2' * 64) + self.assertEqual(len(packets), 8) + for phase in ['commissioning', 'live']: + probes = {item['label']: item for item in packets if item['label'].startswith(phase + '-guard-')} + self.assertEqual(set(probes), {phase + '-guard-ceiling', phase + '-guard-currency'}) + for kind, code in [('ceiling', 'gateway.relative-ceiling.above'), + ('currency', 'gateway.relative-ceiling.binding-mismatch')]: + value = probes[phase + '-guard-' + kind]['arguments'] + self.assertEqual(stripe_platform.request(value, resources, '1' * 64, '2' * 64)['method'], 'POST') + self.assertEqual(stripe_platform.entry_policy(value, resources), code) + for count, accepted in [(29, True), (30, False)]: + many = dict(resources, payments=[dict(resources['payments'][0], id='pi_TEST' + str(i)) for i in range(count)]) + expanded = packet_plan.arguments(stripe_platform.FAMILY, many, '2' * 64) + carrier = {'schema': 'auths.qualification-public-packets/3', 'protected_run': run, + 'evaluated_at': 1000, 'not_after': 1300, + 'trusted_contexts': ['context-0.cbor', 'context-1.cbor'], 'packets': [ + {'label': p['label'], 'proof': p['label'] + '.proof', 'action': p['label'] + '.action', + 'trusted_context': 'context-' + str(['initial', 'fresh'].index(p['context'])) + '.cbor', + 'arguments': p['arguments']} for p in expanded]} + if accepted: + self.assertEqual(len(packet_plan.public_pool(stripe_platform.FAMILY, many, '2' * 64, carrier)), 64) + else: + with self.assertRaises(Refusal): packet_plan.public_pool(stripe_platform.FAMILY, many, '2' * 64, carrier) + def test_an_unanticipated_credential_name_refuses_before_importing_the_sdk(self): with patch.dict(os.environ, {'UNANTICIPATED_PROVIDER_KEY': 'synthetic-forbidden-input'}, clear=True): with self.assertRaisesRegex(Refusal, 'consumer-environment'): diff --git a/qualification/reference/tests/test_reference.py b/qualification/reference/tests/test_reference.py index ebb0f1fb8..2817fe4e9 100644 --- a/qualification/reference/tests/test_reference.py +++ b/qualification/reference/tests/test_reference.py @@ -19,6 +19,7 @@ import measure import fresh_evidence as fresh import expand as expansion +import packet_plan from expand import decode, unique_object @@ -112,9 +113,14 @@ def test_stripe_boundary_and_exact_form_have_no_connect_header(self): self.assertEqual(request['headers'], [ ['Stripe-Version', '2025-03-31.basil'], ['Idempotency-Key', idempotency(stripe.SERVICE, 'qualified-1')]]) - for amount in [0, -1, 1001, True, 10000, 99999999]: + for amount in [0, -1, True, 10001, 99999999]: with self.subTest(amount=amount), self.assertRaises(Refusal): stripe.request({**arguments, 'amount': amount}, resources, COMMITMENT, DIGEST) + self.assertIsNone(stripe.entry_policy(arguments, resources)) + self.assertEqual(stripe.entry_policy({**arguments, 'amount': 1001}, resources), + 'gateway.relative-ceiling.above') + self.assertEqual(stripe.entry_policy({**arguments, 'currency': 'eur'}, resources), + 'gateway.relative-ceiling.binding-mismatch') def test_stripe_resources_are_test_only_unique_and_bound_to_the_run(self): mutations = [ @@ -185,16 +191,21 @@ def test_binding_is_rederived_and_altered_source_or_native_observations_refuse(s (work / name).write_bytes((source / name).read_bytes()) (work / 'candidate').write_bytes(b'synthetic test-only candidate, not an executable') (work / 'context-0.cbor').write_bytes(b'synthetic test-only context') - (work / 'proof.cbor').write_bytes(b'synthetic test-only proof') - (work / 'action.cbor').write_bytes(b'synthetic test-only action') + (work / 'context-1.cbor').write_bytes(b'synthetic fresh test-only context') + planned = packet_plan.arguments(stripe.FAMILY, self.stripe_resources(), DIGEST) + packets = [] + for packet in planned: + label = packet['label'] + (work / (label + '.proof')).write_bytes(b'synthetic test-only proof') + (work / (label + '.action')).write_bytes(b'synthetic test-only action') + packets.append({'label': label, 'trusted_context': + 'context-' + str(['initial', 'fresh'].index(packet['context'])) + '.cbor', + 'proof': label + '.proof', 'action': label + '.action', 'arguments': packet['arguments']}) (work / 'resources.json').write_bytes(canonical(self.stripe_resources())) (work / 'packets.json').write_bytes(canonical({ 'schema': 'auths.qualification-public-packets/3', 'protected_run': RUN, 'evaluated_at': 1000, 'not_after': 1300, - 'trusted_contexts': ['context-0.cbor'], 'packets': [{'label': 'normal', - 'trusted_context': 'context-0.cbor', - 'proof': 'proof.cbor', 'action': 'action.cbor', - 'arguments': self.stripe_arguments()}]})) + 'trusted_contexts': ['context-0.cbor', 'context-1.cbor'], 'packets': packets})) artifacts = json.loads((root / 'bindings/fixtures/qualification/commissioning-v2.json').read_bytes()) tuple_value = json.loads(artifacts['permit'])['statement']['binding']['tuple'] tuple_value['recipe_family'] = stripe.FAMILY @@ -217,26 +228,29 @@ def test_binding_is_rederived_and_altered_source_or_native_observations_refuse(s def review(_binary, arguments): if arguments[0] == 'qualification-candidate': return copy.deepcopy(tuple_value) + label = Path(arguments[arguments.index('--proof') + 1]).stem + value = next(packet['arguments'] for packet in packets if packet['label'] == label) + commitment = sha256(canonical(value)) return {'schema': 'auths.gateway-submission-review/1', - 'actors': ['raw:synthetic-test-only-actor'], 'action_commitment': COMMITMENT, - 'arguments': self.stripe_arguments(), - 'request': stripe.request(self.stripe_arguments(), self.stripe_resources(), COMMITMENT, DIGEST)} + 'actors': ['raw:synthetic-test-only-actor'], 'action_commitment': commitment, + 'arguments': value, + 'request': stripe.request(value, self.stripe_resources(), commitment, DIGEST)} with patch.dict(os.environ, {'GITHUB_SHA': '1' * 40, 'GITHUB_RUN_ID': '123', 'GITHUB_RUN_ATTEMPT': '1'}), patch('expand.child', side_effect=review), \ patch('expand.time.time', return_value=1000): expansion.expand(args) binding = json.loads((args.out_dir / 'binding.json').read_bytes()) - self.assertEqual(binding['allowed_actions'], [COMMITMENT]) + self.assertEqual(binding['allowed_actions'], sorted({sha256(canonical(packet['arguments'])) for packet in packets})) self.assertEqual(binding['maximum_credential_leases'], 64) self.assertEqual(binding['principal_sha256'], sha256(b'raw:synthetic-test-only-actor')) self.assertEqual(binding['resources_sha256'], sha256((work / 'resources.json').read_bytes())) - self.assertEqual(binding['trusted_contexts_sha256'], [sha256(b'synthetic test-only context')]) + self.assertEqual(binding['trusted_contexts_sha256'], sorted([ + sha256(b'synthetic test-only context'), sha256(b'synthetic fresh test-only context')])) self.assertFalse(json.loads((args.out_dir / 'oracle-commitments.json').read_bytes())['qualification_issued']) original_packets = json.loads(args.packets.read_bytes()) - (work / 'context-1.cbor').write_bytes(b'synthetic second test-only context') for problem in ['unused', 'duplicate', 'unknown', 'empty', 'obsolete']: changed = copy.deepcopy(original_packets) - if problem == 'unused': changed['trusted_contexts'].append('context-1.cbor') + if problem == 'unused': changed['trusted_contexts'].append('context-2.cbor') if problem == 'duplicate': changed['trusted_contexts'].append('context-0.cbor') if problem == 'unknown': changed['packets'][0]['trusted_context'] = 'context-2.cbor' if problem == 'empty': changed['trusted_contexts'] = [] diff --git a/release/semantic-freeze-versions.toml b/release/semantic-freeze-versions.toml index a6a0b3109..dbe88c8b7 100644 --- a/release/semantic-freeze-versions.toml +++ b/release/semantic-freeze-versions.toml @@ -1,4 +1,4 @@ -freeze_version = 381 +freeze_version = 383 # Semantic identity counters live outside the xtask source tree deliberately. # The formal source closure binds xtask's executable code, while the semantic @@ -45,7 +45,7 @@ freeze_version = 381 "auths.frozen-bytes/product/integrations/auths-stripe/fixtures/subscription-create/v1/manifest.sha256.json" = 1 "auths.frozen-bytes/product/integrations/auths-stripe/fixtures/subscription-modify/v1/manifest.sha256.json" = 1 "auths.frozen-bytes/product/integrations/auths-stripe/fixtures/v1/manifest.sha256.json" = 1 -"auths.identity.protocol" = 132 +"auths.identity.protocol" = 133 "auths.modular-components" = 20 "auths.portable-abi-bindings" = 121 "auths.product.bounded-domains" = 19 @@ -60,11 +60,11 @@ freeze_version = 381 "auths.product.mcp-closed-execution" = 31 "auths.product.mechanism-profile-conformance" = 12 "auths.product.operations" = 5 -"auths.product.public-sdk-contract" = 129 +"auths.product.public-sdk-contract" = 130 "auths.product.receipts" = 13 "auths.product.release-assurance" = 7 "auths.product.simplified-waist" = 19 "auths.product.vocabulary" = 24 "auths.release.benchmark-contract" = 1 "auths.release.evolution-contract" = 79 -"auths.release.public-surface" = 381 +"auths.release.public-surface" = 383 diff --git a/release/semantic-freeze.json b/release/semantic-freeze.json index d0d58155c..aed4faf3c 100644 --- a/release/semantic-freeze.json +++ b/release/semantic-freeze.json @@ -1,6 +1,6 @@ { "schema": "auths.semantic-freeze/1", - "freezeVersion": 381, + "freezeVersion": 383, "publicSurface": { "rustRoots": [ "auths", @@ -550,7 +550,7 @@ }, { "id": "auths.identity.protocol", - "version": 132, + "version": 133, "classification": "frozen-meaning", "categories": [ "identity-protocol-versions", @@ -573,7 +573,7 @@ "core/fixtures/identity/v1/vectors.json", "core/spec/identity/v1" ], - "sha256": "ce403bf8c8be69014095d2806a3e530fbf44f515feef5322ab8d6e8cb5880f34" + "sha256": "9a803b61de925ce4ea7e91903b29fae1461f61f1a2e2a374a82b7e5cc9e0ea31" }, { "id": "auths.modular-components", @@ -871,7 +871,7 @@ }, { "id": "auths.product.public-sdk-contract", - "version": 129, + "version": 130, "classification": "frozen-meaning", "categories": [ "rust-sdk-contract", @@ -889,7 +889,7 @@ "product/runtime/auths-runtime/src", "product/sdk/auths-sdk/src" ], - "sha256": "f4aaff15cbdcf812cb419b61d5556fbe42543984275d2cc8dd22a128ca8d5217" + "sha256": "42d4e8dfbfc1b1639a093222cefefc854ee7a7dcbab2f2d4ed8c7bdce02f2d67" }, { "id": "auths.product.receipts", @@ -1011,7 +1011,7 @@ }, { "id": "auths.release.public-surface", - "version": 381, + "version": 383, "classification": "release-metadata", "categories": [ "package-names", @@ -1104,7 +1104,7 @@ "xtask/src/release_launch.rs", "xtask/src/semantic_freeze.rs" ], - "sha256": "840bd445df50aeece21207fa9d5533005b7d62af14ff623ccdb6320902a57672" + "sha256": "9e0d71e666dd24c0957b266ac430882dac80a36c117b8c1f70c35e6f7a1548a5" } ] } From 9739f15865b05a72697ac5ba71d350f273dabd31 Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 13:04:26 +0100 Subject: [PATCH 079/108] Reconstruct qualification record resource names from owned ledgers --- qualification/reference/README.md | 7 ++ qualification/reference/resource_summary.py | 45 ++++++++++++ .../reference/tests/test_resource_summary.py | 70 +++++++++++++++++++ qualification/run/assemble.sh | 16 ++++- 4 files changed, 137 insertions(+), 1 deletion(-) create mode 100644 qualification/reference/resource_summary.py create mode 100644 qualification/reference/tests/test_resource_summary.py diff --git a/qualification/reference/README.md b/qualification/reference/README.md index 10320b4fb..d64cd7b13 100644 --- a/qualification/reference/README.md +++ b/qualification/reference/README.md @@ -127,6 +127,13 @@ written atomically and retained after partial failure for cleanup. Existing outputs cannot be replaced. TLS requests refuse redirects and ambient proxies; provider error bodies never enter diagnostics. +`resource_summary.py` reconstructs the native record's sorted resource names +from the complete closed ledger. Stripe names the test platform and each test +payment; Airtable names the approved base, table and each owned record. The +projection checks run ownership, duplicate IDs, test mode and the native +96-byte name limit. Assembly uses this projection instead of accepting an +arbitrary string list or sorting the ledger object. + Unit cases use synthetic providers, including lost responses, changed ownership, foreign resources, duplicate records and unsafe files. Actual setup/cleanup rehearsals are recorded separately and confer no protected qualification. diff --git a/qualification/reference/resource_summary.py b/qualification/reference/resource_summary.py new file mode 100644 index 000000000..afeb389dd --- /dev/null +++ b/qualification/reference/resource_summary.py @@ -0,0 +1,45 @@ +"""Reconstruct public record resource names from a closed, run-bound ledger.""" + +import argparse +from pathlib import Path + +import airtable_record as airtable +import stripe_platform as stripe +from common import require, text +import resource_io as io + + +def summary(family, ledger): + require(type(ledger) is dict, 'qualification.reference.resource-binding') + run = io.run_id(ledger.get('protected_run')) + if family == stripe.FAMILY: + stripe.resources(ledger, run) + values = ['stripe:test-platform:' + ledger['platform']] + values += ['stripe:test-payment:' + payment['id'] for payment in ledger['payments']] + elif family == airtable.FAMILY: + airtable.resources(ledger, run) + table = ledger['base'] + '/' + ledger['table'] + values = ['airtable:base:' + ledger['base'], 'airtable:table:' + table] + values += ['airtable:record:' + table + '/' + record['id'] for record in ledger['records']] + else: + require(False, 'qualification.reference.family-unknown') + # Match the native record's BoundedText<96>. Refuse rather than truncate, + # hash away, or stringify an arbitrary object supplied by a harness. + for value in values: + text(value, maximum=96) + require(len(values) == len(set(values)) and 1 <= len(values) <= 32, + 'qualification.reference.resource-bound') + return sorted(values) + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('--family', required=True) + parser.add_argument('--resources', type=Path, required=True) + parser.add_argument('--out', type=Path, required=True) + args = parser.parse_args() + io.write(args.out, summary(args.family, io.read(args.resources)), new=True) + + +if __name__ == '__main__': + io.finish(main) diff --git a/qualification/reference/tests/test_resource_summary.py b/qualification/reference/tests/test_resource_summary.py new file mode 100644 index 000000000..0eee083aa --- /dev/null +++ b/qualification/reference/tests/test_resource_summary.py @@ -0,0 +1,70 @@ +"""Native record resource projection keeps exact, owned provider identities.""" + +import copy +from pathlib import Path +import sys +import unittest + +sys.path.insert(0, str(Path(__file__).resolve().parents[1])) +import airtable_record as airtable +import stripe_platform as stripe +from resource_summary import summary +from common import Refusal + +RUN = 'recipe-qualification/123/1' + + +class Summary(unittest.TestCase): + def stripe(self): + return {'schema': 'auths.stripe-platform-qualification-resources/1', + 'protected_run': RUN, 'platform': 'acct_SYNTHETIC', 'payments': [ + {'id': 'pi_SYNTHETIC', 'amount_received': 2000, 'currency': 'usd', + 'livemode': False, 'run_metadata': RUN}]} + + def airtable(self): + return {'schema': 'auths.airtable-record-qualification-resources/1', + 'protected_run': RUN, 'base': airtable.BASE, 'table': airtable.TABLE, + 'records': [{'id': 'recSYNTHETIC00001', 'run_metadata': RUN}]} + + def test_exact_provider_names_are_sorted_native_bounded_strings(self): + self.assertEqual(summary(stripe.FAMILY, self.stripe()), + ['stripe:test-payment:pi_SYNTHETIC', 'stripe:test-platform:acct_SYNTHETIC']) + table = airtable.BASE + '/' + airtable.TABLE + self.assertEqual(summary(airtable.FAMILY, self.airtable()), sorted([ + 'airtable:base:' + airtable.BASE, 'airtable:table:' + table, + 'airtable:record:' + table + '/recSYNTHETIC00001'])) + + def test_foreign_run_duplicate_live_and_open_ledger_cannot_be_summarized(self): + changes = [lambda v: v['payments'][0].update(run_metadata='recipe-qualification/999/1'), + lambda v: v['payments'].append(copy.deepcopy(v['payments'][0])), + lambda v: v['payments'][0].update(livemode=True), + lambda v: v.update(provider_resources=['unreviewed']), + lambda v: v.update(protected_run='../../another-run')] + for change in changes: + value = self.stripe() + change(value) + with self.assertRaises(Refusal): summary(stripe.FAMILY, value) + with self.assertRaises(Refusal): summary(airtable.FAMILY, self.stripe()) + with self.assertRaises(Refusal): summary('unknown-family', self.stripe()) + with self.assertRaises(Refusal): summary(stripe.FAMILY, ['unreviewed']) + + def test_oversized_native_name_is_refused_without_truncation(self): + value = self.stripe() + value['payments'][0]['id'] = 'pi_' + 'A' * 128 + with self.assertRaises(Refusal): summary(stripe.FAMILY, value) + + def test_record_bound_includes_platform_base_and_table_names(self): + value = self.stripe() + value['payments'] = [dict(value['payments'][0], id='pi_SYNTHETIC' + str(i)) for i in range(31)] + self.assertEqual(len(summary(stripe.FAMILY, value)), 32) + value['payments'].append(dict(value['payments'][0], id='pi_SYNTHETIC31')) + with self.assertRaises(Refusal): summary(stripe.FAMILY, value) + value = self.airtable() + value['records'] = [{'id': 'recSYNTHETIC' + str(i).zfill(5), 'run_metadata': RUN} for i in range(30)] + self.assertEqual(len(summary(airtable.FAMILY, value)), 32) + value['records'].append({'id': 'recSYNTHETIC00030', 'run_metadata': RUN}) + with self.assertRaises(Refusal): summary(airtable.FAMILY, value) + + +if __name__ == '__main__': + unittest.main() diff --git a/qualification/run/assemble.sh b/qualification/run/assemble.sh index 3c333dc8e..53caad899 100755 --- a/qualification/run/assemble.sh +++ b/qualification/run/assemble.sh @@ -21,8 +21,15 @@ root="$(git rev-parse --show-toplevel)" directory="${root}/qualification/families/${family}" tool="${AUTHS_QUALIFICATION:-${root}/target/release/auths-qualification}" +# Downloaded artifacts do not retain directory modes. Only this job's owned, +# real work directory may receive the reconstructed public proposal inputs. +[ -d "${work}" ] && [ ! -L "${work}" ] && [ -O "${work}" ] \ + || { echo "qualification.unsafe-work-directory" >&2; exit 1; } +chmod 0700 "${work}" + # A failed rerun must not leave an earlier proposal available to a signer. rm -rf "${work}/proposal" "${work}/evidence" +rm -f "${work}/provider-resources.json" for required in tuple.json packages.json facts.json "${stage}-effects.json" resources.json cases/redaction.scan.json; do [ -s "${work}/${required}" ] || { echo "qualification.evidence-incomplete ${required}" >&2; exit 1; } @@ -34,6 +41,13 @@ commit="$(jq -r .commit "${work}/facts.json")" [ "$(jq -r .recipe_family "${work}/tuple.json")" = "${family}" ] \ || { echo "qualification.tuple-names-another-family" >&2; exit 1; } +# The ledger is a closed family/run-bound object, not a caller-selected array +# of record strings. Reconstruct the native record summary from its exact IDs. +env -i PATH="${PATH}" PYTHONNOUSERSITE=1 python3 \ + "${root}/qualification/reference/resource_summary.py" \ + --family "${family}" --resources "${work}/resources.json" \ + --out "${work}/provider-resources.json" + # The trust stages are run here, by the tool this job built, whatever the # harness left under that name. "${tool}" stage-trust --tuple "${work}/tuple.json" --out "${work}/cases/rotation.trust.json" @@ -73,7 +87,7 @@ jq -n \ --slurpfile tuple "${work}/tuple.json" \ --slurpfile packages "${work}/packages.json" \ --slurpfile facts "${work}/facts.json" \ - --slurpfile resources "${work}/resources.json" \ + --slurpfile resources "${work}/provider-resources.json" \ '{qualification_id: $identifier, provider_kind: $record[0].provider_kind, tuple: $tuple[0], From 7525ad3a1e676cf2fb6c38a472caa862da4649ea Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 13:14:13 +0100 Subject: [PATCH 080/108] Scan and close final qualification proposals before publication --- .github/workflows/recipe-qualification.yml | 72 ++++--------- ...NDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md | 8 ++ qualification/README.md | 12 ++- .../tests/test_proposal_publication.py | 100 ++++++++++++++++++ qualification/run/assemble.sh | 2 + qualification/run/close_proposal.py | 93 ++++++++++++++++ 6 files changed, 231 insertions(+), 56 deletions(-) create mode 100644 qualification/reference/tests/test_proposal_publication.py create mode 100644 qualification/run/close_proposal.py diff --git a/.github/workflows/recipe-qualification.yml b/.github/workflows/recipe-qualification.yml index b72fb86e9..62dd65705 100644 --- a/.github/workflows/recipe-qualification.yml +++ b/.github/workflows/recipe-qualification.yml @@ -302,70 +302,34 @@ jobs: export AUTHS_QUALIFICATION="${GITHUB_WORKSPACE}/target/release/auths-qualification" bash qualification/run/resource-session.sh "${FAMILY}" "${RUNNER_TEMP}/work" \ bash qualification/run/live.sh "${FAMILY}" "${RUNNER_TEMP}/work" - - name: Scan what the run kept, then remove the canaries - # The scan runs here because the canaries exist only here. A failed - # scan fails the job before anything is uploaded. - shell: bash - run: | - set -euo pipefail - export AUTHS_QUALIFICATION="${GITHUB_WORKSPACE}/target/release/auths-qualification" - qualification/run/redact.sh "${RUNNER_TEMP}/work" - test ! -e "${RUNNER_TEMP}/work/canaries" - - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 - with: - name: live-${{ matrix.family }} - path: ${{ runner.temp }}/work - if-no-files-found: error - retention-days: 30 - - assemble: - name: assemble the record (${{ matrix.family }}) - needs: [families, live] - if: github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main' - runs-on: ubuntu-latest - timeout-minutes: 15 - strategy: - fail-fast: true - matrix: - family: ${{ fromJSON(needs.families.outputs.list) }} - steps: - - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 - with: - persist-credentials: false - - uses: ./.github/actions/setup-rust-cache - with: - toolchain: 1.97.1 - - name: Build the release tool from this commit - run: cargo build --locked --release -p auths-recipe-qualification-issuance --bin auths-qualification - - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 - with: - name: live-${{ matrix.family }} - path: ${{ runner.temp }}/work - - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 - with: - name: offline-${{ matrix.family }} - path: ${{ runner.temp }}/offline - - name: Build the evidence and assemble + - name: Close and scan the final proposal after successful cleanup + # The resource session has exited successfully, including its cleanup. + # Keep the real canaries while rebuilding the complete redaction + # evidence, then scan the actual final proposal before any upload. shell: bash env: FAMILY: ${{ matrix.family }} RUN: ${{ github.run_id }}-${{ github.run_attempt }} run: | set -euo pipefail - export AUTHS_QUALIFICATION="${GITHUB_WORKSPACE}/target/release/auths-qualification" - # The candidate's facts are the ones recorded before any live - # harness ran. - cp "${RUNNER_TEMP}/offline/facts.json" "${RUNNER_TEMP}/work/facts.json" - qualification/run/assemble.sh "${FAMILY}" "${RUNNER_TEMP}/work" \ - "recipe-qualification-live-${FAMILY}" "${RUN}" - mkdir -p "${RUNNER_TEMP}/proposal" - cp -R "${RUNNER_TEMP}/work/proposal/." "${RUNNER_TEMP}/proposal/" + chmod 0700 "${RUNNER_TEMP}/work" + python3 qualification/run/close_proposal.py \ + --family "${FAMILY}" --work "${RUNNER_TEMP}/work" \ + --environment "recipe-qualification-live-${FAMILY}" --run "${RUN}" \ + --tool "${GITHUB_WORKSPACE}/target/release/auths-qualification" + test ! -e "${RUNNER_TEMP}/work/canaries" - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: name: proposal-${{ matrix.family }} - path: ${{ runner.temp }}/proposal + path: ${{ runner.temp }}/work/proposal if-no-files-found: error retention-days: 90 + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 + with: + name: qualification-operator-report-${{ matrix.family }}-${{ github.run_id }}-${{ github.run_attempt }} + path: ${{ runner.temp }}/work + if-no-files-found: error + retention-days: 30 sign: # The only job that holds the release signer's key. It waits for a @@ -373,7 +337,7 @@ jobs: # evidence closure, attests each record, and signs one index listing # exactly this run's records. It signs nothing else. name: sign the release - needs: assemble + needs: live if: github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main' runs-on: ubuntu-latest timeout-minutes: 15 diff --git a/docs/research/INDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md b/docs/research/INDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md index 32af3e95a..bb5ed1ba1 100644 --- a/docs/research/INDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md +++ b/docs/research/INDEPENDENT_OPERATOR_QUALIFICATION_NOTES.md @@ -32,3 +32,11 @@ Both signer keys are provisioned in the existing reviewer-protected main-only signing environment; the root key remains outside CI and every Git checkout. No production family has yet been qualified by this work. Development live reports remain explicitly separate from protected production evidence. +# Publication closure correction + +The protected workflow previously removed its real canaries before a separate +job assembled the final proposal. The source-owned closure now assembles and +scans in the operator job after confirmed resource cleanup. It rebuilds with +the complete redaction report and rescans the actual final bytes; output growth +or any assembly/scan failure invalidates the proposal. This closes a publication +gap and does not establish missing protected provider evidence. diff --git a/qualification/README.md b/qualification/README.md index 0fb69b21c..5fab0d3dc 100644 --- a/qualification/README.md +++ b/qualification/README.md @@ -161,8 +161,16 @@ live-member observations. The family additionally writes: outputs from the candidate. Missing categories prevent closure; a family must export the gateway's real support bundle once Epic 4 provides it. -`run/redact.sh` scans the outputs and evidence and removes canaries before -upload. The release tool itself executes signer rotation and freshness; the +`run/close_proposal.py` retains the real canaries through assembly, rescans the +new proposal and evidence, and rebuilds with that complete scan report. It +scans the actual final bytes again and requires the report to remain unchanged +before removing the live phase's canaries. Any failure removes the proposal +and evidence. The live workflow runs this only after the complete resource +session has returned successfully, including confirmed cleanup. It uploads +the closed proposal from that same job; assembly no longer happens after the +canaries have been discarded. Commissioning closure retains canaries for the +subsequent ordinary live phase. +The release tool itself executes signer rotation and freshness; the family cannot replace those reports. Assembly re-verifies scenario, candidate, capability, counter and digest closure before signing can begin. diff --git a/qualification/reference/tests/test_proposal_publication.py b/qualification/reference/tests/test_proposal_publication.py new file mode 100644 index 000000000..b87762fd5 --- /dev/null +++ b/qualification/reference/tests/test_proposal_publication.py @@ -0,0 +1,100 @@ +"""Control-plane closure tests; synthetic assembly is not provider evidence.""" + +import json +import os +from pathlib import Path +import sys +import tempfile +import unittest +from unittest.mock import patch + +sys.path.insert(0, str(Path(__file__).resolve().parents[2] / 'run')) +import close_proposal +import scan_publication as publication + + +class Closure(unittest.TestCase): + def work(self): + temporary = tempfile.TemporaryDirectory() + self.addCleanup(temporary.cleanup) + work = Path(temporary.name) + os.chmod(work, 0o700) + (work / 'cases').mkdir() + (work / 'canaries').write_bytes(b'synthetic-private-scan-canary\n') + (work / 'canaries').chmod(0o600) + (work / 'facts.json').write_bytes(b'{}') + return work + + def synthetic_scan(self, work, _tool, keep_canaries): + self.assertTrue(keep_canaries) + report = work / 'cases/redaction.scan.json' + report.unlink(missing_ok=True) + entries = publication.sources(work) + # Mirrors the native scanner's source-kind/ordinal report identities. + report.write_bytes(json.dumps([(i, kind) for i, (_, kind, _) in enumerate(entries)]).encode()) + self.scanned.append({name: publication.contents(work / name) for name, _, _ in entries}) + + def synthetic_assemble(self, _family, work, _environment, _run, _stage, _tool): + self.builds += 1 + proposal = work / 'proposal' + proposal.mkdir(exist_ok=True) + # Each assembly changes the bytes, while the complete set of output + # categories stays fixed. The last scan must see the rebuilt bytes. + (proposal / 'record.json').write_bytes(json.dumps({'assembly': self.builds}).encode()) + (proposal / 'redaction.json').write_bytes(publication.contents(work / 'cases/redaction.scan.json')) + + def run_close(self, work, stage='live', assembly=None, scan=None): + self.builds, self.scanned = 0, [] + with patch.object(close_proposal, 'assemble', assembly or self.synthetic_assemble), \ + patch.object(publication, 'scan', scan or self.synthetic_scan): + close_proposal.close('synthetic-family', work, 'synthetic-environment', + 'synthetic-run', stage, Path('/synthetic-native-issuer')) + + def test_final_bytes_and_complete_report_are_scanned_before_canary_removal(self): + work = self.work() + self.run_close(work) + self.assertEqual(self.builds, 2) + self.assertEqual(len(self.scanned), 3) + self.assertNotIn('proposal/record.json', self.scanned[0]) + self.assertEqual(self.scanned[-1]['proposal/record.json'], b'{"assembly": 2}') + self.assertEqual((work / 'proposal/redaction.json').read_bytes(), + (work / 'cases/redaction.scan.json').read_bytes()) + self.assertFalse((work / 'canaries').exists()) + + def test_commissioning_keeps_canaries_for_the_subsequent_ordinary_live_phase(self): + work = self.work() + self.run_close(work, stage='commissioning') + self.assertTrue((work / 'canaries').exists()) + self.assertTrue((work / 'proposal/record.json').exists()) + + def test_second_assembly_cannot_grow_the_publication_tree_and_leave_a_proposal(self): + work = self.work() + def expand(*arguments): + self.synthetic_assemble(*arguments) + if self.builds == 2: + (work / 'unexpected.json').write_bytes(b'{}') + with self.assertRaises(publication.Refusal): self.run_close(work, assembly=expand) + self.assertFalse((work / 'proposal').exists()) + self.assertFalse((work / 'cases/redaction.scan.json').exists()) + self.assertTrue((work / 'canaries').exists()) + + def test_assembly_or_final_scan_failure_invalidates_all_proposal_outputs(self): + for failure in ['assembly', 'scan']: + work = self.work() + def assemble(*args): + self.synthetic_assemble(*args) + if failure == 'assembly': raise publication.Refusal('synthetic-refusal') + def scan(*args, **kwargs): + self.synthetic_scan(*args, **kwargs) + if failure == 'scan' and self.builds == 2: + raise publication.Refusal('synthetic-refusal') + with self.assertRaises(publication.Refusal): + self.run_close(work, assembly=assemble, scan=scan) + self.assertFalse((work / 'proposal').exists()) + self.assertFalse((work / 'evidence').exists()) + self.assertFalse((work / 'cases/redaction.scan.json').exists()) + self.assertTrue((work / 'canaries').exists()) + + +if __name__ == '__main__': + unittest.main() diff --git a/qualification/run/assemble.sh b/qualification/run/assemble.sh index 53caad899..6243c4234 100755 --- a/qualification/run/assemble.sh +++ b/qualification/run/assemble.sh @@ -36,6 +36,8 @@ for required in tuple.json packages.json facts.json "${stage}-effects.json" reso done commit="$(jq -r .commit "${work}/facts.json")" [ "${commit}" = "$(git -C "${root}" rev-parse HEAD)" ] || { echo "qualification.commit-changed" >&2; exit 1; } +[ -z "$(git -C "${root}" status --porcelain)" ] \ + || { echo "qualification.source-not-clean" >&2; exit 1; } # The tuple names this family and nothing else's. [ "$(jq -r .recipe_family "${work}/tuple.json")" = "${family}" ] \ diff --git a/qualification/run/close_proposal.py b/qualification/run/close_proposal.py new file mode 100644 index 000000000..db90faf37 --- /dev/null +++ b/qualification/run/close_proposal.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python3 +"""Close and scan a proposal while the operator still holds the real canaries. + +The first assembly introduces new retained files. Rescan those files, rebuild +with that complete redaction report, then scan the actual final bytes again. +The report must remain unchanged; expanding or changing the output categories +during the second assembly refuses publication. No authority is issued here. +""" + +import argparse +import os +from pathlib import Path +import re +import shutil +import stat +import subprocess +import sys + +import scan_publication as publication + + +def invalidate(work): + for name in ['proposal', 'evidence']: + path = work / name + if path.is_symlink(): + path.unlink() + elif path.is_dir(): + shutil.rmtree(path) + else: + path.unlink(missing_ok=True) + cases = work / 'cases' + if cases.is_dir() and not cases.is_symlink(): + (cases / 'redaction.scan.json').unlink(missing_ok=True) + + +def assemble(family, work, environment, run, stage, tool): + # Only this checkout's assembler executes. No artifact supplies a program, + # callback, argument list, signer key or provider credential to it. + script = Path(__file__).resolve().with_name('assemble.sh') + result = subprocess.run( + ['bash', str(script), family, str(work), environment, run, stage], + capture_output=True, timeout=120, + env={'PATH': os.environ.get('PATH', '/usr/bin:/bin'), + 'AUTHS_QUALIFICATION': str(tool)}, cwd=script.parents[2]) + publication.require(result.returncode == 0 + and len(result.stdout) <= publication.MAX_BYTES + and len(result.stderr) <= publication.MAX_BYTES) + + +def close(family, work, environment, run, stage, tool): + publication.require(stage in ['commissioning', 'live'] + and re.fullmatch(r'[a-z][a-z0-9-]{0,63}', family) is not None) + work = Path(work).absolute() + info = os.lstat(work) + publication.require(stat.S_ISDIR(info.st_mode) and info.st_uid == os.getuid() + and stat.S_IMODE(info.st_mode) == 0o700) + complete = False + try: + publication.scan(work, tool, keep_canaries=True) + assemble(family, work, environment, run, stage, tool) + publication.scan(work, tool, keep_canaries=True) + report = publication.contents(work / 'cases/redaction.scan.json') + assemble(family, work, environment, run, stage, tool) + publication.scan(work, tool, keep_canaries=True) + publication.require(publication.contents(work / 'cases/redaction.scan.json') == report) + publication.require((work / 'proposal').is_dir() + and not (work / 'proposal').is_symlink()) + if stage == 'live': + (work / 'canaries').unlink() + complete = True + finally: + if not complete: + invalidate(work) + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--family', required=True) + parser.add_argument('--work', type=Path, required=True) + parser.add_argument('--environment', required=True) + parser.add_argument('--run', required=True) + parser.add_argument('--stage', choices=['commissioning', 'live'], default='live') + parser.add_argument('--tool', type=Path, required=True) + args = parser.parse_args() + try: + close(args.family, args.work, args.environment, args.run, args.stage, args.tool) + except (ValueError, OSError, subprocess.SubprocessError): + print('qualification.proposal.not-closed', file=sys.stderr) + raise SystemExit(1) from None + + +if __name__ == '__main__': + main() From 25b43dec2cee1a78d1ef6daee20d6de936241b12 Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 13:42:26 +0100 Subject: [PATCH 081/108] Add transparent TLS faults and exercise complete proposal closure --- .github/workflows/recipe-qualification.yml | 2 +- .../tests/script_pipeline.rs | 88 ++++- qualification/reference/README.md | 14 + .../reference/tests/test_tls_fault.py | 171 ++++++++++ qualification/run/assemble.sh | 2 +- qualification/run/tls_fault.py | 305 ++++++++++++++++++ 6 files changed, 567 insertions(+), 15 deletions(-) create mode 100644 qualification/reference/tests/test_tls_fault.py create mode 100644 qualification/run/tls_fault.py diff --git a/.github/workflows/recipe-qualification.yml b/.github/workflows/recipe-qualification.yml index 62dd65705..ba6986427 100644 --- a/.github/workflows/recipe-qualification.yml +++ b/.github/workflows/recipe-qualification.yml @@ -313,7 +313,7 @@ jobs: run: | set -euo pipefail chmod 0700 "${RUNNER_TEMP}/work" - python3 qualification/run/close_proposal.py \ + python3 -B qualification/run/close_proposal.py \ --family "${FAMILY}" --work "${RUNNER_TEMP}/work" \ --environment "recipe-qualification-live-${FAMILY}" --run "${RUN}" \ --tool "${GITHUB_WORKSPACE}/target/release/auths-qualification" diff --git a/product/qualification/auths-recipe-qualification-issuance/tests/script_pipeline.rs b/product/qualification/auths-recipe-qualification-issuance/tests/script_pipeline.rs index 6f9e0d3be..7f6afdccf 100644 --- a/product/qualification/auths-recipe-qualification-issuance/tests/script_pipeline.rs +++ b/product/qualification/auths-recipe-qualification-issuance/tests/script_pipeline.rs @@ -25,7 +25,10 @@ fn succeed(command: &mut Command) { fn stage_reports_flow_through_redaction_and_assembly_and_missing_execution_refuses() { let temporary = tempfile::tempdir().expect("directory"); let root = temporary.path().join("repository"); - let family = root.join("qualification/families/example-refund-v1"); + // Exercise the actual closed resource projection with synthetic Stripe + // IDs. The subprocess double still establishes no provider qualification. + let family_name = "stripe-platform-refund-v1"; + let family = root.join(format!("qualification/families/{family_name}")); fs::create_dir_all(&family).expect("family"); let draft = common::draft_json(); let record = serde_json::json!({ @@ -35,6 +38,36 @@ fn stage_reports_flow_through_redaction_and_assembly_and_missing_execution_refus "residual_assumptions": draft["residual_assumptions"], "excluded_claims": draft["excluded_claims"], }); fs::write(family.join("record.json"), record.to_string()).expect("record"); + let source = Path::new(env!("CARGO_MANIFEST_DIR")).join("../../../qualification"); + for (directory, names) in [ + ( + "reference", + &[ + "resource_summary.py", + "resource_io.py", + "fresh_evidence.py", + "common.py", + "stripe_platform.py", + "airtable_record.py", + ][..], + ), + ( + "run", + &[ + "assemble.sh", + "close_proposal.py", + "scan_publication.py", + "redact.sh", + ][..], + ), + ] { + let output = root.join("qualification").join(directory); + fs::create_dir_all(&output).expect("source-owned release scripts"); + for name in names { + fs::copy(source.join(directory).join(name), output.join(name)) + .expect("reviewed source script"); + } + } succeed(Command::new("git").args(["init", "--quiet"]).arg(&root)); succeed(Command::new("git").arg("-C").arg(&root).args(["add", "."])); succeed(Command::new("git").arg("-C").arg(&root).args([ @@ -60,6 +93,17 @@ fn stage_reports_flow_through_redaction_and_assembly_and_missing_execution_refus .to_owned(); let work = temporary.path().join("work"); let harness = common::stage_fixture(&work); + fs::set_permissions(&work, fs::Permissions::from_mode(0o700)).expect("private work"); + let mut tuple = common::tuple_json(); + tuple["recipe_family"] = family_name.into(); + let typed: auths_recipe_qualification::QualificationTuple = + serde_json::from_value(tuple.clone()).expect("synthetic tuple"); + fs::write(work.join("tuple.json"), tuple.to_string()).expect("tuple"); + fs::write( + work.join("tuple-digest"), + typed.digest().expect("tuple digest").to_hex(), + ) + .expect("tuple digest"); let tool = env!("CARGO_BIN_EXE_auths-qualification"); for phase in ["offline", "live"] { succeed( @@ -82,7 +126,13 @@ fn stage_reports_flow_through_redaction_and_assembly_and_missing_execution_refus .expect("packages"); fs::write( work.join("resources.json"), - draft["provider_resources"].to_string(), + serde_json::json!({ + "schema": "auths.stripe-platform-qualification-resources/1", + "protected_run": "recipe-qualification/123/1", "platform": "acct_SYNTHETIC", + "payments": [{"id": "pi_SYNTHETIC", "amount_received": 2000, "currency": "usd", + "livemode": false, "run_metadata": "recipe-qualification/123/1"}], + }) + .to_string(), ) .expect("resources"); let facts = serde_json::json!({ @@ -100,7 +150,7 @@ fn stage_reports_flow_through_redaction_and_assembly_and_missing_execution_refus fs::create_dir_all(&directory).expect("scan directory"); fs::write(directory.join("test-output"), "closed test states only").expect("output"); } - let scripts = Path::new(env!("CARGO_MANIFEST_DIR")).join("../../../qualification/run"); + let scripts = root.join("qualification/run"); for name in [ "commissioning-effects.json", "facts.json", @@ -130,18 +180,25 @@ fn stage_reports_flow_through_redaction_and_assembly_and_missing_execution_refus None => fs::remove_file(path).expect("remove leak"), } } + // The real workflow retains its canaries until the actual final proposal + // has been assembled, rebuilt from the complete scan, and rescanned. succeed( - Command::new("bash") - .arg(scripts.join("redact.sh")) + Command::new("python3") + .arg("-B") + .arg(scripts.join("close_proposal.py")) + .args(["--family", family_name]) + .arg("--work") .arg(&work) - .env("AUTHS_QUALIFICATION", tool) + .args(["--environment", "test-environment", "--run", "test-run"]) + .arg("--tool") + .arg(tool) .current_dir(&root), ); assert!(!work.join("canaries").exists()); let assemble = || { Command::new("bash") .arg(scripts.join("assemble.sh")) - .arg("example-refund-v1") + .arg(family_name) .arg(&work) .args(["test-environment", "test-run"]) .env("AUTHS_QUALIFICATION", tool) @@ -149,13 +206,18 @@ fn stage_reports_flow_through_redaction_and_assembly_and_missing_execution_refus .output() .expect("assemble") }; - let assembled = assemble(); - assert!( - assembled.status.success(), - "{}", - String::from_utf8_lossy(&assembled.stderr) - ); assert!(work.join("proposal/record.json").is_file()); + let record: serde_json::Value = serde_json::from_slice( + &fs::read(work.join("proposal/record.json")).expect("closed record"), + ) + .expect("canonical JSON"); + assert_eq!( + record["provider_resources"], + serde_json::json!([ + "stripe:test-payment:pi_SYNTHETIC", + "stripe:test-platform:acct_SYNTHETIC" + ]) + ); // A failed rerun cannot leave its old proposal usable by the signing job. fs::copy( work.join("cases/recovery.live.json"), diff --git a/qualification/reference/README.md b/qualification/reference/README.md index d64cd7b13..ee419bf72 100644 --- a/qualification/reference/README.md +++ b/qualification/reference/README.md @@ -89,6 +89,20 @@ unmeasured effects and additional result fields refuse. The helper does not assert isolation, installed-consumer provenance or a passing wall; the family harness must measure those separately and the native runner decides the case. +`../run/tls_fault.py` is the external response-loss mechanism for a disposable +Linux gateway network namespace. UID-scoped REDIRECT rules select only the +reviewed provider's IPv4 addresses at port 443; the relay checks the original +destination and forwards the original TLS records. It has no TLS/private key, +decrypts nothing and changes no gateway setting. After the actual private +native counter stream shows one write entry, the relay holds encrypted server +records beyond the handshake. A root-only private control socket can drop or +release that hold. The source controller must independently confirm the +effect before dropping the response; traffic counts cannot confirm it. Scope, +inode, owner, frame, connection, buffer and time bounds fail closed. Disposable +TLS 1.2/1.3 source tests exercise real encrypted transport with synthetic +counters; native/provider qualification and network-namespace integration +remain separate required steps. + `fresh_evidence.py` is the separate response oracle for the reviewed Stripe refund and Airtable update. It validates the approved resource, exact intended value, test-mode success (Stripe) and the action-derived echo, then hashes the diff --git a/qualification/reference/tests/test_tls_fault.py b/qualification/reference/tests/test_tls_fault.py new file mode 100644 index 000000000..b1f258f78 --- /dev/null +++ b/qualification/reference/tests/test_tls_fault.py @@ -0,0 +1,171 @@ +"""Transparent fault mechanics with synthetic counters and disposable TLS. + +These tests demonstrate transport behavior, not native gateway/provider facts. +""" + +import asyncio +import json +import os +from pathlib import Path +import ssl +import subprocess +import sys +import tempfile +import unittest +from unittest.mock import patch + +sys.path.insert(0, str(Path(__file__).resolve().parents[2] / 'run')) +import tls_fault as fault + + +def snapshot(entries=0, scope='1' * 32): + return {'schema': 'auths.gateway-execution-witness/1', 'scope': scope, + 'credential_lease_calls': entries, 'write_transport_entries': entries, + 'read_transport_entries': 0} + + +def server_hello(version=None): + body = b'\x03\x03' + b'\0' * 32 + b'\0\x13\x01\0' + if version is not None: + extension = b'\0\x2b\0\x02' + version + body += len(extension).to_bytes(2, 'big') + extension + return b'\x02' + len(body).to_bytes(3, 'big') + body + + +class Parsing(unittest.TestCase): + def work(self): + temporary = tempfile.TemporaryDirectory() + self.addCleanup(temporary.cleanup) + path = Path(temporary.name) / 'witness.ndjson' + path.write_text(json.dumps(snapshot()) + '\n') + path.chmod(0o600) + return path + + def test_fragmented_negotiation_keeps_handshake_records_unmodified(self): + for version, expected in [(None, 'tls12'), (b'\x03\x04', 'tls13')]: + hello = fault.Hello() + payload = server_hello(version) + hello.server(22, payload[:7]) + self.assertIsNone(hello.version) + hello.server(22, payload[7:]) + self.assertEqual(hello.version, expected) + self.assertFalse(hello.client_boundary(22)) + self.assertTrue(hello.client_boundary(23)) + hello.server(23, b'opaque-ciphertext-never-decoded') + self.assertEqual(hello.version, expected) + + def test_malformed_or_unknown_tls_negotiation_refuses(self): + for value in [server_hello(b'\x03\x05'), b'\x01\0\0\x26' + b'\0' * 38, + b'\x02\xff\xff\xff', server_hello(b'\x03\x04')[:-1] + b'\xff']: + with self.assertRaises(ValueError): fault.Hello().server(22, value) + + def test_witness_requires_actual_changed_scope_local_counters_without_saturation(self): + path = self.work() + witness = fault.Witness(path, os.getuid()) + self.assertFalse(witness.entered()) + with path.open('a') as out: + out.write(json.dumps(snapshot(1)) + '\n' + '{"schema":') + self.assertTrue(witness.entered(), 'a concurrent partial tail is not a new fact') + path.write_text(json.dumps(snapshot()) + '\n') + with self.assertRaises(ValueError): witness.entered() + for changed in [snapshot(1, scope='2' * 32), snapshot(2), + dict(snapshot(1), write_transport_entries=(1 << 64) - 1), + dict(snapshot(1), passed=True)]: + path = self.work() + with path.open('a') as out: out.write(json.dumps(changed) + '\n') + with self.assertRaises(ValueError): fault.Witness(path, os.getuid()).entered() + + def test_changed_inode_links_and_public_witness_are_refused(self): + for mode in ['replacement', 'symlink', 'hardlink', 'public']: + path = self.work() + witness = fault.Witness(path, os.getuid()) + witness.entered() + if mode == 'replacement': + replacement = path.with_name('replacement') + replacement.write_text(json.dumps(snapshot()) + '\n') + replacement.chmod(0o600) + os.replace(replacement, path) + elif mode == 'symlink': + target = path.with_name('target') + path.rename(target) + path.symlink_to(target) + elif mode == 'hardlink': + os.link(path, path.with_name('linked')) + else: + path.chmod(0o644) + with self.assertRaises((ValueError, OSError)): witness.entered() + + def test_control_cannot_invent_entry_or_choose_an_endpoint(self): + state = fault.Fault(None) + for command in [{'command': 'drop'}, {'command': 'drop', 'provider_url': 'unreviewed'}, + {'command': 'passed'}, {'passed': True}]: + with self.assertRaises(ValueError): state.decide(command) + state.armed, state.held_connections = True, 1 + state.decide({'command': 'drop'}) + self.assertEqual(state.status()['command'], 'drop') + with self.assertRaises(ValueError): state.decide({'command': 'release'}) + + +class Transport(unittest.IsolatedAsyncioTestCase): + async def test_disposable_tls12_and_tls13_drop_or_release_real_encrypted_records(self): + for version in [ssl.TLSVersion.TLSv1_2, ssl.TLSVersion.TLSv1_3]: + for command in ['release', 'drop']: + with self.subTest(version=version, command=command), tempfile.TemporaryDirectory() as temporary: + root = Path(temporary) + # Ephemeral local test material stays outside the repository. + made = subprocess.run(['openssl', 'req', '-x509', '-newkey', 'ed25519', '-nodes', + '-subj', '/CN=localhost', '-days', '1', '-keyout', str(root / 'key.pem'), + '-out', str(root / 'cert.pem')], capture_output=True, timeout=10) + self.assertEqual(made.returncode, 0) + server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) + server_context.minimum_version = server_context.maximum_version = version + server_context.load_cert_chain(root / 'cert.pem', root / 'key.pem') + client_context = ssl.create_default_context(cafile=str(root / 'cert.pem')) + client_context.minimum_version = client_context.maximum_version = version + received = asyncio.Event() + request = b'POST /synthetic HTTP/1.1\r\nHost: localhost\r\n\r\n' + response = b'HTTP/1.1 200 OK\r\nContent-Length: 2\r\n\r\n{}' + async def provider(reader, writer): + try: + self.assertEqual(await reader.readuntil(b'\r\n\r\n'), request) + received.set() + writer.write(response) + await writer.drain() + finally: + writer.close() + upstream = await asyncio.start_server(provider, '127.0.0.1', 0, ssl=server_context) + endpoint = upstream.sockets[0].getsockname() + witness = root / 'witness.ndjson' + witness.write_text(json.dumps(snapshot()) + '\n' + json.dumps(snapshot(1)) + '\n') + witness.chmod(0o600) + state = fault.Fault(fault.Witness(witness, os.getuid())) + with patch.object(fault, 'destination', return_value=endpoint): + relay = await asyncio.start_server(lambda r, w: fault.relay(r, w, state, set()), + '127.0.0.1', 0) + endpoint = relay.sockets[0].getsockname() + reader, writer = await asyncio.wait_for(asyncio.open_connection( + *endpoint, ssl=client_context, server_hostname='localhost'), 5) + writer.write(request) + await writer.drain() + await asyncio.wait_for(received.wait(), 5) + pending = asyncio.create_task(reader.read(len(response))) + await asyncio.sleep(0.05) + self.assertFalse(pending.done(), 'response must be held after upstream receipt') + state.decide({'command': command}) + returned = await asyncio.wait_for(pending, 5) + self.assertEqual(returned, response if command == 'release' else b'') + self.assertTrue(state.armed) + self.assertGreater(state.buffered, 0) + writer.close() + try: + await writer.wait_closed() + except OSError: + pass + relay.close() + await relay.wait_closed() + upstream.close() + await upstream.wait_closed() + + +if __name__ == '__main__': + unittest.main() diff --git a/qualification/run/assemble.sh b/qualification/run/assemble.sh index 6243c4234..e6c37a152 100755 --- a/qualification/run/assemble.sh +++ b/qualification/run/assemble.sh @@ -45,7 +45,7 @@ commit="$(jq -r .commit "${work}/facts.json")" # The ledger is a closed family/run-bound object, not a caller-selected array # of record strings. Reconstruct the native record summary from its exact IDs. -env -i PATH="${PATH}" PYTHONNOUSERSITE=1 python3 \ +env -i PATH="${PATH}" PYTHONNOUSERSITE=1 python3 -B \ "${root}/qualification/reference/resource_summary.py" \ --family "${family}" --resources "${work}/resources.json" \ --out "${work}/provider-resources.json" diff --git a/qualification/run/tls_fault.py b/qualification/run/tls_fault.py new file mode 100644 index 000000000..ffc4b764f --- /dev/null +++ b/qualification/run/tls_fault.py @@ -0,0 +1,305 @@ +#!/usr/bin/env python3 +"""Release-only transparent TLS response fault, outside the shipping gateway. + +Run in the gateway's disposable Linux network namespace with UID-scoped +REDIRECT rules for the reviewed provider's IPv4 addresses and port 443. The +original destination is retained. This relay has no TLS key, terminates no TLS, +and never decodes a provider request, response, credential or proof. Only the +unencrypted ServerHello selects the record boundary after the TLS handshake. + +An actual native write-counter change arms the response hold. A separate root +controller must independently observe the effect before sending `drop`. Cipher +bytes and traffic counts are not evidence that the provider applied a write. +The case additionally needs the native result and fresh provider read-back. +""" + +import argparse +import asyncio +import hashlib +import ipaddress +import os +from pathlib import Path +import socket +import stat +import struct +import sys + +sys.path.insert(0, str(Path(__file__).resolve().parents[1] / 'reference')) +from common import closed, require +from expand import decode +import measure +from resource_io import finish + +ORIGINS = {'stripe-platform-refund-v1': 'api.stripe.com', + 'airtable-record-update-v1': 'api.airtable.com'} +MAX_RECORD = 18432 +MAX_HELLO = 65536 +MAX_BUFFER = 2 * 1024 * 1024 +MAX_CONNECTIONS = 16 + + +class Hello: + """Read only plaintext TLS negotiation metadata, never encrypted content.""" + + def __init__(self): + self.pending = bytearray() + self.version = None + + def server(self, kind, payload): + if kind != 22 or self.version is not None: + return + self.pending.extend(payload) + require(len(self.pending) <= MAX_HELLO, 'qualification.fault.hello-bound') + if len(self.pending) < 4: + return + length = int.from_bytes(self.pending[1:4], 'big') + require(self.pending[0] == 2 and 38 <= length <= MAX_HELLO - 4, + 'qualification.fault.server-hello') + if len(self.pending) < length + 4: + return + body = bytes(self.pending[4:length + 4]) + require(body[:2] == b'\x03\x03', 'qualification.fault.tls-version') + sid = body[34] + offset = 35 + sid + 3 + require(sid <= 32 and offset <= len(body) and body[offset - 1] == 0, + 'qualification.fault.server-hello') + selected = None + if offset != len(body): + require(offset + 2 <= len(body), 'qualification.fault.server-hello') + size = int.from_bytes(body[offset:offset + 2], 'big') + offset += 2 + require(offset + size == len(body), 'qualification.fault.server-hello') + while offset < len(body): + require(offset + 4 <= len(body), 'qualification.fault.server-hello') + extension = int.from_bytes(body[offset:offset + 2], 'big') + size = int.from_bytes(body[offset + 2:offset + 4], 'big') + offset += 4 + require(offset + size <= len(body), 'qualification.fault.server-hello') + if extension == 43: + require(selected is None and size == 2, 'qualification.fault.tls-version') + selected = body[offset:offset + size] + offset += size + require(selected in [None, b'\x03\x03', b'\x03\x04'], 'qualification.fault.tls-version') + self.version = 'tls13' if selected == b'\x03\x04' else 'tls12' + self.pending.clear() + + def client_boundary(self, kind): + # TLS 1.3's first encrypted client record contains Finished. It can + # be forwarded while subsequent server application records are held. + # TLS 1.2 keeps Finished as content type 22; type 23 follows it. + return self.version is not None and kind == 23 + + +async def record(reader): + header = await reader.readexactly(5) + kind, version, size = header[0], header[1:3], int.from_bytes(header[3:5], 'big') + require(kind in [20, 21, 22, 23] and version in [b'\x03\x01', b'\x03\x02', b'\x03\x03'] + and 0 < size <= MAX_RECORD, 'qualification.fault.record-bound') + payload = await reader.readexactly(size) + return kind, payload, header + payload + + +class Witness: + """Pin one private, append-only native counter stream and its initial scope.""" + + def __init__(self, path, owner): + self.path, self.owner = Path(path), owner + self.inode, self.previous_size, self.before, self.last = None, 0, None, None + self.prefix_sha256 = None + + def entered(self): + fd = os.open(self.path, os.O_RDONLY | os.O_NOFOLLOW) + with os.fdopen(fd, 'rb') as stream: + info = os.fstat(stream.fileno()) + require(stat.S_ISREG(info.st_mode) and info.st_nlink == 1 + and info.st_uid == self.owner and stat.S_IMODE(info.st_mode) == 0o600 + and 0 < info.st_size <= 256 * 1024, + 'qualification.fault.witness-file') + inode = info.st_dev, info.st_ino + require(self.inode in [None, inode] and info.st_size >= self.previous_size, + 'qualification.fault.changed-witness') + raw = stream.read(256 * 1024 + 1) + require(len(raw) <= 256 * 1024, 'qualification.fault.witness-bound') + require(self.prefix_sha256 is None or hashlib.sha256(raw[:self.previous_size]).digest() + == self.prefix_sha256, 'qualification.fault.changed-witness') + # A concurrent append may end halfway through one bounded frame. + frames = raw.split(b'\n')[:-1] + require(1 <= len(frames) <= 256 and all(0 < len(frame) < 1024 for frame in frames) + and len(raw.rsplit(b'\n', 1)[-1]) < 1024, 'qualification.fault.witness-bound') + values = [measure.snapshot(decode(frame)) for frame in frames] + for before, after in zip(values, values[1:]): + measure.delta(before, after) + require(self.before in [None, values[0]], 'qualification.fault.changed-witness') + if self.last is not None: + measure.delta(self.last, values[-1]) + self.inode, self.previous_size = inode, len(raw) + self.prefix_sha256 = hashlib.sha256(raw).digest() + self.before, self.last = values[0], values[-1] + count = measure.delta(self.before, self.last)['write_transport_entries'] + require(count <= 1, 'qualification.fault.multiple-writes') + return count == 1 + + +class Fault: + def __init__(self, witness): + self.witness = witness + self.decision = asyncio.Event() + self.command = None + self.buffered = self.held_connections = self.connections = 0 + self.armed = False + + def decide(self, value): + closed(value, ['command']) + require(value['command'] in ['drop', 'release'] and self.command is None + and self.armed and self.held_connections > 0, + 'qualification.fault.control-state') + self.command = value['command'] + self.decision.set() + + def status(self): + return {'schema': 'auths.qualification-tls-fault/1', 'armed': self.armed, + 'held_connections': self.held_connections, 'buffered_bytes': self.buffered, + 'command': self.command} + + +def destination(writer, approved): + stream = writer.get_extra_info('socket') + # Linux SO_ORIGINAL_DST preserves the gateway-selected address across + # REDIRECT. No command or artifact may select another upstream endpoint. + raw = stream.getsockopt(socket.SOL_IP, 80, 16) + family = struct.unpack_from('H', raw)[0] + port = int.from_bytes(raw[2:4], 'big') + address = socket.inet_ntoa(raw[4:8]) + require(family == socket.AF_INET and port == 443 and address in approved, + 'qualification.fault.destination') + return address, port + + +async def relay(reader, writer, fault, approved): + fault.connections += 1 + remote = None + tasks = [] + try: + require(fault.connections <= MAX_CONNECTIONS and fault.command is None, + 'qualification.fault.connection-bound') + upstream, remote = await asyncio.wait_for( + asyncio.open_connection(*destination(writer, approved), limit=MAX_RECORD * 2), 5) + hello = Hello() + held = False + + async def client(): + nonlocal held + while True: + kind, _payload, raw = await record(reader) + if not held and hello.client_boundary(kind) and fault.witness.entered(): + # Arm before forwarding Finished/the request so a fast + # upstream response cannot overtake this boundary. + held = True + fault.armed = True + fault.held_connections += 1 + remote.write(raw) + await remote.drain() + + async def server(): + while True: + kind, payload, raw = await record(upstream) + hello.server(kind, payload) + if held and kind == 23: + fault.buffered += len(raw) + require(fault.buffered <= MAX_BUFFER, 'qualification.fault.buffer-bound') + await fault.decision.wait() + if fault.command == 'drop': + return + writer.write(raw) + await writer.drain() + + tasks = [asyncio.create_task(client()), asyncio.create_task(server())] + _done, pending = await asyncio.wait(tasks, timeout=45, return_when=asyncio.FIRST_COMPLETED) + for task in pending: + task.cancel() + await asyncio.gather(*tasks, return_exceptions=True) + except (OSError, ValueError, asyncio.TimeoutError, asyncio.IncompleteReadError): + # Neither TLS ciphertext nor path/provider exception text is emitted. + pass + finally: + for task in tasks: + task.cancel() + for connection in [writer, remote]: + if connection is not None: + connection.close() + try: + await connection.wait_closed() + except OSError: + pass + + +async def control(reader, writer, fault): + try: + stream = writer.get_extra_info('socket') + _pid, uid, _gid = struct.unpack('3i', stream.getsockopt(socket.SOL_SOCKET, socket.SO_PEERCRED, 12)) + require(uid == 0, 'qualification.fault.control-peer') + raw = await asyncio.wait_for(reader.readuntil(b'\n'), 5) + require(len(raw) <= 128, 'qualification.fault.control-bound') + value = decode(raw) + if value == {'command': 'status'}: + pass + else: + fault.decide(value) + from common import canonical + writer.write(canonical(fault.status()) + b'\n') + await writer.drain() + except (OSError, ValueError, asyncio.TimeoutError, asyncio.IncompleteReadError, asyncio.LimitOverrunError): + pass + finally: + writer.close() + try: + await writer.wait_closed() + except OSError: + pass + + +async def serve(args): + require(sys.platform == 'linux' and os.getuid() == 0, 'qualification.fault.linux-root') + origin = ORIGINS[args.family] + approved = {result[4][0] for result in socket.getaddrinfo(origin, 443, socket.AF_INET, socket.SOCK_STREAM)} + require(1 <= len(approved) <= 16 and all(ipaddress.ip_address(value).is_global for value in approved), + 'qualification.fault.provider-address') + parent = os.lstat(args.control.parent) + require(stat.S_ISDIR(parent.st_mode) and parent.st_uid == 0 + and stat.S_IMODE(parent.st_mode) == 0o700 and not args.control.exists() + and not args.control.is_symlink() and args.control.parent.resolve() == args.control.parent, + 'qualification.fault.private-control') + fault = Fault(Witness(args.witness, args.witness_owner)) + # Root's umask keeps the local control socket private at creation. + os.umask(0o077) + ipc = await asyncio.start_unix_server(lambda r, w: control(r, w, fault), args.control, limit=128) + os.chmod(args.control, 0o600) + inode = os.lstat(args.control).st_ino + try: + tcp = await asyncio.start_server(lambda r, w: relay(r, w, fault, approved), '127.0.0.1', args.port, + limit=MAX_RECORD * 2) + print('qualification.fault.ready', flush=True) + async with ipc, tcp: + await asyncio.wait_for(asyncio.gather(ipc.serve_forever(), tcp.serve_forever()), 120) + finally: + ipc.close() + await ipc.wait_closed() + if args.control.exists() and os.lstat(args.control).st_ino == inode: + args.control.unlink() + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--family', choices=sorted(ORIGINS), required=True) + parser.add_argument('--witness', type=lambda v: Path(v).absolute(), required=True) + parser.add_argument('--witness-owner', type=int, required=True) + parser.add_argument('--control', type=lambda v: Path(v).absolute(), required=True) + parser.add_argument('--port', type=int, default=44443) + args = parser.parse_args() + require(1 <= args.port <= 65535 and 1 <= args.witness_owner <= (1 << 32) - 2, + 'qualification.fault.configuration') + finish(lambda: asyncio.run(serve(args))) + + +if __name__ == '__main__': + main() From 85bdb01a86807ad39be765f8e4e25a73d136df17 Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 14:10:50 +0100 Subject: [PATCH 082/108] Reconstruct commissioning authority from reviewed signer source --- .../tests/protected_run.rs | 74 +++++++++- qualification/reference/README.md | 9 ++ .../reference/tests/test_commission_entry.py | 43 ++++++ qualification/run/commission.py | 128 ++++++++++++++++++ 4 files changed, 247 insertions(+), 7 deletions(-) create mode 100644 qualification/reference/tests/test_commission_entry.py create mode 100644 qualification/run/commission.py diff --git a/product/qualification/auths-recipe-qualification-issuance/tests/protected_run.rs b/product/qualification/auths-recipe-qualification-issuance/tests/protected_run.rs index dfc3332f0..fa2d97334 100644 --- a/product/qualification/auths-recipe-qualification-issuance/tests/protected_run.rs +++ b/product/qualification/auths-recipe-qualification-issuance/tests/protected_run.rs @@ -5,6 +5,10 @@ use std::collections::BTreeMap; use std::path::Path; +use auths_recipe_qualification::{ + QualificationRevocationList, QualificationSignerCertificate, QualificationTrustRoot, +}; + const WORKFLOW: &str = ".github/workflows/recipe-qualification.yml"; const PROTECTED: &str = "if: github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main'"; @@ -65,7 +69,16 @@ fn a_pull_request_reaches_no_secret_and_no_signing_job() { let names: Vec<&str> = jobs.keys().map(String::as_str).collect(); assert_eq!( names, - ["assemble", "families", "live", "offline", "sign", "verify"] + [ + "candidate", + "families", + "live", + "offline", + "packet-author", + "sign", + "simulation", + "verify" + ] ); for (name, lines) in &jobs { let has = |needle: &str| lines.iter().any(|line| line.contains(needle)); @@ -78,8 +91,8 @@ fn a_pull_request_reaches_no_secret_and_no_signing_job() { let protected = lines.iter().any(|line| line == PROTECTED); assert_eq!( protected, - !matches!(name.as_str(), "families" | "offline"), - "{name}: everything after offline evidence runs only by hand on the default branch" + matches!(name.as_str(), "live" | "sign" | "verify"), + "{name}: live evidence and signing run only by hand on the default branch" ); assert_eq!( has("QUALIFICATION_RELEASE_SIGNER_KEY"), @@ -103,7 +116,7 @@ fn a_pull_request_reaches_no_secret_and_no_signing_job() { ); // The key is used only by a tool the signing job built itself, and no // privileged or signing-path job runs a binary another job produced. - for name in ["assemble", "sign", "verify"] { + for name in ["sign", "verify"] { let lines = &jobs[name]; assert!( lines @@ -120,8 +133,8 @@ fn a_pull_request_reaches_no_secret_and_no_signing_job() { let live = &jobs["live"]; let scan = live .iter() - .position(|line| line.contains("redact.sh")) - .expect("the live job scans"); + .position(|line| line.contains("close_proposal.py")) + .expect("the live job closes and scans its final proposal"); let upload = live .iter() .position(|line| line.contains("upload-artifact")) @@ -154,7 +167,9 @@ fn a_pull_request_reaches_no_secret_and_no_signing_job() { fn the_repository_holds_no_qualification_key() { let trust = repository().join("qualification/trust"); for entry in std::fs::read_dir(trust).expect("trust directory") { - let name = entry.expect("entry").file_name(); + let entry = entry.expect("entry"); + assert!(entry.file_type().expect("type").is_file()); + let name = entry.file_name(); let name = name.to_string_lossy(); assert!( matches!( @@ -162,9 +177,54 @@ fn the_repository_holds_no_qualification_key() { ".gitkeep" | "qualification-trust-root.json" | "signer-certificate.json" + | "commissioning-signer-certificate.json" | "revocation-list.json" + | "ceremony.json" ), "{name} is not a public trust artifact" ); + let bytes = std::fs::read(entry.path()).expect("public artifact"); + match name.as_ref() { + "qualification-trust-root.json" => { + QualificationTrustRoot::from_canonical_json(&bytes).expect("closed public root"); + } + "signer-certificate.json" | "commissioning-signer-certificate.json" => { + QualificationSignerCertificate::from_canonical_json(&bytes) + .expect("closed public certificate"); + } + "revocation-list.json" => { + QualificationRevocationList::from_canonical_json(&bytes) + .expect("closed public revocations"); + } + "ceremony.json" => { + let ceremony: serde_json::Value = serde_json::from_slice(&bytes).expect("ceremony"); + let mut keys: Vec<&str> = ceremony + .as_object() + .expect("ceremony object") + .keys() + .map(String::as_str) + .collect(); + keys.sort_unstable(); + assert_eq!( + keys, + [ + "assessment", + "created_at", + "operator", + "private_key_retention", + "public_artifacts", + "qualification_issued", + "schema", + "scope", + "stable_launch_ready" + ] + ); + assert_eq!(ceremony["schema"], "auths.qualification-root-ceremony/1"); + assert_eq!(ceremony["qualification_issued"], false); + assert_eq!(ceremony["stable_launch_ready"], false); + } + ".gitkeep" => assert!(bytes.is_empty()), + _ => unreachable!("filename checked above"), + } } } diff --git a/qualification/reference/README.md b/qualification/reference/README.md index ee419bf72..0dd621e95 100644 --- a/qualification/reference/README.md +++ b/qualification/reference/README.md @@ -25,6 +25,15 @@ must match, and the lease ceiling is a source-owned 64 acquisitions. The native issuer separately rechecks both offline artifacts and their mandatory scenarios before signing. An expansion is neither a live report nor a permit. +`../run/commission.py` is the protected source-owned permit signer. It rederives +the contract identity from this checkout before expanding the complete public +packet pool. Only after that succeeds does it read the commissioning key and +invoke its own native issuer. The key remains outside the publication directory, +children inherit no key environment, and the public permit and trust artifacts +are scanned with the actual key canary before output survives. Approval delay +cannot extend the original two-hour author session. This entry point still +requires the admitted source contracts and protected workflow integration. + ```text python qualification/reference/expand.py \ --reviewer \ diff --git a/qualification/reference/tests/test_commission_entry.py b/qualification/reference/tests/test_commission_entry.py new file mode 100644 index 000000000..1def91e5f --- /dev/null +++ b/qualification/reference/tests/test_commission_entry.py @@ -0,0 +1,43 @@ +"""Signer-source pinning only; fixtures issue no commissioning authority.""" + +import base64 +from pathlib import Path +import sys +import tempfile +import unittest +from unittest.mock import patch + +sys.path.insert(0, str(Path(__file__).resolve().parents[2] / 'run')) +import commission +from common import Refusal, canonical + + +class Source(unittest.TestCase): + def test_contract_is_rederived_from_this_checkout_not_copied_from_input(self): + with tempfile.TemporaryDirectory() as temporary: + inputs = Path(temporary) + family = 'stripe-platform-refund-v1' + tuple_value = {'recipe_family': family, 'provider_contract_id': '1' * 64} + (inputs / 'tuple.json').write_bytes(canonical(tuple_value)) + issuer = commission.ROOT / 'target/release/auths-qualification' + with patch.object(commission, 'call', return_value=('1' * 64 + '\n').encode()) as called: + self.assertEqual(commission.source_contract(family, inputs, issuer), tuple_value) + self.assertEqual(called.call_args.args[0], [issuer, 'contract-id', '--contract', + commission.ROOT / 'qualification/families' / family / 'contract.json']) + for changed in [dict(tuple_value, provider_contract_id='2' * 64), + dict(tuple_value, recipe_family='airtable-record-update-v1')]: + (inputs / 'tuple.json').write_bytes(canonical(changed)) + with patch.object(commission, 'call', return_value=('1' * 64 + '\n').encode()): + with self.assertRaises(Refusal): commission.source_contract(family, inputs, issuer) + with self.assertRaises(Refusal): commission.source_contract('../../unreviewed', inputs, issuer) + + def test_seed_parser_has_no_filename_command_or_noncanonical_encoding_input(self): + synthetic = base64.urlsafe_b64encode(bytes(range(32))).rstrip(b'=').decode() + self.assertEqual(commission.signing_seed(synthetic), synthetic.encode()) + for value in [None, synthetic + '=', synthetic + '\n', '$(unreviewed)', + '/tmp/unreviewed', '!' * 43, synthetic[:-1] + 'v']: + with self.assertRaises(Refusal): commission.signing_seed(value) + + +if __name__ == '__main__': + unittest.main() diff --git a/qualification/run/commission.py b/qualification/run/commission.py new file mode 100644 index 000000000..169e0a5a5 --- /dev/null +++ b/qualification/run/commission.py @@ -0,0 +1,128 @@ +#!/usr/bin/env python3 +"""Protected, source-owned commissioning signer entry point. + +The signer job builds its reviewer and issuer from this exact main checkout. +Downloaded candidate bytes are hashed, never executed here. Public inputs +select neither tools nor the reviewed contract, recipe, oracle or lease cap. +The root key and release signer are not inputs to this command. +""" + +import argparse +import base64 +import os +from pathlib import Path +import re +import shutil +import subprocess +import sys +import tempfile +import time +from types import SimpleNamespace + +sys.path.insert(0, str(Path(__file__).resolve().parents[1] / 'reference')) +import expand +from common import digest, require +from resource_io import finish, write_bytes +import artifact_wait + +ROOT = Path(__file__).resolve().parents[2] + + +def call(arguments): + result = subprocess.run(list(map(str, arguments)), stdin=subprocess.DEVNULL, + capture_output=True, timeout=120, cwd=ROOT, env={'PATH': '/usr/bin:/bin'}) + require(result.returncode == 0 and len(result.stdout) <= 65536 and len(result.stderr) <= 65536, + 'qualification.commission.source-command') + return result.stdout + + +def source_contract(family, inputs, issuer): + require(family in expand.REFERENCES, 'qualification.commission.family') + contract = ROOT / 'qualification/families' / family / 'contract.json' + # Hash the reviewed source contract through the native format, never use + # an artifact-supplied contract ID as its own expected value. + expected = digest(call([issuer, 'contract-id', '--contract', contract]).decode('ascii').strip()) + actual = expand.decode(expand.read(inputs / 'tuple.json', 65536)) + require(actual['recipe_family'] == family and actual['provider_contract_id'] == expected, + 'qualification.commission.contract-binding') + return actual + + +def signing_seed(value): + require(type(value) is str and re.fullmatch(r'[A-Za-z0-9_-]{43}', value) is not None, + 'qualification.commission.key-format') + raw = base64.urlsafe_b64decode(value + '=') + require(len(raw) == 32 and base64.urlsafe_b64encode(raw).rstrip(b'=').decode() == value, + 'qualification.commission.key-format') + return value.encode('ascii') + + +def issue(family, inputs, candidate, output): + run, attempt, commit = artifact_wait.identity(os.environ) + require(call(['/usr/bin/git', 'rev-parse', 'HEAD']).decode().strip() == commit + and not call(['/usr/bin/git', 'status', '--porcelain']).strip(), + 'qualification.commission.source-binding') + require(not output.exists() and not output.is_symlink(), 'qualification.commission.output-exists') + issuer, reviewer = [ROOT / 'target/release' / name for name in ['auths-qualification', 'auths-gateway']] + source_contract(family, inputs, issuer) + protected_run = 'recipe-qualification/' + run + '/' + attempt + packets = inputs / 'packets/public-packets.json' + plan = expand.decode(expand.read(packets, 65536)) + now = int(time.time()) + # Delayed approval cannot extend the original installed-author session. + require(type(plan.get('evaluated_at')) is int + and now - 7200 < plan['evaluated_at'] <= now + 60, + 'qualification.commission.author-expired') + not_after = min(now + 7200, plan['evaluated_at'] + 7200) + require(now < not_after, 'qualification.commission.author-expired') + output.mkdir(mode=0o700) + completed = False + try: + with tempfile.TemporaryDirectory(prefix='auths-source-commission-') as private: + private = Path(private) + expansion = private / 'reference' + expand.expand(SimpleNamespace(source_commit=commit, protected_run=protected_run, + tuple=inputs / 'tuple.json', candidate=candidate, reviewer=reviewer, + recipe=inputs / 'recipe.json', profile_lock=inputs / 'profile.lock.json', + resources=inputs / 'resources.json', packets=packets, + conformance=inputs / 'offline/conformance.json', + differential=inputs / 'offline/differential.json', out_dir=expansion)) + # Read the key only after source identity, contract and independent + # full-pool reconstruction passed. Children inherit no key env. + seed = signing_seed(os.environ.get('QUALIFICATION_COMMISSIONING_SIGNER_KEY')) + key = private / 'commissioner.key' + canaries = private / 'canaries' + write_bytes(key, seed, new=True) + write_bytes(canaries, seed + b'\n', new=True) + certificate = ROOT / 'qualification/trust/commissioning-signer-certificate.json' + call([issuer, 'commissioning-sign', '--binding', expansion / 'binding.json', + '--conformance', inputs / 'offline/conformance.json', + '--differential', inputs / 'offline/differential.json', '--signer-key', key, + '--certificate', certificate, '--issued-at', str(now), + '--not-before', str(now), '--not-after', str(not_after), + '--out', output / 'commissioning-permit.json']) + for name, source in [('signer-certificate.json', certificate), + ('revocation-list.json', ROOT / 'qualification/trust/revocation-list.json')]: + write_bytes(output / name, expand.read(source, 65536), new=True) + scan = [issuer, 'stage-redaction', '--canaries', canaries] + for name in ['commissioning-permit.json', 'signer-certificate.json', 'revocation-list.json']: + scan += ['--source', 'evidence=' + str(output / name)] + call([*scan, '--out', private / 'signer-publication-scan.json']) + require(int(time.time()) < not_after, 'qualification.commission.author-expired') + completed = True + finally: + if not completed: + shutil.rmtree(output) + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--family', choices=sorted(expand.REFERENCES), required=True) + for name in ['inputs', 'candidate', 'out']: + parser.add_argument('--' + name, type=lambda value: Path(value).absolute(), required=True) + args = parser.parse_args() + finish(lambda: issue(args.family, args.inputs, args.candidate, args.out)) + + +if __name__ == '__main__': + main() From 5428ca57010059d1191bfebb03072ac386179b28 Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 14:35:06 +0100 Subject: [PATCH 083/108] Plan finite count and sum qualification boundary experiments --- .../tests/protected_run.rs | 10 +- qualification/reference/README.md | 26 ++++-- qualification/reference/author_packets.py | 23 +++-- qualification/reference/check_packets.py | 2 + qualification/reference/expand.py | 2 +- qualification/reference/packet_plan.py | 93 +++++++++++++++---- .../reference/tests/test_author_socket.py | 2 +- qualification/reference/tests/test_packets.py | 36 ++++++- .../reference/tests/test_reference.py | 2 +- 9 files changed, 155 insertions(+), 41 deletions(-) diff --git a/product/qualification/auths-recipe-qualification-issuance/tests/protected_run.rs b/product/qualification/auths-recipe-qualification-issuance/tests/protected_run.rs index fa2d97334..c26b3da63 100644 --- a/product/qualification/auths-recipe-qualification-issuance/tests/protected_run.rs +++ b/product/qualification/auths-recipe-qualification-issuance/tests/protected_run.rs @@ -144,7 +144,11 @@ fn a_pull_request_reaches_no_secret_and_no_signing_job() { live.iter() .any(|line| line.contains("test ! -e") && line.contains("canaries")) ); + assert!(!text.contains("pull_request_target")); +} +#[test] +fn other_workflows_cannot_reach_qualification_signing() { // No other workflow names the signer's key, and nothing in the // repository runs on a trigger that gives a pull request's code secrets. for entry in std::fs::read_dir(repository().join(".github/workflows")).expect("workflows") { @@ -159,7 +163,11 @@ fn a_pull_request_reaches_no_secret_and_no_signing_job() { ); } } - assert!(!text.contains("pull_request_target")); + assert!( + !std::fs::read_to_string(repository().join(WORKFLOW)) + .expect("workflow") + .contains("pull_request_target") + ); } /// The trust directory holds public artifacts only. diff --git a/qualification/reference/README.md b/qualification/reference/README.md index 0dd621e95..490108a65 100644 --- a/qualification/reference/README.md +++ b/qualification/reference/README.md @@ -46,7 +46,7 @@ python qualification/reference/expand.py \ --out-dir ``` -The public packet carrier is `auths.qualification-public-packets/3`, with +The public packet carrier is `auths.qualification-public-packets/4`, with `protected_run`, `evaluated_at`, `not_after`, `trusted_contexts` (1–4 sorted unique adjacent filenames), and 1–64 `packets`. Packet validity is at most five minutes; the signing expansion reviews native proofs at their recorded offline evaluation @@ -69,19 +69,33 @@ hashes. Every installation still authenticates its actual context separately; all listed contexts share one immutable run/family lease budget. An unlisted context, duplicate or reordered list, changed set, or schema 1 permit refuses. The public packet author supplies two native challenges under one exact actor -and grant. Each phase's first resource has a `-fresh` replay packet with the same +and reviewed grants. Each phase's first resource has a `-fresh` replay packet with the same logical operation and arguments, under the second context. Refresh never changes -that packet's assigned challenge, action or context. At most 31 Airtable or 29 -Stripe resources fit the finite 64-packet ceiling. Stripe also has two exact +that packet's assigned challenge, action or context. The full qualification plan +uses exactly 16 resources. Its closed pool has 42 Airtable or 54 Stripe packets, +including four distinct custody-drift operations per phase. Smaller synthetic +operator checks do not establish complete-corpus coverage. Stripe also has two exact guard probes per phase: 1001 cents against a 2000-cent payment, and EUR against that USD payment. Their native proofs authorize request construction; the real relative-ceiling read must refuse them after one custody lease and before any write. A permit never replaces that guard. The grant has bounded USD/EUR sum partitions so the currency probe can reach the provider-read guard; every -payment remains scoped to the exact reviewed test ledger. Source plan schema 3 +payment remains scoped to the exact reviewed test ledger. Source plan schema 4 refuses obsolete plans. The source-owned protected corpus and native durable replay evidence still need integration. +Stripe's count and sum boundary experiments use separate source-owned grants +under that same actor and trust. Count has capacity one and sum capacity 2000; +sum has count capacity two and sum capacity 1000. Each admits one 1000-cent +action at the exact 50% provider ceiling, followed by a distinct 500-cent +overflow operation. The count and sum positives use different test payments. +Their fixed windows are 2/3 days for commissioning and 5/7 days for ordinary +execution. Native counters already distinguish the exact subject, namespace +and window; no persisted counter is edited or reset. The default 64-count grant +cannot consume these experiment counters. The author expires before the next +real boundary of any of those windows. The live harness must measure the actual +capacity refusal and concurrent host behavior before any capability is claimed. + `measure.py` validates and subtracts native execution snapshots: matching fresh scope, no saturation/decrease, no duplicate host in an aggregate. Restarted engines must be measured separately. Budget consumption is never substituted @@ -178,7 +192,7 @@ No provider credential or caller-supplied argument enters the installed author. `author_packets.py` must run outside the checkout from an installed wheel, with only `PATH`, `PYTHONNOUSERSITE` and optional locale variables. It refuses any additional environment variable before importing the SDK. A fresh native key -authors the single actor, grant, challenge and trust; no private key is exported. +authors one actor, the fixed reviewed grants, challenges and trust; no private key is exported. The grant/session lasts at most two hours. Every action keeps the ordinary SDK maximum of 300 seconds; a protected signing wait must not extend that limit. diff --git a/qualification/reference/author_packets.py b/qualification/reference/author_packets.py index 0c1544957..b8af937f0 100644 --- a/qualification/reference/author_packets.py +++ b/qualification/reference/author_packets.py @@ -17,7 +17,7 @@ from common import Refusal, canonical, closed, integer, require, sha256 from expand import decode, read -from packet_plan import REFERENCES, validate +from packet_plan import REFERENCES, grant_for, validate from resource_io import finish, write, write_bytes @@ -53,12 +53,14 @@ def create_session(plan_path): key = native.DevelopmentEd25519Key.generate() actor = native.Principal(key.principal) extension = plan['extension'] - extensions = [] if extension is None else [(extension['extension_id'], bytes.fromhex(extension['extension_body_hex']))] - request = native.GrantRequest(actor, 'auths.mcp', 2, [('tools/call', resource)], - current - 60, end, [audience], None, None, 0, None, 'raw-key-baseline', extensions) - unsigned = native.root_grant(actor, request) - signing = native.prepare_signing(unsigned, key.principal_method, key.verification_method, key.suite) - grant = signing.complete(key.sign(signing.signing_preimage)) + grants = {} + for name, body in ({'default': None} if extension is None else extension).items(): + extensions = [] if body is None else [(body['extension_id'], bytes.fromhex(body['extension_body_hex']))] + request = native.GrantRequest(actor, 'auths.mcp', 2, [('tools/call', resource)], + current - 60, end, [audience], None, None, 0, None, 'raw-key-baseline', extensions) + unsigned = native.root_grant(actor, request) + signing = native.prepare_signing(unsigned, key.principal_method, key.verification_method, key.suite) + grants[name] = signing.complete(key.sign(signing.signing_preimage)) challenges = {name: native.generate_challenge_v1() for name in ['initial', 'fresh']} require(challenges['initial'] != challenges['fresh'], 'qualification.packets.challenge-binding') anchor = native.TrustAnchor(actor.value, actor, [key.principal_method], [('auths.mcp', 2)], @@ -70,7 +72,7 @@ def create_session(plan_path): ('actor', 'every', 'offline-verifiable', None)]) template = native.compile_trusted_context(bytes.fromhex(plan['configuration']), None, 1, 1, 1, [anchor], assurance, None, None, 'none-v1', [key.evidence_type], - [] if extension is None else [extension['extension_id']]) + [] if extension is None else [extension['default']['extension_id']]) contexts = {name: template.bind_request(audience, challenge, current) for name, challenge in challenges.items()} evidence = (key.evidence_type, key.media_type, key.evidence) @@ -88,6 +90,7 @@ def emit(work, label=None): packets, emitted_contexts = [], set() for packet in selected: label, arguments = packet['label'], packet['arguments'] + grant = grants[grant_for(label)] context_name = packet['context'] challenge, context = challenges[context_name], contexts[context_name] context_file = 'context-' + str(['initial', 'fresh'].index(context_name)) + '.cbor' @@ -113,10 +116,10 @@ def emit(work, label=None): emitted_contexts.add(context_file) packets.append({'label': label, 'proof': label + '.proof', 'action': label + '.action', 'trusted_context': context_file, 'arguments': arguments}) - write(work / 'public-packets.json', {'schema': 'auths.qualification-public-packets/3', + write(work / 'public-packets.json', {'schema': 'auths.qualification-public-packets/4', 'protected_run': plan['protected_run'], 'evaluated_at': current, 'not_after': current + validity, 'trusted_contexts': sorted(emitted_contexts), 'packets': packets}, new=True) - write(work / 'author-report.json', {'schema': 'auths.qualification-packet-author/2', + write(work / 'author-report.json', {'schema': 'auths.qualification-packet-author/3', 'family': plan['family'], 'protected_run': plan['protected_run'], 'sdk_version': version, 'packet_count': len(packets), 'trusted_contexts_sha256': { name: sha256(read(work / name, 4 * 1024 * 1024)) for name in sorted(emitted_contexts)}, diff --git a/qualification/reference/check_packets.py b/qualification/reference/check_packets.py index 3d43597ff..fc5fb5798 100644 --- a/qualification/reference/check_packets.py +++ b/qualification/reference/check_packets.py @@ -51,6 +51,8 @@ def check(args): resources = {'schema': 'auths.stripe-platform-qualification-resources/1', 'protected_run': run, 'platform': 'acct_SYNTHETIC', 'payments': [ {'id': 'pi_SYNTHETIC', 'amount_received': 2000, 'currency': 'usd', + 'livemode': False, 'run_metadata': run}, + {'id': 'pi_SYNTHETIC2', 'amount_received': 2000, 'currency': 'usd', 'livemode': False, 'run_metadata': run}]} if reference is stripe_platform else { 'schema': 'auths.airtable-record-qualification-resources/1', 'protected_run': run, 'base': airtable_record.BASE, 'table': airtable_record.TABLE, 'records': [ diff --git a/qualification/reference/expand.py b/qualification/reference/expand.py index 026354169..716859a5d 100644 --- a/qualification/reference/expand.py +++ b/qualification/reference/expand.py @@ -121,7 +121,7 @@ def expand(args): from packet_plan import public_pool public_pool(reference.FAMILY, bound_resources, tuple_value['compiled_recipe_sha256'], plan) closed(plan, ['schema', 'protected_run', 'evaluated_at', 'not_after', 'trusted_contexts', 'packets']) - require(plan['schema'] == 'auths.qualification-public-packets/3' + require(plan['schema'] == 'auths.qualification-public-packets/4' and plan['protected_run'] == protected_run and type(plan['evaluated_at']) is int and 60 <= plan['evaluated_at'] <= 253402300499 and type(plan['not_after']) is int diff --git a/qualification/reference/packet_plan.py b/qualification/reference/packet_plan.py index 858e6fe28..6fe8f2b69 100644 --- a/qualification/reference/packet_plan.py +++ b/qualification/reference/packet_plan.py @@ -17,6 +17,19 @@ REFERENCES = {reference.FAMILY: reference for reference in [stripe_platform, airtable_record]} PACKET_VALIDITY = 7200 +# Distinct source-owned windows isolate the four boundary experiments from +# the ordinary grant and each other. Native counters retain their existing +# subject/namespace/window keys; nothing resets or edits their persisted state. +BUDGET_WINDOWS = {'commissioning-count': 2 * 86400, 'commissioning-sum': 3 * 86400, + 'live-count': 5 * 86400, 'live-sum': 7 * 86400} + + +def grant_for(label): + for phase in ['commissioning', 'live']: + for kind in ['count', 'sum']: + if label in [phase + '-budget-' + kind, phase + '-budget-' + kind + '-over']: + return phase + '-' + kind + return 'default' def arguments(family, resources, recipe_digest): @@ -62,6 +75,33 @@ def arguments(family, resources, recipe_digest): require(reference.entry_policy(probe, resources) is not None, 'qualification.packets.probe-binding') packets.append({'label': label, 'context': 'initial', 'arguments': probe}) + if len(values) == 16: + for kind in ['kind', 'generation', 'commitment', 'version']: + label = phase + '-custody-' + kind + probe = dict(value, payment_intent=values[13]['id'], amount=500, currency='usd') + probe['operation_id'] = 'qlf-' + sha256(canonical([family, resources['protected_run'], label]))[:48] + reference.request(probe, resources, '0' * 64, recipe_digest) + packets.append({'label': label, 'context': 'initial', 'arguments': probe}) + if len(values) >= 2: + for kind in ['count', 'sum']: + for overflow in [False, True]: + label = phase + '-budget-' + kind + ('-over' if overflow else '') + selected = -2 if kind == 'count' else -1 + if overflow: selected = -1 if kind == 'count' else -2 + probe = dict(value, payment_intent=values[selected]['id'], + amount=500 if overflow else 1000, currency='usd') + probe['operation_id'] = 'qlf-' + sha256(canonical([family, resources['protected_run'], label]))[:48] + reference.request(probe, resources, '0' * 64, recipe_digest) + require(reference.entry_policy(probe, resources) is None, + 'qualification.packets.budget-binding') + packets.append({'label': label, 'context': 'initial', 'arguments': probe}) + elif len(values) == 16: + for kind in ['kind', 'generation', 'commitment', 'version']: + label = phase + '-custody-' + kind + probe = dict(value, record_id=values[13]['id']) + probe['operation_id'] = 'qlf-' + sha256(canonical([family, resources['protected_run'], label]))[:48] + reference.request(probe, resources, '0' * 64, recipe_digest) + packets.append({'label': label, 'context': 'initial', 'arguments': probe}) return packets @@ -73,7 +113,7 @@ def public_pool(family, resources, recipe_digest, carrier): """ closed(carrier, ['schema', 'protected_run', 'evaluated_at', 'not_after', 'trusted_contexts', 'packets']) - require(carrier['schema'] == 'auths.qualification-public-packets/3' + require(carrier['schema'] == 'auths.qualification-public-packets/4' and carrier['protected_run'] == resources['protected_run'] and carrier['trusted_contexts'] == ['context-0.cbor', 'context-1.cbor'], 'qualification.packets.pool-binding') @@ -90,13 +130,16 @@ def public_pool(family, resources, recipe_digest, carrier): def validate(plan): closed(plan, ['schema', 'family', 'protected_run', 'evaluated_at', 'not_after', 'configuration', 'extension', 'resources', 'packets']) - require(plan['schema'] == 'auths.qualification-packet-plan/3' + require(plan['schema'] == 'auths.qualification-packet-plan/4' and type(plan['family']) is str and plan['family'] in REFERENCES, 'qualification.packets.schema') run_id(plan['protected_run']) require(type(plan['evaluated_at']) is int and 60 <= plan['evaluated_at'] <= 253402293599 and type(plan['not_after']) is int - and plan['not_after'] == plan['evaluated_at'] + PACKET_VALIDITY, + and plan['not_after'] == (min(plan['evaluated_at'] + PACKET_VALIDITY, + *[(plan['evaluated_at'] // window + 1) * window + for window in [86400, *BUDGET_WINDOWS.values()]]) + if plan['family'] == stripe_platform.FAMILY else plan['evaluated_at'] + PACKET_VALIDITY), 'qualification.packets.time-bound') digest(plan['configuration']) packets = plan['packets'] @@ -110,7 +153,12 @@ def validate(plan): for phase in ['commissioning', 'live'] for index in range(32) for suffix in (['', '-fresh'] if index == 0 else [''])} | ({phase + '-guard-' + kind for phase in ['commissioning', 'live'] - for kind in ['ceiling', 'currency']} if plan['family'] == stripe_platform.FAMILY else set())) + for kind in ['ceiling', 'currency']} if plan['family'] == stripe_platform.FAMILY else set()) + | ({phase + '-budget-' + kind + suffix for phase in ['commissioning', 'live'] + for kind in ['count', 'sum'] for suffix in ['', '-over']} + if plan['family'] == stripe_platform.FAMILY else set()) + | ({phase + '-custody-' + kind for phase in ['commissioning', 'live'] + for kind in ['kind', 'generation', 'commitment', 'version']})) and packet['context'] == ('fresh' if packet['label'].endswith('-fresh') else 'initial'), 'qualification.packets.packet-bound') labels.add(packet['label']) @@ -132,13 +180,15 @@ def validate(plan): 'qualification.packets.resource-binding') extension = plan['extension'] if plan['family'] == stripe_platform.FAMILY: - closed(extension, ['extension_id', 'extension_body_hex']) - require(extension['extension_id'] == 'bounded-policy-commitment-v1' - and type(extension['extension_body_hex']) is str - and 0 < len(extension['extension_body_hex']) <= 8192 - and len(extension['extension_body_hex']) % 2 == 0 - and all(character in '0123456789abcdef' for character in extension['extension_body_hex']), - 'qualification.packets.extension-bound') + closed(extension, ['default', *BUDGET_WINDOWS]) + for value in extension.values(): + closed(value, ['extension_id', 'extension_body_hex']) + require(value['extension_id'] == 'bounded-policy-commitment-v1' + and type(value['extension_body_hex']) is str + and 0 < len(value['extension_body_hex']) <= 8192 + and len(value['extension_body_hex']) % 2 == 0 + and all(character in '0123456789abcdef' for character in value['extension_body_hex']), + 'qualification.packets.extension-bound') else: require(extension is None, 'qualification.packets.extension-bound') return plan @@ -161,14 +211,23 @@ def prepare(args): require(review.get('schema') == 'auths.gateway-recipe-review/2', 'qualification.packets.native-review') extension = None if reference is stripe_platform: - derived = child(args.gateway, ['bound-extension', '--argument', 'amount', '--ceiling', '10000', - '--window-seconds', '86400', '--max-count', '64', '--sum-limit', '32000', '--partition', 'currency=usd,eur', - '--scope', 'payment_intent=' + ','.join(payment['id'] for payment in resources['payments'])]) - extension = {name: derived[name] for name in ['extension_id', 'extension_body_hex']} + extension = {} + for name in ['default', *BUDGET_WINDOWS]: + count = 64 if name == 'default' else (1 if name.endswith('-count') else 2) + total = 32000 if name == 'default' else (2000 if name.endswith('-count') else 1000) + derived = child(args.gateway, ['bound-extension', '--argument', 'amount', '--ceiling', '10000', + '--window-seconds', str(BUDGET_WINDOWS.get(name, 86400)), '--max-count', str(count), + '--sum-limit', str(total), '--partition', 'currency=usd,eur', + '--scope', 'payment_intent=' + ','.join(payment['id'] for payment in resources['payments'])]) + extension[name] = {field: derived[field] for field in ['extension_id', 'extension_body_hex']} evaluated_at = int(time.time()) - plan = validate({'schema': 'auths.qualification-packet-plan/3', 'family': args.family, + # Crossing a declared window would change the capacity experiment. Limit + # the ordinary author lifetime to the real next boundary, never a fake clock. + ends = [(evaluated_at // window + 1) * window for window in [86400, *BUDGET_WINDOWS.values()]] + end = min(evaluated_at + PACKET_VALIDITY, *ends) if reference is stripe_platform else evaluated_at + PACKET_VALIDITY + plan = validate({'schema': 'auths.qualification-packet-plan/4', 'family': args.family, 'protected_run': resources['protected_run'], 'evaluated_at': evaluated_at, - 'not_after': evaluated_at + PACKET_VALIDITY, 'configuration': review['verifier_configuration'], + 'not_after': end, 'configuration': review['verifier_configuration'], 'extension': extension, 'resources': resources, 'packets': arguments(args.family, resources, review['recipe_digest'])}) write(args.work / 'packet-plan.json', plan, new=True) diff --git a/qualification/reference/tests/test_author_socket.py b/qualification/reference/tests/test_author_socket.py index bb658ee64..7db799e9a 100644 --- a/qualification/reference/tests/test_author_socket.py +++ b/qualification/reference/tests/test_author_socket.py @@ -60,7 +60,7 @@ def test_refresh_never_exports_a_changed_action_context_or_aged_packet(self): 'trusted_context': 'context-0.cbor', 'action': 'live-00.action', 'arguments': {'closed': 'source'}} now = int(time.time()) - original = {'schema': 'auths.qualification-public-packets/3', + original = {'schema': 'auths.qualification-public-packets/4', 'protected_run': 'recipe-qualification/123/1', 'evaluated_at': now, 'not_after': now + 300, 'trusted_contexts': ['context-0.cbor'], 'packets': [packet]} write(work / 'public-packets.json', original, new=True) diff --git a/qualification/reference/tests/test_packets.py b/qualification/reference/tests/test_packets.py index 4dc4fdcb5..c9961db8c 100644 --- a/qualification/reference/tests/test_packets.py +++ b/qualification/reference/tests/test_packets.py @@ -21,7 +21,7 @@ def plan(self): 'protected_run': 'recipe-qualification/123/1', 'base': airtable_record.BASE, 'table': airtable_record.TABLE, 'records': [ {'id': 'recTEST0000000001', 'run_metadata': 'recipe-qualification/123/1'}]} - return {'schema': 'auths.qualification-packet-plan/3', 'family': airtable_record.FAMILY, + return {'schema': 'auths.qualification-packet-plan/4', 'family': airtable_record.FAMILY, 'protected_run': resources['protected_run'], 'evaluated_at': 1000, 'not_after': 8200, 'configuration': '1' * 64, 'extension': None, 'resources': resources, 'packets': packet_plan.arguments(airtable_record.FAMILY, resources, '2' * 64)} @@ -37,6 +37,7 @@ def test_resource_action_and_phase_changes_cannot_choose_refresh_authority(self) lambda p: p.update(not_after=9000), lambda p: p.update(evaluated_at=True), lambda p: p.update(credential='synthetic-forbidden-input'), lambda p: p.update(schema='auths.qualification-packet-plan/2'), + lambda p: p.update(schema='auths.qualification-packet-plan/3'), lambda p: p['packets'][0].update(context='fresh'), lambda p: p['packets'][1]['arguments'].update(operation_id='new-operation'), lambda p: p['packets'].reverse(), lambda p: p['packets'].pop()] @@ -62,7 +63,7 @@ def test_signing_pool_refuses_omitted_added_rebound_and_reordered_actions(self): 'action': item['label'] + '.action', 'trusted_context': 'context-' + str(['initial', 'fresh'].index(item['context'])) + '.cbor', 'arguments': item['arguments']} for item in plan['packets']] - carrier = {'schema': 'auths.qualification-public-packets/3', + carrier = {'schema': 'auths.qualification-public-packets/4', 'protected_run': plan['protected_run'], 'evaluated_at': 1000, 'not_after': 1300, 'trusted_contexts': ['context-0.cbor', 'context-1.cbor'], 'packets': packets} self.assertEqual(packet_plan.public_pool(plan['family'], plan['resources'], '2' * 64, carrier), packets) @@ -94,10 +95,10 @@ def test_stripe_guard_probes_are_fixed_valid_requests_with_independent_refusals( value = probes[phase + '-guard-' + kind]['arguments'] self.assertEqual(stripe_platform.request(value, resources, '1' * 64, '2' * 64)['method'], 'POST') self.assertEqual(stripe_platform.entry_policy(value, resources), code) - for count, accepted in [(29, True), (30, False)]: + for count, accepted in [(25, True), (26, False)]: many = dict(resources, payments=[dict(resources['payments'][0], id='pi_TEST' + str(i)) for i in range(count)]) expanded = packet_plan.arguments(stripe_platform.FAMILY, many, '2' * 64) - carrier = {'schema': 'auths.qualification-public-packets/3', 'protected_run': run, + carrier = {'schema': 'auths.qualification-public-packets/4', 'protected_run': run, 'evaluated_at': 1000, 'not_after': 1300, 'trusted_contexts': ['context-0.cbor', 'context-1.cbor'], 'packets': [ {'label': p['label'], 'proof': p['label'] + '.proof', 'action': p['label'] + '.action', @@ -108,6 +109,33 @@ def test_stripe_guard_probes_are_fixed_valid_requests_with_independent_refusals( else: with self.assertRaises(Refusal): packet_plan.public_pool(stripe_platform.FAMILY, many, '2' * 64, carrier) + def test_count_and_sum_experiments_have_distinct_fixed_native_windows(self): + run = 'recipe-qualification/123/1' + resources = {'schema': 'auths.stripe-platform-qualification-resources/1', + 'protected_run': run, 'platform': 'acct_TEST123', 'payments': [ + {'id': 'pi_TEST' + str(index), 'amount_received': 2000, 'currency': 'usd', + 'livemode': False, 'run_metadata': run} for index in range(16)]} + packets = packet_plan.arguments(stripe_platform.FAMILY, resources, '2' * 64) + self.assertEqual(len(packets), 54) + self.assertEqual(len(set(packet_plan.BUDGET_WINDOWS.values()) | {86400}), 5) + for phase in ['commissioning', 'live']: + by_label = {p['label']: p for p in packets} + for kind, resource in [('count', 'pi_TEST14'), ('sum', 'pi_TEST15')]: + label = phase + '-budget-' + kind + positive, overflow = [by_label[label + suffix]['arguments'] for suffix in ['', '-over']] + self.assertEqual(positive['payment_intent'], resource) + self.assertEqual(positive['amount'], 1000) + self.assertEqual(overflow['amount'], 500) + self.assertNotEqual(positive['operation_id'], overflow['operation_id']) + self.assertEqual(packet_plan.grant_for(label), phase + '-' + kind) + self.assertEqual(packet_plan.grant_for(label + '-over'), phase + '-' + kind) + self.assertEqual(packet_plan.grant_for(phase + '-00'), 'default') + self.assertIsNone(stripe_platform.entry_policy(positive, resources)) + for kind in ['kind', 'generation', 'commitment', 'version']: + probe = by_label[phase + '-custody-' + kind] + self.assertEqual(probe['arguments']['payment_intent'], 'pi_TEST13') + self.assertEqual(packet_plan.grant_for(probe['label']), 'default') + def test_an_unanticipated_credential_name_refuses_before_importing_the_sdk(self): with patch.dict(os.environ, {'UNANTICIPATED_PROVIDER_KEY': 'synthetic-forbidden-input'}, clear=True): with self.assertRaisesRegex(Refusal, 'consumer-environment'): diff --git a/qualification/reference/tests/test_reference.py b/qualification/reference/tests/test_reference.py index 2817fe4e9..2808c47a6 100644 --- a/qualification/reference/tests/test_reference.py +++ b/qualification/reference/tests/test_reference.py @@ -203,7 +203,7 @@ def test_binding_is_rederived_and_altered_source_or_native_observations_refuse(s 'proof': label + '.proof', 'action': label + '.action', 'arguments': packet['arguments']}) (work / 'resources.json').write_bytes(canonical(self.stripe_resources())) (work / 'packets.json').write_bytes(canonical({ - 'schema': 'auths.qualification-public-packets/3', 'protected_run': RUN, + 'schema': 'auths.qualification-public-packets/4', 'protected_run': RUN, 'evaluated_at': 1000, 'not_after': 1300, 'trusted_contexts': ['context-0.cbor', 'context-1.cbor'], 'packets': packets})) artifacts = json.loads((root / 'bindings/fixtures/qualification/commissioning-v2.json').read_bytes()) From bf970f115ea4b9da08a9161bf3e61f85cb47832c Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 15:11:59 +0100 Subject: [PATCH 084/108] Add reviewed family corpora and executable offline qualification jobs --- .github/workflows/recipe-qualification.yml | 19 ++ ...gateway-polish-and-recipe-qualification.md | 23 ++ .../tests/script_pipeline.rs | 1 + qualification/README.md | 13 +- .../airtable-record-update-v1/contract.json | 1 + .../corpus-manifest.json | 1 + .../decision-record.md | 9 + .../airtable-record-update-v1/harness | 7 + .../airtable-record-update-v1/record.json | 1 + .../stripe-platform-refund-v1/contract.json | 1 + .../corpus-manifest.json | 1 + .../decision-record.md | 9 + .../stripe-platform-refund-v1/harness | 7 + .../stripe-platform-refund-v1/record.json | 1 + qualification/reference/README.md | 10 +- qualification/reference/family_corpus.py | 184 +++++++++++++++ qualification/reference/family_harness.py | 214 ++++++++++++++++++ qualification/reference/generate_families.py | 119 ++++++++++ .../reference/tests/test_family_plans.py | 50 ++++ qualification/run/commission.py | 2 + qualification/run/live.sh | 2 +- qualification/run/offline.sh | 13 +- 22 files changed, 681 insertions(+), 7 deletions(-) create mode 100644 qualification/families/airtable-record-update-v1/contract.json create mode 100644 qualification/families/airtable-record-update-v1/corpus-manifest.json create mode 100644 qualification/families/airtable-record-update-v1/decision-record.md create mode 100755 qualification/families/airtable-record-update-v1/harness create mode 100644 qualification/families/airtable-record-update-v1/record.json create mode 100644 qualification/families/stripe-platform-refund-v1/contract.json create mode 100644 qualification/families/stripe-platform-refund-v1/corpus-manifest.json create mode 100644 qualification/families/stripe-platform-refund-v1/decision-record.md create mode 100755 qualification/families/stripe-platform-refund-v1/harness create mode 100644 qualification/families/stripe-platform-refund-v1/record.json create mode 100644 qualification/reference/family_corpus.py create mode 100644 qualification/reference/family_harness.py create mode 100644 qualification/reference/generate_families.py create mode 100644 qualification/reference/tests/test_family_plans.py diff --git a/.github/workflows/recipe-qualification.yml b/.github/workflows/recipe-qualification.yml index ba6986427..a0f2884ca 100644 --- a/.github/workflows/recipe-qualification.yml +++ b/.github/workflows/recipe-qualification.yml @@ -235,6 +235,20 @@ jobs: - uses: ./.github/actions/setup-rust-cache with: toolchain: 1.97.1 + - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 + with: + python-version: "3.12" + - name: Install the exact SDK wheel outside the checkout + shell: bash + run: | + set -euo pipefail + python -m pip install maturin==1.9.6 + maturin build --profile python-extension --locked \ + --manifest-path bindings/python/Cargo.toml --out target/qualification-offline-wheels + python -m venv "${RUNNER_TEMP}/offline-consumer" + "${RUNNER_TEMP}/offline-consumer/bin/python" -m pip install target/qualification-offline-wheels/*.whl + mkdir -p "${RUNNER_TEMP}/offline-author-kit" + cp qualification/reference/*.py "${RUNNER_TEMP}/offline-author-kit/" - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 with: name: qualification-shipping-candidate-${{ github.run_id }}-${{ github.run_attempt }} @@ -248,6 +262,11 @@ jobs: chmod +x "${RUNNER_TEMP}/candidate/bin/"* export AUTHS_GATEWAY="${RUNNER_TEMP}/candidate/bin/auths-gateway" export AUTHS_QUALIFICATION="${RUNNER_TEMP}/candidate/bin/auths-qualification" + export AUTHS_QUALIFICATION_CONSUMER_PYTHON="${RUNNER_TEMP}/offline-consumer/bin/python" + export AUTHS_QUALIFICATION_AUTHOR_KIT="${RUNNER_TEMP}/offline-author-kit" + wheels=("${GITHUB_WORKSPACE}"/target/qualification-offline-wheels/*.whl) + test "${#wheels[@]}" -eq 1 + export AUTHS_QUALIFICATION_WHEEL="${wheels[0]}" qualification/run/offline.sh "${FAMILY}" "${RUNNER_TEMP}/work" - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: diff --git a/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md b/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md index 70ff8040d..cb3a6b684 100644 --- a/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md +++ b/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md @@ -1828,3 +1828,26 @@ mapping is `complete`, without an HTTP response or effect claim. `review` is refused as a protected operation or a replacement for an application submission. First commissioning therefore depends on offline native verification, without requiring pre-existing qualification to collect that verification. + +#### 22.7 Reviewed family plans and executable offline collection + +Both family directories now bind the exact source compiler, provider references, +packet author, maintained recipe/lock and ADR in a canonical reviewed-plan +manifest. The native provider contract hashes that manifest; a record separately +hashes the concrete native corpus expanded from its authenticated public pool. +The source generator refuses drift before permit contract derivation. Candidate +outcomes never supply expected verdicts or request/evidence commitments. + +The full plan fixes 16 resources per family and includes both protected phases, +ordinary Python/TypeScript journeys, isolation, drift, rotation, replay, race, +restart, crash, loss/delayed visibility and production doctor. Stripe additionally +has fixed count/sum capacity experiments and exact relative-ceiling probes. +The installed author keeps one actor and reviewed grants; the distinct native +budget windows isolate those capacity experiments without resetting state. + +The six offline scenarios have an executable family harness and hosted jobs +using the actual installed wheel and shipping gateway. The native runner derives +their conformance/differential reports, and the issuer constructs canonical +offline evidence. Verification of this new collection is pending. Protected +operations currently refuse without their production journey implementation; +the source plan is not evidence that those operations ran. Epic 5 remains open. diff --git a/product/qualification/auths-recipe-qualification-issuance/tests/script_pipeline.rs b/product/qualification/auths-recipe-qualification-issuance/tests/script_pipeline.rs index 7f6afdccf..79a77aea8 100644 --- a/product/qualification/auths-recipe-qualification-issuance/tests/script_pipeline.rs +++ b/product/qualification/auths-recipe-qualification-issuance/tests/script_pipeline.rs @@ -249,6 +249,7 @@ fn live_script_cleans_up_after_success_setup_failure_and_stage_failure() { ) .expect("corpus"); let scripts = Path::new(env!("CARGO_MANIFEST_DIR")).join("../../../qualification/run"); + fs::create_dir_all(work.join("cases")).expect("earlier phase report directory"); for mode in ["success", "setup-failed", "failed", "cleanup-failed"] { fs::write(work.join("fault"), mode).expect("fault"); // A prior phase's outputs must also become unusable if the overall diff --git a/qualification/README.md b/qualification/README.md index 5fab0d3dc..cff34448a 100644 --- a/qualification/README.md +++ b/qualification/README.md @@ -90,7 +90,7 @@ One directory per recipe family, named by its `RecipeFamilyId`. | --- | --- | | `decision-record.md` | The family's decision record. Its digest goes into the record. | | `contract.json` | The canonical `auths.provider-contract/1` the run qualifies against. | -| `corpus-manifest.json` | The corpus the differential, hostile, and live stages run. | +| `corpus-manifest.json` | The reviewed source plan and exact compiler/oracle file hashes, expanded into the concrete native corpus. | | `record.json` | What the record states that no run decides: `provider_kind`, `validity_days` (at most 90), `not_applicable` (each capability the family lacks, with the reason the decision record fixes), `custody_descriptor`, `store_descriptor`, `residual_assumptions`, `excluded_claims`. | | `harness` | A reviewed executable implementing `prepare`, `prepare-live`, `step` and `cleanup`. | @@ -98,7 +98,16 @@ The harness owns the provider-specific operations and pure oracle. The release runner owns sequencing, assertions, counters, and the resulting case reports. No family harness writes `passed` reports or `live-effects.json`. -`corpus-manifest.json` is `auths.qualification-corpus/3`, decoded as +The checked-in manifest is `auths.qualification-reviewed-plan/1`. It binds the +exact source compiler, provider references, packet author, recipe, lock and ADR. +`python3 -B qualification/reference/generate_families.py` regenerates the closed +plans, contracts, record metadata and family entry points; `--check` refuses +source or artifact drift. The permit signer performs that check before deriving +the source-owned contract identity. + +The compiler independently derives each request and fresh-evidence subject from +the complete authenticated public pool. Its concrete `corpus.json` is +`auths.qualification-corpus/3`, decoded as `execution::RunCorpus` by `auths-qualification run-stage`. It contains at most 256 unique cases. Each case has `id`, `scenario`, `capabilities`, `phase` (`offline`, `commissioning` or `live`), and at most 32 ordered `steps`. Each step has a closed diff --git a/qualification/families/airtable-record-update-v1/contract.json b/qualification/families/airtable-record-update-v1/contract.json new file mode 100644 index 000000000..f202bd24d --- /dev/null +++ b/qualification/families/airtable-record-update-v1/contract.json @@ -0,0 +1 @@ +{"api_release":"web-api-v0-reviewed-2026-10-07","corpus_manifest_sha256":"884b1afbc343dd9d68a65018d6d7edd848b672891b951345d1bde5c8c234458f","declarations":{"idempotency_sha256":"74234e98afe7498fb5daf1f36ac2d78acc339464f950703b8c019892f982b90b","observation_sha256":"9dd79dd204fa13a2df3c667d106c66c0526d174a2c018631e2b2f6b897eaf311","recovery_sha256":"7081a92b4cd2d13dab5e7c30e640675a252b62bca20d340e14d62d9c8c048eca","retention_sha256":"4a4b5048c97b16e041af55b032c0b8ac20f5142c4bbcbf31b31c6674770a70d0"},"environment_class":"disposable-live-resources","manual_assumptions":["Airtable supplies no idempotency key for this PATCH; durable gateway admission prevents a second entry.","Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only a fresh GET with the exact replacement and echo can reconcile a lost response.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths.","The reviewed fixed Airtable base and table contain only owner-authorized disposable qualification records."],"oracle_version":"auths-reviewed-reference-v2","provider":"airtable","schema":"auths.provider-contract/1"} \ No newline at end of file diff --git a/qualification/families/airtable-record-update-v1/corpus-manifest.json b/qualification/families/airtable-record-update-v1/corpus-manifest.json new file mode 100644 index 000000000..ecc2b3a30 --- /dev/null +++ b/qualification/families/airtable-record-update-v1/corpus-manifest.json @@ -0,0 +1 @@ +{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"32241d9b4811a55abcdd224ef567df3857dbec34d761ef7a35d1044cdfa52d9f","family":"airtable-record-update-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"af7f984509ab11a3676cacc85eda2fa638c25bf91f7bfedf3ff3c119e47f3c41","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"e58dc84b60f5ff13e5c7b1b5aae4917c5427f31cc8ac041acdd85defc8cd5e92","family_harness.py":"de6945b6fb3c3b1feaa1dbfa8b68b9e433bcdef0f0e98a2006ab4485427742f2","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"4896a5f16474cbb418decb719bcc2af4a08483eabeca996427b40560a16d02cf","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","resource_io.py":"025139a787f50f5181e390ea58da45db00dbdef15c8b3928cba9e0485945f6fe","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489"},"source_recipe_sha256":"c0f21ff1d3c8e344fee20a9a0c25bb14a264417ed53418ad536789a6096fb16e"} \ No newline at end of file diff --git a/qualification/families/airtable-record-update-v1/decision-record.md b/qualification/families/airtable-record-update-v1/decision-record.md new file mode 100644 index 000000000..2e581f99b --- /dev/null +++ b/qualification/families/airtable-record-update-v1/decision-record.md @@ -0,0 +1,9 @@ +# airtable-record-update-v1 + +Status: source plan; no production qualification. + +The provider decision is [ADR](../../../docs/adr/0015-airtable-record-update-recipe-qualification.md). Its exact digest is in the reviewed plan. + +The source-owned compiler expands the complete closed packet pool into the native three-phase corpus. Offline operations execute the installed SDK and shipping native reviewer. Protected operations must use PostgreSQL, actual AWS custody, two processes, fresh read-back and measured counters. An absent protected implementation refuses and emits no observation. + +The contract hashes this reviewed source plan; the record separately hashes its concrete native corpus expansion. This avoids a source/candidate/actor commitment cycle. The signer must reconstruct the expansion from its own reviewed source before issuing authority. diff --git a/qualification/families/airtable-record-update-v1/harness b/qualification/families/airtable-record-update-v1/harness new file mode 100755 index 000000000..567a47de4 --- /dev/null +++ b/qualification/families/airtable-record-update-v1/harness @@ -0,0 +1,7 @@ +#!/usr/bin/env python3 +import sys +from pathlib import Path +sys.dont_write_bytecode = True +sys.path.insert(0, str(Path(__file__).resolve().parents[2] / 'reference')) +from family_harness import main +main('airtable-record-update-v1', sys.argv[1:]) diff --git a/qualification/families/airtable-record-update-v1/record.json b/qualification/families/airtable-record-update-v1/record.json new file mode 100644 index 000000000..85a389e83 --- /dev/null +++ b/qualification/families/airtable-record-update-v1/record.json @@ -0,0 +1 @@ +{"custody_descriptor":"aws-secrets-manager-v1 with immutable versions and a customer-managed key","excluded_claims":["Gateway enforcement of the personal access token resource configuration.","Global exactly-once effects across other actors or deployments.","Provider availability, settlement, or indefinite retention."],"not_applicable":[{"capability":"account-binding","reason":"The recipe declares no account-binding probe."},{"capability":"budget","reason":"This recipe declares no numeric count/sum budget."},{"capability":"ceiling","reason":"The field-update profile carries no numeric amount or relative ceiling."},{"capability":"credential-guard","reason":"This recipe declares no provider credential guard."},{"capability":"denied-reads","reason":"The recipe declares no denied credential reads; token scope is an operator assumption."},{"capability":"idempotency","reason":"This PATCH declares no provider idempotency key."},{"capability":"observer-rotation","reason":"The qualified reference configures no signing observer."},{"capability":"response-locator","reason":"Observation uses the verified record ID, not a write-response locator."},{"capability":"version-pin","reason":"Airtable Web API v0 has no immutable response version pin."}],"provider_kind":"airtable","residual_assumptions":["Airtable supplies no idempotency key for this PATCH; durable gateway admission prevents a second entry.","Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only a fresh GET with the exact replacement and echo can reconcile a lost response.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths.","The reviewed fixed Airtable base and table contain only owner-authorized disposable qualification records."],"store_descriptor":"postgresql-v1 schema 6 shared by two isolated gateway processes","validity_days":30} \ No newline at end of file diff --git a/qualification/families/stripe-platform-refund-v1/contract.json b/qualification/families/stripe-platform-refund-v1/contract.json new file mode 100644 index 000000000..fe13e7090 --- /dev/null +++ b/qualification/families/stripe-platform-refund-v1/contract.json @@ -0,0 +1 @@ +{"api_release":"2025-03-31.basil","corpus_manifest_sha256":"1cce0b50bf5d59e70470bb3fe0fb3fe072c36a219f0e384972d0e1f7e7f466be","declarations":{"idempotency_sha256":"425a0dca2f279765debfc847c4a01bff60fea5be68dd9d761ae6bb60ce0b8a7b","observation_sha256":"d0ce5a34d987821c69c0a839d9ed66805c625f8324dd42031fcccf0752a8821e","recovery_sha256":"bf2303abce165c175360ac975586431bbc4cf03167489ea317a27de2f0b04abb","retention_sha256":"846c2164e26d1144d9aa146034b4f7ea4dc305136a59ffd94f999d19f2c360ee"},"environment_class":"provider-test-mode","manual_assumptions":["Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","Stripe idempotency is tested only inside the declared 86400-second retention interval.","Stripe test mode and the installed platform are checked by the declared guard on each lease.","The 50-percent payment basis is a read, not an atomic provider balance reservation.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths."],"oracle_version":"auths-reviewed-reference-v2","provider":"stripe","schema":"auths.provider-contract/1"} \ No newline at end of file diff --git a/qualification/families/stripe-platform-refund-v1/corpus-manifest.json b/qualification/families/stripe-platform-refund-v1/corpus-manifest.json new file mode 100644 index 000000000..37c3c50a1 --- /dev/null +++ b/qualification/families/stripe-platform-refund-v1/corpus-manifest.json @@ -0,0 +1 @@ +{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"a72c557b69103a52eb477deb8364ded53cd58407b9ba7ab33ccbda74389fec1e","family":"stripe-platform-refund-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"99901e36cb7c4f5882897603c874698d582e859b5d6b08d53cd80975e89aa01c","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"e58dc84b60f5ff13e5c7b1b5aae4917c5427f31cc8ac041acdd85defc8cd5e92","family_harness.py":"de6945b6fb3c3b1feaa1dbfa8b68b9e433bcdef0f0e98a2006ab4485427742f2","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"4896a5f16474cbb418decb719bcc2af4a08483eabeca996427b40560a16d02cf","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","resource_io.py":"025139a787f50f5181e390ea58da45db00dbdef15c8b3928cba9e0485945f6fe","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489"},"source_recipe_sha256":"b1972d556f28433932a449636755077f7ee485ef90cca412f153bc7f18881368"} \ No newline at end of file diff --git a/qualification/families/stripe-platform-refund-v1/decision-record.md b/qualification/families/stripe-platform-refund-v1/decision-record.md new file mode 100644 index 000000000..41f19a55f --- /dev/null +++ b/qualification/families/stripe-platform-refund-v1/decision-record.md @@ -0,0 +1,9 @@ +# stripe-platform-refund-v1 + +Status: source plan; no production qualification. + +The provider decision is [ADR](../../../docs/adr/0014-stripe-refund-recipe-qualification.md). Its exact digest is in the reviewed plan. + +The source-owned compiler expands the complete closed packet pool into the native three-phase corpus. Offline operations execute the installed SDK and shipping native reviewer. Protected operations must use PostgreSQL, actual AWS custody, two processes, fresh read-back and measured counters. An absent protected implementation refuses and emits no observation. + +The contract hashes this reviewed source plan; the record separately hashes its concrete native corpus expansion. This avoids a source/candidate/actor commitment cycle. The signer must reconstruct the expansion from its own reviewed source before issuing authority. diff --git a/qualification/families/stripe-platform-refund-v1/harness b/qualification/families/stripe-platform-refund-v1/harness new file mode 100755 index 000000000..c54a3e8f8 --- /dev/null +++ b/qualification/families/stripe-platform-refund-v1/harness @@ -0,0 +1,7 @@ +#!/usr/bin/env python3 +import sys +from pathlib import Path +sys.dont_write_bytecode = True +sys.path.insert(0, str(Path(__file__).resolve().parents[2] / 'reference')) +from family_harness import main +main('stripe-platform-refund-v1', sys.argv[1:]) diff --git a/qualification/families/stripe-platform-refund-v1/record.json b/qualification/families/stripe-platform-refund-v1/record.json new file mode 100644 index 000000000..04792bbc4 --- /dev/null +++ b/qualification/families/stripe-platform-refund-v1/record.json @@ -0,0 +1 @@ +{"custody_descriptor":"aws-secrets-manager-v1 with immutable versions and a customer-managed key","excluded_claims":["Connected-account selection or restrictions.","Global exactly-once effects across other actors or deployments.","Provider availability, settlement, or indefinite retention."],"not_applicable":[{"capability":"observer-rotation","reason":"The qualified reference configures no signing observer."},{"capability":"recovery","reason":"An unrecorded refund response has no verified response locator; loss remains unknown."}],"provider_kind":"stripe","residual_assumptions":["Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","Stripe idempotency is tested only inside the declared 86400-second retention interval.","Stripe test mode and the installed platform are checked by the declared guard on each lease.","The 50-percent payment basis is a read, not an atomic provider balance reservation.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths."],"store_descriptor":"postgresql-v1 schema 6 shared by two isolated gateway processes","validity_days":30} \ No newline at end of file diff --git a/qualification/reference/README.md b/qualification/reference/README.md index 490108a65..5fd3b8e15 100644 --- a/qualification/reference/README.md +++ b/qualification/reference/README.md @@ -60,8 +60,14 @@ pool, including both phase operations and both fresh-challenge replays. Missing, additional, reordered or rebound packets cannot receive a permit. A one-packet refresh is a private execution handoff, never a new signing input. -The protected family setup, complete corpus and live workflow still need to -use these references. No family is qualified by landing this code. +The two family directories now contain reviewed source plans, provider +contracts and record metadata. `family_corpus.py` expands their fixed 16-resource +public pool into complete native case sequences. `family_harness.py` executes +the six offline scenarios with the actual installed SDK and shipping reviewer; +the native runner validates the full plan before selecting that phase. The +workflow retains real canonical conformance and differential evidence. +Protected operations still refuse without the production journey implementation. +No family is qualified by landing this code. The native commissioning permit is now schema 2. Its closed `trusted_contexts_sha256` list contains 1–4 sorted unique exact canonical context diff --git a/qualification/reference/family_corpus.py b/qualification/reference/family_corpus.py new file mode 100644 index 000000000..bfaa5c3a5 --- /dev/null +++ b/qualification/reference/family_corpus.py @@ -0,0 +1,184 @@ +"""Source-owned corpus expansion; no outcome from a run supplies expectations. + +Native review authenticates actors/actions. These provider references derive +requests and fresh-evidence subjects independently. The native stage runner +owns coverage and the comparison of actual observations with this plan. +""" + +import airtable_record +import stripe_platform +import fresh_evidence +from common import canonical, closed, digest, require, sha256 +from expand import child, decode, read, SOURCES +from packet_plan import public_pool + +RESOURCES = 16 +REFERENCES = {r.FAMILY: r for r in [stripe_platform, airtable_record]} + + +def authenticate(family, work, gateway, tuple_value): + reference = REFERENCES.get(family) + require(reference is not None and tuple_value['recipe_family'] == family, + 'qualification.corpus.family') + resources = decode(read(work / 'resources.json', 65536)) + reference.resources(resources, resources['protected_run']) + values = resources['payments'] if reference is stripe_platform else resources['records'] + require(len(values) == RESOURCES, 'qualification.corpus.resource-count') + source = SOURCES[family] + require(decode(read(work / 'recipe.json', 65536)) == reference.recipe( + decode(read(source / 'recipe.json', 65536)), resources) + and read(work / 'profile.lock.json', 65536) == read(source / 'profile.lock.json', 65536), + 'qualification.corpus.reviewed-source') + carrier = decode(read(work / 'public-packets.json', 65536)) + packets = public_pool(family, resources, tuple_value['compiled_recipe_sha256'], carrier) + reviewed, actors = {}, set() + for packet in packets: + actual = child(gateway, ['review-submission', '--recipe', work / 'recipe.json', + '--profile-lock', work / 'profile.lock.json', + '--trusted-context', work / packet['trusted_context'], '--proof', work / packet['proof'], + '--action', work / packet['action'], '--evaluated-at', str(carrier['evaluated_at'])]) + closed(actual, ['schema', 'actors', 'action_commitment', 'arguments', 'request']) + require(actual['schema'] == 'auths.gateway-submission-review/1' + and len(actual['actors']) == 1 and actual['arguments'] == packet['arguments'], + 'qualification.corpus.proof-binding') + request = reference.request(actual['arguments'], resources, digest(actual['action_commitment']), + tuple_value['compiled_recipe_sha256']) + require(actual['request'] == request, 'qualification.corpus.request-binding') + actors.update(actual['actors']) + reviewed[packet['label']] = actual + require(len(actors) == 1, 'qualification.corpus.actor-binding') + return resources, reviewed + + +def compile_plan(family, resources, reviewed, recipe_digest): + """Closed provider-specific cases, including both protected phases. + + Administrative compound probes have source-owned completion codes. Their + harness must check the actual native refusals and counters before returning + that completion; it cannot copy this expected observation as its result. + """ + reference = REFERENCES.get(family) + require(reference is not None, 'qualification.corpus.family') + reference.resources(resources, resources['protected_run']) + values = resources['payments'] if reference is stripe_platform else resources['records'] + require(len(values) == RESOURCES, 'qualification.corpus.resource-count') + cases = [] + + def request(label): + value = reviewed[label] + result = reference.request(value['arguments'], resources, value['action_commitment'], recipe_digest) + require(value['request'] == result, 'qualification.corpus.request-binding') + return sha256(canonical(result)) + + def step(operation, outcome, code, label=None, leases=0, entries=0, confirmed=0, fresh=False): + comparison = {'kind': 'static'} + if fresh: + value = reviewed[label] + comparison = {'kind': 'independent-read-back', 'subject_sha256': fresh_evidence.subject( + family, value['arguments'], resources, value['action_commitment'], recipe_digest)} + return {'operation': operation, 'evidence_comparison': comparison, + 'expected': {'verdict': {'outcome': outcome, 'code': code, + 'request_sha256': None if label is None else request(label), 'evidence_sha256': None}, + 'credential_leases': leases, 'provider_entries': entries, + 'confirmed_by_read_back': confirmed}} + + def complete(operation, code): + return step(operation, 'complete', code) + + def observed(operation, label, leases=2, entries=1, confirmed=1): + return step(operation, 'observed', 'observed-by-provider', label, + leases, entries, confirmed, True) + + def unknown(operation, label, leases=0, entries=0): + return step(operation, 'unknown', 'unknown', label, leases, entries) + + def replay(): + return step('replay', 'refused', 'gateway.attempt.replay') + + def add(phase, identifier, scenario, steps, capabilities=()): + cases.append({'id': phase + '-' + identifier, 'scenario': scenario, + 'capabilities': list(capabilities), 'phase': phase, 'steps': steps}) + + for identifier, scenario, code in [ + ('source', 'clean-source', 'source-clean'), + ('digest', 'recipe-digest-rederives', 'recipe-digest-rederived'), + ('vectors', 'recipe-vectors', 'recipe-vectors-passed'), + ('closed', 'closed-enumeration-hostile', 'closed-enumeration-refused')]: + add('offline', identifier, scenario, [complete('probe', code)]) + label = 'commissioning-00' + add('offline', 'oracle-accept', 'oracle-accepts', [ + step(operation, 'complete', 'request-mapped', label) for operation in ['oracle', 'review']]) + add('offline', 'oracle-reject', 'oracle-rejects', [ + step(operation, 'refused', 'action-outside-validity') for operation in ['oracle', 'review']]) + + for phase in ['commissioning', 'live']: + label = lambda index: phase + '-' + str(index).zfill(2) + add(phase, 'fresh-replay', 'fresh-challenge-replay', + [observed('submit', label(0)), replay()]) + add(phase, 'proof-replay', 'proof-replay', [observed('submit', label(1)), replay()]) + # The held owner response keeps an entered operation unresolved while + # the second actual process races its claim. Airtable can take one + # read-only recovery lease; Stripe has no unrecorded response locator. + add(phase, 'two-host-race', 'two-instance-race', + [observed('race', label(2), leases=3 if reference is airtable_record else 2)]) + for index, operation in [(3, 'restart'), (4, 'crash')]: + ending = observed('replay', label(index), 1, 0, 1) if reference is airtable_record \ + else unknown('replay', label(index)) + add(phase, operation, operation, [unknown('submit', label(index), 1, 1), + complete(operation, 'gateway-' + operation + '-completed'), ending]) + add(phase, 'ambiguous', 'ambiguous-response', [unknown('drop-response', label(5), 1, 1), + observed('replay', label(5), 1, 0, 1) if reference is airtable_record + else unknown('replay', label(5))]) + for index, identifier, operation, scenario in [ + (6, 'response-loss', 'drop-response', 'response-loss'), + (7, 'visibility', 'delay-visibility', 'delayed-visibility')]: + ending = observed('read-back', label(index), 1, 0, 1) if reference is airtable_record \ + else unknown('read-back', label(index)) + add(phase, identifier, scenario, [unknown(operation, label(index), 1, 1), ending], + ('recovery',) if reference is airtable_record else ()) + add(phase, 'secret-rotation', 'provider-secret-rotation', + [complete('rotate', 'provider-secret-rotated'), observed('submit', label(8))]) + add(phase, 'read-back', 'read-back-confirms-write', [observed('submit', label(9)), + observed('read-back', label(9), 1, 0, 0)]) + capabilities = ['echo', 'observation'] + if reference is stripe_platform: + capabilities = ['credential-guard', 'version-pin', 'account-binding', 'denied-reads', + 'idempotency', 'response-locator', *capabilities] + add(phase, 'capabilities', 'declared-capability', [observed('submit', label(10)), + complete('probe', 'provider-capabilities-confirmed')], capabilities) + for index, language in [(11, 'python'), (12, 'typescript')]: + consumer = observed('installed-consumer', label(index)) if phase == 'live' else \ + step('installed-consumer', 'refused', 'gateway.qualification.missing') + add(phase, 'installed-' + language, 'installed-journey', [consumer]) + add(phase, language + '-no-source', 'no-repository-import', + [complete('installed-consumer', 'installed-package-provenance-confirmed')]) + add(phase, language + '-no-token', 'no-provider-token', + [complete('installed-consumer', 'provider-token-absent')]) + for identifier, scenario, code in [ + ('isolation', 'application-cannot-read-secret', 'application-secret-access-refused'), + ('direct-provider', 'direct-provider-attempt', 'direct-provider-access-refused')]: + add(phase, identifier, scenario, [complete('probe', code)]) + for identifier, scenario in [('forged', 'forged-proof'), ('altered', 'altered-action')]: + add(phase, identifier, scenario, + [step('probe', 'refused', 'gateway.verify.invalid-input')]) + for kind, scenario in [('kind', 'store-kind-drift'), ('generation', 'generation-drift'), + ('commitment', 'commitment-drift'), ('version', 'external-version-drift')]: + # Before-entry connection binding probes and actual post-claim + # custody-version failures are distinct measured boundaries. + leases = 1 if kind in ['commitment', 'version'] else 0 + add(phase, 'custody-' + kind, scenario, + [step('probe', 'complete', 'custody-' + kind + '-refused', leases=leases)]) + if reference is stripe_platform: + for kind, code in [('ceiling', 'gateway.relative-ceiling.above'), + ('currency', 'gateway.relative-ceiling.binding-mismatch')]: + add(phase, 'guard-' + kind, 'declared-capability', + [step('probe', 'refused', code, leases=1)], ('ceiling',)) + for kind in ['count', 'sum']: + budget_label = phase + '-budget-' + kind + add(phase, 'budget-' + kind, 'declared-capability', + [observed('race', budget_label), complete('probe', 'budget-' + kind + '-refusal-confirmed')], + ('budget', 'ceiling')) + doctor = complete('probe', 'production-readiness-passed') + doctor['evidence_comparison'] = {'kind': 'production-doctor'} + add('live', 'doctor', 'production-readiness', [doctor]) + return {'schema': 'auths.qualification-corpus/3', 'cases': cases} diff --git a/qualification/reference/family_harness.py b/qualification/reference/family_harness.py new file mode 100644 index 000000000..230b2fda0 --- /dev/null +++ b/qualification/reference/family_harness.py @@ -0,0 +1,214 @@ +"""Reviewed family harness. Offline steps perform actual native checks. + +Protected operations require the source-owned production journey. No missing +operation produces an observation or a passing report. +""" + +import copy +import os +from pathlib import Path +import subprocess +import sys + +import airtable_record +import stripe_platform +from common import canonical, closed, require, sha256 +from expand import child, decode, read, SOURCES +from family_corpus import authenticate, compile_plan, RESOURCES +from packet_plan import prepare as packet_prepare +from resource_io import finish, run_id, write, write_bytes + +ROOT = Path(__file__).resolve().parents[2] +REFERENCES = {r.FAMILY: r for r in [stripe_platform, airtable_record]} + + +def command(arguments, cwd=ROOT): + result = subprocess.run(list(map(str, arguments)), capture_output=True, timeout=90, + cwd=cwd, env={'PATH': '/usr/bin:/bin', 'PYTHONNOUSERSITE': '1'}) + require(len(result.stdout) <= 65536 and len(result.stderr) <= 65536, + 'qualification.harness.output-bound') + return result + + +def gateway(): + return Path(os.environ['AUTHS_GATEWAY']).resolve(strict=True) + + +def source_commit(): + revision = command(['/usr/bin/git', 'rev-parse', 'HEAD']) + status = command(['/usr/bin/git', 'status', '--porcelain']) + require(revision.returncode == status.returncode == 0 and not status.stdout.strip(), + 'qualification.harness.source-not-clean') + commit = revision.stdout.decode('ascii').strip() + require('GITHUB_SHA' not in os.environ or os.environ['GITHUB_SHA'] == commit, + 'qualification.harness.source-binding') + return commit + + +def synthetic_resources(family, protected_run): + if family == stripe_platform.FAMILY: + return {'schema': 'auths.stripe-platform-qualification-resources/1', + 'protected_run': protected_run, 'platform': 'acct_SYNTHETIC', 'payments': [ + {'id': 'pi_SYNTHETIC' + str(index).zfill(2), 'amount_received': 2000, + 'currency': 'usd', 'livemode': False, 'run_metadata': protected_run} + for index in range(RESOURCES)]} + return {'schema': 'auths.airtable-record-qualification-resources/1', + 'protected_run': protected_run, 'base': airtable_record.BASE, 'table': airtable_record.TABLE, + 'records': [{'id': 'recTEST' + str(index).zfill(10), 'run_metadata': protected_run} + for index in range(RESOURCES)]} + + +def candidate(family, work): + issuer = Path(os.environ['AUTHS_QUALIFICATION']).resolve(strict=True) + contract = command([issuer, 'contract-id', '--contract', + ROOT / 'qualification/families' / family / 'contract.json']) + require(contract.returncode == 0, 'qualification.harness.contract') + return child(gateway(), ['qualification-candidate', '--recipe', work / 'recipe.json', + '--profile-lock', work / 'profile.lock.json', '--recipe-family', family, + '--provider-contract-id', contract.stdout.decode('ascii').strip()]) + + +def prepare(family, work): + from generate_families import generate + generate(check=True) + source_commit() + require(work.is_dir() and not work.is_symlink(), 'qualification.harness.work-directory') + os.chmod(work, 0o700) + protected_run = run_id('recipe-qualification/' + os.environ['GITHUB_RUN_ID'] + '/' + os.environ['GITHUB_RUN_ATTEMPT']) + write(work / 'resources.json', synthetic_resources(family, protected_run), new=True) + packet_prepare(type('Inputs', (), {'family': family, 'resources': work / 'resources.json', + 'gateway': gateway(), 'work': work})()) + # The wheel and public author kit are installed/copied by the credential- + # free workflow. The SDK process never receives this checkout or its env. + python = Path(os.environ['AUTHS_QUALIFICATION_CONSUMER_PYTHON']).resolve(strict=True) + kit = Path(os.environ['AUTHS_QUALIFICATION_AUTHOR_KIT']).resolve(strict=True) + result = command([python, '-B', kit / 'author_packets.py', '--plan', work / 'packet-plan.json', + '--work', work], cwd=work) + require(result.returncode == 0, 'qualification.harness.installed-author') + tuple_value = candidate(family, work) + resources, reviewed = authenticate(family, work, gateway(), tuple_value) + corpus = compile_plan(family, resources, reviewed, tuple_value['compiled_recipe_sha256']) + write_bytes(work / 'corpus.json', canonical(corpus), new=True) + author = decode(read(work / 'author-report.json', 65536)) + wheel = Path(os.environ['AUTHS_QUALIFICATION_WHEEL']).resolve(strict=True) + write(work / 'packages.json', sorted([ + {'name': 'auths', 'version': author['sdk_version'], 'sha256': sha256(read(wheel, 64 * 1024 * 1024))}, + {'name': 'auths-gateway', 'version': tuple_value['target']['gateway_version'], + 'sha256': tuple_value['target']['gateway_build_sha256']}, + ], key=lambda package: package['name']), new=True) + + +def review(work, packet, evaluated_at): + return child(gateway(), ['review-submission', '--recipe', work / 'recipe.json', + '--profile-lock', work / 'profile.lock.json', '--trusted-context', work / packet['trusted_context'], + '--proof', work / packet['proof'], '--action', work / packet['action'], + '--evaluated-at', str(evaluated_at)]) + + +def hostile(work): + original = decode(read(work / 'recipe.json', 65536)) + changes = [lambda value: value.update(unreviewed=True), + lambda value: value.update(schema='auths.gateway-recipe-source/0'), + lambda value: value.update(origin='http://api.example.invalid'), + lambda value: value['credential'].update(kind='unreviewed-adapter'), + lambda value: value['write'].update(method='CONNECT'), + lambda value: value['write'].update(unreviewed=True), + lambda value: value['write']['path'][0].update(kind='caller-url'), + lambda value: value['observation'].update(unreviewed=True), + lambda value: value['echo']['write'].update(kind='caller-header')] + directory = work / 'hostile-recipes' + directory.mkdir(mode=0o700, exist_ok=True) + for index, change in enumerate(changes): + value = copy.deepcopy(original) + change(value) + path = directory / (str(index) + '.json') + write(path, value, new=not path.exists()) + refusal = command([gateway(), 'review', '--recipe', path, + '--profile-lock', work / 'profile.lock.json']) + require(refusal.returncode != 0 and b'gateway.' in refusal.stderr, + 'qualification.harness.hostile-recipe-admitted') + + +def offline(family, identifier, index, operation, work): + tuple_value = decode(read(work / 'tuple.json', 65536)) + resources = decode(read(work / 'resources.json', 65536)) + reference = REFERENCES[family] + reference.resources(resources, resources['protected_run']) + carrier = decode(read(work / 'public-packets.json', 65536)) + packet = carrier['packets'][0] + verdict = {'outcome': 'complete', 'code': None, 'request_sha256': None, 'evidence_sha256': None} + if identifier in ['source', 'digest', 'vectors', 'closed']: + require(index == 0 and operation == 'probe', 'qualification.harness.step') + if identifier == 'source': + source_commit() + require(candidate(family, work) == tuple_value, 'qualification.harness.candidate-changed') + verdict['code'] = 'source-clean' + elif identifier == 'digest': + value = child(gateway(), ['review', '--recipe', work / 'recipe.json', + '--profile-lock', work / 'profile.lock.json']) + require(value['recipe_digest'] == tuple_value['compiled_recipe_sha256'], + 'qualification.harness.recipe-digest') + require(read(work / 'profile.lock.json', 65536) == read(SOURCES[family] / 'profile.lock.json', 65536), + 'qualification.harness.lock-drift') + verdict['code'] = 'recipe-digest-rederived' + elif identifier == 'vectors': + authenticate(family, work, gateway(), tuple_value) + verdict['code'] = 'recipe-vectors-passed' + else: + hostile(work) + verdict['code'] = 'closed-enumeration-refused' + else: + require(identifier in ['oracle-accept', 'oracle-reject'] and index in [0, 1] + and operation == ['oracle', 'review'][index], 'qualification.harness.step') + if identifier == 'oracle-reject': + if operation == 'review': + actual = review(work, packet, carrier['evaluated_at'] - 1) + closed(actual, ['outcome', 'code']) + require(actual['outcome'] == 'denied' and actual['code'] == 'action-outside-validity', + 'qualification.harness.native-time-refusal') + # The source author starts every action at this recorded time. + # One second earlier is outside that closed action interval; + # this is offline evaluation, never a production-clock override. + verdict.update(outcome='refused', code='action-outside-validity') + else: + actual = review(work, packet, carrier['evaluated_at']) + expected = reference.request(packet['arguments'], resources, actual['action_commitment'], + tuple_value['compiled_recipe_sha256']) + if operation == 'review': + require(actual['arguments'] == packet['arguments'], 'qualification.harness.arguments') + outbound = actual['request'] + else: + # Only the authenticated action commitment is taken from + # native review. The oracle constructs every request byte. + outbound = expected + verdict.update(code='request-mapped', request_sha256=sha256(canonical(outbound))) + return {'tuple_sha256': sha256(b'auths.qualification-tuple/1\0' + canonical(tuple_value)), + 'observed': {'verdict': verdict, 'credential_leases': 0, 'provider_entries': 0, + 'confirmed_by_read_back': 0}, 'fresh_evidence': None, + 'unauthorized_provider_entries': 0, 'secret_exposed': False, + 'repository_imported': False, 'provider_token_received': False} + + +def main(family, arguments): + def dispatch(): + require(family in REFERENCES and type(arguments) is list, 'qualification.harness.family') + if len(arguments) == 2 and arguments[0] == 'prepare': + return prepare(family, Path(arguments[1]).absolute()) + if len(arguments) == 2 and arguments[0] == 'cleanup': + # No protected setup has been configured yet. Cleanup can complete + # only for the exact synthetic ledger this offline source prepared; + # it cannot claim retirement of any real resource. + work = Path(arguments[1]).absolute() + resources = decode(read(work / 'resources.json', 65536)) + require(resources == synthetic_resources(family, resources['protected_run']), + 'qualification.harness.real-resources-not-retired') + return + if len(arguments) == 6 and arguments[0] == 'step': + _, case, index, operation, directory, output = arguments + require(case.startswith('offline-'), 'qualification.harness.protected-journey-not-configured') + value = offline(family, case.removeprefix('offline-'), int(index), operation, Path(directory).absolute()) + return write(Path(output).absolute(), value, new=True) + # No helper can silently complete an unimplemented protected step, + # provision development custody, or manufacture a live observation. + require(False, 'qualification.harness.protected-journey-not-configured') + finish(dispatch) diff --git a/qualification/reference/generate_families.py b/qualification/reference/generate_families.py new file mode 100644 index 000000000..8f383467f --- /dev/null +++ b/qualification/reference/generate_families.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python3 +"""Regenerate the reviewed plan/contract artifacts from their exact source. + +These are unqualified source plans. This command issues no record, permit, +evidence, attestation or release index and reads no credential. +""" + +from pathlib import Path +import argparse + +from common import canonical, require, sha256 +import airtable_record +import stripe_platform +from expand import SOURCES, decode, read +from resource_io import finish + +ROOT = Path(__file__).resolve().parents[2] +REFERENCE = ROOT / 'qualification/reference' +SOURCES_TO_PIN = ['family_corpus.py', 'family_harness.py', 'packet_plan.py', + 'author_packets.py', 'author_socket.py', 'common.py', 'fresh_evidence.py', + 'native_observation.py', 'measure.py', 'resource_io.py', 'resource_summary.py', + 'expand.py', 'stripe_platform.py', 'airtable_record.py', 'stripe_resources.py', 'airtable_resources.py'] + + +def generate(check=False): + for reference, adr in [(stripe_platform, '0014-stripe-refund-recipe-qualification.md'), + (airtable_record, '0015-airtable-record-update-recipe-qualification.md')]: + family = ROOT / 'qualification/families' / reference.FAMILY + if not check: family.mkdir(parents=True, exist_ok=True) + plan = {'schema': 'auths.qualification-reviewed-plan/1', 'family': reference.FAMILY, + 'resource_count': 16, 'compiled_corpus_schema': 'auths.qualification-corpus/3', + 'packet_plan_schema': 'auths.qualification-packet-plan/4', + 'public_packet_schema': 'auths.qualification-public-packets/4', + 'phases': ['offline', 'commissioning', 'live'], 'maximum_credential_leases': 64, + 'source_files': {name: sha256(read(REFERENCE / name, 2 * 1024 * 1024)) + for name in SOURCES_TO_PIN}, + 'source_recipe_sha256': sha256(read(SOURCES[reference.FAMILY] / 'recipe.json', 65536)), + 'profile_lock_sha256': sha256(read(SOURCES[reference.FAMILY] / 'profile.lock.json', 65536)), + 'decision_record_sha256': sha256(read(ROOT / 'docs/adr' / adr, 65536))} + recipe = decode(read(SOURCES[reference.FAMILY] / 'recipe.json', 65536)) + stripe = reference is stripe_platform + assumptions = sorted([ + 'The provider is independently operated; availability and concurrent outside writes are not controlled by Auths.', + 'Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.', + 'Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.', + 'Stripe test mode and the installed platform are checked by the declared guard on each lease.' if stripe else + 'The reviewed fixed Airtable base and table contain only owner-authorized disposable qualification records.', + 'Stripe idempotency is tested only inside the declared 86400-second retention interval.' if stripe else + 'Airtable supplies no idempotency key for this PATCH; durable gateway admission prevents a second entry.', + 'The 50-percent payment basis is a read, not an atomic provider balance reservation.' if stripe else + 'Only a fresh GET with the exact replacement and echo can reconcile a lost response.', + ]) + declarations = { + 'idempotency_sha256': sha256(canonical(recipe['write'].get('idempotency'))), + 'observation_sha256': sha256(canonical({'observation': recipe['observation'], 'echo': recipe['echo']})), + 'recovery_sha256': sha256(canonical({'declared': not stripe, + 'locator': 'verified-record' if not stripe else 'recorded-response-only'})), + 'retention_sha256': sha256(canonical({'attestation_days': 30, + 'provider_idempotency_seconds': 86400 if stripe else None, + 'commissioning_seconds': 7200})), + } + contract = {'schema': 'auths.provider-contract/1', 'provider': 'stripe' if stripe else 'airtable', + 'api_release': '2025-03-31.basil' if stripe else 'web-api-v0-reviewed-2026-10-07', + 'manual_assumptions': assumptions, 'environment_class': reference.ENVIRONMENT, + 'corpus_manifest_sha256': sha256(canonical(plan)), + 'oracle_version': 'auths-reviewed-reference-v2', 'declarations': declarations} + reasons = {'observer-rotation': 'The qualified reference configures no signing observer.'} + if stripe: + reasons['recovery'] = 'An unrecorded refund response has no verified response locator; loss remains unknown.' + else: + reasons.update({ + 'credential-guard': 'This recipe declares no provider credential guard.', + 'version-pin': 'Airtable Web API v0 has no immutable response version pin.', + 'account-binding': 'The recipe declares no account-binding probe.', + 'denied-reads': 'The recipe declares no denied credential reads; token scope is an operator assumption.', + 'ceiling': 'The field-update profile carries no numeric amount or relative ceiling.', + 'budget': 'This recipe declares no numeric count/sum budget.', + 'idempotency': 'This PATCH declares no provider idempotency key.', + 'response-locator': 'Observation uses the verified record ID, not a write-response locator.', + }) + record = {'provider_kind': 'stripe' if stripe else 'airtable', 'validity_days': 30, + 'not_applicable': [{'capability': name, 'reason': reason} for name, reason in sorted(reasons.items())], + 'custody_descriptor': 'aws-secrets-manager-v1 with immutable versions and a customer-managed key', + 'store_descriptor': 'postgresql-v1 schema 6 shared by two isolated gateway processes', + 'residual_assumptions': assumptions, + 'excluded_claims': sorted(['Global exactly-once effects across other actors or deployments.', + 'Provider availability, settlement, or indefinite retention.', + 'Connected-account selection or restrictions.' if stripe else + 'Gateway enforcement of the personal access token resource configuration.'])} + outputs = {name: canonical(value) for name, value in [ + ('corpus-manifest.json', plan), ('contract.json', contract), ('record.json', record)]} + decision = ( + '# ' + reference.FAMILY + '\n\nStatus: source plan; no production qualification.\n\n' + 'The provider decision is [ADR](../../../docs/adr/' + adr + '). Its exact digest is in the reviewed plan.\n\n' + 'The source-owned compiler expands the complete closed packet pool into the native three-phase corpus. ' + 'Offline operations execute the installed SDK and shipping native reviewer. Protected operations ' + 'must use PostgreSQL, actual AWS custody, two processes, fresh read-back and measured counters. ' + 'An absent protected implementation refuses and emits no observation.\n\n' + 'The contract hashes this reviewed source plan; the record separately hashes its concrete native ' + 'corpus expansion. This avoids a source/candidate/actor commitment cycle. The signer must ' + 'reconstruct the expansion from its own reviewed source before issuing authority.\n') + harness = ('#!/usr/bin/env python3\nimport sys\nfrom pathlib import Path\n' + "sys.dont_write_bytecode = True\nsys.path.insert(0, str(Path(__file__).resolve().parents[2] / 'reference'))\n" + 'from family_harness import main\nmain(' + repr(reference.FAMILY) + ', sys.argv[1:])\n') + outputs.update({'decision-record.md': decision.encode(), 'harness': harness.encode()}) + for name, value in outputs.items(): + if check: + require(read(family / name, 2 * 1024 * 1024) == value, + 'qualification.harness.reviewed-plan-drift') + else: + (family / name).write_bytes(value) + if not check: (family / 'harness').chmod(0o755) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--check', action='store_true') + args = parser.parse_args() + finish(lambda: generate(args.check)) diff --git a/qualification/reference/tests/test_family_plans.py b/qualification/reference/tests/test_family_plans.py new file mode 100644 index 000000000..5dacd94ea --- /dev/null +++ b/qualification/reference/tests/test_family_plans.py @@ -0,0 +1,50 @@ +"""Source/artifact drift and refusal boundaries, without provider evidence.""" + +import copy +from pathlib import Path +import sys +import unittest +from unittest.mock import patch + +sys.path.insert(0, str(Path(__file__).resolve().parents[1])) +import generate_families +import family_corpus +import family_harness +from common import Refusal, canonical + + +class Plans(unittest.TestCase): + def test_generated_source_plans_are_current_and_any_changed_member_refuses(self): + generate_families.generate(check=True) + original = generate_families.read + for name in ['contract.json', 'record.json', 'corpus-manifest.json', 'harness', 'decision-record.md']: + def altered(path, maximum): + raw = original(path, maximum) + return raw + b' ' if path.name == name else raw + with patch.object(generate_families, 'read', side_effect=altered): + with self.assertRaisesRegex(Refusal, 'reviewed-plan-drift'): + generate_families.generate(check=True) + + def test_complete_plan_requires_the_entire_fixed_resource_pool(self): + for family in family_harness.REFERENCES: + resources = family_harness.synthetic_resources(family, 'recipe-qualification/123/1') + member = 'payments' if 'payments' in resources else 'records' + self.assertEqual(len(resources[member]), 16) + for count in [0, 1, 15, 17]: + changed = copy.deepcopy(resources) + changed[member] = [dict(resources[member][0], id=( + 'pi_SYNTHETIC' + str(index) if member == 'payments' else 'recTEST' + str(index).zfill(10))) + for index in range(count)] + with self.assertRaises(Refusal): + family_corpus.compile_plan(family, changed, {}, '1' * 64) + + def test_a_protected_step_cannot_emit_a_placeholder_observation(self): + with patch.object(family_harness, 'write') as written: + with self.assertRaises(SystemExit): + family_harness.main('stripe-platform-refund-v1', + ['step', 'live-proof-replay', '0', 'submit', '/unconfigured', '/unconfigured-output']) + written.assert_not_called() + + +if __name__ == '__main__': + unittest.main() diff --git a/qualification/run/commission.py b/qualification/run/commission.py index 169e0a5a5..b09c8db8f 100644 --- a/qualification/run/commission.py +++ b/qualification/run/commission.py @@ -38,6 +38,8 @@ def call(arguments): def source_contract(family, inputs, issuer): require(family in expand.REFERENCES, 'qualification.commission.family') + from generate_families import generate + generate(check=True) contract = ROOT / 'qualification/families' / family / 'contract.json' # Hash the reviewed source contract through the native format, never use # an artifact-supplied contract ID as its own expected value. diff --git a/qualification/run/live.sh b/qualification/run/live.sh index 9931caf03..c05bac5ab 100755 --- a/qualification/run/live.sh +++ b/qualification/run/live.sh @@ -18,5 +18,5 @@ tool="${AUTHS_QUALIFICATION:-${root}/target/release/auths-qualification}" rm -f "${work}/${stage}-effects.json" "${work}/cases/"*."${stage}".json "${tool}" run-stage --phase "${stage}" \ - --corpus "${root}/qualification/families/${family}/corpus-manifest.json" \ + --corpus "${work}/corpus.json" \ --harness "${harness}" --tuple "${work}/tuple.json" --work-dir "${work}" diff --git a/qualification/run/offline.sh b/qualification/run/offline.sh index 80be28ed8..d8976514e 100755 --- a/qualification/run/offline.sh +++ b/qualification/run/offline.sh @@ -45,19 +45,28 @@ done "$("${AUTHS_QUALIFICATION}" contract-id --contract "${directory}/contract.json")" ] \ || { echo "qualification.contract-changed" >&2; exit 1; } "${AUTHS_QUALIFICATION}" run-stage --phase offline \ - --corpus "${directory}/corpus-manifest.json" --harness "${directory}/harness" \ + --corpus "${work}/corpus.json" --harness "${directory}/harness" \ --tuple "${work}/tuple.json" --work-dir "${work}" "${AUTHS_QUALIFICATION}" stage-trust --tuple "${work}/tuple.json" \ --out "${work}/cases/rotation.trust.json" +# The finite permit consumes actual canonical offline evidence, not a case +# list or an arbitrary report's passing flag. +mkdir -p "${work}/offline" +for member in conformance differential; do + "${AUTHS_QUALIFICATION}" evidence --member "${member}" \ + --tuple "${work}/tuple.json" --commit "$(git -C "${root}" rev-parse HEAD)" \ + --cases "${work}/cases/${member}.offline.json" --out "${work}/offline/${member}.json" +done + digest() { shasum -a 256 "$1" | cut -d' ' -f1; } jq -n \ --arg commit "$(git -C "${root}" rev-parse HEAD)" \ --arg source_closure "$(git -C "${root}" ls-tree -r HEAD | shasum -a 256 | cut -d' ' -f1)" \ --arg generated "$(cat "${AUTHS_GATEWAY}" "${AUTHS_QUALIFICATION}" | shasum -a 256 | cut -d' ' -f1)" \ --arg decision "$(digest "${directory}/decision-record.md")" \ - --arg corpus "$(digest "${directory}/corpus-manifest.json")" \ + --arg corpus "$(digest "${work}/corpus.json")" \ '{commit: $commit, source_closure_sha256: $source_closure, generated_artifacts_sha256: $generated, recipe_decision_record_sha256: $decision, corpus_manifest_sha256: $corpus}' \ From 92f59c3ecf1941fc0eaea366cf202a2890dd768f Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 15:26:21 +0100 Subject: [PATCH 085/108] Preserve the installed consumer virtualenv launcher --- .../airtable-record-update-v1/contract.json | 2 +- .../airtable-record-update-v1/corpus-manifest.json | 2 +- .../stripe-platform-refund-v1/contract.json | 2 +- .../stripe-platform-refund-v1/corpus-manifest.json | 2 +- qualification/reference/family_harness.py | 11 ++++++++++- qualification/reference/tests/test_family_plans.py | 14 ++++++++++++++ 6 files changed, 28 insertions(+), 5 deletions(-) diff --git a/qualification/families/airtable-record-update-v1/contract.json b/qualification/families/airtable-record-update-v1/contract.json index f202bd24d..cfc991494 100644 --- a/qualification/families/airtable-record-update-v1/contract.json +++ b/qualification/families/airtable-record-update-v1/contract.json @@ -1 +1 @@ -{"api_release":"web-api-v0-reviewed-2026-10-07","corpus_manifest_sha256":"884b1afbc343dd9d68a65018d6d7edd848b672891b951345d1bde5c8c234458f","declarations":{"idempotency_sha256":"74234e98afe7498fb5daf1f36ac2d78acc339464f950703b8c019892f982b90b","observation_sha256":"9dd79dd204fa13a2df3c667d106c66c0526d174a2c018631e2b2f6b897eaf311","recovery_sha256":"7081a92b4cd2d13dab5e7c30e640675a252b62bca20d340e14d62d9c8c048eca","retention_sha256":"4a4b5048c97b16e041af55b032c0b8ac20f5142c4bbcbf31b31c6674770a70d0"},"environment_class":"disposable-live-resources","manual_assumptions":["Airtable supplies no idempotency key for this PATCH; durable gateway admission prevents a second entry.","Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only a fresh GET with the exact replacement and echo can reconcile a lost response.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths.","The reviewed fixed Airtable base and table contain only owner-authorized disposable qualification records."],"oracle_version":"auths-reviewed-reference-v2","provider":"airtable","schema":"auths.provider-contract/1"} \ No newline at end of file +{"api_release":"web-api-v0-reviewed-2026-10-07","corpus_manifest_sha256":"06bf7c4f84f4a7ee0097ec106069f11c758ab105bdc3363d690907b02aa67969","declarations":{"idempotency_sha256":"74234e98afe7498fb5daf1f36ac2d78acc339464f950703b8c019892f982b90b","observation_sha256":"9dd79dd204fa13a2df3c667d106c66c0526d174a2c018631e2b2f6b897eaf311","recovery_sha256":"7081a92b4cd2d13dab5e7c30e640675a252b62bca20d340e14d62d9c8c048eca","retention_sha256":"4a4b5048c97b16e041af55b032c0b8ac20f5142c4bbcbf31b31c6674770a70d0"},"environment_class":"disposable-live-resources","manual_assumptions":["Airtable supplies no idempotency key for this PATCH; durable gateway admission prevents a second entry.","Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only a fresh GET with the exact replacement and echo can reconcile a lost response.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths.","The reviewed fixed Airtable base and table contain only owner-authorized disposable qualification records."],"oracle_version":"auths-reviewed-reference-v2","provider":"airtable","schema":"auths.provider-contract/1"} \ No newline at end of file diff --git a/qualification/families/airtable-record-update-v1/corpus-manifest.json b/qualification/families/airtable-record-update-v1/corpus-manifest.json index ecc2b3a30..61b2251a0 100644 --- a/qualification/families/airtable-record-update-v1/corpus-manifest.json +++ b/qualification/families/airtable-record-update-v1/corpus-manifest.json @@ -1 +1 @@ -{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"32241d9b4811a55abcdd224ef567df3857dbec34d761ef7a35d1044cdfa52d9f","family":"airtable-record-update-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"af7f984509ab11a3676cacc85eda2fa638c25bf91f7bfedf3ff3c119e47f3c41","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"e58dc84b60f5ff13e5c7b1b5aae4917c5427f31cc8ac041acdd85defc8cd5e92","family_harness.py":"de6945b6fb3c3b1feaa1dbfa8b68b9e433bcdef0f0e98a2006ab4485427742f2","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"4896a5f16474cbb418decb719bcc2af4a08483eabeca996427b40560a16d02cf","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","resource_io.py":"025139a787f50f5181e390ea58da45db00dbdef15c8b3928cba9e0485945f6fe","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489"},"source_recipe_sha256":"c0f21ff1d3c8e344fee20a9a0c25bb14a264417ed53418ad536789a6096fb16e"} \ No newline at end of file +{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"32241d9b4811a55abcdd224ef567df3857dbec34d761ef7a35d1044cdfa52d9f","family":"airtable-record-update-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"af7f984509ab11a3676cacc85eda2fa638c25bf91f7bfedf3ff3c119e47f3c41","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"e58dc84b60f5ff13e5c7b1b5aae4917c5427f31cc8ac041acdd85defc8cd5e92","family_harness.py":"909d65dbe8fe7b4fe6e739701b30782cd94f511fb8c517a3c14452cf208d7c5b","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"4896a5f16474cbb418decb719bcc2af4a08483eabeca996427b40560a16d02cf","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","resource_io.py":"025139a787f50f5181e390ea58da45db00dbdef15c8b3928cba9e0485945f6fe","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489"},"source_recipe_sha256":"c0f21ff1d3c8e344fee20a9a0c25bb14a264417ed53418ad536789a6096fb16e"} \ No newline at end of file diff --git a/qualification/families/stripe-platform-refund-v1/contract.json b/qualification/families/stripe-platform-refund-v1/contract.json index fe13e7090..5db1f1623 100644 --- a/qualification/families/stripe-platform-refund-v1/contract.json +++ b/qualification/families/stripe-platform-refund-v1/contract.json @@ -1 +1 @@ -{"api_release":"2025-03-31.basil","corpus_manifest_sha256":"1cce0b50bf5d59e70470bb3fe0fb3fe072c36a219f0e384972d0e1f7e7f466be","declarations":{"idempotency_sha256":"425a0dca2f279765debfc847c4a01bff60fea5be68dd9d761ae6bb60ce0b8a7b","observation_sha256":"d0ce5a34d987821c69c0a839d9ed66805c625f8324dd42031fcccf0752a8821e","recovery_sha256":"bf2303abce165c175360ac975586431bbc4cf03167489ea317a27de2f0b04abb","retention_sha256":"846c2164e26d1144d9aa146034b4f7ea4dc305136a59ffd94f999d19f2c360ee"},"environment_class":"provider-test-mode","manual_assumptions":["Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","Stripe idempotency is tested only inside the declared 86400-second retention interval.","Stripe test mode and the installed platform are checked by the declared guard on each lease.","The 50-percent payment basis is a read, not an atomic provider balance reservation.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths."],"oracle_version":"auths-reviewed-reference-v2","provider":"stripe","schema":"auths.provider-contract/1"} \ No newline at end of file +{"api_release":"2025-03-31.basil","corpus_manifest_sha256":"b2ab90f6e401fcc10fc414c51879d66e35974c8c962c73f73e67c640fdc82b02","declarations":{"idempotency_sha256":"425a0dca2f279765debfc847c4a01bff60fea5be68dd9d761ae6bb60ce0b8a7b","observation_sha256":"d0ce5a34d987821c69c0a839d9ed66805c625f8324dd42031fcccf0752a8821e","recovery_sha256":"bf2303abce165c175360ac975586431bbc4cf03167489ea317a27de2f0b04abb","retention_sha256":"846c2164e26d1144d9aa146034b4f7ea4dc305136a59ffd94f999d19f2c360ee"},"environment_class":"provider-test-mode","manual_assumptions":["Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","Stripe idempotency is tested only inside the declared 86400-second retention interval.","Stripe test mode and the installed platform are checked by the declared guard on each lease.","The 50-percent payment basis is a read, not an atomic provider balance reservation.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths."],"oracle_version":"auths-reviewed-reference-v2","provider":"stripe","schema":"auths.provider-contract/1"} \ No newline at end of file diff --git a/qualification/families/stripe-platform-refund-v1/corpus-manifest.json b/qualification/families/stripe-platform-refund-v1/corpus-manifest.json index 37c3c50a1..5b324834b 100644 --- a/qualification/families/stripe-platform-refund-v1/corpus-manifest.json +++ b/qualification/families/stripe-platform-refund-v1/corpus-manifest.json @@ -1 +1 @@ -{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"a72c557b69103a52eb477deb8364ded53cd58407b9ba7ab33ccbda74389fec1e","family":"stripe-platform-refund-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"99901e36cb7c4f5882897603c874698d582e859b5d6b08d53cd80975e89aa01c","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"e58dc84b60f5ff13e5c7b1b5aae4917c5427f31cc8ac041acdd85defc8cd5e92","family_harness.py":"de6945b6fb3c3b1feaa1dbfa8b68b9e433bcdef0f0e98a2006ab4485427742f2","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"4896a5f16474cbb418decb719bcc2af4a08483eabeca996427b40560a16d02cf","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","resource_io.py":"025139a787f50f5181e390ea58da45db00dbdef15c8b3928cba9e0485945f6fe","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489"},"source_recipe_sha256":"b1972d556f28433932a449636755077f7ee485ef90cca412f153bc7f18881368"} \ No newline at end of file +{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"a72c557b69103a52eb477deb8364ded53cd58407b9ba7ab33ccbda74389fec1e","family":"stripe-platform-refund-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"99901e36cb7c4f5882897603c874698d582e859b5d6b08d53cd80975e89aa01c","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"e58dc84b60f5ff13e5c7b1b5aae4917c5427f31cc8ac041acdd85defc8cd5e92","family_harness.py":"909d65dbe8fe7b4fe6e739701b30782cd94f511fb8c517a3c14452cf208d7c5b","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"4896a5f16474cbb418decb719bcc2af4a08483eabeca996427b40560a16d02cf","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","resource_io.py":"025139a787f50f5181e390ea58da45db00dbdef15c8b3928cba9e0485945f6fe","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489"},"source_recipe_sha256":"b1972d556f28433932a449636755077f7ee485ef90cca412f153bc7f18881368"} \ No newline at end of file diff --git a/qualification/reference/family_harness.py b/qualification/reference/family_harness.py index 230b2fda0..c6556800e 100644 --- a/qualification/reference/family_harness.py +++ b/qualification/reference/family_harness.py @@ -34,6 +34,15 @@ def gateway(): return Path(os.environ['AUTHS_GATEWAY']).resolve(strict=True) +def consumer_python(): + # Resolving a venv launcher symlink selects the base interpreter and loses + # its installed wheel. Keep the absolute launcher path when executing it. + python = Path(os.environ['AUTHS_QUALIFICATION_CONSUMER_PYTHON']).absolute() + require(python.is_file() and os.access(python, os.X_OK), + 'qualification.harness.consumer-python') + return python + + def source_commit(): revision = command(['/usr/bin/git', 'rev-parse', 'HEAD']) status = command(['/usr/bin/git', 'status', '--porcelain']) @@ -80,7 +89,7 @@ def prepare(family, work): 'gateway': gateway(), 'work': work})()) # The wheel and public author kit are installed/copied by the credential- # free workflow. The SDK process never receives this checkout or its env. - python = Path(os.environ['AUTHS_QUALIFICATION_CONSUMER_PYTHON']).resolve(strict=True) + python = consumer_python() kit = Path(os.environ['AUTHS_QUALIFICATION_AUTHOR_KIT']).resolve(strict=True) result = command([python, '-B', kit / 'author_packets.py', '--plan', work / 'packet-plan.json', '--work', work], cwd=work) diff --git a/qualification/reference/tests/test_family_plans.py b/qualification/reference/tests/test_family_plans.py index 5dacd94ea..4c180591e 100644 --- a/qualification/reference/tests/test_family_plans.py +++ b/qualification/reference/tests/test_family_plans.py @@ -1,8 +1,11 @@ """Source/artifact drift and refusal boundaries, without provider evidence.""" import copy +import os from pathlib import Path +import subprocess import sys +import tempfile import unittest from unittest.mock import patch @@ -14,6 +17,17 @@ class Plans(unittest.TestCase): + def test_consumer_executes_the_venv_launcher_with_its_installed_prefix(self): + with tempfile.TemporaryDirectory() as directory: + environment = Path(directory) / 'consumer' + subprocess.run([sys.executable, '-m', 'venv', '--without-pip', environment], check=True) + launcher = environment / ('Scripts/python.exe' if os.name == 'nt' else 'bin/python') + with patch.dict(os.environ, {'AUTHS_QUALIFICATION_CONSUMER_PYTHON': str(launcher)}): + result = family_harness.command([family_harness.consumer_python(), '-c', + 'import sys; print(sys.prefix)']) + self.assertEqual(result.returncode, 0) + self.assertEqual(Path(result.stdout.decode().strip()).resolve(), environment.resolve()) + def test_generated_source_plans_are_current_and_any_changed_member_refuses(self): generate_families.generate(check=True) original = generate_families.read From ecef94de127a9d122a38f8c6b37d23d23280b6f1 Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 15:34:29 +0100 Subject: [PATCH 086/108] Author production operator statements with the isolated installed SDK --- .../airtable-record-update-v1/contract.json | 2 +- .../corpus-manifest.json | 2 +- .../stripe-platform-refund-v1/contract.json | 2 +- .../corpus-manifest.json | 2 +- qualification/reference/README.md | 9 ++ qualification/reference/author_operator.py | 95 +++++++++++++++++++ qualification/reference/family_harness.py | 7 ++ qualification/reference/generate_families.py | 2 +- .../reference/tests/test_operator_author.py | 52 ++++++++++ 9 files changed, 168 insertions(+), 5 deletions(-) create mode 100644 qualification/reference/author_operator.py create mode 100644 qualification/reference/tests/test_operator_author.py diff --git a/qualification/families/airtable-record-update-v1/contract.json b/qualification/families/airtable-record-update-v1/contract.json index cfc991494..bab07c010 100644 --- a/qualification/families/airtable-record-update-v1/contract.json +++ b/qualification/families/airtable-record-update-v1/contract.json @@ -1 +1 @@ -{"api_release":"web-api-v0-reviewed-2026-10-07","corpus_manifest_sha256":"06bf7c4f84f4a7ee0097ec106069f11c758ab105bdc3363d690907b02aa67969","declarations":{"idempotency_sha256":"74234e98afe7498fb5daf1f36ac2d78acc339464f950703b8c019892f982b90b","observation_sha256":"9dd79dd204fa13a2df3c667d106c66c0526d174a2c018631e2b2f6b897eaf311","recovery_sha256":"7081a92b4cd2d13dab5e7c30e640675a252b62bca20d340e14d62d9c8c048eca","retention_sha256":"4a4b5048c97b16e041af55b032c0b8ac20f5142c4bbcbf31b31c6674770a70d0"},"environment_class":"disposable-live-resources","manual_assumptions":["Airtable supplies no idempotency key for this PATCH; durable gateway admission prevents a second entry.","Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only a fresh GET with the exact replacement and echo can reconcile a lost response.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths.","The reviewed fixed Airtable base and table contain only owner-authorized disposable qualification records."],"oracle_version":"auths-reviewed-reference-v2","provider":"airtable","schema":"auths.provider-contract/1"} \ No newline at end of file +{"api_release":"web-api-v0-reviewed-2026-10-07","corpus_manifest_sha256":"afe21d0fe8ab6acd3da2a9c03e5b193b7013e8e1cbf922ab0716a22ea65eaff2","declarations":{"idempotency_sha256":"74234e98afe7498fb5daf1f36ac2d78acc339464f950703b8c019892f982b90b","observation_sha256":"9dd79dd204fa13a2df3c667d106c66c0526d174a2c018631e2b2f6b897eaf311","recovery_sha256":"7081a92b4cd2d13dab5e7c30e640675a252b62bca20d340e14d62d9c8c048eca","retention_sha256":"4a4b5048c97b16e041af55b032c0b8ac20f5142c4bbcbf31b31c6674770a70d0"},"environment_class":"disposable-live-resources","manual_assumptions":["Airtable supplies no idempotency key for this PATCH; durable gateway admission prevents a second entry.","Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only a fresh GET with the exact replacement and echo can reconcile a lost response.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths.","The reviewed fixed Airtable base and table contain only owner-authorized disposable qualification records."],"oracle_version":"auths-reviewed-reference-v2","provider":"airtable","schema":"auths.provider-contract/1"} \ No newline at end of file diff --git a/qualification/families/airtable-record-update-v1/corpus-manifest.json b/qualification/families/airtable-record-update-v1/corpus-manifest.json index 61b2251a0..e2298c6d3 100644 --- a/qualification/families/airtable-record-update-v1/corpus-manifest.json +++ b/qualification/families/airtable-record-update-v1/corpus-manifest.json @@ -1 +1 @@ -{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"32241d9b4811a55abcdd224ef567df3857dbec34d761ef7a35d1044cdfa52d9f","family":"airtable-record-update-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"af7f984509ab11a3676cacc85eda2fa638c25bf91f7bfedf3ff3c119e47f3c41","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"e58dc84b60f5ff13e5c7b1b5aae4917c5427f31cc8ac041acdd85defc8cd5e92","family_harness.py":"909d65dbe8fe7b4fe6e739701b30782cd94f511fb8c517a3c14452cf208d7c5b","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"4896a5f16474cbb418decb719bcc2af4a08483eabeca996427b40560a16d02cf","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","resource_io.py":"025139a787f50f5181e390ea58da45db00dbdef15c8b3928cba9e0485945f6fe","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489"},"source_recipe_sha256":"c0f21ff1d3c8e344fee20a9a0c25bb14a264417ed53418ad536789a6096fb16e"} \ No newline at end of file +{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"32241d9b4811a55abcdd224ef567df3857dbec34d761ef7a35d1044cdfa52d9f","family":"airtable-record-update-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"af7f984509ab11a3676cacc85eda2fa638c25bf91f7bfedf3ff3c119e47f3c41","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"e58dc84b60f5ff13e5c7b1b5aae4917c5427f31cc8ac041acdd85defc8cd5e92","family_harness.py":"bd8474b88f5e7f8869c0470bfa4e09ba159c3e9d8b3a4ea2f2404938d8980d6f","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"4896a5f16474cbb418decb719bcc2af4a08483eabeca996427b40560a16d02cf","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","resource_io.py":"025139a787f50f5181e390ea58da45db00dbdef15c8b3928cba9e0485945f6fe","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489"},"source_recipe_sha256":"c0f21ff1d3c8e344fee20a9a0c25bb14a264417ed53418ad536789a6096fb16e"} \ No newline at end of file diff --git a/qualification/families/stripe-platform-refund-v1/contract.json b/qualification/families/stripe-platform-refund-v1/contract.json index 5db1f1623..b93732b40 100644 --- a/qualification/families/stripe-platform-refund-v1/contract.json +++ b/qualification/families/stripe-platform-refund-v1/contract.json @@ -1 +1 @@ -{"api_release":"2025-03-31.basil","corpus_manifest_sha256":"b2ab90f6e401fcc10fc414c51879d66e35974c8c962c73f73e67c640fdc82b02","declarations":{"idempotency_sha256":"425a0dca2f279765debfc847c4a01bff60fea5be68dd9d761ae6bb60ce0b8a7b","observation_sha256":"d0ce5a34d987821c69c0a839d9ed66805c625f8324dd42031fcccf0752a8821e","recovery_sha256":"bf2303abce165c175360ac975586431bbc4cf03167489ea317a27de2f0b04abb","retention_sha256":"846c2164e26d1144d9aa146034b4f7ea4dc305136a59ffd94f999d19f2c360ee"},"environment_class":"provider-test-mode","manual_assumptions":["Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","Stripe idempotency is tested only inside the declared 86400-second retention interval.","Stripe test mode and the installed platform are checked by the declared guard on each lease.","The 50-percent payment basis is a read, not an atomic provider balance reservation.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths."],"oracle_version":"auths-reviewed-reference-v2","provider":"stripe","schema":"auths.provider-contract/1"} \ No newline at end of file +{"api_release":"2025-03-31.basil","corpus_manifest_sha256":"0c323df2b3a790243fe347e019a093547002842605441f2b07168363d18fcb66","declarations":{"idempotency_sha256":"425a0dca2f279765debfc847c4a01bff60fea5be68dd9d761ae6bb60ce0b8a7b","observation_sha256":"d0ce5a34d987821c69c0a839d9ed66805c625f8324dd42031fcccf0752a8821e","recovery_sha256":"bf2303abce165c175360ac975586431bbc4cf03167489ea317a27de2f0b04abb","retention_sha256":"846c2164e26d1144d9aa146034b4f7ea4dc305136a59ffd94f999d19f2c360ee"},"environment_class":"provider-test-mode","manual_assumptions":["Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","Stripe idempotency is tested only inside the declared 86400-second retention interval.","Stripe test mode and the installed platform are checked by the declared guard on each lease.","The 50-percent payment basis is a read, not an atomic provider balance reservation.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths."],"oracle_version":"auths-reviewed-reference-v2","provider":"stripe","schema":"auths.provider-contract/1"} \ No newline at end of file diff --git a/qualification/families/stripe-platform-refund-v1/corpus-manifest.json b/qualification/families/stripe-platform-refund-v1/corpus-manifest.json index 5b324834b..038257e8c 100644 --- a/qualification/families/stripe-platform-refund-v1/corpus-manifest.json +++ b/qualification/families/stripe-platform-refund-v1/corpus-manifest.json @@ -1 +1 @@ -{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"a72c557b69103a52eb477deb8364ded53cd58407b9ba7ab33ccbda74389fec1e","family":"stripe-platform-refund-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"99901e36cb7c4f5882897603c874698d582e859b5d6b08d53cd80975e89aa01c","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"e58dc84b60f5ff13e5c7b1b5aae4917c5427f31cc8ac041acdd85defc8cd5e92","family_harness.py":"909d65dbe8fe7b4fe6e739701b30782cd94f511fb8c517a3c14452cf208d7c5b","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"4896a5f16474cbb418decb719bcc2af4a08483eabeca996427b40560a16d02cf","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","resource_io.py":"025139a787f50f5181e390ea58da45db00dbdef15c8b3928cba9e0485945f6fe","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489"},"source_recipe_sha256":"b1972d556f28433932a449636755077f7ee485ef90cca412f153bc7f18881368"} \ No newline at end of file +{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"a72c557b69103a52eb477deb8364ded53cd58407b9ba7ab33ccbda74389fec1e","family":"stripe-platform-refund-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"99901e36cb7c4f5882897603c874698d582e859b5d6b08d53cd80975e89aa01c","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"e58dc84b60f5ff13e5c7b1b5aae4917c5427f31cc8ac041acdd85defc8cd5e92","family_harness.py":"bd8474b88f5e7f8869c0470bfa4e09ba159c3e9d8b3a4ea2f2404938d8980d6f","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"4896a5f16474cbb418decb719bcc2af4a08483eabeca996427b40560a16d02cf","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","resource_io.py":"025139a787f50f5181e390ea58da45db00dbdef15c8b3928cba9e0485945f6fe","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489"},"source_recipe_sha256":"b1972d556f28433932a449636755077f7ee485ef90cca412f153bc7f18881368"} \ No newline at end of file diff --git a/qualification/reference/README.md b/qualification/reference/README.md index 5fd3b8e15..fb8d8b0ed 100644 --- a/qualification/reference/README.md +++ b/qualification/reference/README.md @@ -248,3 +248,12 @@ deadline. Only the GitHub Actions token enters the GitHub client; provider and signer keys are absent from that child's environment. The native issuer/gateway must still verify every permit/record: a transported artifact grants no authority. The protected workflow has not yet connected this mailbox to admitted corpora. + +`author_operator.py` runs in the same credential-free installed environment as +packet authoring, in a separate process with a fresh operator key. It rechecks +the native recipe digest, lock and both exact contexts, reconstructs each +operator-request preimage, signs it with the SDK, and verifies the signature +with the native SDK verifier. The offline family job produces these actual +installation statements and checks that their operator differs from every +packet actor. This proves technical separation by key; production install +verification and human review are not claimed by its report. diff --git a/qualification/reference/author_operator.py b/qualification/reference/author_operator.py new file mode 100644 index 000000000..3e8455344 --- /dev/null +++ b/qualification/reference/author_operator.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python3 +"""Sign installation statements with a separate installed-SDK operator key. + +The credential-free process keeps its key in memory, signs only the source +installation's two contexts, and exports no key or qualification authority. +This establishes technical separation by key, never a human release review. +""" + +import argparse +import base64 +from pathlib import Path +import time + +from author_packets import installed_native +from common import canonical, closed, require, sha256 +from expand import child, decode, read +from resource_io import finish, write + +SCHEMA = 'auths.gateway-operator-attestation/1' +ALIAS = 'recipe-qualification' + + +def checked_statement(request, key, installation): + closed(request, ['statement', 'preimage_b64']) + statement = request['statement'] + closed(statement, ['schema', 'operator_principal', 'principal_method', + 'verification_method', 'signature_suite', 'installation', 'issued_at']) + now = int(time.time()) + require(statement['schema'] == SCHEMA + and statement['operator_principal'] == key.principal + and statement['principal_method'] == key.principal_method + and statement['verification_method'] == key.verification_method + and statement['signature_suite'] == key.suite + and statement['installation'] == installation + and type(statement['issued_at']) is int + and now - 60 <= statement['issued_at'] <= now, + 'qualification.operator.statement-binding') + preimage = SCHEMA.encode() + b'\0' + canonical(statement) + require(request['preimage_b64'] == base64.urlsafe_b64encode(preimage).rstrip(b'=').decode(), + 'qualification.operator.preimage-binding') + return statement, preimage + + +def author(gateway, work): + native, version = installed_native() + key = native.DevelopmentEd25519Key.generate() + tuple_value = decode(read(work / 'tuple.json', 65536)) + carrier = decode(read(work / 'public-packets.json', 65536)) + require(carrier['trusted_contexts'] == ['context-0.cbor', 'context-1.cbor'], + 'qualification.operator.context-binding') + family = tuple_value['recipe_family'] + require(family in ['stripe-platform-refund-v1', 'airtable-record-update-v1'], + 'qualification.operator.family') + provider = 'stripe' if family == 'stripe-platform-refund-v1' else 'airtable' + review = child(gateway, ['review', '--recipe', work / 'recipe.json', + '--profile-lock', work / 'profile.lock.json']) + require(review['recipe_digest'] == tuple_value['compiled_recipe_sha256'], + 'qualification.operator.recipe-binding') + for context in carrier['trusted_contexts']: + installation = {'recipe_digest': tuple_value['compiled_recipe_sha256'], + 'profile_lock_sha256': sha256(read(work / 'profile.lock.json', 65536)), + 'trusted_context_sha256': sha256(read(work / context, 4 * 1024 * 1024)), + 'provider': provider, 'alias': ALIAS, 'deployment': 'production'} + require(installation['profile_lock_sha256'] == tuple_value['profile_lock_sha256'], + 'qualification.operator.lock-binding') + request = child(gateway, ['operator-request', '--recipe', work / 'recipe.json', + '--profile-lock', work / 'profile.lock.json', '--trusted-context', work / context, + '--provider', provider, '--alias', ALIAS, '--deployment', 'production', + '--operator-principal', key.principal, '--principal-method', key.principal_method, + '--verification-method', key.verification_method, '--signature-suite', key.suite]) + statement, preimage = checked_statement(request, key, installation) + signature = bytes(key.sign(preimage)) + native.verify_ed25519_preimage_v1(bytes(key.public_key), preimage, signature) + write(work / (context + '.operator.json'), {'statement': statement, + 'signature_b64': base64.urlsafe_b64encode(signature).rstrip(b'=').decode(), + 'evidence': [{'evidence_type': key.evidence_type, 'media_type': key.media_type, + 'bytes_b64': base64.urlsafe_b64encode(bytes(key.evidence)).rstrip(b'=').decode()}]}, new=True) + write(work / 'operator-report.json', {'schema': 'auths.qualification-operator-author/1', + 'sdk_version': version, 'operator_principal': key.principal, + 'contexts': carrier['trusted_contexts'], 'private_key_exported': False, + 'provider_token_received': False, 'repository_imported': False, + 'human_review_claimed': False, 'production_install_verified': False, + 'qualification_issued': False}, new=True) + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--gateway', type=lambda value: Path(value).absolute(), required=True) + parser.add_argument('--work', type=lambda value: Path(value).absolute(), required=True) + args = parser.parse_args() + finish(lambda: author(args.gateway, args.work)) + + +if __name__ == '__main__': + main() diff --git a/qualification/reference/family_harness.py b/qualification/reference/family_harness.py index c6556800e..5aca9a3cb 100644 --- a/qualification/reference/family_harness.py +++ b/qualification/reference/family_harness.py @@ -95,7 +95,14 @@ def prepare(family, work): '--work', work], cwd=work) require(result.returncode == 0, 'qualification.harness.installed-author') tuple_value = candidate(family, work) + write(work / 'tuple.json', tuple_value, new=True) + operator = command([python, '-B', kit / 'author_operator.py', + '--gateway', gateway(), '--work', work], cwd=work) + require(operator.returncode == 0, 'qualification.harness.installed-operator') resources, reviewed = authenticate(family, work, gateway(), tuple_value) + operator_report = decode(read(work / 'operator-report.json', 65536)) + require(all(operator_report['operator_principal'] not in value['actors'] + for value in reviewed.values()), 'qualification.harness.operator-separation') corpus = compile_plan(family, resources, reviewed, tuple_value['compiled_recipe_sha256']) write_bytes(work / 'corpus.json', canonical(corpus), new=True) author = decode(read(work / 'author-report.json', 65536)) diff --git a/qualification/reference/generate_families.py b/qualification/reference/generate_families.py index 8f383467f..df1afa325 100644 --- a/qualification/reference/generate_families.py +++ b/qualification/reference/generate_families.py @@ -17,7 +17,7 @@ ROOT = Path(__file__).resolve().parents[2] REFERENCE = ROOT / 'qualification/reference' SOURCES_TO_PIN = ['family_corpus.py', 'family_harness.py', 'packet_plan.py', - 'author_packets.py', 'author_socket.py', 'common.py', 'fresh_evidence.py', + 'author_packets.py', 'author_socket.py', 'author_operator.py', 'common.py', 'fresh_evidence.py', 'native_observation.py', 'measure.py', 'resource_io.py', 'resource_summary.py', 'expand.py', 'stripe_platform.py', 'airtable_record.py', 'stripe_resources.py', 'airtable_resources.py'] diff --git a/qualification/reference/tests/test_operator_author.py b/qualification/reference/tests/test_operator_author.py new file mode 100644 index 000000000..e656ad853 --- /dev/null +++ b/qualification/reference/tests/test_operator_author.py @@ -0,0 +1,52 @@ +"""Installation binding checks; no provider access or qualification issued.""" + +import base64 +import copy +from pathlib import Path +import sys +import time +from types import SimpleNamespace +import unittest + +sys.path.insert(0, str(Path(__file__).resolve().parents[1])) +from author_operator import checked_statement, SCHEMA +from common import canonical, Refusal + + +class Operator(unittest.TestCase): + def setUp(self): + self.key = SimpleNamespace(principal='raw:synthetic-only-operator', + principal_method='raw-key-v1', verification_method='synthetic-only-method', suite='ed25519-v1') + self.installation = {'recipe_digest': '1' * 64, 'profile_lock_sha256': '2' * 64, + 'trusted_context_sha256': '3' * 64, 'provider': 'stripe', + 'alias': 'recipe-qualification', 'deployment': 'production'} + self.statement = {'schema': SCHEMA, 'operator_principal': self.key.principal, + 'principal_method': self.key.principal_method, 'verification_method': self.key.verification_method, + 'signature_suite': self.key.suite, 'installation': self.installation, 'issued_at': int(time.time())} + + def request(self, statement): + return {'statement': statement, 'preimage_b64': base64.urlsafe_b64encode( + SCHEMA.encode() + b'\0' + canonical(statement)).rstrip(b'=').decode()} + + def test_every_installation_field_is_bound_even_when_preimage_is_consistent(self): + checked_statement(self.request(self.statement), self.key, self.installation) + for field in self.installation: + statement = copy.deepcopy(self.statement) + statement['installation'][field] = 'changed' + with self.subTest(field=field), self.assertRaisesRegex(Refusal, 'statement-binding'): + checked_statement(self.request(statement), self.key, self.installation) + + def test_unknown_fields_other_keys_stale_time_and_preimage_substitution_refuse(self): + for change in ['unknown', 'principal', 'future', 'stale', 'preimage']: + request = self.request(copy.deepcopy(self.statement)) + if change == 'unknown': request['statement']['authority'] = 'unreviewed' + if change == 'principal': request['statement']['operator_principal'] = 'raw:other' + if change == 'future': request['statement']['issued_at'] += 300 + if change == 'stale': request['statement']['issued_at'] -= 300 + if change == 'preimage': request['preimage_b64'] = 'c3Vic3RpdHV0ZWQ' + with self.subTest(change=change), self.assertRaises(Refusal): + checked_statement(request, self.key, self.installation) + + +if __name__ == '__main__': + unittest.main() From a9d7d4bef02b0fbbd425a03b42212c1843b84f75 Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 15:45:50 +0100 Subject: [PATCH 087/108] Separate production installation custody identities and prepare isolated hosts --- .github/workflows/gateway-custody-live.yml | 8 +- deployment/gateway/operator.conf.example | 3 +- ...gateway-polish-and-recipe-qualification.md | 19 ++ .../tests/protected_run.rs | 18 ++ .../auths-gateway/semantic-closure.json | 2 +- .../auths-gateway/src/bin/auths-gateway.rs | 24 +-- .../auths-gateway/src/semantic_closure.rs | 2 +- .../airtable-record-update-v1/contract.json | 2 +- .../corpus-manifest.json | 2 +- .../stripe-platform-refund-v1/contract.json | 2 +- .../corpus-manifest.json | 2 +- qualification/reference/README.md | 10 + qualification/reference/generate_families.py | 2 +- qualification/reference/production_setup.py | 199 ++++++++++++++++++ .../reference/tests/test_production_setup.py | 66 ++++++ 15 files changed, 333 insertions(+), 28 deletions(-) create mode 100644 qualification/reference/production_setup.py create mode 100644 qualification/reference/tests/test_production_setup.py diff --git a/.github/workflows/gateway-custody-live.yml b/.github/workflows/gateway-custody-live.yml index af3c8fb9d..13a1a0367 100644 --- a/.github/workflows/gateway-custody-live.yml +++ b/.github/workflows/gateway-custody-live.yml @@ -22,6 +22,7 @@ concurrency: jobs: store-contract: + if: github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main' runs-on: ubuntu-latest timeout-minutes: 20 environment: gateway-custody-live @@ -89,6 +90,7 @@ jobs: run: rm -f "${RUNNER_TEMP}/custody-identity-token" gateway-journey: + if: github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main' # A real gateway whose provider secret lives in the production store: # the north-star refund journey, hostile cases included, with the key # installed into Secrets Manager and leased from it for every write. @@ -121,12 +123,14 @@ jobs: working-directory: examples/stripe-refund-approval env: AWS_ROLE_ARN: arn:aws:iam::585985124542:role/auths-gateway-custody-gateway + AUTHS_GATEWAY_RUNTIME_ROLE_ARN: arn:aws:iam::585985124542:role/auths-gateway-custody-runtime NAMESPACE: journey-${{ github.run_id }}-${{ github.run_attempt }} KMS_KEY: arn:aws:kms:eu-west-1:585985124542:key/1e1c85ae-7d9c-4f2d-978f-bd672b597907 run: | set -euo pipefail umask 077 export AWS_WEB_IDENTITY_TOKEN_FILE="${RUNNER_TEMP}/journey-identity-token" + export AUTHS_GATEWAY_RUNTIME_TOKEN_FILE="${AWS_WEB_IDENTITY_TOKEN_FILE}" refresh() { curl --fail-with-body --silent --show-error \ -H "Authorization: bearer ${ACTIONS_ID_TOKEN_REQUEST_TOKEN}" \ @@ -156,6 +160,7 @@ jobs: retention-days: 30 provider-journey: + if: github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main' # The same journey against a live provider: Stripe test mode. The gateway # is the default build, with no loopback option, and its restricted test # key lives in Secrets Manager. The run makes one 15.00 test refund and @@ -198,6 +203,7 @@ jobs: env: STRIPE_TEST_RESTRICTED_KEY: ${{ secrets.STRIPE_TEST_KEY }} AWS_ROLE_ARN: arn:aws:iam::585985124542:role/auths-gateway-custody-gateway + AUTHS_GATEWAY_RUNTIME_ROLE_ARN: arn:aws:iam::585985124542:role/auths-gateway-custody-runtime NAMESPACE: provider-${{ github.run_id }}-${{ github.run_attempt }} KMS_KEY: arn:aws:kms:eu-west-1:585985124542:key/1e1c85ae-7d9c-4f2d-978f-bd672b597907 STRIPE_ACCOUNT: acct_1QekbYID70YvJ7mY @@ -207,6 +213,7 @@ jobs: set -euo pipefail umask 077 export AWS_WEB_IDENTITY_TOKEN_FILE="${RUNNER_TEMP}/provider-identity-token" + export AUTHS_GATEWAY_RUNTIME_TOKEN_FILE="${AWS_WEB_IDENTITY_TOKEN_FILE}" refresh() { curl --fail-with-body --silent --show-error \ -H "Authorization: bearer ${ACTIONS_ID_TOKEN_REQUEST_TOKEN}" \ @@ -241,4 +248,3 @@ jobs: path: target/journey-artifacts/provider-journey-summary.json if-no-files-found: warn retention-days: 30 - diff --git a/deployment/gateway/operator.conf.example b/deployment/gateway/operator.conf.example index 8c6561e27..1f0a55f44 100644 --- a/deployment/gateway/operator.conf.example +++ b/deployment/gateway/operator.conf.example @@ -4,6 +4,7 @@ AUTHS_POSTGRES_CA_PEM=/etc/auths/postgres-ca.pem AUTHS_POSTGRES_SERVER_NAME=postgres.internal AWS_ROLE_ARN=arn:aws:iam::ACCOUNT:role/auths-operator AWS_WEB_IDENTITY_TOKEN_FILE=/run/auths-identity/operator/token -# Read confirmation during rotation uses the separately provisioned runtime identity. +# Installation, join and rotation read confirmation use the separately +# provisioned runtime identity; the operator role needs no secret-read grant. AUTHS_GATEWAY_RUNTIME_ROLE_ARN=arn:aws:iam::ACCOUNT:role/auths-runtime AUTHS_GATEWAY_RUNTIME_TOKEN_FILE=/run/auths-identity/runtime/token diff --git a/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md b/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md index cb3a6b684..8da40f660 100644 --- a/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md +++ b/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md @@ -1851,3 +1851,22 @@ their conformance/differential reports, and the issuer constructs canonical offline evidence. Verification of this new collection is pending. Protected operations currently refuse without their production journey implementation; the source plan is not evidence that those operations ran. Epic 5 remains open. + +#### 22.8 Production operator installation boundary + +The installed SDK now authors both exact-context operator statements using a +separate process and key, reconstructs the native signing preimage, verifies +the signatures and checks key separation from all packet actors. These are +technical operator statements; they assert no human review or qualification. + +Native installation now selects administrative AWS custody just as rotation +does: the restricted operator identity writes, while the distinct runtime +identity reads the stored commitment for a join. Neither IAM role is broadened. +The existing custody workflow supplies the reader identity and admits live +identity only for manual runs on main. The semantic closure is regenerated +with the native fixture generator after this source change. + +The private production controller binds the shipping executable, prepares two +hosts for each trusted context, requires PostgreSQL/TLS and AWS custody, and +compares all four installed tuples with the planned tuple. Complete protected +provider orchestration and hosted verification are still pending. diff --git a/product/qualification/auths-recipe-qualification-issuance/tests/protected_run.rs b/product/qualification/auths-recipe-qualification-issuance/tests/protected_run.rs index c26b3da63..bba502351 100644 --- a/product/qualification/auths-recipe-qualification-issuance/tests/protected_run.rs +++ b/product/qualification/auths-recipe-qualification-issuance/tests/protected_run.rs @@ -46,6 +46,24 @@ fn jobs(text: &str) -> BTreeMap> { jobs } +#[test] +fn shared_custody_jobs_cannot_run_pull_request_source_with_live_identity() { + let text = + std::fs::read_to_string(repository().join(".github/workflows/gateway-custody-live.yml")) + .expect("custody workflow"); + let jobs = jobs(&text); + assert_eq!( + jobs.keys().map(String::as_str).collect::>(), + ["gateway-journey", "provider-journey", "store-contract"] + ); + for (name, lines) in jobs { + assert!( + lines.iter().any(|line| line == PROTECTED), + "{name} obtains a live identity only from reviewed main source" + ); + } +} + #[test] fn a_pull_request_reaches_no_secret_and_no_signing_job() { let text = std::fs::read_to_string(repository().join(WORKFLOW)).expect("workflow"); diff --git a/product/runtime/auths-gateway/semantic-closure.json b/product/runtime/auths-gateway/semantic-closure.json index b76e8d3aa..5b0e63b68 100644 --- a/product/runtime/auths-gateway/semantic-closure.json +++ b/product/runtime/auths-gateway/semantic-closure.json @@ -1 +1 @@ -{"files":[{"path":"Cargo.lock","sha256":"0e75e2fdef44e79e57797ac6661295ae58ddb8de4a1990a6fd22ce6c54f78604"},{"path":"Cargo.toml","sha256":"6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24"},{"path":"core/adapters/auths-did-keri/Cargo.toml","sha256":"86ba3e3f9a0a70d970568bfb3113b7ba7bbdd81c3eebbb52743dd574a0c0ecaa"},{"path":"core/adapters/auths-did-keri/src/lib.rs","sha256":"a75674842f8a7142004369ccd206ab43e476459293f0ff4bed4d4e659031b3e3"},{"path":"core/adapters/auths-did-key/Cargo.toml","sha256":"d5a3ae07ecde83f91eed4c3785051dd0f44eab6c891754f3309b6b40596707d7"},{"path":"core/adapters/auths-did-key/src/lib.rs","sha256":"b76a3f4528a725df53cfa9242e6e414e1d26caa48468aaed497e28b121f4497c"},{"path":"core/adapters/auths-raw-key/Cargo.toml","sha256":"f49616bc18c19e6aaa7e6a02ccebcdb9f5c1422c1278ef9869e0dbf22ceda7be"},{"path":"core/adapters/auths-raw-key/src/lib.rs","sha256":"45eec1b295dac3bed65cd79c942870b926b06b3f5d38eaebaeb6140ac69315fa"},{"path":"core/crates/auths-algebra-kernel/Cargo.toml","sha256":"0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba"},{"path":"core/crates/auths-algebra-kernel/src/generated.rs","sha256":"ae4bcbef42a408c7ffa0c6a74a42f7de177a6f14479e51d205acf830bda05960"},{"path":"core/crates/auths-algebra-kernel/src/lib.rs","sha256":"6654667eeb9b353d6648954c9fd2e8838462a82ce6b2803eb49e1366892c68c6"},{"path":"core/crates/auths-assurance/Cargo.toml","sha256":"afcb12a97ddd09d7a264b9ecd3fcaefc865ff2c9b4539ee85b00883420ba333a"},{"path":"core/crates/auths-assurance/src/lib.rs","sha256":"0fb2ec844d674b25a9e20b1601452c89c2454901fa506adfa9bb38ef9a7fa213"},{"path":"core/crates/auths-author/Cargo.toml","sha256":"1e6f0e3bc079ddb558decf0db26b291c6e72fc47327b6df1b7650d41689b215f"},{"path":"core/crates/auths-author/src/lib.rs","sha256":"e14475f2f49715a1869d5fa6b11ff1fbb72497e39097e09f833b0bae7e5b3f2b"},{"path":"core/crates/auths-author/src/observations.rs","sha256":"dda7d6bfa6f4bd7e95a480ca283c2c0e996f69c5c15cb0c7197af328131a7066"},{"path":"core/crates/auths-authority/Cargo.toml","sha256":"4f68212938029f79ebd857b4f3038494eb85d0163d49f07e51376715cf959815"},{"path":"core/crates/auths-authority/src/lib.rs","sha256":"da88d5194de4e17449e69972c0fb042afa3c39798a8f570f30771e77c384f1eb"},{"path":"core/crates/auths-codec/Cargo.toml","sha256":"e20e51826e17814effd9d8925d18d5fbdd6c0d37bf50231e743ec2611314722c"},{"path":"core/crates/auths-codec/src/approval.rs","sha256":"fbff43bf4d57f69f8b7738a8647751cde75c5a932dee65d924a1fe9c7202f91f"},{"path":"core/crates/auths-codec/src/bounded_policy.rs","sha256":"d21f6728be2d8a04b6d94921f2b683f7e61cbb42e0ac6866f1c88a49caa534c3"},{"path":"core/crates/auths-codec/src/decode.rs","sha256":"ba2999584cdf53b1b517ecb9c7ea50d39efee17c666a9a38e2ad1ac94379f778"},{"path":"core/crates/auths-codec/src/encode.rs","sha256":"8491192053e2e15d62b4d2a491de22405b7487ead69ab6f6bca40669ce7ca5f7"},{"path":"core/crates/auths-codec/src/error.rs","sha256":"fecb0737c16deb42d859f1dc7727c698438d9ac12064fd99e0024629642c390c"},{"path":"core/crates/auths-codec/src/hash.rs","sha256":"f88e111f1dbb2cef6b7b5e9c948cb45ff92e366710c8a5f5c636138aa748479e"},{"path":"core/crates/auths-codec/src/lib.rs","sha256":"3b0e5c94c6f34f750b88a9333e1d5c8145746d845d3a23e0d2f61807cf592ea7"},{"path":"core/crates/auths-codec/src/observation.rs","sha256":"38328b0c71ff97a4196eeade8b4faa889527ff1f80bb168468bcd49082a3987e"},{"path":"core/crates/auths-composition/Cargo.toml","sha256":"331e13025eb82588b5269ed3975929eb41c823d588c49e4c296273d85c6fe80e"},{"path":"core/crates/auths-composition/src/lib.rs","sha256":"e42e3b0b6a9985b73c533aeb23799c638979aa27a9ce7d0f10a8d60340570fb1"},{"path":"core/crates/auths-model/Cargo.toml","sha256":"565c15302b0cc9270db1e28efa3862804846850ba933cc17aea8abcec4a65987"},{"path":"core/crates/auths-model/src/approval.rs","sha256":"54cf44a9ef747ec21546a4086aecfb130bc7803b0d646430e6082df51e6e305f"},{"path":"core/crates/auths-model/src/bounded.rs","sha256":"f90496abc0a06c028b4d850af6ddab7d850bfafeaa3d042f1b1246a41d8bbbc9"},{"path":"core/crates/auths-model/src/bounded_policy.rs","sha256":"306a8f049cc7cfc7635fe0e4de47eb7813eed63d3c14c3be2b51586aa4eea450"},{"path":"core/crates/auths-model/src/lib.rs","sha256":"e7cfe6bb9574c6b016aa63e70658c31e0b90903ec6479a49f4a2ceb64f5bad97"},{"path":"core/crates/auths-model/src/observation.rs","sha256":"b3ed3e3cc090afca2896a7d3de7988afccc1ee1ea0ebd91b51a8bc0f20ad8dbb"},{"path":"core/crates/auths-multikey/Cargo.toml","sha256":"858756c1197befcada06134742bffe8d58cf674cadd6c046bf710570e96efaf2"},{"path":"core/crates/auths-multikey/src/lib.rs","sha256":"f5177fffb11e40eeaaa665ba886c541fc1f24d5eacdd6983fb03dc20148733f0"},{"path":"core/crates/auths-ports/Cargo.toml","sha256":"596a9b0f5af3717c16a6d13f7054d8a106bcd9f01f5f72c2235dd2afcf0ab16c"},{"path":"core/crates/auths-ports/src/binding.rs","sha256":"a16c012d40aa4249e3ec54372b9611006d0bfe8c7dc3c741911c2194ad17736d"},{"path":"core/crates/auths-ports/src/diagnostics.rs","sha256":"aa596572503b5a65a918bb2ff38281c144ff53821ee914e9325c852828d852df"},{"path":"core/crates/auths-ports/src/lib.rs","sha256":"8da1debf86f9532df0660155d04298beb1ba3a1204508f8586e2e67cd2fb3449"},{"path":"core/crates/auths-ports/src/path.rs","sha256":"b68fc547b4e4d97a60cbbc1cc1939fc6b34a8233b81f840bd396914a707e3ea1"},{"path":"core/crates/auths-raw-key-core/Cargo.toml","sha256":"98c0bc8527a537512e43a74dd6ba9658c6f0cdc16610cf938e3f9b43785d836d"},{"path":"core/crates/auths-raw-key-core/src/lib.rs","sha256":"98c0500c41697aae28708ad0bf970b9a97583d96a3d2c18d23e7fa351e0f7d12"},{"path":"core/crates/auths-registries/Cargo.toml","sha256":"590e49e58b0622d9d6274fea46796dcdb07dec9550eff295cce6a6427ffa51e2"},{"path":"core/crates/auths-registries/src/lib.rs","sha256":"450d3886d85ee333b7e046317fb5b47cde62483d5f3e41d46265e2caf4c373ec"},{"path":"core/crates/auths-registries/src/template.rs","sha256":"1224039dd2b3ce6fa8357613d8cafbae40400493da7176da202b9ade62fa05e4"},{"path":"core/crates/auths-signature-core/Cargo.toml","sha256":"6bee2230eb30af1be0bd5c2d57bd3e1903497a70028d47290d4ac6e9e0e8bca0"},{"path":"core/crates/auths-signature-core/src/lib.rs","sha256":"6e3f9311ded5e49ea50d445eb21e6d8fa12442aa4362a73e0cb6fda15b7cd865"},{"path":"core/crates/auths-signature/Cargo.toml","sha256":"7f7b5682466ba439d8c59579022cb61068cad9fb4bd2d73e1cc21327c902b450"},{"path":"core/crates/auths-signature/src/lib.rs","sha256":"b3d9ac4cc3ba0797b9e1c09f2d6ac05089b25dac4e285a5af28c0165b33d925b"},{"path":"core/crates/auths-verifier/Cargo.toml","sha256":"c43358e06a33324b41a8b93e5cc7279c55f7d21f1f6cfaa539a3fc7b4c27a38f"},{"path":"core/crates/auths-verifier/src/approval.rs","sha256":"c3cae6a49e169051eb555bb092b1069a4d422516d6a2114623a89e5f31ff923f"},{"path":"core/crates/auths-verifier/src/causal.rs","sha256":"9635230f33b13a263573d319ac8a1976addbcc07677514a43e3c7bf28dc04587"},{"path":"core/crates/auths-verifier/src/lib.rs","sha256":"f22dec38dfa47ced8da4f605390da8453273bee1da010f57fd1fdfcb10e0b389"},{"path":"core/crates/auths-verifier/src/observation.rs","sha256":"0bb07f06a0f9524c88427df1c972b1de8ba038a9eeeb15d3134c25125ae84b1e"},{"path":"core/crates/auths-verifier/src/trace.rs","sha256":"2213d72023a1d9e0413a2cf2c51c3dad9e04775d86033a0caaa9d29a8f0036f8"},{"path":"exchange/crates/auths-proof-exchange-model/Cargo.toml","sha256":"34b2db64f93a288e942b5a3918d28cdcbef906e0dc9074ce848018d3d5f7a1fa"},{"path":"exchange/crates/auths-proof-exchange-model/src/lib.rs","sha256":"49fac5aff2339d3a57c41cb8bb2a82852538e8f77ecc4b157c88e264ff31fb55"},{"path":"exchange/crates/auths-proof-exchange-port/Cargo.toml","sha256":"7ff660f1b7579dc570c791090aeb450404fbbf44c92781e289f5ccdde746d739"},{"path":"exchange/crates/auths-proof-exchange-port/src/lib.rs","sha256":"b408fb40c6432edc1facb3d8b3e9433a033f8dc73fe2e0ba5a88c972ca675021"},{"path":"product/config/auths-config/Cargo.toml","sha256":"e4b568ab9f6d84f7d7e6d66443fe825f360db9c27bc7c31d6ddc0647ba3ab304"},{"path":"product/config/auths-config/src/lib.rs","sha256":"fecf00ea65cef9018fda9af2063326d7065b869266d0d9e73a4f06816f1102cc"},{"path":"product/errors/auths-errors/Cargo.toml","sha256":"3b3a199b6460ba75bda84475bb5accd35e1485448a3981038db85bf4772dd350"},{"path":"product/errors/auths-errors/src/lib.rs","sha256":"7feeb9069fa4003f94f1f07c1c94619cf1c883e0dbaaf2187f04d0f742264bdd"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/Cargo.toml","sha256":"716f1f2a117d6d69d8effe9ee9057e24ba3502f20af6a602b06facb638cdabed"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/api.rs","sha256":"9ea61dd7ddd93282b073b98e453e6b75b26dc49689c04e9782435d06a3a09e48"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/clock.rs","sha256":"73f0a6e0f5903883329fa6683f5888288f759512ac69e5c87efd2b6b87f7d79f"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/http.rs","sha256":"14c1fce14e24c984b2a275563a29b6326fb08367922b6e8d37ba38b9cb81aa2b"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/identity.rs","sha256":"186de11230c8b33375951c4368609f8976bf9795f171af3fd7fac26207a94361"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs","sha256":"0b4617d044f5254a5ab22f5a2578f91cc025206a8c1845be39c1c56dcdf7a5df"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/names.rs","sha256":"41bb23572d6002e23ee103d6fe70ecd68764861c6f2e48a1c53af998270a4afa"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs","sha256":"39fed883f4802e68d3b41a68fea0aba0737810996b33d13577de70faba004c29"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/store.rs","sha256":"fc60ee9c49b2f4f063c449b4c78100c5c4872779e94ca168f796603b380ef6e4"},{"path":"product/integrations/auths-custody/Cargo.toml","sha256":"1e14034185ad1ec24a977fd5f41d0abee219606245c046ce2a82287fadef448b"},{"path":"product/integrations/auths-custody/src/conformance.rs","sha256":"8ed1afd58f18fc6becc268908aa6419c9aa404c79da0197963eb2599df44acf6"},{"path":"product/integrations/auths-custody/src/key.rs","sha256":"70cbb0fd21b6f5652157845a22c35be2d0f6c05b3d138fc4b9bb6dbdc3d81c40"},{"path":"product/integrations/auths-custody/src/lib.rs","sha256":"8ee593c1f59b0fd2126bdda9138026f5bc531beb64d4489a99785842e7b98b43"},{"path":"product/operations/auths-operations/Cargo.toml","sha256":"73dde1e914ba5e1386f8d49c0d730423cc72ae77ec44c6554a6a75cc8e8922b1"},{"path":"product/operations/auths-operations/src/explanation.rs","sha256":"b4a39bcbd5712cb9e735ee7deeb281f3fa6af5ddca973735bf3d87dce427ef11"},{"path":"product/operations/auths-operations/src/lib.rs","sha256":"3f401a56555113b98f57bca172a2660eaecedf76247b83a3fdbb089c133a29cd"},{"path":"product/operations/auths-operations/src/render/json.rs","sha256":"2ae042639960afee123730e945d373bc5dda1d2b3af20ae16c939a7e99b9e418"},{"path":"product/operations/auths-operations/src/render/mod.rs","sha256":"b3b7f6fe473f49227ace5a68bfc3d8dc14b5db8dd9888fd9e207070337b1b8bf"},{"path":"product/operations/auths-operations/src/render/text.rs","sha256":"f216cf3bdb00e264523271b16e7059535ac6b1aabf271cebd7935af155e4bfec"},{"path":"product/policy/auths-bounded-policy/Cargo.toml","sha256":"babd5d200923137ead71d8c2528f847cea323ce98da942a1320b054436612c47"},{"path":"product/policy/auths-bounded-policy/src/arithmetic.rs","sha256":"75e43c5d4eab8d1f71c1daf53839f5f9fe45a400afc1f63a30c6f55ce3632627"},{"path":"product/policy/auths-bounded-policy/src/commitment.rs","sha256":"c5706f2d583454e1a7f570f7ada138d4d864bef0205dfae7c1296774f396bb3f"},{"path":"product/policy/auths-bounded-policy/src/eligibility.rs","sha256":"c9acdfb793074e687fc36efad506be27dbd99ffbf40387bc66c8de39ef238432"},{"path":"product/policy/auths-bounded-policy/src/identifier.rs","sha256":"0006a32bae9eb16c4178cf797df418d2b0a781f2bc6474b741dc1a908141831c"},{"path":"product/policy/auths-bounded-policy/src/kernel.rs","sha256":"99187c28b161ac70bee1afed60711f7f645adb4d1671a01863f9849b369811d5"},{"path":"product/policy/auths-bounded-policy/src/lib.rs","sha256":"76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c"},{"path":"product/policy/auths-bounded-policy/src/receipt.rs","sha256":"3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad"},{"path":"product/policy/auths-bounded-policy/src/registry.rs","sha256":"4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0"},{"path":"product/profiles/auths-profile-api/Cargo.toml","sha256":"7ae85761f58625b5d678f961fd052eebf3e000ef565c7312e3ac857763c0017f"},{"path":"product/profiles/auths-profile-api/src/lib.rs","sha256":"a194b82b20bf8aa864c2334ef6c6aec30b2154ded972862252d5dcefa488ab95"},{"path":"product/profiles/auths-profile-mcp/Cargo.toml","sha256":"db264fc25242f7b7e4133cbe5782545b3107b406c87168ae072683cfb59eac66"},{"path":"product/profiles/auths-profile-mcp/src/arguments.rs","sha256":"a5de696586d507e2aee4a49fee99ef1ef4c51a2e46603f8838f1af6d9009833f"},{"path":"product/profiles/auths-profile-mcp/src/lib.rs","sha256":"d0f8b733a09ef8408336cdebc8948d6a5861012ce6878598b11be7084dfd4280"},{"path":"product/profiles/auths-profile-mcp/src/session.rs","sha256":"166c281fa66333388e4760d6098dad02d3359e1d5de4b8f93312c014f97abb03"},{"path":"product/qualification/auths-recipe-qualification/Cargo.toml","sha256":"b7b15b30b9a3d96d4f089d514266d3a892de6608d30707aa44be31cca89ca9fe"},{"path":"product/qualification/auths-recipe-qualification/src/canonical.rs","sha256":"30a9b50777f0dcb4b606abfee2467d5a975d9f6ad941ab6c13ca3df5b359f667"},{"path":"product/qualification/auths-recipe-qualification/src/closure.rs","sha256":"0ad6aee9bd981e2863fa725f209ec84031db2ff12f4c7ac3aaf5120f0bb86039"},{"path":"product/qualification/auths-recipe-qualification/src/commissioning.rs","sha256":"db135c55e4e3079a73253ebae275536523eb36b545d1c152b4d7dce3c6b76828"},{"path":"product/qualification/auths-recipe-qualification/src/commissioning/tests.rs","sha256":"4dde3736d206099b1bea4c14e0092c6c1287d1af9065958777d7c54331dd8686"},{"path":"product/qualification/auths-recipe-qualification/src/error.rs","sha256":"52d5cf720a1e4579008fdda90a3ac2c31f0b8db57985f121f65e54b4da2b7dd1"},{"path":"product/qualification/auths-recipe-qualification/src/evidence.rs","sha256":"ba45a7409d67a8af26ab811af306412014557477a101ab2a8eb0faf8f2bd4b91"},{"path":"product/qualification/auths-recipe-qualification/src/ids.rs","sha256":"e81a906d571497ab2da753e1532d4443706410e0b75fdd59a7d2d788c7aec403"},{"path":"product/qualification/auths-recipe-qualification/src/launch.rs","sha256":"41f2e2de90e1e7d6440a66eda3eb9bea8d5e0741bc232305a76a363ab5f813c1"},{"path":"product/qualification/auths-recipe-qualification/src/lib.rs","sha256":"0e24b0f81191df0d078c7f4d73ced784ba9472372bfcdff3c7d0e2fb1687b323"},{"path":"product/qualification/auths-recipe-qualification/src/model.rs","sha256":"3484eb0ec287b23d4682ade7b1b0f8d1335985b3fb180f06fc28716076957d5f"},{"path":"product/qualification/auths-recipe-qualification/src/release.rs","sha256":"ec478e53f70052e566aac7e15be2f9e1b1cd46837ac6990ae955fa864d311586"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/mod.rs","sha256":"fa23a962fd90331152eed5edbcdf271955f7aed79b8da1e065bfe69a20b487a9"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/schemas.rs","sha256":"c59feec2805621f341a90f81fc005e2c12f7a70f9d264fdeacccb2be4fe1c046"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/verification.rs","sha256":"bdf5746fed4d10a7f577f7878619a917d29aa8b7d522f00d9f774e53eff4c8c1"},{"path":"product/qualification/auths-recipe-qualification/src/verify.rs","sha256":"2ec2784435d11e07295de77b2ee1b2c48b2fcf9609a00454c6e7374b621aed5c"},{"path":"product/receipts/auths-receipts/Cargo.toml","sha256":"6001fa1375899953aafcb07c23a6da0c8f57ea7ec08bb9c950b12a60a8cc6f0f"},{"path":"product/receipts/auths-receipts/src/disclosure.rs","sha256":"ba9ed439be0a320c8a01f5b6e9b51361c1a37e076947490d8e4a484ba6bb119c"},{"path":"product/receipts/auths-receipts/src/lib.rs","sha256":"547a57c4160256719cafb7d0ab972d9fc80b0da14fbbce4148c70c414070ff36"},{"path":"product/runtime/auths-connections/Cargo.toml","sha256":"babeb6e1dda3dfb66291713ce1e43dce5c349833d0b50ea4dccbf986030026b2"},{"path":"product/runtime/auths-connections/src/credential.rs","sha256":"82921413bb053f0f6c7931fbd4e6a86c8cc1d8c6b51debd9c2cef33a8d5b1c51"},{"path":"product/runtime/auths-connections/src/kernel.rs","sha256":"a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8"},{"path":"product/runtime/auths-connections/src/lib.rs","sha256":"79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22"},{"path":"product/runtime/auths-connections/src/model.rs","sha256":"de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77"},{"path":"product/runtime/auths-connections/src/registry.rs","sha256":"e57640e003e72ad3235c567c2bb944a262bd64e673f023b62ea091094cc7e946"},{"path":"product/runtime/auths-gateway-kernel/Cargo.toml","sha256":"34f864e67656af4ac7e5c7a347a23f01fc8ab31365b8e23c0ef474483b14a183"},{"path":"product/runtime/auths-gateway-kernel/src/construct.rs","sha256":"e9d65744bae273d65face4285e5d2da75c06a92ab48f7b8333d496604e31c63c"},{"path":"product/runtime/auths-gateway-kernel/src/lib.rs","sha256":"cfda6f8453426564c085475f183b6f790b438768a19668f1b65d33ba59dc8632"},{"path":"product/runtime/auths-gateway-kernel/src/order.rs","sha256":"e0045f877c4b7fe3860c291039853885064ddcdebba7c9b345ab65e81e646dda"},{"path":"product/runtime/auths-gateway-kernel/src/outcome.rs","sha256":"e9785b1afe70788c89b51b18655bcd5acff7b0c8e3d12fb79c6f05a202e67e6b"},{"path":"product/runtime/auths-gateway-kernel/src/ratio.rs","sha256":"7ace22264812e6fc1ef3a62afee402cf43494bb71ae0d3de219ad1b39d690bcb"},{"path":"product/runtime/auths-gateway-kernel/src/recovery.rs","sha256":"9f46dcd1685ab6e4d1ba04a3fc286a9f3afee8fb47829be1fbc670a7926a2dc6"},{"path":"product/runtime/auths-gateway-kernel/src/transition.rs","sha256":"cefb8f01d915880f6921f2501ff881ad94b9de61072c34d9cd19220992f97374"},{"path":"product/runtime/auths-gateway/Cargo.toml","sha256":"00b28be86921dcdc0ad90cce0c62c2961cafefe96ea6c2edf0e926c3d405ccad"},{"path":"product/runtime/auths-gateway/src/admin.rs","sha256":"0dee40a9fb67c5de10142fc37a7bbabdd8979fb0199fb26caf4bdb024e0a5a40"},{"path":"product/runtime/auths-gateway/src/app.rs","sha256":"6f80f63833ea0815bb44fbf3b0cc54624a08e9fb578b035819f2980dc04e8256"},{"path":"product/runtime/auths-gateway/src/audit.rs","sha256":"0edb2037eb7b5d6f13acfce85c54f62a82bf7fdd31bc7e626c4fec183cef61dd"},{"path":"product/runtime/auths-gateway/src/audit_tests.rs","sha256":"990969384a52d75bc2489d9d412a9e7dd814bca1c8f65c701d6205fae62a15d5"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway-harness.rs","sha256":"12b0c24d36b2e6a3be392d3c081a783b355fdd67dc5b54bacc0410e803116b8c"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway.rs","sha256":"b06a4c94bb349237b1941e7e2bc760bf779323fb4c1a2910e05a559ab638ec85"},{"path":"product/runtime/auths-gateway/src/binding.rs","sha256":"663b0ce878319511aa7d05722ab4ab2fa9be18817884ffb2ee9f131ff1e382d1"},{"path":"product/runtime/auths-gateway/src/bounds.rs","sha256":"38251ad6f22f9d07ef9a219c79fa265ca36f1526eca5f147d7efa46b52ad609d"},{"path":"product/runtime/auths-gateway/src/bounds_aggregate_tests.rs","sha256":"ab34f227b7c8692ba1da88ccb32bb3687a66adf8353d8282fae905d4a88eb612"},{"path":"product/runtime/auths-gateway/src/bounds_tests.rs","sha256":"74136bc570da7b9338b5a1a1ed9d3fd892c55135160964f9d3ac0e2cf5741375"},{"path":"product/runtime/auths-gateway/src/commissioning_budget.rs","sha256":"fab29da3269438cc62330f3eab7b5bd4dc482b4db8af243aae47df5d3aa1deb8"},{"path":"product/runtime/auths-gateway/src/commissioning_budget/tests.rs","sha256":"da104a1643c37515deec6397bca6db2054f2c9158ec3d230a1b1ec9c7d0f659f"},{"path":"product/runtime/auths-gateway/src/commissioning_floor.rs","sha256":"7fa6991c5ccd5ae1403be84b3da390323fab09f36e15ac01fd7a38ea350c6fdb"},{"path":"product/runtime/auths-gateway/src/commissioning_floor/tests.rs","sha256":"6b663d6e556adc0b455b81845bc4394d82c6c4de0c5f43e1310f3ddc6e4e40f7"},{"path":"product/runtime/auths-gateway/src/commissioning_session.rs","sha256":"24b48d5eaeaaa3c620e2dfc7ee1f9255fc4519a1eb404b8608cea7af6a910ee2"},{"path":"product/runtime/auths-gateway/src/commissioning_session/tests.rs","sha256":"37a097fc8a9261d3fffdaef3f905f40b22e3e6601bb5101fadd9414f963c0824"},{"path":"product/runtime/auths-gateway/src/connection.rs","sha256":"7b5d049c258a26ed1c93ecf860f51d051a8a65f9b93554af0b1ea93862398ec9"},{"path":"product/runtime/auths-gateway/src/credential_journal.rs","sha256":"7297fccaee5cd8622928e8e0a42bba50da7941970a6f682ecd300c41ee6509da"},{"path":"product/runtime/auths-gateway/src/echo_verify.rs","sha256":"6d453051665f823abd7354d5c50031d9524cf47d6092d2f09080ae814e3b9575"},{"path":"product/runtime/auths-gateway/src/engine.rs","sha256":"1abff20b98bc894c45bfc5c4414c81a99966d1ec95d924a5b0cd6f4c5626ca24"},{"path":"product/runtime/auths-gateway/src/execution_witness.rs","sha256":"e8b1a8e41d5e3fa309760067849d390ef065feeb46701a83391832645a2f000c"},{"path":"product/runtime/auths-gateway/src/fuzzing.rs","sha256":"ed3b0028487eb546a3b0a91d115aa8f18bcea324b61620bfe8e35a9e6ab18758"},{"path":"product/runtime/auths-gateway/src/generation_floor.rs","sha256":"fe1510ec96ce0f67e9a78edbfa94b33eb7df64c0ac4d0a67901124dcd0164777"},{"path":"product/runtime/auths-gateway/src/harness.rs","sha256":"c87e479f3eb281960f6c9c80d43c7560d7ccb654b0154ec823d3fcec4884ac05"},{"path":"product/runtime/auths-gateway/src/lib.rs","sha256":"fad95d031f88072dd024c78facf0bb0267562b1ac743ddd7219fce47e64024f0"},{"path":"product/runtime/auths-gateway/src/listener.rs","sha256":"aa08239bcbc1fcb55e8a212fbdf6a84f12985b0d436dcb51dc58b06e59e435f2"},{"path":"product/runtime/auths-gateway/src/observed_tests.rs","sha256":"a22be071695f89ca2578a4d82fd80d9cb82289213c9bdb8f0470f6b2dc3d9201"},{"path":"product/runtime/auths-gateway/src/observer.rs","sha256":"562ffcaea071c3856e0708dc2fe33516917e145d2438aabb75af0a2b6ba01046"},{"path":"product/runtime/auths-gateway/src/onboarding.rs","sha256":"0dfd7d67e7f02f18a28d1c86ca1b7751d7463f5efcdbe3825de0ad8cbccb3891"},{"path":"product/runtime/auths-gateway/src/operator.rs","sha256":"c3c36954a3e86723df035b47f43b85fc8ab3a6292983522b6258d5c6b4e6c4e4"},{"path":"product/runtime/auths-gateway/src/pending_vectors/attempts.rs","sha256":"47ef3c8cb1c5504d47ae9a0088705ce6715fe86bac1671a34a56fb38a64d0dd3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/bounds.rs","sha256":"e612217307e1da5b0eb5ee6582a7458bb064b8aa8a529fc6555b1b334127ab68"},{"path":"product/runtime/auths-gateway/src/pending_vectors/codes.rs","sha256":"e00670a5ef24eb856cc2c6dcda8e5a263842f55c76bb939c0c27bd9df37e5522"},{"path":"product/runtime/auths-gateway/src/pending_vectors/keys.rs","sha256":"f84c56f2ea9cb34b2b79c72d13fbf2c6585010ec1ed450af58a78c80c1ea1edd"},{"path":"product/runtime/auths-gateway/src/pending_vectors/mod.rs","sha256":"5de8340f0ef71a0b57a09e323fefe473d3160c6ae952b9ba46f714825fbacafc"},{"path":"product/runtime/auths-gateway/src/pending_vectors/outcomes.rs","sha256":"8ec07b9511b48913af36ac999d2aa0e82924289f6acb23ddaeb9f00f99815166"},{"path":"product/runtime/auths-gateway/src/pending_vectors/production.rs","sha256":"772d032e0a0d9c924fb6d6c188528db85a97e71c9e466ddc19eee277baf83614"},{"path":"product/runtime/auths-gateway/src/pending_vectors/recipes.rs","sha256":"51693208270231c25c3aef2a32151d5962114c71e86b88cb9df83181c7af83d9"},{"path":"product/runtime/auths-gateway/src/pre_entry.rs","sha256":"06ea78ca140468bfaba17d9ab04912ad68673954c3203c98fed28272ff2a00c0"},{"path":"product/runtime/auths-gateway/src/property_tests.rs","sha256":"939c081e2e154aaf10186754044bdd65608932c899b970a04a71d0afaa999a93"},{"path":"product/runtime/auths-gateway/src/qualification.rs","sha256":"c597c83de2b94f0374ae54e40a8b57c2a64ec6e254704dca32185f448a908aca"},{"path":"product/runtime/auths-gateway/src/qualification_simulation.rs","sha256":"4ee7cadfb5f46a92713c80f3e55f499cb074d04d8b21ea89d57762af38642bfa"},{"path":"product/runtime/auths-gateway/src/qualification_tests.rs","sha256":"a9178a2e58eea459d5e5dafc53a3999ea7c84dbbffefe6e5eb1f3d098827f028"},{"path":"product/runtime/auths-gateway/src/quorum_tests.rs","sha256":"a78380b019104d688c11a4410082c7e08ded3106aab099954c4f8a1b4ae0fd89"},{"path":"product/runtime/auths-gateway/src/readiness.rs","sha256":"911c3f11892f94641574375e2da4c671c802738f71082f12c39832331052d43d"},{"path":"product/runtime/auths-gateway/src/recipe.rs","sha256":"fecf9af67e7afc48d080e9f8f55f8ce28e49d0e08988717a27908bbda461d6b6"},{"path":"product/runtime/auths-gateway/src/recipe/lower.rs","sha256":"8088b8751ed831dbb48247af953c6290ac95e2a438ccd5bd65eff54be06a1fd1"},{"path":"product/runtime/auths-gateway/src/recipe/review.rs","sha256":"c3eb7d9fdd98dacf52750b14b67ad7b7faaecbbdeafff1e0b049f67d0a2d0139"},{"path":"product/runtime/auths-gateway/src/recipe/runtime.rs","sha256":"c286f0d15f974402822c0810d8e97f98411dc1c557755cc23e540d85e2bb42d9"},{"path":"product/runtime/auths-gateway/src/recipe/source.rs","sha256":"1af50298fb1461e1b24cbdf560d43124d6b1c4c529586c911b1c4797214a69ff"},{"path":"product/runtime/auths-gateway/src/recipe/tests.rs","sha256":"aac551a2481bbc60864c64079bc667dcb232e45a0f41a04073ed84ab5dbe1fce"},{"path":"product/runtime/auths-gateway/src/recipe/validate.rs","sha256":"3711b17605cb7b0d639bc1b180449231f5882a306cab20e2c7782155cc63b0d4"},{"path":"product/runtime/auths-gateway/src/scenario_tests.rs","sha256":"025b53473b3af6900e03bc2fee91aa63ed26a8778bc8c8296fe08f5540794c39"},{"path":"product/runtime/auths-gateway/src/separation.rs","sha256":"be9306848ca5d801767cf6aa14247c8618312ef0e202f00ce0c24c4844491061"},{"path":"product/runtime/auths-gateway/src/simulation_attestation.rs","sha256":"88705e5d45415f760f1e3c3a065c35c48f4f4065bf7b3feb7882246983814d6f"},{"path":"product/runtime/auths-gateway/src/store.rs","sha256":"884bcad4d70d53e12eae9c8517f6ecd0643068ee0be0370015119d04d6cc2516"},{"path":"product/runtime/auths-gateway/src/store_testkit.rs","sha256":"88d82fee42f1b8ef521e8deef0216e938ebeaad822eb2f5020e70b89d145ea70"},{"path":"product/runtime/auths-gateway/src/submit.rs","sha256":"fe2eacb5ad8152eeecbd232c47a356fc72db0098e34fda99532bdf6ef0cf895c"},{"path":"product/runtime/auths-gateway/src/support.rs","sha256":"9fd979029793a22b15d9776a7fc172476fd7c126a80d4080c65d720845becbcb"},{"path":"product/runtime/auths-gateway/src/transport.rs","sha256":"978fc9fb34a33b3db265b5d1c3ce11696a5b9f08529e46dd2a1e7bb62afb9220"},{"path":"product/runtime/auths-kernel-runtime/Cargo.toml","sha256":"926bcd0053e5edd703be8f0027ad009e2982db013c8174c1366edbf38b48087d"},{"path":"product/runtime/auths-kernel-runtime/src/lib.rs","sha256":"7108faae9ca4bc32dc093ddaf885ac8f74f3c9b8d317b7c7d0ed00d1d0ab5972"},{"path":"product/runtime/auths-lifecycle/Cargo.toml","sha256":"c5053c705f8d5554b44e432fe75287a2faf11d644e5a2552e45ad6cd94176af5"},{"path":"product/runtime/auths-lifecycle/src/codec.rs","sha256":"51c4b746749150e8bfcd8ff972b3f6c1ef40bec15583448ec1b471d9ad737dc0"},{"path":"product/runtime/auths-lifecycle/src/digest.rs","sha256":"55282cd7d8aba37713c2dcb5357c9877819edb72a30eadefb860d28d7d3a3eb7"},{"path":"product/runtime/auths-lifecycle/src/identifier.rs","sha256":"31620e8c16de68d3d2d3b84d6353c1a5b9d4151d8247f91fa389b906a8e660f1"},{"path":"product/runtime/auths-lifecycle/src/kernel.rs","sha256":"2abb8c094b36d35b364e74d78091d14c5d6f3d1eb6552cca3b5538dbd017ce23"},{"path":"product/runtime/auths-lifecycle/src/lib.rs","sha256":"afe5a345cd309b5a4f08ffba3170a6d7f16ff914892b3f2006d5208ed24ec736"},{"path":"product/runtime/auths-lifecycle/src/model.rs","sha256":"1af12bbeeeaa65ec02ddcebd7d2c8c92ec1e339fa40ae85b45ab9b01a722a4fa"},{"path":"product/runtime/auths-lifecycle/src/operation.rs","sha256":"78e6d05fcf5d7ea4f148032a3fa26fdfcab77eb346019effe927b08e0d64d732"},{"path":"product/runtime/auths-lifecycle/src/registry.rs","sha256":"53495fe6f7a77422593a41623e28716f1c140dcc1e00f87f6b0ffbfb93a5ef90"},{"path":"product/runtime/auths-lifecycle/src/sealed.rs","sha256":"2e0c03b5813c926c159598bb7890d1523825edbe57cd687d42a5dfb3374a0c19"},{"path":"product/runtime/auths-lifecycle/src/test_support.rs","sha256":"221d9a5c5ef8e1f9f8fd66927484eaf813571d0568470278ecd8fa08a5eec8cd"},{"path":"product/runtime/auths-lifecycle/src/transition.rs","sha256":"011805a28efdd541f44ccea54dd0e34a1e58f4004447ee58013703b4fb6b2822"},{"path":"product/runtime/auths-runtime/Cargo.toml","sha256":"dd29d80a8b4bb56c869f036a6c9998f6e6d1c0383ac5dc03fa42b24abe2a7ff7"},{"path":"product/runtime/auths-runtime/src/lib.rs","sha256":"132ca03d58c14905d3a822a4972f42a22a5ad33a45f2ba9ca44f3a57d810b4b0"},{"path":"product/runtime/auths-runtime/src/production.rs","sha256":"fd4eff4270c571c10fcff6cf27df28961ebf074de8a1a028f500fda1ca376820"},{"path":"product/sdk/auths-approval-quorum/Cargo.toml","sha256":"df904971fca87a24194c5816738a331588fe8f164acb5d70839a35dca5f57114"},{"path":"product/sdk/auths-approval-quorum/src/lib.rs","sha256":"72e4086088a1c0912e4e1a9e980f26a5c280bf5ab16ea39c9f0f58d5096ac2ce"},{"path":"product/sdk/auths-approval-quorum/src/remote.rs","sha256":"9fa029c7c63003adf260f8aec55160c545681c60c1bace0d934e7525862aac7b"},{"path":"product/sdk/auths-approval-quorum/src/remote_tests.rs","sha256":"8a09ce17cfee82a035a74edd535f3ebeb3db0e078784740d3997b17dbdb10197"},{"path":"product/sdk/auths-approval-quorum/src/tests.rs","sha256":"0acbf12be3e497dcc6c2d8f29c9af3b1a7ed8e11b75f6399570d4f217a785060"},{"path":"product/stores/auths-stores/Cargo.toml","sha256":"a32c4b76d17b264be5d40d24497ff237e1ed87822e8bab86229b3db93106dbe3"},{"path":"product/stores/auths-stores/src/gateway_attempt.rs","sha256":"218841602d3d9b23b44625f50e5b54cf275ccedc2d5c89f02d2482b8524472af"},{"path":"product/stores/auths-stores/src/lib.rs","sha256":"e721262edf8a9ab5568ddc27639176312d4a366203b5f73e2d7c11fde2c554e9"},{"path":"product/stores/auths-stores/src/lifecycle.rs","sha256":"3f2cecfda13fdcd7c4a944518646bcc8abd1237f900c0332d5822281f8f9f1cd"}],"schema":"auths.gateway-semantic-closure/1"} \ No newline at end of file +{"files":[{"path":"Cargo.lock","sha256":"0e75e2fdef44e79e57797ac6661295ae58ddb8de4a1990a6fd22ce6c54f78604"},{"path":"Cargo.toml","sha256":"6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24"},{"path":"core/adapters/auths-did-keri/Cargo.toml","sha256":"86ba3e3f9a0a70d970568bfb3113b7ba7bbdd81c3eebbb52743dd574a0c0ecaa"},{"path":"core/adapters/auths-did-keri/src/lib.rs","sha256":"a75674842f8a7142004369ccd206ab43e476459293f0ff4bed4d4e659031b3e3"},{"path":"core/adapters/auths-did-key/Cargo.toml","sha256":"d5a3ae07ecde83f91eed4c3785051dd0f44eab6c891754f3309b6b40596707d7"},{"path":"core/adapters/auths-did-key/src/lib.rs","sha256":"b76a3f4528a725df53cfa9242e6e414e1d26caa48468aaed497e28b121f4497c"},{"path":"core/adapters/auths-raw-key/Cargo.toml","sha256":"f49616bc18c19e6aaa7e6a02ccebcdb9f5c1422c1278ef9869e0dbf22ceda7be"},{"path":"core/adapters/auths-raw-key/src/lib.rs","sha256":"45eec1b295dac3bed65cd79c942870b926b06b3f5d38eaebaeb6140ac69315fa"},{"path":"core/crates/auths-algebra-kernel/Cargo.toml","sha256":"0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba"},{"path":"core/crates/auths-algebra-kernel/src/generated.rs","sha256":"ae4bcbef42a408c7ffa0c6a74a42f7de177a6f14479e51d205acf830bda05960"},{"path":"core/crates/auths-algebra-kernel/src/lib.rs","sha256":"6654667eeb9b353d6648954c9fd2e8838462a82ce6b2803eb49e1366892c68c6"},{"path":"core/crates/auths-assurance/Cargo.toml","sha256":"afcb12a97ddd09d7a264b9ecd3fcaefc865ff2c9b4539ee85b00883420ba333a"},{"path":"core/crates/auths-assurance/src/lib.rs","sha256":"0fb2ec844d674b25a9e20b1601452c89c2454901fa506adfa9bb38ef9a7fa213"},{"path":"core/crates/auths-author/Cargo.toml","sha256":"1e6f0e3bc079ddb558decf0db26b291c6e72fc47327b6df1b7650d41689b215f"},{"path":"core/crates/auths-author/src/lib.rs","sha256":"e14475f2f49715a1869d5fa6b11ff1fbb72497e39097e09f833b0bae7e5b3f2b"},{"path":"core/crates/auths-author/src/observations.rs","sha256":"dda7d6bfa6f4bd7e95a480ca283c2c0e996f69c5c15cb0c7197af328131a7066"},{"path":"core/crates/auths-authority/Cargo.toml","sha256":"4f68212938029f79ebd857b4f3038494eb85d0163d49f07e51376715cf959815"},{"path":"core/crates/auths-authority/src/lib.rs","sha256":"da88d5194de4e17449e69972c0fb042afa3c39798a8f570f30771e77c384f1eb"},{"path":"core/crates/auths-codec/Cargo.toml","sha256":"e20e51826e17814effd9d8925d18d5fbdd6c0d37bf50231e743ec2611314722c"},{"path":"core/crates/auths-codec/src/approval.rs","sha256":"fbff43bf4d57f69f8b7738a8647751cde75c5a932dee65d924a1fe9c7202f91f"},{"path":"core/crates/auths-codec/src/bounded_policy.rs","sha256":"d21f6728be2d8a04b6d94921f2b683f7e61cbb42e0ac6866f1c88a49caa534c3"},{"path":"core/crates/auths-codec/src/decode.rs","sha256":"ba2999584cdf53b1b517ecb9c7ea50d39efee17c666a9a38e2ad1ac94379f778"},{"path":"core/crates/auths-codec/src/encode.rs","sha256":"8491192053e2e15d62b4d2a491de22405b7487ead69ab6f6bca40669ce7ca5f7"},{"path":"core/crates/auths-codec/src/error.rs","sha256":"fecb0737c16deb42d859f1dc7727c698438d9ac12064fd99e0024629642c390c"},{"path":"core/crates/auths-codec/src/hash.rs","sha256":"f88e111f1dbb2cef6b7b5e9c948cb45ff92e366710c8a5f5c636138aa748479e"},{"path":"core/crates/auths-codec/src/lib.rs","sha256":"3b0e5c94c6f34f750b88a9333e1d5c8145746d845d3a23e0d2f61807cf592ea7"},{"path":"core/crates/auths-codec/src/observation.rs","sha256":"38328b0c71ff97a4196eeade8b4faa889527ff1f80bb168468bcd49082a3987e"},{"path":"core/crates/auths-composition/Cargo.toml","sha256":"331e13025eb82588b5269ed3975929eb41c823d588c49e4c296273d85c6fe80e"},{"path":"core/crates/auths-composition/src/lib.rs","sha256":"e42e3b0b6a9985b73c533aeb23799c638979aa27a9ce7d0f10a8d60340570fb1"},{"path":"core/crates/auths-model/Cargo.toml","sha256":"565c15302b0cc9270db1e28efa3862804846850ba933cc17aea8abcec4a65987"},{"path":"core/crates/auths-model/src/approval.rs","sha256":"54cf44a9ef747ec21546a4086aecfb130bc7803b0d646430e6082df51e6e305f"},{"path":"core/crates/auths-model/src/bounded.rs","sha256":"f90496abc0a06c028b4d850af6ddab7d850bfafeaa3d042f1b1246a41d8bbbc9"},{"path":"core/crates/auths-model/src/bounded_policy.rs","sha256":"306a8f049cc7cfc7635fe0e4de47eb7813eed63d3c14c3be2b51586aa4eea450"},{"path":"core/crates/auths-model/src/lib.rs","sha256":"e7cfe6bb9574c6b016aa63e70658c31e0b90903ec6479a49f4a2ceb64f5bad97"},{"path":"core/crates/auths-model/src/observation.rs","sha256":"b3ed3e3cc090afca2896a7d3de7988afccc1ee1ea0ebd91b51a8bc0f20ad8dbb"},{"path":"core/crates/auths-multikey/Cargo.toml","sha256":"858756c1197befcada06134742bffe8d58cf674cadd6c046bf710570e96efaf2"},{"path":"core/crates/auths-multikey/src/lib.rs","sha256":"f5177fffb11e40eeaaa665ba886c541fc1f24d5eacdd6983fb03dc20148733f0"},{"path":"core/crates/auths-ports/Cargo.toml","sha256":"596a9b0f5af3717c16a6d13f7054d8a106bcd9f01f5f72c2235dd2afcf0ab16c"},{"path":"core/crates/auths-ports/src/binding.rs","sha256":"a16c012d40aa4249e3ec54372b9611006d0bfe8c7dc3c741911c2194ad17736d"},{"path":"core/crates/auths-ports/src/diagnostics.rs","sha256":"aa596572503b5a65a918bb2ff38281c144ff53821ee914e9325c852828d852df"},{"path":"core/crates/auths-ports/src/lib.rs","sha256":"8da1debf86f9532df0660155d04298beb1ba3a1204508f8586e2e67cd2fb3449"},{"path":"core/crates/auths-ports/src/path.rs","sha256":"b68fc547b4e4d97a60cbbc1cc1939fc6b34a8233b81f840bd396914a707e3ea1"},{"path":"core/crates/auths-raw-key-core/Cargo.toml","sha256":"98c0bc8527a537512e43a74dd6ba9658c6f0cdc16610cf938e3f9b43785d836d"},{"path":"core/crates/auths-raw-key-core/src/lib.rs","sha256":"98c0500c41697aae28708ad0bf970b9a97583d96a3d2c18d23e7fa351e0f7d12"},{"path":"core/crates/auths-registries/Cargo.toml","sha256":"590e49e58b0622d9d6274fea46796dcdb07dec9550eff295cce6a6427ffa51e2"},{"path":"core/crates/auths-registries/src/lib.rs","sha256":"450d3886d85ee333b7e046317fb5b47cde62483d5f3e41d46265e2caf4c373ec"},{"path":"core/crates/auths-registries/src/template.rs","sha256":"1224039dd2b3ce6fa8357613d8cafbae40400493da7176da202b9ade62fa05e4"},{"path":"core/crates/auths-signature-core/Cargo.toml","sha256":"6bee2230eb30af1be0bd5c2d57bd3e1903497a70028d47290d4ac6e9e0e8bca0"},{"path":"core/crates/auths-signature-core/src/lib.rs","sha256":"6e3f9311ded5e49ea50d445eb21e6d8fa12442aa4362a73e0cb6fda15b7cd865"},{"path":"core/crates/auths-signature/Cargo.toml","sha256":"7f7b5682466ba439d8c59579022cb61068cad9fb4bd2d73e1cc21327c902b450"},{"path":"core/crates/auths-signature/src/lib.rs","sha256":"b3d9ac4cc3ba0797b9e1c09f2d6ac05089b25dac4e285a5af28c0165b33d925b"},{"path":"core/crates/auths-verifier/Cargo.toml","sha256":"c43358e06a33324b41a8b93e5cc7279c55f7d21f1f6cfaa539a3fc7b4c27a38f"},{"path":"core/crates/auths-verifier/src/approval.rs","sha256":"c3cae6a49e169051eb555bb092b1069a4d422516d6a2114623a89e5f31ff923f"},{"path":"core/crates/auths-verifier/src/causal.rs","sha256":"9635230f33b13a263573d319ac8a1976addbcc07677514a43e3c7bf28dc04587"},{"path":"core/crates/auths-verifier/src/lib.rs","sha256":"f22dec38dfa47ced8da4f605390da8453273bee1da010f57fd1fdfcb10e0b389"},{"path":"core/crates/auths-verifier/src/observation.rs","sha256":"0bb07f06a0f9524c88427df1c972b1de8ba038a9eeeb15d3134c25125ae84b1e"},{"path":"core/crates/auths-verifier/src/trace.rs","sha256":"2213d72023a1d9e0413a2cf2c51c3dad9e04775d86033a0caaa9d29a8f0036f8"},{"path":"exchange/crates/auths-proof-exchange-model/Cargo.toml","sha256":"34b2db64f93a288e942b5a3918d28cdcbef906e0dc9074ce848018d3d5f7a1fa"},{"path":"exchange/crates/auths-proof-exchange-model/src/lib.rs","sha256":"49fac5aff2339d3a57c41cb8bb2a82852538e8f77ecc4b157c88e264ff31fb55"},{"path":"exchange/crates/auths-proof-exchange-port/Cargo.toml","sha256":"7ff660f1b7579dc570c791090aeb450404fbbf44c92781e289f5ccdde746d739"},{"path":"exchange/crates/auths-proof-exchange-port/src/lib.rs","sha256":"b408fb40c6432edc1facb3d8b3e9433a033f8dc73fe2e0ba5a88c972ca675021"},{"path":"product/config/auths-config/Cargo.toml","sha256":"e4b568ab9f6d84f7d7e6d66443fe825f360db9c27bc7c31d6ddc0647ba3ab304"},{"path":"product/config/auths-config/src/lib.rs","sha256":"fecf00ea65cef9018fda9af2063326d7065b869266d0d9e73a4f06816f1102cc"},{"path":"product/errors/auths-errors/Cargo.toml","sha256":"3b3a199b6460ba75bda84475bb5accd35e1485448a3981038db85bf4772dd350"},{"path":"product/errors/auths-errors/src/lib.rs","sha256":"7feeb9069fa4003f94f1f07c1c94619cf1c883e0dbaaf2187f04d0f742264bdd"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/Cargo.toml","sha256":"716f1f2a117d6d69d8effe9ee9057e24ba3502f20af6a602b06facb638cdabed"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/api.rs","sha256":"9ea61dd7ddd93282b073b98e453e6b75b26dc49689c04e9782435d06a3a09e48"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/clock.rs","sha256":"73f0a6e0f5903883329fa6683f5888288f759512ac69e5c87efd2b6b87f7d79f"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/http.rs","sha256":"14c1fce14e24c984b2a275563a29b6326fb08367922b6e8d37ba38b9cb81aa2b"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/identity.rs","sha256":"186de11230c8b33375951c4368609f8976bf9795f171af3fd7fac26207a94361"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs","sha256":"0b4617d044f5254a5ab22f5a2578f91cc025206a8c1845be39c1c56dcdf7a5df"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/names.rs","sha256":"41bb23572d6002e23ee103d6fe70ecd68764861c6f2e48a1c53af998270a4afa"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs","sha256":"39fed883f4802e68d3b41a68fea0aba0737810996b33d13577de70faba004c29"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/store.rs","sha256":"fc60ee9c49b2f4f063c449b4c78100c5c4872779e94ca168f796603b380ef6e4"},{"path":"product/integrations/auths-custody/Cargo.toml","sha256":"1e14034185ad1ec24a977fd5f41d0abee219606245c046ce2a82287fadef448b"},{"path":"product/integrations/auths-custody/src/conformance.rs","sha256":"8ed1afd58f18fc6becc268908aa6419c9aa404c79da0197963eb2599df44acf6"},{"path":"product/integrations/auths-custody/src/key.rs","sha256":"70cbb0fd21b6f5652157845a22c35be2d0f6c05b3d138fc4b9bb6dbdc3d81c40"},{"path":"product/integrations/auths-custody/src/lib.rs","sha256":"8ee593c1f59b0fd2126bdda9138026f5bc531beb64d4489a99785842e7b98b43"},{"path":"product/operations/auths-operations/Cargo.toml","sha256":"73dde1e914ba5e1386f8d49c0d730423cc72ae77ec44c6554a6a75cc8e8922b1"},{"path":"product/operations/auths-operations/src/explanation.rs","sha256":"b4a39bcbd5712cb9e735ee7deeb281f3fa6af5ddca973735bf3d87dce427ef11"},{"path":"product/operations/auths-operations/src/lib.rs","sha256":"3f401a56555113b98f57bca172a2660eaecedf76247b83a3fdbb089c133a29cd"},{"path":"product/operations/auths-operations/src/render/json.rs","sha256":"2ae042639960afee123730e945d373bc5dda1d2b3af20ae16c939a7e99b9e418"},{"path":"product/operations/auths-operations/src/render/mod.rs","sha256":"b3b7f6fe473f49227ace5a68bfc3d8dc14b5db8dd9888fd9e207070337b1b8bf"},{"path":"product/operations/auths-operations/src/render/text.rs","sha256":"f216cf3bdb00e264523271b16e7059535ac6b1aabf271cebd7935af155e4bfec"},{"path":"product/policy/auths-bounded-policy/Cargo.toml","sha256":"babd5d200923137ead71d8c2528f847cea323ce98da942a1320b054436612c47"},{"path":"product/policy/auths-bounded-policy/src/arithmetic.rs","sha256":"75e43c5d4eab8d1f71c1daf53839f5f9fe45a400afc1f63a30c6f55ce3632627"},{"path":"product/policy/auths-bounded-policy/src/commitment.rs","sha256":"c5706f2d583454e1a7f570f7ada138d4d864bef0205dfae7c1296774f396bb3f"},{"path":"product/policy/auths-bounded-policy/src/eligibility.rs","sha256":"c9acdfb793074e687fc36efad506be27dbd99ffbf40387bc66c8de39ef238432"},{"path":"product/policy/auths-bounded-policy/src/identifier.rs","sha256":"0006a32bae9eb16c4178cf797df418d2b0a781f2bc6474b741dc1a908141831c"},{"path":"product/policy/auths-bounded-policy/src/kernel.rs","sha256":"99187c28b161ac70bee1afed60711f7f645adb4d1671a01863f9849b369811d5"},{"path":"product/policy/auths-bounded-policy/src/lib.rs","sha256":"76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c"},{"path":"product/policy/auths-bounded-policy/src/receipt.rs","sha256":"3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad"},{"path":"product/policy/auths-bounded-policy/src/registry.rs","sha256":"4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0"},{"path":"product/profiles/auths-profile-api/Cargo.toml","sha256":"7ae85761f58625b5d678f961fd052eebf3e000ef565c7312e3ac857763c0017f"},{"path":"product/profiles/auths-profile-api/src/lib.rs","sha256":"a194b82b20bf8aa864c2334ef6c6aec30b2154ded972862252d5dcefa488ab95"},{"path":"product/profiles/auths-profile-mcp/Cargo.toml","sha256":"db264fc25242f7b7e4133cbe5782545b3107b406c87168ae072683cfb59eac66"},{"path":"product/profiles/auths-profile-mcp/src/arguments.rs","sha256":"a5de696586d507e2aee4a49fee99ef1ef4c51a2e46603f8838f1af6d9009833f"},{"path":"product/profiles/auths-profile-mcp/src/lib.rs","sha256":"d0f8b733a09ef8408336cdebc8948d6a5861012ce6878598b11be7084dfd4280"},{"path":"product/profiles/auths-profile-mcp/src/session.rs","sha256":"166c281fa66333388e4760d6098dad02d3359e1d5de4b8f93312c014f97abb03"},{"path":"product/qualification/auths-recipe-qualification/Cargo.toml","sha256":"b7b15b30b9a3d96d4f089d514266d3a892de6608d30707aa44be31cca89ca9fe"},{"path":"product/qualification/auths-recipe-qualification/src/canonical.rs","sha256":"30a9b50777f0dcb4b606abfee2467d5a975d9f6ad941ab6c13ca3df5b359f667"},{"path":"product/qualification/auths-recipe-qualification/src/closure.rs","sha256":"0ad6aee9bd981e2863fa725f209ec84031db2ff12f4c7ac3aaf5120f0bb86039"},{"path":"product/qualification/auths-recipe-qualification/src/commissioning.rs","sha256":"db135c55e4e3079a73253ebae275536523eb36b545d1c152b4d7dce3c6b76828"},{"path":"product/qualification/auths-recipe-qualification/src/commissioning/tests.rs","sha256":"4dde3736d206099b1bea4c14e0092c6c1287d1af9065958777d7c54331dd8686"},{"path":"product/qualification/auths-recipe-qualification/src/error.rs","sha256":"52d5cf720a1e4579008fdda90a3ac2c31f0b8db57985f121f65e54b4da2b7dd1"},{"path":"product/qualification/auths-recipe-qualification/src/evidence.rs","sha256":"ba45a7409d67a8af26ab811af306412014557477a101ab2a8eb0faf8f2bd4b91"},{"path":"product/qualification/auths-recipe-qualification/src/ids.rs","sha256":"e81a906d571497ab2da753e1532d4443706410e0b75fdd59a7d2d788c7aec403"},{"path":"product/qualification/auths-recipe-qualification/src/launch.rs","sha256":"41f2e2de90e1e7d6440a66eda3eb9bea8d5e0741bc232305a76a363ab5f813c1"},{"path":"product/qualification/auths-recipe-qualification/src/lib.rs","sha256":"0e24b0f81191df0d078c7f4d73ced784ba9472372bfcdff3c7d0e2fb1687b323"},{"path":"product/qualification/auths-recipe-qualification/src/model.rs","sha256":"3484eb0ec287b23d4682ade7b1b0f8d1335985b3fb180f06fc28716076957d5f"},{"path":"product/qualification/auths-recipe-qualification/src/release.rs","sha256":"ec478e53f70052e566aac7e15be2f9e1b1cd46837ac6990ae955fa864d311586"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/mod.rs","sha256":"fa23a962fd90331152eed5edbcdf271955f7aed79b8da1e065bfe69a20b487a9"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/schemas.rs","sha256":"c59feec2805621f341a90f81fc005e2c12f7a70f9d264fdeacccb2be4fe1c046"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/verification.rs","sha256":"bdf5746fed4d10a7f577f7878619a917d29aa8b7d522f00d9f774e53eff4c8c1"},{"path":"product/qualification/auths-recipe-qualification/src/verify.rs","sha256":"2ec2784435d11e07295de77b2ee1b2c48b2fcf9609a00454c6e7374b621aed5c"},{"path":"product/receipts/auths-receipts/Cargo.toml","sha256":"6001fa1375899953aafcb07c23a6da0c8f57ea7ec08bb9c950b12a60a8cc6f0f"},{"path":"product/receipts/auths-receipts/src/disclosure.rs","sha256":"ba9ed439be0a320c8a01f5b6e9b51361c1a37e076947490d8e4a484ba6bb119c"},{"path":"product/receipts/auths-receipts/src/lib.rs","sha256":"547a57c4160256719cafb7d0ab972d9fc80b0da14fbbce4148c70c414070ff36"},{"path":"product/runtime/auths-connections/Cargo.toml","sha256":"babeb6e1dda3dfb66291713ce1e43dce5c349833d0b50ea4dccbf986030026b2"},{"path":"product/runtime/auths-connections/src/credential.rs","sha256":"82921413bb053f0f6c7931fbd4e6a86c8cc1d8c6b51debd9c2cef33a8d5b1c51"},{"path":"product/runtime/auths-connections/src/kernel.rs","sha256":"a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8"},{"path":"product/runtime/auths-connections/src/lib.rs","sha256":"79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22"},{"path":"product/runtime/auths-connections/src/model.rs","sha256":"de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77"},{"path":"product/runtime/auths-connections/src/registry.rs","sha256":"e57640e003e72ad3235c567c2bb944a262bd64e673f023b62ea091094cc7e946"},{"path":"product/runtime/auths-gateway-kernel/Cargo.toml","sha256":"34f864e67656af4ac7e5c7a347a23f01fc8ab31365b8e23c0ef474483b14a183"},{"path":"product/runtime/auths-gateway-kernel/src/construct.rs","sha256":"e9d65744bae273d65face4285e5d2da75c06a92ab48f7b8333d496604e31c63c"},{"path":"product/runtime/auths-gateway-kernel/src/lib.rs","sha256":"cfda6f8453426564c085475f183b6f790b438768a19668f1b65d33ba59dc8632"},{"path":"product/runtime/auths-gateway-kernel/src/order.rs","sha256":"e0045f877c4b7fe3860c291039853885064ddcdebba7c9b345ab65e81e646dda"},{"path":"product/runtime/auths-gateway-kernel/src/outcome.rs","sha256":"e9785b1afe70788c89b51b18655bcd5acff7b0c8e3d12fb79c6f05a202e67e6b"},{"path":"product/runtime/auths-gateway-kernel/src/ratio.rs","sha256":"7ace22264812e6fc1ef3a62afee402cf43494bb71ae0d3de219ad1b39d690bcb"},{"path":"product/runtime/auths-gateway-kernel/src/recovery.rs","sha256":"9f46dcd1685ab6e4d1ba04a3fc286a9f3afee8fb47829be1fbc670a7926a2dc6"},{"path":"product/runtime/auths-gateway-kernel/src/transition.rs","sha256":"cefb8f01d915880f6921f2501ff881ad94b9de61072c34d9cd19220992f97374"},{"path":"product/runtime/auths-gateway/Cargo.toml","sha256":"00b28be86921dcdc0ad90cce0c62c2961cafefe96ea6c2edf0e926c3d405ccad"},{"path":"product/runtime/auths-gateway/src/admin.rs","sha256":"0dee40a9fb67c5de10142fc37a7bbabdd8979fb0199fb26caf4bdb024e0a5a40"},{"path":"product/runtime/auths-gateway/src/app.rs","sha256":"6f80f63833ea0815bb44fbf3b0cc54624a08e9fb578b035819f2980dc04e8256"},{"path":"product/runtime/auths-gateway/src/audit.rs","sha256":"0edb2037eb7b5d6f13acfce85c54f62a82bf7fdd31bc7e626c4fec183cef61dd"},{"path":"product/runtime/auths-gateway/src/audit_tests.rs","sha256":"990969384a52d75bc2489d9d412a9e7dd814bca1c8f65c701d6205fae62a15d5"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway-harness.rs","sha256":"12b0c24d36b2e6a3be392d3c081a783b355fdd67dc5b54bacc0410e803116b8c"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway.rs","sha256":"6031dca90667d2db39a78736b23e27dd4790a7887d2230bd57f6851754603a11"},{"path":"product/runtime/auths-gateway/src/binding.rs","sha256":"663b0ce878319511aa7d05722ab4ab2fa9be18817884ffb2ee9f131ff1e382d1"},{"path":"product/runtime/auths-gateway/src/bounds.rs","sha256":"38251ad6f22f9d07ef9a219c79fa265ca36f1526eca5f147d7efa46b52ad609d"},{"path":"product/runtime/auths-gateway/src/bounds_aggregate_tests.rs","sha256":"ab34f227b7c8692ba1da88ccb32bb3687a66adf8353d8282fae905d4a88eb612"},{"path":"product/runtime/auths-gateway/src/bounds_tests.rs","sha256":"74136bc570da7b9338b5a1a1ed9d3fd892c55135160964f9d3ac0e2cf5741375"},{"path":"product/runtime/auths-gateway/src/commissioning_budget.rs","sha256":"fab29da3269438cc62330f3eab7b5bd4dc482b4db8af243aae47df5d3aa1deb8"},{"path":"product/runtime/auths-gateway/src/commissioning_budget/tests.rs","sha256":"da104a1643c37515deec6397bca6db2054f2c9158ec3d230a1b1ec9c7d0f659f"},{"path":"product/runtime/auths-gateway/src/commissioning_floor.rs","sha256":"7fa6991c5ccd5ae1403be84b3da390323fab09f36e15ac01fd7a38ea350c6fdb"},{"path":"product/runtime/auths-gateway/src/commissioning_floor/tests.rs","sha256":"6b663d6e556adc0b455b81845bc4394d82c6c4de0c5f43e1310f3ddc6e4e40f7"},{"path":"product/runtime/auths-gateway/src/commissioning_session.rs","sha256":"24b48d5eaeaaa3c620e2dfc7ee1f9255fc4519a1eb404b8608cea7af6a910ee2"},{"path":"product/runtime/auths-gateway/src/commissioning_session/tests.rs","sha256":"37a097fc8a9261d3fffdaef3f905f40b22e3e6601bb5101fadd9414f963c0824"},{"path":"product/runtime/auths-gateway/src/connection.rs","sha256":"7b5d049c258a26ed1c93ecf860f51d051a8a65f9b93554af0b1ea93862398ec9"},{"path":"product/runtime/auths-gateway/src/credential_journal.rs","sha256":"7297fccaee5cd8622928e8e0a42bba50da7941970a6f682ecd300c41ee6509da"},{"path":"product/runtime/auths-gateway/src/echo_verify.rs","sha256":"6d453051665f823abd7354d5c50031d9524cf47d6092d2f09080ae814e3b9575"},{"path":"product/runtime/auths-gateway/src/engine.rs","sha256":"1abff20b98bc894c45bfc5c4414c81a99966d1ec95d924a5b0cd6f4c5626ca24"},{"path":"product/runtime/auths-gateway/src/execution_witness.rs","sha256":"e8b1a8e41d5e3fa309760067849d390ef065feeb46701a83391832645a2f000c"},{"path":"product/runtime/auths-gateway/src/fuzzing.rs","sha256":"ed3b0028487eb546a3b0a91d115aa8f18bcea324b61620bfe8e35a9e6ab18758"},{"path":"product/runtime/auths-gateway/src/generation_floor.rs","sha256":"fe1510ec96ce0f67e9a78edbfa94b33eb7df64c0ac4d0a67901124dcd0164777"},{"path":"product/runtime/auths-gateway/src/harness.rs","sha256":"c87e479f3eb281960f6c9c80d43c7560d7ccb654b0154ec823d3fcec4884ac05"},{"path":"product/runtime/auths-gateway/src/lib.rs","sha256":"fad95d031f88072dd024c78facf0bb0267562b1ac743ddd7219fce47e64024f0"},{"path":"product/runtime/auths-gateway/src/listener.rs","sha256":"aa08239bcbc1fcb55e8a212fbdf6a84f12985b0d436dcb51dc58b06e59e435f2"},{"path":"product/runtime/auths-gateway/src/observed_tests.rs","sha256":"a22be071695f89ca2578a4d82fd80d9cb82289213c9bdb8f0470f6b2dc3d9201"},{"path":"product/runtime/auths-gateway/src/observer.rs","sha256":"562ffcaea071c3856e0708dc2fe33516917e145d2438aabb75af0a2b6ba01046"},{"path":"product/runtime/auths-gateway/src/onboarding.rs","sha256":"0dfd7d67e7f02f18a28d1c86ca1b7751d7463f5efcdbe3825de0ad8cbccb3891"},{"path":"product/runtime/auths-gateway/src/operator.rs","sha256":"c3c36954a3e86723df035b47f43b85fc8ab3a6292983522b6258d5c6b4e6c4e4"},{"path":"product/runtime/auths-gateway/src/pending_vectors/attempts.rs","sha256":"47ef3c8cb1c5504d47ae9a0088705ce6715fe86bac1671a34a56fb38a64d0dd3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/bounds.rs","sha256":"e612217307e1da5b0eb5ee6582a7458bb064b8aa8a529fc6555b1b334127ab68"},{"path":"product/runtime/auths-gateway/src/pending_vectors/codes.rs","sha256":"e00670a5ef24eb856cc2c6dcda8e5a263842f55c76bb939c0c27bd9df37e5522"},{"path":"product/runtime/auths-gateway/src/pending_vectors/keys.rs","sha256":"f84c56f2ea9cb34b2b79c72d13fbf2c6585010ec1ed450af58a78c80c1ea1edd"},{"path":"product/runtime/auths-gateway/src/pending_vectors/mod.rs","sha256":"5de8340f0ef71a0b57a09e323fefe473d3160c6ae952b9ba46f714825fbacafc"},{"path":"product/runtime/auths-gateway/src/pending_vectors/outcomes.rs","sha256":"8ec07b9511b48913af36ac999d2aa0e82924289f6acb23ddaeb9f00f99815166"},{"path":"product/runtime/auths-gateway/src/pending_vectors/production.rs","sha256":"772d032e0a0d9c924fb6d6c188528db85a97e71c9e466ddc19eee277baf83614"},{"path":"product/runtime/auths-gateway/src/pending_vectors/recipes.rs","sha256":"51693208270231c25c3aef2a32151d5962114c71e86b88cb9df83181c7af83d9"},{"path":"product/runtime/auths-gateway/src/pre_entry.rs","sha256":"06ea78ca140468bfaba17d9ab04912ad68673954c3203c98fed28272ff2a00c0"},{"path":"product/runtime/auths-gateway/src/property_tests.rs","sha256":"939c081e2e154aaf10186754044bdd65608932c899b970a04a71d0afaa999a93"},{"path":"product/runtime/auths-gateway/src/qualification.rs","sha256":"c597c83de2b94f0374ae54e40a8b57c2a64ec6e254704dca32185f448a908aca"},{"path":"product/runtime/auths-gateway/src/qualification_simulation.rs","sha256":"4ee7cadfb5f46a92713c80f3e55f499cb074d04d8b21ea89d57762af38642bfa"},{"path":"product/runtime/auths-gateway/src/qualification_tests.rs","sha256":"a9178a2e58eea459d5e5dafc53a3999ea7c84dbbffefe6e5eb1f3d098827f028"},{"path":"product/runtime/auths-gateway/src/quorum_tests.rs","sha256":"a78380b019104d688c11a4410082c7e08ded3106aab099954c4f8a1b4ae0fd89"},{"path":"product/runtime/auths-gateway/src/readiness.rs","sha256":"911c3f11892f94641574375e2da4c671c802738f71082f12c39832331052d43d"},{"path":"product/runtime/auths-gateway/src/recipe.rs","sha256":"fecf9af67e7afc48d080e9f8f55f8ce28e49d0e08988717a27908bbda461d6b6"},{"path":"product/runtime/auths-gateway/src/recipe/lower.rs","sha256":"8088b8751ed831dbb48247af953c6290ac95e2a438ccd5bd65eff54be06a1fd1"},{"path":"product/runtime/auths-gateway/src/recipe/review.rs","sha256":"c3eb7d9fdd98dacf52750b14b67ad7b7faaecbbdeafff1e0b049f67d0a2d0139"},{"path":"product/runtime/auths-gateway/src/recipe/runtime.rs","sha256":"c286f0d15f974402822c0810d8e97f98411dc1c557755cc23e540d85e2bb42d9"},{"path":"product/runtime/auths-gateway/src/recipe/source.rs","sha256":"1af50298fb1461e1b24cbdf560d43124d6b1c4c529586c911b1c4797214a69ff"},{"path":"product/runtime/auths-gateway/src/recipe/tests.rs","sha256":"aac551a2481bbc60864c64079bc667dcb232e45a0f41a04073ed84ab5dbe1fce"},{"path":"product/runtime/auths-gateway/src/recipe/validate.rs","sha256":"3711b17605cb7b0d639bc1b180449231f5882a306cab20e2c7782155cc63b0d4"},{"path":"product/runtime/auths-gateway/src/scenario_tests.rs","sha256":"025b53473b3af6900e03bc2fee91aa63ed26a8778bc8c8296fe08f5540794c39"},{"path":"product/runtime/auths-gateway/src/separation.rs","sha256":"be9306848ca5d801767cf6aa14247c8618312ef0e202f00ce0c24c4844491061"},{"path":"product/runtime/auths-gateway/src/simulation_attestation.rs","sha256":"88705e5d45415f760f1e3c3a065c35c48f4f4065bf7b3feb7882246983814d6f"},{"path":"product/runtime/auths-gateway/src/store.rs","sha256":"884bcad4d70d53e12eae9c8517f6ecd0643068ee0be0370015119d04d6cc2516"},{"path":"product/runtime/auths-gateway/src/store_testkit.rs","sha256":"88d82fee42f1b8ef521e8deef0216e938ebeaad822eb2f5020e70b89d145ea70"},{"path":"product/runtime/auths-gateway/src/submit.rs","sha256":"fe2eacb5ad8152eeecbd232c47a356fc72db0098e34fda99532bdf6ef0cf895c"},{"path":"product/runtime/auths-gateway/src/support.rs","sha256":"9fd979029793a22b15d9776a7fc172476fd7c126a80d4080c65d720845becbcb"},{"path":"product/runtime/auths-gateway/src/transport.rs","sha256":"978fc9fb34a33b3db265b5d1c3ce11696a5b9f08529e46dd2a1e7bb62afb9220"},{"path":"product/runtime/auths-kernel-runtime/Cargo.toml","sha256":"926bcd0053e5edd703be8f0027ad009e2982db013c8174c1366edbf38b48087d"},{"path":"product/runtime/auths-kernel-runtime/src/lib.rs","sha256":"7108faae9ca4bc32dc093ddaf885ac8f74f3c9b8d317b7c7d0ed00d1d0ab5972"},{"path":"product/runtime/auths-lifecycle/Cargo.toml","sha256":"c5053c705f8d5554b44e432fe75287a2faf11d644e5a2552e45ad6cd94176af5"},{"path":"product/runtime/auths-lifecycle/src/codec.rs","sha256":"51c4b746749150e8bfcd8ff972b3f6c1ef40bec15583448ec1b471d9ad737dc0"},{"path":"product/runtime/auths-lifecycle/src/digest.rs","sha256":"55282cd7d8aba37713c2dcb5357c9877819edb72a30eadefb860d28d7d3a3eb7"},{"path":"product/runtime/auths-lifecycle/src/identifier.rs","sha256":"31620e8c16de68d3d2d3b84d6353c1a5b9d4151d8247f91fa389b906a8e660f1"},{"path":"product/runtime/auths-lifecycle/src/kernel.rs","sha256":"2abb8c094b36d35b364e74d78091d14c5d6f3d1eb6552cca3b5538dbd017ce23"},{"path":"product/runtime/auths-lifecycle/src/lib.rs","sha256":"afe5a345cd309b5a4f08ffba3170a6d7f16ff914892b3f2006d5208ed24ec736"},{"path":"product/runtime/auths-lifecycle/src/model.rs","sha256":"1af12bbeeeaa65ec02ddcebd7d2c8c92ec1e339fa40ae85b45ab9b01a722a4fa"},{"path":"product/runtime/auths-lifecycle/src/operation.rs","sha256":"78e6d05fcf5d7ea4f148032a3fa26fdfcab77eb346019effe927b08e0d64d732"},{"path":"product/runtime/auths-lifecycle/src/registry.rs","sha256":"53495fe6f7a77422593a41623e28716f1c140dcc1e00f87f6b0ffbfb93a5ef90"},{"path":"product/runtime/auths-lifecycle/src/sealed.rs","sha256":"2e0c03b5813c926c159598bb7890d1523825edbe57cd687d42a5dfb3374a0c19"},{"path":"product/runtime/auths-lifecycle/src/test_support.rs","sha256":"221d9a5c5ef8e1f9f8fd66927484eaf813571d0568470278ecd8fa08a5eec8cd"},{"path":"product/runtime/auths-lifecycle/src/transition.rs","sha256":"011805a28efdd541f44ccea54dd0e34a1e58f4004447ee58013703b4fb6b2822"},{"path":"product/runtime/auths-runtime/Cargo.toml","sha256":"dd29d80a8b4bb56c869f036a6c9998f6e6d1c0383ac5dc03fa42b24abe2a7ff7"},{"path":"product/runtime/auths-runtime/src/lib.rs","sha256":"132ca03d58c14905d3a822a4972f42a22a5ad33a45f2ba9ca44f3a57d810b4b0"},{"path":"product/runtime/auths-runtime/src/production.rs","sha256":"fd4eff4270c571c10fcff6cf27df28961ebf074de8a1a028f500fda1ca376820"},{"path":"product/sdk/auths-approval-quorum/Cargo.toml","sha256":"df904971fca87a24194c5816738a331588fe8f164acb5d70839a35dca5f57114"},{"path":"product/sdk/auths-approval-quorum/src/lib.rs","sha256":"72e4086088a1c0912e4e1a9e980f26a5c280bf5ab16ea39c9f0f58d5096ac2ce"},{"path":"product/sdk/auths-approval-quorum/src/remote.rs","sha256":"9fa029c7c63003adf260f8aec55160c545681c60c1bace0d934e7525862aac7b"},{"path":"product/sdk/auths-approval-quorum/src/remote_tests.rs","sha256":"8a09ce17cfee82a035a74edd535f3ebeb3db0e078784740d3997b17dbdb10197"},{"path":"product/sdk/auths-approval-quorum/src/tests.rs","sha256":"0acbf12be3e497dcc6c2d8f29c9af3b1a7ed8e11b75f6399570d4f217a785060"},{"path":"product/stores/auths-stores/Cargo.toml","sha256":"a32c4b76d17b264be5d40d24497ff237e1ed87822e8bab86229b3db93106dbe3"},{"path":"product/stores/auths-stores/src/gateway_attempt.rs","sha256":"218841602d3d9b23b44625f50e5b54cf275ccedc2d5c89f02d2482b8524472af"},{"path":"product/stores/auths-stores/src/lib.rs","sha256":"e721262edf8a9ab5568ddc27639176312d4a366203b5f73e2d7c11fde2c554e9"},{"path":"product/stores/auths-stores/src/lifecycle.rs","sha256":"3f2cecfda13fdcd7c4a944518646bcc8abd1237f900c0332d5822281f8f9f1cd"}],"schema":"auths.gateway-semantic-closure/1"} \ No newline at end of file diff --git a/product/runtime/auths-gateway/src/bin/auths-gateway.rs b/product/runtime/auths-gateway/src/bin/auths-gateway.rs index 221f02f6f..385ab665f 100644 --- a/product/runtime/auths-gateway/src/bin/auths-gateway.rs +++ b/product/runtime/auths-gateway/src/bin/auths-gateway.rs @@ -817,24 +817,6 @@ mod unix { && !cfg!(feature = "testkit-production-plaintext") } - /// Opens the credential store the settings select, under the - /// deployment's policy. `unavailable` is the caller's code for a store - /// that is selected and permitted but cannot be opened. - fn open_credentials( - state_dir: &Path, - settings: &CredentialStoreSettings, - deployment: Deployment, - unavailable: &'static str, - ) -> Result, &'static str> { - open_credentials_for( - state_dir, - settings, - deployment, - unavailable, - CredentialAccess::Runtime, - ) - } - #[derive(Clone, Copy, Eq, PartialEq)] enum CredentialAccess { Runtime, @@ -1332,11 +1314,15 @@ mod unix { .map_err(|_| "gateway.install.attempt-store-unavailable")? .map_err(|_| "gateway.install.attempt-store-unavailable")? }; - let credentials = open_credentials( + // Installation writes custody and a join reads the stored commitment. + // Use the same separated writer/reader identities as administration; + // the operator role must not acquire GetSecretValue permission. + let credentials = open_credentials_for( &state_dir, &manifest.credential_store, deployment, "gateway.install.credential-store-unavailable", + CredentialAccess::Operator, )?; let shared = SharedConnection::new(attempts.store(), provider.clone(), alias.clone()); if join { diff --git a/product/runtime/auths-gateway/src/semantic_closure.rs b/product/runtime/auths-gateway/src/semantic_closure.rs index 83c7af04c..ab5aaccab 100644 --- a/product/runtime/auths-gateway/src/semantic_closure.rs +++ b/product/runtime/auths-gateway/src/semantic_closure.rs @@ -10,7 +10,7 @@ /// SHA-256 of the schema, a NUL byte, and `semantic-closure.json`. /// Regenerate through `semantic_closure_is_current` with `AUTHS_UPDATE_FIXTURES=1`. pub const GATEWAY_SEMANTIC_CLOSURE_SHA256: &str = - "e493fbb956c834cb3ae5cc20c6b33dfadb18d0343e81fcb9171956814dde3997"; + "463b30c37a0e608fab12ce63f512896ebde9592a5aa48f2417e02e284e775ee8"; #[cfg(test)] mod tests { diff --git a/qualification/families/airtable-record-update-v1/contract.json b/qualification/families/airtable-record-update-v1/contract.json index bab07c010..33c390828 100644 --- a/qualification/families/airtable-record-update-v1/contract.json +++ b/qualification/families/airtable-record-update-v1/contract.json @@ -1 +1 @@ -{"api_release":"web-api-v0-reviewed-2026-10-07","corpus_manifest_sha256":"afe21d0fe8ab6acd3da2a9c03e5b193b7013e8e1cbf922ab0716a22ea65eaff2","declarations":{"idempotency_sha256":"74234e98afe7498fb5daf1f36ac2d78acc339464f950703b8c019892f982b90b","observation_sha256":"9dd79dd204fa13a2df3c667d106c66c0526d174a2c018631e2b2f6b897eaf311","recovery_sha256":"7081a92b4cd2d13dab5e7c30e640675a252b62bca20d340e14d62d9c8c048eca","retention_sha256":"4a4b5048c97b16e041af55b032c0b8ac20f5142c4bbcbf31b31c6674770a70d0"},"environment_class":"disposable-live-resources","manual_assumptions":["Airtable supplies no idempotency key for this PATCH; durable gateway admission prevents a second entry.","Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only a fresh GET with the exact replacement and echo can reconcile a lost response.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths.","The reviewed fixed Airtable base and table contain only owner-authorized disposable qualification records."],"oracle_version":"auths-reviewed-reference-v2","provider":"airtable","schema":"auths.provider-contract/1"} \ No newline at end of file +{"api_release":"web-api-v0-reviewed-2026-10-07","corpus_manifest_sha256":"f5766ef74aaf21c98e6fad9d00dc54fade2cae8a82209ffe28dc79828a56b645","declarations":{"idempotency_sha256":"74234e98afe7498fb5daf1f36ac2d78acc339464f950703b8c019892f982b90b","observation_sha256":"9dd79dd204fa13a2df3c667d106c66c0526d174a2c018631e2b2f6b897eaf311","recovery_sha256":"7081a92b4cd2d13dab5e7c30e640675a252b62bca20d340e14d62d9c8c048eca","retention_sha256":"4a4b5048c97b16e041af55b032c0b8ac20f5142c4bbcbf31b31c6674770a70d0"},"environment_class":"disposable-live-resources","manual_assumptions":["Airtable supplies no idempotency key for this PATCH; durable gateway admission prevents a second entry.","Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only a fresh GET with the exact replacement and echo can reconcile a lost response.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths.","The reviewed fixed Airtable base and table contain only owner-authorized disposable qualification records."],"oracle_version":"auths-reviewed-reference-v2","provider":"airtable","schema":"auths.provider-contract/1"} \ No newline at end of file diff --git a/qualification/families/airtable-record-update-v1/corpus-manifest.json b/qualification/families/airtable-record-update-v1/corpus-manifest.json index e2298c6d3..82b227cd9 100644 --- a/qualification/families/airtable-record-update-v1/corpus-manifest.json +++ b/qualification/families/airtable-record-update-v1/corpus-manifest.json @@ -1 +1 @@ -{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"32241d9b4811a55abcdd224ef567df3857dbec34d761ef7a35d1044cdfa52d9f","family":"airtable-record-update-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"af7f984509ab11a3676cacc85eda2fa638c25bf91f7bfedf3ff3c119e47f3c41","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"e58dc84b60f5ff13e5c7b1b5aae4917c5427f31cc8ac041acdd85defc8cd5e92","family_harness.py":"bd8474b88f5e7f8869c0470bfa4e09ba159c3e9d8b3a4ea2f2404938d8980d6f","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"4896a5f16474cbb418decb719bcc2af4a08483eabeca996427b40560a16d02cf","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","resource_io.py":"025139a787f50f5181e390ea58da45db00dbdef15c8b3928cba9e0485945f6fe","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489"},"source_recipe_sha256":"c0f21ff1d3c8e344fee20a9a0c25bb14a264417ed53418ad536789a6096fb16e"} \ No newline at end of file +{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"32241d9b4811a55abcdd224ef567df3857dbec34d761ef7a35d1044cdfa52d9f","family":"airtable-record-update-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"af7f984509ab11a3676cacc85eda2fa638c25bf91f7bfedf3ff3c119e47f3c41","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"e58dc84b60f5ff13e5c7b1b5aae4917c5427f31cc8ac041acdd85defc8cd5e92","family_harness.py":"bd8474b88f5e7f8869c0470bfa4e09ba159c3e9d8b3a4ea2f2404938d8980d6f","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"4896a5f16474cbb418decb719bcc2af4a08483eabeca996427b40560a16d02cf","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","production_setup.py":"a9fbbb1d65fac43fdfef25ccae806a783014a3e4bdf9ec74398e7bd2726fc9c4","resource_io.py":"025139a787f50f5181e390ea58da45db00dbdef15c8b3928cba9e0485945f6fe","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489"},"source_recipe_sha256":"c0f21ff1d3c8e344fee20a9a0c25bb14a264417ed53418ad536789a6096fb16e"} \ No newline at end of file diff --git a/qualification/families/stripe-platform-refund-v1/contract.json b/qualification/families/stripe-platform-refund-v1/contract.json index b93732b40..0d2b85913 100644 --- a/qualification/families/stripe-platform-refund-v1/contract.json +++ b/qualification/families/stripe-platform-refund-v1/contract.json @@ -1 +1 @@ -{"api_release":"2025-03-31.basil","corpus_manifest_sha256":"0c323df2b3a790243fe347e019a093547002842605441f2b07168363d18fcb66","declarations":{"idempotency_sha256":"425a0dca2f279765debfc847c4a01bff60fea5be68dd9d761ae6bb60ce0b8a7b","observation_sha256":"d0ce5a34d987821c69c0a839d9ed66805c625f8324dd42031fcccf0752a8821e","recovery_sha256":"bf2303abce165c175360ac975586431bbc4cf03167489ea317a27de2f0b04abb","retention_sha256":"846c2164e26d1144d9aa146034b4f7ea4dc305136a59ffd94f999d19f2c360ee"},"environment_class":"provider-test-mode","manual_assumptions":["Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","Stripe idempotency is tested only inside the declared 86400-second retention interval.","Stripe test mode and the installed platform are checked by the declared guard on each lease.","The 50-percent payment basis is a read, not an atomic provider balance reservation.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths."],"oracle_version":"auths-reviewed-reference-v2","provider":"stripe","schema":"auths.provider-contract/1"} \ No newline at end of file +{"api_release":"2025-03-31.basil","corpus_manifest_sha256":"35af5f48b56f2ff8b0fec798938523d2a94a27107ee86f47b5d7fdfbf4e72fc9","declarations":{"idempotency_sha256":"425a0dca2f279765debfc847c4a01bff60fea5be68dd9d761ae6bb60ce0b8a7b","observation_sha256":"d0ce5a34d987821c69c0a839d9ed66805c625f8324dd42031fcccf0752a8821e","recovery_sha256":"bf2303abce165c175360ac975586431bbc4cf03167489ea317a27de2f0b04abb","retention_sha256":"846c2164e26d1144d9aa146034b4f7ea4dc305136a59ffd94f999d19f2c360ee"},"environment_class":"provider-test-mode","manual_assumptions":["Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","Stripe idempotency is tested only inside the declared 86400-second retention interval.","Stripe test mode and the installed platform are checked by the declared guard on each lease.","The 50-percent payment basis is a read, not an atomic provider balance reservation.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths."],"oracle_version":"auths-reviewed-reference-v2","provider":"stripe","schema":"auths.provider-contract/1"} \ No newline at end of file diff --git a/qualification/families/stripe-platform-refund-v1/corpus-manifest.json b/qualification/families/stripe-platform-refund-v1/corpus-manifest.json index 038257e8c..9066f7ee0 100644 --- a/qualification/families/stripe-platform-refund-v1/corpus-manifest.json +++ b/qualification/families/stripe-platform-refund-v1/corpus-manifest.json @@ -1 +1 @@ -{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"a72c557b69103a52eb477deb8364ded53cd58407b9ba7ab33ccbda74389fec1e","family":"stripe-platform-refund-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"99901e36cb7c4f5882897603c874698d582e859b5d6b08d53cd80975e89aa01c","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"e58dc84b60f5ff13e5c7b1b5aae4917c5427f31cc8ac041acdd85defc8cd5e92","family_harness.py":"bd8474b88f5e7f8869c0470bfa4e09ba159c3e9d8b3a4ea2f2404938d8980d6f","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"4896a5f16474cbb418decb719bcc2af4a08483eabeca996427b40560a16d02cf","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","resource_io.py":"025139a787f50f5181e390ea58da45db00dbdef15c8b3928cba9e0485945f6fe","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489"},"source_recipe_sha256":"b1972d556f28433932a449636755077f7ee485ef90cca412f153bc7f18881368"} \ No newline at end of file +{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"a72c557b69103a52eb477deb8364ded53cd58407b9ba7ab33ccbda74389fec1e","family":"stripe-platform-refund-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"99901e36cb7c4f5882897603c874698d582e859b5d6b08d53cd80975e89aa01c","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"e58dc84b60f5ff13e5c7b1b5aae4917c5427f31cc8ac041acdd85defc8cd5e92","family_harness.py":"bd8474b88f5e7f8869c0470bfa4e09ba159c3e9d8b3a4ea2f2404938d8980d6f","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"4896a5f16474cbb418decb719bcc2af4a08483eabeca996427b40560a16d02cf","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","production_setup.py":"a9fbbb1d65fac43fdfef25ccae806a783014a3e4bdf9ec74398e7bd2726fc9c4","resource_io.py":"025139a787f50f5181e390ea58da45db00dbdef15c8b3928cba9e0485945f6fe","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489"},"source_recipe_sha256":"b1972d556f28433932a449636755077f7ee485ef90cca412f153bc7f18881368"} \ No newline at end of file diff --git a/qualification/reference/README.md b/qualification/reference/README.md index fb8d8b0ed..04c5cdcb2 100644 --- a/qualification/reference/README.md +++ b/qualification/reference/README.md @@ -257,3 +257,13 @@ with the native SDK verifier. The offline family job produces these actual installation statements and checks that their operator differs from every packet actor. This proves technical separation by key; production install verification and human review are not claimed by its report. + +`production_setup.py` is the private controller for four real installations +(two process hosts and two exact challenge contexts). It binds the executable +bytes before install, requires the production PostgreSQL/TLS and AWS settings, +uses the operator writer and distinct runtime reader for install/join, and +checks each installed tuple byte-for-byte. Serving processes receive only the +runtime role. Private state, token paths and database credentials stay outside +publication; native counters come from the running process's admin socket. +The complete protected journey still needs to connect this controller to +resource preparation, mailbox exchanges and the family operations. diff --git a/qualification/reference/generate_families.py b/qualification/reference/generate_families.py index df1afa325..925b0f13a 100644 --- a/qualification/reference/generate_families.py +++ b/qualification/reference/generate_families.py @@ -17,7 +17,7 @@ ROOT = Path(__file__).resolve().parents[2] REFERENCE = ROOT / 'qualification/reference' SOURCES_TO_PIN = ['family_corpus.py', 'family_harness.py', 'packet_plan.py', - 'author_packets.py', 'author_socket.py', 'author_operator.py', 'common.py', 'fresh_evidence.py', + 'author_packets.py', 'author_socket.py', 'author_operator.py', 'production_setup.py', 'common.py', 'fresh_evidence.py', 'native_observation.py', 'measure.py', 'resource_io.py', 'resource_summary.py', 'expand.py', 'stripe_platform.py', 'airtable_record.py', 'stripe_resources.py', 'airtable_resources.py'] diff --git a/qualification/reference/production_setup.py b/qualification/reference/production_setup.py new file mode 100644 index 000000000..3f79f622d --- /dev/null +++ b/qualification/reference/production_setup.py @@ -0,0 +1,199 @@ +"""Source-owned production installation and process custody for qualification. + +This controller requires a real TLS database and existing web-identity token +files. It provisions no IAM grants and offers no development-store fallback. +Provider arguments, recipe identity and results remain owned by the two family +references and the shipping gateway. Nothing here issues an observation. +""" + +import os +from pathlib import Path +import re +import signal +import stat +import subprocess +import time + +from author_operator import ALIAS +from common import closed, require, sha256 +from expand import decode, read +from resource_io import write_bytes + +GATEWAY_UID = 62001 +APPLICATION_UID = 62004 +REGION = 'eu-west-1' +ROLE_PREFIX = 'arn:aws:iam::585985124542:role/auths-gateway-custody-' +OPERATOR_ROLE = ROLE_PREFIX + 'operator' +RUNTIME_ROLE = ROLE_PREFIX + 'runtime' +KMS_KEY = 'arn:aws:kms:eu-west-1:585985124542:key/1e1c85ae-7d9c-4f2d-978f-bd672b597907' +DATABASE_ENV = ['AUTHS_POSTGRES_URL', 'AUTHS_POSTGRES_CA_PEM', 'AUTHS_POSTGRES_SERVER_NAME'] + + +def private_file(path, owner): + path = Path(path).absolute() + info = os.lstat(path) + require(stat.S_ISREG(info.st_mode) and info.st_nlink == 1 and info.st_uid == owner + and stat.S_IMODE(info.st_mode) == 0o600, + 'qualification.production.private-input') + # Native state paths reject symlinked ancestors as well as symlinked files. + require(all(not parent.is_symlink() for parent in [path, *path.parents]), + 'qualification.production.private-input') + return path + + +def native_output(result, canaries, *, required=True, json_output=True): + require(len(result.stdout) <= 65536 and len(result.stderr) <= 65536, + 'qualification.production.output-bound') + require(all(value not in result.stdout + result.stderr for value in canaries), + 'qualification.production.secret-exposed') + if required and result.returncode != 0: + # A native refusal keeps its stable code, never its external details. + match = re.match(rb'(gateway\.[a-z0-9.-]{1,128})(?:\s|$)', result.stderr) + require(False, 'qualification.production.' + (match[1].decode() if match else 'native-refused')) + if result.returncode != 0: + return None + return decode(result.stdout) if json_output else result.stdout + + +class Deployment: + def __init__(self, binary, work, private, environment, canaries): + require(os.name == 'posix' and os.getuid() == 0, + 'qualification.production.controller-identity') + self.binary, self.work, self.private = Path(binary).absolute(), Path(work).absolute(), Path(private).absolute() + self.tuple = decode(read(self.work / 'tuple.json', 65536)) + require(sha256(read(self.binary, 256 * 1024 * 1024)) == self.tuple['target']['gateway_build_sha256'], + 'qualification.production.candidate-bytes') + require(not self.private.exists() and not self.private.is_relative_to(self.work), + 'qualification.production.private-directory') + self.private.mkdir(mode=0o711) + self.gateway = self.private / 'gateway' + self.gateway.mkdir(mode=0o700) + self.sockets = self.private / 'sockets' + self.sockets.mkdir(mode=0o750) + os.chown(self.sockets, GATEWAY_UID, GATEWAY_UID) + self.canaries = list(canaries) + require(self.canaries and all(type(value) is bytes and len(value) >= 8 for value in self.canaries), + 'qualification.production.canaries') + self.database = {} + for name in DATABASE_ENV: + value = environment[name] + require(type(value) is str and 0 < len(value) <= 8192 and '\n' not in value and '\0' not in value, + 'qualification.production.database-input') + self.database[name] = value + require('sslmode=require' in self.database['AUTHS_POSTGRES_URL'], + 'qualification.production.database-tls') + ca = Path(self.database['AUTHS_POSTGRES_CA_PEM']).absolute() + write_bytes(self.gateway / 'postgres-ca.pem', read(ca, 65536), new=True) + os.chown(self.gateway / 'postgres-ca.pem', GATEWAY_UID, GATEWAY_UID) + self.database['AUTHS_POSTGRES_CA_PEM'] = str(self.gateway / 'postgres-ca.pem') + self.operator_token = private_file(environment['AUTHS_QUALIFICATION_OPERATOR_TOKEN_FILE'], GATEWAY_UID) + self.runtime_token = private_file(environment['AUTHS_QUALIFICATION_RUNTIME_TOKEN_FILE'], GATEWAY_UID) + require(not self.operator_token.is_relative_to(self.work) + and not self.runtime_token.is_relative_to(self.work), + 'qualification.production.private-input') + self.namespace = environment['AUTHS_QUALIFICATION_CREDENTIAL_NAMESPACE'] + require(re.fullmatch(r'live-[1-9][0-9]{0,19}-[1-9][0-9]{0,9}', self.namespace) is not None, + 'qualification.production.namespace') + carrier = decode(read(self.work / 'public-packets.json', 65536)) + require(carrier['trusted_contexts'] == ['context-0.cbor', 'context-1.cbor'], + 'qualification.production.contexts') + family = self.tuple['recipe_family'] + require(family in ['stripe-platform-refund-v1', 'airtable-record-update-v1'], + 'qualification.production.family') + self.provider = 'stripe' if family == 'stripe-platform-refund-v1' else 'airtable' + for name in ['recipe.json', 'profile.lock.json', *carrier['trusted_contexts'], + *[context + '.operator.json' for context in carrier['trusted_contexts']]]: + path = self.gateway / name + write_bytes(path, read(self.work / name, 4 * 1024 * 1024), new=True) + os.chown(path, GATEWAY_UID, GATEWAY_UID) + os.chown(self.gateway, GATEWAY_UID, GATEWAY_UID) + self.processes = {} + + def environment(self, administrative=False): + return {'PATH': '/usr/bin:/bin', **self.database, + 'AWS_ROLE_ARN': OPERATOR_ROLE if administrative else RUNTIME_ROLE, + 'AWS_WEB_IDENTITY_TOKEN_FILE': str(self.operator_token if administrative else self.runtime_token), + **({'AUTHS_GATEWAY_RUNTIME_ROLE_ARN': RUNTIME_ROLE, + 'AUTHS_GATEWAY_RUNTIME_TOKEN_FILE': str(self.runtime_token)} if administrative else {})} + + def command(self, arguments, *, administrative=False, secret=b'', required=True, json_output=True): + result = subprocess.run([str(self.binary), *map(str, arguments)], + input=secret, capture_output=True, timeout=90, cwd=self.gateway, + user=GATEWAY_UID, group=GATEWAY_UID, extra_groups=[], env=self.environment(administrative)) + return native_output(result, self.canaries, required=required, json_output=json_output) + + def state(self, host, context=0): + require(host in [0, 1] and context in [0, 1], 'qualification.production.host') + return self.gateway / ('host-' + str(host) + '-context-' + str(context)) + + def app_socket(self, host, context=0): + self.state(host, context) + return self.sockets / ('h' + str(host) + 'c' + str(context) + '.sock') + + def install(self, credential, account): + require(type(credential) is bytes and credential in self.canaries + and b'\n' not in credential and b'\0' not in credential, + 'qualification.production.credential-input') + for context in [0, 1]: + for host in [0, 1]: + state = self.state(host, context) + state.mkdir(mode=0o700) + os.chown(state, GATEWAY_UID, GATEWAY_UID) + trust = 'context-' + str(context) + '.cbor' + arguments = ['install', '--state-dir', state, + '--recipe', self.gateway / 'recipe.json', '--profile-lock', self.gateway / 'profile.lock.json', + '--trusted-context', self.gateway / trust, '--approve-digest', self.tuple['compiled_recipe_sha256'], + '--provider', self.provider, '--alias', ALIAS, '--credential-stdin', + '--deployment', 'production', '--operator-attestation', self.gateway / (trust + '.operator.json'), + '--credential-store', 'aws-secrets-manager-v1', '--credential-namespace', self.namespace, + '--aws-region', REGION, '--aws-kms-key', KMS_KEY, '--aws-identity', 'web-identity', + '--qualification-policy', 'required', '--recipe-family', self.tuple['recipe_family'], + '--provider-contract-id', self.tuple['provider_contract_id']] + arguments += ['--account-label', account] if host == context == 0 else ['--join'] + output = self.command(arguments, administrative=True, secret=credential + b'\n', json_output=False) + expected = ('installed' if host == context == 0 else 'joined') + ' recipe ' \ + + self.tuple['compiled_recipe_sha256'] + ' with separate gateway credential custody\n' + require(output == expected.encode(), 'qualification.production.install-output') + actual = self.command(['qualification-status', '--state-dir', state, '--tuple']) + require(actual == self.tuple, 'qualification.production.installed-tuple') + + def start(self, host, context=0): + key = (host, context) + require(key not in self.processes, 'qualification.production.host-running') + state, endpoint = self.state(host, context), self.app_socket(host, context) + require(len(str(endpoint).encode()) <= 107, 'qualification.production.socket-bound') + process = subprocess.Popen([str(self.binary), 'serve', '--state-dir', str(state), + '--app-socket', str(endpoint)], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, + cwd=self.gateway, user=GATEWAY_UID, group=GATEWAY_UID, extra_groups=[], env=self.environment()) + self.processes[key] = process + deadline = time.monotonic() + 30 + while process.poll() is None and time.monotonic() < deadline: + if endpoint.exists(): + self.witness(host, context) + return + time.sleep(0.05) + require(False, 'qualification.production.gateway-not-ready') + + def stop(self, host, context=0, *, crash=False): + process = self.processes.pop((host, context), None) + require(process is not None and process.poll() is None, 'qualification.production.gateway-not-running') + process.send_signal(signal.SIGKILL if crash else signal.SIGTERM) + try: + process.wait(timeout=30) + except subprocess.TimeoutExpired: + process.kill() + process.wait(timeout=5) + require(False, 'qualification.production.gateway-stop-timeout') + require(process.returncode == (-signal.SIGKILL if crash else 0), + 'qualification.production.gateway-stop-result') + + def witness(self, host, context=0): + from measure import snapshot + result = self.command(['execution-witness', '--state-dir', self.state(host, context)]) + closed(result, ['schema', 'ok', 'code', 'execution_witness']) + require(result['ok'] is True, 'qualification.production.witness-unavailable') + return snapshot(result['execution_witness']) + + def close(self): + for host, context in list(self.processes): + self.stop(host, context) diff --git a/qualification/reference/tests/test_production_setup.py b/qualification/reference/tests/test_production_setup.py new file mode 100644 index 000000000..cc048e2c0 --- /dev/null +++ b/qualification/reference/tests/test_production_setup.py @@ -0,0 +1,66 @@ +"""Private process boundaries, without credentials or provider evidence.""" + +import os +from pathlib import Path +import subprocess +import sys +import tempfile +import unittest + +sys.path.insert(0, str(Path(__file__).resolve().parents[1])) +from common import Refusal +import production_setup as setup + + +class Production(unittest.TestCase): + def deployment(self): + value = object.__new__(setup.Deployment) + value.database = {'AUTHS_POSTGRES_URL': 'synthetic-only sslmode=require', + 'AUTHS_POSTGRES_CA_PEM': '/synthetic-only-ca', 'AUTHS_POSTGRES_SERVER_NAME': 'localhost'} + value.operator_token = Path('/synthetic-only-operator-token') + value.runtime_token = Path('/synthetic-only-runtime-token') + return value + + def test_runtime_cannot_inherit_writer_identity_or_ambient_credentials(self): + value = self.deployment() + environment = value.environment() + self.assertEqual(environment['AWS_ROLE_ARN'], setup.RUNTIME_ROLE) + self.assertEqual(environment['AWS_WEB_IDENTITY_TOKEN_FILE'], str(value.runtime_token)) + self.assertEqual(set(environment), {'PATH', 'AWS_ROLE_ARN', 'AWS_WEB_IDENTITY_TOKEN_FILE', *setup.DATABASE_ENV}) + operator = value.environment(administrative=True) + self.assertEqual(operator['AWS_ROLE_ARN'], setup.OPERATOR_ROLE) + self.assertEqual(operator['AUTHS_GATEWAY_RUNTIME_ROLE_ARN'], setup.RUNTIME_ROLE) + self.assertEqual(operator['AUTHS_GATEWAY_RUNTIME_TOKEN_FILE'], str(value.runtime_token)) + self.assertNotEqual(operator['AWS_ROLE_ARN'], operator['AUTHS_GATEWAY_RUNTIME_ROLE_ARN']) + + def test_native_refusal_never_exports_an_external_detail_or_secret(self): + refused = subprocess.CompletedProcess([], 1, b'', + b'gateway.install.credential-store-unavailable private-external-detail') + with self.assertRaisesRegex(Refusal, '^qualification.production.gateway.install.credential-store-unavailable$'): + setup.native_output(refused, [b'synthetic-only-sensitive-value']) + leaked = subprocess.CompletedProcess([], 0, b'{"secret":"synthetic-only-sensitive-value"}', b'') + with self.assertRaisesRegex(Refusal, 'secret-exposed'): + setup.native_output(leaked, [b'synthetic-only-sensitive-value']) + with self.assertRaisesRegex(Refusal, 'output-bound'): + setup.native_output(subprocess.CompletedProcess([], 0, b'x' * 65537, b''), []) + + def test_private_identity_inputs_refuse_links_wrong_owner_and_readable_files(self): + with tempfile.TemporaryDirectory() as directory: + path = Path(directory).resolve() / 'token' + path.write_bytes(b'synthetic-only-token') + path.chmod(0o600) + self.assertEqual(setup.private_file(path, os.getuid()), path) + linked = path.with_name('linked') + linked.symlink_to(path) + with self.assertRaises(Refusal): setup.private_file(linked, os.getuid()) + hardlinked = path.with_name('hardlinked') + os.link(path, hardlinked) + with self.assertRaises(Refusal): setup.private_file(path, os.getuid()) + hardlinked.unlink() + with self.assertRaises(Refusal): setup.private_file(path, os.getuid() + 1) + path.chmod(0o644) + with self.assertRaises(Refusal): setup.private_file(path, os.getuid()) + + +if __name__ == '__main__': + unittest.main() From 6c1e84f27c1540c5a23b78ea85766f5789bc824f Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 16:14:56 +0100 Subject: [PATCH 088/108] Connect protected operation handlers to measured native execution and independent reads --- .github/workflows/recipe-qualification.yml | 5 + .../airtable-record-update-v1/contract.json | 2 +- .../corpus-manifest.json | 2 +- .../stripe-platform-refund-v1/contract.json | 2 +- .../corpus-manifest.json | 2 +- qualification/reference/README.md | 18 ++ qualification/reference/controller_socket.py | 129 +++++++++++ qualification/reference/family_harness.py | 9 +- qualification/reference/family_operations.py | 204 ++++++++++++++++++ qualification/reference/generate_families.py | 7 +- qualification/reference/installed_submit.py | 34 +++ qualification/reference/production_setup.py | 155 ++++++++++++- qualification/reference/provider_readback.py | 59 +++++ qualification/reference/resource_io.py | 21 +- .../reference/tests/test_controller_socket.py | 79 +++++++ .../reference/tests/test_provider_readback.py | 82 +++++++ 16 files changed, 795 insertions(+), 15 deletions(-) create mode 100644 qualification/reference/controller_socket.py create mode 100644 qualification/reference/family_operations.py create mode 100644 qualification/reference/installed_submit.py create mode 100644 qualification/reference/provider_readback.py create mode 100644 qualification/reference/tests/test_controller_socket.py create mode 100644 qualification/reference/tests/test_provider_readback.py diff --git a/.github/workflows/recipe-qualification.yml b/.github/workflows/recipe-qualification.yml index a0f2884ca..83dd3a1c4 100644 --- a/.github/workflows/recipe-qualification.yml +++ b/.github/workflows/recipe-qualification.yml @@ -147,6 +147,11 @@ jobs: --report "${RUNNER_TEMP}/socket-report/report.json" sudo -n cp "${RUNNER_TEMP}/socket-report/report.json" "${RUNNER_TEMP}/packet-operator/socket-report.json" sudo -n chown "$(id -u):$(id -g)" "${RUNNER_TEMP}/packet-operator/socket-report.json" + - name: Exercise the private root controller transport without credentials + shell: bash + run: | + sudo -n /opt/auths-packet-consumer/bin/python -B -m unittest discover \ + -s /opt/auths-packet-kit/qualification/reference/tests -p test_controller_socket.py - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: name: qualification-packet-author-${{ github.run_id }}-${{ github.run_attempt }} diff --git a/qualification/families/airtable-record-update-v1/contract.json b/qualification/families/airtable-record-update-v1/contract.json index 33c390828..75bcf5279 100644 --- a/qualification/families/airtable-record-update-v1/contract.json +++ b/qualification/families/airtable-record-update-v1/contract.json @@ -1 +1 @@ -{"api_release":"web-api-v0-reviewed-2026-10-07","corpus_manifest_sha256":"f5766ef74aaf21c98e6fad9d00dc54fade2cae8a82209ffe28dc79828a56b645","declarations":{"idempotency_sha256":"74234e98afe7498fb5daf1f36ac2d78acc339464f950703b8c019892f982b90b","observation_sha256":"9dd79dd204fa13a2df3c667d106c66c0526d174a2c018631e2b2f6b897eaf311","recovery_sha256":"7081a92b4cd2d13dab5e7c30e640675a252b62bca20d340e14d62d9c8c048eca","retention_sha256":"4a4b5048c97b16e041af55b032c0b8ac20f5142c4bbcbf31b31c6674770a70d0"},"environment_class":"disposable-live-resources","manual_assumptions":["Airtable supplies no idempotency key for this PATCH; durable gateway admission prevents a second entry.","Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only a fresh GET with the exact replacement and echo can reconcile a lost response.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths.","The reviewed fixed Airtable base and table contain only owner-authorized disposable qualification records."],"oracle_version":"auths-reviewed-reference-v2","provider":"airtable","schema":"auths.provider-contract/1"} \ No newline at end of file +{"api_release":"web-api-v0-reviewed-2026-10-07","corpus_manifest_sha256":"8cb0d845f97fa5ce02e8a18d5c4dfbf43328d08a91a3a8d9d5202f300b355ad6","declarations":{"idempotency_sha256":"74234e98afe7498fb5daf1f36ac2d78acc339464f950703b8c019892f982b90b","observation_sha256":"9dd79dd204fa13a2df3c667d106c66c0526d174a2c018631e2b2f6b897eaf311","recovery_sha256":"7081a92b4cd2d13dab5e7c30e640675a252b62bca20d340e14d62d9c8c048eca","retention_sha256":"4a4b5048c97b16e041af55b032c0b8ac20f5142c4bbcbf31b31c6674770a70d0"},"environment_class":"disposable-live-resources","manual_assumptions":["Airtable supplies no idempotency key for this PATCH; durable gateway admission prevents a second entry.","Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only a fresh GET with the exact replacement and echo can reconcile a lost response.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths.","The reviewed fixed Airtable base and table contain only owner-authorized disposable qualification records."],"oracle_version":"auths-reviewed-reference-v2","provider":"airtable","schema":"auths.provider-contract/1"} \ No newline at end of file diff --git a/qualification/families/airtable-record-update-v1/corpus-manifest.json b/qualification/families/airtable-record-update-v1/corpus-manifest.json index 82b227cd9..8f2195951 100644 --- a/qualification/families/airtable-record-update-v1/corpus-manifest.json +++ b/qualification/families/airtable-record-update-v1/corpus-manifest.json @@ -1 +1 @@ -{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"32241d9b4811a55abcdd224ef567df3857dbec34d761ef7a35d1044cdfa52d9f","family":"airtable-record-update-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"af7f984509ab11a3676cacc85eda2fa638c25bf91f7bfedf3ff3c119e47f3c41","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"e58dc84b60f5ff13e5c7b1b5aae4917c5427f31cc8ac041acdd85defc8cd5e92","family_harness.py":"bd8474b88f5e7f8869c0470bfa4e09ba159c3e9d8b3a4ea2f2404938d8980d6f","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"4896a5f16474cbb418decb719bcc2af4a08483eabeca996427b40560a16d02cf","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","production_setup.py":"a9fbbb1d65fac43fdfef25ccae806a783014a3e4bdf9ec74398e7bd2726fc9c4","resource_io.py":"025139a787f50f5181e390ea58da45db00dbdef15c8b3928cba9e0485945f6fe","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489"},"source_recipe_sha256":"c0f21ff1d3c8e344fee20a9a0c25bb14a264417ed53418ad536789a6096fb16e"} \ No newline at end of file +{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"32241d9b4811a55abcdd224ef567df3857dbec34d761ef7a35d1044cdfa52d9f","family":"airtable-record-update-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"af7f984509ab11a3676cacc85eda2fa638c25bf91f7bfedf3ff3c119e47f3c41","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","controller_socket.py":"742852974870a925c7f0cf995eadb729149463b5163f2273bada6c1f2e3cfa8c","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"e58dc84b60f5ff13e5c7b1b5aae4917c5427f31cc8ac041acdd85defc8cd5e92","family_harness.py":"ed0136600a25c9f12bdcca73b105c3968271ccd227f42ad03a884cf5b9430de6","family_operations.py":"f6f7e54714228af7b48f2691c4ee15b5b2b34ebd5eb7b19dab61d26734bf7ce5","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","installed_submit.py":"f78b91ca7c57ea6909793973ca63fb33f18589ac8acbcb15e8886511e3d6fc50","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"4896a5f16474cbb418decb719bcc2af4a08483eabeca996427b40560a16d02cf","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","production_setup.py":"795f47b92d806171e866510b75557bb6ece1fd1d14f6f51bf5330c25bbf80519","provider_readback.py":"d576768208985b3544f146597d181d796f2a5e2eca5026dae3fa15cadcfe65b2","resource_io.py":"b0ed0223fd11a1a28c25278de539a9b2ed63881b26a8e00e386f25d4d9aa9384","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489"},"source_recipe_sha256":"c0f21ff1d3c8e344fee20a9a0c25bb14a264417ed53418ad536789a6096fb16e"} \ No newline at end of file diff --git a/qualification/families/stripe-platform-refund-v1/contract.json b/qualification/families/stripe-platform-refund-v1/contract.json index 0d2b85913..7a9ffe872 100644 --- a/qualification/families/stripe-platform-refund-v1/contract.json +++ b/qualification/families/stripe-platform-refund-v1/contract.json @@ -1 +1 @@ -{"api_release":"2025-03-31.basil","corpus_manifest_sha256":"35af5f48b56f2ff8b0fec798938523d2a94a27107ee86f47b5d7fdfbf4e72fc9","declarations":{"idempotency_sha256":"425a0dca2f279765debfc847c4a01bff60fea5be68dd9d761ae6bb60ce0b8a7b","observation_sha256":"d0ce5a34d987821c69c0a839d9ed66805c625f8324dd42031fcccf0752a8821e","recovery_sha256":"bf2303abce165c175360ac975586431bbc4cf03167489ea317a27de2f0b04abb","retention_sha256":"846c2164e26d1144d9aa146034b4f7ea4dc305136a59ffd94f999d19f2c360ee"},"environment_class":"provider-test-mode","manual_assumptions":["Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","Stripe idempotency is tested only inside the declared 86400-second retention interval.","Stripe test mode and the installed platform are checked by the declared guard on each lease.","The 50-percent payment basis is a read, not an atomic provider balance reservation.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths."],"oracle_version":"auths-reviewed-reference-v2","provider":"stripe","schema":"auths.provider-contract/1"} \ No newline at end of file +{"api_release":"2025-03-31.basil","corpus_manifest_sha256":"cd5bfcb1ad030343f963d07b1284e1f6a05a30f4d79a41128dcc40cedc08af9b","declarations":{"idempotency_sha256":"425a0dca2f279765debfc847c4a01bff60fea5be68dd9d761ae6bb60ce0b8a7b","observation_sha256":"d0ce5a34d987821c69c0a839d9ed66805c625f8324dd42031fcccf0752a8821e","recovery_sha256":"bf2303abce165c175360ac975586431bbc4cf03167489ea317a27de2f0b04abb","retention_sha256":"846c2164e26d1144d9aa146034b4f7ea4dc305136a59ffd94f999d19f2c360ee"},"environment_class":"provider-test-mode","manual_assumptions":["Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","Stripe idempotency is tested only inside the declared 86400-second retention interval.","Stripe test mode and the installed platform are checked by the declared guard on each lease.","The 50-percent payment basis is a read, not an atomic provider balance reservation.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths."],"oracle_version":"auths-reviewed-reference-v2","provider":"stripe","schema":"auths.provider-contract/1"} \ No newline at end of file diff --git a/qualification/families/stripe-platform-refund-v1/corpus-manifest.json b/qualification/families/stripe-platform-refund-v1/corpus-manifest.json index 9066f7ee0..d41a13aaa 100644 --- a/qualification/families/stripe-platform-refund-v1/corpus-manifest.json +++ b/qualification/families/stripe-platform-refund-v1/corpus-manifest.json @@ -1 +1 @@ -{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"a72c557b69103a52eb477deb8364ded53cd58407b9ba7ab33ccbda74389fec1e","family":"stripe-platform-refund-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"99901e36cb7c4f5882897603c874698d582e859b5d6b08d53cd80975e89aa01c","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"e58dc84b60f5ff13e5c7b1b5aae4917c5427f31cc8ac041acdd85defc8cd5e92","family_harness.py":"bd8474b88f5e7f8869c0470bfa4e09ba159c3e9d8b3a4ea2f2404938d8980d6f","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"4896a5f16474cbb418decb719bcc2af4a08483eabeca996427b40560a16d02cf","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","production_setup.py":"a9fbbb1d65fac43fdfef25ccae806a783014a3e4bdf9ec74398e7bd2726fc9c4","resource_io.py":"025139a787f50f5181e390ea58da45db00dbdef15c8b3928cba9e0485945f6fe","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489"},"source_recipe_sha256":"b1972d556f28433932a449636755077f7ee485ef90cca412f153bc7f18881368"} \ No newline at end of file +{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"a72c557b69103a52eb477deb8364ded53cd58407b9ba7ab33ccbda74389fec1e","family":"stripe-platform-refund-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"99901e36cb7c4f5882897603c874698d582e859b5d6b08d53cd80975e89aa01c","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","controller_socket.py":"742852974870a925c7f0cf995eadb729149463b5163f2273bada6c1f2e3cfa8c","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"e58dc84b60f5ff13e5c7b1b5aae4917c5427f31cc8ac041acdd85defc8cd5e92","family_harness.py":"ed0136600a25c9f12bdcca73b105c3968271ccd227f42ad03a884cf5b9430de6","family_operations.py":"f6f7e54714228af7b48f2691c4ee15b5b2b34ebd5eb7b19dab61d26734bf7ce5","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","installed_submit.py":"f78b91ca7c57ea6909793973ca63fb33f18589ac8acbcb15e8886511e3d6fc50","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"4896a5f16474cbb418decb719bcc2af4a08483eabeca996427b40560a16d02cf","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","production_setup.py":"795f47b92d806171e866510b75557bb6ece1fd1d14f6f51bf5330c25bbf80519","provider_readback.py":"d576768208985b3544f146597d181d796f2a5e2eca5026dae3fa15cadcfe65b2","resource_io.py":"b0ed0223fd11a1a28c25278de539a9b2ed63881b26a8e00e386f25d4d9aa9384","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489"},"source_recipe_sha256":"b1972d556f28433932a449636755077f7ee485ef90cca412f153bc7f18881368"} \ No newline at end of file diff --git a/qualification/reference/README.md b/qualification/reference/README.md index 04c5cdcb2..22da04a76 100644 --- a/qualification/reference/README.md +++ b/qualification/reference/README.md @@ -267,3 +267,21 @@ runtime role. Private state, token paths and database credentials stay outside publication; native counters come from the running process's admin socket. The complete protected journey still needs to connect this controller to resource preparation, mailbox exchanges and the family operations. + +`family_operations.py` retains measured effects across stage-runner processes. +Implemented handlers refresh only original packet labels, reauthenticate exact +action/context/request bindings, execute private commissioning or ordinary +application submissions, collect native counters, and require independent raw +provider read-back for linked outcomes. Replay, read-back, relative guards, +malformed proof/action, genuine credential rotation and the installed Python +client have handlers. Unimplemented cases refuse, so this partial operation +implementation cannot close either complete protected corpus. + +`controller_socket.py` connects those operations to the family harness using a +root-owned private socket with kernel peer checks. Requests carry only closed +family/case/index/operation coordinates. Credentials, command lines, expected +outcomes, packets and publication paths cannot be supplied over this interface. +The credential-free installed-author job exercises the real root peer transport. +`provider_readback.py` independently discovers Stripe refunds by the verified +action's echo within its owned payment, or reads the exact owned Airtable record; +it retains the provider's raw response bytes for digest comparison. diff --git a/qualification/reference/controller_socket.py b/qualification/reference/controller_socket.py new file mode 100644 index 000000000..60e9d3deb --- /dev/null +++ b/qualification/reference/controller_socket.py @@ -0,0 +1,129 @@ +"""Private root-to-root operation transport for the reviewed stage harness. + +Only case coordinates cross this socket. A caller supplies no packet, secret, +command, expected verdict or output path. The owner retains actual measured +state across stage-runner processes and refuses unknown/unimplemented steps. +""" + +import os +from pathlib import Path +import re +import socket +import stat +import struct +import time + +from common import canonical, closed, Refusal, require +from expand import decode + +REQUEST = 'auths.qualification-controller-step/1' +REPLY = 'auths.qualification-controller-reply/1' +MAX_REPLY = 65536 + + +def endpoint(path, *, existing): + path = Path(path).absolute() + require(os.getuid() == 0 and hasattr(socket, 'SO_PEERCRED') + and len(str(path).encode()) <= 107 and path.resolve() == path, + 'qualification.controller.identity') + parent = os.lstat(path.parent) + require(stat.S_ISDIR(parent.st_mode) and parent.st_uid == 0 + and stat.S_IMODE(parent.st_mode) == 0o700, + 'qualification.controller.private-directory') + if existing: + info = os.lstat(path) + require(stat.S_ISSOCK(info.st_mode) and info.st_uid == 0 + and stat.S_IMODE(info.st_mode) == 0o600, 'qualification.controller.socket') + else: + require(not path.exists() and not path.is_symlink(), 'qualification.controller.socket') + return path + + +def peer(connection): + _pid, uid, _gid = struct.unpack('3i', connection.getsockopt(socket.SOL_SOCKET, socket.SO_PEERCRED, 12)) + require(uid == 0, 'qualification.controller.peer') + + +def receive(connection, maximum): + result = b'' + while not result.endswith(b'\n'): + chunk = connection.recv(min(4096, maximum + 1 - len(result))) + require(chunk and len(result) + len(chunk) <= maximum, 'qualification.controller.message-bound') + result += chunk + require(result.count(b'\n') == 1, 'qualification.controller.message-bound') + value = decode(result) + require(result == canonical(value) + b'\n', 'qualification.controller.message-canonical') + return value + + +def checked_request(value, family): + closed(value, ['schema', 'family', 'case', 'index', 'operation']) + require(value['schema'] == REQUEST and value['family'] == family + and type(value['case']) is str and re.fullmatch(r'(commissioning|live)-[a-z0-9-]{1,64}', value['case']) + and type(value['index']) is int and 0 <= value['index'] < 16 + and value['operation'] in ['submit', 'probe', 'replay', 'race', 'restart', 'crash', + 'rotate', 'read-back', 'drop-response', 'delay-visibility', 'installed-consumer'], + 'qualification.controller.coordinates') + return value + + +def call(path, family, case, index, operation): + path = endpoint(path, existing=True) + request = checked_request({'schema': REQUEST, 'family': family, 'case': case, + 'index': index, 'operation': operation}, family) + with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as connection: + connection.settimeout(120) + connection.connect(str(path)) + peer(connection) + connection.sendall(canonical(request) + b'\n') + reply = receive(connection, MAX_REPLY) + if type(reply) is dict and set(reply) == {'schema', 'code'}: + require(reply['schema'] == REPLY and type(reply['code']) is str + and re.fullmatch(r'qualification\.[a-z0-9.-]{1,128}', reply['code']), + 'qualification.controller.reply') + raise Refusal(reply['code']) + closed(reply, ['schema', 'observation']) + require(reply['schema'] == REPLY and type(reply['observation']) is dict, + 'qualification.controller.reply') + return reply['observation'] + + +def serve(path, operations, deadline, stopping): + path = endpoint(path, existing=False) + require(type(deadline) in [int, float] and time.monotonic() < deadline <= time.monotonic() + 7200, + 'qualification.controller.deadline') + with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as server: + server.bind(str(path)) + os.chmod(path, 0o600) + inode = os.lstat(path).st_ino + server.listen(1) + server.settimeout(0.25) + try: + while not stopping.is_set() and time.monotonic() < deadline: + try: + connection, _ = server.accept() + except socket.timeout: + continue + with connection: + connection.settimeout(120) + try: + peer(connection) + value = checked_request(receive(connection, 4096), operations.family) + observation = operations.step(value['case'], value['index'], value['operation']) + reply = {'schema': REPLY, 'observation': observation} + except (Refusal, OSError, ValueError, KeyError, TypeError, TimeoutError) as error: + code = str(error) if isinstance(error, Refusal) else 'qualification.controller.operation-refused' + if re.fullmatch(r'qualification\.[a-z0-9.-]{1,128}', code) is None: + code = 'qualification.controller.operation-refused' + reply = {'schema': REPLY, 'code': code} + payload = canonical(reply) + b'\n' + require(len(payload) <= MAX_REPLY, 'qualification.controller.message-bound') + try: + connection.sendall(payload) + except OSError: + # A lost report cannot undo an entered native attempt; + # its case coordinates remain consumed by Operations. + pass + finally: + if path.exists() and os.lstat(path).st_ino == inode: + path.unlink() diff --git a/qualification/reference/family_harness.py b/qualification/reference/family_harness.py index 5aca9a3cb..6b3d65abd 100644 --- a/qualification/reference/family_harness.py +++ b/qualification/reference/family_harness.py @@ -221,8 +221,13 @@ def dispatch(): return if len(arguments) == 6 and arguments[0] == 'step': _, case, index, operation, directory, output = arguments - require(case.startswith('offline-'), 'qualification.harness.protected-journey-not-configured') - value = offline(family, case.removeprefix('offline-'), int(index), operation, Path(directory).absolute()) + if case.startswith('offline-'): + value = offline(family, case.removeprefix('offline-'), int(index), operation, Path(directory).absolute()) + else: + controller = os.environ.get('AUTHS_QUALIFICATION_CONTROLLER') + require(controller is not None, 'qualification.harness.protected-journey-not-configured') + from controller_socket import call + value = call(controller, family, case, int(index), operation) return write(Path(output).absolute(), value, new=True) # No helper can silently complete an unimplemented protected step, # provision development custody, or manufacture a live observation. diff --git a/qualification/reference/family_operations.py b/qualification/reference/family_operations.py new file mode 100644 index 000000000..dc6b6f202 --- /dev/null +++ b/qualification/reference/family_operations.py @@ -0,0 +1,204 @@ +"""Measured protected operations; absent operations refuse without a report. + +The controller retains the effect ledger across native stage-runner children. +Case IDs select only this source's fixed packet labels. Expectations from the +corpus never enter an operation or an observation. +""" + +from pathlib import Path + +import airtable_record +import stripe_platform +from common import canonical, closed, require, sha256 +from expand import child, decode, read +from native_observation import Effects +from packet_plan import public_pool +from resource_io import write_bytes + +POSITIVES = {'fresh-replay': 0, 'proof-replay': 1, 'two-host-race': 2, + 'restart': 3, 'crash': 4, 'ambiguous': 5, 'response-loss': 6, + 'visibility': 7, 'secret-rotation': 8, 'read-back': 9, 'capabilities': 10, + 'installed-python': 11, 'installed-typescript': 12} + + +class Operations: + def __init__(self, deployment, author, oracle, resources, reviewed): + self.deployment, self.author, self.oracle = deployment, author, oracle + self.resources, self.reviewed = resources, reviewed + self.tuple = deployment.tuple + self.family = self.tuple['recipe_family'] + self.reference = {stripe_platform.FAMILY: stripe_platform, airtable_record.FAMILY: airtable_record}[self.family] + carrier = decode(read(deployment.work / 'public-packets.json', 65536)) + self.packets = {packet['label']: packet for packet in public_pool( + self.family, resources, self.tuple['compiled_recipe_sha256'], carrier)} + require(set(self.packets) == set(reviewed), 'qualification.operations.pool-binding') + self.effects = Effects() + self.completed = set() + self.started = set() + self.phase = None + self.current_credential = None + self.rotation_keys = None + self.consumer_python = None + self.consumer_kit = None + + def configure_consumers(self, python, kit): + self.consumer_python, self.consumer_kit = Path(python).absolute(), Path(kit).absolute() + + def configure_rotation(self, first, second): + require(type(first) is bytes and type(second) is bytes and first != second + and first in self.deployment.canaries and second in self.deployment.canaries, + 'qualification.operations.genuine-rotation-required') + self.rotation_keys, self.current_credential = (first, second), first + + def begin(self, phase): + require(phase in ['commissioning', 'live'] + and (self.phase is None if phase == 'commissioning' else self.phase == 'commissioning'), + 'qualification.operations.phase') + if phase == 'commissioning': + require(self.deployment.permit is not None, 'qualification.operations.permit') + else: + for context in [0, 1]: + for host in [0, 1]: + status = self.deployment.command(['qualification-status', '--state-dir', + self.deployment.state(host, context)]) + require(status == {'policy': 'required', 'state': 'qualified', 'code': None}, + 'qualification.operations.first-release-not-qualified') + self.phase = phase + + def packet(self, label): + require(label in self.packets, 'qualification.operations.packet') + # The retained author accepts known source labels only. Refresh must + # preserve original action/context bytes, actor and request binding. + handoff = self.author.refresh(label) + packet = self.packets[label] + value = decode(read(Path(handoff) / 'public-packets.json', 65536)) + require(value['packets'] == [packet] and value['protected_run'] == self.resources['protected_run'], + 'qualification.operations.refresh-binding') + for name, bound in [(packet['action'], 65536), (packet['trusted_context'], 4 * 1024 * 1024)]: + require(read(Path(handoff) / name, bound) == read(self.deployment.work / name, bound), + 'qualification.operations.refresh-binding') + actual = child(self.deployment.binary, ['review-submission', '--recipe', self.deployment.work / 'recipe.json', + '--profile-lock', self.deployment.work / 'profile.lock.json', + '--trusted-context', Path(handoff) / packet['trusted_context'], + '--proof', Path(handoff) / packet['proof'], '--action', Path(handoff) / packet['action'], + '--evaluated-at', str(value['evaluated_at'])]) + require(actual == self.reviewed[label], 'qualification.operations.refresh-binding') + return handoff, packet + + def observation(self, observed, fresh=None): + return {'tuple_sha256': sha256(b'auths.qualification-tuple/1\0' + canonical(self.tuple)), + 'observed': observed, 'fresh_evidence': fresh, + 'unauthorized_provider_entries': 0, 'secret_exposed': False, + 'repository_imported': False, 'provider_token_received': False} + + def project(self, label, result, before, after): + reviewed = self.reviewed[label] + # A native linked result still needs a separate fresh provider read. + response = self.oracle.fresh(reviewed, self.tuple['compiled_recipe_sha256']) \ + if result['outcome'] == 'observed-by-provider' else None + observed, fresh = self.effects.project(self.tuple, reviewed, self.resources, + result, before, after, response) + return self.observation(observed, fresh) + + def submit(self, phase, label, host=0, context=0): + handoff, packet = self.packet(label) + if phase == 'commissioning': + execution = self.deployment.commissioning_submit(handoff, packet, host, context) + return self.project(label, execution['result'], execution['before'], execution['after']) + before = self.deployment.witness(host, context) + result = self.deployment.application_submit(handoff, packet, host, context) + after = self.deployment.witness(host, context) + return self.project(label, result, before, after) + + def read_back(self, label): + before = self.deployment.witness(0) + result = self.deployment.reobserve(self.reviewed[label]['arguments']['operation_id']) + after = self.deployment.witness(0) + return self.project(label, result, before, after) + + def completed_probe(self, code): + # Completion is constructed only after that source operation returned + # actual native/provider facts; a corpus's expected code is never read. + return self.observation({'verdict': {'outcome': 'complete', 'code': code, + 'request_sha256': None, 'evidence_sha256': None}, 'credential_leases': 0, + 'provider_entries': 0, 'confirmed_by_read_back': 0}) + + def rotate(self): + require(self.rotation_keys is not None, 'qualification.operations.genuine-rotation-required') + successor = next(key for key in self.rotation_keys if key != self.current_credential) + result = self.deployment.rotate(successor) + require(result.get('ok') is True and result.get('code') == 'gateway.admin.rotated', + 'qualification.operations.rotation-refused') + self.current_credential = successor + return self.completed_probe('provider-secret-rotated') + + def hostile(self, phase, identifier): + label = phase + '-13' + handoff, packet = self.packet(label) + directory = self.deployment.private / ('hostile-' + phase + '-' + identifier) + directory.mkdir(mode=0o700) + for name, bound in [(packet['proof'], 4 * 1024 * 1024), (packet['action'], 65536)]: + raw = read(Path(handoff) / name, bound) + if name == packet['proof' if identifier == 'forged' else 'action']: + raw += b'\0' + write_bytes(directory / name, raw, new=True) + if phase == 'commissioning': + execution = self.deployment.commissioning_submit(directory, packet) + return self.project(label, execution['result'], execution['before'], execution['after']) + before = self.deployment.witness(0) + result = self.deployment.application_submit(directory, packet) + return self.project(label, result, before, self.deployment.witness(0)) + + def python_consumer(self, phase): + require(self.consumer_python is not None and self.consumer_kit is not None, + 'qualification.operations.installed-python-not-configured') + label = phase + '-11' + handoff, packet = self.packet(label) + before = self.deployment.witness(0) + result = self.deployment.installed_python_submit(self.consumer_python, self.consumer_kit, handoff, packet) + return self.project(label, result, before, self.deployment.witness(0)) + + def step(self, case, index, operation): + require(type(case) is str and type(index) is int and type(operation) is str, + 'qualification.operations.step') + phase, separator, identifier = case.partition('-') + require(separator and phase in ['commissioning', 'live'] and self.phase == phase, + 'qualification.operations.phase') + require((case, index) not in self.started, 'qualification.operations.repeated-step') + self.started.add((case, index)) + # Source-owned sequences, independent of candidate/corpus outcomes. + if identifier in ['fresh-replay', 'proof-replay']: + require(index in [0, 1] and operation == ['submit', 'replay'][index], + 'qualification.operations.step') + label = phase + '-' + str(POSITIVES[identifier]).zfill(2) + if index == 1: + require((case, 0) in self.completed, 'qualification.operations.order') + context = int(index == 1 and identifier == 'fresh-replay') + result = self.submit(phase, label + ('-fresh' if context else ''), context=context) + elif identifier == 'read-back': + require(index in [0, 1] and operation == ['submit', 'read-back'][index], + 'qualification.operations.step') + label = phase + '-09' + if index == 1: + require((case, 0) in self.completed, 'qualification.operations.order') + result = self.submit(phase, label) if index == 0 else self.read_back(label) + elif identifier in ['guard-ceiling', 'guard-currency']: + require(self.reference is stripe_platform and index == 0 and operation == 'probe', + 'qualification.operations.step') + result = self.submit(phase, phase + '-' + identifier) + elif identifier in ['forged', 'altered']: + require(index == 0 and operation == 'probe', 'qualification.operations.step') + result = self.hostile(phase, identifier) + elif identifier == 'secret-rotation': + require(index in [0, 1] and operation == ['rotate', 'submit'][index], + 'qualification.operations.step') + if index == 1: + require((case, 0) in self.completed, 'qualification.operations.order') + result = self.rotate() if index == 0 else self.submit(phase, phase + '-08') + elif identifier == 'installed-python': + require(index == 0 and operation == 'installed-consumer', 'qualification.operations.step') + result = self.python_consumer(phase) + else: + require(False, 'qualification.operations.not-implemented') + self.completed.add((case, index)) + return result diff --git a/qualification/reference/generate_families.py b/qualification/reference/generate_families.py index 925b0f13a..f874f183b 100644 --- a/qualification/reference/generate_families.py +++ b/qualification/reference/generate_families.py @@ -16,9 +16,10 @@ ROOT = Path(__file__).resolve().parents[2] REFERENCE = ROOT / 'qualification/reference' -SOURCES_TO_PIN = ['family_corpus.py', 'family_harness.py', 'packet_plan.py', - 'author_packets.py', 'author_socket.py', 'author_operator.py', 'production_setup.py', 'common.py', 'fresh_evidence.py', - 'native_observation.py', 'measure.py', 'resource_io.py', 'resource_summary.py', +SOURCES_TO_PIN = ['family_corpus.py', 'family_harness.py', 'family_operations.py', 'packet_plan.py', + 'author_packets.py', 'author_socket.py', 'author_operator.py', 'production_setup.py', + 'controller_socket.py', 'installed_submit.py', 'common.py', 'fresh_evidence.py', + 'native_observation.py', 'measure.py', 'provider_readback.py', 'resource_io.py', 'resource_summary.py', 'expand.py', 'stripe_platform.py', 'airtable_record.py', 'stripe_resources.py', 'airtable_resources.py'] diff --git a/qualification/reference/installed_submit.py b/qualification/reference/installed_submit.py new file mode 100644 index 000000000..8adaa96e9 --- /dev/null +++ b/qualification/reference/installed_submit.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python3 +"""Actual installed Python client with public proof/action and no credential.""" + +import argparse +import asyncio +from dataclasses import asdict +from pathlib import Path + +from author_packets import installed_native +from common import canonical, require +from expand import read +from resource_io import finish + + +def submit(endpoint, proof, action): + installed_native() + from auths.gateway import GatewayClient, GatewayEndpoint + result = asyncio.run(GatewayClient(GatewayEndpoint(endpoint)).submit( + proof=read(proof, 4 * 1024 * 1024), action=read(action, 65536))) + payload = canonical(asdict(result)) + require(len(payload) <= 65536, 'qualification.consumer.output-bound') + print(payload.decode()) + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + for name in ['endpoint', 'proof', 'action']: + parser.add_argument('--' + name, type=lambda value: Path(value).absolute(), required=True) + args = parser.parse_args() + finish(lambda: submit(args.endpoint, args.proof, args.action)) + + +if __name__ == '__main__': + main() diff --git a/qualification/reference/production_setup.py b/qualification/reference/production_setup.py index 3f79f622d..2d966eaf3 100644 --- a/qualification/reference/production_setup.py +++ b/qualification/reference/production_setup.py @@ -61,15 +61,27 @@ def __init__(self, binary, work, private, environment, canaries): 'qualification.production.controller-identity') self.binary, self.work, self.private = Path(binary).absolute(), Path(work).absolute(), Path(private).absolute() self.tuple = decode(read(self.work / 'tuple.json', 65536)) - require(sha256(read(self.binary, 256 * 1024 * 1024)) == self.tuple['target']['gateway_build_sha256'], + executable = read(self.binary, 256 * 1024 * 1024) + require(sha256(executable) == self.tuple['target']['gateway_build_sha256'], 'qualification.production.candidate-bytes') require(not self.private.exists() and not self.private.is_relative_to(self.work), 'qualification.production.private-directory') self.private.mkdir(mode=0o711) + os.chmod(self.private, 0o711) + # Runner temp ancestors may exclude the gateway/application UIDs. + # Copy these exact checked executable bytes into a traversable parent. + self.binary = self.private / 'auths-gateway' + fd = os.open(self.binary, os.O_WRONLY | os.O_CREAT | os.O_EXCL | os.O_NOFOLLOW, 0o755) + os.fchmod(fd, 0o755) + with os.fdopen(fd, 'wb') as stream: + stream.write(executable) + stream.flush() + os.fsync(stream.fileno()) self.gateway = self.private / 'gateway' self.gateway.mkdir(mode=0o700) self.sockets = self.private / 'sockets' self.sockets.mkdir(mode=0o750) + os.chmod(self.sockets, 0o750) os.chown(self.sockets, GATEWAY_UID, GATEWAY_UID) self.canaries = list(canaries) require(self.canaries and all(type(value) is bytes and len(value) >= 8 for value in self.canaries), @@ -101,13 +113,41 @@ def __init__(self, binary, work, private, environment, canaries): require(family in ['stripe-platform-refund-v1', 'airtable-record-update-v1'], 'qualification.production.family') self.provider = 'stripe' if family == 'stripe-platform-refund-v1' else 'airtable' - for name in ['recipe.json', 'profile.lock.json', *carrier['trusted_contexts'], + for name in ['recipe.json', 'profile.lock.json', 'resources.json', *carrier['trusted_contexts'], *[context + '.operator.json' for context in carrier['trusted_contexts']]]: path = self.gateway / name write_bytes(path, read(self.work / name, 4 * 1024 * 1024), new=True) os.chown(path, GATEWAY_UID, GATEWAY_UID) os.chown(self.gateway, GATEWAY_UID, GATEWAY_UID) self.processes = {} + self.handoff_generation = 0 + self.permit = None + + def owned_inputs(self, name, values, owner): + require(re.fullmatch(r'[a-z][a-z0-9-]{0,63}', name) is not None + and owner in [GATEWAY_UID, APPLICATION_UID], 'qualification.production.private-directory') + directory = self.private / name + directory.mkdir(mode=0o700) + for filename, payload in values.items(): + require(re.fullmatch(r'[a-zA-Z0-9][a-zA-Z0-9_.-]{0,95}', filename) is not None, + 'qualification.production.private-input') + path = directory / filename + write_bytes(path, payload, new=True) + os.chown(path, owner, GATEWAY_UID) + os.chown(directory, owner, GATEWAY_UID) + return directory + + def packet_inputs(self, handoff, packet, owner): + closed(packet, ['label', 'proof', 'action', 'trusted_context', 'arguments']) + require(re.fullmatch(r'[a-z][a-z0-9-]{0,63}', packet['label']) is not None + and packet['proof'] == packet['label'] + '.proof' + and packet['action'] == packet['label'] + '.action' + and packet['trusted_context'] in ['context-0.cbor', 'context-1.cbor'], + 'qualification.production.packet-binding') + self.handoff_generation += 1 + values = {name: read(Path(handoff) / name, bound) for name, bound in [ + (packet['proof'], 4 * 1024 * 1024), (packet['action'], 65536)]} + return self.owned_inputs('packet-' + str(self.handoff_generation), values, owner) def environment(self, administrative=False): return {'PATH': '/usr/bin:/bin', **self.database, @@ -194,6 +234,117 @@ def witness(self, host, context=0): require(result['ok'] is True, 'qualification.production.witness-unavailable') return snapshot(result['execution_witness']) + def application_submit(self, handoff, packet, host=0, context=0): + inputs = self.packet_inputs(handoff, packet, APPLICATION_UID) + result = subprocess.run([str(self.binary), 'submit', '--app-socket', str(self.app_socket(host, context)), + '--proof', str(inputs / packet['proof']), '--action', str(inputs / packet['action'])], + stdin=subprocess.DEVNULL, capture_output=True, timeout=90, cwd=inputs, + user=APPLICATION_UID, group=GATEWAY_UID, extra_groups=[], env={'PATH': '/usr/bin:/bin'}) + return native_output(result, self.canaries) + + def installed_python_submit(self, python, kit, handoff, packet, host=0, context=0): + inputs = self.packet_inputs(handoff, packet, APPLICATION_UID) + result = subprocess.run([str(python), '-B', str(Path(kit) / 'installed_submit.py'), + '--endpoint', str(self.app_socket(host, context)), '--proof', str(inputs / packet['proof']), + '--action', str(inputs / packet['action'])], stdin=subprocess.DEVNULL, + capture_output=True, timeout=90, cwd=inputs, user=APPLICATION_UID, + group=GATEWAY_UID, extra_groups=[], env={'PATH': '/usr/bin:/bin', 'PYTHONNOUSERSITE': '1'}) + return native_output(result, self.canaries) + + def register_commissioning(self, source): + require(self.permit is None, 'qualification.production.permit-already-registered') + names = ['commissioning-permit.json', 'signer-certificate.json', 'revocation-list.json'] + permit = self.owned_inputs('permit', {name: read(Path(source) / name, 2 * 1024 * 1024) + for name in names}, GATEWAY_UID) + result = self.command(self.commission_arguments('commissioning-init', permit, 0, 0)) + require(result == {'outcome': 'commissioning-registered', 'qualification': 'required'}, + 'qualification.production.permit-not-registered') + self.permit = permit + + def commission_arguments(self, operation, permit, host, context): + require(operation in ['commissioning-init', 'commissioning-submit'], + 'qualification.production.operation') + resources = decode(read(self.work / 'resources.json', 65536)) + return [operation, '--state-dir', self.state(host, context), '--from', permit, + '--protected-run', resources['protected_run'], '--resource-binding', self.gateway / 'resources.json'] + + def commissioning_submit(self, handoff, packet, host=0, context=0, witness=None): + require(self.permit is not None, 'qualification.production.permit-not-registered') + inputs = self.packet_inputs(handoff, packet, GATEWAY_UID) + arguments = [*self.commission_arguments('commissioning-submit', self.permit, host, context), + '--proof', inputs / packet['proof'], '--action', inputs / packet['action']] + if witness is not None: + require(Path(witness).parent == self.state(host, context) and not Path(witness).exists(), + 'qualification.production.private-input') + arguments += ['--witness-file', witness] + execution = self.command(arguments) + closed(execution, ['schema', 'result', 'before', 'after']) + require(execution['schema'] == 'auths.gateway-commissioning-execution/1', + 'qualification.production.execution') + return execution + + def reobserve(self, operation, host=0, context=0): + require(re.fullmatch(r'qlf-[0-9a-f]{48}', operation) is not None, + 'qualification.production.operation') + result = self.command(['reobserve', '--state-dir', self.state(host, context), '--operation-id', operation]) + closed(result, ['schema', 'ok', 'code', 'result']) + require(result['ok'] is True, 'qualification.production.reobserve') + return result['result'] + + def rotate(self, credential): + require(type(credential) is bytes and credential in self.canaries, + 'qualification.production.credential-input') + result = self.command(['rotate', '--state-dir', self.state(0), '--credential-stdin', '--operator-process'], + administrative=True, secret=credential + b'\n') + require(result.get('ok') is True and result.get('code') == 'gateway.admin.rotated', + 'qualification.production.rotation') + return result + + def import_release(self, source): + # Artifact transport already bounds the archive. Here only native + # release members are copied; no script or binary can enter custody. + names = ['signer-certificate.json', 'revocation-list.json', 'release-index.json'] + release = self.owned_inputs('first-release', {name: read(Path(source) / name, 2 * 1024 * 1024) + for name in names}, GATEWAY_UID) + for group in ['records', 'attestations']: + # Temporarily root-own the new directory while using owner-only I/O. + directory = release / group + directory.mkdir(mode=0o700) + entries = sorted((Path(source) / group).iterdir()) + require(1 <= len(entries) <= 64 and all(path.suffix == '.json' for path in entries), + 'qualification.production.release-bound') + for index, path in enumerate(entries): + destination = directory / (str(index).zfill(4) + '.json') + write_bytes(destination, read(path, 2 * 1024 * 1024), new=True) + os.chown(destination, GATEWAY_UID, GATEWAY_UID) + os.chown(directory, GATEWAY_UID, GATEWAY_UID) + for context in [0, 1]: + for host in [0, 1]: + # Import verifies the certificate, revocations, index and + # record closure under this shipping build's pinned root. + self.command(['qualification-import', '--state-dir', self.state(host, context), + '--from', release], json_output=False) + + def support(self, host=0, context=0): + return self.command(['support-bundle', '--state-dir', self.state(host, context)]) + + def doctor(self, host=0, context=0): + return self.command(['doctor', '--state-dir', self.state(host, context), + '--app-socket', self.app_socket(host, context), '--app-uid', APPLICATION_UID, '--app-gid', GATEWAY_UID]) + def close(self): for host, context in list(self.processes): self.stop(host, context) + + def retire_credentials(self): + require(not self.processes, 'qualification.production.host-running') + result = self.command(['revoke', '--state-dir', self.state(0), '--store-only']) + require(result.get('state') == 'revoked' and result.get('credential_deletion') == 'not-attempted', + 'qualification.production.revoke') + for context in [0, 1]: + for host in [0, 1]: + result = self.command(['credential-collect', '--state-dir', self.state(host, context)], administrative=True) + closed(result, ['schema', 'deleted']) + require(result['schema'] == 'auths.gateway-credential-collection/1' + and type(result['deleted']) is int and result['deleted'] >= 0, + 'qualification.production.credential-collection') diff --git a/qualification/reference/provider_readback.py b/qualification/reference/provider_readback.py new file mode 100644 index 000000000..a15b940e6 --- /dev/null +++ b/qualification/reference/provider_readback.py @@ -0,0 +1,59 @@ +"""Fresh provider reads selected by authenticated actions and the owned pool. + +No candidate response locator, digest or claimed outcome chooses a read. Only +this source-owned reference holds the operator's read credential. Returned raw +bytes remain private; the independent witness publishes their digest only. +""" + +import urllib.parse + +import airtable_record +import stripe_platform +from common import closed, echo, identifier, require +from fresh_evidence import decode, witness +import resource_io + + +class ReadBack: + def __init__(self, family, resources, key, *, exchange=None): + self.family, self.resources, self.key = family, resources, key + self.exchange = exchange or resource_io.exchange + reference = {stripe_platform.FAMILY: stripe_platform, airtable_record.FAMILY: airtable_record}.get(family) + require(reference is not None, 'qualification.readback.family') + reference.resources(resources, resources['protected_run']) + self.reference = reference + + def get(self, path): + stripe = self.reference is stripe_platform + status, raw = self.exchange('https://api.stripe.com' if stripe else 'https://api.airtable.com', + 'GET', path, self.key, headers={'Stripe-Version': '2025-03-31.basil'} if stripe else {}) + require(status == 200 and type(raw) is bytes and 0 < len(raw) <= 65536, + 'qualification.readback.provider-unavailable') + return raw + + def fresh(self, reviewed, recipe_digest): + closed(reviewed, ['schema', 'actors', 'action_commitment', 'arguments', 'request']) + arguments = reviewed['arguments'] + require(reviewed['schema'] == 'auths.gateway-submission-review/1' + and reviewed['request'] == self.reference.request(arguments, self.resources, + reviewed['action_commitment'], recipe_digest), 'qualification.readback.review-binding') + if self.reference is airtable_record: + path = '/v0/' + airtable_record.BASE + '/' + airtable_record.TABLE + '/' + arguments['record_id'] + else: + # Discover the refund by its action-derived echo in the exact + # reviewed payment, rather than borrowing the candidate's locator. + path = '/v1/refunds?' + urllib.parse.urlencode({'payment_intent': arguments['payment_intent'], 'limit': 100}) + value = decode(self.get(path)) + require(type(value.get('data')) is list and len(value['data']) <= 100 + and value.get('has_more') is False, 'qualification.readback.refund-bound') + token = echo(arguments['operator_namespace'], arguments['operation_id'], reviewed['action_commitment']) + matches = [item for item in value['data'] if type(item) is dict + and type(item.get('metadata')) is dict and item['metadata'].get('auths_echo') == token] + require(len(matches) == 1, 'qualification.readback.ambiguous-refund') + refund = identifier(matches[0].get('id'), r're_[A-Za-z0-9]{1,128}') + require(matches[0].get('payment_intent') == arguments['payment_intent'], + 'qualification.readback.payment-binding') + path = '/v1/refunds/' + refund + raw = self.get(path) + witness(self.family, arguments, self.resources, reviewed['action_commitment'], recipe_digest, raw) + return raw diff --git a/qualification/reference/resource_io.py b/qualification/reference/resource_io.py index 7445cd702..6a850d97a 100644 --- a/qualification/reference/resource_io.py +++ b/qualification/reference/resource_io.py @@ -41,7 +41,7 @@ def redirect_request(self, req, fp, code, msg, headers, newurl): raise Refusal('qualification.resources.redirect-refused') -def request(origin, method, path, key, body=None, headers=None): +def exchange(origin, method, path, key, body=None, headers=None): require(path.startswith('/') and not path.startswith('//') and '\r' not in path and '\n' not in path, 'qualification.resources.path-bound') values = {'Authorization': 'Bearer ' + key, 'Accept': 'application/json'} @@ -49,15 +49,28 @@ def request(origin, method, path, key, body=None, headers=None): outbound = urllib.request.Request(origin + path, method=method, data=body, headers=values) try: with urllib.request.build_opener(urllib.request.ProxyHandler({}), NoRedirect).open(outbound, timeout=25) as response: - require(200 <= response.status <= 299, 'qualification.resources.http-refused') raw = response.read(65537) - return decode(raw) - except (urllib.error.HTTPError, urllib.error.URLError, TimeoutError, OSError): + require(0 < len(raw) <= 65536, 'qualification.resources.response-bound') + return response.status, raw + except urllib.error.HTTPError as response: + # Error bytes are private inputs too. No exception/provider detail is + # printed; a reviewed denied-read probe may inspect only its status. + with response: + raw = response.read(65537) + require(len(raw) <= 65536, 'qualification.resources.response-bound') + return response.code, raw + except (urllib.error.URLError, TimeoutError, OSError): # Provider errors can contain submitted credentials or resource data. # They never become stdout, exception text or a saved report. raise Refusal('qualification.resources.provider-unavailable') from None +def request(origin, method, path, key, body=None, headers=None): + status, raw = exchange(origin, method, path, key, body, headers) + require(200 <= status <= 299, 'qualification.resources.http-refused') + return decode(raw) + + def read(path): fd = os.open(path, os.O_RDONLY | os.O_NOFOLLOW) with os.fdopen(fd, 'rb') as stream: diff --git a/qualification/reference/tests/test_controller_socket.py b/qualification/reference/tests/test_controller_socket.py new file mode 100644 index 000000000..8910a80c8 --- /dev/null +++ b/qualification/reference/tests/test_controller_socket.py @@ -0,0 +1,79 @@ +"""Closed controller protocol and real root peer transport, no provider I/O.""" + +import os +from pathlib import Path +import socket +import sys +import tempfile +import threading +import time +import unittest + +sys.path.insert(0, str(Path(__file__).resolve().parents[1])) +from common import canonical, Refusal +import controller_socket as controller + +FAMILY = 'stripe-platform-refund-v1' + + +class Stream: + def __init__(self, raw): self.raw = raw + def recv(self, maximum): + result, self.raw = self.raw[:maximum], self.raw[maximum:] + return result + + +class Controller(unittest.TestCase): + def request(self): + return {'schema': controller.REQUEST, 'family': FAMILY, + 'case': 'commissioning-proof-replay', 'index': 0, 'operation': 'submit'} + + def test_callers_supply_only_closed_source_case_coordinates(self): + request = self.request() + controller.checked_request(request, FAMILY) + for changed in [dict(request, command='sign'), dict(request, expected={'outcome': 'observed'}), + dict(request, provider_key='synthetic-only'), dict(request, family='other-family'), + dict(request, case='../escape'), dict(request, index=True), + dict(request, index=16), dict(request, operation='install')]: + with self.assertRaises(Refusal): controller.checked_request(changed, FAMILY) + + def test_messages_refuse_trailing_frames_duplicates_noncanonical_bytes_and_bounds(self): + raw = canonical(self.request()) + b'\n' + self.assertEqual(controller.receive(Stream(raw), 4096), self.request()) + for bad in [raw + raw, b'{"index":0,"index":1}\n', b'{} \n', b'{}', b'x' * 4097 + b'\n']: + with self.assertRaises((Refusal, ValueError)): controller.receive(Stream(bad), 4096) + + @unittest.skipUnless(os.name == 'posix' and os.getuid() == 0 and hasattr(socket, 'SO_PEERCRED'), + 'the credential-free packet-author job runs this test under root on Linux') + def test_actual_private_socket_returns_refusals_without_inventing_observations(self): + class Operations: + family = FAMILY + def step(self, case, index, operation): + raise Refusal('qualification.operations.not-implemented') + with tempfile.TemporaryDirectory(prefix='auths-controller-') as temporary: + directory = Path(temporary).resolve() + directory.chmod(0o700) + endpoint = directory / 'controller.sock' + stopping = threading.Event() + failures = [] + def run(): + try: controller.serve(endpoint, Operations(), time.monotonic() + 30, stopping) + except BaseException as error: failures.append(error) + thread = threading.Thread(target=run) + thread.start() + try: + deadline = time.monotonic() + 5 + while not endpoint.exists() and not failures and time.monotonic() < deadline: + time.sleep(0.01) + with self.assertRaisesRegex(Refusal, 'operations.not-implemented'): + controller.call(endpoint, FAMILY, 'commissioning-proof-replay', 0, 'submit') + finally: + stopping.set() + thread.join(timeout=5) + self.assertFalse(thread.is_alive()) + self.assertFalse(endpoint.exists()) + self.assertEqual(failures, []) + + +if __name__ == '__main__': + unittest.main() diff --git a/qualification/reference/tests/test_provider_readback.py b/qualification/reference/tests/test_provider_readback.py new file mode 100644 index 000000000..5919331c5 --- /dev/null +++ b/qualification/reference/tests/test_provider_readback.py @@ -0,0 +1,82 @@ +"""Independent selection and raw-byte boundaries using synthetic providers.""" + +import copy +import json +from pathlib import Path +import sys +import unittest + +sys.path.insert(0, str(Path(__file__).resolve().parents[1])) +import airtable_record as airtable +import stripe_platform as stripe +from common import canonical, echo, Refusal +from provider_readback import ReadBack + + +class ProviderReads(unittest.TestCase): + def setUp(self): + self.digest, self.commitment = '1' * 64, '2' * 64 + self.run = 'recipe-qualification/123/1' + self.resources = {'schema': 'auths.stripe-platform-qualification-resources/1', + 'protected_run': self.run, 'platform': 'acct_SYNTHETIC', 'payments': [ + {'id': 'pi_SYNTHETIC', 'amount_received': 2000, 'currency': 'usd', + 'livemode': False, 'run_metadata': self.run}]} + arguments = {'operator_namespace': stripe.SERVICE, 'operation_id': 'synthetic-only-operation', + 'recipe_digest': self.digest, 'payment_intent': 'pi_SYNTHETIC', 'amount': 500, 'currency': 'usd'} + self.review = {'schema': 'auths.gateway-submission-review/1', 'actors': ['raw:synthetic-only-actor'], + 'action_commitment': self.commitment, 'arguments': arguments, + 'request': stripe.request(arguments, self.resources, self.commitment, self.digest)} + self.refund = {'id': 're_SYNTHETIC', 'object': 'refund', 'livemode': False, + 'payment_intent': 'pi_SYNTHETIC', 'amount': 500, 'currency': 'usd', 'status': 'succeeded', + 'metadata': {'auths_echo': echo(stripe.SERVICE, arguments['operation_id'], self.commitment)}} + + def test_refund_locator_is_discovered_independently_and_raw_read_bytes_are_retained(self): + calls, raw = [], json.dumps(self.refund, indent=2).encode() + def exchange(origin, method, path, key, **kwargs): + calls.append((origin, method, path)) + if '?' in path: + return 200, canonical({'data': [dict(self.refund, id='re_OTHER', metadata={}), self.refund], 'has_more': False}) + return 200, raw + reader = ReadBack(stripe.FAMILY, self.resources, 'synthetic-only-key', exchange=exchange) + self.assertEqual(reader.fresh(self.review, self.digest), raw) + self.assertEqual(calls, [('https://api.stripe.com', 'GET', '/v1/refunds?payment_intent=pi_SYNTHETIC&limit=100'), + ('https://api.stripe.com', 'GET', '/v1/refunds/re_SYNTHETIC')]) + + def test_ambiguous_paginated_wrong_payment_and_changed_fresh_state_refuse(self): + for problem in ['duplicate', 'pagination', 'wrong-payment', 'changed-fresh', 'status']: + listing = {'data': [copy.deepcopy(self.refund)], 'has_more': False} + fresh = copy.deepcopy(self.refund) + if problem == 'duplicate': listing['data'].append(copy.deepcopy(self.refund)) + if problem == 'pagination': listing['has_more'] = True + if problem == 'wrong-payment': listing['data'][0]['payment_intent'] = 'pi_OTHER' + if problem == 'changed-fresh': fresh['metadata']['auths_echo'] = 'changed' + def exchange(origin, method, path, key, **kwargs): + return (403 if problem == 'status' else 200), canonical(listing if '?' in path else fresh) + with self.subTest(problem=problem), self.assertRaises(Refusal): + ReadBack(stripe.FAMILY, self.resources, 'synthetic-only-key', exchange=exchange).fresh(self.review, self.digest) + + def test_airtable_reads_only_the_exact_owned_record_and_never_an_off_pool_record(self): + resources = {'schema': 'auths.airtable-record-qualification-resources/1', 'protected_run': self.run, + 'base': airtable.BASE, 'table': airtable.TABLE, + 'records': [{'id': 'recTEST0000000001', 'run_metadata': self.run}]} + arguments = {'operator_namespace': 'airtable-demo', 'operation_id': 'synthetic-only-operation', + 'recipe_digest': self.digest, 'record_id': 'recTEST0000000001', 'replacement': 'Approved'} + reviewed = dict(self.review, arguments=arguments, + request=airtable.request(arguments, resources, self.commitment, self.digest)) + raw = canonical({'id': arguments['record_id'], 'fields': {'DemoStatus': 'Approved', + 'auths_echo': echo('airtable-demo', arguments['operation_id'], self.commitment)}}) + calls = [] + def exchange(origin, method, path, key, **kwargs): + calls.append(path) + return 200, raw + reader = ReadBack(airtable.FAMILY, resources, 'synthetic-only-key', exchange=exchange) + self.assertEqual(reader.fresh(reviewed, self.digest), raw) + self.assertEqual(calls, ['/v0/' + airtable.BASE + '/' + airtable.TABLE + '/' + arguments['record_id']]) + changed = copy.deepcopy(reviewed) + changed['arguments']['record_id'] = 'recOTHER000000001' + with self.assertRaises(Refusal): reader.fresh(changed, self.digest) + self.assertEqual(len(calls), 1) + + +if __name__ == '__main__': + unittest.main() From a36f540a1bd31988dbbd3cd5c04e6f583f74c259 Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 16:28:00 +0100 Subject: [PATCH 089/108] Retain the isolated installed author and add transparent response fault control --- .../airtable-record-update-v1/contract.json | 2 +- .../corpus-manifest.json | 2 +- .../stripe-platform-refund-v1/contract.json | 2 +- .../corpus-manifest.json | 2 +- qualification/reference/README.md | 9 + qualification/reference/check_socket.py | 52 +----- qualification/reference/controller_socket.py | 7 +- qualification/reference/generate_families.py | 8 +- qualification/reference/network_fault.py | 172 ++++++++++++++++++ qualification/reference/retained_author.py | 87 +++++++++ .../reference/tests/test_controller_socket.py | 8 +- .../reference/tests/test_network_fault.py | 59 ++++++ 12 files changed, 353 insertions(+), 57 deletions(-) create mode 100644 qualification/reference/network_fault.py create mode 100644 qualification/reference/retained_author.py create mode 100644 qualification/reference/tests/test_network_fault.py diff --git a/qualification/families/airtable-record-update-v1/contract.json b/qualification/families/airtable-record-update-v1/contract.json index 75bcf5279..c8eeda692 100644 --- a/qualification/families/airtable-record-update-v1/contract.json +++ b/qualification/families/airtable-record-update-v1/contract.json @@ -1 +1 @@ -{"api_release":"web-api-v0-reviewed-2026-10-07","corpus_manifest_sha256":"8cb0d845f97fa5ce02e8a18d5c4dfbf43328d08a91a3a8d9d5202f300b355ad6","declarations":{"idempotency_sha256":"74234e98afe7498fb5daf1f36ac2d78acc339464f950703b8c019892f982b90b","observation_sha256":"9dd79dd204fa13a2df3c667d106c66c0526d174a2c018631e2b2f6b897eaf311","recovery_sha256":"7081a92b4cd2d13dab5e7c30e640675a252b62bca20d340e14d62d9c8c048eca","retention_sha256":"4a4b5048c97b16e041af55b032c0b8ac20f5142c4bbcbf31b31c6674770a70d0"},"environment_class":"disposable-live-resources","manual_assumptions":["Airtable supplies no idempotency key for this PATCH; durable gateway admission prevents a second entry.","Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only a fresh GET with the exact replacement and echo can reconcile a lost response.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths.","The reviewed fixed Airtable base and table contain only owner-authorized disposable qualification records."],"oracle_version":"auths-reviewed-reference-v2","provider":"airtable","schema":"auths.provider-contract/1"} \ No newline at end of file +{"api_release":"web-api-v0-reviewed-2026-10-07","corpus_manifest_sha256":"6f517e64678419c034ceb2f976e871dc0dd5bb7f8d9a7f8a1d45de01850b5a8d","declarations":{"idempotency_sha256":"74234e98afe7498fb5daf1f36ac2d78acc339464f950703b8c019892f982b90b","observation_sha256":"9dd79dd204fa13a2df3c667d106c66c0526d174a2c018631e2b2f6b897eaf311","recovery_sha256":"7081a92b4cd2d13dab5e7c30e640675a252b62bca20d340e14d62d9c8c048eca","retention_sha256":"4a4b5048c97b16e041af55b032c0b8ac20f5142c4bbcbf31b31c6674770a70d0"},"environment_class":"disposable-live-resources","manual_assumptions":["Airtable supplies no idempotency key for this PATCH; durable gateway admission prevents a second entry.","Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only a fresh GET with the exact replacement and echo can reconcile a lost response.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths.","The reviewed fixed Airtable base and table contain only owner-authorized disposable qualification records."],"oracle_version":"auths-reviewed-reference-v2","provider":"airtable","schema":"auths.provider-contract/1"} \ No newline at end of file diff --git a/qualification/families/airtable-record-update-v1/corpus-manifest.json b/qualification/families/airtable-record-update-v1/corpus-manifest.json index 8f2195951..f5c45091d 100644 --- a/qualification/families/airtable-record-update-v1/corpus-manifest.json +++ b/qualification/families/airtable-record-update-v1/corpus-manifest.json @@ -1 +1 @@ -{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"32241d9b4811a55abcdd224ef567df3857dbec34d761ef7a35d1044cdfa52d9f","family":"airtable-record-update-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"af7f984509ab11a3676cacc85eda2fa638c25bf91f7bfedf3ff3c119e47f3c41","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","controller_socket.py":"742852974870a925c7f0cf995eadb729149463b5163f2273bada6c1f2e3cfa8c","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"e58dc84b60f5ff13e5c7b1b5aae4917c5427f31cc8ac041acdd85defc8cd5e92","family_harness.py":"ed0136600a25c9f12bdcca73b105c3968271ccd227f42ad03a884cf5b9430de6","family_operations.py":"f6f7e54714228af7b48f2691c4ee15b5b2b34ebd5eb7b19dab61d26734bf7ce5","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","installed_submit.py":"f78b91ca7c57ea6909793973ca63fb33f18589ac8acbcb15e8886511e3d6fc50","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"4896a5f16474cbb418decb719bcc2af4a08483eabeca996427b40560a16d02cf","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","production_setup.py":"795f47b92d806171e866510b75557bb6ece1fd1d14f6f51bf5330c25bbf80519","provider_readback.py":"d576768208985b3544f146597d181d796f2a5e2eca5026dae3fa15cadcfe65b2","resource_io.py":"b0ed0223fd11a1a28c25278de539a9b2ed63881b26a8e00e386f25d4d9aa9384","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489"},"source_recipe_sha256":"c0f21ff1d3c8e344fee20a9a0c25bb14a264417ed53418ad536789a6096fb16e"} \ No newline at end of file +{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"32241d9b4811a55abcdd224ef567df3857dbec34d761ef7a35d1044cdfa52d9f","family":"airtable-record-update-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"af7f984509ab11a3676cacc85eda2fa638c25bf91f7bfedf3ff3c119e47f3c41","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","controller_socket.py":"10519cc775e963360870eac51c7fcac1ffb988b04d5de89dac1dbf3524ba6531","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"e58dc84b60f5ff13e5c7b1b5aae4917c5427f31cc8ac041acdd85defc8cd5e92","family_harness.py":"ed0136600a25c9f12bdcca73b105c3968271ccd227f42ad03a884cf5b9430de6","family_operations.py":"f6f7e54714228af7b48f2691c4ee15b5b2b34ebd5eb7b19dab61d26734bf7ce5","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","installed_submit.py":"f78b91ca7c57ea6909793973ca63fb33f18589ac8acbcb15e8886511e3d6fc50","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"4896a5f16474cbb418decb719bcc2af4a08483eabeca996427b40560a16d02cf","network_fault.py":"986ca0c9d7d534c2a1ebdd09edb4e6f94c17bb4bfcb35d57307c97419ed20894","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","production_setup.py":"795f47b92d806171e866510b75557bb6ece1fd1d14f6f51bf5330c25bbf80519","provider_readback.py":"d576768208985b3544f146597d181d796f2a5e2eca5026dae3fa15cadcfe65b2","resource_io.py":"b0ed0223fd11a1a28c25278de539a9b2ed63881b26a8e00e386f25d4d9aa9384","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","retained_author.py":"bfd01c7df44f5f525326dfbda13b5ebc6b854f15787a8b2923de883fe20fdcf9","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489","tls_fault.py":"d19ad37a5d37712fe274dbaddfcf062e444aab356e3c28c8cb2f533833b33ece"},"source_recipe_sha256":"c0f21ff1d3c8e344fee20a9a0c25bb14a264417ed53418ad536789a6096fb16e"} \ No newline at end of file diff --git a/qualification/families/stripe-platform-refund-v1/contract.json b/qualification/families/stripe-platform-refund-v1/contract.json index 7a9ffe872..7878317dd 100644 --- a/qualification/families/stripe-platform-refund-v1/contract.json +++ b/qualification/families/stripe-platform-refund-v1/contract.json @@ -1 +1 @@ -{"api_release":"2025-03-31.basil","corpus_manifest_sha256":"cd5bfcb1ad030343f963d07b1284e1f6a05a30f4d79a41128dcc40cedc08af9b","declarations":{"idempotency_sha256":"425a0dca2f279765debfc847c4a01bff60fea5be68dd9d761ae6bb60ce0b8a7b","observation_sha256":"d0ce5a34d987821c69c0a839d9ed66805c625f8324dd42031fcccf0752a8821e","recovery_sha256":"bf2303abce165c175360ac975586431bbc4cf03167489ea317a27de2f0b04abb","retention_sha256":"846c2164e26d1144d9aa146034b4f7ea4dc305136a59ffd94f999d19f2c360ee"},"environment_class":"provider-test-mode","manual_assumptions":["Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","Stripe idempotency is tested only inside the declared 86400-second retention interval.","Stripe test mode and the installed platform are checked by the declared guard on each lease.","The 50-percent payment basis is a read, not an atomic provider balance reservation.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths."],"oracle_version":"auths-reviewed-reference-v2","provider":"stripe","schema":"auths.provider-contract/1"} \ No newline at end of file +{"api_release":"2025-03-31.basil","corpus_manifest_sha256":"2b9f0e171966d6ee8fb7d65cfe6f657562083f56faf7c141efb7db2150ebbd15","declarations":{"idempotency_sha256":"425a0dca2f279765debfc847c4a01bff60fea5be68dd9d761ae6bb60ce0b8a7b","observation_sha256":"d0ce5a34d987821c69c0a839d9ed66805c625f8324dd42031fcccf0752a8821e","recovery_sha256":"bf2303abce165c175360ac975586431bbc4cf03167489ea317a27de2f0b04abb","retention_sha256":"846c2164e26d1144d9aa146034b4f7ea4dc305136a59ffd94f999d19f2c360ee"},"environment_class":"provider-test-mode","manual_assumptions":["Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","Stripe idempotency is tested only inside the declared 86400-second retention interval.","Stripe test mode and the installed platform are checked by the declared guard on each lease.","The 50-percent payment basis is a read, not an atomic provider balance reservation.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths."],"oracle_version":"auths-reviewed-reference-v2","provider":"stripe","schema":"auths.provider-contract/1"} \ No newline at end of file diff --git a/qualification/families/stripe-platform-refund-v1/corpus-manifest.json b/qualification/families/stripe-platform-refund-v1/corpus-manifest.json index d41a13aaa..d1826ba8e 100644 --- a/qualification/families/stripe-platform-refund-v1/corpus-manifest.json +++ b/qualification/families/stripe-platform-refund-v1/corpus-manifest.json @@ -1 +1 @@ -{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"a72c557b69103a52eb477deb8364ded53cd58407b9ba7ab33ccbda74389fec1e","family":"stripe-platform-refund-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"99901e36cb7c4f5882897603c874698d582e859b5d6b08d53cd80975e89aa01c","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","controller_socket.py":"742852974870a925c7f0cf995eadb729149463b5163f2273bada6c1f2e3cfa8c","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"e58dc84b60f5ff13e5c7b1b5aae4917c5427f31cc8ac041acdd85defc8cd5e92","family_harness.py":"ed0136600a25c9f12bdcca73b105c3968271ccd227f42ad03a884cf5b9430de6","family_operations.py":"f6f7e54714228af7b48f2691c4ee15b5b2b34ebd5eb7b19dab61d26734bf7ce5","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","installed_submit.py":"f78b91ca7c57ea6909793973ca63fb33f18589ac8acbcb15e8886511e3d6fc50","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"4896a5f16474cbb418decb719bcc2af4a08483eabeca996427b40560a16d02cf","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","production_setup.py":"795f47b92d806171e866510b75557bb6ece1fd1d14f6f51bf5330c25bbf80519","provider_readback.py":"d576768208985b3544f146597d181d796f2a5e2eca5026dae3fa15cadcfe65b2","resource_io.py":"b0ed0223fd11a1a28c25278de539a9b2ed63881b26a8e00e386f25d4d9aa9384","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489"},"source_recipe_sha256":"b1972d556f28433932a449636755077f7ee485ef90cca412f153bc7f18881368"} \ No newline at end of file +{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"a72c557b69103a52eb477deb8364ded53cd58407b9ba7ab33ccbda74389fec1e","family":"stripe-platform-refund-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"99901e36cb7c4f5882897603c874698d582e859b5d6b08d53cd80975e89aa01c","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","controller_socket.py":"10519cc775e963360870eac51c7fcac1ffb988b04d5de89dac1dbf3524ba6531","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"e58dc84b60f5ff13e5c7b1b5aae4917c5427f31cc8ac041acdd85defc8cd5e92","family_harness.py":"ed0136600a25c9f12bdcca73b105c3968271ccd227f42ad03a884cf5b9430de6","family_operations.py":"f6f7e54714228af7b48f2691c4ee15b5b2b34ebd5eb7b19dab61d26734bf7ce5","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","installed_submit.py":"f78b91ca7c57ea6909793973ca63fb33f18589ac8acbcb15e8886511e3d6fc50","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"4896a5f16474cbb418decb719bcc2af4a08483eabeca996427b40560a16d02cf","network_fault.py":"986ca0c9d7d534c2a1ebdd09edb4e6f94c17bb4bfcb35d57307c97419ed20894","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","production_setup.py":"795f47b92d806171e866510b75557bb6ece1fd1d14f6f51bf5330c25bbf80519","provider_readback.py":"d576768208985b3544f146597d181d796f2a5e2eca5026dae3fa15cadcfe65b2","resource_io.py":"b0ed0223fd11a1a28c25278de539a9b2ed63881b26a8e00e386f25d4d9aa9384","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","retained_author.py":"bfd01c7df44f5f525326dfbda13b5ebc6b854f15787a8b2923de883fe20fdcf9","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489","tls_fault.py":"d19ad37a5d37712fe274dbaddfcf062e444aab356e3c28c8cb2f533833b33ece"},"source_recipe_sha256":"b1972d556f28433932a449636755077f7ee485ef90cca412f153bc7f18881368"} \ No newline at end of file diff --git a/qualification/reference/README.md b/qualification/reference/README.md index 22da04a76..e8e1c8763 100644 --- a/qualification/reference/README.md +++ b/qualification/reference/README.md @@ -285,3 +285,12 @@ The credential-free installed-author job exercises the real root peer transport. `provider_readback.py` independently discovers Stripe refunds by the verified action's echo within its owned payment, or reads the exact owned Airtable record; it retains the provider's raw response bytes for digest comparison. + +The production controller's retained-author adapter now uses the same dedicated +installed-SDK process exercised by the credential-free socket job. Its private +signing session and refresh handoffs stay outside publication. The transparent +response-fault controller adds and removes individual UID-scoped rules; it +retains end-to-end TLS and requires actual native counters before arming. +Application and author UIDs can be denied both IPv4 and IPv6 egress. These +mechanisms do not establish protected case completion until the full journey +executes them and the native runner verifies its measured observations. diff --git a/qualification/reference/check_socket.py b/qualification/reference/check_socket.py index 32bd83a24..28050034f 100644 --- a/qualification/reference/check_socket.py +++ b/qualification/reference/check_socket.py @@ -9,12 +9,11 @@ import argparse import os from pathlib import Path -import subprocess import time import airtable_record import stripe_platform -from author_socket import exchange, refresh +from retained_author import RetainedAuthor from check_packets import review from common import require, sha256 from expand import decode, read @@ -24,26 +23,10 @@ AUTHOR_UID = 62002 -def isolate(): - os.setgroups([]) - os.setgid(AUTHOR_UID) - os.setuid(AUTHOR_UID) - - -def ready(process, work): - deadline = time.monotonic() + 30 - while time.monotonic() < deadline: - require(process.poll() is None, 'qualification.packets.author-refused') - if (work / 'author.sock').exists(): - exchange(work, 'inspect') - return - time.sleep(0.1) - require(False, 'qualification.packets.author-timeout') - - def check(args): require(os.getuid() == 0 and not args.work.exists(), 'qualification.packets.socket-isolation') - args.work.mkdir(mode=0o700) + args.work.mkdir(mode=0o711) + os.chmod(args.work, 0o711) reports = [] for reference in [stripe_platform, airtable_record]: work = args.work / reference.FAMILY @@ -59,27 +42,16 @@ def check(args): write(work / 'resources.json', resources, new=True) prepare(argparse.Namespace(family=reference.FAMILY, resources=work / 'resources.json', gateway=args.gateway, work=work)) - # All author inputs are public, and every private ancestor belongs to - # the dedicated author. Its UID has no access to the controller's - # root-owned credential files or process environment. - for path in work.iterdir(): - os.chown(path, AUTHOR_UID, AUTHOR_UID) - os.chown(work, AUTHOR_UID, AUTHOR_UID) - os.chown(args.work, AUTHOR_UID, AUTHOR_UID) - process = subprocess.Popen([str(args.python), str(Path(__file__).with_name('author_socket.py')), - 'serve', '--plan', str(work / 'packet-plan.json'), '--work', str(work)], - stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, - cwd='/', env={'PATH': '/usr/bin:/bin', 'PYTHONNOUSERSITE': '1'}, preexec_fn=isolate) + author = RetainedAuthor(args.python, Path(__file__).parent, work, + args.work / (reference.FAMILY + '-private')) try: - ready(process, work) original = decode(read(work / 'public-packets.json', 65536)) public_pool(reference.FAMILY, resources, original['packets'][0]['arguments']['recipe_digest'], original) initial = review(args.gateway, work, original['packets'][0], original['evaluated_at']) # Separate connections and fresh output directories simulate the # runner handing public packets across independent job steps. for generation, packet in enumerate(original['packets'], 1): - destination = args.work / (reference.FAMILY + '-public-' + str(generation)) - refresh(work, packet['label'], destination) + destination = author.refresh(packet['label']) fresh = decode(read(destination / 'public-packets.json', 65536)) for name in ['recipe.json', 'profile.lock.json']: (destination / name).write_bytes(read(work / name, 65536)) @@ -88,20 +60,14 @@ def check(args): actual['action_commitment'], packet['arguments']['recipe_digest']) require(actual['request'] == expected and actual['actors'] == initial['actors'], 'qualification.packets.refresh-binding') - require(exchange(work, 'inspect')['generation'] == generation, + require(author.generation == generation, 'qualification.packets.generation') - exchange(work, 'close') - process.wait(timeout=10) - require(process.returncode == 0 and not (work / 'author.sock').exists(), - 'qualification.packets.author-refused') + author.close() reports.append({'family': reference.FAMILY, 'author_uid': AUTHOR_UID, 'controller_uid': 0, 'separate_connections': len(original['packets']), 'same_actor_action_request_and_trust': True, 'socket_removed_on_close': True}) finally: - if process.poll() is None: - process.terminate() - process.wait(timeout=10) - os.chown(args.work, 0, 0) + author.abort() write(args.report, {'schema': 'auths.qualification-author-socket-rehearsal/1', 'gateway_sha256': sha256(read(args.gateway, 256 * 1024 * 1024)), 'synthetic_resources': True, 'provider_contacted': False, diff --git a/qualification/reference/controller_socket.py b/qualification/reference/controller_socket.py index 60e9d3deb..75369b5e7 100644 --- a/qualification/reference/controller_socket.py +++ b/qualification/reference/controller_socket.py @@ -11,6 +11,7 @@ import socket import stat import struct +import subprocess import time from common import canonical, closed, Refusal, require @@ -88,7 +89,7 @@ def call(path, family, case, index, operation): return reply['observation'] -def serve(path, operations, deadline, stopping): +def serve(path, operations, deadline, stopping, ready=None): path = endpoint(path, existing=False) require(type(deadline) in [int, float] and time.monotonic() < deadline <= time.monotonic() + 7200, 'qualification.controller.deadline') @@ -98,6 +99,8 @@ def serve(path, operations, deadline, stopping): inode = os.lstat(path).st_ino server.listen(1) server.settimeout(0.25) + if ready is not None: + ready.set() try: while not stopping.is_set() and time.monotonic() < deadline: try: @@ -111,7 +114,7 @@ def serve(path, operations, deadline, stopping): value = checked_request(receive(connection, 4096), operations.family) observation = operations.step(value['case'], value['index'], value['operation']) reply = {'schema': REPLY, 'observation': observation} - except (Refusal, OSError, ValueError, KeyError, TypeError, TimeoutError) as error: + except (Refusal, OSError, ValueError, KeyError, TypeError, TimeoutError, subprocess.SubprocessError) as error: code = str(error) if isinstance(error, Refusal) else 'qualification.controller.operation-refused' if re.fullmatch(r'qualification\.[a-z0-9.-]{1,128}', code) is None: code = 'qualification.controller.operation-refused' diff --git a/qualification/reference/generate_families.py b/qualification/reference/generate_families.py index f874f183b..c5ebd355d 100644 --- a/qualification/reference/generate_families.py +++ b/qualification/reference/generate_families.py @@ -17,7 +17,8 @@ ROOT = Path(__file__).resolve().parents[2] REFERENCE = ROOT / 'qualification/reference' SOURCES_TO_PIN = ['family_corpus.py', 'family_harness.py', 'family_operations.py', 'packet_plan.py', - 'author_packets.py', 'author_socket.py', 'author_operator.py', 'production_setup.py', + 'author_packets.py', 'author_socket.py', 'retained_author.py', 'author_operator.py', 'production_setup.py', + 'network_fault.py', 'controller_socket.py', 'installed_submit.py', 'common.py', 'fresh_evidence.py', 'native_observation.py', 'measure.py', 'provider_readback.py', 'resource_io.py', 'resource_summary.py', 'expand.py', 'stripe_platform.py', 'airtable_record.py', 'stripe_resources.py', 'airtable_resources.py'] @@ -33,8 +34,9 @@ def generate(check=False): 'packet_plan_schema': 'auths.qualification-packet-plan/4', 'public_packet_schema': 'auths.qualification-public-packets/4', 'phases': ['offline', 'commissioning', 'live'], 'maximum_credential_leases': 64, - 'source_files': {name: sha256(read(REFERENCE / name, 2 * 1024 * 1024)) - for name in SOURCES_TO_PIN}, + 'source_files': {**{name: sha256(read(REFERENCE / name, 2 * 1024 * 1024)) + for name in SOURCES_TO_PIN}, + 'tls_fault.py': sha256(read(ROOT / 'qualification/run/tls_fault.py', 2 * 1024 * 1024))}, 'source_recipe_sha256': sha256(read(SOURCES[reference.FAMILY] / 'recipe.json', 65536)), 'profile_lock_sha256': sha256(read(SOURCES[reference.FAMILY] / 'profile.lock.json', 65536)), 'decision_record_sha256': sha256(read(ROOT / 'docs/adr' / adr, 65536))} diff --git a/qualification/reference/network_fault.py b/qualification/reference/network_fault.py new file mode 100644 index 000000000..8b4da84e3 --- /dev/null +++ b/qualification/reference/network_fault.py @@ -0,0 +1,172 @@ +"""Disposable Linux UID isolation and transparent provider-response faults. + +Only reviewed provider addresses are redirected. TLS remains end to end, and +an independent provider read, rather than traffic, decides whether a response +can be lost. All rules are removed individually; no shared chain is flushed. +""" + +import asyncio +from contextlib import AbstractContextManager +import ipaddress +import os +from pathlib import Path +import socket +import subprocess +import sys +import threading +import time + +from common import Refusal, require +import measure +from production_setup import APPLICATION_UID, GATEWAY_UID + +sys.path.insert(0, str(Path(__file__).resolve().parents[1] / 'run')) +from tls_fault import Fault, ORIGINS, MAX_RECORD, relay + +AUTHOR_UID = 62002 + + +class Rules(AbstractContextManager): + def __init__(self): + require(sys.platform == 'linux' and os.getuid() == 0, 'qualification.network.identity') + self.removals = [] + + def add(self, executable, table, arguments): + require(executable in ['iptables', 'ip6tables'] and table in ['filter', 'nat'] + and arguments[0] == '-A', 'qualification.network.rule') + self.command(executable, table, arguments) + self.removals.append((executable, table, ['-D', *arguments[1:]])) + + @staticmethod + def command(executable, table, arguments): + result = subprocess.run([executable, '-w', '5', '-t', table, *map(str, arguments)], + stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, + timeout=15, env={'PATH': '/usr/sbin:/usr/bin:/sbin:/bin'}) + require(result.returncode == 0, 'qualification.network.rule-refused') + + def __exit__(self, kind, value, traceback): + failures = [] + for executable, table, arguments in reversed(self.removals): + try: + self.command(executable, table, arguments) + except (Refusal, OSError, subprocess.SubprocessError): + failures.append(True) + self.removals = [] + require(not failures, 'qualification.network.cleanup-refused') + + +class Isolation(Rules): + def __enter__(self): + try: + for executable in ['iptables', 'ip6tables']: + for owner in [AUTHOR_UID, APPLICATION_UID]: + self.add(executable, 'filter', ['-A', 'OUTPUT', '-m', 'owner', '--uid-owner', owner, + '-m', 'comment', '--comment', 'auths-qualification-' + str(os.getpid()), '-j', 'REJECT']) + except BaseException: + self.__exit__(None, None, None) + raise + return self + + +class NativeWitness: + """Read a live gateway's actual diagnostic; never synthesize a counter scope.""" + def __init__(self, deployment, host, context): + self.deployment, self.host, self.context = deployment, host, context + self.before = self.last = deployment.witness(host, context) + + def entered(self): + current = self.deployment.witness(self.host, self.context) + measure.delta(self.last, current) + counted = measure.delta(self.before, current) + require(counted['write_transport_entries'] <= 1, 'qualification.fault.multiple-writes') + self.last = current + return counted['write_transport_entries'] == 1 + + +class ResponseFault(Rules): + def __init__(self, family, witness): + super().__init__() + require(family in ORIGINS, 'qualification.fault.family') + self.witness = witness + self.approved = {entry[4][0] for entry in socket.getaddrinfo( + ORIGINS[family], 443, socket.AF_INET, socket.SOCK_STREAM)} + self.ipv6 = {entry[4][0] for entry in socket.getaddrinfo( + ORIGINS[family], 443, socket.AF_UNSPEC, socket.SOCK_STREAM) if entry[0] == socket.AF_INET6} + require(1 <= len(self.approved) <= 16 and len(self.ipv6) <= 16 + and all(ipaddress.ip_address(value).is_global for value in self.approved | self.ipv6), + 'qualification.fault.provider-address') + self.ready, self.finished = threading.Event(), threading.Event() + self.failure, self.loop, self.fault, self.port = None, None, None, None + self.thread = threading.Thread(target=self.run, name='auths-transparent-response-fault', daemon=True) + + async def serving(self): + self.loop = asyncio.get_running_loop() + self.fault = Fault(self.witness) + server = await asyncio.start_server(lambda r, w: relay(r, w, self.fault, self.approved), + '127.0.0.1', 0, limit=MAX_RECORD * 2) + self.port = server.sockets[0].getsockname()[1] + self.ready.set() + try: + async with server: + while not self.finished.is_set(): + await asyncio.sleep(0.05) + finally: + server.close() + await server.wait_closed() + + def run(self): + try: + asyncio.run(self.serving()) + except BaseException: + self.failure = True + self.ready.set() + + def __enter__(self): + self.thread.start() + try: + require(self.ready.wait(10) and not self.failure and self.port is not None, + 'qualification.fault.relay-not-ready') + for address in sorted(self.approved): + self.add('iptables', 'nat', ['-A', 'OUTPUT', '-m', 'owner', '--uid-owner', GATEWAY_UID, + '-p', 'tcp', '-d', address, '--dport', 443, '-j', 'REDIRECT', '--to-ports', self.port]) + # An alternate IPv6 route must not evade the held response. Reject + # only this provider's addresses; custody and database stay usable. + for address in sorted(self.ipv6): + self.add('ip6tables', 'filter', ['-A', 'OUTPUT', '-m', 'owner', '--uid-owner', GATEWAY_UID, + '-p', 'tcp', '-d', address, '--dport', 443, '-j', 'REJECT']) + except BaseException: + self.__exit__(None, None, None) + raise + return self + + def held(self): + deadline = time.monotonic() + 30 + while time.monotonic() < deadline: + require(not self.failure and self.thread.is_alive(), 'qualification.fault.relay-refused') + if self.fault.armed and self.fault.held_connections > 0 and self.fault.buffered > 0: + require(self.witness.entered(), 'qualification.fault.unmeasured-entry') + return + time.sleep(0.05) + require(False, 'qualification.fault.response-not-held') + + def decide(self, decision): + require(decision in ['drop', 'release'], 'qualification.fault.control-state') + completed, failed = threading.Event(), [] + def apply(): + try: + self.fault.decide({'command': decision}) + except BaseException: + failed.append(True) + finally: + completed.set() + self.loop.call_soon_threadsafe(apply) + require(completed.wait(5) and not failed, 'qualification.fault.control-state') + + def __exit__(self, kind, value, traceback): + # First remove routing, then finish retained encrypted connections. + try: + super().__exit__(kind, value, traceback) + finally: + self.finished.set() + self.thread.join(timeout=10) + require(not self.thread.is_alive(), 'qualification.fault.relay-stop') diff --git a/qualification/reference/retained_author.py b/qualification/reference/retained_author.py new file mode 100644 index 000000000..51de534c3 --- /dev/null +++ b/qualification/reference/retained_author.py @@ -0,0 +1,87 @@ +"""Root controller adapter for one isolated installed-SDK author session. + +The dedicated UID retains its key in memory. The controller copies public +inputs and outputs only; refresh accepts one original source packet label. +""" + +import os +from pathlib import Path +import subprocess +import time + +from author_socket import exchange, refresh +from common import require +from expand import decode, read +from packet_plan import public_pool +from resource_io import write_bytes + +AUTHOR_UID = 62002 + + +class RetainedAuthor: + def __init__(self, python, kit, work, private): + require(os.getuid() == 0, 'qualification.packets.controller-identity') + self.work, self.private = Path(work).absolute(), Path(private).absolute() + self.python, self.kit = Path(python).absolute(), Path(kit).absolute() + require(not self.private.exists() and not self.private.is_relative_to(self.work) + and self.private.resolve() == self.private, + 'qualification.packets.private-session') + self.private.mkdir(mode=0o711) + os.chmod(self.private, 0o711) + self.author = self.private / 'author' + self.author.mkdir(mode=0o700) + self.outputs = self.private / 'handoffs' + self.outputs.mkdir(mode=0o700) + for name in ['packet-plan.json', 'resources.json', 'recipe.json', 'profile.lock.json']: + path = self.author / name + write_bytes(path, read(self.work / name, 65536), new=True) + os.chown(path, AUTHOR_UID, AUTHOR_UID) + os.chown(self.author, AUTHOR_UID, AUTHOR_UID) + plan = decode(read(self.work / 'packet-plan.json', 65536)) + resources = decode(read(self.work / 'resources.json', 65536)) + self.generation = 0 + self.process = subprocess.Popen([str(self.python), '-B', str(self.kit / 'author_socket.py'), + 'serve', '--plan', str(self.author / 'packet-plan.json'), '--work', str(self.author)], + stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, + cwd='/', user=AUTHOR_UID, group=AUTHOR_UID, extra_groups=[], + env={'PATH': '/usr/bin:/bin', 'PYTHONNOUSERSITE': '1'}) + try: + deadline = time.monotonic() + 30 + while not (self.author / 'author.sock').exists() and time.monotonic() < deadline: + require(self.process.poll() is None, 'qualification.packets.author-refused') + time.sleep(0.05) + require((self.author / 'author.sock').exists(), 'qualification.packets.author-timeout') + require(exchange(self.author, 'inspect')['generation'] == 0, + 'qualification.packets.generation') + carrier = decode(read(self.author / 'public-packets.json', 65536)) + packets = public_pool(plan['family'], resources, plan['packets'][0]['arguments']['recipe_digest'], carrier) + self.labels = {packet['label'] for packet in packets} + names = ['public-packets.json', 'author-report.json', *carrier['trusted_contexts']] + names += [packet[field] for packet in packets for field in ['proof', 'action']] + for name in names: + write_bytes(self.work / name, read(self.author / name, 4 * 1024 * 1024), new=True) + except BaseException: + self.abort() + raise + + def refresh(self, label): + require(label in self.labels and self.process.poll() is None, + 'qualification.packets.unknown-label') + self.generation += 1 + destination = self.outputs / ('refresh-' + str(self.generation).zfill(4)) + refresh(self.author, label, destination) + require(exchange(self.author, 'inspect')['generation'] == self.generation, + 'qualification.packets.generation') + return destination + + def close(self): + require(self.process.poll() is None, 'qualification.packets.author-refused') + exchange(self.author, 'close') + self.process.wait(timeout=10) + require(self.process.returncode == 0 and not (self.author / 'author.sock').exists(), + 'qualification.packets.author-refused') + + def abort(self): + if self.process.poll() is None: + self.process.kill() + self.process.wait(timeout=10) diff --git a/qualification/reference/tests/test_controller_socket.py b/qualification/reference/tests/test_controller_socket.py index 8910a80c8..075cbe7cb 100644 --- a/qualification/reference/tests/test_controller_socket.py +++ b/qualification/reference/tests/test_controller_socket.py @@ -54,17 +54,15 @@ def step(self, case, index, operation): directory = Path(temporary).resolve() directory.chmod(0o700) endpoint = directory / 'controller.sock' - stopping = threading.Event() + stopping, ready = threading.Event(), threading.Event() failures = [] def run(): - try: controller.serve(endpoint, Operations(), time.monotonic() + 30, stopping) + try: controller.serve(endpoint, Operations(), time.monotonic() + 30, stopping, ready) except BaseException as error: failures.append(error) thread = threading.Thread(target=run) thread.start() try: - deadline = time.monotonic() + 5 - while not endpoint.exists() and not failures and time.monotonic() < deadline: - time.sleep(0.01) + self.assertTrue(ready.wait(5)) with self.assertRaisesRegex(Refusal, 'operations.not-implemented'): controller.call(endpoint, FAMILY, 'commissioning-proof-replay', 0, 'submit') finally: diff --git a/qualification/reference/tests/test_network_fault.py b/qualification/reference/tests/test_network_fault.py new file mode 100644 index 000000000..cade70a3c --- /dev/null +++ b/qualification/reference/tests/test_network_fault.py @@ -0,0 +1,59 @@ +"""Rule rollback and actual-witness boundaries, without network or authority.""" + +from pathlib import Path +import sys +import unittest +from unittest.mock import patch + +sys.path.insert(0, str(Path(__file__).resolve().parents[1])) +from common import Refusal +import network_fault as network + + +class Network(unittest.TestCase): + def rules(self): + value = object.__new__(network.Rules) + value.removals = [] + return value + + def test_only_own_rules_are_removed_in_reverse_order_even_if_one_removal_fails(self): + rules, calls = self.rules(), [] + def command(executable, table, arguments): + calls.append((executable, table, arguments)) + with patch.object(rules, 'command', command): + rules.add('iptables', 'nat', ['-A', 'OUTPUT', '-d', '192.0.2.1', '-j', 'REDIRECT']) + rules.add('ip6tables', 'filter', ['-A', 'OUTPUT', '-d', '2001:db8::1', '-j', 'REJECT']) + rules.__exit__(None, None, None) + self.assertEqual([item[2][0] for item in calls], ['-A', '-A', '-D', '-D']) + self.assertEqual(calls[2][0], 'ip6tables') + self.assertEqual(calls[3][0], 'iptables') + self.assertFalse(rules.removals) + rules.removals = [('iptables', 'nat', ['-D', 'first']), ('ip6tables', 'filter', ['-D', 'second'])] + calls.clear() + def fail(executable, table, arguments): + command(executable, table, arguments) + raise Refusal('qualification.network.rule-refused') + with patch.object(rules, 'command', fail), self.assertRaisesRegex(Refusal, 'cleanup-refused'): + rules.__exit__(None, None, None) + self.assertEqual(len(calls), 2) + self.assertFalse(rules.removals) + + def test_pending_native_scope_and_monotonicity_are_required_to_arm_a_fault(self): + before = {'schema': 'auths.gateway-execution-witness/1', 'scope': '1' * 32, + 'credential_lease_calls': 0, 'write_transport_entries': 0, 'read_transport_entries': 0} + class Deployment: + current = before + def witness(self, host, context): return self.current + deployment = Deployment() + witness = network.NativeWitness(deployment, 0, 0) + self.assertFalse(witness.entered()) + deployment.current = dict(before, credential_lease_calls=1, write_transport_entries=1) + self.assertTrue(witness.entered()) + for changed in [dict(deployment.current, scope='2' * 32), + dict(deployment.current, write_transport_entries=2), before]: + deployment.current = changed + with self.assertRaises(Refusal): witness.entered() + + +if __name__ == '__main__': + unittest.main() From 3a470045e384cb0df0490ab5191af253caa03372 Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 16:42:01 +0100 Subject: [PATCH 090/108] Measure interrupted owners and two-host recovery from native evidence --- .../airtable-record-update-v1/contract.json | 2 +- .../corpus-manifest.json | 2 +- .../stripe-platform-refund-v1/contract.json | 2 +- .../corpus-manifest.json | 2 +- qualification/reference/README.md | 11 ++ qualification/reference/family_corpus.py | 6 +- qualification/reference/family_operations.py | 152 +++++++++++++++++- qualification/reference/native_observation.py | 99 +++++++++++- qualification/reference/production_setup.py | 67 +++++++- .../tests/test_native_observation.py | 59 +++++++ .../reference/tests/test_tls_fault.py | 14 ++ qualification/run/tls_fault.py | 5 +- 12 files changed, 406 insertions(+), 15 deletions(-) diff --git a/qualification/families/airtable-record-update-v1/contract.json b/qualification/families/airtable-record-update-v1/contract.json index c8eeda692..93696c503 100644 --- a/qualification/families/airtable-record-update-v1/contract.json +++ b/qualification/families/airtable-record-update-v1/contract.json @@ -1 +1 @@ -{"api_release":"web-api-v0-reviewed-2026-10-07","corpus_manifest_sha256":"6f517e64678419c034ceb2f976e871dc0dd5bb7f8d9a7f8a1d45de01850b5a8d","declarations":{"idempotency_sha256":"74234e98afe7498fb5daf1f36ac2d78acc339464f950703b8c019892f982b90b","observation_sha256":"9dd79dd204fa13a2df3c667d106c66c0526d174a2c018631e2b2f6b897eaf311","recovery_sha256":"7081a92b4cd2d13dab5e7c30e640675a252b62bca20d340e14d62d9c8c048eca","retention_sha256":"4a4b5048c97b16e041af55b032c0b8ac20f5142c4bbcbf31b31c6674770a70d0"},"environment_class":"disposable-live-resources","manual_assumptions":["Airtable supplies no idempotency key for this PATCH; durable gateway admission prevents a second entry.","Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only a fresh GET with the exact replacement and echo can reconcile a lost response.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths.","The reviewed fixed Airtable base and table contain only owner-authorized disposable qualification records."],"oracle_version":"auths-reviewed-reference-v2","provider":"airtable","schema":"auths.provider-contract/1"} \ No newline at end of file +{"api_release":"web-api-v0-reviewed-2026-10-07","corpus_manifest_sha256":"742269cd42c8e72dbd12f0317e45fd95746e8bccc0f361c8ad5740682584edd7","declarations":{"idempotency_sha256":"74234e98afe7498fb5daf1f36ac2d78acc339464f950703b8c019892f982b90b","observation_sha256":"9dd79dd204fa13a2df3c667d106c66c0526d174a2c018631e2b2f6b897eaf311","recovery_sha256":"7081a92b4cd2d13dab5e7c30e640675a252b62bca20d340e14d62d9c8c048eca","retention_sha256":"4a4b5048c97b16e041af55b032c0b8ac20f5142c4bbcbf31b31c6674770a70d0"},"environment_class":"disposable-live-resources","manual_assumptions":["Airtable supplies no idempotency key for this PATCH; durable gateway admission prevents a second entry.","Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only a fresh GET with the exact replacement and echo can reconcile a lost response.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths.","The reviewed fixed Airtable base and table contain only owner-authorized disposable qualification records."],"oracle_version":"auths-reviewed-reference-v2","provider":"airtable","schema":"auths.provider-contract/1"} \ No newline at end of file diff --git a/qualification/families/airtable-record-update-v1/corpus-manifest.json b/qualification/families/airtable-record-update-v1/corpus-manifest.json index f5c45091d..73dae9e39 100644 --- a/qualification/families/airtable-record-update-v1/corpus-manifest.json +++ b/qualification/families/airtable-record-update-v1/corpus-manifest.json @@ -1 +1 @@ -{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"32241d9b4811a55abcdd224ef567df3857dbec34d761ef7a35d1044cdfa52d9f","family":"airtable-record-update-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"af7f984509ab11a3676cacc85eda2fa638c25bf91f7bfedf3ff3c119e47f3c41","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","controller_socket.py":"10519cc775e963360870eac51c7fcac1ffb988b04d5de89dac1dbf3524ba6531","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"e58dc84b60f5ff13e5c7b1b5aae4917c5427f31cc8ac041acdd85defc8cd5e92","family_harness.py":"ed0136600a25c9f12bdcca73b105c3968271ccd227f42ad03a884cf5b9430de6","family_operations.py":"f6f7e54714228af7b48f2691c4ee15b5b2b34ebd5eb7b19dab61d26734bf7ce5","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","installed_submit.py":"f78b91ca7c57ea6909793973ca63fb33f18589ac8acbcb15e8886511e3d6fc50","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"4896a5f16474cbb418decb719bcc2af4a08483eabeca996427b40560a16d02cf","network_fault.py":"986ca0c9d7d534c2a1ebdd09edb4e6f94c17bb4bfcb35d57307c97419ed20894","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","production_setup.py":"795f47b92d806171e866510b75557bb6ece1fd1d14f6f51bf5330c25bbf80519","provider_readback.py":"d576768208985b3544f146597d181d796f2a5e2eca5026dae3fa15cadcfe65b2","resource_io.py":"b0ed0223fd11a1a28c25278de539a9b2ed63881b26a8e00e386f25d4d9aa9384","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","retained_author.py":"bfd01c7df44f5f525326dfbda13b5ebc6b854f15787a8b2923de883fe20fdcf9","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489","tls_fault.py":"d19ad37a5d37712fe274dbaddfcf062e444aab356e3c28c8cb2f533833b33ece"},"source_recipe_sha256":"c0f21ff1d3c8e344fee20a9a0c25bb14a264417ed53418ad536789a6096fb16e"} \ No newline at end of file +{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"32241d9b4811a55abcdd224ef567df3857dbec34d761ef7a35d1044cdfa52d9f","family":"airtable-record-update-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"af7f984509ab11a3676cacc85eda2fa638c25bf91f7bfedf3ff3c119e47f3c41","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","controller_socket.py":"10519cc775e963360870eac51c7fcac1ffb988b04d5de89dac1dbf3524ba6531","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"6157d5bb0a7510bb09c0e90c5f8051d393f0edbfeb536088e43ac485026740d1","family_harness.py":"ed0136600a25c9f12bdcca73b105c3968271ccd227f42ad03a884cf5b9430de6","family_operations.py":"f70e8ad62c6407afdcdbb4a75518cf89a9e354fca45b8736dbb549be73e9c4f7","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","installed_submit.py":"f78b91ca7c57ea6909793973ca63fb33f18589ac8acbcb15e8886511e3d6fc50","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"8bfe74a120ba57e9443a69146c0d09843a012b198206b8a594c5504acb916aec","network_fault.py":"986ca0c9d7d534c2a1ebdd09edb4e6f94c17bb4bfcb35d57307c97419ed20894","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","production_setup.py":"1b3fce73d7bd945da07c22b9508e2179361b95970a7115c40869019124c9ee4c","provider_readback.py":"d576768208985b3544f146597d181d796f2a5e2eca5026dae3fa15cadcfe65b2","resource_io.py":"b0ed0223fd11a1a28c25278de539a9b2ed63881b26a8e00e386f25d4d9aa9384","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","retained_author.py":"bfd01c7df44f5f525326dfbda13b5ebc6b854f15787a8b2923de883fe20fdcf9","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489","tls_fault.py":"078c11110315b479d5d57c0c987d177134a645717d3c81039d37b9a057588e12"},"source_recipe_sha256":"c0f21ff1d3c8e344fee20a9a0c25bb14a264417ed53418ad536789a6096fb16e"} \ No newline at end of file diff --git a/qualification/families/stripe-platform-refund-v1/contract.json b/qualification/families/stripe-platform-refund-v1/contract.json index 7878317dd..01dce2a5e 100644 --- a/qualification/families/stripe-platform-refund-v1/contract.json +++ b/qualification/families/stripe-platform-refund-v1/contract.json @@ -1 +1 @@ -{"api_release":"2025-03-31.basil","corpus_manifest_sha256":"2b9f0e171966d6ee8fb7d65cfe6f657562083f56faf7c141efb7db2150ebbd15","declarations":{"idempotency_sha256":"425a0dca2f279765debfc847c4a01bff60fea5be68dd9d761ae6bb60ce0b8a7b","observation_sha256":"d0ce5a34d987821c69c0a839d9ed66805c625f8324dd42031fcccf0752a8821e","recovery_sha256":"bf2303abce165c175360ac975586431bbc4cf03167489ea317a27de2f0b04abb","retention_sha256":"846c2164e26d1144d9aa146034b4f7ea4dc305136a59ffd94f999d19f2c360ee"},"environment_class":"provider-test-mode","manual_assumptions":["Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","Stripe idempotency is tested only inside the declared 86400-second retention interval.","Stripe test mode and the installed platform are checked by the declared guard on each lease.","The 50-percent payment basis is a read, not an atomic provider balance reservation.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths."],"oracle_version":"auths-reviewed-reference-v2","provider":"stripe","schema":"auths.provider-contract/1"} \ No newline at end of file +{"api_release":"2025-03-31.basil","corpus_manifest_sha256":"bf756830807b22a7e2b1dcef10b4630c9ed575bf0ae0dd213aa50e9151b97382","declarations":{"idempotency_sha256":"425a0dca2f279765debfc847c4a01bff60fea5be68dd9d761ae6bb60ce0b8a7b","observation_sha256":"d0ce5a34d987821c69c0a839d9ed66805c625f8324dd42031fcccf0752a8821e","recovery_sha256":"bf2303abce165c175360ac975586431bbc4cf03167489ea317a27de2f0b04abb","retention_sha256":"846c2164e26d1144d9aa146034b4f7ea4dc305136a59ffd94f999d19f2c360ee"},"environment_class":"provider-test-mode","manual_assumptions":["Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","Stripe idempotency is tested only inside the declared 86400-second retention interval.","Stripe test mode and the installed platform are checked by the declared guard on each lease.","The 50-percent payment basis is a read, not an atomic provider balance reservation.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths."],"oracle_version":"auths-reviewed-reference-v2","provider":"stripe","schema":"auths.provider-contract/1"} \ No newline at end of file diff --git a/qualification/families/stripe-platform-refund-v1/corpus-manifest.json b/qualification/families/stripe-platform-refund-v1/corpus-manifest.json index d1826ba8e..da3b4685f 100644 --- a/qualification/families/stripe-platform-refund-v1/corpus-manifest.json +++ b/qualification/families/stripe-platform-refund-v1/corpus-manifest.json @@ -1 +1 @@ -{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"a72c557b69103a52eb477deb8364ded53cd58407b9ba7ab33ccbda74389fec1e","family":"stripe-platform-refund-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"99901e36cb7c4f5882897603c874698d582e859b5d6b08d53cd80975e89aa01c","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","controller_socket.py":"10519cc775e963360870eac51c7fcac1ffb988b04d5de89dac1dbf3524ba6531","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"e58dc84b60f5ff13e5c7b1b5aae4917c5427f31cc8ac041acdd85defc8cd5e92","family_harness.py":"ed0136600a25c9f12bdcca73b105c3968271ccd227f42ad03a884cf5b9430de6","family_operations.py":"f6f7e54714228af7b48f2691c4ee15b5b2b34ebd5eb7b19dab61d26734bf7ce5","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","installed_submit.py":"f78b91ca7c57ea6909793973ca63fb33f18589ac8acbcb15e8886511e3d6fc50","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"4896a5f16474cbb418decb719bcc2af4a08483eabeca996427b40560a16d02cf","network_fault.py":"986ca0c9d7d534c2a1ebdd09edb4e6f94c17bb4bfcb35d57307c97419ed20894","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","production_setup.py":"795f47b92d806171e866510b75557bb6ece1fd1d14f6f51bf5330c25bbf80519","provider_readback.py":"d576768208985b3544f146597d181d796f2a5e2eca5026dae3fa15cadcfe65b2","resource_io.py":"b0ed0223fd11a1a28c25278de539a9b2ed63881b26a8e00e386f25d4d9aa9384","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","retained_author.py":"bfd01c7df44f5f525326dfbda13b5ebc6b854f15787a8b2923de883fe20fdcf9","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489","tls_fault.py":"d19ad37a5d37712fe274dbaddfcf062e444aab356e3c28c8cb2f533833b33ece"},"source_recipe_sha256":"b1972d556f28433932a449636755077f7ee485ef90cca412f153bc7f18881368"} \ No newline at end of file +{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"a72c557b69103a52eb477deb8364ded53cd58407b9ba7ab33ccbda74389fec1e","family":"stripe-platform-refund-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"99901e36cb7c4f5882897603c874698d582e859b5d6b08d53cd80975e89aa01c","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","controller_socket.py":"10519cc775e963360870eac51c7fcac1ffb988b04d5de89dac1dbf3524ba6531","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"6157d5bb0a7510bb09c0e90c5f8051d393f0edbfeb536088e43ac485026740d1","family_harness.py":"ed0136600a25c9f12bdcca73b105c3968271ccd227f42ad03a884cf5b9430de6","family_operations.py":"f70e8ad62c6407afdcdbb4a75518cf89a9e354fca45b8736dbb549be73e9c4f7","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","installed_submit.py":"f78b91ca7c57ea6909793973ca63fb33f18589ac8acbcb15e8886511e3d6fc50","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"8bfe74a120ba57e9443a69146c0d09843a012b198206b8a594c5504acb916aec","network_fault.py":"986ca0c9d7d534c2a1ebdd09edb4e6f94c17bb4bfcb35d57307c97419ed20894","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","production_setup.py":"1b3fce73d7bd945da07c22b9508e2179361b95970a7115c40869019124c9ee4c","provider_readback.py":"d576768208985b3544f146597d181d796f2a5e2eca5026dae3fa15cadcfe65b2","resource_io.py":"b0ed0223fd11a1a28c25278de539a9b2ed63881b26a8e00e386f25d4d9aa9384","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","retained_author.py":"bfd01c7df44f5f525326dfbda13b5ebc6b854f15787a8b2923de883fe20fdcf9","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489","tls_fault.py":"078c11110315b479d5d57c0c987d177134a645717d3c81039d37b9a057588e12"},"source_recipe_sha256":"b1972d556f28433932a449636755077f7ee485ef90cca412f153bc7f18881368"} \ No newline at end of file diff --git a/qualification/reference/README.md b/qualification/reference/README.md index e8e1c8763..7c231cf4d 100644 --- a/qualification/reference/README.md +++ b/qualification/reference/README.md @@ -294,3 +294,14 @@ retains end-to-end TLS and requires actual native counters before arming. Application and author UIDs can be denied both IPv4 and IPv6 egress. These mechanisms do not establish protected case completion until the full journey executes them and the native runner verifies its measured observations. + +Interrupted-write handlers now lose a response only after the independent +provider reference observes the exact value and echo. Crash handlers kill the +actual commissioning owner or live gateway and require a native support bundle +with the exact tuple, context and durable Unknown operation key, alongside the +killed owner's native counter stream. The two-host race holds the owner's +response until the second host returns; actual distinct counter scopes are +aggregated without creating a synthetic witness. For Airtable, the follower's +committed read-only recovery makes the owner's response CAS lose, so the +reviewed race expects two leases in total. Protected execution still must +verify these expectations before any qualification can be issued. diff --git a/qualification/reference/family_corpus.py b/qualification/reference/family_corpus.py index bfaa5c3a5..339c5ca26 100644 --- a/qualification/reference/family_corpus.py +++ b/qualification/reference/family_corpus.py @@ -118,9 +118,11 @@ def add(phase, identifier, scenario, steps, capabilities=()): add(phase, 'proof-replay', 'proof-replay', [observed('submit', label(1)), replay()]) # The held owner response keeps an entered operation unresolved while # the second actual process races its claim. Airtable can take one - # read-only recovery lease; Stripe has no unrecorded response locator. + # read-only recovery lease; its committed observation makes the + # owner response CAS lose, so that owner takes no observation lease. + # Stripe has no unrecorded response locator; its owner confirms later. add(phase, 'two-host-race', 'two-instance-race', - [observed('race', label(2), leases=3 if reference is airtable_record else 2)]) + [observed('race', label(2), leases=2)]) for index, operation in [(3, 'restart'), (4, 'crash')]: ending = observed('replay', label(index), 1, 0, 1) if reference is airtable_record \ else unknown('replay', label(index)) diff --git a/qualification/reference/family_operations.py b/qualification/reference/family_operations.py index dc6b6f202..18a6b901b 100644 --- a/qualification/reference/family_operations.py +++ b/qualification/reference/family_operations.py @@ -6,12 +6,18 @@ """ from pathlib import Path +from concurrent.futures import ThreadPoolExecutor +import time import airtable_record import stripe_platform -from common import canonical, closed, require, sha256 +from common import canonical, closed, Refusal, require, sha256 from expand import child, decode, read from native_observation import Effects +from network_fault import NativeWitness, ResponseFault +from production_setup import GATEWAY_UID +from tls_fault import Witness +import measure from packet_plan import public_pool from resource_io import write_bytes @@ -40,6 +46,7 @@ def __init__(self, deployment, author, oracle, resources, reviewed): self.rotation_keys = None self.consumer_python = None self.consumer_kit = None + self.interrupted = set() def configure_consumers(self, python, kit): self.consumer_python, self.consumer_kit = Path(python).absolute(), Path(kit).absolute() @@ -116,6 +123,124 @@ def read_back(self, label): after = self.deployment.witness(0) return self.project(label, result, before, after) + def wait_for_effect(self, label): + deadline = time.monotonic() + 20 + while time.monotonic() < deadline: + try: + return self.oracle.fresh(self.reviewed[label], self.tuple['compiled_recipe_sha256']) + except Refusal: + # No mismatch can become a confirmation. A bounded retry + # lets the independent read observe a just-entered write. + time.sleep(0.5) + require(False, 'qualification.operations.effect-not-independently-observed') + + def lose_response(self, phase, label, *, crash=False): + handoff, packet = self.packet(label) + child = self.deployment.commissioning_child(handoff, packet) if phase == 'commissioning' else None + witness = Witness(child.witness, GATEWAY_UID) if child is not None else NativeWitness(self.deployment, 0, 0) + try: + with ResponseFault(self.family, witness) as fault, ThreadPoolExecutor(max_workers=1) as pool: + if child is not None: + child.start() + pending = None + else: + pending = pool.submit(self.deployment.application_submit, handoff, packet) + fault.held() + self.wait_for_effect(label) + if crash: + if child is not None: + child.crash() + else: + self.deployment.stop(0, crash=True) + # Preserve the killed owner's last actual scope. Its + # durable record is read by a separate native command. + before, after = witness.before, witness.last + support = self.deployment.support() + observed, fresh = self.effects.project_interrupted(self.tuple, self.reviewed[label], + self.resources, sha256(read(self.deployment.work / packet['trusted_context'], 4 * 1024 * 1024)), + support, before, after) + self.interrupted.add((phase, label)) + fault.decide('drop') + if pending is not None: + try: + pending.result(timeout=10) + except (Refusal, OSError): + pass # The stored native diagnostic, not this failure, is the evidence. + return self.observation(observed, fresh) + fault.decide('drop') + if child is not None: + execution = child.finish() + require(witness.entered() and execution['before'] == witness.before + and execution['after'] == witness.last, + 'qualification.operations.witness-binding') + return self.project(label, execution['result'], execution['before'], execution['after']) + result = pending.result(timeout=90) + return self.project(label, result, witness.before, self.deployment.witness(0)) + finally: + if child is not None: + child.abort() + + def race(self, phase, label): + handoff, packet = self.packet(label) + children = [self.deployment.commissioning_child(handoff, packet, host=host) + for host in [0, 1]] if phase == 'commissioning' else [] + witness = Witness(children[0].witness, GATEWAY_UID) if children else NativeWitness(self.deployment, 0, 0) + try: + with ResponseFault(self.family, witness) as fault, ThreadPoolExecutor(max_workers=2) as pool: + if children: + children[0].start() + owner = None + else: + owner = pool.submit(self.deployment.application_submit, handoff, packet, 0) + fault.held() + self.wait_for_effect(label) + # The follower finishes while the entered owner's response + # remains held. Its actual result and scope cannot be confused + # with the eventual owner's response or a process-local stub. + if children: + children[1].start() + follower = children[1].finish() + else: + follower_before = self.deployment.witness(1) + follower_result = self.deployment.application_submit(handoff, packet, 1) + follower = {'result': follower_result, 'before': follower_before, + 'after': self.deployment.witness(1)} + fault.decide('release') + if children: + first = children[0].finish() + require(witness.entered() and first['before'] == witness.before + and first['after'] == witness.last, 'qualification.operations.witness-binding') + else: + first = {'result': owner.result(timeout=90), 'before': witness.before, + 'after': self.deployment.witness(0)} + observed, fresh = self.effects.project_race(self.tuple, self.reviewed[label], self.resources, + [first['result'], follower['result']], + [(first['before'], first['after']), (follower['before'], follower['after'])], + self.oracle.fresh(self.reviewed[label], self.tuple['compiled_recipe_sha256'])) + return self.observation(observed, fresh) + finally: + for child in children: + child.abort() + + def resume_host(self, phase, label, *, crash): + if crash: + require((phase, label) in self.interrupted, 'qualification.operations.owner-not-interrupted') + if phase == 'live': + self.deployment.start(0) + else: + # The commissioning child was the actual owner. The running + # application process is deliberately still subject to its + # required production gate; reload its durable shared state. + self.deployment.stop(0) + self.deployment.start(0) + else: + before = self.deployment.witness(0) + self.deployment.stop(0) + self.deployment.start(0) + require(self.deployment.witness(0)['scope'] != before['scope'], + 'qualification.operations.restart-scope') + return self.completed_probe('gateway-' + ('crash' if crash else 'restart') + '-completed') + def completed_probe(self, code): # Completion is constructed only after that source operation returned # actual native/provider facts; a corpus's expected code is never read. @@ -182,6 +307,31 @@ def step(self, case, index, operation): if index == 1: require((case, 0) in self.completed, 'qualification.operations.order') result = self.submit(phase, label) if index == 0 else self.read_back(label) + elif identifier == 'two-host-race': + require(index == 0 and operation == 'race', 'qualification.operations.step') + result = self.race(phase, phase + '-02') + elif identifier in ['restart', 'crash']: + require(index in [0, 1, 2] and operation == ['submit', identifier, 'replay'][index], + 'qualification.operations.step') + label = phase + '-' + str(POSITIVES[identifier]).zfill(2) + if index: + require((case, index - 1) in self.completed, 'qualification.operations.order') + if index == 0: + result = self.lose_response(phase, label, crash=identifier == 'crash') + elif index == 1: + result = self.resume_host(phase, label, crash=identifier == 'crash') + else: + result = self.submit(phase, label) + elif identifier in ['ambiguous', 'response-loss']: + ending = 'replay' if identifier == 'ambiguous' else 'read-back' + require(index in [0, 1] and operation == ['drop-response', ending][index], + 'qualification.operations.step') + label = phase + '-' + str(POSITIVES[identifier]).zfill(2) + if index == 0: + result = self.lose_response(phase, label) + else: + require((case, 0) in self.completed, 'qualification.operations.order') + result = self.submit(phase, label) if ending == 'replay' else self.read_back(label) elif identifier in ['guard-ceiling', 'guard-currency']: require(self.reference is stripe_platform and index == 0 and operation == 'probe', 'qualification.operations.step') diff --git a/qualification/reference/native_observation.py b/qualification/reference/native_observation.py index 7658e2636..4894196e5 100644 --- a/qualification/reference/native_observation.py +++ b/qualification/reference/native_observation.py @@ -56,6 +56,72 @@ def result(value): return 'observed', kind, evidence +def interrupted_state(tuple_value, reviewed, trusted_context_sha256, support): + """Authenticate a killed owner's durable native Unknown diagnostic. + + The owner did not return a submit result. This is a distinct source of + evidence: the native store projects its durable Attempting record to + Unknown, for the exact operation key and installed tuple. + """ + closed(support, ['schema', 'gateway_package', 'gateway_version', 'semantic_closure_sha256', + 'build_sha256', 'recipe_sha256', 'profile_lock_sha256', 'trusted_context_sha256', + 'deployment', 'credential_store_kind', 'qualification', 'connection', 'attempts', 'codes']) + target = tuple_value['target'] + require(support['schema'] == 'auths.gateway-support-bundle/1' + and support['gateway_package'] == target['gateway_package'] + and support['gateway_version'] == target['gateway_version'] + and support['semantic_closure_sha256'] == tuple_value['gateway_semantic_closure_sha256'] + and support['build_sha256'] == target['gateway_build_sha256'] + and support['recipe_sha256'] == tuple_value['compiled_recipe_sha256'] + and support['profile_lock_sha256'] == tuple_value['profile_lock_sha256'] + and support['trusted_context_sha256'] == digest(trusted_context_sha256) + and support['deployment'] == 'production' + and support['credential_store_kind'] == target['credential_store_kind'] + and target['store_kind'] == 'postgresql-v1' + and target['store_schema'] == 'auths.lifecycle.postgresql/6' + and target['credential_store_kind'] == 'aws-secrets-manager-v1', + 'qualification.observation.interrupted-tuple') + qualification = support['qualification'] + closed(qualification, ['policy', 'state', 'code']) + require(qualification['policy'] == 'required' + and qualification['state'] in ['unqualified', 'candidate', 'qualified', 'stale', 'revoked'] + and (qualification['code'] is None or type(qualification['code']) is str), + 'qualification.observation.interrupted-qualification') + expected_codes = [] if qualification['code'] is None else [qualification['code']] + if support['connection'] is None: + expected_codes += ['gateway.support.connection-unavailable'] + else: + closed(support['connection'], ['state', 'generation', 'credential_generation', 'credential_held', 'in_flight']) + require(support['connection']['state'] == 'active' + and type(support['connection']['credential_held']) is bool, + 'qualification.observation.interrupted-connection') + for field in ['generation', 'credential_generation', 'in_flight']: + integer(support['connection'][field], 0, measure.MAXIMUM - 1) + require(support['codes'] == expected_codes, 'qualification.observation.interrupted-unavailable') + attempts = support['attempts'] + closed(attempts, ['listed', 'truncated', 'by_stage', 'identifiers']) + integer(attempts['listed'], 1, 256) + require(attempts['truncated'] is False and type(attempts['identifiers']) is list + and len(attempts['identifiers']) == attempts['listed'], + 'qualification.observation.interrupted-attempts') + stages, keys = {}, set() + for item in attempts['identifiers']: + closed(item, ['key_sha256', 'stage']) + digest(item['key_sha256']) + require(item['key_sha256'] not in keys and item['stage'] in ['not-entered', 'unknown', + 'response-recorded', 'observed', 'observed-by-provider'], + 'qualification.observation.interrupted-attempts') + keys.add(item['key_sha256']) + stages[item['stage']] = stages.get(item['stage'], 0) + 1 + require(type(attempts['by_stage']) is dict and all(type(count) is int for count in attempts['by_stage'].values()) + and attempts['by_stage'] == stages, 'qualification.observation.interrupted-attempts') + arguments = reviewed['arguments'] + key = sha256(b'auths.gateway-logical-operation/1\0' + arguments['operator_namespace'].encode() + + b'\0' + arguments['operation_id'].encode()) + require({'key_sha256': key, 'stage': 'unknown'} in attempts['identifiers'], + 'qualification.observation.interrupted-state') + + class Effects: """One journey's measured entries and confirmations, keyed by exact action. @@ -70,6 +136,33 @@ def __init__(self): self.tuple_sha256 = None def project(self, tuple_value, reviewed, resources, native_result, before, after, response=None): + return self._project(tuple_value, reviewed, resources, result(native_result), + measure.delta(before, after), response, status=native_result.get('status')) + + def project_race(self, tuple_value, reviewed, resources, native_results, pairs, response): + require(type(native_results) is list and len(native_results) == 2 and len(pairs) == 2, + 'qualification.observation.race-hosts') + decoded = [result(value) for value in native_results] + linked = [value for value in decoded if value[2] is not None] + require(linked and all(value[0] in ['observed', 'unknown'] + or (value[0] == 'refused' and value[1] == 'gateway.attempt.replay') for value in decoded) + and all(all(value[2][field] == linked[0][2][field] + for field in ['channel', 'echo', 'evidence_digest']) for value in linked), + 'qualification.observation.race-evidence') + # Both are actual host results; the survivor's read-only recovery can + # supply the link. Distinct native scopes are aggregated directly. + return self._project(tuple_value, reviewed, resources, linked[0], measure.aggregate(pairs), response, + status=next(value['status'] for value in native_results + if value['outcome'] == 'observed-by-provider')) + + def project_interrupted(self, tuple_value, reviewed, resources, trusted_context_sha256, support, before, after): + interrupted_state(tuple_value, reviewed, trusted_context_sha256, support) + counted = measure.delta(before, after) + require(counted['credential_lease_calls'] >= 1 and counted['write_transport_entries'] == 1, + 'qualification.observation.interrupted-entry') + return self._project(tuple_value, reviewed, resources, ('unknown', 'unknown', None), counted, None) + + def _project(self, tuple_value, reviewed, resources, decoded_result, counted, response, status=None): tuple_sha256 = sha256(b'auths.qualification-tuple/1\0' + canonical(tuple_value)) require(self.tuple_sha256 in [None, tuple_sha256], 'qualification.observation.changed-tuple') family = tuple_value['recipe_family'] @@ -86,10 +179,9 @@ def project(self, tuple_value, reviewed, resources, native_result, before, after arguments = reviewed['arguments'] expected_request = reference.request(arguments, resources, commitment, recipe_digest) require(reviewed['request'] == expected_request, 'qualification.observation.request') - counted = measure.delta(before, after) leases = integer(counted['credential_lease_calls'], 0, (1 << 32) - 1) writes = integer(counted['write_transport_entries'], 0, 1) - outcome, code, evidence = result(native_result) + outcome, code, evidence = decoded_result require(outcome != 'refused' or writes == 0, 'qualification.observation.refused-entry') key = (family, resources['protected_run'], arguments['operator_namespace'], arguments['operation_id']) binding = sha256(canonical({'arguments': arguments, 'action_commitment': commitment, @@ -106,8 +198,7 @@ def project(self, tuple_value, reviewed, resources, native_result, before, after else: require(type(response) is bytes and (writes == 1 or prior is not None), 'qualification.observation.unmeasured-effect') - require(native_result['status'] == 200 - or (native_result['status'] is None and reference is airtable_record), + require(status == 200 or (status is None and reference is airtable_record), 'qualification.observation.status') require(evidence['echo'] == echo(arguments['operator_namespace'], arguments['operation_id'], commitment), 'qualification.observation.echo') diff --git a/qualification/reference/production_setup.py b/qualification/reference/production_setup.py index 2d966eaf3..031916789 100644 --- a/qualification/reference/production_setup.py +++ b/qualification/reference/production_setup.py @@ -15,7 +15,7 @@ import time from author_operator import ALIAS -from common import closed, require, sha256 +from common import closed, Refusal, require, sha256 from expand import decode, read from resource_io import write_bytes @@ -268,7 +268,7 @@ def commission_arguments(self, operation, permit, host, context): return [operation, '--state-dir', self.state(host, context), '--from', permit, '--protected-run', resources['protected_run'], '--resource-binding', self.gateway / 'resources.json'] - def commissioning_submit(self, handoff, packet, host=0, context=0, witness=None): + def commissioning_arguments_for_packet(self, handoff, packet, host, context, witness=None): require(self.permit is not None, 'qualification.production.permit-not-registered') inputs = self.packet_inputs(handoff, packet, GATEWAY_UID) arguments = [*self.commission_arguments('commissioning-submit', self.permit, host, context), @@ -277,12 +277,27 @@ def commissioning_submit(self, handoff, packet, host=0, context=0, witness=None) require(Path(witness).parent == self.state(host, context) and not Path(witness).exists(), 'qualification.production.private-input') arguments += ['--witness-file', witness] - execution = self.command(arguments) + return arguments + + @staticmethod + def commissioning_execution(execution): closed(execution, ['schema', 'result', 'before', 'after']) require(execution['schema'] == 'auths.gateway-commissioning-execution/1', 'qualification.production.execution') return execution + def commissioning_submit(self, handoff, packet, host=0, context=0, witness=None): + arguments = self.commissioning_arguments_for_packet(handoff, packet, host, context, witness) + return self.commissioning_execution(self.command(arguments)) + + def commissioning_child(self, handoff, packet, host=0, context=0): + # This private native process owns the entered operation during the + # commissioning phase. Killing an unrelated serving process would not + # exercise loss of the actual owner. + witness = self.state(host, context) / ('witness-' + str(self.handoff_generation + 1) + '.jsonl') + arguments = self.commissioning_arguments_for_packet(handoff, packet, host, context, witness) + return CommissioningChild(self, arguments, witness) + def reobserve(self, operation, host=0, context=0): require(re.fullmatch(r'qlf-[0-9a-f]{48}', operation) is not None, 'qualification.production.operation') @@ -348,3 +363,49 @@ def retire_credentials(self): require(result['schema'] == 'auths.gateway-credential-collection/1' and type(result['deleted']) is int and result['deleted'] >= 0, 'qualification.production.credential-collection') + + +class CommissioningChild: + def __init__(self, deployment, arguments, witness): + self.deployment, self.arguments, self.witness = deployment, arguments, witness + self.canaries, self.process = deployment.canaries, None + self.consumed = False + + def start(self): + require(self.process is None and not self.consumed, 'qualification.production.child-consumed') + self.deadline = time.monotonic() + 90 + self.process = subprocess.Popen([str(self.deployment.binary), *map(str, self.arguments)], + stdin=subprocess.DEVNULL, stdout=subprocess.PIPE, stderr=subprocess.PIPE, + cwd=self.deployment.gateway, user=GATEWAY_UID, group=GATEWAY_UID, extra_groups=[], + env=self.deployment.environment()) + + def finish(self): + require(self.process is not None and not self.consumed, 'qualification.production.child-consumed') + try: + stdout, stderr = self.process.communicate(timeout=max(0.01, self.deadline - time.monotonic())) + except subprocess.TimeoutExpired: + self.abort() + raise Refusal('qualification.production.child-timeout') from None + self.consumed = True + result = subprocess.CompletedProcess([], self.process.returncode, stdout, stderr) + return Deployment.commissioning_execution(native_output(result, self.canaries)) + + def crash(self): + require(self.process is not None and not self.consumed and self.process.poll() is None, + 'qualification.production.child-not-running') + self.process.kill() + stdout, stderr = self.process.communicate(timeout=10) + self.consumed = True + require(self.process.returncode == -signal.SIGKILL, 'qualification.production.child-crash') + require(len(stdout) <= 65536 and len(stderr) <= 65536 + and all(value not in stdout + stderr for value in self.canaries), + 'qualification.production.secret-exposed') + + def abort(self): + if self.process is None: + return + if self.process.poll() is None: + self.process.kill() + if not self.consumed: + self.process.communicate(timeout=10) + self.consumed = True diff --git a/qualification/reference/tests/test_native_observation.py b/qualification/reference/tests/test_native_observation.py index eab6f31d2..ebbe35725 100644 --- a/qualification/reference/tests/test_native_observation.py +++ b/qualification/reference/tests/test_native_observation.py @@ -78,6 +78,65 @@ def test_a_read_only_recovery_confirms_only_its_measured_unknown_write(self): response=self.response) self.assertEqual(again['confirmed_by_read_back'], 0) + def support(self): + self.tuple.update(profile_lock_sha256='3' * 64, gateway_semantic_closure_sha256='4' * 64, + target={'gateway_package': 'auths-gateway', 'gateway_version': 'synthetic-only', + 'gateway_build_sha256': '5' * 64, 'store_kind': 'postgresql-v1', + 'store_schema': 'auths.lifecycle.postgresql/6', 'credential_store_kind': 'aws-secrets-manager-v1'}) + key = sha256(b'auths.gateway-logical-operation/1\0' + self.arguments['operator_namespace'].encode() + + b'\0' + self.arguments['operation_id'].encode()) + return {'schema': 'auths.gateway-support-bundle/1', 'gateway_package': 'auths-gateway', + 'gateway_version': 'synthetic-only', 'semantic_closure_sha256': '4' * 64, + 'build_sha256': '5' * 64, 'recipe_sha256': '1' * 64, 'profile_lock_sha256': '3' * 64, + 'trusted_context_sha256': '6' * 64, 'deployment': 'production', + 'credential_store_kind': 'aws-secrets-manager-v1', + 'qualification': {'policy': 'required', 'state': 'unqualified', 'code': 'gateway.qualification.missing'}, + 'connection': None, 'attempts': {'listed': 1, 'truncated': False, 'by_stage': {'unknown': 1}, + 'identifiers': [{'key_sha256': key, 'stage': 'unknown'}]}, + 'codes': ['gateway.qualification.missing', 'gateway.support.connection-unavailable']} + + def test_killed_client_is_not_evidence_without_exact_durable_native_unknown_and_entry(self): + support = self.support() + ledger = Effects() + facts, fresh = ledger.project_interrupted(self.tuple, self.review, self.resources, '6' * 64, + support, self.before, self.after) + self.assertEqual((facts['verdict']['outcome'], facts['provider_entries'], facts['confirmed_by_read_back']), + ('unknown', 1, 0)) + self.assertIsNone(fresh) + for problem in ['wrong-build', 'wrong-context', 'different-operation', 'not-unknown', 'truncated', + 'unavailable', 'no-entry', 'false-count']: + value, after = copy.deepcopy(support), self.after + if problem == 'wrong-build': value['build_sha256'] = '7' * 64 + if problem == 'wrong-context': value['trusted_context_sha256'] = '7' * 64 + if problem == 'different-operation': value['attempts']['identifiers'][0]['key_sha256'] = '7' * 64 + if problem == 'not-unknown': value['attempts']['identifiers'][0]['stage'] = 'response-recorded' + if problem == 'truncated': value['attempts']['truncated'] = True + if problem == 'unavailable': value['attempts'] = None + if problem == 'no-entry': after = self.before + if problem == 'false-count': value['attempts']['by_stage']['unknown'] = True + with self.subTest(problem=problem), self.assertRaises(Refusal): + Effects().project_interrupted(self.tuple, self.review, self.resources, '6' * 64, + value, self.before, after) + + def test_race_aggregates_distinct_actual_native_scopes_without_counting_a_second_confirmation(self): + second = dict(self.before, scope='2' * 32) + recovered = dict(second, credential_lease_calls=1, read_transport_entries=1) + ledger = Effects() + facts, fresh = ledger.project_race(self.tuple, self.review, self.resources, + [{'outcome': 'unknown'}, dict(self.observed, status=None)], + [(self.before, self.after), (second, recovered)], self.response) + self.assertEqual((facts['credential_leases'], facts['provider_entries'], facts['confirmed_by_read_back']), (2, 1, 1)) + self.assertEqual(fresh['response_sha256'], sha256(self.response)) + for other in [{'outcome': 'denied', 'code': 'action-outside-validity'}, + {'outcome': 'not-entered', 'code': 'gateway.attempt.persistence'}]: + with self.assertRaises(Refusal): + Effects().project_race(self.tuple, self.review, self.resources, + [self.observed, other], [(self.before, self.after), (second, recovered)], self.response) + with self.assertRaisesRegex(Refusal, 'duplicate-host'): + Effects().project_race(self.tuple, self.review, self.resources, + [self.observed, {'outcome': 'unknown'}], + [(self.before, self.after), (self.before, self.after)], self.response) + def test_wrong_response_echo_request_scope_and_ambiguous_claims_refuse(self): for problem in ['raw-bytes', 'echo', 'request', 'scope', 'extra-field', 'refused-entry']: ledger, value, review = Effects(), copy.deepcopy(self.observed), copy.deepcopy(self.review) diff --git a/qualification/reference/tests/test_tls_fault.py b/qualification/reference/tests/test_tls_fault.py index b1f258f78..cda1f0ef6 100644 --- a/qualification/reference/tests/test_tls_fault.py +++ b/qualification/reference/tests/test_tls_fault.py @@ -151,6 +151,20 @@ async def provider(reader, writer): pending = asyncio.create_task(reader.read(len(response))) await asyncio.sleep(0.05) self.assertFalse(pending.done(), 'response must be held after upstream receipt') + # A racing gateway's recovery connection must retain + # its independent route while the owner stays held. + follower, follower_writer = await asyncio.wait_for(asyncio.open_connection( + *endpoint, ssl=client_context, server_hostname='localhost'), 5) + follower_writer.write(request) + await follower_writer.drain() + self.assertEqual(await asyncio.wait_for(follower.readexactly(len(response)), 5), response) + self.assertFalse(pending.done()) + self.assertEqual(state.held_connections, 1) + follower_writer.close() + try: + await follower_writer.wait_closed() + except OSError: + pass state.decide({'command': command}) returned = await asyncio.wait_for(pending, 5) self.assertEqual(returned, response if command == 'release' else b'') diff --git a/qualification/run/tls_fault.py b/qualification/run/tls_fault.py index ffc4b764f..bc127b01e 100644 --- a/qualification/run/tls_fault.py +++ b/qualification/run/tls_fault.py @@ -191,7 +191,10 @@ async def client(): nonlocal held while True: kind, _payload, raw = await record(reader) - if not held and hello.client_boundary(kind) and fault.witness.entered(): + if not held and not fault.armed and hello.client_boundary(kind) and fault.witness.entered(): + # Exactly one connection owns this held write. A second + # gateway must retain its independent read-only recovery + # route while racing that durable claim. # Arm before forwarding Finished/the request so a fast # upstream response cannot overtake this boundary. held = True From 9dd368c07952b54a790b1d26c1ff173a228d36fc Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 16:52:23 +0100 Subject: [PATCH 091/108] Preserve native read-back refusals and validate actual production doctor evidence --- .../airtable-record-update-v1/contract.json | 2 +- .../corpus-manifest.json | 2 +- .../stripe-platform-refund-v1/contract.json | 2 +- .../corpus-manifest.json | 2 +- qualification/reference/README.md | 9 ++++ qualification/reference/family_corpus.py | 6 +-- qualification/reference/family_operations.py | 44 ++++++++++++++++++- qualification/reference/native_observation.py | 18 ++++++++ qualification/reference/production_setup.py | 32 +++++++++++--- .../tests/test_native_observation.py | 22 ++++++++++ 10 files changed, 124 insertions(+), 15 deletions(-) diff --git a/qualification/families/airtable-record-update-v1/contract.json b/qualification/families/airtable-record-update-v1/contract.json index 93696c503..7ce066695 100644 --- a/qualification/families/airtable-record-update-v1/contract.json +++ b/qualification/families/airtable-record-update-v1/contract.json @@ -1 +1 @@ -{"api_release":"web-api-v0-reviewed-2026-10-07","corpus_manifest_sha256":"742269cd42c8e72dbd12f0317e45fd95746e8bccc0f361c8ad5740682584edd7","declarations":{"idempotency_sha256":"74234e98afe7498fb5daf1f36ac2d78acc339464f950703b8c019892f982b90b","observation_sha256":"9dd79dd204fa13a2df3c667d106c66c0526d174a2c018631e2b2f6b897eaf311","recovery_sha256":"7081a92b4cd2d13dab5e7c30e640675a252b62bca20d340e14d62d9c8c048eca","retention_sha256":"4a4b5048c97b16e041af55b032c0b8ac20f5142c4bbcbf31b31c6674770a70d0"},"environment_class":"disposable-live-resources","manual_assumptions":["Airtable supplies no idempotency key for this PATCH; durable gateway admission prevents a second entry.","Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only a fresh GET with the exact replacement and echo can reconcile a lost response.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths.","The reviewed fixed Airtable base and table contain only owner-authorized disposable qualification records."],"oracle_version":"auths-reviewed-reference-v2","provider":"airtable","schema":"auths.provider-contract/1"} \ No newline at end of file +{"api_release":"web-api-v0-reviewed-2026-10-07","corpus_manifest_sha256":"b63bfb99d968e86dedc3f3afa262f138a6176ad2b06a290ff407cd6080192226","declarations":{"idempotency_sha256":"74234e98afe7498fb5daf1f36ac2d78acc339464f950703b8c019892f982b90b","observation_sha256":"9dd79dd204fa13a2df3c667d106c66c0526d174a2c018631e2b2f6b897eaf311","recovery_sha256":"7081a92b4cd2d13dab5e7c30e640675a252b62bca20d340e14d62d9c8c048eca","retention_sha256":"4a4b5048c97b16e041af55b032c0b8ac20f5142c4bbcbf31b31c6674770a70d0"},"environment_class":"disposable-live-resources","manual_assumptions":["Airtable supplies no idempotency key for this PATCH; durable gateway admission prevents a second entry.","Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only a fresh GET with the exact replacement and echo can reconcile a lost response.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths.","The reviewed fixed Airtable base and table contain only owner-authorized disposable qualification records."],"oracle_version":"auths-reviewed-reference-v2","provider":"airtable","schema":"auths.provider-contract/1"} \ No newline at end of file diff --git a/qualification/families/airtable-record-update-v1/corpus-manifest.json b/qualification/families/airtable-record-update-v1/corpus-manifest.json index 73dae9e39..d7a6a22c8 100644 --- a/qualification/families/airtable-record-update-v1/corpus-manifest.json +++ b/qualification/families/airtable-record-update-v1/corpus-manifest.json @@ -1 +1 @@ -{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"32241d9b4811a55abcdd224ef567df3857dbec34d761ef7a35d1044cdfa52d9f","family":"airtable-record-update-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"af7f984509ab11a3676cacc85eda2fa638c25bf91f7bfedf3ff3c119e47f3c41","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","controller_socket.py":"10519cc775e963360870eac51c7fcac1ffb988b04d5de89dac1dbf3524ba6531","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"6157d5bb0a7510bb09c0e90c5f8051d393f0edbfeb536088e43ac485026740d1","family_harness.py":"ed0136600a25c9f12bdcca73b105c3968271ccd227f42ad03a884cf5b9430de6","family_operations.py":"f70e8ad62c6407afdcdbb4a75518cf89a9e354fca45b8736dbb549be73e9c4f7","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","installed_submit.py":"f78b91ca7c57ea6909793973ca63fb33f18589ac8acbcb15e8886511e3d6fc50","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"8bfe74a120ba57e9443a69146c0d09843a012b198206b8a594c5504acb916aec","network_fault.py":"986ca0c9d7d534c2a1ebdd09edb4e6f94c17bb4bfcb35d57307c97419ed20894","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","production_setup.py":"1b3fce73d7bd945da07c22b9508e2179361b95970a7115c40869019124c9ee4c","provider_readback.py":"d576768208985b3544f146597d181d796f2a5e2eca5026dae3fa15cadcfe65b2","resource_io.py":"b0ed0223fd11a1a28c25278de539a9b2ed63881b26a8e00e386f25d4d9aa9384","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","retained_author.py":"bfd01c7df44f5f525326dfbda13b5ebc6b854f15787a8b2923de883fe20fdcf9","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489","tls_fault.py":"078c11110315b479d5d57c0c987d177134a645717d3c81039d37b9a057588e12"},"source_recipe_sha256":"c0f21ff1d3c8e344fee20a9a0c25bb14a264417ed53418ad536789a6096fb16e"} \ No newline at end of file +{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"32241d9b4811a55abcdd224ef567df3857dbec34d761ef7a35d1044cdfa52d9f","family":"airtable-record-update-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"af7f984509ab11a3676cacc85eda2fa638c25bf91f7bfedf3ff3c119e47f3c41","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","controller_socket.py":"10519cc775e963360870eac51c7fcac1ffb988b04d5de89dac1dbf3524ba6531","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"9cee4fac304abb67fe39b86df3b5a2522f385a6f1e62fcb5e15daa6f3f90b2d6","family_harness.py":"ed0136600a25c9f12bdcca73b105c3968271ccd227f42ad03a884cf5b9430de6","family_operations.py":"778fd16c5e9b199aeab6057412d7f3381c1b15612d0de576f5a8bc163e31bc8b","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","installed_submit.py":"f78b91ca7c57ea6909793973ca63fb33f18589ac8acbcb15e8886511e3d6fc50","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"abebdf9f5704f0a19457347798548d98b3ddb3adbd48e91bc58a82faf4afbd08","network_fault.py":"986ca0c9d7d534c2a1ebdd09edb4e6f94c17bb4bfcb35d57307c97419ed20894","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","production_setup.py":"0bab950dd88f3d2094a60262402383b310844c727fa1b042c903497bcaac154f","provider_readback.py":"d576768208985b3544f146597d181d796f2a5e2eca5026dae3fa15cadcfe65b2","resource_io.py":"b0ed0223fd11a1a28c25278de539a9b2ed63881b26a8e00e386f25d4d9aa9384","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","retained_author.py":"bfd01c7df44f5f525326dfbda13b5ebc6b854f15787a8b2923de883fe20fdcf9","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489","tls_fault.py":"078c11110315b479d5d57c0c987d177134a645717d3c81039d37b9a057588e12"},"source_recipe_sha256":"c0f21ff1d3c8e344fee20a9a0c25bb14a264417ed53418ad536789a6096fb16e"} \ No newline at end of file diff --git a/qualification/families/stripe-platform-refund-v1/contract.json b/qualification/families/stripe-platform-refund-v1/contract.json index 01dce2a5e..54004af0d 100644 --- a/qualification/families/stripe-platform-refund-v1/contract.json +++ b/qualification/families/stripe-platform-refund-v1/contract.json @@ -1 +1 @@ -{"api_release":"2025-03-31.basil","corpus_manifest_sha256":"bf756830807b22a7e2b1dcef10b4630c9ed575bf0ae0dd213aa50e9151b97382","declarations":{"idempotency_sha256":"425a0dca2f279765debfc847c4a01bff60fea5be68dd9d761ae6bb60ce0b8a7b","observation_sha256":"d0ce5a34d987821c69c0a839d9ed66805c625f8324dd42031fcccf0752a8821e","recovery_sha256":"bf2303abce165c175360ac975586431bbc4cf03167489ea317a27de2f0b04abb","retention_sha256":"846c2164e26d1144d9aa146034b4f7ea4dc305136a59ffd94f999d19f2c360ee"},"environment_class":"provider-test-mode","manual_assumptions":["Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","Stripe idempotency is tested only inside the declared 86400-second retention interval.","Stripe test mode and the installed platform are checked by the declared guard on each lease.","The 50-percent payment basis is a read, not an atomic provider balance reservation.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths."],"oracle_version":"auths-reviewed-reference-v2","provider":"stripe","schema":"auths.provider-contract/1"} \ No newline at end of file +{"api_release":"2025-03-31.basil","corpus_manifest_sha256":"8b41bf8bf8af0e7fcbfb0c4987f0602910bc9f081a48fa0cb699e3160b06a29a","declarations":{"idempotency_sha256":"425a0dca2f279765debfc847c4a01bff60fea5be68dd9d761ae6bb60ce0b8a7b","observation_sha256":"d0ce5a34d987821c69c0a839d9ed66805c625f8324dd42031fcccf0752a8821e","recovery_sha256":"bf2303abce165c175360ac975586431bbc4cf03167489ea317a27de2f0b04abb","retention_sha256":"846c2164e26d1144d9aa146034b4f7ea4dc305136a59ffd94f999d19f2c360ee"},"environment_class":"provider-test-mode","manual_assumptions":["Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","Stripe idempotency is tested only inside the declared 86400-second retention interval.","Stripe test mode and the installed platform are checked by the declared guard on each lease.","The 50-percent payment basis is a read, not an atomic provider balance reservation.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths."],"oracle_version":"auths-reviewed-reference-v2","provider":"stripe","schema":"auths.provider-contract/1"} \ No newline at end of file diff --git a/qualification/families/stripe-platform-refund-v1/corpus-manifest.json b/qualification/families/stripe-platform-refund-v1/corpus-manifest.json index da3b4685f..d8f1ecc86 100644 --- a/qualification/families/stripe-platform-refund-v1/corpus-manifest.json +++ b/qualification/families/stripe-platform-refund-v1/corpus-manifest.json @@ -1 +1 @@ -{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"a72c557b69103a52eb477deb8364ded53cd58407b9ba7ab33ccbda74389fec1e","family":"stripe-platform-refund-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"99901e36cb7c4f5882897603c874698d582e859b5d6b08d53cd80975e89aa01c","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","controller_socket.py":"10519cc775e963360870eac51c7fcac1ffb988b04d5de89dac1dbf3524ba6531","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"6157d5bb0a7510bb09c0e90c5f8051d393f0edbfeb536088e43ac485026740d1","family_harness.py":"ed0136600a25c9f12bdcca73b105c3968271ccd227f42ad03a884cf5b9430de6","family_operations.py":"f70e8ad62c6407afdcdbb4a75518cf89a9e354fca45b8736dbb549be73e9c4f7","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","installed_submit.py":"f78b91ca7c57ea6909793973ca63fb33f18589ac8acbcb15e8886511e3d6fc50","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"8bfe74a120ba57e9443a69146c0d09843a012b198206b8a594c5504acb916aec","network_fault.py":"986ca0c9d7d534c2a1ebdd09edb4e6f94c17bb4bfcb35d57307c97419ed20894","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","production_setup.py":"1b3fce73d7bd945da07c22b9508e2179361b95970a7115c40869019124c9ee4c","provider_readback.py":"d576768208985b3544f146597d181d796f2a5e2eca5026dae3fa15cadcfe65b2","resource_io.py":"b0ed0223fd11a1a28c25278de539a9b2ed63881b26a8e00e386f25d4d9aa9384","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","retained_author.py":"bfd01c7df44f5f525326dfbda13b5ebc6b854f15787a8b2923de883fe20fdcf9","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489","tls_fault.py":"078c11110315b479d5d57c0c987d177134a645717d3c81039d37b9a057588e12"},"source_recipe_sha256":"b1972d556f28433932a449636755077f7ee485ef90cca412f153bc7f18881368"} \ No newline at end of file +{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"a72c557b69103a52eb477deb8364ded53cd58407b9ba7ab33ccbda74389fec1e","family":"stripe-platform-refund-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"99901e36cb7c4f5882897603c874698d582e859b5d6b08d53cd80975e89aa01c","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","controller_socket.py":"10519cc775e963360870eac51c7fcac1ffb988b04d5de89dac1dbf3524ba6531","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"9cee4fac304abb67fe39b86df3b5a2522f385a6f1e62fcb5e15daa6f3f90b2d6","family_harness.py":"ed0136600a25c9f12bdcca73b105c3968271ccd227f42ad03a884cf5b9430de6","family_operations.py":"778fd16c5e9b199aeab6057412d7f3381c1b15612d0de576f5a8bc163e31bc8b","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","installed_submit.py":"f78b91ca7c57ea6909793973ca63fb33f18589ac8acbcb15e8886511e3d6fc50","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"abebdf9f5704f0a19457347798548d98b3ddb3adbd48e91bc58a82faf4afbd08","network_fault.py":"986ca0c9d7d534c2a1ebdd09edb4e6f94c17bb4bfcb35d57307c97419ed20894","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","production_setup.py":"0bab950dd88f3d2094a60262402383b310844c727fa1b042c903497bcaac154f","provider_readback.py":"d576768208985b3544f146597d181d796f2a5e2eca5026dae3fa15cadcfe65b2","resource_io.py":"b0ed0223fd11a1a28c25278de539a9b2ed63881b26a8e00e386f25d4d9aa9384","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","retained_author.py":"bfd01c7df44f5f525326dfbda13b5ebc6b854f15787a8b2923de883fe20fdcf9","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489","tls_fault.py":"078c11110315b479d5d57c0c987d177134a645717d3c81039d37b9a057588e12"},"source_recipe_sha256":"b1972d556f28433932a449636755077f7ee485ef90cca412f153bc7f18881368"} \ No newline at end of file diff --git a/qualification/reference/README.md b/qualification/reference/README.md index 7c231cf4d..dad59bae3 100644 --- a/qualification/reference/README.md +++ b/qualification/reference/README.md @@ -305,3 +305,12 @@ aggregated without creating a synthetic witness. For Airtable, the follower's committed read-only recovery makes the owner's response CAS lose, so the reviewed race expects two leases in total. Protected execution still must verify these expectations before any qualification can be issued. + +Read-back cases retain native distinctions: an already linked terminal attempt +refuses redundant re-observation without a lease; a lost Stripe response cannot +acquire a locator from the controller's independent discovery. A refused Stripe +re-observation needs the exact durable native Unknown record and this journey's +previously measured unconfirmed entry before it can project Unknown. No refused +admin response becomes linked effect evidence. The production doctor is run as +root so its native application privilege-drop probe actually executes; its raw +validated report digest and exact installed tuple enter the native runner. diff --git a/qualification/reference/family_corpus.py b/qualification/reference/family_corpus.py index 339c5ca26..4a1247f8b 100644 --- a/qualification/reference/family_corpus.py +++ b/qualification/reference/family_corpus.py @@ -125,12 +125,12 @@ def add(phase, identifier, scenario, steps, capabilities=()): [observed('race', label(2), leases=2)]) for index, operation in [(3, 'restart'), (4, 'crash')]: ending = observed('replay', label(index), 1, 0, 1) if reference is airtable_record \ - else unknown('replay', label(index)) + else replay() add(phase, operation, operation, [unknown('submit', label(index), 1, 1), complete(operation, 'gateway-' + operation + '-completed'), ending]) add(phase, 'ambiguous', 'ambiguous-response', [unknown('drop-response', label(5), 1, 1), observed('replay', label(5), 1, 0, 1) if reference is airtable_record - else unknown('replay', label(5))]) + else replay()]) for index, identifier, operation, scenario in [ (6, 'response-loss', 'drop-response', 'response-loss'), (7, 'visibility', 'delay-visibility', 'delayed-visibility')]: @@ -141,7 +141,7 @@ def add(phase, identifier, scenario, steps, capabilities=()): add(phase, 'secret-rotation', 'provider-secret-rotation', [complete('rotate', 'provider-secret-rotated'), observed('submit', label(8))]) add(phase, 'read-back', 'read-back-confirms-write', [observed('submit', label(9)), - observed('read-back', label(9), 1, 0, 0)]) + step('read-back', 'refused', 'gateway.reobserve.not-observable')]) capabilities = ['echo', 'observation'] if reference is stripe_platform: capabilities = ['credential-guard', 'version-pin', 'account-binding', 'denied-reads', diff --git a/qualification/reference/family_operations.py b/qualification/reference/family_operations.py index 18a6b901b..a699fde3a 100644 --- a/qualification/reference/family_operations.py +++ b/qualification/reference/family_operations.py @@ -119,9 +119,19 @@ def submit(self, phase, label, host=0, context=0): def read_back(self, label): before = self.deployment.witness(0) - result = self.deployment.reobserve(self.reviewed[label]['arguments']['operation_id']) + response = self.deployment.reobserve(self.reviewed[label]['arguments']['operation_id']) after = self.deployment.witness(0) - return self.project(label, result, before, after) + if response['ok']: + return self.project(label, response['result'], before, after) + if label.endswith('-09'): + observed, fresh = self.effects.project_admin_refusal(self.tuple, self.reviewed[label], self.resources, + response, before, after) + else: + require(self.reference is stripe_platform, 'qualification.operations.recovery-refused') + observed, fresh = self.effects.project_stored_unknown(self.tuple, self.reviewed[label], self.resources, + sha256(read(self.deployment.work / self.packets[label]['trusted_context'], 4 * 1024 * 1024)), + self.deployment.support(), before, after) + return self.observation(observed, fresh) def wait_for_effect(self, label): deadline = time.monotonic() + 20 @@ -241,6 +251,33 @@ def resume_host(self, phase, label, *, crash): 'qualification.operations.restart-scope') return self.completed_probe('gateway-' + ('crash' if crash else 'restart') + '-completed') + def doctor(self): + require(self.phase == 'live', 'qualification.operations.phase') + for host in [0, 1]: + for context in [0, 1]: + require(self.deployment.command(['qualification-status', '--state-dir', + self.deployment.state(host, context), '--tuple']) == self.tuple, + 'qualification.operations.doctor-tuple') + before = self.deployment.witness(0) + report, raw = self.deployment.doctor() + closed(report, ['schema', 'ready', 'checks']) + expected = [{'check': name, 'ready': True, 'code': None} for name in [ + 'trust', 'store', 'recipe', 'qualification', 'provider-secret-custody', + 'connection-generation', 'clock', 'transport-policy', 'operator-plane-isolation']] + expected += [{'check': 'observer-custody', 'state': 'not-configured'}] + require(report['ready'] is True and type(report['checks']) is list + and all(type(item) is dict and item.get('ready') is True for item in report['checks'][:-1]) + and report == {'schema': 'auths.gateway-readiness/1', 'ready': True, 'checks': expected}, + 'qualification.operations.doctor-not-ready') + counts = measure.delta(before, self.deployment.witness(0)) + observation = self.observation({'verdict': {'outcome': 'complete', 'code': 'production-readiness-passed', + 'request_sha256': None, 'evidence_sha256': sha256(raw)}, + 'credential_leases': counts['credential_lease_calls'], 'provider_entries': counts['write_transport_entries'], + 'confirmed_by_read_back': 0}, {'kind': 'production-doctor', + 'tuple_sha256': sha256(b'auths.qualification-tuple/1\0' + canonical(self.tuple)), + 'report_sha256': sha256(raw)}) + return observation + def completed_probe(self, code): # Completion is constructed only after that source operation returned # actual native/provider facts; a corpus's expected code is never read. @@ -345,6 +382,9 @@ def step(self, case, index, operation): if index == 1: require((case, 0) in self.completed, 'qualification.operations.order') result = self.rotate() if index == 0 else self.submit(phase, phase + '-08') + elif identifier == 'doctor': + require(phase == 'live' and index == 0 and operation == 'probe', 'qualification.operations.step') + result = self.doctor() elif identifier == 'installed-python': require(index == 0 and operation == 'installed-consumer', 'qualification.operations.step') result = self.python_consumer(phase) diff --git a/qualification/reference/native_observation.py b/qualification/reference/native_observation.py index 4894196e5..80f10ada4 100644 --- a/qualification/reference/native_observation.py +++ b/qualification/reference/native_observation.py @@ -162,6 +162,24 @@ def project_interrupted(self, tuple_value, reviewed, resources, trusted_context_ 'qualification.observation.interrupted-entry') return self._project(tuple_value, reviewed, resources, ('unknown', 'unknown', None), counted, None) + def project_stored_unknown(self, tuple_value, reviewed, resources, trusted_context_sha256, support, before, after): + interrupted_state(tuple_value, reviewed, trusted_context_sha256, support) + counted = measure.delta(before, after) + key = (tuple_value['recipe_family'], resources['protected_run'], + reviewed['arguments']['operator_namespace'], reviewed['arguments']['operation_id']) + require(counted['credential_lease_calls'] == counted['write_transport_entries'] == 0 + and key in self.entries and not self.entries[key]['confirmed'], + 'qualification.observation.unmeasured-unknown') + return self._project(tuple_value, reviewed, resources, ('unknown', 'unknown', None), counted, None) + + def project_admin_refusal(self, tuple_value, reviewed, resources, response, before, after): + closed(response, ['schema', 'ok', 'code']) + require(response == {'schema': 'auths.gateway-admin-response/1', 'ok': False, + 'code': 'gateway.reobserve.not-observable'}, + 'qualification.observation.admin-refusal') + return self._project(tuple_value, reviewed, resources, ('refused', response['code'], None), + measure.delta(before, after), None) + def _project(self, tuple_value, reviewed, resources, decoded_result, counted, response, status=None): tuple_sha256 = sha256(b'auths.qualification-tuple/1\0' + canonical(tuple_value)) require(self.tuple_sha256 in [None, tuple_sha256], 'qualification.observation.changed-tuple') diff --git a/qualification/reference/production_setup.py b/qualification/reference/production_setup.py index 031916789..52743d28f 100644 --- a/qualification/reference/production_setup.py +++ b/qualification/reference/production_setup.py @@ -119,6 +119,8 @@ def __init__(self, binary, work, private, environment, canaries): write_bytes(path, read(self.work / name, 4 * 1024 * 1024), new=True) os.chown(path, GATEWAY_UID, GATEWAY_UID) os.chown(self.gateway, GATEWAY_UID, GATEWAY_UID) + require(len(str(self.state(0) / 'admin.sock').encode()) <= 107, + 'qualification.production.socket-bound') self.processes = {} self.handoff_generation = 0 self.permit = None @@ -301,10 +303,22 @@ def commissioning_child(self, handoff, packet, host=0, context=0): def reobserve(self, operation, host=0, context=0): require(re.fullmatch(r'qlf-[0-9a-f]{48}', operation) is not None, 'qualification.production.operation') - result = self.command(['reobserve', '--state-dir', self.state(host, context), '--operation-id', operation]) - closed(result, ['schema', 'ok', 'code', 'result']) - require(result['ok'] is True, 'qualification.production.reobserve') - return result['result'] + result = subprocess.run([str(self.binary), 'reobserve', '--state-dir', str(self.state(host, context)), + '--operation-id', operation], stdin=subprocess.DEVNULL, capture_output=True, timeout=90, + cwd=self.gateway, user=GATEWAY_UID, group=GATEWAY_UID, extra_groups=[], env=self.environment()) + # Native admin refusals still have a closed response on stdout. Read + # that response only for its exact normal refusal exit, after scanning. + native_output(result, self.canaries, required=False) + require(result.returncode == 0 or (result.returncode == 1 and result.stderr == b'gateway.admin.refused\n'), + 'qualification.production.reobserve') + response = decode(result.stdout) + closed(response, ['schema', 'ok', 'code', 'result'] if result.returncode == 0 else ['schema', 'ok', 'code']) + require(response['schema'] == 'auths.gateway-admin-response/1' + and response['ok'] is (result.returncode == 0) + and response['code'] == ('gateway.admin.reobserved' if result.returncode == 0 + else 'gateway.reobserve.not-observable'), + 'qualification.production.reobserve') + return response def rotate(self, credential): require(type(credential) is bytes and credential in self.canaries, @@ -344,8 +358,14 @@ def support(self, host=0, context=0): return self.command(['support-bundle', '--state-dir', self.state(host, context)]) def doctor(self, host=0, context=0): - return self.command(['doctor', '--state-dir', self.state(host, context), - '--app-socket', self.app_socket(host, context), '--app-uid', APPLICATION_UID, '--app-gid', GATEWAY_UID]) + # Only root can actually drop privileges to the application UID. The + # native doctor itself runs runtime checks as the gateway owner. + result = subprocess.run([str(self.binary), 'doctor', '--state-dir', str(self.state(host, context)), + '--app-socket', str(self.app_socket(host, context)), '--app-uid', str(APPLICATION_UID), + '--app-gid', str(GATEWAY_UID)], stdin=subprocess.DEVNULL, capture_output=True, + timeout=90, cwd=self.gateway, env=self.environment()) + raw = native_output(result, self.canaries, json_output=False) + return decode(raw), raw def close(self): for host, context in list(self.processes): diff --git a/qualification/reference/tests/test_native_observation.py b/qualification/reference/tests/test_native_observation.py index ebbe35725..de678465d 100644 --- a/qualification/reference/tests/test_native_observation.py +++ b/qualification/reference/tests/test_native_observation.py @@ -118,6 +118,28 @@ def test_killed_client_is_not_evidence_without_exact_durable_native_unknown_and_ Effects().project_interrupted(self.tuple, self.review, self.resources, '6' * 64, value, self.before, after) + def test_an_unobservable_admin_refusal_cannot_invent_a_recovered_effect(self): + support = self.support() + response = {'schema': 'auths.gateway-admin-response/1', 'ok': False, + 'code': 'gateway.reobserve.not-observable'} + ledger = Effects() + ledger.project(self.tuple, self.review, self.resources, {'outcome': 'unknown'}, self.before, self.after) + unknown, fresh = ledger.project_stored_unknown(self.tuple, self.review, self.resources, '6' * 64, + support, self.after, self.after) + self.assertEqual((unknown['verdict']['outcome'], unknown['provider_entries']), ('unknown', 0)) + self.assertIsNone(fresh) + with self.assertRaisesRegex(Refusal, 'unmeasured-unknown'): + Effects().project_stored_unknown(self.tuple, self.review, self.resources, '6' * 64, + support, self.after, self.after) + refused, fresh = ledger.project_admin_refusal(self.tuple, self.review, self.resources, + response, self.after, self.after) + self.assertEqual(refused['verdict'], {'outcome': 'refused', 'code': 'gateway.reobserve.not-observable', + 'request_sha256': None, 'evidence_sha256': None}) + self.assertIsNone(fresh) + with self.assertRaises(Refusal): + ledger.project_admin_refusal(self.tuple, self.review, self.resources, + dict(response, code='gateway.admin.socket-unavailable'), self.after, self.after) + def test_race_aggregates_distinct_actual_native_scopes_without_counting_a_second_confirmation(self): second = dict(self.before, scope='2' * 32) recovered = dict(second, credential_lease_calls=1, read_transport_entries=1) From 1f116953ec75d7567b1c27c3dd1b37ed369ac8b2 Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 17:01:03 +0100 Subject: [PATCH 092/108] Exercise actual installed TypeScript and Python consumer provenance --- .github/workflows/recipe-qualification.yml | 64 +++++++++++++++++++ .../tests/protected_run.rs | 1 + .../airtable-record-update-v1/contract.json | 2 +- .../corpus-manifest.json | 2 +- .../stripe-platform-refund-v1/contract.json | 2 +- .../corpus-manifest.json | 2 +- qualification/reference/README.md | 9 +++ qualification/reference/family_operations.py | 54 ++++++++++++++++ qualification/reference/generate_families.py | 2 +- qualification/reference/installed_submit.mjs | 54 ++++++++++++++++ qualification/reference/installed_submit.py | 22 ++++++- qualification/reference/production_setup.py | 18 +++++- 12 files changed, 223 insertions(+), 9 deletions(-) create mode 100644 qualification/reference/installed_submit.mjs diff --git a/.github/workflows/recipe-qualification.yml b/.github/workflows/recipe-qualification.yml index 83dd3a1c4..9cbac3851 100644 --- a/.github/workflows/recipe-qualification.yml +++ b/.github/workflows/recipe-qualification.yml @@ -161,6 +161,70 @@ jobs: if-no-files-found: error retention-days: 30 + typescript-consumer: + name: installed TypeScript qualification consumer + runs-on: ubuntu-latest + timeout-minutes: 60 + steps: + - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 + with: + persist-credentials: false + - uses: ./.github/actions/setup-rust-cache + with: + toolchain: 1.97.1 + targets: wasm32-unknown-unknown + - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 + with: + node-version: 22.23.1 + cache: npm + cache-dependency-path: bindings/typescript/package-lock.json + - run: npm ci + working-directory: bindings/typescript + - run: cargo install wasm-pack --version 0.15.0 --locked + - run: npm run build:wasm + working-directory: bindings/typescript + - run: npm run build + working-directory: bindings/typescript + - run: mkdir -p target/qualification-typescript + - run: npm pack --pack-destination ../../target/qualification-typescript + working-directory: bindings/typescript + - name: Inspect the actually installed tarball without checkout imports or credentials + shell: bash + run: | + set -euo pipefail + consumer="${RUNNER_TEMP}/qualification-typescript-consumer" + npm install --ignore-scripts --no-audit --no-fund --prefix "${consumer}" \ + "${GITHUB_WORKSPACE}"/target/qualification-typescript/auths-dev-sdk-*.tgz + cp qualification/reference/installed_submit.mjs "${consumer}/installed_submit.mjs" + cd "${consumer}" + env -i PATH="${PATH}" node installed_submit.mjs inspect \ + > "${GITHUB_WORKSPACE}/target/qualification-typescript/consumer-report.json" + - name: Bind the exact tarball and consumer to this source + env: + SOURCE_COMMIT: ${{ github.sha }} + run: | + python3 - <<'PY' + import hashlib, json, os + from pathlib import Path + root = Path('target/qualification-typescript') + packages = list(root.glob('*.tgz')) + assert len(packages) == 1 + report = json.loads((root / 'consumer-report.json').read_bytes()) + assert report['repository_imported'] is False and report['provider_token_received'] is False + (root / 'package.json').write_text(json.dumps({ + 'schema': 'auths.qualification-installed-package/1', 'source_commit': os.environ['SOURCE_COMMIT'], + 'name': report['package_name'], 'version': report['version'], 'file': packages[0].name, + 'sha256': hashlib.sha256(packages[0].read_bytes()).hexdigest(), + 'qualification_issued': False, + }, sort_keys=True) + '\n') + PY + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 + with: + name: qualification-typescript-${{ github.run_id }}-${{ github.run_attempt }} + path: target/qualification-typescript + if-no-files-found: error + retention-days: 30 + simulation: name: disposable bootstrap and two provider simulations runs-on: ubuntu-latest diff --git a/product/qualification/auths-recipe-qualification-issuance/tests/protected_run.rs b/product/qualification/auths-recipe-qualification-issuance/tests/protected_run.rs index bba502351..7832da576 100644 --- a/product/qualification/auths-recipe-qualification-issuance/tests/protected_run.rs +++ b/product/qualification/auths-recipe-qualification-issuance/tests/protected_run.rs @@ -95,6 +95,7 @@ fn a_pull_request_reaches_no_secret_and_no_signing_job() { "packet-author", "sign", "simulation", + "typescript-consumer", "verify" ] ); diff --git a/qualification/families/airtable-record-update-v1/contract.json b/qualification/families/airtable-record-update-v1/contract.json index 7ce066695..d99231205 100644 --- a/qualification/families/airtable-record-update-v1/contract.json +++ b/qualification/families/airtable-record-update-v1/contract.json @@ -1 +1 @@ -{"api_release":"web-api-v0-reviewed-2026-10-07","corpus_manifest_sha256":"b63bfb99d968e86dedc3f3afa262f138a6176ad2b06a290ff407cd6080192226","declarations":{"idempotency_sha256":"74234e98afe7498fb5daf1f36ac2d78acc339464f950703b8c019892f982b90b","observation_sha256":"9dd79dd204fa13a2df3c667d106c66c0526d174a2c018631e2b2f6b897eaf311","recovery_sha256":"7081a92b4cd2d13dab5e7c30e640675a252b62bca20d340e14d62d9c8c048eca","retention_sha256":"4a4b5048c97b16e041af55b032c0b8ac20f5142c4bbcbf31b31c6674770a70d0"},"environment_class":"disposable-live-resources","manual_assumptions":["Airtable supplies no idempotency key for this PATCH; durable gateway admission prevents a second entry.","Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only a fresh GET with the exact replacement and echo can reconcile a lost response.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths.","The reviewed fixed Airtable base and table contain only owner-authorized disposable qualification records."],"oracle_version":"auths-reviewed-reference-v2","provider":"airtable","schema":"auths.provider-contract/1"} \ No newline at end of file +{"api_release":"web-api-v0-reviewed-2026-10-07","corpus_manifest_sha256":"2c0f4be046d74a8568e1be1a17193ef77ba87c7f2b6925dffcbdec0cc452afaa","declarations":{"idempotency_sha256":"74234e98afe7498fb5daf1f36ac2d78acc339464f950703b8c019892f982b90b","observation_sha256":"9dd79dd204fa13a2df3c667d106c66c0526d174a2c018631e2b2f6b897eaf311","recovery_sha256":"7081a92b4cd2d13dab5e7c30e640675a252b62bca20d340e14d62d9c8c048eca","retention_sha256":"4a4b5048c97b16e041af55b032c0b8ac20f5142c4bbcbf31b31c6674770a70d0"},"environment_class":"disposable-live-resources","manual_assumptions":["Airtable supplies no idempotency key for this PATCH; durable gateway admission prevents a second entry.","Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only a fresh GET with the exact replacement and echo can reconcile a lost response.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths.","The reviewed fixed Airtable base and table contain only owner-authorized disposable qualification records."],"oracle_version":"auths-reviewed-reference-v2","provider":"airtable","schema":"auths.provider-contract/1"} \ No newline at end of file diff --git a/qualification/families/airtable-record-update-v1/corpus-manifest.json b/qualification/families/airtable-record-update-v1/corpus-manifest.json index d7a6a22c8..64cf94259 100644 --- a/qualification/families/airtable-record-update-v1/corpus-manifest.json +++ b/qualification/families/airtable-record-update-v1/corpus-manifest.json @@ -1 +1 @@ -{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"32241d9b4811a55abcdd224ef567df3857dbec34d761ef7a35d1044cdfa52d9f","family":"airtable-record-update-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"af7f984509ab11a3676cacc85eda2fa638c25bf91f7bfedf3ff3c119e47f3c41","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","controller_socket.py":"10519cc775e963360870eac51c7fcac1ffb988b04d5de89dac1dbf3524ba6531","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"9cee4fac304abb67fe39b86df3b5a2522f385a6f1e62fcb5e15daa6f3f90b2d6","family_harness.py":"ed0136600a25c9f12bdcca73b105c3968271ccd227f42ad03a884cf5b9430de6","family_operations.py":"778fd16c5e9b199aeab6057412d7f3381c1b15612d0de576f5a8bc163e31bc8b","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","installed_submit.py":"f78b91ca7c57ea6909793973ca63fb33f18589ac8acbcb15e8886511e3d6fc50","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"abebdf9f5704f0a19457347798548d98b3ddb3adbd48e91bc58a82faf4afbd08","network_fault.py":"986ca0c9d7d534c2a1ebdd09edb4e6f94c17bb4bfcb35d57307c97419ed20894","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","production_setup.py":"0bab950dd88f3d2094a60262402383b310844c727fa1b042c903497bcaac154f","provider_readback.py":"d576768208985b3544f146597d181d796f2a5e2eca5026dae3fa15cadcfe65b2","resource_io.py":"b0ed0223fd11a1a28c25278de539a9b2ed63881b26a8e00e386f25d4d9aa9384","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","retained_author.py":"bfd01c7df44f5f525326dfbda13b5ebc6b854f15787a8b2923de883fe20fdcf9","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489","tls_fault.py":"078c11110315b479d5d57c0c987d177134a645717d3c81039d37b9a057588e12"},"source_recipe_sha256":"c0f21ff1d3c8e344fee20a9a0c25bb14a264417ed53418ad536789a6096fb16e"} \ No newline at end of file +{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"32241d9b4811a55abcdd224ef567df3857dbec34d761ef7a35d1044cdfa52d9f","family":"airtable-record-update-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"af7f984509ab11a3676cacc85eda2fa638c25bf91f7bfedf3ff3c119e47f3c41","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","controller_socket.py":"10519cc775e963360870eac51c7fcac1ffb988b04d5de89dac1dbf3524ba6531","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"9cee4fac304abb67fe39b86df3b5a2522f385a6f1e62fcb5e15daa6f3f90b2d6","family_harness.py":"ed0136600a25c9f12bdcca73b105c3968271ccd227f42ad03a884cf5b9430de6","family_operations.py":"69037c5766b3f6b82424d53972a5db8ffe2fa8c6bae1c13ffc392b8eb3502272","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","installed_submit.mjs":"9d57a91c4a052fbb9103582689ee99a6d087758dcfee00defa4c762b87187468","installed_submit.py":"f9151c2dffa1a02327b0ba05bdeb180654918a2b913195185a6649d010783dc7","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"abebdf9f5704f0a19457347798548d98b3ddb3adbd48e91bc58a82faf4afbd08","network_fault.py":"986ca0c9d7d534c2a1ebdd09edb4e6f94c17bb4bfcb35d57307c97419ed20894","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","production_setup.py":"bf961e523146c1b619d5cdb7a4773dfe6ee60064b6233d8b6c87e7f7cfc1000f","provider_readback.py":"d576768208985b3544f146597d181d796f2a5e2eca5026dae3fa15cadcfe65b2","resource_io.py":"b0ed0223fd11a1a28c25278de539a9b2ed63881b26a8e00e386f25d4d9aa9384","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","retained_author.py":"bfd01c7df44f5f525326dfbda13b5ebc6b854f15787a8b2923de883fe20fdcf9","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489","tls_fault.py":"078c11110315b479d5d57c0c987d177134a645717d3c81039d37b9a057588e12"},"source_recipe_sha256":"c0f21ff1d3c8e344fee20a9a0c25bb14a264417ed53418ad536789a6096fb16e"} \ No newline at end of file diff --git a/qualification/families/stripe-platform-refund-v1/contract.json b/qualification/families/stripe-platform-refund-v1/contract.json index 54004af0d..d977c8ffc 100644 --- a/qualification/families/stripe-platform-refund-v1/contract.json +++ b/qualification/families/stripe-platform-refund-v1/contract.json @@ -1 +1 @@ -{"api_release":"2025-03-31.basil","corpus_manifest_sha256":"8b41bf8bf8af0e7fcbfb0c4987f0602910bc9f081a48fa0cb699e3160b06a29a","declarations":{"idempotency_sha256":"425a0dca2f279765debfc847c4a01bff60fea5be68dd9d761ae6bb60ce0b8a7b","observation_sha256":"d0ce5a34d987821c69c0a839d9ed66805c625f8324dd42031fcccf0752a8821e","recovery_sha256":"bf2303abce165c175360ac975586431bbc4cf03167489ea317a27de2f0b04abb","retention_sha256":"846c2164e26d1144d9aa146034b4f7ea4dc305136a59ffd94f999d19f2c360ee"},"environment_class":"provider-test-mode","manual_assumptions":["Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","Stripe idempotency is tested only inside the declared 86400-second retention interval.","Stripe test mode and the installed platform are checked by the declared guard on each lease.","The 50-percent payment basis is a read, not an atomic provider balance reservation.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths."],"oracle_version":"auths-reviewed-reference-v2","provider":"stripe","schema":"auths.provider-contract/1"} \ No newline at end of file +{"api_release":"2025-03-31.basil","corpus_manifest_sha256":"19a67d735cc2cbfdc85e74b9a2e1c246c696c30eb34ac42294c500911ec68024","declarations":{"idempotency_sha256":"425a0dca2f279765debfc847c4a01bff60fea5be68dd9d761ae6bb60ce0b8a7b","observation_sha256":"d0ce5a34d987821c69c0a839d9ed66805c625f8324dd42031fcccf0752a8821e","recovery_sha256":"bf2303abce165c175360ac975586431bbc4cf03167489ea317a27de2f0b04abb","retention_sha256":"846c2164e26d1144d9aa146034b4f7ea4dc305136a59ffd94f999d19f2c360ee"},"environment_class":"provider-test-mode","manual_assumptions":["Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","Stripe idempotency is tested only inside the declared 86400-second retention interval.","Stripe test mode and the installed platform are checked by the declared guard on each lease.","The 50-percent payment basis is a read, not an atomic provider balance reservation.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths."],"oracle_version":"auths-reviewed-reference-v2","provider":"stripe","schema":"auths.provider-contract/1"} \ No newline at end of file diff --git a/qualification/families/stripe-platform-refund-v1/corpus-manifest.json b/qualification/families/stripe-platform-refund-v1/corpus-manifest.json index d8f1ecc86..9a0e291e2 100644 --- a/qualification/families/stripe-platform-refund-v1/corpus-manifest.json +++ b/qualification/families/stripe-platform-refund-v1/corpus-manifest.json @@ -1 +1 @@ -{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"a72c557b69103a52eb477deb8364ded53cd58407b9ba7ab33ccbda74389fec1e","family":"stripe-platform-refund-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"99901e36cb7c4f5882897603c874698d582e859b5d6b08d53cd80975e89aa01c","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","controller_socket.py":"10519cc775e963360870eac51c7fcac1ffb988b04d5de89dac1dbf3524ba6531","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"9cee4fac304abb67fe39b86df3b5a2522f385a6f1e62fcb5e15daa6f3f90b2d6","family_harness.py":"ed0136600a25c9f12bdcca73b105c3968271ccd227f42ad03a884cf5b9430de6","family_operations.py":"778fd16c5e9b199aeab6057412d7f3381c1b15612d0de576f5a8bc163e31bc8b","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","installed_submit.py":"f78b91ca7c57ea6909793973ca63fb33f18589ac8acbcb15e8886511e3d6fc50","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"abebdf9f5704f0a19457347798548d98b3ddb3adbd48e91bc58a82faf4afbd08","network_fault.py":"986ca0c9d7d534c2a1ebdd09edb4e6f94c17bb4bfcb35d57307c97419ed20894","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","production_setup.py":"0bab950dd88f3d2094a60262402383b310844c727fa1b042c903497bcaac154f","provider_readback.py":"d576768208985b3544f146597d181d796f2a5e2eca5026dae3fa15cadcfe65b2","resource_io.py":"b0ed0223fd11a1a28c25278de539a9b2ed63881b26a8e00e386f25d4d9aa9384","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","retained_author.py":"bfd01c7df44f5f525326dfbda13b5ebc6b854f15787a8b2923de883fe20fdcf9","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489","tls_fault.py":"078c11110315b479d5d57c0c987d177134a645717d3c81039d37b9a057588e12"},"source_recipe_sha256":"b1972d556f28433932a449636755077f7ee485ef90cca412f153bc7f18881368"} \ No newline at end of file +{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"a72c557b69103a52eb477deb8364ded53cd58407b9ba7ab33ccbda74389fec1e","family":"stripe-platform-refund-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"99901e36cb7c4f5882897603c874698d582e859b5d6b08d53cd80975e89aa01c","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","controller_socket.py":"10519cc775e963360870eac51c7fcac1ffb988b04d5de89dac1dbf3524ba6531","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"9cee4fac304abb67fe39b86df3b5a2522f385a6f1e62fcb5e15daa6f3f90b2d6","family_harness.py":"ed0136600a25c9f12bdcca73b105c3968271ccd227f42ad03a884cf5b9430de6","family_operations.py":"69037c5766b3f6b82424d53972a5db8ffe2fa8c6bae1c13ffc392b8eb3502272","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","installed_submit.mjs":"9d57a91c4a052fbb9103582689ee99a6d087758dcfee00defa4c762b87187468","installed_submit.py":"f9151c2dffa1a02327b0ba05bdeb180654918a2b913195185a6649d010783dc7","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"abebdf9f5704f0a19457347798548d98b3ddb3adbd48e91bc58a82faf4afbd08","network_fault.py":"986ca0c9d7d534c2a1ebdd09edb4e6f94c17bb4bfcb35d57307c97419ed20894","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","production_setup.py":"bf961e523146c1b619d5cdb7a4773dfe6ee60064b6233d8b6c87e7f7cfc1000f","provider_readback.py":"d576768208985b3544f146597d181d796f2a5e2eca5026dae3fa15cadcfe65b2","resource_io.py":"b0ed0223fd11a1a28c25278de539a9b2ed63881b26a8e00e386f25d4d9aa9384","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","retained_author.py":"bfd01c7df44f5f525326dfbda13b5ebc6b854f15787a8b2923de883fe20fdcf9","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489","tls_fault.py":"078c11110315b479d5d57c0c987d177134a645717d3c81039d37b9a057588e12"},"source_recipe_sha256":"b1972d556f28433932a449636755077f7ee485ef90cca412f153bc7f18881368"} \ No newline at end of file diff --git a/qualification/reference/README.md b/qualification/reference/README.md index dad59bae3..3c52697e3 100644 --- a/qualification/reference/README.md +++ b/qualification/reference/README.md @@ -314,3 +314,12 @@ previously measured unconfirmed entry before it can project Unknown. No refused admin response becomes linked effect evidence. The production doctor is run as root so its native application privilege-drop probe actually executes; its raw validated report digest and exact installed tuple enter the native runner. + +The credential-free workflow also packs and installs the full TypeScript SDK, +including its maintained WASM assets, outside the checkout. Its source-owned +consumer resolves the gateway module from `node_modules` and rejects ambient +environment inputs. Both installed consumers expose a closed provenance probe; +protected steps recheck actual package versions against the retained package +manifest and measure the serving gateway's unchanged counters. The TypeScript +journey submits public packets from the separate author through the actual +installed GatewayClient; it performs no provider request construction. diff --git a/qualification/reference/family_operations.py b/qualification/reference/family_operations.py index a699fde3a..60aab5e96 100644 --- a/qualification/reference/family_operations.py +++ b/qualification/reference/family_operations.py @@ -47,10 +47,15 @@ def __init__(self, deployment, author, oracle, resources, reviewed): self.consumer_python = None self.consumer_kit = None self.interrupted = set() + self.consumer_node = None + self.consumer_script = None def configure_consumers(self, python, kit): self.consumer_python, self.consumer_kit = Path(python).absolute(), Path(kit).absolute() + def configure_typescript(self, node, script): + self.consumer_node, self.consumer_script = Path(node).absolute(), Path(script).absolute() + def configure_rotation(self, first, second): require(type(first) is bytes and type(second) is bytes and first != second and first in self.deployment.canaries and second in self.deployment.canaries, @@ -320,6 +325,48 @@ def python_consumer(self, phase): result = self.deployment.installed_python_submit(self.consumer_python, self.consumer_kit, handoff, packet) return self.project(label, result, before, self.deployment.witness(0)) + def typescript_consumer(self, phase): + require(self.consumer_node is not None and self.consumer_script is not None, + 'qualification.operations.installed-typescript-not-configured') + label = phase + '-12' + handoff, packet = self.packet(label) + before = self.deployment.witness(0) + result = self.deployment.installed_typescript_submit(self.consumer_node, self.consumer_script, handoff, packet) + return self.project(label, result, before, self.deployment.witness(0)) + + def inspect_consumer(self, language, probe): + require(probe in ['no-source', 'no-token'], 'qualification.operations.step') + if language == 'python': + require(self.consumer_python is not None and self.consumer_kit is not None, + 'qualification.operations.installed-python-not-configured') + executable, script = self.consumer_python, self.consumer_kit / 'installed_submit.py' + else: + require(language == 'typescript' and self.consumer_node is not None and self.consumer_script is not None, + 'qualification.operations.installed-typescript-not-configured') + executable, script = self.consumer_node, self.consumer_script + before = self.deployment.witness(0) + value = self.deployment.inspect_consumer(executable, script, language) + closed(value, ['schema', 'language', 'package_name', 'version', 'installation', 'module_sha256', + 'repository_imported', 'provider_token_received']) + require(value['schema'] == 'auths.qualification-consumer-provenance/1' + and value['language'] == language + and value['package_name'] == ('auths' if language == 'python' else '@auths-dev/sdk') + and value['installation'] == ('site-packages' if language == 'python' else 'node_modules') + and value['repository_imported'] is False and value['provider_token_received'] is False, + 'qualification.operations.consumer-provenance') + packages = decode(read(self.deployment.work / 'packages.json', 65536)) + require(type(packages) is list and len([package for package in packages + if package['name'] == value['package_name'] and package['version'] == value['version']]) == 1, + 'qualification.operations.consumer-version') + from common import digest + digest(value['module_sha256']) + counts = measure.delta(before, self.deployment.witness(0)) + return self.observation({'verdict': {'outcome': 'complete', + 'code': 'installed-package-provenance-confirmed' if probe == 'no-source' else 'provider-token-absent', + 'request_sha256': None, 'evidence_sha256': None}, + 'credential_leases': counts['credential_lease_calls'], 'provider_entries': counts['write_transport_entries'], + 'confirmed_by_read_back': 0}) + def step(self, case, index, operation): require(type(case) is str and type(index) is int and type(operation) is str, 'qualification.operations.step') @@ -385,6 +432,13 @@ def step(self, case, index, operation): elif identifier == 'doctor': require(phase == 'live' and index == 0 and operation == 'probe', 'qualification.operations.step') result = self.doctor() + elif identifier == 'installed-typescript': + require(index == 0 and operation == 'installed-consumer', 'qualification.operations.step') + result = self.typescript_consumer(phase) + elif identifier in ['python-no-source', 'python-no-token', 'typescript-no-source', 'typescript-no-token']: + require(index == 0 and operation == 'installed-consumer', 'qualification.operations.step') + language, _, probe = identifier.partition('-') + result = self.inspect_consumer(language, probe) elif identifier == 'installed-python': require(index == 0 and operation == 'installed-consumer', 'qualification.operations.step') result = self.python_consumer(phase) diff --git a/qualification/reference/generate_families.py b/qualification/reference/generate_families.py index c5ebd355d..ad178d1ec 100644 --- a/qualification/reference/generate_families.py +++ b/qualification/reference/generate_families.py @@ -19,7 +19,7 @@ SOURCES_TO_PIN = ['family_corpus.py', 'family_harness.py', 'family_operations.py', 'packet_plan.py', 'author_packets.py', 'author_socket.py', 'retained_author.py', 'author_operator.py', 'production_setup.py', 'network_fault.py', - 'controller_socket.py', 'installed_submit.py', 'common.py', 'fresh_evidence.py', + 'controller_socket.py', 'installed_submit.py', 'installed_submit.mjs', 'common.py', 'fresh_evidence.py', 'native_observation.py', 'measure.py', 'provider_readback.py', 'resource_io.py', 'resource_summary.py', 'expand.py', 'stripe_platform.py', 'airtable_record.py', 'stripe_resources.py', 'airtable_resources.py'] diff --git a/qualification/reference/installed_submit.mjs b/qualification/reference/installed_submit.mjs new file mode 100644 index 000000000..cd4d3e9ea --- /dev/null +++ b/qualification/reference/installed_submit.mjs @@ -0,0 +1,54 @@ +/** Installed TypeScript consumer; accepts public proof/action paths only. */ +import { readFile, realpath, stat } from 'node:fs/promises'; +import { createHash } from 'node:crypto'; +import { fileURLToPath } from 'node:url'; +import { dirname, isAbsolute, join } from 'node:path'; + +function requireFact(value) { + if (!value) throw new Error('qualification.consumer.refused'); +} +const digest = value => createHash('sha256').update(value).digest('hex'); + +try { + requireFact(Object.keys(process.env).every(name => ['PATH', 'LC_CTYPE', 'LANG'].includes(name))); + const gatewayFile = await realpath(fileURLToPath(import.meta.resolve('@auths-dev/sdk/gateway'))); + requireFact(gatewayFile.endsWith('/node_modules/@auths-dev/sdk/dist/gateway.js')); + const packageRoot = dirname(dirname(gatewayFile)); + const metadata = JSON.parse(await readFile(join(packageRoot, 'package.json'), 'utf8')); + requireFact(metadata.name === '@auths-dev/sdk' && typeof metadata.version === 'string'); + const sdk = await import('@auths-dev/sdk/gateway'); + const [operation, ...arguments_] = process.argv.slice(2); + let result; + if (operation === 'inspect') { + requireFact(arguments_.length === 0); + result = { schema: 'auths.qualification-consumer-provenance/1', language: 'typescript', + package_name: metadata.name, version: metadata.version, installation: 'node_modules', + module_sha256: digest(await readFile(gatewayFile)), repository_imported: false, + provider_token_received: false }; + } else { + requireFact(operation === 'submit' && arguments_.length === 3 && arguments_.every(isAbsolute)); + const [endpoint, proofPath, actionPath] = arguments_; + async function bounded(path, maximum) { + const info = await stat(path); + requireFact(info.isFile() && info.size > 0 && info.size <= maximum); + const bytes = await readFile(path); + requireFact(bytes.length > 0 && bytes.length <= maximum); + return bytes; + } + result = await new sdk.GatewayClient(new sdk.GatewayEndpoint(endpoint)).submit({ + proof: await bounded(proofPath, 4 * 1024 * 1024), action: await bounded(actionPath, 65536) }); + // Map the installed client's documented field spelling back to the + // shipping native result carrier; no decision or evidence is invented. + if (result.outcome === 'observed-by-provider') { + result = { outcome: result.outcome, status: result.status, evidence: { + channel: result.evidence.channel, echo: result.evidence.echo, + evidence_digest: result.evidence.evidenceDigest, observed_at: result.evidence.observedAt } }; + } + } + const encoded = JSON.stringify(result); + requireFact(Buffer.byteLength(encoded) <= 65536); + process.stdout.write(encoded + '\n'); +} catch { + process.stderr.write('qualification.consumer.refused\n'); + process.exitCode = 1; +} diff --git a/qualification/reference/installed_submit.py b/qualification/reference/installed_submit.py index 8adaa96e9..3ffe4b407 100644 --- a/qualification/reference/installed_submit.py +++ b/qualification/reference/installed_submit.py @@ -5,9 +5,10 @@ import asyncio from dataclasses import asdict from pathlib import Path +import importlib.metadata from author_packets import installed_native -from common import canonical, require +from common import canonical, require, sha256 from expand import read from resource_io import finish @@ -22,12 +23,27 @@ def submit(endpoint, proof, action): print(payload.decode()) +def inspect(): + native, version = installed_native() + import auths + distribution = importlib.metadata.distribution('auths') + require(Path(distribution.locate_file('auths/__init__.py')).resolve() == Path(auths.__file__).resolve(), + 'qualification.consumer.distribution-binding') + print(canonical({'schema': 'auths.qualification-consumer-provenance/1', 'language': 'python', + 'package_name': 'auths', 'version': version, 'installation': 'site-packages', + 'module_sha256': sha256(read(Path(native.__file__), 64 * 1024 * 1024)), + 'repository_imported': False, 'provider_token_received': False}).decode()) + + def main(): parser = argparse.ArgumentParser(description=__doc__) + subparsers = parser.add_subparsers(dest='operation', required=True) + subparsers.add_parser('inspect') + submission = subparsers.add_parser('submit') for name in ['endpoint', 'proof', 'action']: - parser.add_argument('--' + name, type=lambda value: Path(value).absolute(), required=True) + submission.add_argument('--' + name, type=lambda value: Path(value).absolute(), required=True) args = parser.parse_args() - finish(lambda: submit(args.endpoint, args.proof, args.action)) + finish(lambda: inspect() if args.operation == 'inspect' else submit(args.endpoint, args.proof, args.action)) if __name__ == '__main__': diff --git a/qualification/reference/production_setup.py b/qualification/reference/production_setup.py index 52743d28f..99ee7000a 100644 --- a/qualification/reference/production_setup.py +++ b/qualification/reference/production_setup.py @@ -246,13 +246,29 @@ def application_submit(self, handoff, packet, host=0, context=0): def installed_python_submit(self, python, kit, handoff, packet, host=0, context=0): inputs = self.packet_inputs(handoff, packet, APPLICATION_UID) - result = subprocess.run([str(python), '-B', str(Path(kit) / 'installed_submit.py'), + result = subprocess.run([str(python), '-B', str(Path(kit) / 'installed_submit.py'), 'submit', '--endpoint', str(self.app_socket(host, context)), '--proof', str(inputs / packet['proof']), '--action', str(inputs / packet['action'])], stdin=subprocess.DEVNULL, capture_output=True, timeout=90, cwd=inputs, user=APPLICATION_UID, group=GATEWAY_UID, extra_groups=[], env={'PATH': '/usr/bin:/bin', 'PYTHONNOUSERSITE': '1'}) return native_output(result, self.canaries) + def installed_typescript_submit(self, node, script, handoff, packet, host=0, context=0): + inputs = self.packet_inputs(handoff, packet, APPLICATION_UID) + result = subprocess.run([str(node), str(script), 'submit', str(self.app_socket(host, context)), + str(inputs / packet['proof']), str(inputs / packet['action'])], stdin=subprocess.DEVNULL, + capture_output=True, timeout=90, cwd=inputs, user=APPLICATION_UID, + group=GATEWAY_UID, extra_groups=[], env={'PATH': '/usr/bin:/bin'}) + return native_output(result, self.canaries) + + def inspect_consumer(self, executable, script, language): + require(language in ['python', 'typescript'], 'qualification.production.consumer') + result = subprocess.run([str(executable), *(['-B'] if language == 'python' else []), str(script), 'inspect'], + stdin=subprocess.DEVNULL, capture_output=True, timeout=30, cwd='/', + user=APPLICATION_UID, group=GATEWAY_UID, extra_groups=[], + env={'PATH': '/usr/bin:/bin', **({'PYTHONNOUSERSITE': '1'} if language == 'python' else {})}) + return native_output(result, self.canaries) + def register_commissioning(self, source): require(self.permit is None, 'qualification.production.permit-already-registered') names = ['commissioning-permit.json', 'signer-certificate.json', 'revocation-list.json'] From 42d13101095bfc2e0df11b4f98ab3693b750da91 Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 17:19:13 +0100 Subject: [PATCH 093/108] Hold actual observation responses and provision bounded hosted infrastructure --- .../airtable-record-update-v1/contract.json | 2 +- .../corpus-manifest.json | 2 +- .../stripe-platform-refund-v1/contract.json | 2 +- .../corpus-manifest.json | 2 +- qualification/reference/family_corpus.py | 8 +- qualification/reference/family_operations.py | 31 ++- qualification/reference/generate_families.py | 2 +- qualification/reference/network_fault.py | 6 +- .../reference/production_environment.py | 253 ++++++++++++++++++ qualification/reference/production_setup.py | 5 +- .../reference/tests/test_network_fault.py | 13 + .../tests/test_production_environment.py | 97 +++++++ .../reference/tests/test_tls_fault.py | 9 + qualification/run/tls_fault.py | 8 +- 14 files changed, 417 insertions(+), 23 deletions(-) create mode 100644 qualification/reference/production_environment.py create mode 100644 qualification/reference/tests/test_production_environment.py diff --git a/qualification/families/airtable-record-update-v1/contract.json b/qualification/families/airtable-record-update-v1/contract.json index d99231205..4e07bf98e 100644 --- a/qualification/families/airtable-record-update-v1/contract.json +++ b/qualification/families/airtable-record-update-v1/contract.json @@ -1 +1 @@ -{"api_release":"web-api-v0-reviewed-2026-10-07","corpus_manifest_sha256":"2c0f4be046d74a8568e1be1a17193ef77ba87c7f2b6925dffcbdec0cc452afaa","declarations":{"idempotency_sha256":"74234e98afe7498fb5daf1f36ac2d78acc339464f950703b8c019892f982b90b","observation_sha256":"9dd79dd204fa13a2df3c667d106c66c0526d174a2c018631e2b2f6b897eaf311","recovery_sha256":"7081a92b4cd2d13dab5e7c30e640675a252b62bca20d340e14d62d9c8c048eca","retention_sha256":"4a4b5048c97b16e041af55b032c0b8ac20f5142c4bbcbf31b31c6674770a70d0"},"environment_class":"disposable-live-resources","manual_assumptions":["Airtable supplies no idempotency key for this PATCH; durable gateway admission prevents a second entry.","Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only a fresh GET with the exact replacement and echo can reconcile a lost response.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths.","The reviewed fixed Airtable base and table contain only owner-authorized disposable qualification records."],"oracle_version":"auths-reviewed-reference-v2","provider":"airtable","schema":"auths.provider-contract/1"} \ No newline at end of file +{"api_release":"web-api-v0-reviewed-2026-10-07","corpus_manifest_sha256":"bcdcea41b0ff34a1c564a17271e82991b8c232c738c14952d6669ccff2373797","declarations":{"idempotency_sha256":"74234e98afe7498fb5daf1f36ac2d78acc339464f950703b8c019892f982b90b","observation_sha256":"9dd79dd204fa13a2df3c667d106c66c0526d174a2c018631e2b2f6b897eaf311","recovery_sha256":"7081a92b4cd2d13dab5e7c30e640675a252b62bca20d340e14d62d9c8c048eca","retention_sha256":"4a4b5048c97b16e041af55b032c0b8ac20f5142c4bbcbf31b31c6674770a70d0"},"environment_class":"disposable-live-resources","manual_assumptions":["Airtable supplies no idempotency key for this PATCH; durable gateway admission prevents a second entry.","Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only a fresh GET with the exact replacement and echo can reconcile a lost response.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths.","The reviewed fixed Airtable base and table contain only owner-authorized disposable qualification records."],"oracle_version":"auths-reviewed-reference-v2","provider":"airtable","schema":"auths.provider-contract/1"} \ No newline at end of file diff --git a/qualification/families/airtable-record-update-v1/corpus-manifest.json b/qualification/families/airtable-record-update-v1/corpus-manifest.json index 64cf94259..f65e028a1 100644 --- a/qualification/families/airtable-record-update-v1/corpus-manifest.json +++ b/qualification/families/airtable-record-update-v1/corpus-manifest.json @@ -1 +1 @@ -{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"32241d9b4811a55abcdd224ef567df3857dbec34d761ef7a35d1044cdfa52d9f","family":"airtable-record-update-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"af7f984509ab11a3676cacc85eda2fa638c25bf91f7bfedf3ff3c119e47f3c41","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","controller_socket.py":"10519cc775e963360870eac51c7fcac1ffb988b04d5de89dac1dbf3524ba6531","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"9cee4fac304abb67fe39b86df3b5a2522f385a6f1e62fcb5e15daa6f3f90b2d6","family_harness.py":"ed0136600a25c9f12bdcca73b105c3968271ccd227f42ad03a884cf5b9430de6","family_operations.py":"69037c5766b3f6b82424d53972a5db8ffe2fa8c6bae1c13ffc392b8eb3502272","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","installed_submit.mjs":"9d57a91c4a052fbb9103582689ee99a6d087758dcfee00defa4c762b87187468","installed_submit.py":"f9151c2dffa1a02327b0ba05bdeb180654918a2b913195185a6649d010783dc7","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"abebdf9f5704f0a19457347798548d98b3ddb3adbd48e91bc58a82faf4afbd08","network_fault.py":"986ca0c9d7d534c2a1ebdd09edb4e6f94c17bb4bfcb35d57307c97419ed20894","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","production_setup.py":"bf961e523146c1b619d5cdb7a4773dfe6ee60064b6233d8b6c87e7f7cfc1000f","provider_readback.py":"d576768208985b3544f146597d181d796f2a5e2eca5026dae3fa15cadcfe65b2","resource_io.py":"b0ed0223fd11a1a28c25278de539a9b2ed63881b26a8e00e386f25d4d9aa9384","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","retained_author.py":"bfd01c7df44f5f525326dfbda13b5ebc6b854f15787a8b2923de883fe20fdcf9","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489","tls_fault.py":"078c11110315b479d5d57c0c987d177134a645717d3c81039d37b9a057588e12"},"source_recipe_sha256":"c0f21ff1d3c8e344fee20a9a0c25bb14a264417ed53418ad536789a6096fb16e"} \ No newline at end of file +{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"32241d9b4811a55abcdd224ef567df3857dbec34d761ef7a35d1044cdfa52d9f","family":"airtable-record-update-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"af7f984509ab11a3676cacc85eda2fa638c25bf91f7bfedf3ff3c119e47f3c41","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","controller_socket.py":"10519cc775e963360870eac51c7fcac1ffb988b04d5de89dac1dbf3524ba6531","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"b614b12b0789afb2ce4f4b81618db8d6e2333a8b52ec76fc96fbba1be715ee68","family_harness.py":"ed0136600a25c9f12bdcca73b105c3968271ccd227f42ad03a884cf5b9430de6","family_operations.py":"5b1555d7594aae382a47eab1f9804f9e279029d77cdd0745c0c538588417100b","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","installed_submit.mjs":"9d57a91c4a052fbb9103582689ee99a6d087758dcfee00defa4c762b87187468","installed_submit.py":"f9151c2dffa1a02327b0ba05bdeb180654918a2b913195185a6649d010783dc7","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"abebdf9f5704f0a19457347798548d98b3ddb3adbd48e91bc58a82faf4afbd08","network_fault.py":"94340720d8601f79ac77b95d1e855be25195c19b67db3103bbf054d82c02472b","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","production_environment.py":"4afa2491624b0dfbc44fba868474415628d18f1493f8e6c772f108eccd1390da","production_setup.py":"db59d9dd0af97f145a2b71843c42b551258a6c1e88a1b888843698389e03751f","provider_readback.py":"d576768208985b3544f146597d181d796f2a5e2eca5026dae3fa15cadcfe65b2","resource_io.py":"b0ed0223fd11a1a28c25278de539a9b2ed63881b26a8e00e386f25d4d9aa9384","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","retained_author.py":"bfd01c7df44f5f525326dfbda13b5ebc6b854f15787a8b2923de883fe20fdcf9","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489","tls_fault.py":"10e125f9623bc32a420a1d83e6d46fe30aa1ca8ff4da97a3e2422fc0e11ec42d"},"source_recipe_sha256":"c0f21ff1d3c8e344fee20a9a0c25bb14a264417ed53418ad536789a6096fb16e"} \ No newline at end of file diff --git a/qualification/families/stripe-platform-refund-v1/contract.json b/qualification/families/stripe-platform-refund-v1/contract.json index d977c8ffc..359a991ed 100644 --- a/qualification/families/stripe-platform-refund-v1/contract.json +++ b/qualification/families/stripe-platform-refund-v1/contract.json @@ -1 +1 @@ -{"api_release":"2025-03-31.basil","corpus_manifest_sha256":"19a67d735cc2cbfdc85e74b9a2e1c246c696c30eb34ac42294c500911ec68024","declarations":{"idempotency_sha256":"425a0dca2f279765debfc847c4a01bff60fea5be68dd9d761ae6bb60ce0b8a7b","observation_sha256":"d0ce5a34d987821c69c0a839d9ed66805c625f8324dd42031fcccf0752a8821e","recovery_sha256":"bf2303abce165c175360ac975586431bbc4cf03167489ea317a27de2f0b04abb","retention_sha256":"846c2164e26d1144d9aa146034b4f7ea4dc305136a59ffd94f999d19f2c360ee"},"environment_class":"provider-test-mode","manual_assumptions":["Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","Stripe idempotency is tested only inside the declared 86400-second retention interval.","Stripe test mode and the installed platform are checked by the declared guard on each lease.","The 50-percent payment basis is a read, not an atomic provider balance reservation.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths."],"oracle_version":"auths-reviewed-reference-v2","provider":"stripe","schema":"auths.provider-contract/1"} \ No newline at end of file +{"api_release":"2025-03-31.basil","corpus_manifest_sha256":"56a9fb0a7e044135a8e14dd23387afb71a127f54c9ae3a968f5e81a142f2371f","declarations":{"idempotency_sha256":"425a0dca2f279765debfc847c4a01bff60fea5be68dd9d761ae6bb60ce0b8a7b","observation_sha256":"d0ce5a34d987821c69c0a839d9ed66805c625f8324dd42031fcccf0752a8821e","recovery_sha256":"bf2303abce165c175360ac975586431bbc4cf03167489ea317a27de2f0b04abb","retention_sha256":"846c2164e26d1144d9aa146034b4f7ea4dc305136a59ffd94f999d19f2c360ee"},"environment_class":"provider-test-mode","manual_assumptions":["Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","Stripe idempotency is tested only inside the declared 86400-second retention interval.","Stripe test mode and the installed platform are checked by the declared guard on each lease.","The 50-percent payment basis is a read, not an atomic provider balance reservation.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths."],"oracle_version":"auths-reviewed-reference-v2","provider":"stripe","schema":"auths.provider-contract/1"} \ No newline at end of file diff --git a/qualification/families/stripe-platform-refund-v1/corpus-manifest.json b/qualification/families/stripe-platform-refund-v1/corpus-manifest.json index 9a0e291e2..379647b2c 100644 --- a/qualification/families/stripe-platform-refund-v1/corpus-manifest.json +++ b/qualification/families/stripe-platform-refund-v1/corpus-manifest.json @@ -1 +1 @@ -{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"a72c557b69103a52eb477deb8364ded53cd58407b9ba7ab33ccbda74389fec1e","family":"stripe-platform-refund-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"99901e36cb7c4f5882897603c874698d582e859b5d6b08d53cd80975e89aa01c","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","controller_socket.py":"10519cc775e963360870eac51c7fcac1ffb988b04d5de89dac1dbf3524ba6531","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"9cee4fac304abb67fe39b86df3b5a2522f385a6f1e62fcb5e15daa6f3f90b2d6","family_harness.py":"ed0136600a25c9f12bdcca73b105c3968271ccd227f42ad03a884cf5b9430de6","family_operations.py":"69037c5766b3f6b82424d53972a5db8ffe2fa8c6bae1c13ffc392b8eb3502272","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","installed_submit.mjs":"9d57a91c4a052fbb9103582689ee99a6d087758dcfee00defa4c762b87187468","installed_submit.py":"f9151c2dffa1a02327b0ba05bdeb180654918a2b913195185a6649d010783dc7","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"abebdf9f5704f0a19457347798548d98b3ddb3adbd48e91bc58a82faf4afbd08","network_fault.py":"986ca0c9d7d534c2a1ebdd09edb4e6f94c17bb4bfcb35d57307c97419ed20894","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","production_setup.py":"bf961e523146c1b619d5cdb7a4773dfe6ee60064b6233d8b6c87e7f7cfc1000f","provider_readback.py":"d576768208985b3544f146597d181d796f2a5e2eca5026dae3fa15cadcfe65b2","resource_io.py":"b0ed0223fd11a1a28c25278de539a9b2ed63881b26a8e00e386f25d4d9aa9384","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","retained_author.py":"bfd01c7df44f5f525326dfbda13b5ebc6b854f15787a8b2923de883fe20fdcf9","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489","tls_fault.py":"078c11110315b479d5d57c0c987d177134a645717d3c81039d37b9a057588e12"},"source_recipe_sha256":"b1972d556f28433932a449636755077f7ee485ef90cca412f153bc7f18881368"} \ No newline at end of file +{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"a72c557b69103a52eb477deb8364ded53cd58407b9ba7ab33ccbda74389fec1e","family":"stripe-platform-refund-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"99901e36cb7c4f5882897603c874698d582e859b5d6b08d53cd80975e89aa01c","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","controller_socket.py":"10519cc775e963360870eac51c7fcac1ffb988b04d5de89dac1dbf3524ba6531","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"b614b12b0789afb2ce4f4b81618db8d6e2333a8b52ec76fc96fbba1be715ee68","family_harness.py":"ed0136600a25c9f12bdcca73b105c3968271ccd227f42ad03a884cf5b9430de6","family_operations.py":"5b1555d7594aae382a47eab1f9804f9e279029d77cdd0745c0c538588417100b","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","installed_submit.mjs":"9d57a91c4a052fbb9103582689ee99a6d087758dcfee00defa4c762b87187468","installed_submit.py":"f9151c2dffa1a02327b0ba05bdeb180654918a2b913195185a6649d010783dc7","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"abebdf9f5704f0a19457347798548d98b3ddb3adbd48e91bc58a82faf4afbd08","network_fault.py":"94340720d8601f79ac77b95d1e855be25195c19b67db3103bbf054d82c02472b","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","production_environment.py":"4afa2491624b0dfbc44fba868474415628d18f1493f8e6c772f108eccd1390da","production_setup.py":"db59d9dd0af97f145a2b71843c42b551258a6c1e88a1b888843698389e03751f","provider_readback.py":"d576768208985b3544f146597d181d796f2a5e2eca5026dae3fa15cadcfe65b2","resource_io.py":"b0ed0223fd11a1a28c25278de539a9b2ed63881b26a8e00e386f25d4d9aa9384","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","retained_author.py":"bfd01c7df44f5f525326dfbda13b5ebc6b854f15787a8b2923de883fe20fdcf9","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489","tls_fault.py":"10e125f9623bc32a420a1d83e6d46fe30aa1ca8ff4da97a3e2422fc0e11ec42d"},"source_recipe_sha256":"b1972d556f28433932a449636755077f7ee485ef90cca412f153bc7f18881368"} \ No newline at end of file diff --git a/qualification/reference/family_corpus.py b/qualification/reference/family_corpus.py index 4a1247f8b..b4f846c74 100644 --- a/qualification/reference/family_corpus.py +++ b/qualification/reference/family_corpus.py @@ -134,9 +134,13 @@ def add(phase, identifier, scenario, steps, capabilities=()): for index, identifier, operation, scenario in [ (6, 'response-loss', 'drop-response', 'response-loss'), (7, 'visibility', 'delay-visibility', 'delayed-visibility')]: - ending = observed('read-back', label(index), 1, 0, 1) if reference is airtable_record \ + ending = observed('read-back', label(index), 1, 0, 1) if reference is airtable_record or index == 7 \ else unknown('read-back', label(index)) - add(phase, identifier, scenario, [unknown(operation, label(index), 1, 1), ending], + # Delaying the observation response exercises a second actual + # lease, after the write response has durably supplied its locator. + # Stripe can reconcile that locator; losing the write response + # still cannot borrow the independent oracle's discovered locator. + add(phase, identifier, scenario, [unknown(operation, label(index), 2 if index == 7 else 1, 1), ending], ('recovery',) if reference is airtable_record else ()) add(phase, 'secret-rotation', 'provider-secret-rotation', [complete('rotate', 'provider-secret-rotated'), observed('submit', label(8))]) diff --git a/qualification/reference/family_operations.py b/qualification/reference/family_operations.py index 60aab5e96..46bf32ea2 100644 --- a/qualification/reference/family_operations.py +++ b/qualification/reference/family_operations.py @@ -149,10 +149,11 @@ def wait_for_effect(self, label): time.sleep(0.5) require(False, 'qualification.operations.effect-not-independently-observed') - def lose_response(self, phase, label, *, crash=False): + def lose_response(self, phase, label, *, crash=False, observation=False): handoff, packet = self.packet(label) child = self.deployment.commissioning_child(handoff, packet) if phase == 'commissioning' else None - witness = Witness(child.witness, GATEWAY_UID) if child is not None else NativeWitness(self.deployment, 0, 0) + witness = Witness(child.witness, GATEWAY_UID, observation=observation) if child is not None \ + else NativeWitness(self.deployment, 0, 0, observation=observation) try: with ResponseFault(self.family, witness) as fault, ThreadPoolExecutor(max_workers=1) as pool: if child is not None: @@ -254,7 +255,10 @@ def resume_host(self, phase, label, *, crash): self.deployment.start(0) require(self.deployment.witness(0)['scope'] != before['scope'], 'qualification.operations.restart-scope') - return self.completed_probe('gateway-' + ('crash' if crash else 'restart') + '-completed') + resumed = self.deployment.witness(0) + self.deployment.support() + return self.completed_probe('gateway-' + ('crash' if crash else 'restart') + '-completed', + resumed, self.deployment.witness(0)) def doctor(self): require(self.phase == 'live', 'qualification.operations.phase') @@ -283,21 +287,24 @@ def doctor(self): 'report_sha256': sha256(raw)}) return observation - def completed_probe(self, code): + def completed_probe(self, code, before, after): # Completion is constructed only after that source operation returned # actual native/provider facts; a corpus's expected code is never read. + counted = measure.delta(before, after) return self.observation({'verdict': {'outcome': 'complete', 'code': code, - 'request_sha256': None, 'evidence_sha256': None}, 'credential_leases': 0, - 'provider_entries': 0, 'confirmed_by_read_back': 0}) + 'request_sha256': None, 'evidence_sha256': None}, + 'credential_leases': counted['credential_lease_calls'], + 'provider_entries': counted['write_transport_entries'], 'confirmed_by_read_back': 0}) def rotate(self): require(self.rotation_keys is not None, 'qualification.operations.genuine-rotation-required') successor = next(key for key in self.rotation_keys if key != self.current_credential) + before = self.deployment.witness(0) result = self.deployment.rotate(successor) require(result.get('ok') is True and result.get('code') == 'gateway.admin.rotated', 'qualification.operations.rotation-refused') self.current_credential = successor - return self.completed_probe('provider-secret-rotated') + return self.completed_probe('provider-secret-rotated', before, self.deployment.witness(0)) def hostile(self, phase, identifier): label = phase + '-13' @@ -406,13 +413,17 @@ def step(self, case, index, operation): result = self.resume_host(phase, label, crash=identifier == 'crash') else: result = self.submit(phase, label) - elif identifier in ['ambiguous', 'response-loss']: + elif identifier in ['ambiguous', 'response-loss', 'visibility']: ending = 'replay' if identifier == 'ambiguous' else 'read-back' - require(index in [0, 1] and operation == ['drop-response', ending][index], + first = 'delay-visibility' if identifier == 'visibility' else 'drop-response' + require(index in [0, 1] and operation == [first, ending][index], 'qualification.operations.step') label = phase + '-' + str(POSITIVES[identifier]).zfill(2) if index == 0: - result = self.lose_response(phase, label) + # Visibility withholds the actual observation response after + # the second native credential lease. The write response and + # its verified locator have already reached durable state. + result = self.lose_response(phase, label, observation=identifier == 'visibility') else: require((case, 0) in self.completed, 'qualification.operations.order') result = self.submit(phase, label) if ending == 'replay' else self.read_back(label) diff --git a/qualification/reference/generate_families.py b/qualification/reference/generate_families.py index ad178d1ec..683fa71f9 100644 --- a/qualification/reference/generate_families.py +++ b/qualification/reference/generate_families.py @@ -18,7 +18,7 @@ REFERENCE = ROOT / 'qualification/reference' SOURCES_TO_PIN = ['family_corpus.py', 'family_harness.py', 'family_operations.py', 'packet_plan.py', 'author_packets.py', 'author_socket.py', 'retained_author.py', 'author_operator.py', 'production_setup.py', - 'network_fault.py', + 'network_fault.py', 'production_environment.py', 'controller_socket.py', 'installed_submit.py', 'installed_submit.mjs', 'common.py', 'fresh_evidence.py', 'native_observation.py', 'measure.py', 'provider_readback.py', 'resource_io.py', 'resource_summary.py', 'expand.py', 'stripe_platform.py', 'airtable_record.py', 'stripe_resources.py', 'airtable_resources.py'] diff --git a/qualification/reference/network_fault.py b/qualification/reference/network_fault.py index 8b4da84e3..eb9a3e960 100644 --- a/qualification/reference/network_fault.py +++ b/qualification/reference/network_fault.py @@ -70,8 +70,9 @@ def __enter__(self): class NativeWitness: """Read a live gateway's actual diagnostic; never synthesize a counter scope.""" - def __init__(self, deployment, host, context): + def __init__(self, deployment, host, context, *, observation=False): self.deployment, self.host, self.context = deployment, host, context + self.observation = observation self.before = self.last = deployment.witness(host, context) def entered(self): @@ -80,7 +81,8 @@ def entered(self): counted = measure.delta(self.before, current) require(counted['write_transport_entries'] <= 1, 'qualification.fault.multiple-writes') self.last = current - return counted['write_transport_entries'] == 1 + return counted['write_transport_entries'] == 1 and (not self.observation + or counted['credential_lease_calls'] >= 2) class ResponseFault(Rules): diff --git a/qualification/reference/production_environment.py b/qualification/reference/production_environment.py new file mode 100644 index 000000000..ab2312ff0 --- /dev/null +++ b/qualification/reference/production_environment.py @@ -0,0 +1,253 @@ +"""Ephemeral hosted PostgreSQL/TLS, synchronized clock and actual OIDC inputs. + +This source owns no IAM grant and never uploads a credential. Only a manual +main run in the existing protected custody environment may provision it. +""" + +import base64 +import os +from pathlib import Path +import secrets +import stat +import subprocess +import sys +import threading +import time +import urllib.parse +import urllib.request + +from common import Refusal, require +from expand import decode +from production_setup import GATEWAY_UID +from resource_io import NoRedirect, write_bytes + +sys.path.insert(0, str(Path(__file__).resolve().parents[1] / 'run')) +import artifact_wait + +SUBJECT = 'repo:auths-dev@260513770/auths-proof@1310728509:environment:gateway-custody-live' +POSTGRES_IMAGE = 'postgres:17.10-bookworm' +COMMAND_ENVIRONMENT = {'PATH': '/usr/sbin:/usr/bin:/sbin:/bin', + 'DOCKER_CONFIG': '/nonexistent-auths-docker-config'} + + +def checked_token(raw, environment): + require(type(raw) is str and 32 <= len(raw) <= 16384 and raw.count('.') == 2, + 'qualification.infrastructure.identity-token') + try: + encoded = raw.split('.')[1] + claims = decode(base64.urlsafe_b64decode(encoded + '=' * (-len(encoded) % 4))) + except (ValueError, UnicodeError): + raise Refusal('qualification.infrastructure.identity-token') from None + run, attempt, commit = artifact_wait.identity(environment) + now = int(time.time()) + require(type(claims) is dict and claims.get('iss') == 'https://token.actions.githubusercontent.com' + and claims.get('aud') == 'sts.amazonaws.com' and claims.get('sub') == SUBJECT + and claims.get('repository_id') == '1310728509' and claims.get('repository_owner_id') == '260513770' + and claims.get('repository') == 'auths-dev/auths-proof' + and claims.get('event_name') == 'workflow_dispatch' and claims.get('ref') == 'refs/heads/main' + and claims.get('sha') == commit and claims.get('run_id') == run and claims.get('run_attempt') == attempt + and type(claims.get('iat')) is int and type(claims.get('exp')) is int + and now - 120 <= claims['iat'] <= now + 30 and now + 60 < claims['exp'] <= now + 900, + 'qualification.infrastructure.identity-binding') + # These are source preconditions, not signature verification. The actual + # AWS role assumption separately authenticates the signed token. + return raw.encode() + + +def token_url(value): + require(type(value) is str and len(value) <= 8192, 'qualification.infrastructure.identity-url') + try: + parsed = urllib.parse.urlsplit(value) + port = parsed.port + except ValueError: + raise Refusal('qualification.infrastructure.identity-url') from None + require(parsed.scheme == 'https' and parsed.hostname is not None + and parsed.hostname.endswith('.actions.githubusercontent.com') + and port is None and parsed.username is None and parsed.password is None + and not parsed.fragment, 'qualification.infrastructure.identity-url') + query = urllib.parse.parse_qsl(parsed.query, keep_blank_values=True) + require(not any(name == 'audience' for name, _ in query), 'qualification.infrastructure.identity-url') + return urllib.parse.urlunsplit(parsed._replace(query=urllib.parse.urlencode([*query, ('audience', 'sts.amazonaws.com')]))) + + +def command(arguments, timeout=60): + result = subprocess.run(list(map(str, arguments)), stdin=subprocess.DEVNULL, capture_output=True, + timeout=timeout, env=COMMAND_ENVIRONMENT) + require(result.returncode == 0 and len(result.stdout) <= 65536 and len(result.stderr) <= 65536, + 'qualification.infrastructure.command-refused') + return result.stdout + + +class Infrastructure: + def __init__(self, private, environment, canaries): + require(sys.platform == 'linux' and os.getuid() == 0 + and environment.get('GITHUB_ACTIONS') == 'true' + and environment.get('RUNNER_ENVIRONMENT') == 'github-hosted', + 'qualification.infrastructure.host') + self.run, self.attempt, self.commit = artifact_wait.identity(environment) + self.url = token_url(environment.get('ACTIONS_ID_TOKEN_REQUEST_URL')) + self.request_token = environment.get('ACTIONS_ID_TOKEN_REQUEST_TOKEN') + require(type(self.request_token) is str and 8 <= len(self.request_token) <= 16384 + and all(33 <= ord(character) <= 126 for character in self.request_token), + 'qualification.infrastructure.identity-request') + self.private, self.environment, self.canaries = Path(private).absolute(), dict(environment), canaries + require(not self.private.exists() and self.private.resolve() == self.private, + 'qualification.infrastructure.private-directory') + self.private.mkdir(mode=0o711) + os.chmod(self.private, 0o711) + self.root = self.private / 'operator' + self.root.mkdir(mode=0o700) + self.tokens = self.private / 'tokens' + self.tokens.mkdir(mode=0o700) + os.chown(self.tokens, GATEWAY_UID, GATEWAY_UID) + self.canaries.append(self.request_token.encode()) + self.stopping = threading.Event() + self.refresher, self.refusal, self.container = None, None, None + + def refresh(self): + request = urllib.request.Request(self.url, + headers={'Authorization': 'bearer ' + self.request_token, 'Accept': 'application/json'}) + try: + with urllib.request.build_opener(urllib.request.ProxyHandler({}), NoRedirect).open(request, timeout=20) as response: + raw = response.read(65537) + require(response.status == 200 and 0 < len(raw) <= 65536, + 'qualification.infrastructure.identity-response') + except (OSError, ValueError): + raise Refusal('qualification.infrastructure.identity-unavailable') from None + response = decode(raw) + require(type(response) is dict, 'qualification.infrastructure.identity-response') + token = checked_token(response.get('value'), self.environment) + self.canaries.append(token) + for name in ['operator.jwt', 'runtime.jwt']: + temporary = self.tokens / (name + '.next') + fd = os.open(temporary, os.O_WRONLY | os.O_CREAT | os.O_EXCL | os.O_NOFOLLOW, 0o600) + try: + os.fchmod(fd, 0o600) + os.fchown(fd, GATEWAY_UID, GATEWAY_UID) + with os.fdopen(fd, 'wb') as stream: + stream.write(token) + stream.flush() + os.fsync(stream.fileno()) + os.replace(temporary, self.tokens / name) + finally: + temporary.unlink(missing_ok=True) + + def start_identity(self): + self.refresh() + def renew(): + while not self.stopping.wait(60): + try: + self.refresh() + except (Refusal, OSError, ValueError): + self.refusal = True + return + self.refresher = threading.Thread(target=renew, name='auths-oidc-refresh', daemon=True) + self.refresher.start() + + def check_identity(self): + require(self.refresher is not None and self.refresher.is_alive() and self.refusal is None, + 'qualification.infrastructure.identity-refresh-refused') + + def synchronize_clock(self): + directory = Path('/etc/systemd/timesyncd.conf.d') + directory.mkdir(mode=0o755, exist_ok=True) + path = directory / ('90-auths-qualification-' + self.run + '-' + self.attempt + '.conf') + fd = os.open(path, os.O_WRONLY | os.O_CREAT | os.O_EXCL | os.O_NOFOLLOW, 0o644) + with os.fdopen(fd, 'wb') as stream: + stream.write(b'[Time]\nPollIntervalMinSec=32s\nPollIntervalMaxSec=5min\n') + self.clock_configuration = path + command(['systemctl', 'enable', '--now', 'systemd-timesyncd']) + command(['systemctl', 'restart', 'systemd-timesyncd']) + deadline = time.monotonic() + 60 + while time.monotonic() < deadline: + try: + info = os.lstat('/run/systemd/timesync/synchronized') + if stat.S_ISREG(info.st_mode) and not info.st_mode & 0o022 and 0 <= time.time() - info.st_mtime <= 900: + require(command(['timedatectl', 'show', '--property=NTPSynchronized', '--value']).strip() == b'yes', + 'qualification.infrastructure.clock-untrusted') + return + except FileNotFoundError: + pass + time.sleep(0.25) + require(False, 'qualification.infrastructure.clock-untrusted') + + def start_database(self): + certificates = self.root / 'certificates' + certificates.mkdir(mode=0o700) + command(['openssl', 'req', '-x509', '-newkey', 'rsa:2048', '-nodes', '-days', '1', + '-subj', '/CN=auths-qualification-ephemeral-ca', '-keyout', certificates / 'ca.key', + '-out', certificates / 'ca.pem']) + command(['openssl', 'req', '-newkey', 'rsa:2048', '-nodes', '-subj', '/CN=localhost', + '-keyout', certificates / 'server.key', '-out', certificates / 'server.csr']) + write_bytes(certificates / 'server.ext', b'subjectAltName=DNS:localhost,IP:127.0.0.1\n', new=True) + command(['openssl', 'x509', '-req', '-days', '1', '-in', certificates / 'server.csr', + '-CA', certificates / 'ca.pem', '-CAkey', certificates / 'ca.key', '-CAcreateserial', + '-extfile', certificates / 'server.ext', '-out', certificates / 'server.pem']) + server = self.root / 'postgres-tls' + server.mkdir(mode=0o700) + for source, name in [('server.key', 'server.key'), ('server.pem', 'server.pem'), ('ca.pem', 'ca.pem')]: + write_bytes(server / name, (certificates / source).read_bytes(), new=True) + os.chown(server / name, 999, 999) + os.chown(server, 999, 999) + password = secrets.token_hex(24) + self.canaries.append(password.encode()) + configuration = self.root / 'postgres.env' + write_bytes(configuration, ('POSTGRES_USER=auths\nPOSTGRES_DB=auths_qualification\nPOSTGRES_PASSWORD=' + password + '\n').encode(), new=True) + # A closed name is retained before Docker starts, so cleanup can remove + # an ambiguously started container without listing unrelated resources. + self.container = 'auths-qualification-' + secrets.token_hex(8) + command(['docker', 'run', '--detach', '--name', self.container, '--env-file', configuration, + '--publish', '127.0.0.1::5432', '--mount', 'type=bind,src=' + str(server) + ',dst=/tls,readonly', + POSTGRES_IMAGE, 'postgres', '-c', 'ssl=on', '-c', 'ssl_cert_file=/tls/server.pem', + '-c', 'ssl_key_file=/tls/server.key', '-c', 'ssl_ca_file=/tls/ca.pem', '-c', 'synchronous_commit=on'], timeout=120) + port = command(['docker', 'port', self.container, '5432/tcp']).decode().strip() + require(port.startswith('127.0.0.1:') and port.removeprefix('127.0.0.1:').isdigit(), + 'qualification.infrastructure.database-port') + number = int(port.removeprefix('127.0.0.1:')) + require(1 <= number <= 65535, 'qualification.infrastructure.database-port') + deadline = time.monotonic() + 45 + while time.monotonic() < deadline: + result = subprocess.run(['docker', 'exec', self.container, 'pg_isready', '-U', 'auths', '-d', 'auths_qualification'], + stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, timeout=5, + env=COMMAND_ENVIRONMENT) + if result.returncode == 0: + return {'AUTHS_POSTGRES_URL': 'host=127.0.0.1 port=' + str(number) + + ' dbname=auths_qualification user=auths password=' + password + ' sslmode=require', + 'AUTHS_POSTGRES_CA_PEM': str(certificates / 'ca.pem'), 'AUTHS_POSTGRES_SERVER_NAME': 'localhost', + 'AUTHS_QUALIFICATION_OPERATOR_TOKEN_FILE': str(self.tokens / 'operator.jwt'), + 'AUTHS_QUALIFICATION_RUNTIME_TOKEN_FILE': str(self.tokens / 'runtime.jwt'), + 'AUTHS_QUALIFICATION_CREDENTIAL_NAMESPACE': 'live-' + self.run + '-' + self.attempt} + time.sleep(0.25) + require(False, 'qualification.infrastructure.database-unavailable') + + def close(self): + # The caller must first collect its native credential journal. Keep + # attempting local cleanup even when one owned resource cannot retire. + failures = [] + def attempt(action): + try: + action() + except (Refusal, OSError, ValueError, subprocess.SubprocessError): + failures.append(True) + self.stopping.set() + if self.refresher is not None: + self.refresher.join(timeout=30) + if self.refresher.is_alive(): + failures.append(True) + if self.container is not None: + def remove_container(): + # Docker's exact-name filter distinguishes a failed start + # from a daemon error without listing unrelated containers. + found = command(['docker', 'container', 'ls', '--all', '--filter', + 'name=^/' + self.container + '$', '--format', '{{.Names}}']).strip() + require(found in [b'', self.container.encode()], 'qualification.infrastructure.cleanup-binding') + if found: + command(['docker', 'rm', '--force', '--volumes', self.container]) + self.container = None + attempt(remove_container) + if hasattr(self, 'clock_configuration'): + attempt(lambda: self.clock_configuration.unlink(missing_ok=True)) + for name in ['operator.jwt', 'runtime.jwt']: + attempt(lambda name=name: (self.tokens / name).unlink(missing_ok=True)) + self.request_token = None + require(not failures, 'qualification.infrastructure.cleanup-incomplete') diff --git a/qualification/reference/production_setup.py b/qualification/reference/production_setup.py index 99ee7000a..4fe09990b 100644 --- a/qualification/reference/production_setup.py +++ b/qualification/reference/production_setup.py @@ -83,7 +83,10 @@ def __init__(self, binary, work, private, environment, canaries): self.sockets.mkdir(mode=0o750) os.chmod(self.sockets, 0o750) os.chown(self.sockets, GATEWAY_UID, GATEWAY_UID) - self.canaries = list(canaries) + # The root session adds actual renewed OIDC tokens to this same private + # list. Copying it would omit later credentials from output scanning. + require(type(canaries) is list, 'qualification.production.canaries') + self.canaries = canaries require(self.canaries and all(type(value) is bytes and len(value) >= 8 for value in self.canaries), 'qualification.production.canaries') self.database = {} diff --git a/qualification/reference/tests/test_network_fault.py b/qualification/reference/tests/test_network_fault.py index cade70a3c..2c0950fd2 100644 --- a/qualification/reference/tests/test_network_fault.py +++ b/qualification/reference/tests/test_network_fault.py @@ -54,6 +54,19 @@ def witness(self, host, context): return self.current deployment.current = changed with self.assertRaises(Refusal): witness.entered() + def test_visibility_fault_waits_for_the_observation_lease(self): + before = {'schema': 'auths.gateway-execution-witness/1', 'scope': '1' * 32, + 'credential_lease_calls': 0, 'write_transport_entries': 0, 'read_transport_entries': 0} + class Deployment: + current = before + def witness(self, host, context): return self.current + deployment = Deployment() + witness = network.NativeWitness(deployment, 0, 0, observation=True) + deployment.current = dict(before, credential_lease_calls=1, write_transport_entries=1) + self.assertFalse(witness.entered(), 'losing the write response is a different scenario') + deployment.current = dict(deployment.current, credential_lease_calls=2, read_transport_entries=1) + self.assertTrue(witness.entered()) + if __name__ == '__main__': unittest.main() diff --git a/qualification/reference/tests/test_production_environment.py b/qualification/reference/tests/test_production_environment.py new file mode 100644 index 000000000..659d727e9 --- /dev/null +++ b/qualification/reference/tests/test_production_environment.py @@ -0,0 +1,97 @@ +"""Hosted identity and owned cleanup boundaries; no real token or provider.""" + +import base64 +import json +from pathlib import Path +import sys +import tempfile +import threading +import unittest +from unittest.mock import patch + +sys.path.insert(0, str(Path(__file__).resolve().parents[1])) +from common import Refusal +import production_environment as infrastructure + + +class Environment(unittest.TestCase): + environment = {'GITHUB_REPOSITORY': 'auths-dev/auths-proof', + 'GITHUB_EVENT_NAME': 'workflow_dispatch', 'GITHUB_REF': 'refs/heads/main', + 'GITHUB_RUN_ID': '123', 'GITHUB_RUN_ATTEMPT': '2', 'GITHUB_SHA': '1' * 40} + + def claims(self): + return {'iss': 'https://token.actions.githubusercontent.com', 'aud': 'sts.amazonaws.com', + 'sub': infrastructure.SUBJECT, 'repository_id': '1310728509', + 'repository_owner_id': '260513770', 'repository': 'auths-dev/auths-proof', + 'event_name': 'workflow_dispatch', 'ref': 'refs/heads/main', 'sha': '1' * 40, + 'run_id': '123', 'run_attempt': '2', 'iat': 1000, 'exp': 1300} + + @staticmethod + def token(claims): + encoded = base64.urlsafe_b64encode(json.dumps(claims).encode()).decode().rstrip('=') + return 'synthetic-only-header.' + encoded + '.synthetic-only-signature' + + def test_identity_preconditions_bind_the_actual_run_and_freshness(self): + with patch.object(infrastructure.time, 'time', return_value=1000): + raw = self.token(self.claims()) + self.assertEqual(infrastructure.checked_token(raw, self.environment), raw.encode()) + mutations = {'iss': 'https://example.invalid', 'aud': 'unreviewed', 'sub': 'unreviewed', + 'repository_id': '1', 'repository_owner_id': '1', 'repository': 'unreviewed', + 'event_name': 'pull_request', 'ref': 'refs/heads/unreviewed', 'sha': '2' * 40, + 'run_id': '124', 'run_attempt': '1', 'iat': True, 'exp': True} + for name, value in mutations.items(): + with self.subTest(name=name), self.assertRaises(Refusal): + infrastructure.checked_token(self.token(dict(self.claims(), **{name: value})), self.environment) + for times in [(879, 1300), (1031, 1300), (1000, 1060), (1000, 1901)]: + with self.assertRaises(Refusal): + infrastructure.checked_token(self.token(dict(self.claims(), iat=times[0], exp=times[1])), self.environment) + with self.assertRaises(Refusal): + infrastructure.checked_token(self.token([]), self.environment) + + def test_request_destination_cannot_be_selected_by_credentials_or_redirects(self): + url = 'https://pipelines.actions.githubusercontent.com/identity?api-version=2.0' + self.assertEqual(infrastructure.token_url(url), url + '&audience=sts.amazonaws.com') + for value in ['http://pipelines.actions.githubusercontent.com/identity', + 'https://actions.githubusercontent.com.example.invalid/identity', + 'https://user@pipelines.actions.githubusercontent.com/identity', + url + '#fragment', url + '&audience=unreviewed', + 'https://pipelines.actions.githubusercontent.com:bad/identity', + 'https://pipelines.actions.githubusercontent.com:443/identity']: + with self.subTest(value=value), self.assertRaises(Refusal): + infrastructure.token_url(value) + + def test_cleanup_continues_after_owned_database_failure_and_retains_failure(self): + with tempfile.TemporaryDirectory() as directory: + root = Path(directory) + value = object.__new__(infrastructure.Infrastructure) + value.stopping, value.refresher = threading.Event(), None + value.container, value.request_token = 'auths-qualification-synthetic-only', 'synthetic-only-token' + value.tokens, value.clock_configuration = root, root / 'clock.conf' + for name in ['operator.jwt', 'runtime.jwt', 'clock.conf']: + (root / name).write_bytes(b'synthetic-only-private-input') + calls = [] + def refused(arguments, **kwargs): + calls.append(arguments) + raise Refusal('qualification.infrastructure.command-refused') + with patch.object(infrastructure, 'command', refused), self.assertRaisesRegex(Refusal, 'cleanup-incomplete'): + value.close() + self.assertEqual(len(calls), 1) + self.assertIn('name=^/auths-qualification-synthetic-only$', calls[0]) + self.assertEqual(list(root.iterdir()), []) + self.assertIsNone(value.request_token) + self.assertEqual(value.container, 'auths-qualification-synthetic-only') + + def test_failed_container_start_can_retire_when_its_exact_name_is_absent(self): + with tempfile.TemporaryDirectory() as directory: + value = object.__new__(infrastructure.Infrastructure) + value.stopping, value.refresher = threading.Event(), None + value.tokens, value.container = Path(directory), 'auths-qualification-synthetic-only' + value.request_token = 'synthetic-only-token' + with patch.object(infrastructure, 'command', return_value=b'') as command: + value.close() + self.assertEqual(command.call_count, 1) + self.assertIsNone(value.container) + + +if __name__ == '__main__': + unittest.main() diff --git a/qualification/reference/tests/test_tls_fault.py b/qualification/reference/tests/test_tls_fault.py index cda1f0ef6..f94157dcf 100644 --- a/qualification/reference/tests/test_tls_fault.py +++ b/qualification/reference/tests/test_tls_fault.py @@ -95,6 +95,15 @@ def test_changed_inode_links_and_public_witness_are_refused(self): path.chmod(0o644) with self.assertRaises((ValueError, OSError)): witness.entered() + def test_visibility_stream_does_not_arm_on_the_write_lease(self): + path = self.work() + witness = fault.Witness(path, os.getuid(), observation=True) + with path.open('a') as out: out.write(json.dumps(snapshot(1)) + '\n') + self.assertFalse(witness.entered()) + with path.open('a') as out: + out.write(json.dumps(dict(snapshot(1), credential_lease_calls=2, read_transport_entries=1)) + '\n') + self.assertTrue(witness.entered()) + def test_control_cannot_invent_entry_or_choose_an_endpoint(self): state = fault.Fault(None) for command in [{'command': 'drop'}, {'command': 'drop', 'provider_url': 'unreviewed'}, diff --git a/qualification/run/tls_fault.py b/qualification/run/tls_fault.py index bc127b01e..7396b99ca 100644 --- a/qualification/run/tls_fault.py +++ b/qualification/run/tls_fault.py @@ -102,8 +102,9 @@ async def record(reader): class Witness: """Pin one private, append-only native counter stream and its initial scope.""" - def __init__(self, path, owner): + def __init__(self, path, owner, *, observation=False): self.path, self.owner = Path(path), owner + self.observation = observation self.inode, self.previous_size, self.before, self.last = None, 0, None, None self.prefix_sha256 = None @@ -135,9 +136,10 @@ def entered(self): self.inode, self.previous_size = inode, len(raw) self.prefix_sha256 = hashlib.sha256(raw).digest() self.before, self.last = values[0], values[-1] - count = measure.delta(self.before, self.last)['write_transport_entries'] + counted = measure.delta(self.before, self.last) + count = counted['write_transport_entries'] require(count <= 1, 'qualification.fault.multiple-writes') - return count == 1 + return count == 1 and (not self.observation or counted['credential_lease_calls'] >= 2) class Fault: From 6d42baf3360d6c0ce903762ec2a7a6157a01aa29 Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 17:38:22 +0100 Subject: [PATCH 094/108] Retain one production operator across bounded qualification phases --- .../src/bin/qualification_runner/mod.rs | 3 + .../airtable-record-update-v1/contract.json | 2 +- .../corpus-manifest.json | 2 +- .../stripe-platform-refund-v1/contract.json | 2 +- .../corpus-manifest.json | 2 +- qualification/reference/README.md | 13 + qualification/reference/family_harness.py | 7 +- qualification/reference/generate_families.py | 2 +- qualification/reference/journey_session.py | 257 ++++++++++++++ qualification/reference/production_journey.py | 329 ++++++++++++++++++ qualification/reference/production_setup.py | 39 ++- .../reference/tests/test_journey_session.py | 105 ++++++ qualification/run/close_proposal.py | 4 +- 13 files changed, 749 insertions(+), 18 deletions(-) create mode 100644 qualification/reference/journey_session.py create mode 100644 qualification/reference/production_journey.py create mode 100644 qualification/reference/tests/test_journey_session.py diff --git a/product/qualification/auths-recipe-qualification-issuance/src/bin/qualification_runner/mod.rs b/product/qualification/auths-recipe-qualification-issuance/src/bin/qualification_runner/mod.rs index 2aa58e141..70c63c91c 100644 --- a/product/qualification/auths-recipe-qualification-issuance/src/bin/qualification_runner/mod.rs +++ b/product/qualification/auths-recipe-qualification-issuance/src/bin/qualification_runner/mod.rs @@ -53,6 +53,9 @@ fn execute_step( "WINDIR", "AUTHS_GATEWAY", "AUTHS_QUALIFICATION", + // A private root coordinator accepts case coordinates only. + // The actual SDK child still receives an empty environment. + "AUTHS_QUALIFICATION_CONTROLLER", "VIRTUAL_ENV", ] { if let Some(value) = std::env::var_os(name) { diff --git a/qualification/families/airtable-record-update-v1/contract.json b/qualification/families/airtable-record-update-v1/contract.json index 4e07bf98e..08aafb61c 100644 --- a/qualification/families/airtable-record-update-v1/contract.json +++ b/qualification/families/airtable-record-update-v1/contract.json @@ -1 +1 @@ -{"api_release":"web-api-v0-reviewed-2026-10-07","corpus_manifest_sha256":"bcdcea41b0ff34a1c564a17271e82991b8c232c738c14952d6669ccff2373797","declarations":{"idempotency_sha256":"74234e98afe7498fb5daf1f36ac2d78acc339464f950703b8c019892f982b90b","observation_sha256":"9dd79dd204fa13a2df3c667d106c66c0526d174a2c018631e2b2f6b897eaf311","recovery_sha256":"7081a92b4cd2d13dab5e7c30e640675a252b62bca20d340e14d62d9c8c048eca","retention_sha256":"4a4b5048c97b16e041af55b032c0b8ac20f5142c4bbcbf31b31c6674770a70d0"},"environment_class":"disposable-live-resources","manual_assumptions":["Airtable supplies no idempotency key for this PATCH; durable gateway admission prevents a second entry.","Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only a fresh GET with the exact replacement and echo can reconcile a lost response.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths.","The reviewed fixed Airtable base and table contain only owner-authorized disposable qualification records."],"oracle_version":"auths-reviewed-reference-v2","provider":"airtable","schema":"auths.provider-contract/1"} \ No newline at end of file +{"api_release":"web-api-v0-reviewed-2026-10-07","corpus_manifest_sha256":"1a5aa673b3a61c2be0f38e24904eba42061ebe20d8cf8a5a28690348e3b162d8","declarations":{"idempotency_sha256":"74234e98afe7498fb5daf1f36ac2d78acc339464f950703b8c019892f982b90b","observation_sha256":"9dd79dd204fa13a2df3c667d106c66c0526d174a2c018631e2b2f6b897eaf311","recovery_sha256":"7081a92b4cd2d13dab5e7c30e640675a252b62bca20d340e14d62d9c8c048eca","retention_sha256":"4a4b5048c97b16e041af55b032c0b8ac20f5142c4bbcbf31b31c6674770a70d0"},"environment_class":"disposable-live-resources","manual_assumptions":["Airtable supplies no idempotency key for this PATCH; durable gateway admission prevents a second entry.","Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only a fresh GET with the exact replacement and echo can reconcile a lost response.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths.","The reviewed fixed Airtable base and table contain only owner-authorized disposable qualification records."],"oracle_version":"auths-reviewed-reference-v2","provider":"airtable","schema":"auths.provider-contract/1"} \ No newline at end of file diff --git a/qualification/families/airtable-record-update-v1/corpus-manifest.json b/qualification/families/airtable-record-update-v1/corpus-manifest.json index f65e028a1..6c4e77c02 100644 --- a/qualification/families/airtable-record-update-v1/corpus-manifest.json +++ b/qualification/families/airtable-record-update-v1/corpus-manifest.json @@ -1 +1 @@ -{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"32241d9b4811a55abcdd224ef567df3857dbec34d761ef7a35d1044cdfa52d9f","family":"airtable-record-update-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"af7f984509ab11a3676cacc85eda2fa638c25bf91f7bfedf3ff3c119e47f3c41","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","controller_socket.py":"10519cc775e963360870eac51c7fcac1ffb988b04d5de89dac1dbf3524ba6531","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"b614b12b0789afb2ce4f4b81618db8d6e2333a8b52ec76fc96fbba1be715ee68","family_harness.py":"ed0136600a25c9f12bdcca73b105c3968271ccd227f42ad03a884cf5b9430de6","family_operations.py":"5b1555d7594aae382a47eab1f9804f9e279029d77cdd0745c0c538588417100b","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","installed_submit.mjs":"9d57a91c4a052fbb9103582689ee99a6d087758dcfee00defa4c762b87187468","installed_submit.py":"f9151c2dffa1a02327b0ba05bdeb180654918a2b913195185a6649d010783dc7","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"abebdf9f5704f0a19457347798548d98b3ddb3adbd48e91bc58a82faf4afbd08","network_fault.py":"94340720d8601f79ac77b95d1e855be25195c19b67db3103bbf054d82c02472b","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","production_environment.py":"4afa2491624b0dfbc44fba868474415628d18f1493f8e6c772f108eccd1390da","production_setup.py":"db59d9dd0af97f145a2b71843c42b551258a6c1e88a1b888843698389e03751f","provider_readback.py":"d576768208985b3544f146597d181d796f2a5e2eca5026dae3fa15cadcfe65b2","resource_io.py":"b0ed0223fd11a1a28c25278de539a9b2ed63881b26a8e00e386f25d4d9aa9384","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","retained_author.py":"bfd01c7df44f5f525326dfbda13b5ebc6b854f15787a8b2923de883fe20fdcf9","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489","tls_fault.py":"10e125f9623bc32a420a1d83e6d46fe30aa1ca8ff4da97a3e2422fc0e11ec42d"},"source_recipe_sha256":"c0f21ff1d3c8e344fee20a9a0c25bb14a264417ed53418ad536789a6096fb16e"} \ No newline at end of file +{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"32241d9b4811a55abcdd224ef567df3857dbec34d761ef7a35d1044cdfa52d9f","family":"airtable-record-update-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"af7f984509ab11a3676cacc85eda2fa638c25bf91f7bfedf3ff3c119e47f3c41","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","controller_socket.py":"10519cc775e963360870eac51c7fcac1ffb988b04d5de89dac1dbf3524ba6531","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"b614b12b0789afb2ce4f4b81618db8d6e2333a8b52ec76fc96fbba1be715ee68","family_harness.py":"0e0a42be6cf75dfb3f674b26cbdfbb4c473edea71083dfaad89ecb40dec039ba","family_operations.py":"5b1555d7594aae382a47eab1f9804f9e279029d77cdd0745c0c538588417100b","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","installed_submit.mjs":"9d57a91c4a052fbb9103582689ee99a6d087758dcfee00defa4c762b87187468","installed_submit.py":"f9151c2dffa1a02327b0ba05bdeb180654918a2b913195185a6649d010783dc7","journey_session.py":"3c807ce45dcabe3b39d63333872af3746fe9276aacf5eba30bf903b51d80dfef","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"abebdf9f5704f0a19457347798548d98b3ddb3adbd48e91bc58a82faf4afbd08","network_fault.py":"94340720d8601f79ac77b95d1e855be25195c19b67db3103bbf054d82c02472b","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","production_environment.py":"4afa2491624b0dfbc44fba868474415628d18f1493f8e6c772f108eccd1390da","production_journey.py":"d7eab2f2df1d51b7a201c146184c76f2a046e8867631c3facc066ab067412525","production_setup.py":"7caf73bbeea7260ef494a2406cc78d313ab10a613cba19fa0d58fc491bc75fcd","provider_readback.py":"d576768208985b3544f146597d181d796f2a5e2eca5026dae3fa15cadcfe65b2","resource_io.py":"b0ed0223fd11a1a28c25278de539a9b2ed63881b26a8e00e386f25d4d9aa9384","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","retained_author.py":"bfd01c7df44f5f525326dfbda13b5ebc6b854f15787a8b2923de883fe20fdcf9","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489","tls_fault.py":"10e125f9623bc32a420a1d83e6d46fe30aa1ca8ff4da97a3e2422fc0e11ec42d"},"source_recipe_sha256":"c0f21ff1d3c8e344fee20a9a0c25bb14a264417ed53418ad536789a6096fb16e"} \ No newline at end of file diff --git a/qualification/families/stripe-platform-refund-v1/contract.json b/qualification/families/stripe-platform-refund-v1/contract.json index 359a991ed..483c4dbe0 100644 --- a/qualification/families/stripe-platform-refund-v1/contract.json +++ b/qualification/families/stripe-platform-refund-v1/contract.json @@ -1 +1 @@ -{"api_release":"2025-03-31.basil","corpus_manifest_sha256":"56a9fb0a7e044135a8e14dd23387afb71a127f54c9ae3a968f5e81a142f2371f","declarations":{"idempotency_sha256":"425a0dca2f279765debfc847c4a01bff60fea5be68dd9d761ae6bb60ce0b8a7b","observation_sha256":"d0ce5a34d987821c69c0a839d9ed66805c625f8324dd42031fcccf0752a8821e","recovery_sha256":"bf2303abce165c175360ac975586431bbc4cf03167489ea317a27de2f0b04abb","retention_sha256":"846c2164e26d1144d9aa146034b4f7ea4dc305136a59ffd94f999d19f2c360ee"},"environment_class":"provider-test-mode","manual_assumptions":["Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","Stripe idempotency is tested only inside the declared 86400-second retention interval.","Stripe test mode and the installed platform are checked by the declared guard on each lease.","The 50-percent payment basis is a read, not an atomic provider balance reservation.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths."],"oracle_version":"auths-reviewed-reference-v2","provider":"stripe","schema":"auths.provider-contract/1"} \ No newline at end of file +{"api_release":"2025-03-31.basil","corpus_manifest_sha256":"20bc3838a07fa79ff3a29041be9b358a2803bce3ddeeff528723acc6d2b76473","declarations":{"idempotency_sha256":"425a0dca2f279765debfc847c4a01bff60fea5be68dd9d761ae6bb60ce0b8a7b","observation_sha256":"d0ce5a34d987821c69c0a839d9ed66805c625f8324dd42031fcccf0752a8821e","recovery_sha256":"bf2303abce165c175360ac975586431bbc4cf03167489ea317a27de2f0b04abb","retention_sha256":"846c2164e26d1144d9aa146034b4f7ea4dc305136a59ffd94f999d19f2c360ee"},"environment_class":"provider-test-mode","manual_assumptions":["Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","Stripe idempotency is tested only inside the declared 86400-second retention interval.","Stripe test mode and the installed platform are checked by the declared guard on each lease.","The 50-percent payment basis is a read, not an atomic provider balance reservation.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths."],"oracle_version":"auths-reviewed-reference-v2","provider":"stripe","schema":"auths.provider-contract/1"} \ No newline at end of file diff --git a/qualification/families/stripe-platform-refund-v1/corpus-manifest.json b/qualification/families/stripe-platform-refund-v1/corpus-manifest.json index 379647b2c..bceddc8ab 100644 --- a/qualification/families/stripe-platform-refund-v1/corpus-manifest.json +++ b/qualification/families/stripe-platform-refund-v1/corpus-manifest.json @@ -1 +1 @@ -{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"a72c557b69103a52eb477deb8364ded53cd58407b9ba7ab33ccbda74389fec1e","family":"stripe-platform-refund-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"99901e36cb7c4f5882897603c874698d582e859b5d6b08d53cd80975e89aa01c","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","controller_socket.py":"10519cc775e963360870eac51c7fcac1ffb988b04d5de89dac1dbf3524ba6531","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"b614b12b0789afb2ce4f4b81618db8d6e2333a8b52ec76fc96fbba1be715ee68","family_harness.py":"ed0136600a25c9f12bdcca73b105c3968271ccd227f42ad03a884cf5b9430de6","family_operations.py":"5b1555d7594aae382a47eab1f9804f9e279029d77cdd0745c0c538588417100b","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","installed_submit.mjs":"9d57a91c4a052fbb9103582689ee99a6d087758dcfee00defa4c762b87187468","installed_submit.py":"f9151c2dffa1a02327b0ba05bdeb180654918a2b913195185a6649d010783dc7","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"abebdf9f5704f0a19457347798548d98b3ddb3adbd48e91bc58a82faf4afbd08","network_fault.py":"94340720d8601f79ac77b95d1e855be25195c19b67db3103bbf054d82c02472b","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","production_environment.py":"4afa2491624b0dfbc44fba868474415628d18f1493f8e6c772f108eccd1390da","production_setup.py":"db59d9dd0af97f145a2b71843c42b551258a6c1e88a1b888843698389e03751f","provider_readback.py":"d576768208985b3544f146597d181d796f2a5e2eca5026dae3fa15cadcfe65b2","resource_io.py":"b0ed0223fd11a1a28c25278de539a9b2ed63881b26a8e00e386f25d4d9aa9384","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","retained_author.py":"bfd01c7df44f5f525326dfbda13b5ebc6b854f15787a8b2923de883fe20fdcf9","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489","tls_fault.py":"10e125f9623bc32a420a1d83e6d46fe30aa1ca8ff4da97a3e2422fc0e11ec42d"},"source_recipe_sha256":"b1972d556f28433932a449636755077f7ee485ef90cca412f153bc7f18881368"} \ No newline at end of file +{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"a72c557b69103a52eb477deb8364ded53cd58407b9ba7ab33ccbda74389fec1e","family":"stripe-platform-refund-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"99901e36cb7c4f5882897603c874698d582e859b5d6b08d53cd80975e89aa01c","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","controller_socket.py":"10519cc775e963360870eac51c7fcac1ffb988b04d5de89dac1dbf3524ba6531","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"b614b12b0789afb2ce4f4b81618db8d6e2333a8b52ec76fc96fbba1be715ee68","family_harness.py":"0e0a42be6cf75dfb3f674b26cbdfbb4c473edea71083dfaad89ecb40dec039ba","family_operations.py":"5b1555d7594aae382a47eab1f9804f9e279029d77cdd0745c0c538588417100b","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","installed_submit.mjs":"9d57a91c4a052fbb9103582689ee99a6d087758dcfee00defa4c762b87187468","installed_submit.py":"f9151c2dffa1a02327b0ba05bdeb180654918a2b913195185a6649d010783dc7","journey_session.py":"3c807ce45dcabe3b39d63333872af3746fe9276aacf5eba30bf903b51d80dfef","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"abebdf9f5704f0a19457347798548d98b3ddb3adbd48e91bc58a82faf4afbd08","network_fault.py":"94340720d8601f79ac77b95d1e855be25195c19b67db3103bbf054d82c02472b","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","production_environment.py":"4afa2491624b0dfbc44fba868474415628d18f1493f8e6c772f108eccd1390da","production_journey.py":"d7eab2f2df1d51b7a201c146184c76f2a046e8867631c3facc066ab067412525","production_setup.py":"7caf73bbeea7260ef494a2406cc78d313ab10a613cba19fa0d58fc491bc75fcd","provider_readback.py":"d576768208985b3544f146597d181d796f2a5e2eca5026dae3fa15cadcfe65b2","resource_io.py":"b0ed0223fd11a1a28c25278de539a9b2ed63881b26a8e00e386f25d4d9aa9384","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","retained_author.py":"bfd01c7df44f5f525326dfbda13b5ebc6b854f15787a8b2923de883fe20fdcf9","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489","tls_fault.py":"10e125f9623bc32a420a1d83e6d46fe30aa1ca8ff4da97a3e2422fc0e11ec42d"},"source_recipe_sha256":"b1972d556f28433932a449636755077f7ee485ef90cca412f153bc7f18881368"} \ No newline at end of file diff --git a/qualification/reference/README.md b/qualification/reference/README.md index 3c52697e3..84c240240 100644 --- a/qualification/reference/README.md +++ b/qualification/reference/README.md @@ -249,6 +249,19 @@ signer keys are absent from that child's environment. The native issuer/gateway must still verify every permit/record: a transported artifact grants no authority. The protected workflow has not yet connected this mailbox to admitted corpora. +`production_journey.py` and `journey_session.py` now retain one hosted root +operator across fixed phases: prepare, commission, import the first release, +ordinary live execution, cleanup, and final proposal closure. The author plan's +bounded session survives short proof expiry; every submission still refreshes +and reauthenticates an original source label. The root peer protocol accepts +only a phase or status command. Public mailbox extraction and native authority +verification remain separate. Retained copies are independently rescanned +before the runner can upload them. Failed setup invalidates proposals, keeps +scan canaries, and attempts all owned cleanup with native credential collection +before retiring the renewing workload identity. These entry points still need +the protected workflow's complete job sequence and the remaining case handlers; +they do not establish a passing protected qualification. + `author_operator.py` runs in the same credential-free installed environment as packet authoring, in a separate process with a fresh operator key. It rechecks the native recipe digest, lock and both exact contexts, reconstructs each diff --git a/qualification/reference/family_harness.py b/qualification/reference/family_harness.py index 6b3d65abd..b4830dbe0 100644 --- a/qualification/reference/family_harness.py +++ b/qualification/reference/family_harness.py @@ -44,8 +44,11 @@ def consumer_python(): def source_commit(): - revision = command(['/usr/bin/git', 'rev-parse', 'HEAD']) - status = command(['/usr/bin/git', 'status', '--porcelain']) + # A protected root controller reads the runner-owned checkout. Trust only + # this exact source directory for these read-only Git invocations. + git = ['/usr/bin/git', '-c', 'safe.directory=' + str(ROOT)] + revision = command([*git, 'rev-parse', 'HEAD']) + status = command([*git, 'status', '--porcelain']) require(revision.returncode == status.returncode == 0 and not status.stdout.strip(), 'qualification.harness.source-not-clean') commit = revision.stdout.decode('ascii').strip() diff --git a/qualification/reference/generate_families.py b/qualification/reference/generate_families.py index 683fa71f9..b594b5828 100644 --- a/qualification/reference/generate_families.py +++ b/qualification/reference/generate_families.py @@ -18,7 +18,7 @@ REFERENCE = ROOT / 'qualification/reference' SOURCES_TO_PIN = ['family_corpus.py', 'family_harness.py', 'family_operations.py', 'packet_plan.py', 'author_packets.py', 'author_socket.py', 'retained_author.py', 'author_operator.py', 'production_setup.py', - 'network_fault.py', 'production_environment.py', + 'network_fault.py', 'production_environment.py', 'production_journey.py', 'journey_session.py', 'controller_socket.py', 'installed_submit.py', 'installed_submit.mjs', 'common.py', 'fresh_evidence.py', 'native_observation.py', 'measure.py', 'provider_readback.py', 'resource_io.py', 'resource_summary.py', 'expand.py', 'stripe_platform.py', 'airtable_record.py', 'stripe_resources.py', 'airtable_resources.py'] diff --git a/qualification/reference/journey_session.py b/qualification/reference/journey_session.py new file mode 100644 index 000000000..7243b8229 --- /dev/null +++ b/qualification/reference/journey_session.py @@ -0,0 +1,257 @@ +#!/usr/bin/env python3 +"""Private fixed-phase IPC for one hosted operator, across workflow steps. + +Only the root peer can advance the source-owned sequence or request its status. +Commands cannot select scripts, packets, expectations or secret destinations. +The artifact reader is a separate credential-minimal source-owned process. +""" + +import argparse +import os +from pathlib import Path +import re +import signal +import socket +import subprocess +import sys +import time +from types import SimpleNamespace + +from common import canonical, closed, Refusal, require, sha256 +import controller_socket as controller +from expand import read +from production_journey import Journey, PHASES, GITHUB_INPUTS +from resource_io import finish, write_bytes + +import artifact_wait +import scan_publication + +REQUEST = 'auths.qualification-journey-command/1' +REPLY = 'auths.qualification-journey-reply/1' +COMMANDS = [*PHASES, 'status', 'abort'] +INPUT_NAMES = ['family', 'root', 'binary', 'issuer', 'python', 'kit', 'wheel', 'node', 'script', 'package', + 'exports', 'runner_uid', 'runner_gid'] +PROVIDER_NAMES = ['STRIPE_QUALIFICATION_SETUP_KEY', 'STRIPE_QUALIFICATION_RUNTIME_KEY', + 'STRIPE_QUALIFICATION_NEXT_RUNTIME_KEY', 'AIRTABLE_QUALIFICATION_TOKEN', 'AIRTABLE_QUALIFICATION_NEXT_TOKEN'] + + +def checked_command(value, family): + closed(value, ['schema', 'family', 'command']) + require(value['schema'] == REQUEST and value['family'] == family and value['command'] in COMMANDS, + 'qualification.journey.command') + return value['command'] + + +def endpoint(root, existing=True): + return controller.endpoint(Path(root).absolute() / 'control/session.sock', existing=existing) + + +def call(root, family, command): + request = {'schema': REQUEST, 'family': family, 'command': command} + checked_command(request, family) + with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as connection: + connection.settimeout(3600) + connection.connect(str(endpoint(root))) + controller.peer(connection) + connection.sendall(canonical(request) + b'\n') + reply = controller.receive(connection, 4096) + closed(reply, ['schema', 'ok', 'code', 'family', 'not_after', 'next_phase', 'retired']) + require(reply['schema'] == REPLY and type(reply['ok']) is bool and reply['family'] == family + and type(reply['not_after']) is int and type(reply['next_phase']) is int + and 0 <= reply['next_phase'] <= len(PHASES) and type(reply['retired']) is bool, + 'qualification.journey.reply') + if not reply['ok']: + code = reply['code'] + require(type(code) is str and re.fullmatch(r'qualification\.[a-z0-9.-]{1,128}', code), + 'qualification.journey.reply') + raise Refusal(code) + require(reply['code'] is None, 'qualification.journey.reply') + return reply + + +def export(journey, kind, destination, owner, group): + require(kind in ['commissioning-inputs', 'first-proposal', 'final-proposal'] + and not destination.exists() and not destination.is_symlink(), + 'qualification.journey.export-directory') + journey.scan() + if kind == 'commissioning-inputs': + from expand import decode + carrier = decode(read(journey.work / 'public-packets.json', 65536)) + names = {name: name for name in ['tuple.json', 'recipe.json', 'profile.lock.json', 'resources.json']} + names.update({'offline/' + member + '.json': 'offline/' + member + '.json' + for member in ['conformance', 'differential']}) + packets = ['public-packets.json', *carrier['trusted_contexts']] + packets += [packet[field] for packet in carrier['packets'] for field in ['proof', 'action']] + names.update({'packets/' + name: name for name in packets}) + else: + inventory = scan_publication.sources(journey.work / 'proposal') + names = {name: 'proposal/' + name for name, _kind, _digest in inventory} + require(0 < len(names) <= scan_publication.MAX_FILES, 'qualification.journey.export-bound') + destination.mkdir(mode=0o700) + expected = {} + try: + for name, source in sorted(names.items()): + output = destination / name + output.parent.mkdir(mode=0o700, parents=True, exist_ok=True) + payload = read(journey.work / source, scan_publication.MAX_BYTES) + require(all(canary not in payload for canary in journey.canaries), 'qualification.journey.secret-exposed') + write_bytes(output, payload, new=True) + expected[name] = sha256(payload) + inventory = scan_publication.sources(destination) + require({name: digest for name, _kind, digest in inventory} == expected, + 'qualification.journey.export-changed') + # Scan these actual retained copies, including encoded secret forms, + # before allowing the runner to read or upload them. + scan = [journey.issuer, 'stage-redaction', '--canaries', journey.work / 'canaries'] + for name in sorted(names): + scan += ['--source', 'evidence=' + str(destination / name)] + journey.call([*scan, '--out', journey.controller / ('export-' + kind + '.json')]) + require(scan_publication.sources(destination) == inventory, 'qualification.journey.export-changed') + for parent, directories, files in os.walk(destination, topdown=False): + for name in files: + os.chown(Path(parent) / name, owner, group) + for name in directories: + os.chown(Path(parent) / name, owner, group) + os.chown(destination, owner, group) + except BaseException: + import shutil + shutil.rmtree(destination) + raise + + +def serve(args): + journey = Journey(args.family, args.root, args.binary, args.issuer, args.python, args.kit, + args.wheel, args.node, args.script, args.package, os.environ) + exports = Path(args.exports).absolute() + require(not exports.exists() and exports.resolve() == exports and not exports.is_relative_to(journey.root) + and type(args.runner_uid) is int and 0 < args.runner_uid < (1 << 32) - 1 + and type(args.runner_gid) is int and 0 < args.runner_gid < (1 << 32) - 1, + 'qualification.journey.export-directory') + exports.mkdir(mode=0o700) + os.chown(exports, args.runner_uid, args.runner_gid) + stopping, complete = False, False + def interrupted(_signal, _frame): + nonlocal stopping + stopping = True + for number in [signal.SIGTERM, signal.SIGINT]: + signal.signal(number, interrupted) + path = endpoint(args.root, existing=False) + try: + with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as server: + server.bind(str(path)) + os.chmod(path, 0o600) + inode = os.lstat(path).st_ino + server.listen(1) + server.settimeout(0.25) + while not stopping and time.monotonic() < journey.deadline: + try: + connection, _ = server.accept() + except socket.timeout: + continue + with connection: + connection.settimeout(3600) + code = None + try: + controller.peer(connection) + command = checked_command(controller.receive(connection, 4096), args.family) + if command == 'abort': + journey.abort() + stopping = True + elif command != 'status': + journey.advance(command) + kind = {'prepare': 'commissioning-inputs', 'commission': 'first-proposal', + 'final-proposal': 'final-proposal'}.get(command) + if kind is not None: + export(journey, kind, exports / kind, args.runner_uid, args.runner_gid) + if command == 'final-proposal': + # Copies were separately scanned with the + # retained canaries; now remove them locally. + (journey.work / 'canaries').unlink() + complete, stopping = True, True + except (Refusal, OSError, ValueError, KeyError, TypeError, subprocess.SubprocessError) as error: + code = str(error) if isinstance(error, Refusal) else 'qualification.journey.refused' + if re.fullmatch(r'qualification\.[a-z0-9.-]{1,128}', code) is None: + code = 'qualification.journey.refused' + journey.failed = True + stopping = True + reply = {'schema': REPLY, 'ok': code is None, 'code': code, 'family': journey.family, + 'not_after': journey.not_after, 'next_phase': journey.next_phase, 'retired': journey.retired} + try: + connection.sendall(canonical(reply) + b'\n') + except OSError: + journey.failed, stopping, complete = True, True, False + if path.exists() and os.lstat(path).st_ino == inode: + path.unlink() + require(complete, 'qualification.journey.not-complete') + finally: + if not complete: + journey.abort() + + +def start(args): + require(os.getuid() == 0 and not args.root.exists(), 'qualification.journey.identity') + environment = {name: os.environ[name] for name in [*GITHUB_INPUTS, + 'ACTIONS_ID_TOKEN_REQUEST_URL', 'ACTIONS_ID_TOKEN_REQUEST_TOKEN']} + environment.update({name: os.environ[name] for name in PROVIDER_NAMES if name in os.environ}) + environment['PATH'] = '/usr/sbin:/usr/bin:/sbin:/bin' + if 'RUNNER_TRACKING_ID' in os.environ: + environment['RUNNER_TRACKING_ID'] = os.environ['RUNNER_TRACKING_ID'] + arguments = [sys.executable, '-B', str(Path(__file__).absolute()), 'serve'] + for name in INPUT_NAMES: + arguments += ['--' + name.replace('_', '-'), str(getattr(args, name))] + process = subprocess.Popen(arguments, env=environment, cwd='/', stdin=subprocess.DEVNULL, + stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, start_new_session=True) + started = False + try: + deadline = time.monotonic() + 30 + while time.monotonic() < deadline: + require(process.poll() is None, 'qualification.journey.session-not-started') + if (args.root / 'control/session.sock').exists(): + call(args.root, args.family, 'status') + started = True + return + time.sleep(0.05) + raise Refusal('qualification.journey.session-not-started') + finally: + if not started and process.poll() is None: + process.terminate() + process.wait(timeout=10) + + +def receive(args): + require(args.kind in ['commissioning-permit', 'first-release'], 'qualification.journey.mailbox') + status = call(args.root, args.family, 'status') + require(status['next_phase'] == (1 if args.kind == 'commissioning-permit' else 2), + 'qualification.journey.mailbox-order') + artifact_wait.wait(SimpleNamespace(kind=args.kind, family=args.family, not_after=status['not_after'], + out=args.root / 'mailboxes' / args.kind)) + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + commands = parser.add_subparsers(dest='verb', required=True) + for name in ['start', 'serve']: + command = commands.add_parser(name) + for field in INPUT_NAMES: + command.add_argument('--' + field.replace('_', '-'), required=True, + type=int if field in ['runner_uid', 'runner_gid'] else str if field == 'family' else + lambda value: Path(value).absolute()) + for name in ['advance', 'receive']: + command = commands.add_parser(name) + command.add_argument('--family', required=True) + command.add_argument('--root', type=lambda value: Path(value).absolute(), required=True) + if name == 'advance': + command.add_argument('--phase', choices=COMMANDS, required=True) + else: + command.add_argument('--kind', choices=['commissioning-permit', 'first-release'], required=True) + args = parser.parse_args() + def dispatch(): + if args.verb == 'advance': + call(args.root, args.family, args.phase) + else: + {'start': start, 'serve': serve, 'receive': receive}[args.verb](args) + finish(dispatch) + + +if __name__ == '__main__': + main() diff --git a/qualification/reference/production_journey.py b/qualification/reference/production_journey.py new file mode 100644 index 000000000..8d3831f58 --- /dev/null +++ b/qualification/reference/production_journey.py @@ -0,0 +1,329 @@ +"""One root operator session across separately reviewed authority exchanges. + +The original installed author, provider ledger and measurements survive both +protected stages. Mailboxes contain bounded public data only; native authority +verification stays mandatory. No missing operation can close a phase. +""" + +import os +from pathlib import Path +import subprocess +import sys +import threading +import time +from types import SimpleNamespace + +import airtable_record +import stripe_platform +from common import closed, digest, Refusal, require, sha256 +import controller_socket +from expand import child, decode, read +from family_corpus import authenticate, compile_plan, RESOURCES +from family_harness import ROOT +from family_operations import Operations +from generate_families import generate +from network_fault import Isolation +from packet_plan import prepare as prepare_packets +from production_environment import Infrastructure +from production_setup import Deployment +from provider_readback import ReadBack +from retained_author import RetainedAuthor +from resource_io import write, write_bytes +from stripe_resources import Resources as StripeResources +from airtable_resources import Resources as AirtableResources + +sys.path.insert(0, str(ROOT / 'qualification/run')) +import artifact_wait +import close_proposal +import scan_publication + +ENVIRONMENT = 'gateway-custody-live' +PHASES = ['prepare', 'commission', 'import-first', 'live', 'cleanup', 'final-proposal'] +GITHUB_INPUTS = ['GITHUB_REPOSITORY', 'GITHUB_EVENT_NAME', 'GITHUB_REF', 'GITHUB_RUN_ID', + 'GITHUB_RUN_ATTEMPT', 'GITHUB_SHA', 'GITHUB_ACTIONS', 'RUNNER_ENVIRONMENT'] + + +def provider_keys(family, environment): + """Reject absent or fake rotation before any infrastructure/provider write.""" + stripe = family == stripe_platform.FAMILY + require(stripe or family == airtable_record.FAMILY, 'qualification.journey.family') + names = ['STRIPE_QUALIFICATION_RUNTIME_KEY', 'STRIPE_QUALIFICATION_NEXT_RUNTIME_KEY'] if stripe \ + else ['AIRTABLE_QUALIFICATION_TOKEN', 'AIRTABLE_QUALIFICATION_NEXT_TOKEN'] + result = [] + for name in names + (['STRIPE_QUALIFICATION_SETUP_KEY'] if stripe else []): + value = environment.get(name) + prefix = 'sk_test_' if name.endswith('SETUP_KEY') else 'rk_test_' if stripe else 'pat' + require(type(value) is str and value.startswith(prefix) and 20 <= len(value) <= 2048 + and all(33 <= ord(character) <= 126 for character in value), + 'qualification.journey.provider-key') + result.append(value.encode()) + require(result[0] != result[1], 'qualification.journey.genuine-rotation-required') + return result + + +class Journey: + def __init__(self, family, root, binary, issuer, python, kit, wheel, node, script, package, environment): + require(sys.platform == 'linux' and os.getuid() == 0, 'qualification.journey.identity') + self.run, self.attempt, self.commit = artifact_wait.identity(environment) + require(environment.get('GITHUB_ACTIONS') == 'true' + and environment.get('RUNNER_ENVIRONMENT') == 'github-hosted', 'qualification.journey.host') + self.family, self.root = family, Path(root).absolute() + self.keys = provider_keys(family, environment) + require(not self.root.exists() and self.root.resolve() == self.root + and not self.root.is_relative_to(ROOT), 'qualification.journey.private-directory') + self.binary, self.issuer, self.python, self.kit, self.wheel, self.node, self.script, self.package = [ + Path(path).absolute() for path in [binary, issuer, python, kit, wheel, node, script, package]] + self.environment = {name: environment[name] for name in GITHUB_INPUTS} + # The infrastructure consumes OIDC only; no provider key is put in its + # environment, any native child or the credential-free author. + self.identity_environment = {**self.environment, **{name: environment[name] for name in + ['ACTIONS_ID_TOKEN_REQUEST_URL', 'ACTIONS_ID_TOKEN_REQUEST_TOKEN']}} + self.root.mkdir(mode=0o700) + self.work = self.root / 'publication' + self.work.mkdir(mode=0o700) + (self.work / 'cases').mkdir(mode=0o700) + self.mailboxes = self.root / 'mailboxes' + self.mailboxes.mkdir(mode=0o700) + # Author/gateway UIDs need traversal of their own private descendants. + # Publication and mailboxes remain root-only underneath this parent. + os.chmod(self.root, 0o711) + self.controller = self.root / 'control' + self.controller.mkdir(mode=0o700) + self.endpoint = self.controller / 'operations.sock' + require(len(str(self.endpoint).encode()) <= 107, 'qualification.journey.socket-bound') + self.canaries = list(self.keys) + self.infrastructure = self.author = self.deployment = self.isolation = self.resources = None + self.operations = self.worker = None + self.stopping, self.ready = threading.Event(), threading.Event() + self.worker_failed = False + self.next_phase, self.failed, self.retired = 0, False, False + self.deadline = time.monotonic() + 7200 + self.not_after = int(time.time()) + 7200 + + def call(self, arguments, *, environment=None, timeout=120, maximum=65536): + result = subprocess.run(list(map(str, arguments)), stdin=subprocess.DEVNULL, capture_output=True, + timeout=timeout, cwd=ROOT, env=environment or {'PATH': '/usr/bin:/bin'}) + require(len(result.stdout) <= maximum and len(result.stderr) <= 65536 + and all(canary not in result.stdout + result.stderr for canary in self.canaries), + 'qualification.journey.private-output') + require(result.returncode == 0, 'qualification.journey.source-command') + return result.stdout + + def git(self, *arguments): + return self.call(['/usr/bin/git', '-c', 'safe.directory=' + str(ROOT), *arguments], + maximum=2 * 1024 * 1024) + + def check_source(self): + generate(check=True) + require(self.git('rev-parse', 'HEAD').decode().strip() == self.commit + and not self.git('status', '--porcelain').strip(), 'qualification.journey.source-binding') + + def scan(self): + payload = b'\n'.join(dict.fromkeys(self.canaries)) + b'\n' + require(len(payload) <= scan_publication.MAX_BYTES, 'qualification.journey.canary-bound') + write_bytes(self.work / 'canaries', payload, new=not (self.work / 'canaries').exists()) + scan_publication.scan(self.work, self.issuer, keep_canaries=True) + + def start_controller(self): + def run(): + try: + controller_socket.serve(self.endpoint, self.operations, self.deadline, self.stopping, self.ready) + except BaseException: + self.worker_failed = True + self.ready.set() + self.worker = threading.Thread(target=run, name='auths-family-operations', daemon=True) + self.worker.start() + require(self.ready.wait(10) and not self.worker_failed and self.worker.is_alive(), + 'qualification.journey.controller-not-ready') + + def stage(self, phase): + if phase != 'offline': + require(self.worker is not None and self.worker.is_alive() and not self.worker_failed, + 'qualification.journey.controller-refused') + self.infrastructure.check_identity() + self.operations.begin(phase) + environment = {'PATH': '/usr/bin:/bin', 'PYTHONNOUSERSITE': '1', **self.environment, + 'AUTHS_GATEWAY': str(self.binary), 'AUTHS_QUALIFICATION': str(self.issuer), + 'AUTHS_QUALIFICATION_CONTROLLER': str(self.endpoint)} + self.call([self.issuer, 'run-stage', '--phase', phase, '--corpus', self.work / 'corpus.json', + '--harness', ROOT / 'qualification/families' / self.family / 'harness', + '--tuple', self.work / 'tuple.json', '--work-dir', self.work], environment=environment, timeout=2400) + + def prepare(self): + self.check_source() + for name in ['author_socket.py', 'author_packets.py', 'author_operator.py', 'installed_submit.py']: + require(read(self.kit / name, 2 * 1024 * 1024) == read(ROOT / 'qualification/reference' / name, 2 * 1024 * 1024), + 'qualification.journey.consumer-source') + require(read(self.script, 2 * 1024 * 1024) == read(ROOT / 'qualification/reference/installed_submit.mjs', 2 * 1024 * 1024), + 'qualification.journey.consumer-source') + self.infrastructure = Infrastructure(self.root / 'infrastructure', self.identity_environment, self.canaries) + self.infrastructure.start_identity() + self.infrastructure.synchronize_clock() + production = self.infrastructure.start_database() + self.isolation = Isolation() + self.isolation.__enter__() + self.resources = StripeResources({'runtime': self.keys[0].decode(), 'setup': self.keys[2].decode()}) \ + if self.family == stripe_platform.FAMILY else AirtableResources(self.keys[0].decode()) + self.journal = self.controller / 'resources.json' + self.resources.prepare('recipe-qualification/' + self.run + '/' + self.attempt, + RESOURCES, self.journal, self.work / 'resources.json') + prepare_packets(SimpleNamespace(family=self.family, resources=self.work / 'resources.json', + gateway=self.binary, work=self.work)) + self.author = RetainedAuthor(self.python, self.kit, self.work, self.root / 'packet-author') + carrier = decode(read(self.work / 'public-packets.json', 65536)) + # Original proofs are deliberately five minutes; only a source label + # can refresh them within the separately bounded two-hour action plan. + plan = decode(read(self.work / 'packet-plan.json', 65536)) + self.not_after = min(self.not_after, plan['not_after']) + self.deadline = min(self.deadline, time.monotonic() + self.not_after - time.time()) + require(time.time() < self.not_after, 'qualification.journey.author-expired') + contract = self.call([self.issuer, 'contract-id', '--contract', + ROOT / 'qualification/families' / self.family / 'contract.json']).decode().strip() + digest(contract) + tuple_value = child(self.binary, ['qualification-candidate', '--recipe', self.work / 'recipe.json', + '--profile-lock', self.work / 'profile.lock.json', '--recipe-family', self.family, + '--provider-contract-id', contract]) + write(self.work / 'tuple.json', tuple_value, new=True) + self.call([self.python, '-B', self.kit / 'author_operator.py', '--gateway', self.binary, '--work', self.work]) + resources, reviewed = authenticate(self.family, self.work, self.binary, tuple_value) + operator = decode(read(self.work / 'operator-report.json', 65536)) + require(all(operator['operator_principal'] not in value['actors'] for value in reviewed.values()), + 'qualification.journey.operator-separation') + write(self.work / 'corpus.json', compile_plan(self.family, resources, reviewed, + tuple_value['compiled_recipe_sha256']), new=True) + self.packages(tuple_value) + self.stage('offline') + self.offline_evidence() + write(self.work / 'facts.json', {'commit': self.commit, + 'source_closure_sha256': sha256(self.git('ls-tree', '-r', 'HEAD')), + 'generated_artifacts_sha256': sha256(read(self.binary, 256 * 1024 * 1024) + + read(self.issuer, 256 * 1024 * 1024)), + 'recipe_decision_record_sha256': sha256(read(ROOT / 'qualification/families' / self.family / 'decision-record.md', 65536)), + 'corpus_manifest_sha256': sha256(read(self.work / 'corpus.json', 2 * 1024 * 1024))}, new=True) + self.deployment = Deployment(self.binary, self.work, self.root / 'deployment', production, self.canaries) + account = resources['platform'] if self.family == stripe_platform.FAMILY else 'airtable-qualification' + self.deployment.install(self.keys[0], account) + for host in [0, 1]: + for context in [0, 1]: + self.deployment.start(host, context) + self.operations = Operations(self.deployment, self.author, + ReadBack(self.family, resources, self.keys[0].decode()), resources, reviewed) + self.operations.configure_rotation(self.keys[0], self.keys[1]) + self.operations.configure_consumers(self.python, self.kit) + self.operations.configure_typescript(self.node, self.script) + self.start_controller() + self.scan() + + def packages(self, tuple_value): + author = decode(read(self.work / 'author-report.json', 65536)) + package = decode(read(self.package / 'package.json', 65536)) + closed(package, ['schema', 'source_commit', 'name', 'version', 'file', 'sha256', 'qualification_issued']) + require(package['schema'] == 'auths.qualification-installed-package/1' + and package['source_commit'] == self.commit and package['name'] == '@auths-dev/sdk' + and package['qualification_issued'] is False + and type(package['file']) is str and Path(package['file']).name == package['file'] + and package['file'].endswith('.tgz') + and sha256(read(self.package / package['file'], 64 * 1024 * 1024)) == digest(package['sha256']), + 'qualification.journey.typescript-package') + write(self.work / 'packages.json', sorted([ + {'name': 'auths', 'version': author['sdk_version'], 'sha256': sha256(read(self.wheel, 64 * 1024 * 1024))}, + {'name': 'auths-gateway', 'version': tuple_value['target']['gateway_version'], + 'sha256': tuple_value['target']['gateway_build_sha256']}, + {'name': package['name'], 'version': package['version'], 'sha256': package['sha256']}, + ], key=lambda package: package['name']), new=True) + + def offline_evidence(self): + directory = self.work / 'offline' + directory.mkdir(mode=0o700) + for member in ['conformance', 'differential']: + self.call([self.issuer, 'evidence', '--member', member, '--tuple', self.work / 'tuple.json', + '--commit', self.commit, '--cases', self.work / 'cases' / (member + '.offline.json'), + '--out', directory / (member + '.json')]) + + def commission(self): + self.deployment.register_commissioning(self.mailboxes / 'commissioning-permit') + self.stage('commissioning') + self.scan() + close_proposal.close(self.family, self.work, ENVIRONMENT, self.run + '-' + self.attempt, + 'commissioning', self.issuer) + + def import_first(self): + self.deployment.import_release(self.mailboxes / 'first-release') + # Each serving process reloads the independently verified installed + # qualification. No production-policy switch or temporary exception. + for host in [0, 1]: + for context in [0, 1]: + self.deployment.stop(host, context) + self.deployment.start(host, context) + self.operations.begin('live') + + def live(self): + # begin('live') already verified all four ordinary required gates. + require(self.operations.phase == 'live', 'qualification.journey.first-release-required') + self.infrastructure.check_identity() + environment = {'PATH': '/usr/bin:/bin', 'PYTHONNOUSERSITE': '1', **self.environment, + 'AUTHS_GATEWAY': str(self.binary), 'AUTHS_QUALIFICATION': str(self.issuer), + 'AUTHS_QUALIFICATION_CONTROLLER': str(self.endpoint)} + self.call([self.issuer, 'run-stage', '--phase', 'live', '--corpus', self.work / 'corpus.json', + '--harness', ROOT / 'qualification/families' / self.family / 'harness', + '--tuple', self.work / 'tuple.json', '--work-dir', self.work], environment=environment, timeout=2400) + self.scan() + + def cleanup(self): + failures = [] + def attempt(action): + try: + action() + except (Refusal, OSError, ValueError, KeyError, subprocess.SubprocessError): + failures.append(True) + self.stopping.set() + if self.worker is not None: + self.worker.join(timeout=130) + if self.worker.is_alive(): + failures.append(True) + if self.deployment is not None: + attempt(self.deployment.close) + # Collect while the actual web identity is still renewing. A + # partial native installation cannot invent a collector result. + if (self.deployment.state(0) / 'installation.json').is_file(): + attempt(self.deployment.retire_credentials) + else: + failures.append(True) + if self.resources is not None and hasattr(self, 'journal') and self.journal.exists(): + attempt(lambda: self.resources.cleanup(self.journal)) + if self.author is not None: + attempt(self.author.close) + attempt(self.author.abort) + if self.isolation is not None: + attempt(lambda: self.isolation.__exit__(None, None, None)) + if self.infrastructure is not None: + attempt(self.infrastructure.close) + self.retired = not failures + require(self.retired, 'qualification.journey.cleanup-incomplete') + + def final_proposal(self): + require(self.retired, 'qualification.journey.cleanup-required') + self.scan() + close_proposal.close(self.family, self.work, ENVIRONMENT, self.run + '-' + self.attempt, + 'live', self.issuer) + + def advance(self, phase): + require(phase in PHASES and not self.failed and self.next_phase < len(PHASES) + and phase == PHASES[self.next_phase], 'qualification.journey.phase') + try: + if phase != 'cleanup': + require(time.monotonic() < self.deadline and time.time() < self.not_after, + 'qualification.journey.deadline') + self.check_source() + getattr(self, phase.replace('-', '_'))() + self.next_phase += 1 + except BaseException: + self.failed = True + close_proposal.invalidate(self.work) + raise + + def abort(self): + self.failed = True + close_proposal.invalidate(self.work) + if not self.retired: + self.cleanup() diff --git a/qualification/reference/production_setup.py b/qualification/reference/production_setup.py index 4fe09990b..1e41e0c17 100644 --- a/qualification/reference/production_setup.py +++ b/qualification/reference/production_setup.py @@ -220,7 +220,7 @@ def start(self, host, context=0): require(False, 'qualification.production.gateway-not-ready') def stop(self, host, context=0, *, crash=False): - process = self.processes.pop((host, context), None) + process = self.processes.get((host, context)) require(process is not None and process.poll() is None, 'qualification.production.gateway-not-running') process.send_signal(signal.SIGKILL if crash else signal.SIGTERM) try: @@ -228,7 +228,9 @@ def stop(self, host, context=0, *, crash=False): except subprocess.TimeoutExpired: process.kill() process.wait(timeout=5) + self.processes.pop((host, context)) require(False, 'qualification.production.gateway-stop-timeout') + self.processes.pop((host, context)) require(process.returncode == (-signal.SIGKILL if crash else 0), 'qualification.production.gateway-stop-result') @@ -387,21 +389,38 @@ def doctor(self, host=0, context=0): return decode(raw), raw def close(self): + failures = [] for host, context in list(self.processes): - self.stop(host, context) + if self.processes[(host, context)].poll() is not None: + self.processes.pop((host, context)) + failures.append(True) + continue + try: + self.stop(host, context) + except (Refusal, OSError, subprocess.SubprocessError): + failures.append(True) + require(not failures, 'qualification.production.gateway-cleanup-incomplete') def retire_credentials(self): require(not self.processes, 'qualification.production.host-running') - result = self.command(['revoke', '--state-dir', self.state(0), '--store-only']) - require(result.get('state') == 'revoked' and result.get('credential_deletion') == 'not-attempted', - 'qualification.production.revoke') + failures = [] + try: + result = self.command(['revoke', '--state-dir', self.state(0), '--store-only']) + require(result.get('state') == 'revoked' and result.get('credential_deletion') == 'not-attempted', + 'qualification.production.revoke') + except (Refusal, OSError, subprocess.SubprocessError): + failures.append(True) for context in [0, 1]: for host in [0, 1]: - result = self.command(['credential-collect', '--state-dir', self.state(host, context)], administrative=True) - closed(result, ['schema', 'deleted']) - require(result['schema'] == 'auths.gateway-credential-collection/1' - and type(result['deleted']) is int and result['deleted'] >= 0, - 'qualification.production.credential-collection') + try: + result = self.command(['credential-collect', '--state-dir', self.state(host, context)], administrative=True) + closed(result, ['schema', 'deleted']) + require(result['schema'] == 'auths.gateway-credential-collection/1' + and type(result['deleted']) is int and result['deleted'] >= 0, + 'qualification.production.credential-collection') + except (Refusal, OSError, subprocess.SubprocessError): + failures.append(True) + require(not failures, 'qualification.production.credential-cleanup-incomplete') class CommissioningChild: diff --git a/qualification/reference/tests/test_journey_session.py b/qualification/reference/tests/test_journey_session.py new file mode 100644 index 000000000..051cb2da7 --- /dev/null +++ b/qualification/reference/tests/test_journey_session.py @@ -0,0 +1,105 @@ +"""Session refusal and cleanup ordering; these tests issue no authority.""" + +from pathlib import Path +import sys +import tempfile +import threading +import time +import unittest +from unittest.mock import patch + +sys.path.insert(0, str(Path(__file__).resolve().parents[1])) +from common import Refusal +import journey_session as session +import production_journey as production + + +class Session(unittest.TestCase): + def test_rpc_can_select_a_known_phase_but_no_inputs_or_execution_program(self): + request = {'schema': session.REQUEST, 'family': 'airtable-record-update-v1', 'command': 'prepare'} + self.assertEqual(session.checked_command(request, request['family']), 'prepare') + for changed in [dict(request, command='sign'), dict(request, command='__init__'), + dict(request, expected={'outcome': 'observed'}), dict(request, key='synthetic-only'), + dict(request, root='/unreviewed'), dict(request, command_line=['unreviewed']), + dict(request, family='unreviewed')]: + with self.assertRaises(Refusal): session.checked_command(changed, request['family']) + + def test_genuine_rotation_preflight_refuses_before_a_provider_can_be_configured(self): + names = ['STRIPE_QUALIFICATION_RUNTIME_KEY', 'STRIPE_QUALIFICATION_NEXT_RUNTIME_KEY', + 'STRIPE_QUALIFICATION_SETUP_KEY'] + environment = dict(zip(names, ['rk_test_SYNTHETIC_ONLY_FIRST', + 'rk_test_SYNTHETIC_ONLY_SECOND', 'sk_test_SYNTHETIC_ONLY_SETUP'])) + self.assertEqual(len(production.provider_keys('stripe-platform-refund-v1', environment)), 3) + for changed in [{}, dict(environment, STRIPE_QUALIFICATION_NEXT_RUNTIME_KEY=environment[names[0]]), + dict(environment, STRIPE_QUALIFICATION_RUNTIME_KEY=environment[names[2]]), + dict(environment, STRIPE_QUALIFICATION_RUNTIME_KEY='rk_live_SYNTHETIC_ONLY')]: + with self.assertRaises(Refusal): production.provider_keys('stripe-platform-refund-v1', changed) + + def journey(self, root): + value = object.__new__(production.Journey) + value.next_phase, value.failed, value.retired = 0, False, False + value.work, value.controller = root / 'publication', root / 'control' + value.work.mkdir() + value.controller.mkdir() + (value.work / 'cases').mkdir() + value.deadline, value.not_after = time.monotonic() + 60, int(time.time()) + 60 + value.check_source = lambda: None + return value + + def test_failed_setup_invalidates_proposal_and_cannot_advance_or_be_replayed(self): + with tempfile.TemporaryDirectory() as directory: + value = self.journey(Path(directory)) + (value.work / 'proposal').mkdir() + (value.work / 'proposal/record.json').write_bytes(b'synthetic-only-record') + (value.work / 'canaries').write_bytes(b'synthetic-only-canary') + calls = [] + def prepare(): + calls.append('actual-source-prepare') + raise Refusal('qualification.resources.provider-unavailable') + value.prepare = prepare + with self.assertRaises(Refusal): value.advance('commission') + self.assertEqual(calls, []) + with self.assertRaises(Refusal): value.advance('prepare') + self.assertTrue(value.failed) + self.assertFalse((value.work / 'proposal').exists()) + self.assertTrue((value.work / 'canaries').exists(), 'real scan canaries must survive failure cleanup') + for phase in ['prepare', 'commission', 'live', 'final-proposal']: + with self.assertRaises(Refusal): value.advance(phase) + self.assertEqual(calls, ['actual-source-prepare']) + + def test_all_cleanup_is_attempted_with_credential_collection_before_identity_retirement(self): + with tempfile.TemporaryDirectory() as directory: + value = self.journey(Path(directory)) + value.stopping, value.worker = threading.Event(), None + calls = [] + class Deployment: + def state(self, host): return Path(directory) + def close(self): calls.append('stop-gateways') + def retire_credentials(self): + calls.append('collect-credentials') + raise Refusal('qualification.production.credential-cleanup-incomplete') + class Resources: + def cleanup(self, journal): + calls.append('retire-owned-provider-resources') + raise Refusal('qualification.resources.provider-unavailable') + class Author: + def close(self): calls.append('close-author') + def abort(self): calls.append('abort-own-author') + class Isolation: + def __exit__(self, *_args): calls.append('remove-own-rules') + class Infrastructure: + def close(self): calls.append('retire-identity-and-database') + (Path(directory) / 'installation.json').write_bytes(b'synthetic-only-installation') + value.journal = value.controller / 'resources.json' + value.journal.write_bytes(b'synthetic-only-journal') + value.deployment, value.resources = Deployment(), Resources() + value.author, value.isolation, value.infrastructure = Author(), Isolation(), Infrastructure() + with self.assertRaisesRegex(Refusal, 'cleanup-incomplete'): value.cleanup() + self.assertEqual(calls, ['stop-gateways', 'collect-credentials', 'retire-owned-provider-resources', + 'close-author', 'abort-own-author', 'remove-own-rules', 'retire-identity-and-database']) + self.assertFalse(value.retired) + with self.assertRaisesRegex(Refusal, 'cleanup-required'): value.final_proposal() + + +if __name__ == '__main__': + unittest.main() diff --git a/qualification/run/close_proposal.py b/qualification/run/close_proposal.py index db90faf37..fc2a3d265 100644 --- a/qualification/run/close_proposal.py +++ b/qualification/run/close_proposal.py @@ -41,7 +41,9 @@ def assemble(family, work, environment, run, stage, tool): ['bash', str(script), family, str(work), environment, run, stage], capture_output=True, timeout=120, env={'PATH': os.environ.get('PATH', '/usr/bin:/bin'), - 'AUTHS_QUALIFICATION': str(tool)}, cwd=script.parents[2]) + 'AUTHS_QUALIFICATION': str(tool), 'GIT_CONFIG_COUNT': '1', + 'GIT_CONFIG_KEY_0': 'safe.directory', 'GIT_CONFIG_VALUE_0': str(script.parents[2])}, + cwd=script.parents[2]) publication.require(result.returncode == 0 and len(result.stdout) <= publication.MAX_BYTES and len(result.stderr) <= publication.MAX_BYTES) From 28c8be4565d9dd9f96035e38ca391c5996fc0df2 Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 17:49:28 +0100 Subject: [PATCH 095/108] Measure application file and provider egress isolation under its actual UID --- .../airtable-record-update-v1/contract.json | 2 +- .../corpus-manifest.json | 2 +- .../stripe-platform-refund-v1/contract.json | 2 +- .../corpus-manifest.json | 2 +- qualification/reference/application_probe.py | 52 ++++++++++++++++ qualification/reference/family_operations.py | 32 +++++++++- qualification/reference/generate_families.py | 2 +- qualification/reference/production_journey.py | 2 +- qualification/reference/production_setup.py | 16 +++++ .../reference/tests/test_application_probe.py | 61 +++++++++++++++++++ 10 files changed, 166 insertions(+), 7 deletions(-) create mode 100644 qualification/reference/application_probe.py create mode 100644 qualification/reference/tests/test_application_probe.py diff --git a/qualification/families/airtable-record-update-v1/contract.json b/qualification/families/airtable-record-update-v1/contract.json index 08aafb61c..0ec3c2351 100644 --- a/qualification/families/airtable-record-update-v1/contract.json +++ b/qualification/families/airtable-record-update-v1/contract.json @@ -1 +1 @@ -{"api_release":"web-api-v0-reviewed-2026-10-07","corpus_manifest_sha256":"1a5aa673b3a61c2be0f38e24904eba42061ebe20d8cf8a5a28690348e3b162d8","declarations":{"idempotency_sha256":"74234e98afe7498fb5daf1f36ac2d78acc339464f950703b8c019892f982b90b","observation_sha256":"9dd79dd204fa13a2df3c667d106c66c0526d174a2c018631e2b2f6b897eaf311","recovery_sha256":"7081a92b4cd2d13dab5e7c30e640675a252b62bca20d340e14d62d9c8c048eca","retention_sha256":"4a4b5048c97b16e041af55b032c0b8ac20f5142c4bbcbf31b31c6674770a70d0"},"environment_class":"disposable-live-resources","manual_assumptions":["Airtable supplies no idempotency key for this PATCH; durable gateway admission prevents a second entry.","Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only a fresh GET with the exact replacement and echo can reconcile a lost response.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths.","The reviewed fixed Airtable base and table contain only owner-authorized disposable qualification records."],"oracle_version":"auths-reviewed-reference-v2","provider":"airtable","schema":"auths.provider-contract/1"} \ No newline at end of file +{"api_release":"web-api-v0-reviewed-2026-10-07","corpus_manifest_sha256":"6e569302b75f9f9d48207e603012050305f3bc65cf235ecfd092882ee967a6ac","declarations":{"idempotency_sha256":"74234e98afe7498fb5daf1f36ac2d78acc339464f950703b8c019892f982b90b","observation_sha256":"9dd79dd204fa13a2df3c667d106c66c0526d174a2c018631e2b2f6b897eaf311","recovery_sha256":"7081a92b4cd2d13dab5e7c30e640675a252b62bca20d340e14d62d9c8c048eca","retention_sha256":"4a4b5048c97b16e041af55b032c0b8ac20f5142c4bbcbf31b31c6674770a70d0"},"environment_class":"disposable-live-resources","manual_assumptions":["Airtable supplies no idempotency key for this PATCH; durable gateway admission prevents a second entry.","Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only a fresh GET with the exact replacement and echo can reconcile a lost response.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths.","The reviewed fixed Airtable base and table contain only owner-authorized disposable qualification records."],"oracle_version":"auths-reviewed-reference-v2","provider":"airtable","schema":"auths.provider-contract/1"} \ No newline at end of file diff --git a/qualification/families/airtable-record-update-v1/corpus-manifest.json b/qualification/families/airtable-record-update-v1/corpus-manifest.json index 6c4e77c02..627fba2cc 100644 --- a/qualification/families/airtable-record-update-v1/corpus-manifest.json +++ b/qualification/families/airtable-record-update-v1/corpus-manifest.json @@ -1 +1 @@ -{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"32241d9b4811a55abcdd224ef567df3857dbec34d761ef7a35d1044cdfa52d9f","family":"airtable-record-update-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"af7f984509ab11a3676cacc85eda2fa638c25bf91f7bfedf3ff3c119e47f3c41","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","controller_socket.py":"10519cc775e963360870eac51c7fcac1ffb988b04d5de89dac1dbf3524ba6531","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"b614b12b0789afb2ce4f4b81618db8d6e2333a8b52ec76fc96fbba1be715ee68","family_harness.py":"0e0a42be6cf75dfb3f674b26cbdfbb4c473edea71083dfaad89ecb40dec039ba","family_operations.py":"5b1555d7594aae382a47eab1f9804f9e279029d77cdd0745c0c538588417100b","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","installed_submit.mjs":"9d57a91c4a052fbb9103582689ee99a6d087758dcfee00defa4c762b87187468","installed_submit.py":"f9151c2dffa1a02327b0ba05bdeb180654918a2b913195185a6649d010783dc7","journey_session.py":"3c807ce45dcabe3b39d63333872af3746fe9276aacf5eba30bf903b51d80dfef","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"abebdf9f5704f0a19457347798548d98b3ddb3adbd48e91bc58a82faf4afbd08","network_fault.py":"94340720d8601f79ac77b95d1e855be25195c19b67db3103bbf054d82c02472b","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","production_environment.py":"4afa2491624b0dfbc44fba868474415628d18f1493f8e6c772f108eccd1390da","production_journey.py":"d7eab2f2df1d51b7a201c146184c76f2a046e8867631c3facc066ab067412525","production_setup.py":"7caf73bbeea7260ef494a2406cc78d313ab10a613cba19fa0d58fc491bc75fcd","provider_readback.py":"d576768208985b3544f146597d181d796f2a5e2eca5026dae3fa15cadcfe65b2","resource_io.py":"b0ed0223fd11a1a28c25278de539a9b2ed63881b26a8e00e386f25d4d9aa9384","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","retained_author.py":"bfd01c7df44f5f525326dfbda13b5ebc6b854f15787a8b2923de883fe20fdcf9","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489","tls_fault.py":"10e125f9623bc32a420a1d83e6d46fe30aa1ca8ff4da97a3e2422fc0e11ec42d"},"source_recipe_sha256":"c0f21ff1d3c8e344fee20a9a0c25bb14a264417ed53418ad536789a6096fb16e"} \ No newline at end of file +{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"32241d9b4811a55abcdd224ef567df3857dbec34d761ef7a35d1044cdfa52d9f","family":"airtable-record-update-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"af7f984509ab11a3676cacc85eda2fa638c25bf91f7bfedf3ff3c119e47f3c41","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","application_probe.py":"5e2dd6a91eb0a2acf2df1079cead5bd67ae5d6743abce6e48201e7326f63daa2","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","controller_socket.py":"10519cc775e963360870eac51c7fcac1ffb988b04d5de89dac1dbf3524ba6531","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"b614b12b0789afb2ce4f4b81618db8d6e2333a8b52ec76fc96fbba1be715ee68","family_harness.py":"0e0a42be6cf75dfb3f674b26cbdfbb4c473edea71083dfaad89ecb40dec039ba","family_operations.py":"37395ed317b91f2c62e7e544587f2508b5a4e9bd565c2363a2aa9ecdf63c80fb","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","installed_submit.mjs":"9d57a91c4a052fbb9103582689ee99a6d087758dcfee00defa4c762b87187468","installed_submit.py":"f9151c2dffa1a02327b0ba05bdeb180654918a2b913195185a6649d010783dc7","journey_session.py":"3c807ce45dcabe3b39d63333872af3746fe9276aacf5eba30bf903b51d80dfef","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"abebdf9f5704f0a19457347798548d98b3ddb3adbd48e91bc58a82faf4afbd08","network_fault.py":"94340720d8601f79ac77b95d1e855be25195c19b67db3103bbf054d82c02472b","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","production_environment.py":"4afa2491624b0dfbc44fba868474415628d18f1493f8e6c772f108eccd1390da","production_journey.py":"179b93aa525ddd73ad1b3e9fcf38eeb540173845025707aed6b9fa9a44e4aad8","production_setup.py":"6ed9488e59514cde495aed9f5efde604c69bf416112759ec24ae36eb79070003","provider_readback.py":"d576768208985b3544f146597d181d796f2a5e2eca5026dae3fa15cadcfe65b2","resource_io.py":"b0ed0223fd11a1a28c25278de539a9b2ed63881b26a8e00e386f25d4d9aa9384","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","retained_author.py":"bfd01c7df44f5f525326dfbda13b5ebc6b854f15787a8b2923de883fe20fdcf9","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489","tls_fault.py":"10e125f9623bc32a420a1d83e6d46fe30aa1ca8ff4da97a3e2422fc0e11ec42d"},"source_recipe_sha256":"c0f21ff1d3c8e344fee20a9a0c25bb14a264417ed53418ad536789a6096fb16e"} \ No newline at end of file diff --git a/qualification/families/stripe-platform-refund-v1/contract.json b/qualification/families/stripe-platform-refund-v1/contract.json index 483c4dbe0..03eb8d940 100644 --- a/qualification/families/stripe-platform-refund-v1/contract.json +++ b/qualification/families/stripe-platform-refund-v1/contract.json @@ -1 +1 @@ -{"api_release":"2025-03-31.basil","corpus_manifest_sha256":"20bc3838a07fa79ff3a29041be9b358a2803bce3ddeeff528723acc6d2b76473","declarations":{"idempotency_sha256":"425a0dca2f279765debfc847c4a01bff60fea5be68dd9d761ae6bb60ce0b8a7b","observation_sha256":"d0ce5a34d987821c69c0a839d9ed66805c625f8324dd42031fcccf0752a8821e","recovery_sha256":"bf2303abce165c175360ac975586431bbc4cf03167489ea317a27de2f0b04abb","retention_sha256":"846c2164e26d1144d9aa146034b4f7ea4dc305136a59ffd94f999d19f2c360ee"},"environment_class":"provider-test-mode","manual_assumptions":["Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","Stripe idempotency is tested only inside the declared 86400-second retention interval.","Stripe test mode and the installed platform are checked by the declared guard on each lease.","The 50-percent payment basis is a read, not an atomic provider balance reservation.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths."],"oracle_version":"auths-reviewed-reference-v2","provider":"stripe","schema":"auths.provider-contract/1"} \ No newline at end of file +{"api_release":"2025-03-31.basil","corpus_manifest_sha256":"f452c395a4eabfe96bd91286f0b179b5342f7c1287b582cf9990add72eccb683","declarations":{"idempotency_sha256":"425a0dca2f279765debfc847c4a01bff60fea5be68dd9d761ae6bb60ce0b8a7b","observation_sha256":"d0ce5a34d987821c69c0a839d9ed66805c625f8324dd42031fcccf0752a8821e","recovery_sha256":"bf2303abce165c175360ac975586431bbc4cf03167489ea317a27de2f0b04abb","retention_sha256":"846c2164e26d1144d9aa146034b4f7ea4dc305136a59ffd94f999d19f2c360ee"},"environment_class":"provider-test-mode","manual_assumptions":["Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","Stripe idempotency is tested only inside the declared 86400-second retention interval.","Stripe test mode and the installed platform are checked by the declared guard on each lease.","The 50-percent payment basis is a read, not an atomic provider balance reservation.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths."],"oracle_version":"auths-reviewed-reference-v2","provider":"stripe","schema":"auths.provider-contract/1"} \ No newline at end of file diff --git a/qualification/families/stripe-platform-refund-v1/corpus-manifest.json b/qualification/families/stripe-platform-refund-v1/corpus-manifest.json index bceddc8ab..0ef3ab084 100644 --- a/qualification/families/stripe-platform-refund-v1/corpus-manifest.json +++ b/qualification/families/stripe-platform-refund-v1/corpus-manifest.json @@ -1 +1 @@ -{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"a72c557b69103a52eb477deb8364ded53cd58407b9ba7ab33ccbda74389fec1e","family":"stripe-platform-refund-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"99901e36cb7c4f5882897603c874698d582e859b5d6b08d53cd80975e89aa01c","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","controller_socket.py":"10519cc775e963360870eac51c7fcac1ffb988b04d5de89dac1dbf3524ba6531","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"b614b12b0789afb2ce4f4b81618db8d6e2333a8b52ec76fc96fbba1be715ee68","family_harness.py":"0e0a42be6cf75dfb3f674b26cbdfbb4c473edea71083dfaad89ecb40dec039ba","family_operations.py":"5b1555d7594aae382a47eab1f9804f9e279029d77cdd0745c0c538588417100b","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","installed_submit.mjs":"9d57a91c4a052fbb9103582689ee99a6d087758dcfee00defa4c762b87187468","installed_submit.py":"f9151c2dffa1a02327b0ba05bdeb180654918a2b913195185a6649d010783dc7","journey_session.py":"3c807ce45dcabe3b39d63333872af3746fe9276aacf5eba30bf903b51d80dfef","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"abebdf9f5704f0a19457347798548d98b3ddb3adbd48e91bc58a82faf4afbd08","network_fault.py":"94340720d8601f79ac77b95d1e855be25195c19b67db3103bbf054d82c02472b","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","production_environment.py":"4afa2491624b0dfbc44fba868474415628d18f1493f8e6c772f108eccd1390da","production_journey.py":"d7eab2f2df1d51b7a201c146184c76f2a046e8867631c3facc066ab067412525","production_setup.py":"7caf73bbeea7260ef494a2406cc78d313ab10a613cba19fa0d58fc491bc75fcd","provider_readback.py":"d576768208985b3544f146597d181d796f2a5e2eca5026dae3fa15cadcfe65b2","resource_io.py":"b0ed0223fd11a1a28c25278de539a9b2ed63881b26a8e00e386f25d4d9aa9384","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","retained_author.py":"bfd01c7df44f5f525326dfbda13b5ebc6b854f15787a8b2923de883fe20fdcf9","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489","tls_fault.py":"10e125f9623bc32a420a1d83e6d46fe30aa1ca8ff4da97a3e2422fc0e11ec42d"},"source_recipe_sha256":"b1972d556f28433932a449636755077f7ee485ef90cca412f153bc7f18881368"} \ No newline at end of file +{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"a72c557b69103a52eb477deb8364ded53cd58407b9ba7ab33ccbda74389fec1e","family":"stripe-platform-refund-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"99901e36cb7c4f5882897603c874698d582e859b5d6b08d53cd80975e89aa01c","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","application_probe.py":"5e2dd6a91eb0a2acf2df1079cead5bd67ae5d6743abce6e48201e7326f63daa2","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","controller_socket.py":"10519cc775e963360870eac51c7fcac1ffb988b04d5de89dac1dbf3524ba6531","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"b614b12b0789afb2ce4f4b81618db8d6e2333a8b52ec76fc96fbba1be715ee68","family_harness.py":"0e0a42be6cf75dfb3f674b26cbdfbb4c473edea71083dfaad89ecb40dec039ba","family_operations.py":"37395ed317b91f2c62e7e544587f2508b5a4e9bd565c2363a2aa9ecdf63c80fb","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","installed_submit.mjs":"9d57a91c4a052fbb9103582689ee99a6d087758dcfee00defa4c762b87187468","installed_submit.py":"f9151c2dffa1a02327b0ba05bdeb180654918a2b913195185a6649d010783dc7","journey_session.py":"3c807ce45dcabe3b39d63333872af3746fe9276aacf5eba30bf903b51d80dfef","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"abebdf9f5704f0a19457347798548d98b3ddb3adbd48e91bc58a82faf4afbd08","network_fault.py":"94340720d8601f79ac77b95d1e855be25195c19b67db3103bbf054d82c02472b","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","production_environment.py":"4afa2491624b0dfbc44fba868474415628d18f1493f8e6c772f108eccd1390da","production_journey.py":"179b93aa525ddd73ad1b3e9fcf38eeb540173845025707aed6b9fa9a44e4aad8","production_setup.py":"6ed9488e59514cde495aed9f5efde604c69bf416112759ec24ae36eb79070003","provider_readback.py":"d576768208985b3544f146597d181d796f2a5e2eca5026dae3fa15cadcfe65b2","resource_io.py":"b0ed0223fd11a1a28c25278de539a9b2ed63881b26a8e00e386f25d4d9aa9384","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","retained_author.py":"bfd01c7df44f5f525326dfbda13b5ebc6b854f15787a8b2923de883fe20fdcf9","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489","tls_fault.py":"10e125f9623bc32a420a1d83e6d46fe30aa1ca8ff4da97a3e2422fc0e11ec42d"},"source_recipe_sha256":"b1972d556f28433932a449636755077f7ee485ef90cca412f153bc7f18881368"} \ No newline at end of file diff --git a/qualification/reference/application_probe.py b/qualification/reference/application_probe.py new file mode 100644 index 000000000..cd07f5f3b --- /dev/null +++ b/qualification/reference/application_probe.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python3 +"""Actual unprivileged file/egress refusals; no credential or provider request.""" + +import errno +import ipaddress +import os +from pathlib import Path +import socket +import sys + +from common import canonical, require +from resource_io import finish +from production_setup import APPLICATION_UID + + +def probe(kind, values): + require(os.getuid() == APPLICATION_UID and kind in ['files', 'egress'] + and 1 <= len(values) <= 8 + and set(os.environ) <= {'PATH', 'LC_CTYPE', 'PYTHONNOUSERSITE'}, + 'qualification.application.probe-input') + for value in values: + if kind == 'files': + require(Path(value).is_absolute(), 'qualification.application.probe-input') + try: + fd = os.open(value, os.O_RDONLY | os.O_NOFOLLOW) + except OSError as error: + require(error.errno in [errno.EACCES, errno.EPERM], 'qualification.application.file-refusal-unmeasured') + else: + os.close(fd) + require(False, 'qualification.application.private-file-accessible') + else: + address = ipaddress.ip_address(value) + require(address.is_global, 'qualification.application.probe-input') + family = socket.AF_INET if address.version == 4 else socket.AF_INET6 + with socket.socket(family, socket.SOCK_STREAM) as connection: + connection.settimeout(3) + try: + connection.connect((str(address), 443)) + except OSError as error: + require(error.errno in [errno.EACCES, errno.EPERM, errno.ECONNREFUSED, + errno.ENETUNREACH, errno.EHOSTUNREACH], 'qualification.application.egress-refusal-unmeasured') + else: + require(False, 'qualification.application.provider-reachable') + return {'schema': 'auths.qualification-application-probe/1', 'kind': kind, + 'attempted': len(values), 'refused': len(values), 'provider_requests': 0} + + +if __name__ == '__main__': + def main(): + require(len(sys.argv) >= 3, 'qualification.application.probe-input') + sys.stdout.buffer.write(canonical(probe(sys.argv[1], sys.argv[2:]))) + finish(main) diff --git a/qualification/reference/family_operations.py b/qualification/reference/family_operations.py index 46bf32ea2..066e6f29f 100644 --- a/qualification/reference/family_operations.py +++ b/qualification/reference/family_operations.py @@ -7,6 +7,8 @@ from pathlib import Path from concurrent.futures import ThreadPoolExecutor +import ipaddress +import socket import time import airtable_record @@ -15,7 +17,7 @@ from expand import child, decode, read from native_observation import Effects from network_fault import NativeWitness, ResponseFault -from production_setup import GATEWAY_UID +from production_setup import GATEWAY_UID, private_file from tls_fault import Witness import measure from packet_plan import public_pool @@ -374,6 +376,31 @@ def inspect_consumer(self, language, probe): 'credential_leases': counts['credential_lease_calls'], 'provider_entries': counts['write_transport_entries'], 'confirmed_by_read_back': 0}) + def application_boundary(self, identifier): + require(self.consumer_python is not None and self.consumer_kit is not None, + 'qualification.operations.installed-python-not-configured') + if identifier == 'isolation': + # Root first verifies these actual private files exist with the + # native owner/mode. ENOENT cannot masquerade as denied access. + values = [private_file(path, GATEWAY_UID) for path in [ + self.deployment.operator_token, self.deployment.runtime_token, + self.deployment.state(0) / 'installation.json']] + kind, code = 'files', 'application-secret-access-refused' + else: + require(identifier == 'direct-provider', 'qualification.operations.step') + origin = 'api.stripe.com' if self.reference is stripe_platform else 'api.airtable.com' + addresses = {item[4][0] for item in socket.getaddrinfo(origin, 443, socket.AF_UNSPEC, socket.SOCK_STREAM)} + require(1 <= len(addresses) <= 32 and all(ipaddress.ip_address(value).is_global for value in addresses), + 'qualification.operations.provider-address') + values = [address for version in [4, 6] for address in + sorted(value for value in addresses if ipaddress.ip_address(value).version == version)[:2]] + require(any(ipaddress.ip_address(value).version == 4 for value in values), + 'qualification.operations.provider-address') + kind, code = 'egress', 'direct-provider-access-refused' + before = self.deployment.witness(0) + self.deployment.application_probe(self.consumer_python, self.consumer_kit, kind, values) + return self.completed_probe(code, before, self.deployment.witness(0)) + def step(self, case, index, operation): require(type(case) is str and type(index) is int and type(operation) is str, 'qualification.operations.step') @@ -443,6 +470,9 @@ def step(self, case, index, operation): elif identifier == 'doctor': require(phase == 'live' and index == 0 and operation == 'probe', 'qualification.operations.step') result = self.doctor() + elif identifier in ['isolation', 'direct-provider']: + require(index == 0 and operation == 'probe', 'qualification.operations.step') + result = self.application_boundary(identifier) elif identifier == 'installed-typescript': require(index == 0 and operation == 'installed-consumer', 'qualification.operations.step') result = self.typescript_consumer(phase) diff --git a/qualification/reference/generate_families.py b/qualification/reference/generate_families.py index b594b5828..bfc96b59a 100644 --- a/qualification/reference/generate_families.py +++ b/qualification/reference/generate_families.py @@ -19,7 +19,7 @@ SOURCES_TO_PIN = ['family_corpus.py', 'family_harness.py', 'family_operations.py', 'packet_plan.py', 'author_packets.py', 'author_socket.py', 'retained_author.py', 'author_operator.py', 'production_setup.py', 'network_fault.py', 'production_environment.py', 'production_journey.py', 'journey_session.py', - 'controller_socket.py', 'installed_submit.py', 'installed_submit.mjs', 'common.py', 'fresh_evidence.py', + 'controller_socket.py', 'application_probe.py', 'installed_submit.py', 'installed_submit.mjs', 'common.py', 'fresh_evidence.py', 'native_observation.py', 'measure.py', 'provider_readback.py', 'resource_io.py', 'resource_summary.py', 'expand.py', 'stripe_platform.py', 'airtable_record.py', 'stripe_resources.py', 'airtable_resources.py'] diff --git a/qualification/reference/production_journey.py b/qualification/reference/production_journey.py index 8d3831f58..52812eaf7 100644 --- a/qualification/reference/production_journey.py +++ b/qualification/reference/production_journey.py @@ -151,7 +151,7 @@ def stage(self, phase): def prepare(self): self.check_source() - for name in ['author_socket.py', 'author_packets.py', 'author_operator.py', 'installed_submit.py']: + for name in ['author_socket.py', 'author_packets.py', 'author_operator.py', 'installed_submit.py', 'application_probe.py']: require(read(self.kit / name, 2 * 1024 * 1024) == read(ROOT / 'qualification/reference' / name, 2 * 1024 * 1024), 'qualification.journey.consumer-source') require(read(self.script, 2 * 1024 * 1024) == read(ROOT / 'qualification/reference/installed_submit.mjs', 2 * 1024 * 1024), diff --git a/qualification/reference/production_setup.py b/qualification/reference/production_setup.py index 1e41e0c17..03f3833b4 100644 --- a/qualification/reference/production_setup.py +++ b/qualification/reference/production_setup.py @@ -274,6 +274,22 @@ def inspect_consumer(self, executable, script, language): env={'PATH': '/usr/bin:/bin', **({'PYTHONNOUSERSITE': '1'} if language == 'python' else {})}) return native_output(result, self.canaries) + def application_probe(self, python, kit, kind, values): + require(kind in ['files', 'egress'] and type(values) is list and 1 <= len(values) <= 8, + 'qualification.production.application-probe') + result = subprocess.run([str(python), '-B', str(Path(kit) / 'application_probe.py'), kind, *map(str, values)], + stdin=subprocess.DEVNULL, capture_output=True, timeout=30, cwd='/', + user=APPLICATION_UID, group=GATEWAY_UID, extra_groups=[], + env={'PATH': '/usr/bin:/bin', 'PYTHONNOUSERSITE': '1'}) + value = native_output(result, self.canaries) + closed(value, ['schema', 'kind', 'attempted', 'refused', 'provider_requests']) + require(value['schema'] == 'auths.qualification-application-probe/1' and value['kind'] == kind + and type(value['attempted']) is int and type(value['refused']) is int + and type(value['provider_requests']) is int + and value['attempted'] == value['refused'] == len(values) and value['provider_requests'] == 0, + 'qualification.production.application-probe') + return value + def register_commissioning(self, source): require(self.permit is None, 'qualification.production.permit-already-registered') names = ['commissioning-permit.json', 'signer-certificate.json', 'revocation-list.json'] diff --git a/qualification/reference/tests/test_application_probe.py b/qualification/reference/tests/test_application_probe.py new file mode 100644 index 000000000..6e07c0560 --- /dev/null +++ b/qualification/reference/tests/test_application_probe.py @@ -0,0 +1,61 @@ +"""Actual file-open and bounded socket refusals, without provider traffic.""" + +import errno +import os +from pathlib import Path +import sys +import tempfile +import unittest +from unittest.mock import MagicMock, patch + +sys.path.insert(0, str(Path(__file__).resolve().parents[1])) +import application_probe as application +from common import Refusal + + +class Application(unittest.TestCase): + def test_readable_missing_or_non_permission_errors_cannot_be_reported_as_isolation(self): + with tempfile.TemporaryDirectory() as directory, \ + patch.object(application.os, 'getuid', return_value=application.APPLICATION_UID), \ + patch.dict(os.environ, {'PATH': '/usr/bin:/bin'}, clear=True): + path = Path(directory) / 'synthetic-only-private-file' + path.write_bytes(b'synthetic-only-not-a-secret') + with self.assertRaisesRegex(Refusal, 'private-file-accessible'): + application.probe('files', [str(path)]) + path.unlink() + with self.assertRaisesRegex(Refusal, 'file-refusal-unmeasured'): + application.probe('files', [str(path)]) + with patch.object(application.os, 'open', side_effect=OSError(errno.EACCES, 'synthetic-only')): + report = application.probe('files', [str(path)]) + self.assertEqual(report['attempted'], report['refused']) + self.assertEqual(report['provider_requests'], 0) + + def test_successful_or_unmeasured_connection_cannot_be_reported_as_egress_refusal(self): + connection = MagicMock() + factory = MagicMock() + factory.__enter__.return_value = connection + with patch.object(application.os, 'getuid', return_value=application.APPLICATION_UID), \ + patch.dict(os.environ, {'PATH': '/usr/bin:/bin'}, clear=True), \ + patch.object(application.socket, 'socket', return_value=factory): + with self.assertRaisesRegex(Refusal, 'provider-reachable'): + application.probe('egress', ['8.8.8.8']) + connection.connect.side_effect = TimeoutError('synthetic-only') + with self.assertRaisesRegex(Refusal, 'egress-refusal-unmeasured'): + application.probe('egress', ['8.8.8.8']) + connection.connect.side_effect = PermissionError(errno.EACCES, 'synthetic-only') + report = application.probe('egress', ['8.8.8.8', '2606:4700:4700::1111']) + self.assertEqual(report['attempted'], 2) + self.assertEqual(report['refused'], 2) + self.assertEqual(report['provider_requests'], 0) + with self.assertRaises(Refusal): application.probe('egress', ['127.0.0.1']) + + def test_an_ambient_provider_credential_refuses_before_the_probe(self): + with patch.object(application.os, 'getuid', return_value=application.APPLICATION_UID), \ + patch.dict(os.environ, {'AUTHS_QUALIFICATION_PROVIDER_CREDENTIAL': 'synthetic-only'}, clear=True), \ + patch.object(application.os, 'open') as opened: + with self.assertRaises(Refusal): application.probe('files', ['/unreviewed']) + opened.assert_not_called() + + +if __name__ == '__main__': + unittest.main() From 69a9c78e5361fffcd69d2ebc78ea1d62afe825e9 Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 18:04:46 +0100 Subject: [PATCH 096/108] Exercise remaining budget capacity and measured provider capabilities --- .../airtable-record-update-v1/contract.json | 2 +- .../corpus-manifest.json | 2 +- .../stripe-platform-refund-v1/contract.json | 2 +- .../corpus-manifest.json | 2 +- qualification/reference/README.md | 19 +++ qualification/reference/family_operations.py | 149 +++++++++++++++++- qualification/reference/native_observation.py | 30 ++++ .../reference/tests/test_capability_probes.py | 90 +++++++++++ .../tests/test_native_observation.py | 41 +++++ 9 files changed, 331 insertions(+), 6 deletions(-) create mode 100644 qualification/reference/tests/test_capability_probes.py diff --git a/qualification/families/airtable-record-update-v1/contract.json b/qualification/families/airtable-record-update-v1/contract.json index 0ec3c2351..d1ffb43e5 100644 --- a/qualification/families/airtable-record-update-v1/contract.json +++ b/qualification/families/airtable-record-update-v1/contract.json @@ -1 +1 @@ -{"api_release":"web-api-v0-reviewed-2026-10-07","corpus_manifest_sha256":"6e569302b75f9f9d48207e603012050305f3bc65cf235ecfd092882ee967a6ac","declarations":{"idempotency_sha256":"74234e98afe7498fb5daf1f36ac2d78acc339464f950703b8c019892f982b90b","observation_sha256":"9dd79dd204fa13a2df3c667d106c66c0526d174a2c018631e2b2f6b897eaf311","recovery_sha256":"7081a92b4cd2d13dab5e7c30e640675a252b62bca20d340e14d62d9c8c048eca","retention_sha256":"4a4b5048c97b16e041af55b032c0b8ac20f5142c4bbcbf31b31c6674770a70d0"},"environment_class":"disposable-live-resources","manual_assumptions":["Airtable supplies no idempotency key for this PATCH; durable gateway admission prevents a second entry.","Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only a fresh GET with the exact replacement and echo can reconcile a lost response.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths.","The reviewed fixed Airtable base and table contain only owner-authorized disposable qualification records."],"oracle_version":"auths-reviewed-reference-v2","provider":"airtable","schema":"auths.provider-contract/1"} \ No newline at end of file +{"api_release":"web-api-v0-reviewed-2026-10-07","corpus_manifest_sha256":"e7ba4d91426ade1fe5107170b89b64bc735bf2b3d164d3d65975da8012cefa2c","declarations":{"idempotency_sha256":"74234e98afe7498fb5daf1f36ac2d78acc339464f950703b8c019892f982b90b","observation_sha256":"9dd79dd204fa13a2df3c667d106c66c0526d174a2c018631e2b2f6b897eaf311","recovery_sha256":"7081a92b4cd2d13dab5e7c30e640675a252b62bca20d340e14d62d9c8c048eca","retention_sha256":"4a4b5048c97b16e041af55b032c0b8ac20f5142c4bbcbf31b31c6674770a70d0"},"environment_class":"disposable-live-resources","manual_assumptions":["Airtable supplies no idempotency key for this PATCH; durable gateway admission prevents a second entry.","Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only a fresh GET with the exact replacement and echo can reconcile a lost response.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths.","The reviewed fixed Airtable base and table contain only owner-authorized disposable qualification records."],"oracle_version":"auths-reviewed-reference-v2","provider":"airtable","schema":"auths.provider-contract/1"} \ No newline at end of file diff --git a/qualification/families/airtable-record-update-v1/corpus-manifest.json b/qualification/families/airtable-record-update-v1/corpus-manifest.json index 627fba2cc..8879e35eb 100644 --- a/qualification/families/airtable-record-update-v1/corpus-manifest.json +++ b/qualification/families/airtable-record-update-v1/corpus-manifest.json @@ -1 +1 @@ -{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"32241d9b4811a55abcdd224ef567df3857dbec34d761ef7a35d1044cdfa52d9f","family":"airtable-record-update-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"af7f984509ab11a3676cacc85eda2fa638c25bf91f7bfedf3ff3c119e47f3c41","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","application_probe.py":"5e2dd6a91eb0a2acf2df1079cead5bd67ae5d6743abce6e48201e7326f63daa2","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","controller_socket.py":"10519cc775e963360870eac51c7fcac1ffb988b04d5de89dac1dbf3524ba6531","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"b614b12b0789afb2ce4f4b81618db8d6e2333a8b52ec76fc96fbba1be715ee68","family_harness.py":"0e0a42be6cf75dfb3f674b26cbdfbb4c473edea71083dfaad89ecb40dec039ba","family_operations.py":"37395ed317b91f2c62e7e544587f2508b5a4e9bd565c2363a2aa9ecdf63c80fb","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","installed_submit.mjs":"9d57a91c4a052fbb9103582689ee99a6d087758dcfee00defa4c762b87187468","installed_submit.py":"f9151c2dffa1a02327b0ba05bdeb180654918a2b913195185a6649d010783dc7","journey_session.py":"3c807ce45dcabe3b39d63333872af3746fe9276aacf5eba30bf903b51d80dfef","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"abebdf9f5704f0a19457347798548d98b3ddb3adbd48e91bc58a82faf4afbd08","network_fault.py":"94340720d8601f79ac77b95d1e855be25195c19b67db3103bbf054d82c02472b","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","production_environment.py":"4afa2491624b0dfbc44fba868474415628d18f1493f8e6c772f108eccd1390da","production_journey.py":"179b93aa525ddd73ad1b3e9fcf38eeb540173845025707aed6b9fa9a44e4aad8","production_setup.py":"6ed9488e59514cde495aed9f5efde604c69bf416112759ec24ae36eb79070003","provider_readback.py":"d576768208985b3544f146597d181d796f2a5e2eca5026dae3fa15cadcfe65b2","resource_io.py":"b0ed0223fd11a1a28c25278de539a9b2ed63881b26a8e00e386f25d4d9aa9384","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","retained_author.py":"bfd01c7df44f5f525326dfbda13b5ebc6b854f15787a8b2923de883fe20fdcf9","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489","tls_fault.py":"10e125f9623bc32a420a1d83e6d46fe30aa1ca8ff4da97a3e2422fc0e11ec42d"},"source_recipe_sha256":"c0f21ff1d3c8e344fee20a9a0c25bb14a264417ed53418ad536789a6096fb16e"} \ No newline at end of file +{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"32241d9b4811a55abcdd224ef567df3857dbec34d761ef7a35d1044cdfa52d9f","family":"airtable-record-update-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"af7f984509ab11a3676cacc85eda2fa638c25bf91f7bfedf3ff3c119e47f3c41","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","application_probe.py":"5e2dd6a91eb0a2acf2df1079cead5bd67ae5d6743abce6e48201e7326f63daa2","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","controller_socket.py":"10519cc775e963360870eac51c7fcac1ffb988b04d5de89dac1dbf3524ba6531","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"b614b12b0789afb2ce4f4b81618db8d6e2333a8b52ec76fc96fbba1be715ee68","family_harness.py":"0e0a42be6cf75dfb3f674b26cbdfbb4c473edea71083dfaad89ecb40dec039ba","family_operations.py":"8ab354fdf5f2eaab9c061ab967935c76b861a388541bc36fbcf9da5a9a630012","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","installed_submit.mjs":"9d57a91c4a052fbb9103582689ee99a6d087758dcfee00defa4c762b87187468","installed_submit.py":"f9151c2dffa1a02327b0ba05bdeb180654918a2b913195185a6649d010783dc7","journey_session.py":"3c807ce45dcabe3b39d63333872af3746fe9276aacf5eba30bf903b51d80dfef","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"580fa1db01a6fa7691d618f123f9117ce39b25e6478460ceac46c1e650d6b454","network_fault.py":"94340720d8601f79ac77b95d1e855be25195c19b67db3103bbf054d82c02472b","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","production_environment.py":"4afa2491624b0dfbc44fba868474415628d18f1493f8e6c772f108eccd1390da","production_journey.py":"179b93aa525ddd73ad1b3e9fcf38eeb540173845025707aed6b9fa9a44e4aad8","production_setup.py":"6ed9488e59514cde495aed9f5efde604c69bf416112759ec24ae36eb79070003","provider_readback.py":"d576768208985b3544f146597d181d796f2a5e2eca5026dae3fa15cadcfe65b2","resource_io.py":"b0ed0223fd11a1a28c25278de539a9b2ed63881b26a8e00e386f25d4d9aa9384","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","retained_author.py":"bfd01c7df44f5f525326dfbda13b5ebc6b854f15787a8b2923de883fe20fdcf9","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489","tls_fault.py":"10e125f9623bc32a420a1d83e6d46fe30aa1ca8ff4da97a3e2422fc0e11ec42d"},"source_recipe_sha256":"c0f21ff1d3c8e344fee20a9a0c25bb14a264417ed53418ad536789a6096fb16e"} \ No newline at end of file diff --git a/qualification/families/stripe-platform-refund-v1/contract.json b/qualification/families/stripe-platform-refund-v1/contract.json index 03eb8d940..8dafa8986 100644 --- a/qualification/families/stripe-platform-refund-v1/contract.json +++ b/qualification/families/stripe-platform-refund-v1/contract.json @@ -1 +1 @@ -{"api_release":"2025-03-31.basil","corpus_manifest_sha256":"f452c395a4eabfe96bd91286f0b179b5342f7c1287b582cf9990add72eccb683","declarations":{"idempotency_sha256":"425a0dca2f279765debfc847c4a01bff60fea5be68dd9d761ae6bb60ce0b8a7b","observation_sha256":"d0ce5a34d987821c69c0a839d9ed66805c625f8324dd42031fcccf0752a8821e","recovery_sha256":"bf2303abce165c175360ac975586431bbc4cf03167489ea317a27de2f0b04abb","retention_sha256":"846c2164e26d1144d9aa146034b4f7ea4dc305136a59ffd94f999d19f2c360ee"},"environment_class":"provider-test-mode","manual_assumptions":["Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","Stripe idempotency is tested only inside the declared 86400-second retention interval.","Stripe test mode and the installed platform are checked by the declared guard on each lease.","The 50-percent payment basis is a read, not an atomic provider balance reservation.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths."],"oracle_version":"auths-reviewed-reference-v2","provider":"stripe","schema":"auths.provider-contract/1"} \ No newline at end of file +{"api_release":"2025-03-31.basil","corpus_manifest_sha256":"59a93f3f7077e2b8d7d11c187ffeedba030e5e58e81c20e085266f0b9a653961","declarations":{"idempotency_sha256":"425a0dca2f279765debfc847c4a01bff60fea5be68dd9d761ae6bb60ce0b8a7b","observation_sha256":"d0ce5a34d987821c69c0a839d9ed66805c625f8324dd42031fcccf0752a8821e","recovery_sha256":"bf2303abce165c175360ac975586431bbc4cf03167489ea317a27de2f0b04abb","retention_sha256":"846c2164e26d1144d9aa146034b4f7ea4dc305136a59ffd94f999d19f2c360ee"},"environment_class":"provider-test-mode","manual_assumptions":["Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","Stripe idempotency is tested only inside the declared 86400-second retention interval.","Stripe test mode and the installed platform are checked by the declared guard on each lease.","The 50-percent payment basis is a read, not an atomic provider balance reservation.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths."],"oracle_version":"auths-reviewed-reference-v2","provider":"stripe","schema":"auths.provider-contract/1"} \ No newline at end of file diff --git a/qualification/families/stripe-platform-refund-v1/corpus-manifest.json b/qualification/families/stripe-platform-refund-v1/corpus-manifest.json index 0ef3ab084..8ca749c7e 100644 --- a/qualification/families/stripe-platform-refund-v1/corpus-manifest.json +++ b/qualification/families/stripe-platform-refund-v1/corpus-manifest.json @@ -1 +1 @@ -{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"a72c557b69103a52eb477deb8364ded53cd58407b9ba7ab33ccbda74389fec1e","family":"stripe-platform-refund-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"99901e36cb7c4f5882897603c874698d582e859b5d6b08d53cd80975e89aa01c","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","application_probe.py":"5e2dd6a91eb0a2acf2df1079cead5bd67ae5d6743abce6e48201e7326f63daa2","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","controller_socket.py":"10519cc775e963360870eac51c7fcac1ffb988b04d5de89dac1dbf3524ba6531","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"b614b12b0789afb2ce4f4b81618db8d6e2333a8b52ec76fc96fbba1be715ee68","family_harness.py":"0e0a42be6cf75dfb3f674b26cbdfbb4c473edea71083dfaad89ecb40dec039ba","family_operations.py":"37395ed317b91f2c62e7e544587f2508b5a4e9bd565c2363a2aa9ecdf63c80fb","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","installed_submit.mjs":"9d57a91c4a052fbb9103582689ee99a6d087758dcfee00defa4c762b87187468","installed_submit.py":"f9151c2dffa1a02327b0ba05bdeb180654918a2b913195185a6649d010783dc7","journey_session.py":"3c807ce45dcabe3b39d63333872af3746fe9276aacf5eba30bf903b51d80dfef","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"abebdf9f5704f0a19457347798548d98b3ddb3adbd48e91bc58a82faf4afbd08","network_fault.py":"94340720d8601f79ac77b95d1e855be25195c19b67db3103bbf054d82c02472b","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","production_environment.py":"4afa2491624b0dfbc44fba868474415628d18f1493f8e6c772f108eccd1390da","production_journey.py":"179b93aa525ddd73ad1b3e9fcf38eeb540173845025707aed6b9fa9a44e4aad8","production_setup.py":"6ed9488e59514cde495aed9f5efde604c69bf416112759ec24ae36eb79070003","provider_readback.py":"d576768208985b3544f146597d181d796f2a5e2eca5026dae3fa15cadcfe65b2","resource_io.py":"b0ed0223fd11a1a28c25278de539a9b2ed63881b26a8e00e386f25d4d9aa9384","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","retained_author.py":"bfd01c7df44f5f525326dfbda13b5ebc6b854f15787a8b2923de883fe20fdcf9","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489","tls_fault.py":"10e125f9623bc32a420a1d83e6d46fe30aa1ca8ff4da97a3e2422fc0e11ec42d"},"source_recipe_sha256":"b1972d556f28433932a449636755077f7ee485ef90cca412f153bc7f18881368"} \ No newline at end of file +{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"a72c557b69103a52eb477deb8364ded53cd58407b9ba7ab33ccbda74389fec1e","family":"stripe-platform-refund-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"99901e36cb7c4f5882897603c874698d582e859b5d6b08d53cd80975e89aa01c","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","application_probe.py":"5e2dd6a91eb0a2acf2df1079cead5bd67ae5d6743abce6e48201e7326f63daa2","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","controller_socket.py":"10519cc775e963360870eac51c7fcac1ffb988b04d5de89dac1dbf3524ba6531","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"b614b12b0789afb2ce4f4b81618db8d6e2333a8b52ec76fc96fbba1be715ee68","family_harness.py":"0e0a42be6cf75dfb3f674b26cbdfbb4c473edea71083dfaad89ecb40dec039ba","family_operations.py":"8ab354fdf5f2eaab9c061ab967935c76b861a388541bc36fbcf9da5a9a630012","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","installed_submit.mjs":"9d57a91c4a052fbb9103582689ee99a6d087758dcfee00defa4c762b87187468","installed_submit.py":"f9151c2dffa1a02327b0ba05bdeb180654918a2b913195185a6649d010783dc7","journey_session.py":"3c807ce45dcabe3b39d63333872af3746fe9276aacf5eba30bf903b51d80dfef","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"580fa1db01a6fa7691d618f123f9117ce39b25e6478460ceac46c1e650d6b454","network_fault.py":"94340720d8601f79ac77b95d1e855be25195c19b67db3103bbf054d82c02472b","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","production_environment.py":"4afa2491624b0dfbc44fba868474415628d18f1493f8e6c772f108eccd1390da","production_journey.py":"179b93aa525ddd73ad1b3e9fcf38eeb540173845025707aed6b9fa9a44e4aad8","production_setup.py":"6ed9488e59514cde495aed9f5efde604c69bf416112759ec24ae36eb79070003","provider_readback.py":"d576768208985b3544f146597d181d796f2a5e2eca5026dae3fa15cadcfe65b2","resource_io.py":"b0ed0223fd11a1a28c25278de539a9b2ed63881b26a8e00e386f25d4d9aa9384","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","retained_author.py":"bfd01c7df44f5f525326dfbda13b5ebc6b854f15787a8b2923de883fe20fdcf9","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489","tls_fault.py":"10e125f9623bc32a420a1d83e6d46fe30aa1ca8ff4da97a3e2422fc0e11ec42d"},"source_recipe_sha256":"b1972d556f28433932a449636755077f7ee485ef90cca412f153bc7f18881368"} \ No newline at end of file diff --git a/qualification/reference/README.md b/qualification/reference/README.md index 84c240240..c906c305f 100644 --- a/qualification/reference/README.md +++ b/qualification/reference/README.md @@ -308,6 +308,25 @@ Application and author UIDs can be denied both IPv4 and IPv6 egress. These mechanisms do not establish protected case completion until the full journey executes them and the native runner verifies its measured observations. +The application isolation handlers now attempt actual file opens and bounded +connections from the installed consumer's application UID. Missing files, +timeouts, unexpected socket errors, or an accessible secret cannot become a +passing isolation report. Count/sum races hold the actual owner's encrypted +response while a different reviewed operation competes for the last capacity, +then verify its persisted refusal after completion. Guard refusals retain a +request digest only after original-action reauthentication, the independent +Stripe policy decision, and the exact actual post-lease native refusal. + +Declared capability checks require a previously confirmed native effect and +independent fresh read-back. Stripe also checks actual account/test-mode and +denied-read scope. Its authorized fixture reference retries exactly that +already observed run-owned refund with the same runtime key/body/idempotency +key, and requires the same refund plus a unique fresh matching echo afterward. +The separate fixture API entry is retained explicitly in the public probe +report; it is outside the native gateway counter scope and never masquerades +as a native entry or a newly applied effect. Airtable confirms its exact field +replacement and echo without a duplicate write. + Interrupted-write handlers now lose a response only after the independent provider reference observes the exact value and echo. Crash handlers kill the actual commissioning owner or live gateway and require a native support bundle diff --git a/qualification/reference/family_operations.py b/qualification/reference/family_operations.py index 066e6f29f..8c3566840 100644 --- a/qualification/reference/family_operations.py +++ b/qualification/reference/family_operations.py @@ -15,13 +15,15 @@ import stripe_platform from common import canonical, closed, Refusal, require, sha256 from expand import child, decode, read -from native_observation import Effects +from native_observation import Effects, result as native_result from network_fault import NativeWitness, ResponseFault from production_setup import GATEWAY_UID, private_file from tls_fault import Witness import measure from packet_plan import public_pool from resource_io import write_bytes +import resource_io +import fresh_evidence POSITIVES = {'fresh-replay': 0, 'proof-replay': 1, 'two-host-race': 2, 'restart': 3, 'crash': 4, 'ambiguous': 5, 'response-loss': 6, @@ -51,6 +53,7 @@ def __init__(self, deployment, author, oracle, resources, reviewed): self.interrupted = set() self.consumer_node = None self.consumer_script = None + self.budget_refusals = set() def configure_consumers(self, python, kit): self.consumer_python, self.consumer_kit = Path(python).absolute(), Path(kit).absolute() @@ -262,6 +265,72 @@ def resume_host(self, phase, label, *, crash): return self.completed_probe('gateway-' + ('crash' if crash else 'restart') + '-completed', resumed, self.deployment.witness(0)) + def budget_race(self, phase, kind): + require(self.reference is stripe_platform and kind in ['count', 'sum'], 'qualification.operations.step') + label = phase + '-budget-' + kind + owner_handoff, packet = self.packet(label) + other_handoff, other_packet = self.packet(label + '-over') + require(packet['arguments']['operation_id'] != other_packet['arguments']['operation_id'] + and packet['arguments']['payment_intent'] != other_packet['arguments']['payment_intent'], + 'qualification.operations.budget-binding') + code = 'gateway.policy.window-exhausted' if kind == 'count' else 'gateway.policy.sum-exhausted' + children = [self.deployment.commissioning_child(handoff, current, host=host) + for host, handoff, current in [(0, owner_handoff, packet), (1, other_handoff, other_packet)]] \ + if phase == 'commissioning' else [] + witness = Witness(children[0].witness, GATEWAY_UID) if children else NativeWitness(self.deployment, 0, 0) + try: + with ResponseFault(self.family, witness) as fault, ThreadPoolExecutor(max_workers=1) as pool: + if children: + children[0].start() + owner = None + else: + owner = pool.submit(self.deployment.application_submit, owner_handoff, packet, 0) + fault.held() + self.wait_for_effect(label) + if children: + children[1].start() + competitor = children[1].finish() + else: + before = self.deployment.witness(1) + value = self.deployment.application_submit(other_handoff, other_packet, 1) + competitor = {'result': value, 'before': before, 'after': self.deployment.witness(1)} + require(native_result(competitor['result']) == ('refused', code, None), + 'qualification.operations.budget-refusal') + fault.decide('release') + if children: + first = children[0].finish() + require(witness.entered() and first['before'] == witness.before and first['after'] == witness.last, + 'qualification.operations.witness-binding') + else: + first = {'result': owner.result(timeout=90), 'before': witness.before, + 'after': self.deployment.witness(0)} + observed, fresh = self.effects.project_budget_race(self.tuple, self.reviewed[label], self.resources, + first['result'], competitor['result'], + [(first['before'], first['after']), (competitor['before'], competitor['after'])], + self.oracle.fresh(self.reviewed[label], self.tuple['compiled_recipe_sha256']), code) + self.budget_refusals.add((phase, kind)) + return self.observation(observed, fresh) + finally: + for child in children: + child.abort() + + def budget_probe(self, phase, kind): + require((phase, kind) in self.budget_refusals, 'qualification.operations.budget-not-raced') + handoff, packet = self.packet(phase + '-budget-' + kind + '-over') + code = 'gateway.policy.window-exhausted' if kind == 'count' else 'gateway.policy.sum-exhausted' + before = self.deployment.witness(1) + if phase == 'commissioning': + execution = self.deployment.commissioning_submit(handoff, packet, host=1) + value = execution['result'] + measured_before, measured_after = execution['before'], execution['after'] + else: + value = self.deployment.application_submit(handoff, packet, host=1) + measured_before, measured_after = before, self.deployment.witness(1) + require(native_result(value) == ('refused', code, None) + and all(count == 0 for count in measure.delta(measured_before, measured_after).values()), + 'qualification.operations.budget-refusal') + return self.completed_probe('budget-' + kind + '-refusal-confirmed', before, self.deployment.witness(1)) + def doctor(self): require(self.phase == 'live', 'qualification.operations.phase') for host in [0, 1]: @@ -401,6 +470,71 @@ def application_boundary(self, identifier): self.deployment.application_probe(self.consumer_python, self.consumer_kit, kind, values) return self.completed_probe(code, before, self.deployment.witness(0)) + def guard(self, phase, identifier): + label = phase + '-' + identifier + handoff, packet = self.packet(label) + if phase == 'commissioning': + execution = self.deployment.commissioning_submit(handoff, packet) + value, before, after = execution['result'], execution['before'], execution['after'] + else: + before = self.deployment.witness(0) + value = self.deployment.application_submit(handoff, packet) + after = self.deployment.witness(0) + observed, fresh = self.effects.project_guard_refusal(self.tuple, self.reviewed[label], self.resources, + value, before, after) + return self.observation(observed, fresh) + + def capabilities(self, phase): + label = phase + '-10' + reviewed = self.reviewed[label] + effect = (self.family, self.resources['protected_run'], reviewed['arguments']['operator_namespace'], + reviewed['arguments']['operation_id']) + require(effect in self.effects.entries and self.effects.entries[effect]['confirmed'] is True, + 'qualification.operations.capability-unconfirmed-effect') + before = self.deployment.witness(0) + # A capability probe follows the actual native linked effect. It + # cannot pre-seed matching state that would conceal a failed write. + first = self.oracle.fresh(reviewed, self.tuple['compiled_recipe_sha256']) + measured = {'schema': 'auths.qualification-provider-capability-probes/1', + 'family': self.family, 'protected_run': self.resources['protected_run'], + 'request_sha256': sha256(canonical(reviewed['request'])), + 'fixture_duplicate_api_entries': 0, 'additional_effects': 0, + 'refused_reads': []} + if self.reference is stripe_platform: + require(self.current_credential is not None and self.current_credential.startswith(b'rk_test_'), + 'qualification.operations.runtime-credential') + key = self.current_credential.decode() + headers = {'Stripe-Version': '2025-03-31.basil'} + balance = resource_io.request('https://api.stripe.com', 'GET', '/v1/balance', key, headers=headers) + account = resource_io.request('https://api.stripe.com', 'GET', '/v1/account', key, headers=headers) + require(balance.get('livemode') is False and account.get('id') == self.resources['platform'], + 'qualification.operations.account-guard') + for path in ['/v1/customers', '/v1/payouts']: + status, _private = resource_io.exchange('https://api.stripe.com', 'GET', path, key, headers=headers) + require(status == 403, 'qualification.operations.denied-read-permission') + measured['refused_reads'].append({'path': path, 'status': status}) + # The authorized test reference retries only this already observed + # run-owned request, using the same runtime key and idempotency key. + # This is explicitly a fixture API call, outside the native counter + # scope. It is retained rather than hidden in gateway measurements. + request = stripe_platform.request(reviewed['arguments'], self.resources, + reviewed['action_commitment'], self.tuple['compiled_recipe_sha256']) + require(request == reviewed['request'], 'qualification.operations.request-binding') + duplicate = resource_io.request('https://api.stripe.com', 'POST', '/v1/refunds', key, + request['body'].encode(), {**dict(request['headers']), 'Content-Type': request['content_type']}) + prior = fresh_evidence.decode(first) + require(duplicate.get('id') == prior['id'], 'qualification.operations.idempotency-new-effect') + fresh_evidence.witness(self.family, reviewed['arguments'], self.resources, + reviewed['action_commitment'], self.tuple['compiled_recipe_sha256'], canonical(duplicate)) + measured['fixture_duplicate_api_entries'] = 1 + final = self.oracle.fresh(reviewed, self.tuple['compiled_recipe_sha256']) + require(fresh_evidence.decode(final).get('id') == fresh_evidence.decode(first).get('id'), + 'qualification.operations.capability-effect-changed') + directory = self.deployment.work / 'provider-capability-probes' + directory.mkdir(mode=0o700, exist_ok=True) + write_bytes(directory / (phase + '.json'), canonical(measured), new=True) + return self.completed_probe('provider-capabilities-confirmed', before, self.deployment.witness(0)) + def step(self, case, index, operation): require(type(case) is str and type(index) is int and type(operation) is str, 'qualification.operations.step') @@ -425,9 +559,20 @@ def step(self, case, index, operation): if index == 1: require((case, 0) in self.completed, 'qualification.operations.order') result = self.submit(phase, label) if index == 0 else self.read_back(label) + elif identifier == 'capabilities': + require(index in [0, 1] and operation == ['submit', 'probe'][index], 'qualification.operations.step') + if index == 1: + require((case, 0) in self.completed, 'qualification.operations.order') + result = self.submit(phase, phase + '-10') if index == 0 else self.capabilities(phase) elif identifier == 'two-host-race': require(index == 0 and operation == 'race', 'qualification.operations.step') result = self.race(phase, phase + '-02') + elif identifier in ['budget-count', 'budget-sum']: + require(index in [0, 1] and operation == ['race', 'probe'][index], 'qualification.operations.step') + kind = identifier.removeprefix('budget-') + if index == 1: + require((case, 0) in self.completed, 'qualification.operations.order') + result = self.budget_race(phase, kind) if index == 0 else self.budget_probe(phase, kind) elif identifier in ['restart', 'crash']: require(index in [0, 1, 2] and operation == ['submit', identifier, 'replay'][index], 'qualification.operations.step') @@ -457,7 +602,7 @@ def step(self, case, index, operation): elif identifier in ['guard-ceiling', 'guard-currency']: require(self.reference is stripe_platform and index == 0 and operation == 'probe', 'qualification.operations.step') - result = self.submit(phase, phase + '-' + identifier) + result = self.guard(phase, identifier) elif identifier in ['forged', 'altered']: require(index == 0 and operation == 'probe', 'qualification.operations.step') result = self.hostile(phase, identifier) diff --git a/qualification/reference/native_observation.py b/qualification/reference/native_observation.py index 80f10ada4..000c5b45c 100644 --- a/qualification/reference/native_observation.py +++ b/qualification/reference/native_observation.py @@ -155,6 +155,36 @@ def project_race(self, tuple_value, reviewed, resources, native_results, pairs, status=next(value['status'] for value in native_results if value['outcome'] == 'observed-by-provider')) + def project_budget_race(self, tuple_value, reviewed, resources, owner, competitor, pairs, response, code): + require(code in ['gateway.policy.window-exhausted', 'gateway.policy.sum-exhausted'] + and type(pairs) is list and len(pairs) == 2, + 'qualification.observation.budget-hosts') + winner, loser = result(owner), result(competitor) + refusal = measure.delta(*pairs[1]) + require(winner[2] is not None and loser == ('refused', code, None) + and refusal['credential_lease_calls'] == refusal['write_transport_entries'] == 0, + 'qualification.observation.budget-refusal') + # The authenticated competitor uses a different operation. Preserve + # both real process scopes; no synthetic before/after pair is created. + return self._project(tuple_value, reviewed, resources, winner, measure.aggregate(pairs), response, + status=owner.get('status')) + + def project_guard_refusal(self, tuple_value, reviewed, resources, native, before, after): + require(tuple_value['recipe_family'] == stripe_platform.FAMILY, + 'qualification.observation.guard-family') + actual = result(native) + expected = stripe_platform.entry_policy(reviewed['arguments'], resources) + require(expected in ['gateway.relative-ceiling.above', 'gateway.relative-ceiling.binding-mismatch'] + and actual == ('refused', expected, None), 'qualification.observation.guard-refusal') + facts, fresh = self.project(tuple_value, reviewed, resources, native, before, after) + require(facts['credential_leases'] == 1 and facts['provider_entries'] == 0, + 'qualification.observation.guard-entry') + # This valid original action was independently reauthenticated. The + # actual native guard code identifies a refusal after that same mapped + # request, unlike malformed proof/action refusals, which keep no hash. + facts['verdict']['request_sha256'] = sha256(canonical(reviewed['request'])) + return facts, fresh + def project_interrupted(self, tuple_value, reviewed, resources, trusted_context_sha256, support, before, after): interrupted_state(tuple_value, reviewed, trusted_context_sha256, support) counted = measure.delta(before, after) diff --git a/qualification/reference/tests/test_capability_probes.py b/qualification/reference/tests/test_capability_probes.py new file mode 100644 index 000000000..77ccc5bce --- /dev/null +++ b/qualification/reference/tests/test_capability_probes.py @@ -0,0 +1,90 @@ +"""Provider-reference refusal boundaries using synthetic responses only.""" + +from pathlib import Path +import sys +import tempfile +from types import SimpleNamespace +import unittest +from unittest.mock import patch + +sys.path.insert(0, str(Path(__file__).resolve().parents[1])) +from common import canonical, echo, Refusal +import family_operations as operations +from native_observation import Effects +import stripe_platform as stripe + + +class Capabilities(unittest.TestCase): + def operation(self, root): + value = object.__new__(operations.Operations) + value.family, value.reference = stripe.FAMILY, stripe + value.tuple = {'recipe_family': stripe.FAMILY, 'compiled_recipe_sha256': '1' * 64} + run = 'recipe-qualification/123/1' + value.resources = {'schema': 'auths.stripe-platform-qualification-resources/1', + 'protected_run': run, 'platform': 'acct_SYNTHETIC', 'payments': [ + {'id': 'pi_SYNTHETIC', 'amount_received': 2000, 'currency': 'usd', + 'livemode': False, 'run_metadata': run}]} + arguments = {'operator_namespace': stripe.SERVICE, 'operation_id': 'synthetic-only', + 'recipe_digest': '1' * 64, 'payment_intent': 'pi_SYNTHETIC', 'amount': 500, 'currency': 'usd'} + review = {'schema': 'auths.gateway-submission-review/1', 'actors': ['raw:synthetic-only'], + 'action_commitment': '2' * 64, 'arguments': arguments, + 'request': stripe.request(arguments, value.resources, '2' * 64, '1' * 64)} + value.reviewed = {'commissioning-10': review} + value.effects = Effects() + value.effects.entries[(value.family, run, stripe.SERVICE, arguments['operation_id'])] = {'confirmed': True} + response = {'id': 're_SYNTHETIC', 'object': 'refund', 'livemode': False, + 'payment_intent': 'pi_SYNTHETIC', 'amount': 500, 'currency': 'usd', 'status': 'succeeded', + 'metadata': {'auths_echo': echo(stripe.SERVICE, arguments['operation_id'], '2' * 64)}} + value.oracle = SimpleNamespace(fresh=lambda *_args: canonical(response)) + before = {'schema': 'auths.gateway-execution-witness/1', 'scope': '1' * 32, + 'credential_lease_calls': 0, 'write_transport_entries': 0, 'read_transport_entries': 0} + value.deployment = SimpleNamespace(work=root, witness=lambda *_args: before) + value.current_credential = b'rk_test_SYNTHETIC_ONLY_RUNTIME' + return value, response + + def test_duplicate_probe_records_its_fixture_entry_and_verifies_the_existing_effect(self): + with tempfile.TemporaryDirectory() as directory: + value, response = self.operation(Path(directory)) + calls = [] + def request(origin, method, path, key, body=None, headers=None): + calls.append((method, path, body, headers)) + if path == '/v1/balance': return {'livemode': False} + if path == '/v1/account': return {'id': value.resources['platform']} + self.assertEqual((method, path), ('POST', '/v1/refunds')) + return response + with patch.object(operations.resource_io, 'request', request), \ + patch.object(operations.resource_io, 'exchange', return_value=(403, b'synthetic-only-denial')): + report = value.capabilities('commissioning') + self.assertEqual(report['observed']['provider_entries'], 0, 'this is the actual native counter scope') + self.assertEqual(len([call for call in calls if call[0] == 'POST']), 1) + native = value.reviewed['commissioning-10']['request'] + self.assertEqual(calls[-1][2], native['body'].encode()) + self.assertEqual(calls[-1][3]['Idempotency-Key'], native['idempotency_key']) + import json + retained = json.loads((Path(directory) / 'provider-capability-probes/commissioning.json').read_bytes()) + self.assertEqual(retained['fixture_duplicate_api_entries'], 1) + self.assertEqual(retained['additional_effects'], 0) + + def test_wrong_effect_or_overbroad_key_cannot_complete_the_capability_case(self): + for problem in ['new-refund', 'unexpected-permission', 'unconfirmed-native-effect']: + with tempfile.TemporaryDirectory() as directory: + value, response = self.operation(Path(directory)) + if problem == 'unconfirmed-native-effect': + next(iter(value.effects.entries.values()))['confirmed'] = False + calls = [] + def request(origin, method, path, key, body=None, headers=None): + calls.append(method) + if path == '/v1/balance': return {'livemode': False} + if path == '/v1/account': return {'id': value.resources['platform']} + return dict(response, id='re_CHANGED') + with patch.object(operations.resource_io, 'request', request), \ + patch.object(operations.resource_io, 'exchange', + return_value=(200 if problem == 'unexpected-permission' else 403, b'synthetic-only')), \ + self.assertRaises(Refusal): + value.capabilities('commissioning') + self.assertFalse((Path(directory) / 'provider-capability-probes').exists()) + if problem != 'new-refund': self.assertNotIn('POST', calls) + + +if __name__ == '__main__': + unittest.main() diff --git a/qualification/reference/tests/test_native_observation.py b/qualification/reference/tests/test_native_observation.py index de678465d..64d2170c2 100644 --- a/qualification/reference/tests/test_native_observation.py +++ b/qualification/reference/tests/test_native_observation.py @@ -7,6 +7,7 @@ sys.path.insert(0, str(Path(__file__).resolve().parents[1])) import airtable_record as airtable +import stripe_platform as stripe from common import Refusal, canonical, echo, sha256 from native_observation import Effects, result @@ -159,6 +160,46 @@ def test_race_aggregates_distinct_actual_native_scopes_without_counting_a_second [self.observed, {'outcome': 'unknown'}], [(self.before, self.after), (self.before, self.after)], self.response) + def test_budget_competitor_must_refuse_without_leasing_or_entering_in_a_distinct_scope(self): + second = dict(self.before, scope='2' * 32) + code = 'gateway.policy.sum-exhausted' + refused = {'outcome': 'not-entered', 'code': code} + facts, _ = Effects().project_budget_race(self.tuple, self.review, self.resources, + self.observed, refused, [(self.before, self.after), (second, second)], self.response, code) + self.assertEqual((facts['provider_entries'], facts['confirmed_by_read_back']), (1, 1)) + for other, after in [({'outcome': 'unknown'}, second), + ({'outcome': 'not-entered', 'code': 'gateway.attempt.replay'}, second), + (refused, dict(second, credential_lease_calls=1)), + (refused, dict(second, write_transport_entries=1))]: + with self.assertRaises(Refusal): + Effects().project_budget_race(self.tuple, self.review, self.resources, + self.observed, other, [(self.before, self.after), (second, after)], self.response, code) + with self.assertRaisesRegex(Refusal, 'duplicate-host'): + Effects().project_budget_race(self.tuple, self.review, self.resources, + self.observed, refused, [(self.before, self.after), (self.before, self.before)], self.response, code) + + def test_only_a_reauthenticated_declared_guard_refusal_retains_its_request_digest(self): + resources = {'schema': 'auths.stripe-platform-qualification-resources/1', + 'protected_run': self.run, 'platform': 'acct_SYNTHETIC', 'payments': [ + {'id': 'pi_SYNTHETIC', 'amount_received': 2000, 'currency': 'usd', + 'livemode': False, 'run_metadata': self.run}]} + tuple_value = dict(self.tuple, recipe_family=stripe.FAMILY) + arguments = {'operator_namespace': stripe.SERVICE, 'operation_id': 'synthetic-only', + 'recipe_digest': '1' * 64, 'payment_intent': 'pi_SYNTHETIC', 'amount': 1001, 'currency': 'usd'} + reviewed = dict(self.review, arguments=arguments, + request=stripe.request(arguments, resources, self.review['action_commitment'], '1' * 64)) + native = {'outcome': 'not-entered', 'code': 'gateway.relative-ceiling.above'} + after = dict(self.before, credential_lease_calls=1, read_transport_entries=5) + facts, fresh = Effects().project_guard_refusal(tuple_value, reviewed, resources, native, self.before, after) + self.assertEqual(facts['verdict']['request_sha256'], sha256(canonical(reviewed['request']))) + self.assertEqual(facts['provider_entries'], 0) + self.assertIsNone(fresh) + for changed, counters in [(dict(native, code='gateway.verify.invalid-input'), after), + (native, dict(after, credential_lease_calls=0)), + (native, dict(after, write_transport_entries=1))]: + with self.assertRaises(Refusal): + Effects().project_guard_refusal(tuple_value, reviewed, resources, changed, self.before, counters) + def test_wrong_response_echo_request_scope_and_ambiguous_claims_refuse(self): for problem in ['raw-bytes', 'echo', 'request', 'scope', 'extra-field', 'refused-entry']: ledger, value, review = Effects(), copy.deepcopy(self.observed), copy.deepcopy(self.review) From 8a28f186e7ab5354b6d94114c5fa8ab422123716 Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 18:19:57 +0100 Subject: [PATCH 097/108] Connect retained production qualification to independently reconstructed signing --- .github/workflows/recipe-qualification.yml | 353 ++++++++++++++---- .../tests/protected_run.rs | 57 ++- .../airtable-record-update-v1/contract.json | 2 +- .../corpus-manifest.json | 2 +- .../stripe-platform-refund-v1/contract.json | 2 +- .../corpus-manifest.json | 2 +- qualification/reference/README.md | 14 +- qualification/reference/generate_families.py | 4 +- .../reference/tests/test_release_entry.py | 85 +++++ qualification/run/sign_release.py | 193 ++++++++++ 10 files changed, 619 insertions(+), 95 deletions(-) create mode 100644 qualification/reference/tests/test_release_entry.py create mode 100644 qualification/run/sign_release.py diff --git a/.github/workflows/recipe-qualification.yml b/.github/workflows/recipe-qualification.yml index 9cbac3851..8bd5a9df6 100644 --- a/.github/workflows/recipe-qualification.yml +++ b/.github/workflows/recipe-qualification.yml @@ -161,6 +161,13 @@ jobs: if-no-files-found: error retention-days: 30 + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 + with: + name: qualification-python-${{ github.run_id }}-${{ github.run_attempt }} + path: target/qualification-wheels/*.whl + if-no-files-found: error + retention-days: 30 + typescript-consumer: name: installed TypeScript qualification consumer runs-on: ubuntu-latest @@ -345,91 +352,213 @@ jobs: retention-days: 30 live: - # Disposable provider resources, through the candidate gateway. Each - # family has its own protected environment holding only that family's - # qualification credential, which is not a production credential. - name: live evidence (${{ matrix.family }}) - needs: [families, candidate, offline] + name: retained production operator (${{ matrix.family }}) + needs: [families, candidate, offline, packet-author, typescript-consumer, simulation] if: github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main' runs-on: ubuntu-latest - timeout-minutes: 90 - environment: recipe-qualification-live-${{ matrix.family }} + timeout-minutes: 135 + environment: gateway-custody-live permissions: contents: read + actions: read id-token: write strategy: - fail-fast: true + fail-fast: false matrix: family: ${{ fromJSON(needs.families.outputs.list) }} + env: + FAMILY: ${{ matrix.family }} steps: - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 with: persist-credentials: false - - uses: ./.github/actions/setup-rust-cache + - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 with: - toolchain: 1.97.1 - - name: Build the release tool from this commit - run: cargo build --locked --release -p auths-recipe-qualification-issuance --bin auths-qualification - - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 + python-version: "3.12" + - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 with: - name: offline-${{ matrix.family }} - path: ${{ runner.temp }}/work + node-version: 22.23.1 - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 with: name: qualification-shipping-candidate-${{ github.run_id }}-${{ github.run_attempt }} path: ${{ runner.temp }}/candidate - - name: Run the family's live harness + - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 + with: + name: qualification-python-${{ github.run_id }}-${{ github.run_attempt }} + path: ${{ runner.temp }}/python-package + - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 + with: + name: qualification-typescript-${{ github.run_id }}-${{ github.run_attempt }} + path: ${{ runner.temp }}/typescript-package + - name: Install the exact credential-free consumer packages shell: bash - env: - FAMILY: ${{ matrix.family }} - AUTHS_QUALIFICATION_PROVIDER_CREDENTIAL: ${{ secrets.QUALIFICATION_PROVIDER_CREDENTIAL }} run: | set -euo pipefail + umask 077 + wheels=("${RUNNER_TEMP}"/python-package/*.whl) + test "${#wheels[@]}" -eq 1 + python -m venv "${RUNNER_TEMP}/consumer" + "${RUNNER_TEMP}/consumer/bin/python" -m pip install --no-index "${wheels[0]}" + npm install --ignore-scripts --no-audit --no-fund --prefix "${RUNNER_TEMP}/typescript-consumer" \ + "${RUNNER_TEMP}"/typescript-package/auths-dev-sdk-*.tgz + sudo -n mkdir -m 0755 /opt/auths-qualification + sudo -n cp -R "${RUNNER_TEMP}/consumer" /opt/auths-qualification/python + sudo -n cp -R "${RUNNER_TEMP}/typescript-consumer" /opt/auths-qualification/typescript + sudo -n cp qualification/reference/installed_submit.mjs /opt/auths-qualification/typescript/ + sudo -n cp -R qualification/reference /opt/auths-qualification/kit + sudo -n cp "$(command -v node)" /opt/auths-qualification/node + sudo -n chmod -R a+rX /opt/auths-qualification chmod +x "${RUNNER_TEMP}/candidate/bin/"* - export AUTHS_GATEWAY="${RUNNER_TEMP}/candidate/bin/auths-gateway" - export AUTHS_QUALIFICATION="${GITHUB_WORKSPACE}/target/release/auths-qualification" - bash qualification/run/resource-session.sh "${FAMILY}" "${RUNNER_TEMP}/work" \ - bash qualification/run/live.sh "${FAMILY}" "${RUNNER_TEMP}/work" - - name: Close and scan the final proposal after successful cleanup - # The resource session has exited successfully, including its cleanup. - # Keep the real canaries while rebuilding the complete redaction - # evidence, then scan the actual final proposal before any upload. + - name: Prepare the retained operator and scan public commissioning inputs + id: operator shell: bash env: - FAMILY: ${{ matrix.family }} - RUN: ${{ github.run_id }}-${{ github.run_attempt }} + STRIPE_QUALIFICATION_SETUP_KEY: ${{ matrix.family == 'stripe-platform-refund-v1' && secrets.STRIPE_QUALIFICATION_SETUP_KEY || '' }} + STRIPE_QUALIFICATION_RUNTIME_KEY: ${{ matrix.family == 'stripe-platform-refund-v1' && secrets.STRIPE_QUALIFICATION_RUNTIME_KEY || '' }} + STRIPE_QUALIFICATION_NEXT_RUNTIME_KEY: ${{ matrix.family == 'stripe-platform-refund-v1' && secrets.STRIPE_QUALIFICATION_NEXT_RUNTIME_KEY || '' }} + AIRTABLE_QUALIFICATION_TOKEN: ${{ matrix.family == 'airtable-record-update-v1' && secrets.AIRTABLE_QUALIFICATION_TOKEN || '' }} + AIRTABLE_QUALIFICATION_NEXT_TOKEN: ${{ matrix.family == 'airtable-record-update-v1' && secrets.AIRTABLE_QUALIFICATION_NEXT_TOKEN || '' }} + run: | + set -euo pipefail + wheels=("${RUNNER_TEMP}"/python-package/*.whl) + test "${#wheels[@]}" -eq 1 + keep=GITHUB_REPOSITORY,GITHUB_EVENT_NAME,GITHUB_REF,GITHUB_RUN_ID,GITHUB_RUN_ATTEMPT,GITHUB_SHA,GITHUB_ACTIONS,RUNNER_ENVIRONMENT,RUNNER_TRACKING_ID,ACTIONS_ID_TOKEN_REQUEST_URL,ACTIONS_ID_TOKEN_REQUEST_TOKEN + keep+=,STRIPE_QUALIFICATION_SETUP_KEY,STRIPE_QUALIFICATION_RUNTIME_KEY,STRIPE_QUALIFICATION_NEXT_RUNTIME_KEY,AIRTABLE_QUALIFICATION_TOKEN,AIRTABLE_QUALIFICATION_NEXT_TOKEN + sudo -n --preserve-env="${keep}" python3 -B qualification/reference/journey_session.py start \ + --family "${FAMILY}" --root "/tmp/aq-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}" \ + --binary "${RUNNER_TEMP}/candidate/bin/auths-gateway" \ + --issuer "${RUNNER_TEMP}/candidate/bin/auths-qualification" \ + --python /opt/auths-qualification/python/bin/python --kit /opt/auths-qualification/kit \ + --wheel "${wheels[0]}" --node /opt/auths-qualification/node \ + --script /opt/auths-qualification/typescript/installed_submit.mjs \ + --package "${RUNNER_TEMP}/typescript-package" --exports "${RUNNER_TEMP}/operator-exports" \ + --runner-uid "$(id -u)" --runner-gid "$(id -g)" + sudo -n python3 -B qualification/reference/journey_session.py advance \ + --family "${FAMILY}" --root "/tmp/aq-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}" --phase prepare + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 + with: + name: qualification-commissioning-inputs-${{ matrix.family }}-${{ github.run_id }}-${{ github.run_attempt }} + path: ${{ runner.temp }}/operator-exports/commissioning-inputs + if-no-files-found: error + retention-days: 30 + - name: Receive the independent permit and close the measured first proposal + shell: bash + env: + GH_TOKEN: ${{ github.token }} + run: | + set -euo pipefail + keep=GH_TOKEN,GITHUB_REPOSITORY,GITHUB_EVENT_NAME,GITHUB_REF,GITHUB_RUN_ID,GITHUB_RUN_ATTEMPT,GITHUB_SHA + sudo -n --preserve-env="${keep}" python3 -B qualification/reference/journey_session.py receive \ + --family "${FAMILY}" --root "/tmp/aq-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}" --kind commissioning-permit + sudo -n python3 -B qualification/reference/journey_session.py advance \ + --family "${FAMILY}" --root "/tmp/aq-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}" --phase commission + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 + with: + name: qualification-first-proposal-${{ matrix.family }}-${{ github.run_id }}-${{ github.run_attempt }} + path: ${{ runner.temp }}/operator-exports/first-proposal + if-no-files-found: error + retention-days: 30 + - name: Import first qualification, exercise ordinary production and retire owned resources + shell: bash + env: + GH_TOKEN: ${{ github.token }} run: | set -euo pipefail - chmod 0700 "${RUNNER_TEMP}/work" - python3 -B qualification/run/close_proposal.py \ - --family "${FAMILY}" --work "${RUNNER_TEMP}/work" \ - --environment "recipe-qualification-live-${FAMILY}" --run "${RUN}" \ - --tool "${GITHUB_WORKSPACE}/target/release/auths-qualification" - test ! -e "${RUNNER_TEMP}/work/canaries" + keep=GH_TOKEN,GITHUB_REPOSITORY,GITHUB_EVENT_NAME,GITHUB_REF,GITHUB_RUN_ID,GITHUB_RUN_ATTEMPT,GITHUB_SHA + sudo -n --preserve-env="${keep}" python3 -B qualification/reference/journey_session.py receive \ + --family "${FAMILY}" --root "/tmp/aq-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}" --kind first-release + for phase in import-first live cleanup final-proposal; do + sudo -n python3 -B qualification/reference/journey_session.py advance \ + --family "${FAMILY}" --root "/tmp/aq-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}" --phase "${phase}" + done + sudo -n test ! -e "/tmp/aq-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}/publication/canaries" - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: - name: proposal-${{ matrix.family }} - path: ${{ runner.temp }}/work/proposal + name: qualification-final-proposal-${{ matrix.family }}-${{ github.run_id }}-${{ github.run_attempt }} + path: ${{ runner.temp }}/operator-exports/final-proposal if-no-files-found: error retention-days: 90 + - name: Retire this operator after failure or cancellation + if: always() && steps.operator.outcome != 'skipped' + shell: bash + run: | + set -euo pipefail + root="/tmp/aq-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}" + if sudo -n test -S "${root}/control/session.sock"; then + sudo -n python3 -B qualification/reference/journey_session.py advance \ + --family "${FAMILY}" --root "${root}" --phase abort + fi + + commissioner: + name: independently review finite commissioning (${{ matrix.family }}) + needs: [families, candidate, offline, packet-author, typescript-consumer, simulation] + if: github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main' + runs-on: ubuntu-latest + timeout-minutes: 135 + environment: recipe-qualification-commissioning + permissions: + contents: read + actions: read + strategy: + fail-fast: false + matrix: + family: ${{ fromJSON(needs.families.outputs.list) }} + env: + FAMILY: ${{ matrix.family }} + steps: + - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 + with: + persist-credentials: false + - uses: ./.github/actions/setup-rust-cache + with: + toolchain: 1.97.1 + - name: Build the issuer and reviewer from this protected checkout + run: cargo build --locked --release -p auths-gateway --bin auths-gateway -p auths-recipe-qualification-issuance --bin auths-qualification + - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 + with: + name: qualification-shipping-candidate-${{ github.run_id }}-${{ github.run_attempt }} + path: ${{ runner.temp }}/candidate + - name: Receive only this run's bounded public inputs + shell: bash + env: + GH_TOKEN: ${{ github.token }} + run: | + set -euo pipefail + umask 077 + mkdir -m 0700 "${RUNNER_TEMP}/inputs" + python3 -B qualification/run/artifact_wait.py --kind commissioning-inputs --family "${FAMILY}" \ + --not-after "$(( $(date -u +%s) + 7200 ))" --out "${RUNNER_TEMP}/inputs/${FAMILY}" + - name: Review the full source pool before reading the commissioning key + shell: bash + env: + QUALIFICATION_COMMISSIONING_SIGNER_KEY: ${{ secrets.QUALIFICATION_COMMISSIONING_SIGNER_KEY }} + run: | + python3 -B qualification/run/commission.py --family "${FAMILY}" \ + --inputs "${RUNNER_TEMP}/inputs/${FAMILY}" --candidate "${RUNNER_TEMP}/candidate/bin/auths-gateway" \ + --out "${RUNNER_TEMP}/permit" - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: - name: qualification-operator-report-${{ matrix.family }}-${{ github.run_id }}-${{ github.run_attempt }} - path: ${{ runner.temp }}/work + name: qualification-commissioning-permit-${{ matrix.family }}-${{ github.run_id }}-${{ github.run_attempt }} + path: ${{ runner.temp }}/permit if-no-files-found: error retention-days: 30 - sign: - # The only job that holds the release signer's key. It waits for a - # required reviewer of its environment, re-verifies every record's - # evidence closure, attests each record, and signs one index listing - # exactly this run's records. It signs nothing else. - name: sign the release - needs: live + first-sign: + name: independently sign first qualification (${{ matrix.family }}) + needs: [families, candidate, offline, packet-author, typescript-consumer, simulation] if: github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main' runs-on: ubuntu-latest - timeout-minutes: 15 + timeout-minutes: 135 environment: recipe-qualification-signing + permissions: + contents: read + actions: read + strategy: + fail-fast: false + matrix: + family: ${{ fromJSON(needs.families.outputs.list) }} + env: + FAMILY: ${{ matrix.family }} steps: - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 with: @@ -437,41 +566,119 @@ jobs: - uses: ./.github/actions/setup-rust-cache with: toolchain: 1.97.1 - - name: Build the release tool from this commit - run: cargo build --locked --release -p auths-recipe-qualification-issuance --bin auths-qualification + - name: Build the issuer and reviewer from this protected checkout + run: cargo build --locked --release -p auths-gateway --bin auths-gateway -p auths-recipe-qualification-issuance --bin auths-qualification - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 with: - pattern: proposal-* - path: ${{ runner.temp }}/proposals - - name: Sign every proposal into one release + name: qualification-shipping-candidate-${{ github.run_id }}-${{ github.run_attempt }} + path: ${{ runner.temp }}/candidate + - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 + with: + name: qualification-python-${{ github.run_id }}-${{ github.run_attempt }} + path: ${{ runner.temp }}/python-package + - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 + with: + name: qualification-typescript-${{ github.run_id }}-${{ github.run_attempt }} + path: ${{ runner.temp }}/typescript-package + - name: Receive only this run's original public pool and first proposal + shell: bash + env: + GH_TOKEN: ${{ github.token }} + run: | + set -euo pipefail + umask 077 + mkdir -m 0700 "${RUNNER_TEMP}/inputs" + python3 -B qualification/run/artifact_wait.py --kind commissioning-inputs --family "${FAMILY}" \ + --not-after "$(( $(date -u +%s) + 7200 ))" --out "${RUNNER_TEMP}/inputs/${FAMILY}" + mkdir -m 0700 "${RUNNER_TEMP}/proposals" + python3 -B qualification/run/artifact_wait.py --kind first-proposal --family "${FAMILY}" \ + --not-after "$(( $(date -u +%s) + 7200 ))" --out "${RUNNER_TEMP}/proposals/${FAMILY}" + - name: Reconstruct and sign the first qualification without executing downloaded programs shell: bash env: QUALIFICATION_RELEASE_SIGNER_KEY: ${{ secrets.QUALIFICATION_RELEASE_SIGNER_KEY }} + run: | + set -euo pipefail + wheels=("${RUNNER_TEMP}"/python-package/*.whl) + test "${#wheels[@]}" -eq 1 + python3 -B qualification/run/sign_release.py --family "${FAMILY}" --stage commissioning \ + --inputs "${RUNNER_TEMP}/inputs" --proposal "${RUNNER_TEMP}/proposals" \ + --candidate "${RUNNER_TEMP}/candidate" --wheel "${wheels[0]}" \ + --typescript "${RUNNER_TEMP}/typescript-package" --out "${RUNNER_TEMP}/release" + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 + with: + name: qualification-first-release-${{ matrix.family }}-${{ github.run_id }}-${{ github.run_attempt }} + path: ${{ runner.temp }}/release + if-no-files-found: error + retention-days: 30 + + sign: + name: sign the complete cleaned qualification release + needs: [live, families, commissioner, first-sign] + if: github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main' + runs-on: ubuntu-latest + timeout-minutes: 60 + environment: recipe-qualification-signing + permissions: + contents: read + actions: read + steps: + - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 + with: + persist-credentials: false + - uses: ./.github/actions/setup-rust-cache + with: + toolchain: 1.97.1 + - name: Build the issuer and reviewer from this protected checkout + run: cargo build --locked --release -p auths-gateway --bin auths-gateway -p auths-recipe-qualification-issuance --bin auths-qualification + - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 + with: + name: qualification-shipping-candidate-${{ github.run_id }}-${{ github.run_attempt }} + path: ${{ runner.temp }}/candidate + - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 + with: + name: qualification-python-${{ github.run_id }}-${{ github.run_attempt }} + path: ${{ runner.temp }}/python-package + - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 + with: + name: qualification-typescript-${{ github.run_id }}-${{ github.run_attempt }} + path: ${{ runner.temp }}/typescript-package + - name: Receive exact-run public inputs and cleanup-closed proposals + shell: bash + env: + GH_TOKEN: ${{ github.token }} + FAMILIES: ${{ needs.families.outputs.list }} run: | set -euo pipefail umask 077 - for required in qualification-trust-root.json signer-certificate.json revocation-list.json; do - test -s "qualification/trust/${required}" \ - || { echo "qualification.trust-not-published ${required}" >&2; exit 1; } - done - key="${RUNNER_TEMP}/release-signer.key" - trap 'rm -f "${key}"' EXIT - printf '%s' "${QUALIFICATION_RELEASE_SIGNER_KEY}" > "${key}" - # The key is given only to the tool this job built from the - # reviewed commit, never to a binary another job produced. - tool="${GITHUB_WORKSPACE}/target/release/auths-qualification" + mkdir -m 0700 "${RUNNER_TEMP}/inputs" "${RUNNER_TEMP}/proposals" + while IFS= read -r family; do + python3 -B qualification/run/artifact_wait.py --kind commissioning-inputs --family "${family}" \ + --not-after "$(( $(date -u +%s) + 7200 ))" --out "${RUNNER_TEMP}/inputs/${family}" + python3 -B qualification/run/artifact_wait.py --kind final-proposal --family "${family}" \ + --not-after "$(( $(date -u +%s) + 7200 ))" --out "${RUNNER_TEMP}/proposals/${family}" + done < <(jq -r '.[]' <<< "${FAMILIES}") + - name: Reconstruct every family before reading the release signer + shell: bash + env: + FAMILIES: ${{ needs.families.outputs.list }} + QUALIFICATION_RELEASE_SIGNER_KEY: ${{ secrets.QUALIFICATION_RELEASE_SIGNER_KEY }} + run: | + set -euo pipefail + wheels=("${RUNNER_TEMP}"/python-package/*.whl) + test "${#wheels[@]}" -eq 1 arguments=() - for proposal in "${RUNNER_TEMP}"/proposals/proposal-*; do - arguments+=(--proposal-dir "${proposal}") - done - "${tool}" sign "${arguments[@]}" --signer-key "${key}" \ - --certificate qualification/trust/signer-certificate.json \ - --out-dir "${RUNNER_TEMP}/release" - cp qualification/trust/revocation-list.json "${RUNNER_TEMP}/release/revocation-list.json" - mkdir -p "${RUNNER_TEMP}/release-inputs" - for proposal in "${RUNNER_TEMP}"/proposals/proposal-*; do - cp "${proposal}/tuple.json" "${RUNNER_TEMP}/release-inputs/$(basename "${proposal}").tuple.json" - done + while IFS= read -r family; do + arguments+=(--family "${family}") + done < <(jq -r 'sort | .[]' <<< "${FAMILIES}") + python3 -B qualification/run/sign_release.py "${arguments[@]}" --stage live \ + --inputs "${RUNNER_TEMP}/inputs" --proposal "${RUNNER_TEMP}/proposals" \ + --candidate "${RUNNER_TEMP}/candidate" --wheel "${wheels[0]}" \ + --typescript "${RUNNER_TEMP}/typescript-package" --out "${RUNNER_TEMP}/release" + mkdir -m 0700 "${RUNNER_TEMP}/release-inputs" + while IFS= read -r family; do + cp "${RUNNER_TEMP}/inputs/${family}/tuple.json" "${RUNNER_TEMP}/release-inputs/${family}.tuple.json" + done < <(jq -r 'sort | .[]' <<< "${FAMILIES}") - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: name: signed-release diff --git a/product/qualification/auths-recipe-qualification-issuance/tests/protected_run.rs b/product/qualification/auths-recipe-qualification-issuance/tests/protected_run.rs index 7832da576..8da638d9f 100644 --- a/product/qualification/auths-recipe-qualification-issuance/tests/protected_run.rs +++ b/product/qualification/auths-recipe-qualification-issuance/tests/protected_run.rs @@ -89,7 +89,9 @@ fn a_pull_request_reaches_no_secret_and_no_signing_job() { names, [ "candidate", + "commissioner", "families", + "first-sign", "live", "offline", "packet-author", @@ -104,23 +106,29 @@ fn a_pull_request_reaches_no_secret_and_no_signing_job() { let privileged = has("secrets.") || has("environment:") || has("id-token"); assert_eq!( privileged, - matches!(name.as_str(), "live" | "sign"), - "{name}: only the live and signing jobs reach a secret or an environment" + matches!( + name.as_str(), + "commissioner" | "first-sign" | "live" | "sign" + ), + "{name}: only the operator, commissioner and release signers reach protected inputs" ); let protected = lines.iter().any(|line| line == PROTECTED); assert_eq!( protected, - matches!(name.as_str(), "live" | "sign" | "verify"), + matches!( + name.as_str(), + "commissioner" | "first-sign" | "live" | "sign" | "verify" + ), "{name}: live evidence and signing run only by hand on the default branch" ); assert_eq!( has("QUALIFICATION_RELEASE_SIGNER_KEY"), - name == "sign", - "{name}: the signer's key" + matches!(name.as_str(), "first-sign" | "sign"), + "{name}: the release signer's key" ); assert_eq!( - has("\" sign ") || has("${tool}\" sign"), - name == "sign", + has("qualification/run/sign_release.py"), + matches!(name.as_str(), "first-sign" | "sign"), "{name}: the signing command" ); } @@ -129,13 +137,15 @@ fn a_pull_request_reaches_no_secret_and_no_signing_job() { sign.iter() .any(|line| line == "environment: recipe-qualification-signing") ); - assert!( - sign.iter().any(|line| line.contains("rm -f \"${key}\"")), - "the key file is removed when the job ends" - ); + let signer_source = + std::fs::read_to_string(repository().join("qualification/run/sign_release.py")) + .expect("source-owned signer"); + assert!(signer_source.contains("with tempfile.TemporaryDirectory(")); + assert!(signer_source.contains("verify_proposal(")); + assert!(signer_source.contains("commission.signing_seed(os.environ.get(")); // The key is used only by a tool the signing job built itself, and no - // privileged or signing-path job runs a binary another job produced. - for name in ["sign", "verify"] { + // signing-path job runs a binary another job produced. + for name in ["commissioner", "first-sign", "sign", "verify"] { let lines = &jobs[name]; assert!( lines @@ -152,8 +162,8 @@ fn a_pull_request_reaches_no_secret_and_no_signing_job() { let live = &jobs["live"]; let scan = live .iter() - .position(|line| line.contains("close_proposal.py")) - .expect("the live job closes and scans its final proposal"); + .position(|line| line.contains("--phase prepare")) + .expect("the retained operator prepares and scans before export"); let upload = live .iter() .position(|line| line.contains("upload-artifact")) @@ -163,6 +173,23 @@ fn a_pull_request_reaches_no_secret_and_no_signing_job() { live.iter() .any(|line| line.contains("test ! -e") && line.contains("canaries")) ); + assert!( + live.iter() + .any(|line| line == "environment: gateway-custody-live") + ); + for phase in [ + "commissioning-permit", + "first-release", + "import-first live cleanup final-proposal", + ] { + assert!(live.iter().any(|line| line.contains(phase)), "{phase}"); + } + assert!(!live.iter().any(|line| line.contains("resource-session.sh"))); + assert!( + jobs["commissioner"] + .iter() + .any(|line| line.contains("commission.py")) + ); assert!(!text.contains("pull_request_target")); } diff --git a/qualification/families/airtable-record-update-v1/contract.json b/qualification/families/airtable-record-update-v1/contract.json index d1ffb43e5..f770c95ac 100644 --- a/qualification/families/airtable-record-update-v1/contract.json +++ b/qualification/families/airtable-record-update-v1/contract.json @@ -1 +1 @@ -{"api_release":"web-api-v0-reviewed-2026-10-07","corpus_manifest_sha256":"e7ba4d91426ade1fe5107170b89b64bc735bf2b3d164d3d65975da8012cefa2c","declarations":{"idempotency_sha256":"74234e98afe7498fb5daf1f36ac2d78acc339464f950703b8c019892f982b90b","observation_sha256":"9dd79dd204fa13a2df3c667d106c66c0526d174a2c018631e2b2f6b897eaf311","recovery_sha256":"7081a92b4cd2d13dab5e7c30e640675a252b62bca20d340e14d62d9c8c048eca","retention_sha256":"4a4b5048c97b16e041af55b032c0b8ac20f5142c4bbcbf31b31c6674770a70d0"},"environment_class":"disposable-live-resources","manual_assumptions":["Airtable supplies no idempotency key for this PATCH; durable gateway admission prevents a second entry.","Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only a fresh GET with the exact replacement and echo can reconcile a lost response.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths.","The reviewed fixed Airtable base and table contain only owner-authorized disposable qualification records."],"oracle_version":"auths-reviewed-reference-v2","provider":"airtable","schema":"auths.provider-contract/1"} \ No newline at end of file +{"api_release":"web-api-v0-reviewed-2026-10-07","corpus_manifest_sha256":"bfc778c19e7df4e1038a732e0422e057dcaaab86152baa443fb9540e02bd2e7d","declarations":{"idempotency_sha256":"74234e98afe7498fb5daf1f36ac2d78acc339464f950703b8c019892f982b90b","observation_sha256":"9dd79dd204fa13a2df3c667d106c66c0526d174a2c018631e2b2f6b897eaf311","recovery_sha256":"7081a92b4cd2d13dab5e7c30e640675a252b62bca20d340e14d62d9c8c048eca","retention_sha256":"4a4b5048c97b16e041af55b032c0b8ac20f5142c4bbcbf31b31c6674770a70d0"},"environment_class":"disposable-live-resources","manual_assumptions":["Airtable supplies no idempotency key for this PATCH; durable gateway admission prevents a second entry.","Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only a fresh GET with the exact replacement and echo can reconcile a lost response.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths.","The reviewed fixed Airtable base and table contain only owner-authorized disposable qualification records."],"oracle_version":"auths-reviewed-reference-v2","provider":"airtable","schema":"auths.provider-contract/1"} \ No newline at end of file diff --git a/qualification/families/airtable-record-update-v1/corpus-manifest.json b/qualification/families/airtable-record-update-v1/corpus-manifest.json index 8879e35eb..941b1e958 100644 --- a/qualification/families/airtable-record-update-v1/corpus-manifest.json +++ b/qualification/families/airtable-record-update-v1/corpus-manifest.json @@ -1 +1 @@ -{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"32241d9b4811a55abcdd224ef567df3857dbec34d761ef7a35d1044cdfa52d9f","family":"airtable-record-update-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"af7f984509ab11a3676cacc85eda2fa638c25bf91f7bfedf3ff3c119e47f3c41","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","application_probe.py":"5e2dd6a91eb0a2acf2df1079cead5bd67ae5d6743abce6e48201e7326f63daa2","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","controller_socket.py":"10519cc775e963360870eac51c7fcac1ffb988b04d5de89dac1dbf3524ba6531","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"b614b12b0789afb2ce4f4b81618db8d6e2333a8b52ec76fc96fbba1be715ee68","family_harness.py":"0e0a42be6cf75dfb3f674b26cbdfbb4c473edea71083dfaad89ecb40dec039ba","family_operations.py":"8ab354fdf5f2eaab9c061ab967935c76b861a388541bc36fbcf9da5a9a630012","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","installed_submit.mjs":"9d57a91c4a052fbb9103582689ee99a6d087758dcfee00defa4c762b87187468","installed_submit.py":"f9151c2dffa1a02327b0ba05bdeb180654918a2b913195185a6649d010783dc7","journey_session.py":"3c807ce45dcabe3b39d63333872af3746fe9276aacf5eba30bf903b51d80dfef","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"580fa1db01a6fa7691d618f123f9117ce39b25e6478460ceac46c1e650d6b454","network_fault.py":"94340720d8601f79ac77b95d1e855be25195c19b67db3103bbf054d82c02472b","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","production_environment.py":"4afa2491624b0dfbc44fba868474415628d18f1493f8e6c772f108eccd1390da","production_journey.py":"179b93aa525ddd73ad1b3e9fcf38eeb540173845025707aed6b9fa9a44e4aad8","production_setup.py":"6ed9488e59514cde495aed9f5efde604c69bf416112759ec24ae36eb79070003","provider_readback.py":"d576768208985b3544f146597d181d796f2a5e2eca5026dae3fa15cadcfe65b2","resource_io.py":"b0ed0223fd11a1a28c25278de539a9b2ed63881b26a8e00e386f25d4d9aa9384","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","retained_author.py":"bfd01c7df44f5f525326dfbda13b5ebc6b854f15787a8b2923de883fe20fdcf9","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489","tls_fault.py":"10e125f9623bc32a420a1d83e6d46fe30aa1ca8ff4da97a3e2422fc0e11ec42d"},"source_recipe_sha256":"c0f21ff1d3c8e344fee20a9a0c25bb14a264417ed53418ad536789a6096fb16e"} \ No newline at end of file +{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"32241d9b4811a55abcdd224ef567df3857dbec34d761ef7a35d1044cdfa52d9f","family":"airtable-record-update-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"af7f984509ab11a3676cacc85eda2fa638c25bf91f7bfedf3ff3c119e47f3c41","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","application_probe.py":"5e2dd6a91eb0a2acf2df1079cead5bd67ae5d6743abce6e48201e7326f63daa2","artifact_wait.py":"56efcf5a34103955e43c1d3be7fd58843efdc8095187d74dc890cf3342863f55","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","close_proposal.py":"9a6927722ada8eaba720ff13168101244880da3fe6f2c95f653bc3840ef81756","commission.py":"f4495d6e3d2b9c50e72e339e9571eacd9b3628ebebe7c86c601b94e785a5c9fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","controller_socket.py":"10519cc775e963360870eac51c7fcac1ffb988b04d5de89dac1dbf3524ba6531","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"b614b12b0789afb2ce4f4b81618db8d6e2333a8b52ec76fc96fbba1be715ee68","family_harness.py":"0e0a42be6cf75dfb3f674b26cbdfbb4c473edea71083dfaad89ecb40dec039ba","family_operations.py":"8ab354fdf5f2eaab9c061ab967935c76b861a388541bc36fbcf9da5a9a630012","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","installed_submit.mjs":"9d57a91c4a052fbb9103582689ee99a6d087758dcfee00defa4c762b87187468","installed_submit.py":"f9151c2dffa1a02327b0ba05bdeb180654918a2b913195185a6649d010783dc7","journey_session.py":"3c807ce45dcabe3b39d63333872af3746fe9276aacf5eba30bf903b51d80dfef","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"580fa1db01a6fa7691d618f123f9117ce39b25e6478460ceac46c1e650d6b454","network_fault.py":"94340720d8601f79ac77b95d1e855be25195c19b67db3103bbf054d82c02472b","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","production_environment.py":"4afa2491624b0dfbc44fba868474415628d18f1493f8e6c772f108eccd1390da","production_journey.py":"179b93aa525ddd73ad1b3e9fcf38eeb540173845025707aed6b9fa9a44e4aad8","production_setup.py":"6ed9488e59514cde495aed9f5efde604c69bf416112759ec24ae36eb79070003","provider_readback.py":"d576768208985b3544f146597d181d796f2a5e2eca5026dae3fa15cadcfe65b2","resource_io.py":"b0ed0223fd11a1a28c25278de539a9b2ed63881b26a8e00e386f25d4d9aa9384","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","retained_author.py":"bfd01c7df44f5f525326dfbda13b5ebc6b854f15787a8b2923de883fe20fdcf9","sign_release.py":"d0aa7697cc6889538dfd54f9101a5b7bc2e8f7aede729da2d382b6466781df99","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489","tls_fault.py":"10e125f9623bc32a420a1d83e6d46fe30aa1ca8ff4da97a3e2422fc0e11ec42d"},"source_recipe_sha256":"c0f21ff1d3c8e344fee20a9a0c25bb14a264417ed53418ad536789a6096fb16e"} \ No newline at end of file diff --git a/qualification/families/stripe-platform-refund-v1/contract.json b/qualification/families/stripe-platform-refund-v1/contract.json index 8dafa8986..1fa5718b9 100644 --- a/qualification/families/stripe-platform-refund-v1/contract.json +++ b/qualification/families/stripe-platform-refund-v1/contract.json @@ -1 +1 @@ -{"api_release":"2025-03-31.basil","corpus_manifest_sha256":"59a93f3f7077e2b8d7d11c187ffeedba030e5e58e81c20e085266f0b9a653961","declarations":{"idempotency_sha256":"425a0dca2f279765debfc847c4a01bff60fea5be68dd9d761ae6bb60ce0b8a7b","observation_sha256":"d0ce5a34d987821c69c0a839d9ed66805c625f8324dd42031fcccf0752a8821e","recovery_sha256":"bf2303abce165c175360ac975586431bbc4cf03167489ea317a27de2f0b04abb","retention_sha256":"846c2164e26d1144d9aa146034b4f7ea4dc305136a59ffd94f999d19f2c360ee"},"environment_class":"provider-test-mode","manual_assumptions":["Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","Stripe idempotency is tested only inside the declared 86400-second retention interval.","Stripe test mode and the installed platform are checked by the declared guard on each lease.","The 50-percent payment basis is a read, not an atomic provider balance reservation.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths."],"oracle_version":"auths-reviewed-reference-v2","provider":"stripe","schema":"auths.provider-contract/1"} \ No newline at end of file +{"api_release":"2025-03-31.basil","corpus_manifest_sha256":"8d88635d501b670d76aa605a8f6129c7f806c0a50ece01177df5a22ad04cf585","declarations":{"idempotency_sha256":"425a0dca2f279765debfc847c4a01bff60fea5be68dd9d761ae6bb60ce0b8a7b","observation_sha256":"d0ce5a34d987821c69c0a839d9ed66805c625f8324dd42031fcccf0752a8821e","recovery_sha256":"bf2303abce165c175360ac975586431bbc4cf03167489ea317a27de2f0b04abb","retention_sha256":"846c2164e26d1144d9aa146034b4f7ea4dc305136a59ffd94f999d19f2c360ee"},"environment_class":"provider-test-mode","manual_assumptions":["Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","Stripe idempotency is tested only inside the declared 86400-second retention interval.","Stripe test mode and the installed platform are checked by the declared guard on each lease.","The 50-percent payment basis is a read, not an atomic provider balance reservation.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths."],"oracle_version":"auths-reviewed-reference-v2","provider":"stripe","schema":"auths.provider-contract/1"} \ No newline at end of file diff --git a/qualification/families/stripe-platform-refund-v1/corpus-manifest.json b/qualification/families/stripe-platform-refund-v1/corpus-manifest.json index 8ca749c7e..8bbf177cf 100644 --- a/qualification/families/stripe-platform-refund-v1/corpus-manifest.json +++ b/qualification/families/stripe-platform-refund-v1/corpus-manifest.json @@ -1 +1 @@ -{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"a72c557b69103a52eb477deb8364ded53cd58407b9ba7ab33ccbda74389fec1e","family":"stripe-platform-refund-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"99901e36cb7c4f5882897603c874698d582e859b5d6b08d53cd80975e89aa01c","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","application_probe.py":"5e2dd6a91eb0a2acf2df1079cead5bd67ae5d6743abce6e48201e7326f63daa2","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","controller_socket.py":"10519cc775e963360870eac51c7fcac1ffb988b04d5de89dac1dbf3524ba6531","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"b614b12b0789afb2ce4f4b81618db8d6e2333a8b52ec76fc96fbba1be715ee68","family_harness.py":"0e0a42be6cf75dfb3f674b26cbdfbb4c473edea71083dfaad89ecb40dec039ba","family_operations.py":"8ab354fdf5f2eaab9c061ab967935c76b861a388541bc36fbcf9da5a9a630012","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","installed_submit.mjs":"9d57a91c4a052fbb9103582689ee99a6d087758dcfee00defa4c762b87187468","installed_submit.py":"f9151c2dffa1a02327b0ba05bdeb180654918a2b913195185a6649d010783dc7","journey_session.py":"3c807ce45dcabe3b39d63333872af3746fe9276aacf5eba30bf903b51d80dfef","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"580fa1db01a6fa7691d618f123f9117ce39b25e6478460ceac46c1e650d6b454","network_fault.py":"94340720d8601f79ac77b95d1e855be25195c19b67db3103bbf054d82c02472b","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","production_environment.py":"4afa2491624b0dfbc44fba868474415628d18f1493f8e6c772f108eccd1390da","production_journey.py":"179b93aa525ddd73ad1b3e9fcf38eeb540173845025707aed6b9fa9a44e4aad8","production_setup.py":"6ed9488e59514cde495aed9f5efde604c69bf416112759ec24ae36eb79070003","provider_readback.py":"d576768208985b3544f146597d181d796f2a5e2eca5026dae3fa15cadcfe65b2","resource_io.py":"b0ed0223fd11a1a28c25278de539a9b2ed63881b26a8e00e386f25d4d9aa9384","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","retained_author.py":"bfd01c7df44f5f525326dfbda13b5ebc6b854f15787a8b2923de883fe20fdcf9","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489","tls_fault.py":"10e125f9623bc32a420a1d83e6d46fe30aa1ca8ff4da97a3e2422fc0e11ec42d"},"source_recipe_sha256":"b1972d556f28433932a449636755077f7ee485ef90cca412f153bc7f18881368"} \ No newline at end of file +{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"a72c557b69103a52eb477deb8364ded53cd58407b9ba7ab33ccbda74389fec1e","family":"stripe-platform-refund-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"99901e36cb7c4f5882897603c874698d582e859b5d6b08d53cd80975e89aa01c","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","application_probe.py":"5e2dd6a91eb0a2acf2df1079cead5bd67ae5d6743abce6e48201e7326f63daa2","artifact_wait.py":"56efcf5a34103955e43c1d3be7fd58843efdc8095187d74dc890cf3342863f55","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","close_proposal.py":"9a6927722ada8eaba720ff13168101244880da3fe6f2c95f653bc3840ef81756","commission.py":"f4495d6e3d2b9c50e72e339e9571eacd9b3628ebebe7c86c601b94e785a5c9fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","controller_socket.py":"10519cc775e963360870eac51c7fcac1ffb988b04d5de89dac1dbf3524ba6531","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"b614b12b0789afb2ce4f4b81618db8d6e2333a8b52ec76fc96fbba1be715ee68","family_harness.py":"0e0a42be6cf75dfb3f674b26cbdfbb4c473edea71083dfaad89ecb40dec039ba","family_operations.py":"8ab354fdf5f2eaab9c061ab967935c76b861a388541bc36fbcf9da5a9a630012","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","installed_submit.mjs":"9d57a91c4a052fbb9103582689ee99a6d087758dcfee00defa4c762b87187468","installed_submit.py":"f9151c2dffa1a02327b0ba05bdeb180654918a2b913195185a6649d010783dc7","journey_session.py":"3c807ce45dcabe3b39d63333872af3746fe9276aacf5eba30bf903b51d80dfef","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"580fa1db01a6fa7691d618f123f9117ce39b25e6478460ceac46c1e650d6b454","network_fault.py":"94340720d8601f79ac77b95d1e855be25195c19b67db3103bbf054d82c02472b","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","production_environment.py":"4afa2491624b0dfbc44fba868474415628d18f1493f8e6c772f108eccd1390da","production_journey.py":"179b93aa525ddd73ad1b3e9fcf38eeb540173845025707aed6b9fa9a44e4aad8","production_setup.py":"6ed9488e59514cde495aed9f5efde604c69bf416112759ec24ae36eb79070003","provider_readback.py":"d576768208985b3544f146597d181d796f2a5e2eca5026dae3fa15cadcfe65b2","resource_io.py":"b0ed0223fd11a1a28c25278de539a9b2ed63881b26a8e00e386f25d4d9aa9384","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","retained_author.py":"bfd01c7df44f5f525326dfbda13b5ebc6b854f15787a8b2923de883fe20fdcf9","sign_release.py":"d0aa7697cc6889538dfd54f9101a5b7bc2e8f7aede729da2d382b6466781df99","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489","tls_fault.py":"10e125f9623bc32a420a1d83e6d46fe30aa1ca8ff4da97a3e2422fc0e11ec42d"},"source_recipe_sha256":"b1972d556f28433932a449636755077f7ee485ef90cca412f153bc7f18881368"} \ No newline at end of file diff --git a/qualification/reference/README.md b/qualification/reference/README.md index c906c305f..8044d9e6a 100644 --- a/qualification/reference/README.md +++ b/qualification/reference/README.md @@ -247,7 +247,7 @@ Missing artifacts are checked every ten minutes within a fixed two-hour deadline. Only the GitHub Actions token enters the GitHub client; provider and signer keys are absent from that child's environment. The native issuer/gateway must still verify every permit/record: a transported artifact grants no authority. -The protected workflow has not yet connected this mailbox to admitted corpora. +The protected workflow connects these mailboxes to the retained operator, commissioner and release signer jobs. `production_journey.py` and `journey_session.py` now retain one hosted root operator across fixed phases: prepare, commission, import the first release, @@ -259,7 +259,7 @@ verification remain separate. Retained copies are independently rescanned before the runner can upload them. Failed setup invalidates proposals, keeps scan canaries, and attempts all owned cleanup with native credential collection before retiring the renewing workload identity. These entry points still need -the protected workflow's complete job sequence and the remaining case handlers; +the remaining custody-drift case handlers and successful protected execution; they do not establish a passing protected qualification. `author_operator.py` runs in the same credential-free installed environment as @@ -355,3 +355,13 @@ protected steps recheck actual package versions against the retained package manifest and measure the serving gateway's unchanged counters. The TypeScript journey submits public packets from the separate author through the actual installed GatewayClient; it performs no provider request construction. + +`../run/sign_release.py` independently reconstructs the complete original public +pool and source corpus before either first-run or final release signing. The +proposal must match the reviewed contract, exact run, source closure, candidate +and SDK artifact bytes, resource summary, residual assumptions and exclusions. +Every source case must appear once with its reviewed scenario and capabilities; +the native assembler then re-verifies the evidence closure and must reconstruct +identical record bytes. All families pass before the release key is read. +The signing process executes its own native builds only and separately scans +the exact retained release with its real key canary before publication. diff --git a/qualification/reference/generate_families.py b/qualification/reference/generate_families.py index bfc96b59a..0f7154cff 100644 --- a/qualification/reference/generate_families.py +++ b/qualification/reference/generate_families.py @@ -36,7 +36,9 @@ def generate(check=False): 'phases': ['offline', 'commissioning', 'live'], 'maximum_credential_leases': 64, 'source_files': {**{name: sha256(read(REFERENCE / name, 2 * 1024 * 1024)) for name in SOURCES_TO_PIN}, - 'tls_fault.py': sha256(read(ROOT / 'qualification/run/tls_fault.py', 2 * 1024 * 1024))}, + **{name: sha256(read(ROOT / 'qualification/run' / name, 2 * 1024 * 1024)) + for name in ['tls_fault.py', 'artifact_wait.py', 'commission.py', + 'sign_release.py', 'close_proposal.py']}}, 'source_recipe_sha256': sha256(read(SOURCES[reference.FAMILY] / 'recipe.json', 65536)), 'profile_lock_sha256': sha256(read(SOURCES[reference.FAMILY] / 'profile.lock.json', 65536)), 'decision_record_sha256': sha256(read(ROOT / 'docs/adr' / adr, 65536))} diff --git a/qualification/reference/tests/test_release_entry.py b/qualification/reference/tests/test_release_entry.py new file mode 100644 index 000000000..65b23131f --- /dev/null +++ b/qualification/reference/tests/test_release_entry.py @@ -0,0 +1,85 @@ +"""Signer boundary tests; no credentials, signatures or provider traffic.""" + +import copy +from pathlib import Path +import sys +import tempfile +from types import SimpleNamespace +import unittest +from unittest.mock import patch + +sys.path.insert(0, str(Path(__file__).resolve().parents[2] / 'run')) +import sign_release as release +from common import canonical, Refusal + + +class Coverage(unittest.TestCase): + def test_proposal_cannot_change_omit_repeat_or_import_another_phase_case(self): + corpus = {'cases': [ + {'id': 'offline-source', 'phase': 'offline', 'scenario': 'clean-source', 'capabilities': []}, + {'id': 'commissioning-live', 'phase': 'commissioning', 'scenario': 'declared-capability', + 'capabilities': ['observation', 'budget']}, + {'id': 'live-live', 'phase': 'live', 'scenario': 'declared-capability', 'capabilities': ['observation']}]} + reports = [dict(id=case['id'], scenario=case['scenario'], capabilities=sorted(case['capabilities']), + unauthorized_provider_entries=0) for case in corpus['cases'][:2]] + with tempfile.TemporaryDirectory() as temporary: + root = Path(temporary) + (root / 'evidence').mkdir() + def save(values): + (root / 'evidence/00.json').write_bytes(canonical({'cases': values})) + save(reports) + release.coverage(root, corpus, 'commissioning') + changed = copy.deepcopy(reports) + changed[1]['scenario'] = 'proof-replay' + changed_caps = copy.deepcopy(reports) + changed_caps[1]['capabilities'] = [] + entered = copy.deepcopy(reports) + entered[1]['unauthorized_provider_entries'] = 1 + for values in [reports[:1], reports + reports[:1], changed, changed_caps, entered, + reports + [dict(id='live-live', scenario='declared-capability', + capabilities=['observation'], unauthorized_provider_entries=0)]]: + save(values) + with self.assertRaises(Refusal): release.coverage(root, corpus, 'commissioning') + + +class SigningBoundary(unittest.TestCase): + def test_failed_independent_reconstruction_never_reads_the_key_or_signs(self): + identity = {'GITHUB_REPOSITORY': 'auths-dev/auths-proof', 'GITHUB_EVENT_NAME': 'workflow_dispatch', + 'GITHUB_REF': 'refs/heads/main', 'GITHUB_RUN_ID': '123', 'GITHUB_RUN_ATTEMPT': '1', + 'GITHUB_SHA': '1' * 40} + with tempfile.TemporaryDirectory() as temporary: + root = Path(temporary) + args = SimpleNamespace(family=['stripe-platform-refund-v1'], stage='commissioning', + inputs=root / 'inputs', candidate=root / 'candidate', wheel=root / 'sdk.whl', + typescript=root / 'typescript', proposal=root / 'proposals', out=root / 'out') + with patch.dict(release.os.environ, identity, clear=True), \ + patch.object(release.commission, 'call', side_effect=[('1' * 40 + '\n').encode(), b'']) as native, \ + patch.object(release, 'verify_proposal', side_effect=Refusal('qualification.sign.record-source-binding')), \ + patch.object(release.commission, 'signing_seed') as seed: + with self.assertRaises(Refusal): release.sign(args) + seed.assert_not_called() + self.assertEqual(native.call_count, 2) + self.assertFalse(args.out.exists()) + + def test_all_families_pass_before_the_key_is_read(self): + identity = {'GITHUB_REPOSITORY': 'auths-dev/auths-proof', 'GITHUB_EVENT_NAME': 'workflow_dispatch', + 'GITHUB_REF': 'refs/heads/main', 'GITHUB_RUN_ID': '123', 'GITHUB_RUN_ATTEMPT': '1', + 'GITHUB_SHA': '1' * 40} + with tempfile.TemporaryDirectory() as temporary: + root = Path(temporary) + args = SimpleNamespace(family=['airtable-record-update-v1', 'stripe-platform-refund-v1'], stage='live', + inputs=root / 'inputs', candidate=root / 'candidate', wheel=root / 'sdk.whl', + typescript=root / 'typescript', proposal=root / 'proposals', out=root / 'out') + with patch.dict(release.os.environ, identity, clear=True), \ + patch.object(release.commission, 'call', side_effect=[('1' * 40 + '\n').encode(), b'']), \ + patch.object(release, 'verify_proposal', side_effect=[(Path('/source/issuer'), {}), + Refusal('qualification.sign.corpus-coverage')]) as verify, \ + patch.object(release.commission, 'signing_seed') as seed: + with self.assertRaises(Refusal): release.sign(args) + self.assertEqual(verify.call_count, 2) + seed.assert_not_called() + self.assertFalse(args.out.exists()) + + +if __name__ == '__main__': + unittest.main() diff --git a/qualification/run/sign_release.py b/qualification/run/sign_release.py new file mode 100644 index 000000000..523cb1387 --- /dev/null +++ b/qualification/run/sign_release.py @@ -0,0 +1,193 @@ +#!/usr/bin/env python3 +"""Sign only proposals independently reconstructed from this protected source. + +The commissioning inputs, candidate and SDK artifacts are public data. This +job executes only its own reviewer and issuer; its key is read after the whole +pool, corpus, policy statements and native evidence closure have been checked. +""" + +import argparse +import os +from pathlib import Path +import shutil +import tempfile +import time +from types import SimpleNamespace +import tomllib + +import artifact_wait +import commission + +from common import canonical, closed, require, sha256 +import expand +from family_corpus import authenticate, compile_plan +from resource_io import finish, write_bytes +from resource_summary import summary + +ROOT = commission.ROOT +FIRST_EXCLUSION = ('First-run commissioning: ordinary installed clients were refused; their qualified ' + 'effect and production readiness require the subsequent live phase.') +DRAFT_FIELDS = ['qualification_id', 'provider_kind', 'tuple', 'not_before', 'not_after', 'provenance', + 'source_closure_sha256', 'generated_artifacts_sha256', 'installed_packages', + 'recipe_decision_record_sha256', 'corpus_manifest_sha256', 'provider_resources', + 'custody_descriptor', 'store_descriptor', 'residual_assumptions', 'excluded_claims'] + + +def json(path, maximum=2 * 1024 * 1024): + return expand.decode(expand.read(path, maximum)) + + +def packages(candidate, wheel, typescript, commit, tuple_value): + metadata = json(typescript / 'package.json') + closed(metadata, ['schema', 'source_commit', 'name', 'version', 'file', 'sha256', 'qualification_issued']) + source = json(ROOT / 'bindings/typescript/package.json') + require(metadata['schema'] == 'auths.qualification-installed-package/1' + and metadata['source_commit'] == commit and metadata['name'] == source['name'] + and metadata['version'] == source['version'] and metadata['qualification_issued'] is False + and type(metadata['file']) is str and Path(metadata['file']).name == metadata['file'] + and metadata['file'].endswith('.tgz') + and metadata['sha256'] == sha256(expand.read(typescript / metadata['file'], 64 * 1024 * 1024)), + 'qualification.sign.package-binding') + python_version = tomllib.loads(expand.read(ROOT / 'bindings/python/pyproject.toml', 65536).decode())['project']['version'] + require(wheel.name.startswith('auths-' + python_version + '-') and wheel.suffix == '.whl', + 'qualification.sign.package-binding') + return sorted([ + {'name': 'auths', 'version': python_version, 'sha256': sha256(expand.read(wheel, 64 * 1024 * 1024))}, + {'name': 'auths-gateway', 'version': tuple_value['target']['gateway_version'], + 'sha256': sha256(expand.read(candidate / 'bin/auths-gateway', 256 * 1024 * 1024))}, + {'name': source['name'], 'version': source['version'], 'sha256': metadata['sha256']}, + ], key=lambda value: value['name']) + + +def coverage(proposal, corpus, stage): + expected = {case['id']: case for case in corpus['cases'] if case['phase'] in ['offline', stage]} + actual = {} + for path in sorted((proposal / 'evidence').iterdir()): + require(path.name.endswith('.json'), 'qualification.sign.evidence-binding') + for case in json(path)['cases']: + name = case['id'] + if name in expected: + require(name not in actual and case['scenario'] == expected[name]['scenario'] + and type(case['capabilities']) is list + and len(case['capabilities']) == len(set(case['capabilities'])) + and set(case['capabilities']) == set(expected[name]['capabilities']) + and case['unauthorized_provider_entries'] == 0, + 'qualification.sign.corpus-coverage') + actual[name] = case + else: + # Additional reports come only from native trust and publication + # stages. They cannot substitute for a source-owned run case. + require(not name.startswith(('offline-', 'commissioning-', 'live-')), + 'qualification.sign.corpus-coverage') + require(set(actual) == set(expected), 'qualification.sign.corpus-coverage') + + +def verify_proposal(family, stage, inputs, candidate, wheel, typescript, proposal, private, run, attempt, commit): + issuer, reviewer = [ROOT / 'target/release' / name for name in ['auths-qualification', 'auths-gateway']] + tuple_value = commission.source_contract(family, inputs, issuer) + expansion = private / 'expansion' + expand.expand(SimpleNamespace(source_commit=commit, protected_run='recipe-qualification/' + run + '/' + attempt, + tuple=inputs / 'tuple.json', candidate=candidate / 'bin/auths-gateway', reviewer=reviewer, + recipe=inputs / 'recipe.json', profile_lock=inputs / 'profile.lock.json', resources=inputs / 'resources.json', + packets=inputs / 'packets/public-packets.json', conformance=inputs / 'offline/conformance.json', + differential=inputs / 'offline/differential.json', out_dir=expansion)) + work = private / 'pool' + work.mkdir(mode=0o700) + for path in (inputs / 'packets').iterdir(): + write_bytes(work / path.name, expand.read(path, 2 * 1024 * 1024), new=True) + for name in ['recipe.json', 'profile.lock.json', 'resources.json']: + write_bytes(work / name, expand.read(inputs / name, 65536), new=True) + resources, reviewed = authenticate(family, work, reviewer, tuple_value) + corpus = compile_plan(family, resources, reviewed, tuple_value['compiled_recipe_sha256']) + coverage(proposal, corpus, stage) + record_bytes = expand.read(proposal / 'record.json', 2 * 1024 * 1024) + record = expand.decode(record_bytes) + now = int(time.time()) + start, end = record['not_before'], record['not_after'] + policy = json(ROOT / 'qualification/families' / family / 'record.json') + require(type(start) is int and type(end) is int and now - 7200 < start <= now + and now < end and end == start + (7200 if stage == 'commissioning' else policy['validity_days'] * 86400), + 'qualification.sign.validity-binding') + expected = { + 'qualification_id': 'qlf_' + sha256(('\n'.join([family, commit, run + '-' + attempt, stage])).encode())[:32], + 'provider_kind': policy['provider_kind'], 'tuple': tuple_value, + 'not_before': start, 'not_after': end, + 'provenance': {'repository': 'github.com/auths-dev/auths-proof', 'commit': commit, + 'workflow': '.github/workflows/recipe-qualification.yml', 'environment': 'gateway-custody-live'}, + 'source_closure_sha256': sha256(commission.call(['/usr/bin/git', 'ls-tree', '-r', 'HEAD'])), + 'generated_artifacts_sha256': sha256(expand.read(candidate / 'bin/auths-gateway', 256 * 1024 * 1024) + + expand.read(candidate / 'bin/auths-qualification', 256 * 1024 * 1024)), + 'installed_packages': packages(candidate, wheel, typescript, commit, tuple_value), + 'recipe_decision_record_sha256': sha256(expand.read(ROOT / 'qualification/families' / family / 'decision-record.md', 65536)), + 'corpus_manifest_sha256': sha256(canonical(corpus)), 'provider_resources': summary(family, resources), + 'custody_descriptor': policy['custody_descriptor'], 'store_descriptor': policy['store_descriptor'], + 'residual_assumptions': sorted(policy['residual_assumptions']), + 'excluded_claims': sorted(set(policy['excluded_claims'] + ([FIRST_EXCLUSION] if stage == 'commissioning' else []))), + } + require({name: record.get(name) for name in DRAFT_FIELDS} == expected + and json(proposal / 'tuple.json') == tuple_value, 'qualification.sign.record-source-binding') + draft = private / 'draft.json' + write_bytes(draft, canonical({**expected, 'not_applicable': policy['not_applicable']}), new=True) + reconstructed = private / 'reconstructed' + commission.call([issuer, 'assemble', '--draft', draft, '--evidence-dir', proposal / 'evidence', + '--out-dir', reconstructed]) + require(expand.read(reconstructed / 'record.json', 2 * 1024 * 1024) == record_bytes, + 'qualification.sign.native-closure') + return issuer, tuple_value + + +def sign(args): + run, attempt, commit = artifact_wait.identity(os.environ) + require(commission.call(['/usr/bin/git', 'rev-parse', 'HEAD']).decode().strip() == commit + and not commission.call(['/usr/bin/git', 'status', '--porcelain']).strip(), + 'qualification.sign.source-binding') + require(not args.out.exists() and not args.out.is_symlink(), 'qualification.sign.output-exists') + require(args.family == sorted(set(args.family)) and 1 <= len(args.family) <= len(expand.REFERENCES), + 'qualification.sign.family-set') + complete = False + try: + with tempfile.TemporaryDirectory(prefix='auths-source-release-') as temporary: + private = Path(temporary) + for family in args.family: + local = private / family + local.mkdir(mode=0o700) + issuer, _tuple = verify_proposal(family, args.stage, args.inputs / family, args.candidate, + args.wheel, args.typescript, args.proposal / family, local, run, attempt, commit) + seed = commission.signing_seed(os.environ.get('QUALIFICATION_RELEASE_SIGNER_KEY')) + key, canaries = private / 'release-signer.key', private / 'canaries' + write_bytes(key, seed, new=True) + write_bytes(canaries, seed + b'\n', new=True) + args.out.mkdir(mode=0o700) + arguments = [issuer, 'sign'] + for family in args.family: + arguments += ['--proposal-dir', args.proposal / family] + commission.call([*arguments, '--signer-key', key, + '--certificate', ROOT / 'qualification/trust/signer-certificate.json', '--out-dir', args.out]) + write_bytes(args.out / 'revocation-list.json', expand.read(ROOT / 'qualification/trust/revocation-list.json', 65536), new=True) + for family in args.family: + commission.call([issuer, 'verify', '--root', ROOT / 'qualification/trust/qualification-trust-root.json', + '--release-dir', args.out, '--deployment', args.inputs / family / 'tuple.json']) + sources = sorted(path for path in args.out.rglob('*') if path.is_file()) + require(0 < len(sources) <= 256 and all(not path.is_symlink() for path in sources), + 'qualification.sign.publication-bound') + arguments = [issuer, 'stage-redaction', '--canaries', canaries] + for path in sources: + arguments += ['--source', 'evidence=' + str(path)] + commission.call([*arguments, '--out', private / 'publication-scan.json']) + complete = True + finally: + if not complete and args.out.exists(): + shutil.rmtree(args.out) + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--family', choices=sorted(expand.REFERENCES), action='append', required=True) + parser.add_argument('--stage', choices=['commissioning', 'live'], required=True) + for name in ['inputs', 'candidate', 'wheel', 'typescript', 'proposal', 'out']: + parser.add_argument('--' + name, type=lambda value: Path(value).absolute(), required=True) + finish(lambda: sign(parser.parse_args())) + + +if __name__ == '__main__': + main() From ec7c635815db31ba15dbfa7785dbcde7b656e440 Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 18:32:41 +0100 Subject: [PATCH 098/108] Exercise exact owned AWS custody drift before production admission --- .../tests/protected_run.rs | 7 + .../airtable-record-update-v1/contract.json | 2 +- .../corpus-manifest.json | 2 +- .../stripe-platform-refund-v1/contract.json | 2 +- .../corpus-manifest.json | 2 +- qualification/reference/README.md | 19 +- qualification/reference/custody_fault.py | 190 ++++++++++++++++++ qualification/reference/family_corpus.py | 7 +- qualification/reference/family_operations.py | 40 ++++ qualification/reference/generate_families.py | 2 +- .../reference/tests/test_custody_fault.py | 91 +++++++++ 11 files changed, 354 insertions(+), 10 deletions(-) create mode 100644 qualification/reference/custody_fault.py create mode 100644 qualification/reference/tests/test_custody_fault.py diff --git a/product/qualification/auths-recipe-qualification-issuance/tests/protected_run.rs b/product/qualification/auths-recipe-qualification-issuance/tests/protected_run.rs index 8da638d9f..d926ee1e9 100644 --- a/product/qualification/auths-recipe-qualification-issuance/tests/protected_run.rs +++ b/product/qualification/auths-recipe-qualification-issuance/tests/protected_run.rs @@ -132,6 +132,13 @@ fn a_pull_request_reaches_no_secret_and_no_signing_job() { "{name}: the signing command" ); } + assert!(!text.contains("pull_request_target")); +} + +#[test] +fn signing_builds_are_independent_and_operator_exports_follow_scanning() { + let text = std::fs::read_to_string(repository().join(WORKFLOW)).expect("workflow"); + let jobs = jobs(&text); let sign = &jobs["sign"]; assert!( sign.iter() diff --git a/qualification/families/airtable-record-update-v1/contract.json b/qualification/families/airtable-record-update-v1/contract.json index f770c95ac..b37589ae5 100644 --- a/qualification/families/airtable-record-update-v1/contract.json +++ b/qualification/families/airtable-record-update-v1/contract.json @@ -1 +1 @@ -{"api_release":"web-api-v0-reviewed-2026-10-07","corpus_manifest_sha256":"bfc778c19e7df4e1038a732e0422e057dcaaab86152baa443fb9540e02bd2e7d","declarations":{"idempotency_sha256":"74234e98afe7498fb5daf1f36ac2d78acc339464f950703b8c019892f982b90b","observation_sha256":"9dd79dd204fa13a2df3c667d106c66c0526d174a2c018631e2b2f6b897eaf311","recovery_sha256":"7081a92b4cd2d13dab5e7c30e640675a252b62bca20d340e14d62d9c8c048eca","retention_sha256":"4a4b5048c97b16e041af55b032c0b8ac20f5142c4bbcbf31b31c6674770a70d0"},"environment_class":"disposable-live-resources","manual_assumptions":["Airtable supplies no idempotency key for this PATCH; durable gateway admission prevents a second entry.","Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only a fresh GET with the exact replacement and echo can reconcile a lost response.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths.","The reviewed fixed Airtable base and table contain only owner-authorized disposable qualification records."],"oracle_version":"auths-reviewed-reference-v2","provider":"airtable","schema":"auths.provider-contract/1"} \ No newline at end of file +{"api_release":"web-api-v0-reviewed-2026-10-07","corpus_manifest_sha256":"8a4e4d127ac63e929b2ae40518b001f9c13af964a9cdfb8d99f70e29e44d0dc9","declarations":{"idempotency_sha256":"74234e98afe7498fb5daf1f36ac2d78acc339464f950703b8c019892f982b90b","observation_sha256":"9dd79dd204fa13a2df3c667d106c66c0526d174a2c018631e2b2f6b897eaf311","recovery_sha256":"7081a92b4cd2d13dab5e7c30e640675a252b62bca20d340e14d62d9c8c048eca","retention_sha256":"4a4b5048c97b16e041af55b032c0b8ac20f5142c4bbcbf31b31c6674770a70d0"},"environment_class":"disposable-live-resources","manual_assumptions":["Airtable supplies no idempotency key for this PATCH; durable gateway admission prevents a second entry.","Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only a fresh GET with the exact replacement and echo can reconcile a lost response.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths.","The reviewed fixed Airtable base and table contain only owner-authorized disposable qualification records."],"oracle_version":"auths-reviewed-reference-v2","provider":"airtable","schema":"auths.provider-contract/1"} \ No newline at end of file diff --git a/qualification/families/airtable-record-update-v1/corpus-manifest.json b/qualification/families/airtable-record-update-v1/corpus-manifest.json index 941b1e958..6605c66d2 100644 --- a/qualification/families/airtable-record-update-v1/corpus-manifest.json +++ b/qualification/families/airtable-record-update-v1/corpus-manifest.json @@ -1 +1 @@ -{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"32241d9b4811a55abcdd224ef567df3857dbec34d761ef7a35d1044cdfa52d9f","family":"airtable-record-update-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"af7f984509ab11a3676cacc85eda2fa638c25bf91f7bfedf3ff3c119e47f3c41","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","application_probe.py":"5e2dd6a91eb0a2acf2df1079cead5bd67ae5d6743abce6e48201e7326f63daa2","artifact_wait.py":"56efcf5a34103955e43c1d3be7fd58843efdc8095187d74dc890cf3342863f55","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","close_proposal.py":"9a6927722ada8eaba720ff13168101244880da3fe6f2c95f653bc3840ef81756","commission.py":"f4495d6e3d2b9c50e72e339e9571eacd9b3628ebebe7c86c601b94e785a5c9fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","controller_socket.py":"10519cc775e963360870eac51c7fcac1ffb988b04d5de89dac1dbf3524ba6531","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"b614b12b0789afb2ce4f4b81618db8d6e2333a8b52ec76fc96fbba1be715ee68","family_harness.py":"0e0a42be6cf75dfb3f674b26cbdfbb4c473edea71083dfaad89ecb40dec039ba","family_operations.py":"8ab354fdf5f2eaab9c061ab967935c76b861a388541bc36fbcf9da5a9a630012","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","installed_submit.mjs":"9d57a91c4a052fbb9103582689ee99a6d087758dcfee00defa4c762b87187468","installed_submit.py":"f9151c2dffa1a02327b0ba05bdeb180654918a2b913195185a6649d010783dc7","journey_session.py":"3c807ce45dcabe3b39d63333872af3746fe9276aacf5eba30bf903b51d80dfef","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"580fa1db01a6fa7691d618f123f9117ce39b25e6478460ceac46c1e650d6b454","network_fault.py":"94340720d8601f79ac77b95d1e855be25195c19b67db3103bbf054d82c02472b","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","production_environment.py":"4afa2491624b0dfbc44fba868474415628d18f1493f8e6c772f108eccd1390da","production_journey.py":"179b93aa525ddd73ad1b3e9fcf38eeb540173845025707aed6b9fa9a44e4aad8","production_setup.py":"6ed9488e59514cde495aed9f5efde604c69bf416112759ec24ae36eb79070003","provider_readback.py":"d576768208985b3544f146597d181d796f2a5e2eca5026dae3fa15cadcfe65b2","resource_io.py":"b0ed0223fd11a1a28c25278de539a9b2ed63881b26a8e00e386f25d4d9aa9384","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","retained_author.py":"bfd01c7df44f5f525326dfbda13b5ebc6b854f15787a8b2923de883fe20fdcf9","sign_release.py":"d0aa7697cc6889538dfd54f9101a5b7bc2e8f7aede729da2d382b6466781df99","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489","tls_fault.py":"10e125f9623bc32a420a1d83e6d46fe30aa1ca8ff4da97a3e2422fc0e11ec42d"},"source_recipe_sha256":"c0f21ff1d3c8e344fee20a9a0c25bb14a264417ed53418ad536789a6096fb16e"} \ No newline at end of file +{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"32241d9b4811a55abcdd224ef567df3857dbec34d761ef7a35d1044cdfa52d9f","family":"airtable-record-update-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"af7f984509ab11a3676cacc85eda2fa638c25bf91f7bfedf3ff3c119e47f3c41","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","application_probe.py":"5e2dd6a91eb0a2acf2df1079cead5bd67ae5d6743abce6e48201e7326f63daa2","artifact_wait.py":"56efcf5a34103955e43c1d3be7fd58843efdc8095187d74dc890cf3342863f55","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","close_proposal.py":"9a6927722ada8eaba720ff13168101244880da3fe6f2c95f653bc3840ef81756","commission.py":"f4495d6e3d2b9c50e72e339e9571eacd9b3628ebebe7c86c601b94e785a5c9fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","controller_socket.py":"10519cc775e963360870eac51c7fcac1ffb988b04d5de89dac1dbf3524ba6531","custody_fault.py":"7b1e96d1085d5fe5acd1ca35867a5d657093191984763477ebcfcb054dbb59cb","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"a3662539a9a130f5272cbd8b3750be3ebb46d4ad903aba7afa10880f99a2f601","family_harness.py":"0e0a42be6cf75dfb3f674b26cbdfbb4c473edea71083dfaad89ecb40dec039ba","family_operations.py":"37dca5e6ed97a5edbff3408663589258a3db2aac400b2d9e12ae8f603f61bda1","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","installed_submit.mjs":"9d57a91c4a052fbb9103582689ee99a6d087758dcfee00defa4c762b87187468","installed_submit.py":"f9151c2dffa1a02327b0ba05bdeb180654918a2b913195185a6649d010783dc7","journey_session.py":"3c807ce45dcabe3b39d63333872af3746fe9276aacf5eba30bf903b51d80dfef","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"580fa1db01a6fa7691d618f123f9117ce39b25e6478460ceac46c1e650d6b454","network_fault.py":"94340720d8601f79ac77b95d1e855be25195c19b67db3103bbf054d82c02472b","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","production_environment.py":"4afa2491624b0dfbc44fba868474415628d18f1493f8e6c772f108eccd1390da","production_journey.py":"179b93aa525ddd73ad1b3e9fcf38eeb540173845025707aed6b9fa9a44e4aad8","production_setup.py":"6ed9488e59514cde495aed9f5efde604c69bf416112759ec24ae36eb79070003","provider_readback.py":"d576768208985b3544f146597d181d796f2a5e2eca5026dae3fa15cadcfe65b2","resource_io.py":"b0ed0223fd11a1a28c25278de539a9b2ed63881b26a8e00e386f25d4d9aa9384","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","retained_author.py":"bfd01c7df44f5f525326dfbda13b5ebc6b854f15787a8b2923de883fe20fdcf9","sign_release.py":"d0aa7697cc6889538dfd54f9101a5b7bc2e8f7aede729da2d382b6466781df99","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489","tls_fault.py":"10e125f9623bc32a420a1d83e6d46fe30aa1ca8ff4da97a3e2422fc0e11ec42d"},"source_recipe_sha256":"c0f21ff1d3c8e344fee20a9a0c25bb14a264417ed53418ad536789a6096fb16e"} \ No newline at end of file diff --git a/qualification/families/stripe-platform-refund-v1/contract.json b/qualification/families/stripe-platform-refund-v1/contract.json index 1fa5718b9..e03b39ade 100644 --- a/qualification/families/stripe-platform-refund-v1/contract.json +++ b/qualification/families/stripe-platform-refund-v1/contract.json @@ -1 +1 @@ -{"api_release":"2025-03-31.basil","corpus_manifest_sha256":"8d88635d501b670d76aa605a8f6129c7f806c0a50ece01177df5a22ad04cf585","declarations":{"idempotency_sha256":"425a0dca2f279765debfc847c4a01bff60fea5be68dd9d761ae6bb60ce0b8a7b","observation_sha256":"d0ce5a34d987821c69c0a839d9ed66805c625f8324dd42031fcccf0752a8821e","recovery_sha256":"bf2303abce165c175360ac975586431bbc4cf03167489ea317a27de2f0b04abb","retention_sha256":"846c2164e26d1144d9aa146034b4f7ea4dc305136a59ffd94f999d19f2c360ee"},"environment_class":"provider-test-mode","manual_assumptions":["Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","Stripe idempotency is tested only inside the declared 86400-second retention interval.","Stripe test mode and the installed platform are checked by the declared guard on each lease.","The 50-percent payment basis is a read, not an atomic provider balance reservation.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths."],"oracle_version":"auths-reviewed-reference-v2","provider":"stripe","schema":"auths.provider-contract/1"} \ No newline at end of file +{"api_release":"2025-03-31.basil","corpus_manifest_sha256":"e19803b375a796ed3169be6d23e3029e95382866f8b3be5ca45fdf725f9ce54b","declarations":{"idempotency_sha256":"425a0dca2f279765debfc847c4a01bff60fea5be68dd9d761ae6bb60ce0b8a7b","observation_sha256":"d0ce5a34d987821c69c0a839d9ed66805c625f8324dd42031fcccf0752a8821e","recovery_sha256":"bf2303abce165c175360ac975586431bbc4cf03167489ea317a27de2f0b04abb","retention_sha256":"846c2164e26d1144d9aa146034b4f7ea4dc305136a59ffd94f999d19f2c360ee"},"environment_class":"provider-test-mode","manual_assumptions":["Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","Stripe idempotency is tested only inside the declared 86400-second retention interval.","Stripe test mode and the installed platform are checked by the declared guard on each lease.","The 50-percent payment basis is a read, not an atomic provider balance reservation.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths."],"oracle_version":"auths-reviewed-reference-v2","provider":"stripe","schema":"auths.provider-contract/1"} \ No newline at end of file diff --git a/qualification/families/stripe-platform-refund-v1/corpus-manifest.json b/qualification/families/stripe-platform-refund-v1/corpus-manifest.json index 8bbf177cf..fd87b3630 100644 --- a/qualification/families/stripe-platform-refund-v1/corpus-manifest.json +++ b/qualification/families/stripe-platform-refund-v1/corpus-manifest.json @@ -1 +1 @@ -{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"a72c557b69103a52eb477deb8364ded53cd58407b9ba7ab33ccbda74389fec1e","family":"stripe-platform-refund-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"99901e36cb7c4f5882897603c874698d582e859b5d6b08d53cd80975e89aa01c","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","application_probe.py":"5e2dd6a91eb0a2acf2df1079cead5bd67ae5d6743abce6e48201e7326f63daa2","artifact_wait.py":"56efcf5a34103955e43c1d3be7fd58843efdc8095187d74dc890cf3342863f55","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","close_proposal.py":"9a6927722ada8eaba720ff13168101244880da3fe6f2c95f653bc3840ef81756","commission.py":"f4495d6e3d2b9c50e72e339e9571eacd9b3628ebebe7c86c601b94e785a5c9fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","controller_socket.py":"10519cc775e963360870eac51c7fcac1ffb988b04d5de89dac1dbf3524ba6531","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"b614b12b0789afb2ce4f4b81618db8d6e2333a8b52ec76fc96fbba1be715ee68","family_harness.py":"0e0a42be6cf75dfb3f674b26cbdfbb4c473edea71083dfaad89ecb40dec039ba","family_operations.py":"8ab354fdf5f2eaab9c061ab967935c76b861a388541bc36fbcf9da5a9a630012","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","installed_submit.mjs":"9d57a91c4a052fbb9103582689ee99a6d087758dcfee00defa4c762b87187468","installed_submit.py":"f9151c2dffa1a02327b0ba05bdeb180654918a2b913195185a6649d010783dc7","journey_session.py":"3c807ce45dcabe3b39d63333872af3746fe9276aacf5eba30bf903b51d80dfef","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"580fa1db01a6fa7691d618f123f9117ce39b25e6478460ceac46c1e650d6b454","network_fault.py":"94340720d8601f79ac77b95d1e855be25195c19b67db3103bbf054d82c02472b","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","production_environment.py":"4afa2491624b0dfbc44fba868474415628d18f1493f8e6c772f108eccd1390da","production_journey.py":"179b93aa525ddd73ad1b3e9fcf38eeb540173845025707aed6b9fa9a44e4aad8","production_setup.py":"6ed9488e59514cde495aed9f5efde604c69bf416112759ec24ae36eb79070003","provider_readback.py":"d576768208985b3544f146597d181d796f2a5e2eca5026dae3fa15cadcfe65b2","resource_io.py":"b0ed0223fd11a1a28c25278de539a9b2ed63881b26a8e00e386f25d4d9aa9384","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","retained_author.py":"bfd01c7df44f5f525326dfbda13b5ebc6b854f15787a8b2923de883fe20fdcf9","sign_release.py":"d0aa7697cc6889538dfd54f9101a5b7bc2e8f7aede729da2d382b6466781df99","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489","tls_fault.py":"10e125f9623bc32a420a1d83e6d46fe30aa1ca8ff4da97a3e2422fc0e11ec42d"},"source_recipe_sha256":"b1972d556f28433932a449636755077f7ee485ef90cca412f153bc7f18881368"} \ No newline at end of file +{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"a72c557b69103a52eb477deb8364ded53cd58407b9ba7ab33ccbda74389fec1e","family":"stripe-platform-refund-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"99901e36cb7c4f5882897603c874698d582e859b5d6b08d53cd80975e89aa01c","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","application_probe.py":"5e2dd6a91eb0a2acf2df1079cead5bd67ae5d6743abce6e48201e7326f63daa2","artifact_wait.py":"56efcf5a34103955e43c1d3be7fd58843efdc8095187d74dc890cf3342863f55","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","close_proposal.py":"9a6927722ada8eaba720ff13168101244880da3fe6f2c95f653bc3840ef81756","commission.py":"f4495d6e3d2b9c50e72e339e9571eacd9b3628ebebe7c86c601b94e785a5c9fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","controller_socket.py":"10519cc775e963360870eac51c7fcac1ffb988b04d5de89dac1dbf3524ba6531","custody_fault.py":"7b1e96d1085d5fe5acd1ca35867a5d657093191984763477ebcfcb054dbb59cb","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"a3662539a9a130f5272cbd8b3750be3ebb46d4ad903aba7afa10880f99a2f601","family_harness.py":"0e0a42be6cf75dfb3f674b26cbdfbb4c473edea71083dfaad89ecb40dec039ba","family_operations.py":"37dca5e6ed97a5edbff3408663589258a3db2aac400b2d9e12ae8f603f61bda1","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","installed_submit.mjs":"9d57a91c4a052fbb9103582689ee99a6d087758dcfee00defa4c762b87187468","installed_submit.py":"f9151c2dffa1a02327b0ba05bdeb180654918a2b913195185a6649d010783dc7","journey_session.py":"3c807ce45dcabe3b39d63333872af3746fe9276aacf5eba30bf903b51d80dfef","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"580fa1db01a6fa7691d618f123f9117ce39b25e6478460ceac46c1e650d6b454","network_fault.py":"94340720d8601f79ac77b95d1e855be25195c19b67db3103bbf054d82c02472b","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","production_environment.py":"4afa2491624b0dfbc44fba868474415628d18f1493f8e6c772f108eccd1390da","production_journey.py":"179b93aa525ddd73ad1b3e9fcf38eeb540173845025707aed6b9fa9a44e4aad8","production_setup.py":"6ed9488e59514cde495aed9f5efde604c69bf416112759ec24ae36eb79070003","provider_readback.py":"d576768208985b3544f146597d181d796f2a5e2eca5026dae3fa15cadcfe65b2","resource_io.py":"b0ed0223fd11a1a28c25278de539a9b2ed63881b26a8e00e386f25d4d9aa9384","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","retained_author.py":"bfd01c7df44f5f525326dfbda13b5ebc6b854f15787a8b2923de883fe20fdcf9","sign_release.py":"d0aa7697cc6889538dfd54f9101a5b7bc2e8f7aede729da2d382b6466781df99","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489","tls_fault.py":"10e125f9623bc32a420a1d83e6d46fe30aa1ca8ff4da97a3e2422fc0e11ec42d"},"source_recipe_sha256":"b1972d556f28433932a449636755077f7ee485ef90cca412f153bc7f18881368"} \ No newline at end of file diff --git a/qualification/reference/README.md b/qualification/reference/README.md index 8044d9e6a..4080fd4e5 100644 --- a/qualification/reference/README.md +++ b/qualification/reference/README.md @@ -259,7 +259,7 @@ verification remain separate. Retained copies are independently rescanned before the runner can upload them. Failed setup invalidates proposals, keeps scan canaries, and attempts all owned cleanup with native credential collection before retiring the renewing workload identity. These entry points still need -the remaining custody-drift case handlers and successful protected execution; +successful protected execution and partial-install cleanup recovery; they do not establish a passing protected qualification. `author_operator.py` runs in the same credential-free installed environment as @@ -365,3 +365,20 @@ the native assembler then re-verifies the evidence closure and must reconstruct identical record bytes. All families pass before the release key is read. The signing process executes its own native builds only and separately scans the exact retained release with its real key canary before publication. + +`custody_fault.py` exercises only the current credential derived from the +native installation journal under the retained operator workload identity. +Generation drift prepares a real unpublished successor, removes the current +generation, and proves there is no fallback. Commitment drift recreates the +owned secret with wrong bytes under its original immutable version. Version +drift stores the original bytes under a different real immutable version. +Each failure must be the actual native before-admission refusal with zero +counted leases and provider entries. The exact original credential/version is +restored and checked through native status even when submission fails. A +durable private restoration obligation precedes deletion and remains on failure. +No shared connection, attempt, qualification state or host floor is edited. +The plaintext-kind probe invokes the shipping install command with empty stdin +and requires its exact production-policy refusal before a state directory exists. +These are disposable AWS fixture mutations, never application credential inputs +or a provider test response substituted for AWS. They establish the precise +before-admission boundary, not a fabricated post-claim lease failure. diff --git a/qualification/reference/custody_fault.py b/qualification/reference/custody_fault.py new file mode 100644 index 000000000..902f2bec7 --- /dev/null +++ b/qualification/reference/custody_fault.py @@ -0,0 +1,190 @@ +"""Disposable AWS custody drift under the retained operator identity. + +Only the current secret derived from this installation's native journal can be +changed. The shared connection, host floors, qualification and attempt state +remain untouched. No remote enumeration or caller-selected name is accepted. +""" + +from contextlib import contextmanager +import base64 +import os +from pathlib import Path +import re +import subprocess +import time + +from common import closed, Refusal, require, sha256 +from expand import decode, read +from production_setup import GATEWAY_UID, KMS_KEY, REGION, private_file, native_output +from resource_io import write, write_bytes + + +def reference(namespace, connection, generation, secret): + require(type(namespace) is str and re.fullmatch(r'[a-z][a-z0-9-]{0,63}', namespace) + and type(connection) is str and re.fullmatch(r'conn_[A-Za-z0-9_-]{22}', connection) + and type(generation) is int and 1 <= generation < 1 << 64 + and type(secret) is bytes and 0 < len(secret) <= 65536, 'qualification.custody.reference') + decoded = base64.urlsafe_b64decode(connection[5:] + '==') + require(len(decoded) == 16 and base64.urlsafe_b64encode(decoded).rstrip(b'=').decode() == connection[5:], + 'qualification.custody.reference') + number = generation.to_bytes(8, 'big') + commitment = sha256(b'auths.connection-credential-store/1\0' + connection.encode() + number + secret) + name = 'auths-gateway/' + sha256(b'auths.gateway-secret-name/1\0' + namespace.encode() + + b'\0' + connection.encode() + b'\0' + number) + version = sha256(b'auths.gateway-secret-version/1\0' + connection.encode() + b'\0' + + number + bytes.fromhex(commitment)) + return name, version, commitment + + +class Faults: + def __init__(self, deployment): + require(os.getuid() == 0, 'qualification.custody.identity') + self.deployment = deployment + self.root = deployment.private / 'custody-faults' + require(not self.root.exists(), 'qualification.custody.directory') + self.root.mkdir(mode=0o700) + self.generation = 0 + + def api(self, operation, arguments, *, required=True): + require(operation in ['describe-secret', 'delete-secret', 'create-secret'], + 'qualification.custody.operation') + supplied = self.deployment.environment(administrative=True) + environment = {'PATH': '/usr/local/bin:/usr/bin:/bin', + 'AWS_ROLE_ARN': supplied['AWS_ROLE_ARN'], + 'AWS_WEB_IDENTITY_TOKEN_FILE': supplied['AWS_WEB_IDENTITY_TOKEN_FILE'], + 'AWS_REGION': REGION, 'AWS_DEFAULT_REGION': REGION, 'AWS_EC2_METADATA_DISABLED': 'true', + 'AWS_CONFIG_FILE': '/nonexistent-auths-aws-config', + 'AWS_SHARED_CREDENTIALS_FILE': '/nonexistent-auths-aws-credentials', + 'AWS_PAGER': '', 'AWS_CLI_AUTO_PROMPT': 'off', 'AWS_MAX_ATTEMPTS': '1'} + result = subprocess.run(['aws', '--no-cli-pager', '--region', REGION, + '--cli-connect-timeout', '5', '--cli-read-timeout', '10', 'secretsmanager', operation, + *map(str, arguments)], cwd='/', stdin=subprocess.DEVNULL, capture_output=True, + timeout=30, env=environment) + require(len(result.stdout) <= 65536 and len(result.stderr) <= 65536 + and all(canary not in result.stdout + result.stderr for canary in self.deployment.canaries), + 'qualification.custody.private-output') + if result.returncode != 0: + require(not required, 'qualification.custody.aws-refused') + if b'(ResourceNotFoundException)' in result.stderr: + return {'missing': True} + return None + return decode(result.stdout) + + def present(self, name, version): + value = self.api('describe-secret', ['--secret-id', name]) + require(value.get('Name') == name and type(value.get('VersionIdsToStages')) is dict + and version in value['VersionIdsToStages'] and not value.get('DeletedDate'), + 'qualification.custody.exact-version') + + def delete(self, name): + value = self.api('delete-secret', ['--secret-id', name, '--force-delete-without-recovery'], required=False) + require(value is not None and (value.get('Name') == name or value == {'missing': True}), + 'qualification.custody.exact-name') + + def create(self, name, version, payload): + # AWS may retain a force-deleted name briefly. Retries select identical + # immutable bytes and the same explicit version, never another secret. + for attempt in range(4): + value = self.api('create-secret', ['--name', name, '--client-request-token', version, + '--kms-key-id', KMS_KEY, '--secret-binary', 'fileb://' + str(payload)], required=False) + if value is not None and value != {'missing': True}: + require(value.get('Name') == name and value.get('VersionId') == version, + 'qualification.custody.exact-version') + self.present(name, version) + return + if attempt < 3: + time.sleep(2) + raise Refusal('qualification.custody.restore-required') + + def current(self, credential): + state = self.deployment.state(0) + notes = decode(read(private_file(state / 'credential-journal.json', GATEWAY_UID), 4096)) + closed(notes, ['schema', 'connection_id', 'generations']) + require(notes['schema'] == 'auths.gateway-credential-journal/1' + and type(notes['generations']) is list and 1 <= len(notes['generations']) <= 64 + and all(type(value) is int and 1 <= value < 1 << 64 for value in notes['generations']) + and notes['generations'] == sorted(set(notes['generations'])), 'qualification.custody.journal') + response = self.deployment.command(['status', '--state-dir', state]) + require(response.get('ok') is True and response.get('code') == 'gateway.admin.status', + 'qualification.custody.native-status') + status = response['status'] + generation = status['credential_generation'] + require(status['state'] == 'active' and status['credential_held'] is True and status['in_flight'] == 0 + and generation in notes['generations'] and status['generation'] >= generation, + 'qualification.custody.current-credential') + name, version, commitment = reference(self.deployment.namespace, notes['connection_id'], generation, credential) + self.present(name, version) + return notes['connection_id'], generation, name, version, commitment + + @contextmanager + def drift(self, kind, credential, successor): + require(kind in ['generation', 'commitment', 'version'] and credential != successor + and credential in self.deployment.canaries and successor in self.deployment.canaries, + 'qualification.custody.fault') + connection, generation, name, version, _commitment = self.current(credential) + self.generation += 1 + private = self.root / str(self.generation) + private.mkdir(mode=0o700) + original, altered = private / 'original', private / 'altered' + write_bytes(original, credential, new=True) + replacement_version = version + if kind == 'generation': + response = self.deployment.command(['rotate-prepare', '--state-dir', self.deployment.state(0), + '--credential-stdin', '--operator-process'], administrative=True, secret=successor + b'\n') + next_name, next_version, next_commitment = reference(self.deployment.namespace, connection, + generation + 1, successor) + require(response.get('ok') is True and response.get('code') == 'gateway.admin.rotation-prepared' + and response.get('commitment') == next_commitment, 'qualification.custody.prepared-generation') + self.present(next_name, next_version) + elif kind == 'commitment': + write_bytes(altered, b'qualification-fixture-incorrect-credential-bytes', new=True) + else: + # The same authorized bytes under a different actual immutable + # version cannot satisfy the exact recorded version request. + replacement_version = ('0' if version[0] != '0' else '1') + version[1:] + write_bytes(altered, credential, new=True) + # Retain the exact restoration obligation before the first deletion. + write(private / 'obligation.json', {'schema': 'auths.qualification-custody-restoration/1', + 'connection_id': connection, 'generation': generation, 'name': name, 'version': version, + 'kind': kind, 'restored': False}, new=True) + deleted = False + try: + # A transport exception can follow an accepted delete, so every + # attempted deletion creates an unconditional restoration duty. + deleted = True + self.delete(name) + if kind != 'generation': + self.create(name, replacement_version, altered) + yield + finally: + if deleted: + if kind != 'generation': + self.delete(name) + self.create(name, version, original) + restored = self.current(credential) + require(restored[:4] == (connection, generation, name, version), + 'qualification.custody.restoration-binding') + write(private / 'obligation.json', {'schema': 'auths.qualification-custody-restoration/1', + 'connection_id': connection, 'generation': generation, 'name': name, 'version': version, + 'kind': kind, 'restored': True}) + original.unlink(missing_ok=True) + altered.unlink(missing_ok=True) + + def kind(self): + state = self.deployment.gateway / 'refused-plaintext-install' + require(not state.exists(), 'qualification.custody.directory') + arguments = ['install', '--state-dir', state, + '--recipe', self.deployment.gateway / 'recipe.json', + '--profile-lock', self.deployment.gateway / 'profile.lock.json', + '--trusted-context', self.deployment.gateway / 'context-0.cbor', + '--approve-digest', self.deployment.tuple['compiled_recipe_sha256'], + '--provider', self.deployment.provider, '--alias', 'qualification', + '--join', + '--credential-stdin', '--deployment', 'production', '--credential-store', 'local-file-v1'] + result = subprocess.run([str(self.deployment.binary), *map(str, arguments)], input=b'', + capture_output=True, timeout=30, cwd='/', user=GATEWAY_UID, group=GATEWAY_UID, + extra_groups=[], env=self.deployment.environment()) + native_output(result, self.deployment.canaries, required=False) + require(result.returncode == 1 and result.stdout == b'' + and result.stderr == b'gateway.credential.production-plaintext-refused\n' + and not state.exists(), 'qualification.custody.kind-not-refused') diff --git a/qualification/reference/family_corpus.py b/qualification/reference/family_corpus.py index b4f846c74..7d94b24a4 100644 --- a/qualification/reference/family_corpus.py +++ b/qualification/reference/family_corpus.py @@ -169,11 +169,10 @@ def add(phase, identifier, scenario, steps, capabilities=()): [step('probe', 'refused', 'gateway.verify.invalid-input')]) for kind, scenario in [('kind', 'store-kind-drift'), ('generation', 'generation-drift'), ('commitment', 'commitment-drift'), ('version', 'external-version-drift')]: - # Before-entry connection binding probes and actual post-claim - # custody-version failures are distinct measured boundaries. - leases = 1 if kind in ['commitment', 'version'] else 0 + # The real AWS adapter authenticates the exact immutable version + # and bytes during holds(), before admission or a counted lease. add(phase, 'custody-' + kind, scenario, - [step('probe', 'complete', 'custody-' + kind + '-refused', leases=leases)]) + [step('probe', 'complete', 'custody-' + kind + '-refused')]) if reference is stripe_platform: for kind, code in [('ceiling', 'gateway.relative-ceiling.above'), ('currency', 'gateway.relative-ceiling.binding-mismatch')]: diff --git a/qualification/reference/family_operations.py b/qualification/reference/family_operations.py index 8c3566840..e4661f6e8 100644 --- a/qualification/reference/family_operations.py +++ b/qualification/reference/family_operations.py @@ -13,6 +13,7 @@ import airtable_record import stripe_platform +from custody_fault import Faults from common import canonical, closed, Refusal, require, sha256 from expand import child, decode, read from native_observation import Effects, result as native_result @@ -54,6 +55,7 @@ def __init__(self, deployment, author, oracle, resources, reviewed): self.consumer_node = None self.consumer_script = None self.budget_refusals = set() + self.custody_faults = None def configure_consumers(self, python, kit): self.consumer_python, self.consumer_kit = Path(python).absolute(), Path(kit).absolute() @@ -377,6 +379,41 @@ def rotate(self): self.current_credential = successor return self.completed_probe('provider-secret-rotated', before, self.deployment.witness(0)) + def custody(self, phase, kind): + require(kind in ['kind', 'generation', 'commitment', 'version'] and self.rotation_keys is not None, + 'qualification.operations.custody-input') + if self.custody_faults is None: + self.custody_faults = Faults(self.deployment) + before = self.deployment.witness(0) + if kind == 'kind': + self.custody_faults.kind() + after = self.deployment.witness(0) + else: + successor = next(key for key in self.rotation_keys if key != self.current_credential) + handoff, packet = self.packet(phase + '-custody-' + kind) + with self.custody_faults.drift(kind, self.current_credential, successor): + if phase == 'commissioning': + execution = self.deployment.commissioning_submit(handoff, packet) + result, before, after = execution['result'], execution['before'], execution['after'] + else: + result = self.deployment.application_submit(handoff, packet) + after = self.deployment.witness(0) + require(native_result(result) == ('refused', 'gateway.connection.credential-generation-missing', None), + 'qualification.operations.custody-not-refused') + counted = measure.delta(before, after) + require(counted['credential_lease_calls'] == counted['write_transport_entries'] == 0, + 'qualification.operations.custody-entered') + report = {'schema': 'auths.qualification-custody-probe/1', 'family': self.family, + 'protected_run': self.resources['protected_run'], 'phase': phase, 'kind': kind, + 'native_code': 'gateway.credential.production-plaintext-refused' if kind == 'kind' + else 'gateway.connection.credential-generation-missing', + 'credential_leases': counted['credential_lease_calls'], 'provider_entries': counted['write_transport_entries'], + 'fixture_edits_to_connection_or_host_floors': 0} + directory = self.deployment.work / 'custody-probes' + directory.mkdir(mode=0o700, exist_ok=True) + resource_io.write(directory / (phase + '-' + kind + '.json'), report, new=True) + return self.completed_probe('custody-' + kind + '-refused', before, after) + def hostile(self, phase, identifier): label = phase + '-13' handoff, packet = self.packet(label) @@ -603,6 +640,9 @@ def step(self, case, index, operation): require(self.reference is stripe_platform and index == 0 and operation == 'probe', 'qualification.operations.step') result = self.guard(phase, identifier) + elif identifier in ['custody-kind', 'custody-generation', 'custody-commitment', 'custody-version']: + require(index == 0 and operation == 'probe', 'qualification.operations.step') + result = self.custody(phase, identifier.removeprefix('custody-')) elif identifier in ['forged', 'altered']: require(index == 0 and operation == 'probe', 'qualification.operations.step') result = self.hostile(phase, identifier) diff --git a/qualification/reference/generate_families.py b/qualification/reference/generate_families.py index 0f7154cff..06dbe1f6b 100644 --- a/qualification/reference/generate_families.py +++ b/qualification/reference/generate_families.py @@ -18,7 +18,7 @@ REFERENCE = ROOT / 'qualification/reference' SOURCES_TO_PIN = ['family_corpus.py', 'family_harness.py', 'family_operations.py', 'packet_plan.py', 'author_packets.py', 'author_socket.py', 'retained_author.py', 'author_operator.py', 'production_setup.py', - 'network_fault.py', 'production_environment.py', 'production_journey.py', 'journey_session.py', + 'network_fault.py', 'production_environment.py', 'production_journey.py', 'journey_session.py', 'custody_fault.py', 'controller_socket.py', 'application_probe.py', 'installed_submit.py', 'installed_submit.mjs', 'common.py', 'fresh_evidence.py', 'native_observation.py', 'measure.py', 'provider_readback.py', 'resource_io.py', 'resource_summary.py', 'expand.py', 'stripe_platform.py', 'airtable_record.py', 'stripe_resources.py', 'airtable_resources.py'] diff --git a/qualification/reference/tests/test_custody_fault.py b/qualification/reference/tests/test_custody_fault.py new file mode 100644 index 000000000..9f3563b76 --- /dev/null +++ b/qualification/reference/tests/test_custody_fault.py @@ -0,0 +1,91 @@ +"""Bounded custody fixture obligations; no AWS or provider calls.""" + +from pathlib import Path +import sys +import tempfile +from types import SimpleNamespace +import unittest +from unittest.mock import patch + +sys.path.insert(0, str(Path(__file__).resolve().parents[1])) +import custody_fault as custody +from common import Refusal +from expand import decode + +CONNECTION = 'conn_AAAAAAAAAAAAAAAAAAAAAA' +FIRST = b'qualification-fixture-first-credential' +SECOND = b'qualification-fixture-second-credential' + + +class Reference(unittest.TestCase): + def test_every_coordinate_is_bound_and_noncanonical_connection_is_refused(self): + first = custody.reference('test-namespace', CONNECTION, 1, FIRST) + self.assertTrue(first[0].startswith('auths-gateway/')) + self.assertEqual([len(value) for value in first], [78, 64, 64]) + self.assertNotEqual(first, custody.reference('other-namespace', CONNECTION, 1, FIRST)) + self.assertNotEqual(first, custody.reference('test-namespace', CONNECTION, 2, FIRST)) + changed = custody.reference('test-namespace', CONNECTION, 1, SECOND) + self.assertEqual(first[0], changed[0]) + self.assertNotEqual(first[1:], changed[1:]) + for connection in [CONNECTION + '=', CONNECTION[:-1] + 'B', '../../secret', 'conn_' + 'a' * 32]: + with self.assertRaises(Refusal): custody.reference('test-namespace', connection, 1, FIRST) + for generation in [True, 0, -1, 1 << 64]: + with self.assertRaises(Refusal): custody.reference('test-namespace', CONNECTION, generation, FIRST) + + +class Restoration(unittest.TestCase): + def fixture(self, root): + value = object.__new__(custody.Faults) + value.root, value.generation = root, 0 + value.deployment = SimpleNamespace(canaries=[FIRST, SECOND], namespace='test-namespace') + value.current = lambda credential: (CONNECTION, 1, *custody.reference('test-namespace', CONNECTION, 1, credential)) + return value + + def test_wrong_bytes_use_the_original_version_then_always_restore_exact_bytes(self): + with tempfile.TemporaryDirectory() as temporary: + value = self.fixture(Path(temporary)) + events = [] + value.delete = lambda name: events.append(('delete', name)) + value.create = lambda name, version, payload: events.append(('create', name, version, payload.read_bytes())) + with self.assertRaisesRegex(Refusal, 'qualification.fixture.submission-failed'): + with value.drift('commitment', FIRST, SECOND): + events.append(('submit',)) + raise Refusal('qualification.fixture.submission-failed') + self.assertEqual([event[0] for event in events], ['delete', 'create', 'submit', 'delete', 'create']) + self.assertEqual(events[1][1:3], events[4][1:3]) + self.assertNotEqual(events[1][3], FIRST) + self.assertEqual(events[4][3], FIRST) + self.assertFalse((value.root / '1/original').exists()) + self.assertTrue(decode((value.root / '1/obligation.json').read_bytes())['restored']) + + def test_same_bytes_use_a_distinct_real_version_and_original_version_is_restored(self): + with tempfile.TemporaryDirectory() as temporary: + value = self.fixture(Path(temporary)) + events = [] + value.delete = lambda name: None + value.create = lambda name, version, payload: events.append((name, version, payload.read_bytes())) + with value.drift('version', FIRST, SECOND): pass + self.assertEqual(events[0][0], events[1][0]) + self.assertNotEqual(events[0][1], events[1][1]) + self.assertEqual(events[0][2], events[1][2]) + + def test_ambiguous_delete_still_requires_restoration_and_failure_keeps_obligation(self): + with tempfile.TemporaryDirectory() as temporary: + value = self.fixture(Path(temporary)) + with patch.object(value, 'delete', side_effect=[Refusal('qualification.custody.aws-refused'), None]), \ + patch.object(value, 'create', side_effect=Refusal('qualification.custody.restore-required')): + with self.assertRaisesRegex(Refusal, 'restore-required'): + with value.drift('commitment', FIRST, SECOND): self.fail('delete was refused') + self.assertEqual((value.root / '1/original').read_bytes(), FIRST) + self.assertFalse(decode((value.root / '1/obligation.json').read_bytes())['restored']) + + def test_absent_exact_owned_name_is_idempotent_but_other_failures_are_not(self): + value = object.__new__(custody.Faults) + with patch.object(value, 'api', return_value={'missing': True}): value.delete('owned-fixture-name') + for response in [None, {'Name': 'another-fixture-name'}]: + with patch.object(value, 'api', return_value=response): + with self.assertRaises(Refusal): value.delete('owned-fixture-name') + + +if __name__ == '__main__': + unittest.main() From cbab9c0505bb0330f78389c991977d52fe9cc5ef Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 18:46:10 +0100 Subject: [PATCH 099/108] Retain interrupted install cleanup without relaxing execution floors --- docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md | 12 ++++ .../auths-gateway/semantic-closure.json | 2 +- .../auths-gateway/src/bin/auths-gateway.rs | 27 ++++---- .../runtime/auths-gateway/src/connection.rs | 23 ++++++- product/runtime/auths-gateway/src/engine.rs | 66 ++++++++++++++++++- .../auths-gateway/src/semantic_closure.rs | 2 +- .../airtable-record-update-v1/contract.json | 2 +- .../corpus-manifest.json | 2 +- .../stripe-platform-refund-v1/contract.json | 2 +- .../corpus-manifest.json | 2 +- qualification/reference/README.md | 12 +++- qualification/reference/custody_fault.py | 48 ++++++++++++-- .../reference/production_environment.py | 22 +++---- qualification/reference/production_journey.py | 12 +++- qualification/reference/production_setup.py | 2 + .../reference/tests/test_custody_fault.py | 31 ++++++++- .../reference/tests/test_journey_session.py | 29 ++++++++ 17 files changed, 256 insertions(+), 40 deletions(-) diff --git a/docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md b/docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md index 6c88061b0..c42db3210 100644 --- a/docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md +++ b/docs/operations/GATEWAY_PRODUCTION_RUNBOOK.md @@ -30,6 +30,18 @@ a deletion error does not undo revocation. Never turn unknown into failure or submit the operation again. Database failure means no durable stop can be claimed; isolate app ingress at the host firewall and retain the incident. +Install retains the authenticated recipe, trust, operator statement and custody +configuration before creating a credential. Their presence is cleanup input, +not proof that install completed: a missing or damaged host floor still refuses +every execution lease. If an interrupted install committed its connection, +explicitly revoke it through the store-only command, then collect its journal. +Collection can read that irreversibly revoked record without accepting a +damaged or missing execution floor; it still requires the exact journal, +fixed retirement delay and unchanged shared record, and never repairs the floor. +Active or disabled connections keep the normal floor requirement. If no +connection committed, retain the journal as an orphan cleanup obligation; +never infer deletion from a failed install command. + ## Provider-secret rotation For the web-identity reference, the operator configuration must explicitly diff --git a/product/runtime/auths-gateway/semantic-closure.json b/product/runtime/auths-gateway/semantic-closure.json index 5b0e63b68..0e15e713c 100644 --- a/product/runtime/auths-gateway/semantic-closure.json +++ b/product/runtime/auths-gateway/semantic-closure.json @@ -1 +1 @@ -{"files":[{"path":"Cargo.lock","sha256":"0e75e2fdef44e79e57797ac6661295ae58ddb8de4a1990a6fd22ce6c54f78604"},{"path":"Cargo.toml","sha256":"6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24"},{"path":"core/adapters/auths-did-keri/Cargo.toml","sha256":"86ba3e3f9a0a70d970568bfb3113b7ba7bbdd81c3eebbb52743dd574a0c0ecaa"},{"path":"core/adapters/auths-did-keri/src/lib.rs","sha256":"a75674842f8a7142004369ccd206ab43e476459293f0ff4bed4d4e659031b3e3"},{"path":"core/adapters/auths-did-key/Cargo.toml","sha256":"d5a3ae07ecde83f91eed4c3785051dd0f44eab6c891754f3309b6b40596707d7"},{"path":"core/adapters/auths-did-key/src/lib.rs","sha256":"b76a3f4528a725df53cfa9242e6e414e1d26caa48468aaed497e28b121f4497c"},{"path":"core/adapters/auths-raw-key/Cargo.toml","sha256":"f49616bc18c19e6aaa7e6a02ccebcdb9f5c1422c1278ef9869e0dbf22ceda7be"},{"path":"core/adapters/auths-raw-key/src/lib.rs","sha256":"45eec1b295dac3bed65cd79c942870b926b06b3f5d38eaebaeb6140ac69315fa"},{"path":"core/crates/auths-algebra-kernel/Cargo.toml","sha256":"0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba"},{"path":"core/crates/auths-algebra-kernel/src/generated.rs","sha256":"ae4bcbef42a408c7ffa0c6a74a42f7de177a6f14479e51d205acf830bda05960"},{"path":"core/crates/auths-algebra-kernel/src/lib.rs","sha256":"6654667eeb9b353d6648954c9fd2e8838462a82ce6b2803eb49e1366892c68c6"},{"path":"core/crates/auths-assurance/Cargo.toml","sha256":"afcb12a97ddd09d7a264b9ecd3fcaefc865ff2c9b4539ee85b00883420ba333a"},{"path":"core/crates/auths-assurance/src/lib.rs","sha256":"0fb2ec844d674b25a9e20b1601452c89c2454901fa506adfa9bb38ef9a7fa213"},{"path":"core/crates/auths-author/Cargo.toml","sha256":"1e6f0e3bc079ddb558decf0db26b291c6e72fc47327b6df1b7650d41689b215f"},{"path":"core/crates/auths-author/src/lib.rs","sha256":"e14475f2f49715a1869d5fa6b11ff1fbb72497e39097e09f833b0bae7e5b3f2b"},{"path":"core/crates/auths-author/src/observations.rs","sha256":"dda7d6bfa6f4bd7e95a480ca283c2c0e996f69c5c15cb0c7197af328131a7066"},{"path":"core/crates/auths-authority/Cargo.toml","sha256":"4f68212938029f79ebd857b4f3038494eb85d0163d49f07e51376715cf959815"},{"path":"core/crates/auths-authority/src/lib.rs","sha256":"da88d5194de4e17449e69972c0fb042afa3c39798a8f570f30771e77c384f1eb"},{"path":"core/crates/auths-codec/Cargo.toml","sha256":"e20e51826e17814effd9d8925d18d5fbdd6c0d37bf50231e743ec2611314722c"},{"path":"core/crates/auths-codec/src/approval.rs","sha256":"fbff43bf4d57f69f8b7738a8647751cde75c5a932dee65d924a1fe9c7202f91f"},{"path":"core/crates/auths-codec/src/bounded_policy.rs","sha256":"d21f6728be2d8a04b6d94921f2b683f7e61cbb42e0ac6866f1c88a49caa534c3"},{"path":"core/crates/auths-codec/src/decode.rs","sha256":"ba2999584cdf53b1b517ecb9c7ea50d39efee17c666a9a38e2ad1ac94379f778"},{"path":"core/crates/auths-codec/src/encode.rs","sha256":"8491192053e2e15d62b4d2a491de22405b7487ead69ab6f6bca40669ce7ca5f7"},{"path":"core/crates/auths-codec/src/error.rs","sha256":"fecb0737c16deb42d859f1dc7727c698438d9ac12064fd99e0024629642c390c"},{"path":"core/crates/auths-codec/src/hash.rs","sha256":"f88e111f1dbb2cef6b7b5e9c948cb45ff92e366710c8a5f5c636138aa748479e"},{"path":"core/crates/auths-codec/src/lib.rs","sha256":"3b0e5c94c6f34f750b88a9333e1d5c8145746d845d3a23e0d2f61807cf592ea7"},{"path":"core/crates/auths-codec/src/observation.rs","sha256":"38328b0c71ff97a4196eeade8b4faa889527ff1f80bb168468bcd49082a3987e"},{"path":"core/crates/auths-composition/Cargo.toml","sha256":"331e13025eb82588b5269ed3975929eb41c823d588c49e4c296273d85c6fe80e"},{"path":"core/crates/auths-composition/src/lib.rs","sha256":"e42e3b0b6a9985b73c533aeb23799c638979aa27a9ce7d0f10a8d60340570fb1"},{"path":"core/crates/auths-model/Cargo.toml","sha256":"565c15302b0cc9270db1e28efa3862804846850ba933cc17aea8abcec4a65987"},{"path":"core/crates/auths-model/src/approval.rs","sha256":"54cf44a9ef747ec21546a4086aecfb130bc7803b0d646430e6082df51e6e305f"},{"path":"core/crates/auths-model/src/bounded.rs","sha256":"f90496abc0a06c028b4d850af6ddab7d850bfafeaa3d042f1b1246a41d8bbbc9"},{"path":"core/crates/auths-model/src/bounded_policy.rs","sha256":"306a8f049cc7cfc7635fe0e4de47eb7813eed63d3c14c3be2b51586aa4eea450"},{"path":"core/crates/auths-model/src/lib.rs","sha256":"e7cfe6bb9574c6b016aa63e70658c31e0b90903ec6479a49f4a2ceb64f5bad97"},{"path":"core/crates/auths-model/src/observation.rs","sha256":"b3ed3e3cc090afca2896a7d3de7988afccc1ee1ea0ebd91b51a8bc0f20ad8dbb"},{"path":"core/crates/auths-multikey/Cargo.toml","sha256":"858756c1197befcada06134742bffe8d58cf674cadd6c046bf710570e96efaf2"},{"path":"core/crates/auths-multikey/src/lib.rs","sha256":"f5177fffb11e40eeaaa665ba886c541fc1f24d5eacdd6983fb03dc20148733f0"},{"path":"core/crates/auths-ports/Cargo.toml","sha256":"596a9b0f5af3717c16a6d13f7054d8a106bcd9f01f5f72c2235dd2afcf0ab16c"},{"path":"core/crates/auths-ports/src/binding.rs","sha256":"a16c012d40aa4249e3ec54372b9611006d0bfe8c7dc3c741911c2194ad17736d"},{"path":"core/crates/auths-ports/src/diagnostics.rs","sha256":"aa596572503b5a65a918bb2ff38281c144ff53821ee914e9325c852828d852df"},{"path":"core/crates/auths-ports/src/lib.rs","sha256":"8da1debf86f9532df0660155d04298beb1ba3a1204508f8586e2e67cd2fb3449"},{"path":"core/crates/auths-ports/src/path.rs","sha256":"b68fc547b4e4d97a60cbbc1cc1939fc6b34a8233b81f840bd396914a707e3ea1"},{"path":"core/crates/auths-raw-key-core/Cargo.toml","sha256":"98c0bc8527a537512e43a74dd6ba9658c6f0cdc16610cf938e3f9b43785d836d"},{"path":"core/crates/auths-raw-key-core/src/lib.rs","sha256":"98c0500c41697aae28708ad0bf970b9a97583d96a3d2c18d23e7fa351e0f7d12"},{"path":"core/crates/auths-registries/Cargo.toml","sha256":"590e49e58b0622d9d6274fea46796dcdb07dec9550eff295cce6a6427ffa51e2"},{"path":"core/crates/auths-registries/src/lib.rs","sha256":"450d3886d85ee333b7e046317fb5b47cde62483d5f3e41d46265e2caf4c373ec"},{"path":"core/crates/auths-registries/src/template.rs","sha256":"1224039dd2b3ce6fa8357613d8cafbae40400493da7176da202b9ade62fa05e4"},{"path":"core/crates/auths-signature-core/Cargo.toml","sha256":"6bee2230eb30af1be0bd5c2d57bd3e1903497a70028d47290d4ac6e9e0e8bca0"},{"path":"core/crates/auths-signature-core/src/lib.rs","sha256":"6e3f9311ded5e49ea50d445eb21e6d8fa12442aa4362a73e0cb6fda15b7cd865"},{"path":"core/crates/auths-signature/Cargo.toml","sha256":"7f7b5682466ba439d8c59579022cb61068cad9fb4bd2d73e1cc21327c902b450"},{"path":"core/crates/auths-signature/src/lib.rs","sha256":"b3d9ac4cc3ba0797b9e1c09f2d6ac05089b25dac4e285a5af28c0165b33d925b"},{"path":"core/crates/auths-verifier/Cargo.toml","sha256":"c43358e06a33324b41a8b93e5cc7279c55f7d21f1f6cfaa539a3fc7b4c27a38f"},{"path":"core/crates/auths-verifier/src/approval.rs","sha256":"c3cae6a49e169051eb555bb092b1069a4d422516d6a2114623a89e5f31ff923f"},{"path":"core/crates/auths-verifier/src/causal.rs","sha256":"9635230f33b13a263573d319ac8a1976addbcc07677514a43e3c7bf28dc04587"},{"path":"core/crates/auths-verifier/src/lib.rs","sha256":"f22dec38dfa47ced8da4f605390da8453273bee1da010f57fd1fdfcb10e0b389"},{"path":"core/crates/auths-verifier/src/observation.rs","sha256":"0bb07f06a0f9524c88427df1c972b1de8ba038a9eeeb15d3134c25125ae84b1e"},{"path":"core/crates/auths-verifier/src/trace.rs","sha256":"2213d72023a1d9e0413a2cf2c51c3dad9e04775d86033a0caaa9d29a8f0036f8"},{"path":"exchange/crates/auths-proof-exchange-model/Cargo.toml","sha256":"34b2db64f93a288e942b5a3918d28cdcbef906e0dc9074ce848018d3d5f7a1fa"},{"path":"exchange/crates/auths-proof-exchange-model/src/lib.rs","sha256":"49fac5aff2339d3a57c41cb8bb2a82852538e8f77ecc4b157c88e264ff31fb55"},{"path":"exchange/crates/auths-proof-exchange-port/Cargo.toml","sha256":"7ff660f1b7579dc570c791090aeb450404fbbf44c92781e289f5ccdde746d739"},{"path":"exchange/crates/auths-proof-exchange-port/src/lib.rs","sha256":"b408fb40c6432edc1facb3d8b3e9433a033f8dc73fe2e0ba5a88c972ca675021"},{"path":"product/config/auths-config/Cargo.toml","sha256":"e4b568ab9f6d84f7d7e6d66443fe825f360db9c27bc7c31d6ddc0647ba3ab304"},{"path":"product/config/auths-config/src/lib.rs","sha256":"fecf00ea65cef9018fda9af2063326d7065b869266d0d9e73a4f06816f1102cc"},{"path":"product/errors/auths-errors/Cargo.toml","sha256":"3b3a199b6460ba75bda84475bb5accd35e1485448a3981038db85bf4772dd350"},{"path":"product/errors/auths-errors/src/lib.rs","sha256":"7feeb9069fa4003f94f1f07c1c94619cf1c883e0dbaaf2187f04d0f742264bdd"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/Cargo.toml","sha256":"716f1f2a117d6d69d8effe9ee9057e24ba3502f20af6a602b06facb638cdabed"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/api.rs","sha256":"9ea61dd7ddd93282b073b98e453e6b75b26dc49689c04e9782435d06a3a09e48"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/clock.rs","sha256":"73f0a6e0f5903883329fa6683f5888288f759512ac69e5c87efd2b6b87f7d79f"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/http.rs","sha256":"14c1fce14e24c984b2a275563a29b6326fb08367922b6e8d37ba38b9cb81aa2b"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/identity.rs","sha256":"186de11230c8b33375951c4368609f8976bf9795f171af3fd7fac26207a94361"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs","sha256":"0b4617d044f5254a5ab22f5a2578f91cc025206a8c1845be39c1c56dcdf7a5df"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/names.rs","sha256":"41bb23572d6002e23ee103d6fe70ecd68764861c6f2e48a1c53af998270a4afa"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs","sha256":"39fed883f4802e68d3b41a68fea0aba0737810996b33d13577de70faba004c29"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/store.rs","sha256":"fc60ee9c49b2f4f063c449b4c78100c5c4872779e94ca168f796603b380ef6e4"},{"path":"product/integrations/auths-custody/Cargo.toml","sha256":"1e14034185ad1ec24a977fd5f41d0abee219606245c046ce2a82287fadef448b"},{"path":"product/integrations/auths-custody/src/conformance.rs","sha256":"8ed1afd58f18fc6becc268908aa6419c9aa404c79da0197963eb2599df44acf6"},{"path":"product/integrations/auths-custody/src/key.rs","sha256":"70cbb0fd21b6f5652157845a22c35be2d0f6c05b3d138fc4b9bb6dbdc3d81c40"},{"path":"product/integrations/auths-custody/src/lib.rs","sha256":"8ee593c1f59b0fd2126bdda9138026f5bc531beb64d4489a99785842e7b98b43"},{"path":"product/operations/auths-operations/Cargo.toml","sha256":"73dde1e914ba5e1386f8d49c0d730423cc72ae77ec44c6554a6a75cc8e8922b1"},{"path":"product/operations/auths-operations/src/explanation.rs","sha256":"b4a39bcbd5712cb9e735ee7deeb281f3fa6af5ddca973735bf3d87dce427ef11"},{"path":"product/operations/auths-operations/src/lib.rs","sha256":"3f401a56555113b98f57bca172a2660eaecedf76247b83a3fdbb089c133a29cd"},{"path":"product/operations/auths-operations/src/render/json.rs","sha256":"2ae042639960afee123730e945d373bc5dda1d2b3af20ae16c939a7e99b9e418"},{"path":"product/operations/auths-operations/src/render/mod.rs","sha256":"b3b7f6fe473f49227ace5a68bfc3d8dc14b5db8dd9888fd9e207070337b1b8bf"},{"path":"product/operations/auths-operations/src/render/text.rs","sha256":"f216cf3bdb00e264523271b16e7059535ac6b1aabf271cebd7935af155e4bfec"},{"path":"product/policy/auths-bounded-policy/Cargo.toml","sha256":"babd5d200923137ead71d8c2528f847cea323ce98da942a1320b054436612c47"},{"path":"product/policy/auths-bounded-policy/src/arithmetic.rs","sha256":"75e43c5d4eab8d1f71c1daf53839f5f9fe45a400afc1f63a30c6f55ce3632627"},{"path":"product/policy/auths-bounded-policy/src/commitment.rs","sha256":"c5706f2d583454e1a7f570f7ada138d4d864bef0205dfae7c1296774f396bb3f"},{"path":"product/policy/auths-bounded-policy/src/eligibility.rs","sha256":"c9acdfb793074e687fc36efad506be27dbd99ffbf40387bc66c8de39ef238432"},{"path":"product/policy/auths-bounded-policy/src/identifier.rs","sha256":"0006a32bae9eb16c4178cf797df418d2b0a781f2bc6474b741dc1a908141831c"},{"path":"product/policy/auths-bounded-policy/src/kernel.rs","sha256":"99187c28b161ac70bee1afed60711f7f645adb4d1671a01863f9849b369811d5"},{"path":"product/policy/auths-bounded-policy/src/lib.rs","sha256":"76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c"},{"path":"product/policy/auths-bounded-policy/src/receipt.rs","sha256":"3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad"},{"path":"product/policy/auths-bounded-policy/src/registry.rs","sha256":"4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0"},{"path":"product/profiles/auths-profile-api/Cargo.toml","sha256":"7ae85761f58625b5d678f961fd052eebf3e000ef565c7312e3ac857763c0017f"},{"path":"product/profiles/auths-profile-api/src/lib.rs","sha256":"a194b82b20bf8aa864c2334ef6c6aec30b2154ded972862252d5dcefa488ab95"},{"path":"product/profiles/auths-profile-mcp/Cargo.toml","sha256":"db264fc25242f7b7e4133cbe5782545b3107b406c87168ae072683cfb59eac66"},{"path":"product/profiles/auths-profile-mcp/src/arguments.rs","sha256":"a5de696586d507e2aee4a49fee99ef1ef4c51a2e46603f8838f1af6d9009833f"},{"path":"product/profiles/auths-profile-mcp/src/lib.rs","sha256":"d0f8b733a09ef8408336cdebc8948d6a5861012ce6878598b11be7084dfd4280"},{"path":"product/profiles/auths-profile-mcp/src/session.rs","sha256":"166c281fa66333388e4760d6098dad02d3359e1d5de4b8f93312c014f97abb03"},{"path":"product/qualification/auths-recipe-qualification/Cargo.toml","sha256":"b7b15b30b9a3d96d4f089d514266d3a892de6608d30707aa44be31cca89ca9fe"},{"path":"product/qualification/auths-recipe-qualification/src/canonical.rs","sha256":"30a9b50777f0dcb4b606abfee2467d5a975d9f6ad941ab6c13ca3df5b359f667"},{"path":"product/qualification/auths-recipe-qualification/src/closure.rs","sha256":"0ad6aee9bd981e2863fa725f209ec84031db2ff12f4c7ac3aaf5120f0bb86039"},{"path":"product/qualification/auths-recipe-qualification/src/commissioning.rs","sha256":"db135c55e4e3079a73253ebae275536523eb36b545d1c152b4d7dce3c6b76828"},{"path":"product/qualification/auths-recipe-qualification/src/commissioning/tests.rs","sha256":"4dde3736d206099b1bea4c14e0092c6c1287d1af9065958777d7c54331dd8686"},{"path":"product/qualification/auths-recipe-qualification/src/error.rs","sha256":"52d5cf720a1e4579008fdda90a3ac2c31f0b8db57985f121f65e54b4da2b7dd1"},{"path":"product/qualification/auths-recipe-qualification/src/evidence.rs","sha256":"ba45a7409d67a8af26ab811af306412014557477a101ab2a8eb0faf8f2bd4b91"},{"path":"product/qualification/auths-recipe-qualification/src/ids.rs","sha256":"e81a906d571497ab2da753e1532d4443706410e0b75fdd59a7d2d788c7aec403"},{"path":"product/qualification/auths-recipe-qualification/src/launch.rs","sha256":"41f2e2de90e1e7d6440a66eda3eb9bea8d5e0741bc232305a76a363ab5f813c1"},{"path":"product/qualification/auths-recipe-qualification/src/lib.rs","sha256":"0e24b0f81191df0d078c7f4d73ced784ba9472372bfcdff3c7d0e2fb1687b323"},{"path":"product/qualification/auths-recipe-qualification/src/model.rs","sha256":"3484eb0ec287b23d4682ade7b1b0f8d1335985b3fb180f06fc28716076957d5f"},{"path":"product/qualification/auths-recipe-qualification/src/release.rs","sha256":"ec478e53f70052e566aac7e15be2f9e1b1cd46837ac6990ae955fa864d311586"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/mod.rs","sha256":"fa23a962fd90331152eed5edbcdf271955f7aed79b8da1e065bfe69a20b487a9"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/schemas.rs","sha256":"c59feec2805621f341a90f81fc005e2c12f7a70f9d264fdeacccb2be4fe1c046"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/verification.rs","sha256":"bdf5746fed4d10a7f577f7878619a917d29aa8b7d522f00d9f774e53eff4c8c1"},{"path":"product/qualification/auths-recipe-qualification/src/verify.rs","sha256":"2ec2784435d11e07295de77b2ee1b2c48b2fcf9609a00454c6e7374b621aed5c"},{"path":"product/receipts/auths-receipts/Cargo.toml","sha256":"6001fa1375899953aafcb07c23a6da0c8f57ea7ec08bb9c950b12a60a8cc6f0f"},{"path":"product/receipts/auths-receipts/src/disclosure.rs","sha256":"ba9ed439be0a320c8a01f5b6e9b51361c1a37e076947490d8e4a484ba6bb119c"},{"path":"product/receipts/auths-receipts/src/lib.rs","sha256":"547a57c4160256719cafb7d0ab972d9fc80b0da14fbbce4148c70c414070ff36"},{"path":"product/runtime/auths-connections/Cargo.toml","sha256":"babeb6e1dda3dfb66291713ce1e43dce5c349833d0b50ea4dccbf986030026b2"},{"path":"product/runtime/auths-connections/src/credential.rs","sha256":"82921413bb053f0f6c7931fbd4e6a86c8cc1d8c6b51debd9c2cef33a8d5b1c51"},{"path":"product/runtime/auths-connections/src/kernel.rs","sha256":"a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8"},{"path":"product/runtime/auths-connections/src/lib.rs","sha256":"79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22"},{"path":"product/runtime/auths-connections/src/model.rs","sha256":"de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77"},{"path":"product/runtime/auths-connections/src/registry.rs","sha256":"e57640e003e72ad3235c567c2bb944a262bd64e673f023b62ea091094cc7e946"},{"path":"product/runtime/auths-gateway-kernel/Cargo.toml","sha256":"34f864e67656af4ac7e5c7a347a23f01fc8ab31365b8e23c0ef474483b14a183"},{"path":"product/runtime/auths-gateway-kernel/src/construct.rs","sha256":"e9d65744bae273d65face4285e5d2da75c06a92ab48f7b8333d496604e31c63c"},{"path":"product/runtime/auths-gateway-kernel/src/lib.rs","sha256":"cfda6f8453426564c085475f183b6f790b438768a19668f1b65d33ba59dc8632"},{"path":"product/runtime/auths-gateway-kernel/src/order.rs","sha256":"e0045f877c4b7fe3860c291039853885064ddcdebba7c9b345ab65e81e646dda"},{"path":"product/runtime/auths-gateway-kernel/src/outcome.rs","sha256":"e9785b1afe70788c89b51b18655bcd5acff7b0c8e3d12fb79c6f05a202e67e6b"},{"path":"product/runtime/auths-gateway-kernel/src/ratio.rs","sha256":"7ace22264812e6fc1ef3a62afee402cf43494bb71ae0d3de219ad1b39d690bcb"},{"path":"product/runtime/auths-gateway-kernel/src/recovery.rs","sha256":"9f46dcd1685ab6e4d1ba04a3fc286a9f3afee8fb47829be1fbc670a7926a2dc6"},{"path":"product/runtime/auths-gateway-kernel/src/transition.rs","sha256":"cefb8f01d915880f6921f2501ff881ad94b9de61072c34d9cd19220992f97374"},{"path":"product/runtime/auths-gateway/Cargo.toml","sha256":"00b28be86921dcdc0ad90cce0c62c2961cafefe96ea6c2edf0e926c3d405ccad"},{"path":"product/runtime/auths-gateway/src/admin.rs","sha256":"0dee40a9fb67c5de10142fc37a7bbabdd8979fb0199fb26caf4bdb024e0a5a40"},{"path":"product/runtime/auths-gateway/src/app.rs","sha256":"6f80f63833ea0815bb44fbf3b0cc54624a08e9fb578b035819f2980dc04e8256"},{"path":"product/runtime/auths-gateway/src/audit.rs","sha256":"0edb2037eb7b5d6f13acfce85c54f62a82bf7fdd31bc7e626c4fec183cef61dd"},{"path":"product/runtime/auths-gateway/src/audit_tests.rs","sha256":"990969384a52d75bc2489d9d412a9e7dd814bca1c8f65c701d6205fae62a15d5"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway-harness.rs","sha256":"12b0c24d36b2e6a3be392d3c081a783b355fdd67dc5b54bacc0410e803116b8c"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway.rs","sha256":"6031dca90667d2db39a78736b23e27dd4790a7887d2230bd57f6851754603a11"},{"path":"product/runtime/auths-gateway/src/binding.rs","sha256":"663b0ce878319511aa7d05722ab4ab2fa9be18817884ffb2ee9f131ff1e382d1"},{"path":"product/runtime/auths-gateway/src/bounds.rs","sha256":"38251ad6f22f9d07ef9a219c79fa265ca36f1526eca5f147d7efa46b52ad609d"},{"path":"product/runtime/auths-gateway/src/bounds_aggregate_tests.rs","sha256":"ab34f227b7c8692ba1da88ccb32bb3687a66adf8353d8282fae905d4a88eb612"},{"path":"product/runtime/auths-gateway/src/bounds_tests.rs","sha256":"74136bc570da7b9338b5a1a1ed9d3fd892c55135160964f9d3ac0e2cf5741375"},{"path":"product/runtime/auths-gateway/src/commissioning_budget.rs","sha256":"fab29da3269438cc62330f3eab7b5bd4dc482b4db8af243aae47df5d3aa1deb8"},{"path":"product/runtime/auths-gateway/src/commissioning_budget/tests.rs","sha256":"da104a1643c37515deec6397bca6db2054f2c9158ec3d230a1b1ec9c7d0f659f"},{"path":"product/runtime/auths-gateway/src/commissioning_floor.rs","sha256":"7fa6991c5ccd5ae1403be84b3da390323fab09f36e15ac01fd7a38ea350c6fdb"},{"path":"product/runtime/auths-gateway/src/commissioning_floor/tests.rs","sha256":"6b663d6e556adc0b455b81845bc4394d82c6c4de0c5f43e1310f3ddc6e4e40f7"},{"path":"product/runtime/auths-gateway/src/commissioning_session.rs","sha256":"24b48d5eaeaaa3c620e2dfc7ee1f9255fc4519a1eb404b8608cea7af6a910ee2"},{"path":"product/runtime/auths-gateway/src/commissioning_session/tests.rs","sha256":"37a097fc8a9261d3fffdaef3f905f40b22e3e6601bb5101fadd9414f963c0824"},{"path":"product/runtime/auths-gateway/src/connection.rs","sha256":"7b5d049c258a26ed1c93ecf860f51d051a8a65f9b93554af0b1ea93862398ec9"},{"path":"product/runtime/auths-gateway/src/credential_journal.rs","sha256":"7297fccaee5cd8622928e8e0a42bba50da7941970a6f682ecd300c41ee6509da"},{"path":"product/runtime/auths-gateway/src/echo_verify.rs","sha256":"6d453051665f823abd7354d5c50031d9524cf47d6092d2f09080ae814e3b9575"},{"path":"product/runtime/auths-gateway/src/engine.rs","sha256":"1abff20b98bc894c45bfc5c4414c81a99966d1ec95d924a5b0cd6f4c5626ca24"},{"path":"product/runtime/auths-gateway/src/execution_witness.rs","sha256":"e8b1a8e41d5e3fa309760067849d390ef065feeb46701a83391832645a2f000c"},{"path":"product/runtime/auths-gateway/src/fuzzing.rs","sha256":"ed3b0028487eb546a3b0a91d115aa8f18bcea324b61620bfe8e35a9e6ab18758"},{"path":"product/runtime/auths-gateway/src/generation_floor.rs","sha256":"fe1510ec96ce0f67e9a78edbfa94b33eb7df64c0ac4d0a67901124dcd0164777"},{"path":"product/runtime/auths-gateway/src/harness.rs","sha256":"c87e479f3eb281960f6c9c80d43c7560d7ccb654b0154ec823d3fcec4884ac05"},{"path":"product/runtime/auths-gateway/src/lib.rs","sha256":"fad95d031f88072dd024c78facf0bb0267562b1ac743ddd7219fce47e64024f0"},{"path":"product/runtime/auths-gateway/src/listener.rs","sha256":"aa08239bcbc1fcb55e8a212fbdf6a84f12985b0d436dcb51dc58b06e59e435f2"},{"path":"product/runtime/auths-gateway/src/observed_tests.rs","sha256":"a22be071695f89ca2578a4d82fd80d9cb82289213c9bdb8f0470f6b2dc3d9201"},{"path":"product/runtime/auths-gateway/src/observer.rs","sha256":"562ffcaea071c3856e0708dc2fe33516917e145d2438aabb75af0a2b6ba01046"},{"path":"product/runtime/auths-gateway/src/onboarding.rs","sha256":"0dfd7d67e7f02f18a28d1c86ca1b7751d7463f5efcdbe3825de0ad8cbccb3891"},{"path":"product/runtime/auths-gateway/src/operator.rs","sha256":"c3c36954a3e86723df035b47f43b85fc8ab3a6292983522b6258d5c6b4e6c4e4"},{"path":"product/runtime/auths-gateway/src/pending_vectors/attempts.rs","sha256":"47ef3c8cb1c5504d47ae9a0088705ce6715fe86bac1671a34a56fb38a64d0dd3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/bounds.rs","sha256":"e612217307e1da5b0eb5ee6582a7458bb064b8aa8a529fc6555b1b334127ab68"},{"path":"product/runtime/auths-gateway/src/pending_vectors/codes.rs","sha256":"e00670a5ef24eb856cc2c6dcda8e5a263842f55c76bb939c0c27bd9df37e5522"},{"path":"product/runtime/auths-gateway/src/pending_vectors/keys.rs","sha256":"f84c56f2ea9cb34b2b79c72d13fbf2c6585010ec1ed450af58a78c80c1ea1edd"},{"path":"product/runtime/auths-gateway/src/pending_vectors/mod.rs","sha256":"5de8340f0ef71a0b57a09e323fefe473d3160c6ae952b9ba46f714825fbacafc"},{"path":"product/runtime/auths-gateway/src/pending_vectors/outcomes.rs","sha256":"8ec07b9511b48913af36ac999d2aa0e82924289f6acb23ddaeb9f00f99815166"},{"path":"product/runtime/auths-gateway/src/pending_vectors/production.rs","sha256":"772d032e0a0d9c924fb6d6c188528db85a97e71c9e466ddc19eee277baf83614"},{"path":"product/runtime/auths-gateway/src/pending_vectors/recipes.rs","sha256":"51693208270231c25c3aef2a32151d5962114c71e86b88cb9df83181c7af83d9"},{"path":"product/runtime/auths-gateway/src/pre_entry.rs","sha256":"06ea78ca140468bfaba17d9ab04912ad68673954c3203c98fed28272ff2a00c0"},{"path":"product/runtime/auths-gateway/src/property_tests.rs","sha256":"939c081e2e154aaf10186754044bdd65608932c899b970a04a71d0afaa999a93"},{"path":"product/runtime/auths-gateway/src/qualification.rs","sha256":"c597c83de2b94f0374ae54e40a8b57c2a64ec6e254704dca32185f448a908aca"},{"path":"product/runtime/auths-gateway/src/qualification_simulation.rs","sha256":"4ee7cadfb5f46a92713c80f3e55f499cb074d04d8b21ea89d57762af38642bfa"},{"path":"product/runtime/auths-gateway/src/qualification_tests.rs","sha256":"a9178a2e58eea459d5e5dafc53a3999ea7c84dbbffefe6e5eb1f3d098827f028"},{"path":"product/runtime/auths-gateway/src/quorum_tests.rs","sha256":"a78380b019104d688c11a4410082c7e08ded3106aab099954c4f8a1b4ae0fd89"},{"path":"product/runtime/auths-gateway/src/readiness.rs","sha256":"911c3f11892f94641574375e2da4c671c802738f71082f12c39832331052d43d"},{"path":"product/runtime/auths-gateway/src/recipe.rs","sha256":"fecf9af67e7afc48d080e9f8f55f8ce28e49d0e08988717a27908bbda461d6b6"},{"path":"product/runtime/auths-gateway/src/recipe/lower.rs","sha256":"8088b8751ed831dbb48247af953c6290ac95e2a438ccd5bd65eff54be06a1fd1"},{"path":"product/runtime/auths-gateway/src/recipe/review.rs","sha256":"c3eb7d9fdd98dacf52750b14b67ad7b7faaecbbdeafff1e0b049f67d0a2d0139"},{"path":"product/runtime/auths-gateway/src/recipe/runtime.rs","sha256":"c286f0d15f974402822c0810d8e97f98411dc1c557755cc23e540d85e2bb42d9"},{"path":"product/runtime/auths-gateway/src/recipe/source.rs","sha256":"1af50298fb1461e1b24cbdf560d43124d6b1c4c529586c911b1c4797214a69ff"},{"path":"product/runtime/auths-gateway/src/recipe/tests.rs","sha256":"aac551a2481bbc60864c64079bc667dcb232e45a0f41a04073ed84ab5dbe1fce"},{"path":"product/runtime/auths-gateway/src/recipe/validate.rs","sha256":"3711b17605cb7b0d639bc1b180449231f5882a306cab20e2c7782155cc63b0d4"},{"path":"product/runtime/auths-gateway/src/scenario_tests.rs","sha256":"025b53473b3af6900e03bc2fee91aa63ed26a8778bc8c8296fe08f5540794c39"},{"path":"product/runtime/auths-gateway/src/separation.rs","sha256":"be9306848ca5d801767cf6aa14247c8618312ef0e202f00ce0c24c4844491061"},{"path":"product/runtime/auths-gateway/src/simulation_attestation.rs","sha256":"88705e5d45415f760f1e3c3a065c35c48f4f4065bf7b3feb7882246983814d6f"},{"path":"product/runtime/auths-gateway/src/store.rs","sha256":"884bcad4d70d53e12eae9c8517f6ecd0643068ee0be0370015119d04d6cc2516"},{"path":"product/runtime/auths-gateway/src/store_testkit.rs","sha256":"88d82fee42f1b8ef521e8deef0216e938ebeaad822eb2f5020e70b89d145ea70"},{"path":"product/runtime/auths-gateway/src/submit.rs","sha256":"fe2eacb5ad8152eeecbd232c47a356fc72db0098e34fda99532bdf6ef0cf895c"},{"path":"product/runtime/auths-gateway/src/support.rs","sha256":"9fd979029793a22b15d9776a7fc172476fd7c126a80d4080c65d720845becbcb"},{"path":"product/runtime/auths-gateway/src/transport.rs","sha256":"978fc9fb34a33b3db265b5d1c3ce11696a5b9f08529e46dd2a1e7bb62afb9220"},{"path":"product/runtime/auths-kernel-runtime/Cargo.toml","sha256":"926bcd0053e5edd703be8f0027ad009e2982db013c8174c1366edbf38b48087d"},{"path":"product/runtime/auths-kernel-runtime/src/lib.rs","sha256":"7108faae9ca4bc32dc093ddaf885ac8f74f3c9b8d317b7c7d0ed00d1d0ab5972"},{"path":"product/runtime/auths-lifecycle/Cargo.toml","sha256":"c5053c705f8d5554b44e432fe75287a2faf11d644e5a2552e45ad6cd94176af5"},{"path":"product/runtime/auths-lifecycle/src/codec.rs","sha256":"51c4b746749150e8bfcd8ff972b3f6c1ef40bec15583448ec1b471d9ad737dc0"},{"path":"product/runtime/auths-lifecycle/src/digest.rs","sha256":"55282cd7d8aba37713c2dcb5357c9877819edb72a30eadefb860d28d7d3a3eb7"},{"path":"product/runtime/auths-lifecycle/src/identifier.rs","sha256":"31620e8c16de68d3d2d3b84d6353c1a5b9d4151d8247f91fa389b906a8e660f1"},{"path":"product/runtime/auths-lifecycle/src/kernel.rs","sha256":"2abb8c094b36d35b364e74d78091d14c5d6f3d1eb6552cca3b5538dbd017ce23"},{"path":"product/runtime/auths-lifecycle/src/lib.rs","sha256":"afe5a345cd309b5a4f08ffba3170a6d7f16ff914892b3f2006d5208ed24ec736"},{"path":"product/runtime/auths-lifecycle/src/model.rs","sha256":"1af12bbeeeaa65ec02ddcebd7d2c8c92ec1e339fa40ae85b45ab9b01a722a4fa"},{"path":"product/runtime/auths-lifecycle/src/operation.rs","sha256":"78e6d05fcf5d7ea4f148032a3fa26fdfcab77eb346019effe927b08e0d64d732"},{"path":"product/runtime/auths-lifecycle/src/registry.rs","sha256":"53495fe6f7a77422593a41623e28716f1c140dcc1e00f87f6b0ffbfb93a5ef90"},{"path":"product/runtime/auths-lifecycle/src/sealed.rs","sha256":"2e0c03b5813c926c159598bb7890d1523825edbe57cd687d42a5dfb3374a0c19"},{"path":"product/runtime/auths-lifecycle/src/test_support.rs","sha256":"221d9a5c5ef8e1f9f8fd66927484eaf813571d0568470278ecd8fa08a5eec8cd"},{"path":"product/runtime/auths-lifecycle/src/transition.rs","sha256":"011805a28efdd541f44ccea54dd0e34a1e58f4004447ee58013703b4fb6b2822"},{"path":"product/runtime/auths-runtime/Cargo.toml","sha256":"dd29d80a8b4bb56c869f036a6c9998f6e6d1c0383ac5dc03fa42b24abe2a7ff7"},{"path":"product/runtime/auths-runtime/src/lib.rs","sha256":"132ca03d58c14905d3a822a4972f42a22a5ad33a45f2ba9ca44f3a57d810b4b0"},{"path":"product/runtime/auths-runtime/src/production.rs","sha256":"fd4eff4270c571c10fcff6cf27df28961ebf074de8a1a028f500fda1ca376820"},{"path":"product/sdk/auths-approval-quorum/Cargo.toml","sha256":"df904971fca87a24194c5816738a331588fe8f164acb5d70839a35dca5f57114"},{"path":"product/sdk/auths-approval-quorum/src/lib.rs","sha256":"72e4086088a1c0912e4e1a9e980f26a5c280bf5ab16ea39c9f0f58d5096ac2ce"},{"path":"product/sdk/auths-approval-quorum/src/remote.rs","sha256":"9fa029c7c63003adf260f8aec55160c545681c60c1bace0d934e7525862aac7b"},{"path":"product/sdk/auths-approval-quorum/src/remote_tests.rs","sha256":"8a09ce17cfee82a035a74edd535f3ebeb3db0e078784740d3997b17dbdb10197"},{"path":"product/sdk/auths-approval-quorum/src/tests.rs","sha256":"0acbf12be3e497dcc6c2d8f29c9af3b1a7ed8e11b75f6399570d4f217a785060"},{"path":"product/stores/auths-stores/Cargo.toml","sha256":"a32c4b76d17b264be5d40d24497ff237e1ed87822e8bab86229b3db93106dbe3"},{"path":"product/stores/auths-stores/src/gateway_attempt.rs","sha256":"218841602d3d9b23b44625f50e5b54cf275ccedc2d5c89f02d2482b8524472af"},{"path":"product/stores/auths-stores/src/lib.rs","sha256":"e721262edf8a9ab5568ddc27639176312d4a366203b5f73e2d7c11fde2c554e9"},{"path":"product/stores/auths-stores/src/lifecycle.rs","sha256":"3f2cecfda13fdcd7c4a944518646bcc8abd1237f900c0332d5822281f8f9f1cd"}],"schema":"auths.gateway-semantic-closure/1"} \ No newline at end of file +{"files":[{"path":"Cargo.lock","sha256":"0e75e2fdef44e79e57797ac6661295ae58ddb8de4a1990a6fd22ce6c54f78604"},{"path":"Cargo.toml","sha256":"6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24"},{"path":"core/adapters/auths-did-keri/Cargo.toml","sha256":"86ba3e3f9a0a70d970568bfb3113b7ba7bbdd81c3eebbb52743dd574a0c0ecaa"},{"path":"core/adapters/auths-did-keri/src/lib.rs","sha256":"a75674842f8a7142004369ccd206ab43e476459293f0ff4bed4d4e659031b3e3"},{"path":"core/adapters/auths-did-key/Cargo.toml","sha256":"d5a3ae07ecde83f91eed4c3785051dd0f44eab6c891754f3309b6b40596707d7"},{"path":"core/adapters/auths-did-key/src/lib.rs","sha256":"b76a3f4528a725df53cfa9242e6e414e1d26caa48468aaed497e28b121f4497c"},{"path":"core/adapters/auths-raw-key/Cargo.toml","sha256":"f49616bc18c19e6aaa7e6a02ccebcdb9f5c1422c1278ef9869e0dbf22ceda7be"},{"path":"core/adapters/auths-raw-key/src/lib.rs","sha256":"45eec1b295dac3bed65cd79c942870b926b06b3f5d38eaebaeb6140ac69315fa"},{"path":"core/crates/auths-algebra-kernel/Cargo.toml","sha256":"0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba"},{"path":"core/crates/auths-algebra-kernel/src/generated.rs","sha256":"ae4bcbef42a408c7ffa0c6a74a42f7de177a6f14479e51d205acf830bda05960"},{"path":"core/crates/auths-algebra-kernel/src/lib.rs","sha256":"6654667eeb9b353d6648954c9fd2e8838462a82ce6b2803eb49e1366892c68c6"},{"path":"core/crates/auths-assurance/Cargo.toml","sha256":"afcb12a97ddd09d7a264b9ecd3fcaefc865ff2c9b4539ee85b00883420ba333a"},{"path":"core/crates/auths-assurance/src/lib.rs","sha256":"0fb2ec844d674b25a9e20b1601452c89c2454901fa506adfa9bb38ef9a7fa213"},{"path":"core/crates/auths-author/Cargo.toml","sha256":"1e6f0e3bc079ddb558decf0db26b291c6e72fc47327b6df1b7650d41689b215f"},{"path":"core/crates/auths-author/src/lib.rs","sha256":"e14475f2f49715a1869d5fa6b11ff1fbb72497e39097e09f833b0bae7e5b3f2b"},{"path":"core/crates/auths-author/src/observations.rs","sha256":"dda7d6bfa6f4bd7e95a480ca283c2c0e996f69c5c15cb0c7197af328131a7066"},{"path":"core/crates/auths-authority/Cargo.toml","sha256":"4f68212938029f79ebd857b4f3038494eb85d0163d49f07e51376715cf959815"},{"path":"core/crates/auths-authority/src/lib.rs","sha256":"da88d5194de4e17449e69972c0fb042afa3c39798a8f570f30771e77c384f1eb"},{"path":"core/crates/auths-codec/Cargo.toml","sha256":"e20e51826e17814effd9d8925d18d5fbdd6c0d37bf50231e743ec2611314722c"},{"path":"core/crates/auths-codec/src/approval.rs","sha256":"fbff43bf4d57f69f8b7738a8647751cde75c5a932dee65d924a1fe9c7202f91f"},{"path":"core/crates/auths-codec/src/bounded_policy.rs","sha256":"d21f6728be2d8a04b6d94921f2b683f7e61cbb42e0ac6866f1c88a49caa534c3"},{"path":"core/crates/auths-codec/src/decode.rs","sha256":"ba2999584cdf53b1b517ecb9c7ea50d39efee17c666a9a38e2ad1ac94379f778"},{"path":"core/crates/auths-codec/src/encode.rs","sha256":"8491192053e2e15d62b4d2a491de22405b7487ead69ab6f6bca40669ce7ca5f7"},{"path":"core/crates/auths-codec/src/error.rs","sha256":"fecb0737c16deb42d859f1dc7727c698438d9ac12064fd99e0024629642c390c"},{"path":"core/crates/auths-codec/src/hash.rs","sha256":"f88e111f1dbb2cef6b7b5e9c948cb45ff92e366710c8a5f5c636138aa748479e"},{"path":"core/crates/auths-codec/src/lib.rs","sha256":"3b0e5c94c6f34f750b88a9333e1d5c8145746d845d3a23e0d2f61807cf592ea7"},{"path":"core/crates/auths-codec/src/observation.rs","sha256":"38328b0c71ff97a4196eeade8b4faa889527ff1f80bb168468bcd49082a3987e"},{"path":"core/crates/auths-composition/Cargo.toml","sha256":"331e13025eb82588b5269ed3975929eb41c823d588c49e4c296273d85c6fe80e"},{"path":"core/crates/auths-composition/src/lib.rs","sha256":"e42e3b0b6a9985b73c533aeb23799c638979aa27a9ce7d0f10a8d60340570fb1"},{"path":"core/crates/auths-model/Cargo.toml","sha256":"565c15302b0cc9270db1e28efa3862804846850ba933cc17aea8abcec4a65987"},{"path":"core/crates/auths-model/src/approval.rs","sha256":"54cf44a9ef747ec21546a4086aecfb130bc7803b0d646430e6082df51e6e305f"},{"path":"core/crates/auths-model/src/bounded.rs","sha256":"f90496abc0a06c028b4d850af6ddab7d850bfafeaa3d042f1b1246a41d8bbbc9"},{"path":"core/crates/auths-model/src/bounded_policy.rs","sha256":"306a8f049cc7cfc7635fe0e4de47eb7813eed63d3c14c3be2b51586aa4eea450"},{"path":"core/crates/auths-model/src/lib.rs","sha256":"e7cfe6bb9574c6b016aa63e70658c31e0b90903ec6479a49f4a2ceb64f5bad97"},{"path":"core/crates/auths-model/src/observation.rs","sha256":"b3ed3e3cc090afca2896a7d3de7988afccc1ee1ea0ebd91b51a8bc0f20ad8dbb"},{"path":"core/crates/auths-multikey/Cargo.toml","sha256":"858756c1197befcada06134742bffe8d58cf674cadd6c046bf710570e96efaf2"},{"path":"core/crates/auths-multikey/src/lib.rs","sha256":"f5177fffb11e40eeaaa665ba886c541fc1f24d5eacdd6983fb03dc20148733f0"},{"path":"core/crates/auths-ports/Cargo.toml","sha256":"596a9b0f5af3717c16a6d13f7054d8a106bcd9f01f5f72c2235dd2afcf0ab16c"},{"path":"core/crates/auths-ports/src/binding.rs","sha256":"a16c012d40aa4249e3ec54372b9611006d0bfe8c7dc3c741911c2194ad17736d"},{"path":"core/crates/auths-ports/src/diagnostics.rs","sha256":"aa596572503b5a65a918bb2ff38281c144ff53821ee914e9325c852828d852df"},{"path":"core/crates/auths-ports/src/lib.rs","sha256":"8da1debf86f9532df0660155d04298beb1ba3a1204508f8586e2e67cd2fb3449"},{"path":"core/crates/auths-ports/src/path.rs","sha256":"b68fc547b4e4d97a60cbbc1cc1939fc6b34a8233b81f840bd396914a707e3ea1"},{"path":"core/crates/auths-raw-key-core/Cargo.toml","sha256":"98c0bc8527a537512e43a74dd6ba9658c6f0cdc16610cf938e3f9b43785d836d"},{"path":"core/crates/auths-raw-key-core/src/lib.rs","sha256":"98c0500c41697aae28708ad0bf970b9a97583d96a3d2c18d23e7fa351e0f7d12"},{"path":"core/crates/auths-registries/Cargo.toml","sha256":"590e49e58b0622d9d6274fea46796dcdb07dec9550eff295cce6a6427ffa51e2"},{"path":"core/crates/auths-registries/src/lib.rs","sha256":"450d3886d85ee333b7e046317fb5b47cde62483d5f3e41d46265e2caf4c373ec"},{"path":"core/crates/auths-registries/src/template.rs","sha256":"1224039dd2b3ce6fa8357613d8cafbae40400493da7176da202b9ade62fa05e4"},{"path":"core/crates/auths-signature-core/Cargo.toml","sha256":"6bee2230eb30af1be0bd5c2d57bd3e1903497a70028d47290d4ac6e9e0e8bca0"},{"path":"core/crates/auths-signature-core/src/lib.rs","sha256":"6e3f9311ded5e49ea50d445eb21e6d8fa12442aa4362a73e0cb6fda15b7cd865"},{"path":"core/crates/auths-signature/Cargo.toml","sha256":"7f7b5682466ba439d8c59579022cb61068cad9fb4bd2d73e1cc21327c902b450"},{"path":"core/crates/auths-signature/src/lib.rs","sha256":"b3d9ac4cc3ba0797b9e1c09f2d6ac05089b25dac4e285a5af28c0165b33d925b"},{"path":"core/crates/auths-verifier/Cargo.toml","sha256":"c43358e06a33324b41a8b93e5cc7279c55f7d21f1f6cfaa539a3fc7b4c27a38f"},{"path":"core/crates/auths-verifier/src/approval.rs","sha256":"c3cae6a49e169051eb555bb092b1069a4d422516d6a2114623a89e5f31ff923f"},{"path":"core/crates/auths-verifier/src/causal.rs","sha256":"9635230f33b13a263573d319ac8a1976addbcc07677514a43e3c7bf28dc04587"},{"path":"core/crates/auths-verifier/src/lib.rs","sha256":"f22dec38dfa47ced8da4f605390da8453273bee1da010f57fd1fdfcb10e0b389"},{"path":"core/crates/auths-verifier/src/observation.rs","sha256":"0bb07f06a0f9524c88427df1c972b1de8ba038a9eeeb15d3134c25125ae84b1e"},{"path":"core/crates/auths-verifier/src/trace.rs","sha256":"2213d72023a1d9e0413a2cf2c51c3dad9e04775d86033a0caaa9d29a8f0036f8"},{"path":"exchange/crates/auths-proof-exchange-model/Cargo.toml","sha256":"34b2db64f93a288e942b5a3918d28cdcbef906e0dc9074ce848018d3d5f7a1fa"},{"path":"exchange/crates/auths-proof-exchange-model/src/lib.rs","sha256":"49fac5aff2339d3a57c41cb8bb2a82852538e8f77ecc4b157c88e264ff31fb55"},{"path":"exchange/crates/auths-proof-exchange-port/Cargo.toml","sha256":"7ff660f1b7579dc570c791090aeb450404fbbf44c92781e289f5ccdde746d739"},{"path":"exchange/crates/auths-proof-exchange-port/src/lib.rs","sha256":"b408fb40c6432edc1facb3d8b3e9433a033f8dc73fe2e0ba5a88c972ca675021"},{"path":"product/config/auths-config/Cargo.toml","sha256":"e4b568ab9f6d84f7d7e6d66443fe825f360db9c27bc7c31d6ddc0647ba3ab304"},{"path":"product/config/auths-config/src/lib.rs","sha256":"fecf00ea65cef9018fda9af2063326d7065b869266d0d9e73a4f06816f1102cc"},{"path":"product/errors/auths-errors/Cargo.toml","sha256":"3b3a199b6460ba75bda84475bb5accd35e1485448a3981038db85bf4772dd350"},{"path":"product/errors/auths-errors/src/lib.rs","sha256":"7feeb9069fa4003f94f1f07c1c94619cf1c883e0dbaaf2187f04d0f742264bdd"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/Cargo.toml","sha256":"716f1f2a117d6d69d8effe9ee9057e24ba3502f20af6a602b06facb638cdabed"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/api.rs","sha256":"9ea61dd7ddd93282b073b98e453e6b75b26dc49689c04e9782435d06a3a09e48"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/clock.rs","sha256":"73f0a6e0f5903883329fa6683f5888288f759512ac69e5c87efd2b6b87f7d79f"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/http.rs","sha256":"14c1fce14e24c984b2a275563a29b6326fb08367922b6e8d37ba38b9cb81aa2b"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/identity.rs","sha256":"186de11230c8b33375951c4368609f8976bf9795f171af3fd7fac26207a94361"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs","sha256":"0b4617d044f5254a5ab22f5a2578f91cc025206a8c1845be39c1c56dcdf7a5df"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/names.rs","sha256":"41bb23572d6002e23ee103d6fe70ecd68764861c6f2e48a1c53af998270a4afa"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs","sha256":"39fed883f4802e68d3b41a68fea0aba0737810996b33d13577de70faba004c29"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/store.rs","sha256":"fc60ee9c49b2f4f063c449b4c78100c5c4872779e94ca168f796603b380ef6e4"},{"path":"product/integrations/auths-custody/Cargo.toml","sha256":"1e14034185ad1ec24a977fd5f41d0abee219606245c046ce2a82287fadef448b"},{"path":"product/integrations/auths-custody/src/conformance.rs","sha256":"8ed1afd58f18fc6becc268908aa6419c9aa404c79da0197963eb2599df44acf6"},{"path":"product/integrations/auths-custody/src/key.rs","sha256":"70cbb0fd21b6f5652157845a22c35be2d0f6c05b3d138fc4b9bb6dbdc3d81c40"},{"path":"product/integrations/auths-custody/src/lib.rs","sha256":"8ee593c1f59b0fd2126bdda9138026f5bc531beb64d4489a99785842e7b98b43"},{"path":"product/operations/auths-operations/Cargo.toml","sha256":"73dde1e914ba5e1386f8d49c0d730423cc72ae77ec44c6554a6a75cc8e8922b1"},{"path":"product/operations/auths-operations/src/explanation.rs","sha256":"b4a39bcbd5712cb9e735ee7deeb281f3fa6af5ddca973735bf3d87dce427ef11"},{"path":"product/operations/auths-operations/src/lib.rs","sha256":"3f401a56555113b98f57bca172a2660eaecedf76247b83a3fdbb089c133a29cd"},{"path":"product/operations/auths-operations/src/render/json.rs","sha256":"2ae042639960afee123730e945d373bc5dda1d2b3af20ae16c939a7e99b9e418"},{"path":"product/operations/auths-operations/src/render/mod.rs","sha256":"b3b7f6fe473f49227ace5a68bfc3d8dc14b5db8dd9888fd9e207070337b1b8bf"},{"path":"product/operations/auths-operations/src/render/text.rs","sha256":"f216cf3bdb00e264523271b16e7059535ac6b1aabf271cebd7935af155e4bfec"},{"path":"product/policy/auths-bounded-policy/Cargo.toml","sha256":"babd5d200923137ead71d8c2528f847cea323ce98da942a1320b054436612c47"},{"path":"product/policy/auths-bounded-policy/src/arithmetic.rs","sha256":"75e43c5d4eab8d1f71c1daf53839f5f9fe45a400afc1f63a30c6f55ce3632627"},{"path":"product/policy/auths-bounded-policy/src/commitment.rs","sha256":"c5706f2d583454e1a7f570f7ada138d4d864bef0205dfae7c1296774f396bb3f"},{"path":"product/policy/auths-bounded-policy/src/eligibility.rs","sha256":"c9acdfb793074e687fc36efad506be27dbd99ffbf40387bc66c8de39ef238432"},{"path":"product/policy/auths-bounded-policy/src/identifier.rs","sha256":"0006a32bae9eb16c4178cf797df418d2b0a781f2bc6474b741dc1a908141831c"},{"path":"product/policy/auths-bounded-policy/src/kernel.rs","sha256":"99187c28b161ac70bee1afed60711f7f645adb4d1671a01863f9849b369811d5"},{"path":"product/policy/auths-bounded-policy/src/lib.rs","sha256":"76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c"},{"path":"product/policy/auths-bounded-policy/src/receipt.rs","sha256":"3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad"},{"path":"product/policy/auths-bounded-policy/src/registry.rs","sha256":"4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0"},{"path":"product/profiles/auths-profile-api/Cargo.toml","sha256":"7ae85761f58625b5d678f961fd052eebf3e000ef565c7312e3ac857763c0017f"},{"path":"product/profiles/auths-profile-api/src/lib.rs","sha256":"a194b82b20bf8aa864c2334ef6c6aec30b2154ded972862252d5dcefa488ab95"},{"path":"product/profiles/auths-profile-mcp/Cargo.toml","sha256":"db264fc25242f7b7e4133cbe5782545b3107b406c87168ae072683cfb59eac66"},{"path":"product/profiles/auths-profile-mcp/src/arguments.rs","sha256":"a5de696586d507e2aee4a49fee99ef1ef4c51a2e46603f8838f1af6d9009833f"},{"path":"product/profiles/auths-profile-mcp/src/lib.rs","sha256":"d0f8b733a09ef8408336cdebc8948d6a5861012ce6878598b11be7084dfd4280"},{"path":"product/profiles/auths-profile-mcp/src/session.rs","sha256":"166c281fa66333388e4760d6098dad02d3359e1d5de4b8f93312c014f97abb03"},{"path":"product/qualification/auths-recipe-qualification/Cargo.toml","sha256":"b7b15b30b9a3d96d4f089d514266d3a892de6608d30707aa44be31cca89ca9fe"},{"path":"product/qualification/auths-recipe-qualification/src/canonical.rs","sha256":"30a9b50777f0dcb4b606abfee2467d5a975d9f6ad941ab6c13ca3df5b359f667"},{"path":"product/qualification/auths-recipe-qualification/src/closure.rs","sha256":"0ad6aee9bd981e2863fa725f209ec84031db2ff12f4c7ac3aaf5120f0bb86039"},{"path":"product/qualification/auths-recipe-qualification/src/commissioning.rs","sha256":"db135c55e4e3079a73253ebae275536523eb36b545d1c152b4d7dce3c6b76828"},{"path":"product/qualification/auths-recipe-qualification/src/commissioning/tests.rs","sha256":"4dde3736d206099b1bea4c14e0092c6c1287d1af9065958777d7c54331dd8686"},{"path":"product/qualification/auths-recipe-qualification/src/error.rs","sha256":"52d5cf720a1e4579008fdda90a3ac2c31f0b8db57985f121f65e54b4da2b7dd1"},{"path":"product/qualification/auths-recipe-qualification/src/evidence.rs","sha256":"ba45a7409d67a8af26ab811af306412014557477a101ab2a8eb0faf8f2bd4b91"},{"path":"product/qualification/auths-recipe-qualification/src/ids.rs","sha256":"e81a906d571497ab2da753e1532d4443706410e0b75fdd59a7d2d788c7aec403"},{"path":"product/qualification/auths-recipe-qualification/src/launch.rs","sha256":"41f2e2de90e1e7d6440a66eda3eb9bea8d5e0741bc232305a76a363ab5f813c1"},{"path":"product/qualification/auths-recipe-qualification/src/lib.rs","sha256":"0e24b0f81191df0d078c7f4d73ced784ba9472372bfcdff3c7d0e2fb1687b323"},{"path":"product/qualification/auths-recipe-qualification/src/model.rs","sha256":"3484eb0ec287b23d4682ade7b1b0f8d1335985b3fb180f06fc28716076957d5f"},{"path":"product/qualification/auths-recipe-qualification/src/release.rs","sha256":"ec478e53f70052e566aac7e15be2f9e1b1cd46837ac6990ae955fa864d311586"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/mod.rs","sha256":"fa23a962fd90331152eed5edbcdf271955f7aed79b8da1e065bfe69a20b487a9"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/schemas.rs","sha256":"c59feec2805621f341a90f81fc005e2c12f7a70f9d264fdeacccb2be4fe1c046"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/verification.rs","sha256":"bdf5746fed4d10a7f577f7878619a917d29aa8b7d522f00d9f774e53eff4c8c1"},{"path":"product/qualification/auths-recipe-qualification/src/verify.rs","sha256":"2ec2784435d11e07295de77b2ee1b2c48b2fcf9609a00454c6e7374b621aed5c"},{"path":"product/receipts/auths-receipts/Cargo.toml","sha256":"6001fa1375899953aafcb07c23a6da0c8f57ea7ec08bb9c950b12a60a8cc6f0f"},{"path":"product/receipts/auths-receipts/src/disclosure.rs","sha256":"ba9ed439be0a320c8a01f5b6e9b51361c1a37e076947490d8e4a484ba6bb119c"},{"path":"product/receipts/auths-receipts/src/lib.rs","sha256":"547a57c4160256719cafb7d0ab972d9fc80b0da14fbbce4148c70c414070ff36"},{"path":"product/runtime/auths-connections/Cargo.toml","sha256":"babeb6e1dda3dfb66291713ce1e43dce5c349833d0b50ea4dccbf986030026b2"},{"path":"product/runtime/auths-connections/src/credential.rs","sha256":"82921413bb053f0f6c7931fbd4e6a86c8cc1d8c6b51debd9c2cef33a8d5b1c51"},{"path":"product/runtime/auths-connections/src/kernel.rs","sha256":"a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8"},{"path":"product/runtime/auths-connections/src/lib.rs","sha256":"79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22"},{"path":"product/runtime/auths-connections/src/model.rs","sha256":"de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77"},{"path":"product/runtime/auths-connections/src/registry.rs","sha256":"e57640e003e72ad3235c567c2bb944a262bd64e673f023b62ea091094cc7e946"},{"path":"product/runtime/auths-gateway-kernel/Cargo.toml","sha256":"34f864e67656af4ac7e5c7a347a23f01fc8ab31365b8e23c0ef474483b14a183"},{"path":"product/runtime/auths-gateway-kernel/src/construct.rs","sha256":"e9d65744bae273d65face4285e5d2da75c06a92ab48f7b8333d496604e31c63c"},{"path":"product/runtime/auths-gateway-kernel/src/lib.rs","sha256":"cfda6f8453426564c085475f183b6f790b438768a19668f1b65d33ba59dc8632"},{"path":"product/runtime/auths-gateway-kernel/src/order.rs","sha256":"e0045f877c4b7fe3860c291039853885064ddcdebba7c9b345ab65e81e646dda"},{"path":"product/runtime/auths-gateway-kernel/src/outcome.rs","sha256":"e9785b1afe70788c89b51b18655bcd5acff7b0c8e3d12fb79c6f05a202e67e6b"},{"path":"product/runtime/auths-gateway-kernel/src/ratio.rs","sha256":"7ace22264812e6fc1ef3a62afee402cf43494bb71ae0d3de219ad1b39d690bcb"},{"path":"product/runtime/auths-gateway-kernel/src/recovery.rs","sha256":"9f46dcd1685ab6e4d1ba04a3fc286a9f3afee8fb47829be1fbc670a7926a2dc6"},{"path":"product/runtime/auths-gateway-kernel/src/transition.rs","sha256":"cefb8f01d915880f6921f2501ff881ad94b9de61072c34d9cd19220992f97374"},{"path":"product/runtime/auths-gateway/Cargo.toml","sha256":"00b28be86921dcdc0ad90cce0c62c2961cafefe96ea6c2edf0e926c3d405ccad"},{"path":"product/runtime/auths-gateway/src/admin.rs","sha256":"0dee40a9fb67c5de10142fc37a7bbabdd8979fb0199fb26caf4bdb024e0a5a40"},{"path":"product/runtime/auths-gateway/src/app.rs","sha256":"6f80f63833ea0815bb44fbf3b0cc54624a08e9fb578b035819f2980dc04e8256"},{"path":"product/runtime/auths-gateway/src/audit.rs","sha256":"0edb2037eb7b5d6f13acfce85c54f62a82bf7fdd31bc7e626c4fec183cef61dd"},{"path":"product/runtime/auths-gateway/src/audit_tests.rs","sha256":"990969384a52d75bc2489d9d412a9e7dd814bca1c8f65c701d6205fae62a15d5"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway-harness.rs","sha256":"12b0c24d36b2e6a3be392d3c081a783b355fdd67dc5b54bacc0410e803116b8c"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway.rs","sha256":"3dba485deeb4d60f3f5603ad4ce9a0edf49a85c68c5c4ca072df73d2910da832"},{"path":"product/runtime/auths-gateway/src/binding.rs","sha256":"663b0ce878319511aa7d05722ab4ab2fa9be18817884ffb2ee9f131ff1e382d1"},{"path":"product/runtime/auths-gateway/src/bounds.rs","sha256":"38251ad6f22f9d07ef9a219c79fa265ca36f1526eca5f147d7efa46b52ad609d"},{"path":"product/runtime/auths-gateway/src/bounds_aggregate_tests.rs","sha256":"ab34f227b7c8692ba1da88ccb32bb3687a66adf8353d8282fae905d4a88eb612"},{"path":"product/runtime/auths-gateway/src/bounds_tests.rs","sha256":"74136bc570da7b9338b5a1a1ed9d3fd892c55135160964f9d3ac0e2cf5741375"},{"path":"product/runtime/auths-gateway/src/commissioning_budget.rs","sha256":"fab29da3269438cc62330f3eab7b5bd4dc482b4db8af243aae47df5d3aa1deb8"},{"path":"product/runtime/auths-gateway/src/commissioning_budget/tests.rs","sha256":"da104a1643c37515deec6397bca6db2054f2c9158ec3d230a1b1ec9c7d0f659f"},{"path":"product/runtime/auths-gateway/src/commissioning_floor.rs","sha256":"7fa6991c5ccd5ae1403be84b3da390323fab09f36e15ac01fd7a38ea350c6fdb"},{"path":"product/runtime/auths-gateway/src/commissioning_floor/tests.rs","sha256":"6b663d6e556adc0b455b81845bc4394d82c6c4de0c5f43e1310f3ddc6e4e40f7"},{"path":"product/runtime/auths-gateway/src/commissioning_session.rs","sha256":"24b48d5eaeaaa3c620e2dfc7ee1f9255fc4519a1eb404b8608cea7af6a910ee2"},{"path":"product/runtime/auths-gateway/src/commissioning_session/tests.rs","sha256":"37a097fc8a9261d3fffdaef3f905f40b22e3e6601bb5101fadd9414f963c0824"},{"path":"product/runtime/auths-gateway/src/connection.rs","sha256":"e8d24277d7e4a53610e091fe78b373b841245d8e59a2bc788716b76e7d912441"},{"path":"product/runtime/auths-gateway/src/credential_journal.rs","sha256":"7297fccaee5cd8622928e8e0a42bba50da7941970a6f682ecd300c41ee6509da"},{"path":"product/runtime/auths-gateway/src/echo_verify.rs","sha256":"6d453051665f823abd7354d5c50031d9524cf47d6092d2f09080ae814e3b9575"},{"path":"product/runtime/auths-gateway/src/engine.rs","sha256":"c16e9b0ead514b6357f5b09914fae9de9a8977e1a2dac20e3aefeecb1cc16ee4"},{"path":"product/runtime/auths-gateway/src/execution_witness.rs","sha256":"e8b1a8e41d5e3fa309760067849d390ef065feeb46701a83391832645a2f000c"},{"path":"product/runtime/auths-gateway/src/fuzzing.rs","sha256":"ed3b0028487eb546a3b0a91d115aa8f18bcea324b61620bfe8e35a9e6ab18758"},{"path":"product/runtime/auths-gateway/src/generation_floor.rs","sha256":"fe1510ec96ce0f67e9a78edbfa94b33eb7df64c0ac4d0a67901124dcd0164777"},{"path":"product/runtime/auths-gateway/src/harness.rs","sha256":"c87e479f3eb281960f6c9c80d43c7560d7ccb654b0154ec823d3fcec4884ac05"},{"path":"product/runtime/auths-gateway/src/lib.rs","sha256":"fad95d031f88072dd024c78facf0bb0267562b1ac743ddd7219fce47e64024f0"},{"path":"product/runtime/auths-gateway/src/listener.rs","sha256":"aa08239bcbc1fcb55e8a212fbdf6a84f12985b0d436dcb51dc58b06e59e435f2"},{"path":"product/runtime/auths-gateway/src/observed_tests.rs","sha256":"a22be071695f89ca2578a4d82fd80d9cb82289213c9bdb8f0470f6b2dc3d9201"},{"path":"product/runtime/auths-gateway/src/observer.rs","sha256":"562ffcaea071c3856e0708dc2fe33516917e145d2438aabb75af0a2b6ba01046"},{"path":"product/runtime/auths-gateway/src/onboarding.rs","sha256":"0dfd7d67e7f02f18a28d1c86ca1b7751d7463f5efcdbe3825de0ad8cbccb3891"},{"path":"product/runtime/auths-gateway/src/operator.rs","sha256":"c3c36954a3e86723df035b47f43b85fc8ab3a6292983522b6258d5c6b4e6c4e4"},{"path":"product/runtime/auths-gateway/src/pending_vectors/attempts.rs","sha256":"47ef3c8cb1c5504d47ae9a0088705ce6715fe86bac1671a34a56fb38a64d0dd3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/bounds.rs","sha256":"e612217307e1da5b0eb5ee6582a7458bb064b8aa8a529fc6555b1b334127ab68"},{"path":"product/runtime/auths-gateway/src/pending_vectors/codes.rs","sha256":"e00670a5ef24eb856cc2c6dcda8e5a263842f55c76bb939c0c27bd9df37e5522"},{"path":"product/runtime/auths-gateway/src/pending_vectors/keys.rs","sha256":"f84c56f2ea9cb34b2b79c72d13fbf2c6585010ec1ed450af58a78c80c1ea1edd"},{"path":"product/runtime/auths-gateway/src/pending_vectors/mod.rs","sha256":"5de8340f0ef71a0b57a09e323fefe473d3160c6ae952b9ba46f714825fbacafc"},{"path":"product/runtime/auths-gateway/src/pending_vectors/outcomes.rs","sha256":"8ec07b9511b48913af36ac999d2aa0e82924289f6acb23ddaeb9f00f99815166"},{"path":"product/runtime/auths-gateway/src/pending_vectors/production.rs","sha256":"772d032e0a0d9c924fb6d6c188528db85a97e71c9e466ddc19eee277baf83614"},{"path":"product/runtime/auths-gateway/src/pending_vectors/recipes.rs","sha256":"51693208270231c25c3aef2a32151d5962114c71e86b88cb9df83181c7af83d9"},{"path":"product/runtime/auths-gateway/src/pre_entry.rs","sha256":"06ea78ca140468bfaba17d9ab04912ad68673954c3203c98fed28272ff2a00c0"},{"path":"product/runtime/auths-gateway/src/property_tests.rs","sha256":"939c081e2e154aaf10186754044bdd65608932c899b970a04a71d0afaa999a93"},{"path":"product/runtime/auths-gateway/src/qualification.rs","sha256":"c597c83de2b94f0374ae54e40a8b57c2a64ec6e254704dca32185f448a908aca"},{"path":"product/runtime/auths-gateway/src/qualification_simulation.rs","sha256":"4ee7cadfb5f46a92713c80f3e55f499cb074d04d8b21ea89d57762af38642bfa"},{"path":"product/runtime/auths-gateway/src/qualification_tests.rs","sha256":"a9178a2e58eea459d5e5dafc53a3999ea7c84dbbffefe6e5eb1f3d098827f028"},{"path":"product/runtime/auths-gateway/src/quorum_tests.rs","sha256":"a78380b019104d688c11a4410082c7e08ded3106aab099954c4f8a1b4ae0fd89"},{"path":"product/runtime/auths-gateway/src/readiness.rs","sha256":"911c3f11892f94641574375e2da4c671c802738f71082f12c39832331052d43d"},{"path":"product/runtime/auths-gateway/src/recipe.rs","sha256":"fecf9af67e7afc48d080e9f8f55f8ce28e49d0e08988717a27908bbda461d6b6"},{"path":"product/runtime/auths-gateway/src/recipe/lower.rs","sha256":"8088b8751ed831dbb48247af953c6290ac95e2a438ccd5bd65eff54be06a1fd1"},{"path":"product/runtime/auths-gateway/src/recipe/review.rs","sha256":"c3eb7d9fdd98dacf52750b14b67ad7b7faaecbbdeafff1e0b049f67d0a2d0139"},{"path":"product/runtime/auths-gateway/src/recipe/runtime.rs","sha256":"c286f0d15f974402822c0810d8e97f98411dc1c557755cc23e540d85e2bb42d9"},{"path":"product/runtime/auths-gateway/src/recipe/source.rs","sha256":"1af50298fb1461e1b24cbdf560d43124d6b1c4c529586c911b1c4797214a69ff"},{"path":"product/runtime/auths-gateway/src/recipe/tests.rs","sha256":"aac551a2481bbc60864c64079bc667dcb232e45a0f41a04073ed84ab5dbe1fce"},{"path":"product/runtime/auths-gateway/src/recipe/validate.rs","sha256":"3711b17605cb7b0d639bc1b180449231f5882a306cab20e2c7782155cc63b0d4"},{"path":"product/runtime/auths-gateway/src/scenario_tests.rs","sha256":"025b53473b3af6900e03bc2fee91aa63ed26a8778bc8c8296fe08f5540794c39"},{"path":"product/runtime/auths-gateway/src/separation.rs","sha256":"be9306848ca5d801767cf6aa14247c8618312ef0e202f00ce0c24c4844491061"},{"path":"product/runtime/auths-gateway/src/simulation_attestation.rs","sha256":"88705e5d45415f760f1e3c3a065c35c48f4f4065bf7b3feb7882246983814d6f"},{"path":"product/runtime/auths-gateway/src/store.rs","sha256":"884bcad4d70d53e12eae9c8517f6ecd0643068ee0be0370015119d04d6cc2516"},{"path":"product/runtime/auths-gateway/src/store_testkit.rs","sha256":"88d82fee42f1b8ef521e8deef0216e938ebeaad822eb2f5020e70b89d145ea70"},{"path":"product/runtime/auths-gateway/src/submit.rs","sha256":"fe2eacb5ad8152eeecbd232c47a356fc72db0098e34fda99532bdf6ef0cf895c"},{"path":"product/runtime/auths-gateway/src/support.rs","sha256":"9fd979029793a22b15d9776a7fc172476fd7c126a80d4080c65d720845becbcb"},{"path":"product/runtime/auths-gateway/src/transport.rs","sha256":"978fc9fb34a33b3db265b5d1c3ce11696a5b9f08529e46dd2a1e7bb62afb9220"},{"path":"product/runtime/auths-kernel-runtime/Cargo.toml","sha256":"926bcd0053e5edd703be8f0027ad009e2982db013c8174c1366edbf38b48087d"},{"path":"product/runtime/auths-kernel-runtime/src/lib.rs","sha256":"7108faae9ca4bc32dc093ddaf885ac8f74f3c9b8d317b7c7d0ed00d1d0ab5972"},{"path":"product/runtime/auths-lifecycle/Cargo.toml","sha256":"c5053c705f8d5554b44e432fe75287a2faf11d644e5a2552e45ad6cd94176af5"},{"path":"product/runtime/auths-lifecycle/src/codec.rs","sha256":"51c4b746749150e8bfcd8ff972b3f6c1ef40bec15583448ec1b471d9ad737dc0"},{"path":"product/runtime/auths-lifecycle/src/digest.rs","sha256":"55282cd7d8aba37713c2dcb5357c9877819edb72a30eadefb860d28d7d3a3eb7"},{"path":"product/runtime/auths-lifecycle/src/identifier.rs","sha256":"31620e8c16de68d3d2d3b84d6353c1a5b9d4151d8247f91fa389b906a8e660f1"},{"path":"product/runtime/auths-lifecycle/src/kernel.rs","sha256":"2abb8c094b36d35b364e74d78091d14c5d6f3d1eb6552cca3b5538dbd017ce23"},{"path":"product/runtime/auths-lifecycle/src/lib.rs","sha256":"afe5a345cd309b5a4f08ffba3170a6d7f16ff914892b3f2006d5208ed24ec736"},{"path":"product/runtime/auths-lifecycle/src/model.rs","sha256":"1af12bbeeeaa65ec02ddcebd7d2c8c92ec1e339fa40ae85b45ab9b01a722a4fa"},{"path":"product/runtime/auths-lifecycle/src/operation.rs","sha256":"78e6d05fcf5d7ea4f148032a3fa26fdfcab77eb346019effe927b08e0d64d732"},{"path":"product/runtime/auths-lifecycle/src/registry.rs","sha256":"53495fe6f7a77422593a41623e28716f1c140dcc1e00f87f6b0ffbfb93a5ef90"},{"path":"product/runtime/auths-lifecycle/src/sealed.rs","sha256":"2e0c03b5813c926c159598bb7890d1523825edbe57cd687d42a5dfb3374a0c19"},{"path":"product/runtime/auths-lifecycle/src/test_support.rs","sha256":"221d9a5c5ef8e1f9f8fd66927484eaf813571d0568470278ecd8fa08a5eec8cd"},{"path":"product/runtime/auths-lifecycle/src/transition.rs","sha256":"011805a28efdd541f44ccea54dd0e34a1e58f4004447ee58013703b4fb6b2822"},{"path":"product/runtime/auths-runtime/Cargo.toml","sha256":"dd29d80a8b4bb56c869f036a6c9998f6e6d1c0383ac5dc03fa42b24abe2a7ff7"},{"path":"product/runtime/auths-runtime/src/lib.rs","sha256":"132ca03d58c14905d3a822a4972f42a22a5ad33a45f2ba9ca44f3a57d810b4b0"},{"path":"product/runtime/auths-runtime/src/production.rs","sha256":"fd4eff4270c571c10fcff6cf27df28961ebf074de8a1a028f500fda1ca376820"},{"path":"product/sdk/auths-approval-quorum/Cargo.toml","sha256":"df904971fca87a24194c5816738a331588fe8f164acb5d70839a35dca5f57114"},{"path":"product/sdk/auths-approval-quorum/src/lib.rs","sha256":"72e4086088a1c0912e4e1a9e980f26a5c280bf5ab16ea39c9f0f58d5096ac2ce"},{"path":"product/sdk/auths-approval-quorum/src/remote.rs","sha256":"9fa029c7c63003adf260f8aec55160c545681c60c1bace0d934e7525862aac7b"},{"path":"product/sdk/auths-approval-quorum/src/remote_tests.rs","sha256":"8a09ce17cfee82a035a74edd535f3ebeb3db0e078784740d3997b17dbdb10197"},{"path":"product/sdk/auths-approval-quorum/src/tests.rs","sha256":"0acbf12be3e497dcc6c2d8f29c9af3b1a7ed8e11b75f6399570d4f217a785060"},{"path":"product/stores/auths-stores/Cargo.toml","sha256":"a32c4b76d17b264be5d40d24497ff237e1ed87822e8bab86229b3db93106dbe3"},{"path":"product/stores/auths-stores/src/gateway_attempt.rs","sha256":"218841602d3d9b23b44625f50e5b54cf275ccedc2d5c89f02d2482b8524472af"},{"path":"product/stores/auths-stores/src/lib.rs","sha256":"e721262edf8a9ab5568ddc27639176312d4a366203b5f73e2d7c11fde2c554e9"},{"path":"product/stores/auths-stores/src/lifecycle.rs","sha256":"3f2cecfda13fdcd7c4a944518646bcc8abd1237f900c0332d5822281f8f9f1cd"}],"schema":"auths.gateway-semantic-closure/1"} \ No newline at end of file diff --git a/product/runtime/auths-gateway/src/bin/auths-gateway.rs b/product/runtime/auths-gateway/src/bin/auths-gateway.rs index 385ab665f..5483ccda9 100644 --- a/product/runtime/auths-gateway/src/bin/auths-gateway.rs +++ b/product/runtime/auths-gateway/src/bin/auths-gateway.rs @@ -1324,6 +1324,21 @@ mod unix { "gateway.install.credential-store-unavailable", CredentialAccess::Operator, )?; + // Retain authenticated cleanup inputs before any custody write. A + // pending install has no generation floor and cannot admit a lease. + // Explicit store-only revocation can still make its journal collectible. + private_file(&state_dir.join("recipe.json"), &source)?; + private_file(&state_dir.join("profile.lock.json"), &lock)?; + private_file(&state_dir.join("trusted.context.cbor"), &trust)?; + if let Some(bytes) = &attestation { + private_file(&state_dir.join(OPERATOR_ATTESTATION_FILE), bytes)?; + } + if let Some(bytes) = &qualification_root { + private_file(&state_dir.join(QUALIFICATION_ROOT_FILE), bytes)?; + } + let manifest_bytes = serde_json_canonicalizer::to_vec(&manifest) + .map_err(|_| "gateway.install.manifest-invalid")?; + private_file(&state_dir.join("installation.json"), &manifest_bytes)?; let shared = SharedConnection::new(attempts.store(), provider.clone(), alias.clone()); if join { join_connection(&shared, &*credentials, &recipe, &candidate).await?; @@ -1406,18 +1421,6 @@ mod unix { tokio::task::spawn_blocking(move || floor.initialize(&record)) .await .map_err(|_| "gateway.install.connection-store-unavailable")??; - private_file(&state_dir.join("recipe.json"), &source)?; - private_file(&state_dir.join("profile.lock.json"), &lock)?; - private_file(&state_dir.join("trusted.context.cbor"), &trust)?; - if let Some(bytes) = &attestation { - private_file(&state_dir.join(OPERATOR_ATTESTATION_FILE), bytes)?; - } - if let Some(bytes) = &qualification_root { - private_file(&state_dir.join(QUALIFICATION_ROOT_FILE), bytes)?; - } - let manifest_bytes = serde_json_canonicalizer::to_vec(&manifest) - .map_err(|_| "gateway.install.manifest-invalid")?; - private_file(&state_dir.join("installation.json"), &manifest_bytes)?; println!( "{} recipe {} with separate gateway credential custody", if join { "joined" } else { "installed" }, diff --git a/product/runtime/auths-gateway/src/connection.rs b/product/runtime/auths-gateway/src/connection.rs index e755d4320..15bda3cef 100644 --- a/product/runtime/auths-gateway/src/connection.rs +++ b/product/runtime/auths-gateway/src/connection.rs @@ -186,12 +186,33 @@ impl SharedConnection { /// # Errors /// Unreadable, obsolete, or foreign state is an error, never absence. pub async fn load(&self) -> Result, SharedConnectionError> { + match self.read_record().await? { + Some(loaded) => self.accept_floor(loaded).await.map(Some), + None => Ok(None), + } + } + + /// Cleanup may inspect an irreversibly revoked record without accepting + /// it for execution. Active and disabled records still require the host + /// floor. This permits retirement after an interrupted fresh install; + /// it never initializes, replaces or lowers an execution witness. + pub(crate) async fn load_for_credential_collection( + &self, + ) -> Result, SharedConnectionError> { + match self.read_record().await? { + Some(loaded) if loaded.record().state() == ConnectionState::Revoked => Ok(Some(loaded)), + Some(loaded) => self.accept_floor(loaded).await.map(Some), + None => Ok(None), + } + } + + async fn read_record(&self) -> Result, SharedConnectionError> { let store = Arc::clone(&self.store); let key = self.key; let bytes = blocking(move || store.load(crate::GatewayRecordKind::Connection, &key)).await?; match bytes { - Some(bytes) => self.accept_floor(self.decode(bytes)?).await.map(Some), + Some(bytes) => self.decode(bytes).map(Some), None => Ok(None), } } diff --git a/product/runtime/auths-gateway/src/engine.rs b/product/runtime/auths-gateway/src/engine.rs index 50552c275..1117bb224 100644 --- a/product/runtime/auths-gateway/src/engine.rs +++ b/product/runtime/auths-gateway/src/engine.rs @@ -468,6 +468,9 @@ impl GatewayEngine { /// requires it unchanged, and never deletes its active credential or a /// future prepared generation. Run under operator workload identity. /// Existing attempts and provider state are never changed. + /// An explicitly revoked record is cleanup authority even when an + /// interrupted install left no usable execution floor; all other states + /// still require that floor. Collection never repairs an execution floor. /// /// # Errors /// A damaged journal, changed connection or failed deletion refuses and @@ -477,7 +480,7 @@ impl GatewayEngine { .credential_journal .clone() .ok_or("gateway.admin.credential-journal-unavailable")?; - let current = self.load_for_admin().await?; + let current = self.load_for_collection().await?; let record = current.record().clone(); let id = record.connection_id().clone(); let reading = journal.clone(); @@ -485,7 +488,7 @@ impl GatewayEngine { .await .map_err(|_| "gateway.admin.credential-journal-unavailable")??; tokio::time::sleep(self.retirement_delay).await; - let latest = self.load_for_admin().await?; + let latest = self.load_for_collection().await?; if !latest.unchanged(¤t) { return Err("gateway.admin.generation-conflict"); } @@ -513,6 +516,14 @@ impl GatewayEngine { Ok(deleted) } + async fn load_for_collection(&self) -> Result { + self.connection + .load_for_credential_collection() + .await + .map_err(|_| "gateway.admin.connection-unavailable")? + .ok_or("gateway.admin.connection-unavailable") + } + /// Installs the qualification gate the operator plane built for this /// deployment. Without one, every lease is refused as unqualified. #[must_use] @@ -2338,6 +2349,57 @@ pub(crate) mod tests { ); } + #[tokio::test] + async fn interrupted_install_cleanup_requires_revocation_and_never_repairs_the_floor() { + let mut installation = installation(8).await; + let host = &mut installation.first; + let record = host.record().await; + let directory = tempfile::tempdir().expect("private cleanup root"); + private_directory(directory.path()); + let journal = crate::CredentialJournal::new(directory.path().to_path_buf()); + journal.initialize(record.connection_id()).expect("journal"); + journal + .register(record.connection_id(), record.credential_generation()) + .expect("note"); + host.engine.credential_journal = Some(journal); + host.engine.connection = host + .engine + .connection + .clone() + .with_generation_floor(crate::GenerationFloor::new(directory.path().to_path_buf())); + let path = directory.path().join("connection-floor.json"); + let leases = host.leases.load(Ordering::SeqCst); + for damaged in [None, Some(b"corrupt".to_vec())] { + if let Some(bytes) = damaged { + std::fs::write(&path, bytes).expect("damaged floor"); + } + assert!(matches!( + host.engine.prepare_entry().await, + Err("gateway.connection.restore-rollback") + )); + assert_eq!( + host.engine.collect_credentials().await, + Err("gateway.admin.connection-unavailable") + ); + assert_eq!(host.stored(&installation.connection_id), [1]); + } + SharedConnection::new(host.engine.attempts.store(), provider(), alias()) + .stop(true, wall_clock_seconds().expect("clock")) + .await + .expect("explicit store-only revoke"); + assert_eq!(host.engine.collect_credentials().await, Ok(1)); + assert!(host.stored(&installation.connection_id).is_empty()); + assert_eq!( + std::fs::read(&path).expect("retained floor").as_slice(), + b"corrupt" + ); + assert!(matches!( + host.engine.prepare_entry().await, + Err("gateway.connection.restore-rollback") + )); + assert_eq!(host.leases.load(Ordering::SeqCst), leases); + } + #[tokio::test] async fn readiness_and_emergency_stop_make_no_credential_lease() { let installation = installation(8).await; diff --git a/product/runtime/auths-gateway/src/semantic_closure.rs b/product/runtime/auths-gateway/src/semantic_closure.rs index ab5aaccab..994940746 100644 --- a/product/runtime/auths-gateway/src/semantic_closure.rs +++ b/product/runtime/auths-gateway/src/semantic_closure.rs @@ -10,7 +10,7 @@ /// SHA-256 of the schema, a NUL byte, and `semantic-closure.json`. /// Regenerate through `semantic_closure_is_current` with `AUTHS_UPDATE_FIXTURES=1`. pub const GATEWAY_SEMANTIC_CLOSURE_SHA256: &str = - "463b30c37a0e608fab12ce63f512896ebde9592a5aa48f2417e02e284e775ee8"; + "d2535ce12c2c5b369e5bf3ff27c6943d4be6bcba88759a1632de61d90af34073"; #[cfg(test)] mod tests { diff --git a/qualification/families/airtable-record-update-v1/contract.json b/qualification/families/airtable-record-update-v1/contract.json index b37589ae5..f72e5d836 100644 --- a/qualification/families/airtable-record-update-v1/contract.json +++ b/qualification/families/airtable-record-update-v1/contract.json @@ -1 +1 @@ -{"api_release":"web-api-v0-reviewed-2026-10-07","corpus_manifest_sha256":"8a4e4d127ac63e929b2ae40518b001f9c13af964a9cdfb8d99f70e29e44d0dc9","declarations":{"idempotency_sha256":"74234e98afe7498fb5daf1f36ac2d78acc339464f950703b8c019892f982b90b","observation_sha256":"9dd79dd204fa13a2df3c667d106c66c0526d174a2c018631e2b2f6b897eaf311","recovery_sha256":"7081a92b4cd2d13dab5e7c30e640675a252b62bca20d340e14d62d9c8c048eca","retention_sha256":"4a4b5048c97b16e041af55b032c0b8ac20f5142c4bbcbf31b31c6674770a70d0"},"environment_class":"disposable-live-resources","manual_assumptions":["Airtable supplies no idempotency key for this PATCH; durable gateway admission prevents a second entry.","Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only a fresh GET with the exact replacement and echo can reconcile a lost response.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths.","The reviewed fixed Airtable base and table contain only owner-authorized disposable qualification records."],"oracle_version":"auths-reviewed-reference-v2","provider":"airtable","schema":"auths.provider-contract/1"} \ No newline at end of file +{"api_release":"web-api-v0-reviewed-2026-10-07","corpus_manifest_sha256":"1a62031a82c236a6407279ee055637d0cedfb2ca8e1a15457a9154f69e9f97ae","declarations":{"idempotency_sha256":"74234e98afe7498fb5daf1f36ac2d78acc339464f950703b8c019892f982b90b","observation_sha256":"9dd79dd204fa13a2df3c667d106c66c0526d174a2c018631e2b2f6b897eaf311","recovery_sha256":"7081a92b4cd2d13dab5e7c30e640675a252b62bca20d340e14d62d9c8c048eca","retention_sha256":"4a4b5048c97b16e041af55b032c0b8ac20f5142c4bbcbf31b31c6674770a70d0"},"environment_class":"disposable-live-resources","manual_assumptions":["Airtable supplies no idempotency key for this PATCH; durable gateway admission prevents a second entry.","Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only a fresh GET with the exact replacement and echo can reconcile a lost response.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths.","The reviewed fixed Airtable base and table contain only owner-authorized disposable qualification records."],"oracle_version":"auths-reviewed-reference-v2","provider":"airtable","schema":"auths.provider-contract/1"} \ No newline at end of file diff --git a/qualification/families/airtable-record-update-v1/corpus-manifest.json b/qualification/families/airtable-record-update-v1/corpus-manifest.json index 6605c66d2..c1c6e370f 100644 --- a/qualification/families/airtable-record-update-v1/corpus-manifest.json +++ b/qualification/families/airtable-record-update-v1/corpus-manifest.json @@ -1 +1 @@ -{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"32241d9b4811a55abcdd224ef567df3857dbec34d761ef7a35d1044cdfa52d9f","family":"airtable-record-update-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"af7f984509ab11a3676cacc85eda2fa638c25bf91f7bfedf3ff3c119e47f3c41","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","application_probe.py":"5e2dd6a91eb0a2acf2df1079cead5bd67ae5d6743abce6e48201e7326f63daa2","artifact_wait.py":"56efcf5a34103955e43c1d3be7fd58843efdc8095187d74dc890cf3342863f55","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","close_proposal.py":"9a6927722ada8eaba720ff13168101244880da3fe6f2c95f653bc3840ef81756","commission.py":"f4495d6e3d2b9c50e72e339e9571eacd9b3628ebebe7c86c601b94e785a5c9fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","controller_socket.py":"10519cc775e963360870eac51c7fcac1ffb988b04d5de89dac1dbf3524ba6531","custody_fault.py":"7b1e96d1085d5fe5acd1ca35867a5d657093191984763477ebcfcb054dbb59cb","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"a3662539a9a130f5272cbd8b3750be3ebb46d4ad903aba7afa10880f99a2f601","family_harness.py":"0e0a42be6cf75dfb3f674b26cbdfbb4c473edea71083dfaad89ecb40dec039ba","family_operations.py":"37dca5e6ed97a5edbff3408663589258a3db2aac400b2d9e12ae8f603f61bda1","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","installed_submit.mjs":"9d57a91c4a052fbb9103582689ee99a6d087758dcfee00defa4c762b87187468","installed_submit.py":"f9151c2dffa1a02327b0ba05bdeb180654918a2b913195185a6649d010783dc7","journey_session.py":"3c807ce45dcabe3b39d63333872af3746fe9276aacf5eba30bf903b51d80dfef","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"580fa1db01a6fa7691d618f123f9117ce39b25e6478460ceac46c1e650d6b454","network_fault.py":"94340720d8601f79ac77b95d1e855be25195c19b67db3103bbf054d82c02472b","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","production_environment.py":"4afa2491624b0dfbc44fba868474415628d18f1493f8e6c772f108eccd1390da","production_journey.py":"179b93aa525ddd73ad1b3e9fcf38eeb540173845025707aed6b9fa9a44e4aad8","production_setup.py":"6ed9488e59514cde495aed9f5efde604c69bf416112759ec24ae36eb79070003","provider_readback.py":"d576768208985b3544f146597d181d796f2a5e2eca5026dae3fa15cadcfe65b2","resource_io.py":"b0ed0223fd11a1a28c25278de539a9b2ed63881b26a8e00e386f25d4d9aa9384","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","retained_author.py":"bfd01c7df44f5f525326dfbda13b5ebc6b854f15787a8b2923de883fe20fdcf9","sign_release.py":"d0aa7697cc6889538dfd54f9101a5b7bc2e8f7aede729da2d382b6466781df99","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489","tls_fault.py":"10e125f9623bc32a420a1d83e6d46fe30aa1ca8ff4da97a3e2422fc0e11ec42d"},"source_recipe_sha256":"c0f21ff1d3c8e344fee20a9a0c25bb14a264417ed53418ad536789a6096fb16e"} \ No newline at end of file +{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"32241d9b4811a55abcdd224ef567df3857dbec34d761ef7a35d1044cdfa52d9f","family":"airtable-record-update-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"af7f984509ab11a3676cacc85eda2fa638c25bf91f7bfedf3ff3c119e47f3c41","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","application_probe.py":"5e2dd6a91eb0a2acf2df1079cead5bd67ae5d6743abce6e48201e7326f63daa2","artifact_wait.py":"56efcf5a34103955e43c1d3be7fd58843efdc8095187d74dc890cf3342863f55","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","close_proposal.py":"9a6927722ada8eaba720ff13168101244880da3fe6f2c95f653bc3840ef81756","commission.py":"f4495d6e3d2b9c50e72e339e9571eacd9b3628ebebe7c86c601b94e785a5c9fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","controller_socket.py":"10519cc775e963360870eac51c7fcac1ffb988b04d5de89dac1dbf3524ba6531","custody_fault.py":"f5e95620a1bb3fccc733be13c6ab68b6e84c0b134a6b54252766e4e57410907f","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"a3662539a9a130f5272cbd8b3750be3ebb46d4ad903aba7afa10880f99a2f601","family_harness.py":"0e0a42be6cf75dfb3f674b26cbdfbb4c473edea71083dfaad89ecb40dec039ba","family_operations.py":"37dca5e6ed97a5edbff3408663589258a3db2aac400b2d9e12ae8f603f61bda1","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","installed_submit.mjs":"9d57a91c4a052fbb9103582689ee99a6d087758dcfee00defa4c762b87187468","installed_submit.py":"f9151c2dffa1a02327b0ba05bdeb180654918a2b913195185a6649d010783dc7","journey_session.py":"3c807ce45dcabe3b39d63333872af3746fe9276aacf5eba30bf903b51d80dfef","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"580fa1db01a6fa7691d618f123f9117ce39b25e6478460ceac46c1e650d6b454","network_fault.py":"94340720d8601f79ac77b95d1e855be25195c19b67db3103bbf054d82c02472b","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","production_environment.py":"607a0bc37396a5a86da1d408b384ee4a54d920b849009717587150242bd47d73","production_journey.py":"1b019d80eace9687cbd6acd21b3e1978ae2e8885c2c81dff4fbe9a3b7be3e314","production_setup.py":"eac6cda2c2bff17364e72512b70ecfc3b6dad8c70088c1fe83d59f4ebaa395a0","provider_readback.py":"d576768208985b3544f146597d181d796f2a5e2eca5026dae3fa15cadcfe65b2","resource_io.py":"b0ed0223fd11a1a28c25278de539a9b2ed63881b26a8e00e386f25d4d9aa9384","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","retained_author.py":"bfd01c7df44f5f525326dfbda13b5ebc6b854f15787a8b2923de883fe20fdcf9","sign_release.py":"d0aa7697cc6889538dfd54f9101a5b7bc2e8f7aede729da2d382b6466781df99","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489","tls_fault.py":"10e125f9623bc32a420a1d83e6d46fe30aa1ca8ff4da97a3e2422fc0e11ec42d"},"source_recipe_sha256":"c0f21ff1d3c8e344fee20a9a0c25bb14a264417ed53418ad536789a6096fb16e"} \ No newline at end of file diff --git a/qualification/families/stripe-platform-refund-v1/contract.json b/qualification/families/stripe-platform-refund-v1/contract.json index e03b39ade..a00524a10 100644 --- a/qualification/families/stripe-platform-refund-v1/contract.json +++ b/qualification/families/stripe-platform-refund-v1/contract.json @@ -1 +1 @@ -{"api_release":"2025-03-31.basil","corpus_manifest_sha256":"e19803b375a796ed3169be6d23e3029e95382866f8b3be5ca45fdf725f9ce54b","declarations":{"idempotency_sha256":"425a0dca2f279765debfc847c4a01bff60fea5be68dd9d761ae6bb60ce0b8a7b","observation_sha256":"d0ce5a34d987821c69c0a839d9ed66805c625f8324dd42031fcccf0752a8821e","recovery_sha256":"bf2303abce165c175360ac975586431bbc4cf03167489ea317a27de2f0b04abb","retention_sha256":"846c2164e26d1144d9aa146034b4f7ea4dc305136a59ffd94f999d19f2c360ee"},"environment_class":"provider-test-mode","manual_assumptions":["Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","Stripe idempotency is tested only inside the declared 86400-second retention interval.","Stripe test mode and the installed platform are checked by the declared guard on each lease.","The 50-percent payment basis is a read, not an atomic provider balance reservation.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths."],"oracle_version":"auths-reviewed-reference-v2","provider":"stripe","schema":"auths.provider-contract/1"} \ No newline at end of file +{"api_release":"2025-03-31.basil","corpus_manifest_sha256":"54050ff518d37580f9f19d57a7406720360c87c0e2218446708196e324eae1de","declarations":{"idempotency_sha256":"425a0dca2f279765debfc847c4a01bff60fea5be68dd9d761ae6bb60ce0b8a7b","observation_sha256":"d0ce5a34d987821c69c0a839d9ed66805c625f8324dd42031fcccf0752a8821e","recovery_sha256":"bf2303abce165c175360ac975586431bbc4cf03167489ea317a27de2f0b04abb","retention_sha256":"846c2164e26d1144d9aa146034b4f7ea4dc305136a59ffd94f999d19f2c360ee"},"environment_class":"provider-test-mode","manual_assumptions":["Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","Stripe idempotency is tested only inside the declared 86400-second retention interval.","Stripe test mode and the installed platform are checked by the declared guard on each lease.","The 50-percent payment basis is a read, not an atomic provider balance reservation.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths."],"oracle_version":"auths-reviewed-reference-v2","provider":"stripe","schema":"auths.provider-contract/1"} \ No newline at end of file diff --git a/qualification/families/stripe-platform-refund-v1/corpus-manifest.json b/qualification/families/stripe-platform-refund-v1/corpus-manifest.json index fd87b3630..dee9157d0 100644 --- a/qualification/families/stripe-platform-refund-v1/corpus-manifest.json +++ b/qualification/families/stripe-platform-refund-v1/corpus-manifest.json @@ -1 +1 @@ -{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"a72c557b69103a52eb477deb8364ded53cd58407b9ba7ab33ccbda74389fec1e","family":"stripe-platform-refund-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"99901e36cb7c4f5882897603c874698d582e859b5d6b08d53cd80975e89aa01c","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","application_probe.py":"5e2dd6a91eb0a2acf2df1079cead5bd67ae5d6743abce6e48201e7326f63daa2","artifact_wait.py":"56efcf5a34103955e43c1d3be7fd58843efdc8095187d74dc890cf3342863f55","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","close_proposal.py":"9a6927722ada8eaba720ff13168101244880da3fe6f2c95f653bc3840ef81756","commission.py":"f4495d6e3d2b9c50e72e339e9571eacd9b3628ebebe7c86c601b94e785a5c9fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","controller_socket.py":"10519cc775e963360870eac51c7fcac1ffb988b04d5de89dac1dbf3524ba6531","custody_fault.py":"7b1e96d1085d5fe5acd1ca35867a5d657093191984763477ebcfcb054dbb59cb","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"a3662539a9a130f5272cbd8b3750be3ebb46d4ad903aba7afa10880f99a2f601","family_harness.py":"0e0a42be6cf75dfb3f674b26cbdfbb4c473edea71083dfaad89ecb40dec039ba","family_operations.py":"37dca5e6ed97a5edbff3408663589258a3db2aac400b2d9e12ae8f603f61bda1","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","installed_submit.mjs":"9d57a91c4a052fbb9103582689ee99a6d087758dcfee00defa4c762b87187468","installed_submit.py":"f9151c2dffa1a02327b0ba05bdeb180654918a2b913195185a6649d010783dc7","journey_session.py":"3c807ce45dcabe3b39d63333872af3746fe9276aacf5eba30bf903b51d80dfef","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"580fa1db01a6fa7691d618f123f9117ce39b25e6478460ceac46c1e650d6b454","network_fault.py":"94340720d8601f79ac77b95d1e855be25195c19b67db3103bbf054d82c02472b","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","production_environment.py":"4afa2491624b0dfbc44fba868474415628d18f1493f8e6c772f108eccd1390da","production_journey.py":"179b93aa525ddd73ad1b3e9fcf38eeb540173845025707aed6b9fa9a44e4aad8","production_setup.py":"6ed9488e59514cde495aed9f5efde604c69bf416112759ec24ae36eb79070003","provider_readback.py":"d576768208985b3544f146597d181d796f2a5e2eca5026dae3fa15cadcfe65b2","resource_io.py":"b0ed0223fd11a1a28c25278de539a9b2ed63881b26a8e00e386f25d4d9aa9384","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","retained_author.py":"bfd01c7df44f5f525326dfbda13b5ebc6b854f15787a8b2923de883fe20fdcf9","sign_release.py":"d0aa7697cc6889538dfd54f9101a5b7bc2e8f7aede729da2d382b6466781df99","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489","tls_fault.py":"10e125f9623bc32a420a1d83e6d46fe30aa1ca8ff4da97a3e2422fc0e11ec42d"},"source_recipe_sha256":"b1972d556f28433932a449636755077f7ee485ef90cca412f153bc7f18881368"} \ No newline at end of file +{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"a72c557b69103a52eb477deb8364ded53cd58407b9ba7ab33ccbda74389fec1e","family":"stripe-platform-refund-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"99901e36cb7c4f5882897603c874698d582e859b5d6b08d53cd80975e89aa01c","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","application_probe.py":"5e2dd6a91eb0a2acf2df1079cead5bd67ae5d6743abce6e48201e7326f63daa2","artifact_wait.py":"56efcf5a34103955e43c1d3be7fd58843efdc8095187d74dc890cf3342863f55","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","close_proposal.py":"9a6927722ada8eaba720ff13168101244880da3fe6f2c95f653bc3840ef81756","commission.py":"f4495d6e3d2b9c50e72e339e9571eacd9b3628ebebe7c86c601b94e785a5c9fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","controller_socket.py":"10519cc775e963360870eac51c7fcac1ffb988b04d5de89dac1dbf3524ba6531","custody_fault.py":"f5e95620a1bb3fccc733be13c6ab68b6e84c0b134a6b54252766e4e57410907f","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"a3662539a9a130f5272cbd8b3750be3ebb46d4ad903aba7afa10880f99a2f601","family_harness.py":"0e0a42be6cf75dfb3f674b26cbdfbb4c473edea71083dfaad89ecb40dec039ba","family_operations.py":"37dca5e6ed97a5edbff3408663589258a3db2aac400b2d9e12ae8f603f61bda1","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","installed_submit.mjs":"9d57a91c4a052fbb9103582689ee99a6d087758dcfee00defa4c762b87187468","installed_submit.py":"f9151c2dffa1a02327b0ba05bdeb180654918a2b913195185a6649d010783dc7","journey_session.py":"3c807ce45dcabe3b39d63333872af3746fe9276aacf5eba30bf903b51d80dfef","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"580fa1db01a6fa7691d618f123f9117ce39b25e6478460ceac46c1e650d6b454","network_fault.py":"94340720d8601f79ac77b95d1e855be25195c19b67db3103bbf054d82c02472b","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","production_environment.py":"607a0bc37396a5a86da1d408b384ee4a54d920b849009717587150242bd47d73","production_journey.py":"1b019d80eace9687cbd6acd21b3e1978ae2e8885c2c81dff4fbe9a3b7be3e314","production_setup.py":"eac6cda2c2bff17364e72512b70ecfc3b6dad8c70088c1fe83d59f4ebaa395a0","provider_readback.py":"d576768208985b3544f146597d181d796f2a5e2eca5026dae3fa15cadcfe65b2","resource_io.py":"b0ed0223fd11a1a28c25278de539a9b2ed63881b26a8e00e386f25d4d9aa9384","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","retained_author.py":"bfd01c7df44f5f525326dfbda13b5ebc6b854f15787a8b2923de883fe20fdcf9","sign_release.py":"d0aa7697cc6889538dfd54f9101a5b7bc2e8f7aede729da2d382b6466781df99","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489","tls_fault.py":"10e125f9623bc32a420a1d83e6d46fe30aa1ca8ff4da97a3e2422fc0e11ec42d"},"source_recipe_sha256":"b1972d556f28433932a449636755077f7ee485ef90cca412f153bc7f18881368"} \ No newline at end of file diff --git a/qualification/reference/README.md b/qualification/reference/README.md index 4080fd4e5..d50ea0033 100644 --- a/qualification/reference/README.md +++ b/qualification/reference/README.md @@ -259,7 +259,7 @@ verification remain separate. Retained copies are independently rescanned before the runner can upload them. Failed setup invalidates proposals, keeps scan canaries, and attempts all owned cleanup with native credential collection before retiring the renewing workload identity. These entry points still need -successful protected execution and partial-install cleanup recovery; +successful protected execution; they do not establish a passing protected qualification. `author_operator.py` runs in the same credential-free installed environment as @@ -382,3 +382,13 @@ and requires its exact production-policy refusal before a state directory exists These are disposable AWS fixture mutations, never application credential inputs or a provider test response substituted for AWS. They establish the precise before-admission boundary, not a fabricated post-claim lease failure. + +Interrupted setup is cleaned separately from a completed cohort. Successful +native install results track the four completed installations; a manifest alone +does not establish completion. A partial cohort first stops all its owned +gateway processes and removes its exclusively owned disposable database, then +deletes only the bounded names derived from its actual native credential +journals, while its operator identity is still available. It never enumerates +AWS resources, deletes another connection, or reports native collection for a +partial setup. Completed cohorts require native store-only revocation and +collection. Failed phases remain invalid and cannot publish a qualification. diff --git a/qualification/reference/custody_fault.py b/qualification/reference/custody_fault.py index 902f2bec7..f7a0aebc8 100644 --- a/qualification/reference/custody_fault.py +++ b/qualification/reference/custody_fault.py @@ -19,18 +19,23 @@ from resource_io import write, write_bytes -def reference(namespace, connection, generation, secret): +def coordinates(namespace, connection, generation): require(type(namespace) is str and re.fullmatch(r'[a-z][a-z0-9-]{0,63}', namespace) and type(connection) is str and re.fullmatch(r'conn_[A-Za-z0-9_-]{22}', connection) - and type(generation) is int and 1 <= generation < 1 << 64 - and type(secret) is bytes and 0 < len(secret) <= 65536, 'qualification.custody.reference') + and type(generation) is int and 1 <= generation < 1 << 64, 'qualification.custody.reference') decoded = base64.urlsafe_b64decode(connection[5:] + '==') require(len(decoded) == 16 and base64.urlsafe_b64encode(decoded).rstrip(b'=').decode() == connection[5:], 'qualification.custody.reference') number = generation.to_bytes(8, 'big') - commitment = sha256(b'auths.connection-credential-store/1\0' + connection.encode() + number + secret) name = 'auths-gateway/' + sha256(b'auths.gateway-secret-name/1\0' + namespace.encode() + b'\0' + connection.encode() + b'\0' + number) + return name, number + + +def reference(namespace, connection, generation, secret): + require(type(secret) is bytes and 0 < len(secret) <= 65536, 'qualification.custody.reference') + name, number = coordinates(namespace, connection, generation) + commitment = sha256(b'auths.connection-credential-store/1\0' + connection.encode() + number + secret) version = sha256(b'auths.gateway-secret-version/1\0' + connection.encode() + b'\0' + number + bytes.fromhex(commitment)) return name, version, commitment @@ -188,3 +193,38 @@ def kind(self): require(result.returncode == 1 and result.stdout == b'' and result.stderr == b'gateway.credential.production-plaintext-refused\n' and not state.exists(), 'qualification.custody.kind-not-refused') + + def retire_partial(self, infrastructure): + # This source reference owns the entire disposable database. Removing + # it first makes an ambiguously committed incomplete install unusable. + # A complete cohort must use native revocation and collection instead. + require(not self.deployment.processes and len(self.deployment.installations) < 4 + and infrastructure.container is None, 'qualification.custody.partial-not-stopped') + names, connections = set(), set() + for context in [0, 1]: + for host in [0, 1]: + path = self.deployment.state(host, context) / 'credential-journal.json' + if not path.exists() and not path.is_symlink(): + # Native source registers this journal before any create. + continue + notes = decode(read(private_file(path, GATEWAY_UID), 4096)) + closed(notes, ['schema', 'connection_id', 'generations']) + require(notes['schema'] == 'auths.gateway-credential-journal/1' + and type(notes['connection_id']) is str + and type(notes['generations']) is list and len(notes['generations']) <= 16 + and all(type(generation) is int and 1 <= generation < 1 << 64 + for generation in notes['generations']) + and notes['generations'] == sorted(set(notes['generations'])), + 'qualification.custody.journal') + connections.add(notes['connection_id']) + coordinates(self.deployment.namespace, notes['connection_id'], 1) + for generation in notes['generations']: + names.add(coordinates(self.deployment.namespace, notes['connection_id'], generation)[0]) + require(len(connections) <= 1 and len(names) <= 16, 'qualification.custody.partial-bound') + failures = [] + for name in sorted(names): + try: + self.delete(name) + except (Refusal, OSError, subprocess.SubprocessError): + failures.append(True) + require(not failures, 'qualification.custody.partial-cleanup-incomplete') diff --git a/qualification/reference/production_environment.py b/qualification/reference/production_environment.py index ab2312ff0..c2376ccb2 100644 --- a/qualification/reference/production_environment.py +++ b/qualification/reference/production_environment.py @@ -220,6 +220,16 @@ def start_database(self): time.sleep(0.25) require(False, 'qualification.infrastructure.database-unavailable') + def stop_database(self): + if self.container is not None: + # The exact-name filter never lists unrelated user containers. + found = command(['docker', 'container', 'ls', '--all', '--filter', + 'name=^/' + self.container + '$', '--format', '{{.Names}}']).strip() + require(found in [b'', self.container.encode()], 'qualification.infrastructure.cleanup-binding') + if found: + command(['docker', 'rm', '--force', '--volumes', self.container]) + self.container = None + def close(self): # The caller must first collect its native credential journal. Keep # attempting local cleanup even when one owned resource cannot retire. @@ -234,17 +244,7 @@ def attempt(action): self.refresher.join(timeout=30) if self.refresher.is_alive(): failures.append(True) - if self.container is not None: - def remove_container(): - # Docker's exact-name filter distinguishes a failed start - # from a daemon error without listing unrelated containers. - found = command(['docker', 'container', 'ls', '--all', '--filter', - 'name=^/' + self.container + '$', '--format', '{{.Names}}']).strip() - require(found in [b'', self.container.encode()], 'qualification.infrastructure.cleanup-binding') - if found: - command(['docker', 'rm', '--force', '--volumes', self.container]) - self.container = None - attempt(remove_container) + attempt(self.stop_database) if hasattr(self, 'clock_configuration'): attempt(lambda: self.clock_configuration.unlink(missing_ok=True)) for name in ['operator.jwt', 'runtime.jwt']: diff --git a/qualification/reference/production_journey.py b/qualification/reference/production_journey.py index 52812eaf7..030c8e716 100644 --- a/qualification/reference/production_journey.py +++ b/qualification/reference/production_journey.py @@ -21,6 +21,7 @@ from family_corpus import authenticate, compile_plan, RESOURCES from family_harness import ROOT from family_operations import Operations +from custody_fault import Faults from generate_families import generate from network_fault import Isolation from packet_plan import prepare as prepare_packets @@ -285,10 +286,17 @@ def attempt(action): attempt(self.deployment.close) # Collect while the actual web identity is still renewing. A # partial native installation cannot invent a collector result. - if (self.deployment.state(0) / 'installation.json').is_file(): + if len(self.deployment.installations) == 4: attempt(self.deployment.retire_credentials) else: - failures.append(True) + def retire_partial(): + require(not self.deployment.processes, 'qualification.journey.gateway-still-running') + self.infrastructure.stop_database() + require(self.infrastructure.container is None, 'qualification.journey.database-still-running') + existing = self.operations.custody_faults if self.operations is not None else None + faults = existing if existing is not None else Faults(self.deployment) + faults.retire_partial(self.infrastructure) + attempt(retire_partial) if self.resources is not None and hasattr(self, 'journal') and self.journal.exists(): attempt(lambda: self.resources.cleanup(self.journal)) if self.author is not None: diff --git a/qualification/reference/production_setup.py b/qualification/reference/production_setup.py index 03f3833b4..1fba5e52a 100644 --- a/qualification/reference/production_setup.py +++ b/qualification/reference/production_setup.py @@ -125,6 +125,7 @@ def __init__(self, binary, work, private, environment, canaries): require(len(str(self.state(0) / 'admin.sock').encode()) <= 107, 'qualification.production.socket-bound') self.processes = {} + self.installations = [] self.handoff_generation = 0 self.permit = None @@ -201,6 +202,7 @@ def install(self, credential, account): require(output == expected.encode(), 'qualification.production.install-output') actual = self.command(['qualification-status', '--state-dir', state, '--tuple']) require(actual == self.tuple, 'qualification.production.installed-tuple') + self.installations.append((host, context)) def start(self, host, context=0): key = (host, context) diff --git a/qualification/reference/tests/test_custody_fault.py b/qualification/reference/tests/test_custody_fault.py index 9f3563b76..106014bcb 100644 --- a/qualification/reference/tests/test_custody_fault.py +++ b/qualification/reference/tests/test_custody_fault.py @@ -9,7 +9,7 @@ sys.path.insert(0, str(Path(__file__).resolve().parents[1])) import custody_fault as custody -from common import Refusal +from common import Refusal, canonical from expand import decode CONNECTION = 'conn_AAAAAAAAAAAAAAAAAAAAAA' @@ -86,6 +86,35 @@ def test_absent_exact_owned_name_is_idempotent_but_other_failures_are_not(self): with patch.object(value, 'api', return_value=response): with self.assertRaises(Refusal): value.delete('owned-fixture-name') + def test_partial_retirement_requires_stopped_processes_and_database_and_one_exact_connection(self): + with tempfile.TemporaryDirectory() as temporary: + root = Path(temporary) + value = self.fixture(root) + value.deployment.processes, value.deployment.installations = {}, [] + value.deployment.state = lambda host, context: root / (str(host) + str(context)) + for host, context in [(0, 0), (1, 0)]: + state = value.deployment.state(host, context) + state.mkdir() + (state / 'credential-journal.json').write_bytes(canonical({ + 'schema': 'auths.gateway-credential-journal/1', 'connection_id': CONNECTION, + 'generations': [1, 2]})) + infrastructure = SimpleNamespace(container='owned-fixture-container') + with patch.object(value, 'delete') as deleted: + with self.assertRaises(Refusal): value.retire_partial(infrastructure) + deleted.assert_not_called() + infrastructure.container = None + with patch.object(custody, 'private_file', side_effect=lambda path, owner: path), \ + patch.object(value, 'delete') as deleted: + value.retire_partial(infrastructure) + self.assertEqual(deleted.call_count, 2, 'duplicate host journals are not remote enumeration') + expected = {custody.coordinates('test-namespace', CONNECTION, generation)[0] for generation in [1, 2]} + self.assertEqual({call.args[0] for call in deleted.call_args_list}, expected) + value.deployment.processes = {(0, 0): object()} + with self.assertRaises(Refusal): value.retire_partial(infrastructure) + value.deployment.processes = {} + value.deployment.installations = [(0, 0), (1, 0), (0, 1), (1, 1)] + with self.assertRaises(Refusal): value.retire_partial(infrastructure) + if __name__ == '__main__': unittest.main() diff --git a/qualification/reference/tests/test_journey_session.py b/qualification/reference/tests/test_journey_session.py index 051cb2da7..44eb4c4ca 100644 --- a/qualification/reference/tests/test_journey_session.py +++ b/qualification/reference/tests/test_journey_session.py @@ -73,6 +73,7 @@ def test_all_cleanup_is_attempted_with_credential_collection_before_identity_ret value.stopping, value.worker = threading.Event(), None calls = [] class Deployment: + installations = [(0, 0), (1, 0), (0, 1), (1, 1)] def state(self, host): return Path(directory) def close(self): calls.append('stop-gateways') def retire_credentials(self): @@ -100,6 +101,34 @@ def close(self): calls.append('retire-identity-and-database') self.assertFalse(value.retired) with self.assertRaisesRegex(Refusal, 'cleanup-required'): value.final_proposal() + def test_partial_install_removes_its_database_before_exact_journal_retirement(self): + with tempfile.TemporaryDirectory() as directory: + value = self.journey(Path(directory)) + value.stopping, value.worker = threading.Event(), None + value.operations = value.resources = value.author = value.isolation = None + calls = [] + class Deployment: + installations, processes = [], {} + def close(self): calls.append('stop-own-gateways') + def retire_credentials(self): raise AssertionError('partial state cannot claim native collection') + class Infrastructure: + container = 'owned-fixture-container' + def stop_database(self): + calls.append('remove-owned-database') + self.container = None + def close(self): calls.append('retire-identity') + class Faults: + def __init__(self, deployment): self.deployment = deployment + def retire_partial(self, infrastructure): + if infrastructure.container is not None or self.deployment.processes: + raise Refusal('qualification.custody.partial-not-stopped') + calls.append('delete-exact-journal-names') + value.deployment, value.infrastructure = Deployment(), Infrastructure() + with patch.object(production, 'Faults', Faults): value.cleanup() + self.assertEqual(calls, ['stop-own-gateways', 'remove-owned-database', + 'delete-exact-journal-names', 'retire-identity']) + self.assertTrue(value.retired) + if __name__ == '__main__': unittest.main() From 2efd9d61c83dd1e0fb8d879b17e7997bed239383 Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 18:57:50 +0100 Subject: [PATCH 100/108] Keep refused joins disposable and reuse existing protected environments --- .github/workflows/recipe-qualification.yml | 4 ++-- product/runtime/auths-gateway/tests/operator_plane.rs | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/recipe-qualification.yml b/.github/workflows/recipe-qualification.yml index 8bd5a9df6..7fb1a0254 100644 --- a/.github/workflows/recipe-qualification.yml +++ b/.github/workflows/recipe-qualification.yml @@ -414,7 +414,7 @@ jobs: shell: bash env: STRIPE_QUALIFICATION_SETUP_KEY: ${{ matrix.family == 'stripe-platform-refund-v1' && secrets.STRIPE_QUALIFICATION_SETUP_KEY || '' }} - STRIPE_QUALIFICATION_RUNTIME_KEY: ${{ matrix.family == 'stripe-platform-refund-v1' && secrets.STRIPE_QUALIFICATION_RUNTIME_KEY || '' }} + STRIPE_QUALIFICATION_RUNTIME_KEY: ${{ matrix.family == 'stripe-platform-refund-v1' && secrets.STRIPE_TEST_KEY || '' }} STRIPE_QUALIFICATION_NEXT_RUNTIME_KEY: ${{ matrix.family == 'stripe-platform-refund-v1' && secrets.STRIPE_QUALIFICATION_NEXT_RUNTIME_KEY || '' }} AIRTABLE_QUALIFICATION_TOKEN: ${{ matrix.family == 'airtable-record-update-v1' && secrets.AIRTABLE_QUALIFICATION_TOKEN || '' }} AIRTABLE_QUALIFICATION_NEXT_TOKEN: ${{ matrix.family == 'airtable-record-update-v1' && secrets.AIRTABLE_QUALIFICATION_NEXT_TOKEN || '' }} @@ -495,7 +495,7 @@ jobs: if: github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main' runs-on: ubuntu-latest timeout-minutes: 135 - environment: recipe-qualification-commissioning + environment: recipe-qualification-signing permissions: contents: read actions: read diff --git a/product/runtime/auths-gateway/tests/operator_plane.rs b/product/runtime/auths-gateway/tests/operator_plane.rs index 64bb5088a..751d1e530 100644 --- a/product/runtime/auths-gateway/tests/operator_plane.rs +++ b/product/runtime/auths-gateway/tests/operator_plane.rs @@ -171,6 +171,7 @@ fn a_joined_process_sees_every_change_committed_through_the_other() { let store = root.join("shared-attempts"); let first = root.join("first"); let second = root.join("second"); + let refused_state = root.join("refused-join"); let store_argument = store.display().to_string(); let shared = ["--attempt-store", store_argument.as_str()]; @@ -183,7 +184,7 @@ fn a_joined_process_sees_every_change_committed_through_the_other() { assert!(installed.status.success(), "{}", stderr(&installed)); let refused = install( &root, - &second, + &refused_state, &[&["--join"], &shared[..]].concat(), b"another-token\n", ); @@ -193,6 +194,8 @@ fn a_joined_process_sees_every_change_committed_through_the_other() { "{}", stderr(&refused) ); + assert!(refused_state.join("installation.json").is_file()); + assert!(!refused_state.join("connection-floor.json").exists()); let joined = install( &root, &second, From 3637efceaf0a0507af90943e46762da3e26edca0 Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 18:59:55 +0100 Subject: [PATCH 101/108] Pace Airtable rehearsal traffic without retrying gateway effects --- .../airtable-record-update-v1/contract.json | 2 +- .../corpus-manifest.json | 2 +- .../stripe-platform-refund-v1/contract.json | 2 +- .../corpus-manifest.json | 2 +- qualification/reference/README.md | 7 ++++++ qualification/reference/family_operations.py | 2 ++ qualification/reference/resource_io.py | 20 +++++++++++++++++ .../reference/tests/test_resources.py | 22 +++++++++++++++++++ 8 files changed, 55 insertions(+), 4 deletions(-) diff --git a/qualification/families/airtable-record-update-v1/contract.json b/qualification/families/airtable-record-update-v1/contract.json index f72e5d836..426abdadb 100644 --- a/qualification/families/airtable-record-update-v1/contract.json +++ b/qualification/families/airtable-record-update-v1/contract.json @@ -1 +1 @@ -{"api_release":"web-api-v0-reviewed-2026-10-07","corpus_manifest_sha256":"1a62031a82c236a6407279ee055637d0cedfb2ca8e1a15457a9154f69e9f97ae","declarations":{"idempotency_sha256":"74234e98afe7498fb5daf1f36ac2d78acc339464f950703b8c019892f982b90b","observation_sha256":"9dd79dd204fa13a2df3c667d106c66c0526d174a2c018631e2b2f6b897eaf311","recovery_sha256":"7081a92b4cd2d13dab5e7c30e640675a252b62bca20d340e14d62d9c8c048eca","retention_sha256":"4a4b5048c97b16e041af55b032c0b8ac20f5142c4bbcbf31b31c6674770a70d0"},"environment_class":"disposable-live-resources","manual_assumptions":["Airtable supplies no idempotency key for this PATCH; durable gateway admission prevents a second entry.","Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only a fresh GET with the exact replacement and echo can reconcile a lost response.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths.","The reviewed fixed Airtable base and table contain only owner-authorized disposable qualification records."],"oracle_version":"auths-reviewed-reference-v2","provider":"airtable","schema":"auths.provider-contract/1"} \ No newline at end of file +{"api_release":"web-api-v0-reviewed-2026-10-07","corpus_manifest_sha256":"1879c108bdafa40d48d97291b7c1ac79f1ed5c02ec0a3dda967619b9f7bf42af","declarations":{"idempotency_sha256":"74234e98afe7498fb5daf1f36ac2d78acc339464f950703b8c019892f982b90b","observation_sha256":"9dd79dd204fa13a2df3c667d106c66c0526d174a2c018631e2b2f6b897eaf311","recovery_sha256":"7081a92b4cd2d13dab5e7c30e640675a252b62bca20d340e14d62d9c8c048eca","retention_sha256":"4a4b5048c97b16e041af55b032c0b8ac20f5142c4bbcbf31b31c6674770a70d0"},"environment_class":"disposable-live-resources","manual_assumptions":["Airtable supplies no idempotency key for this PATCH; durable gateway admission prevents a second entry.","Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only a fresh GET with the exact replacement and echo can reconcile a lost response.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths.","The reviewed fixed Airtable base and table contain only owner-authorized disposable qualification records."],"oracle_version":"auths-reviewed-reference-v2","provider":"airtable","schema":"auths.provider-contract/1"} \ No newline at end of file diff --git a/qualification/families/airtable-record-update-v1/corpus-manifest.json b/qualification/families/airtable-record-update-v1/corpus-manifest.json index c1c6e370f..d88dc70ec 100644 --- a/qualification/families/airtable-record-update-v1/corpus-manifest.json +++ b/qualification/families/airtable-record-update-v1/corpus-manifest.json @@ -1 +1 @@ -{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"32241d9b4811a55abcdd224ef567df3857dbec34d761ef7a35d1044cdfa52d9f","family":"airtable-record-update-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"af7f984509ab11a3676cacc85eda2fa638c25bf91f7bfedf3ff3c119e47f3c41","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","application_probe.py":"5e2dd6a91eb0a2acf2df1079cead5bd67ae5d6743abce6e48201e7326f63daa2","artifact_wait.py":"56efcf5a34103955e43c1d3be7fd58843efdc8095187d74dc890cf3342863f55","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","close_proposal.py":"9a6927722ada8eaba720ff13168101244880da3fe6f2c95f653bc3840ef81756","commission.py":"f4495d6e3d2b9c50e72e339e9571eacd9b3628ebebe7c86c601b94e785a5c9fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","controller_socket.py":"10519cc775e963360870eac51c7fcac1ffb988b04d5de89dac1dbf3524ba6531","custody_fault.py":"f5e95620a1bb3fccc733be13c6ab68b6e84c0b134a6b54252766e4e57410907f","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"a3662539a9a130f5272cbd8b3750be3ebb46d4ad903aba7afa10880f99a2f601","family_harness.py":"0e0a42be6cf75dfb3f674b26cbdfbb4c473edea71083dfaad89ecb40dec039ba","family_operations.py":"37dca5e6ed97a5edbff3408663589258a3db2aac400b2d9e12ae8f603f61bda1","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","installed_submit.mjs":"9d57a91c4a052fbb9103582689ee99a6d087758dcfee00defa4c762b87187468","installed_submit.py":"f9151c2dffa1a02327b0ba05bdeb180654918a2b913195185a6649d010783dc7","journey_session.py":"3c807ce45dcabe3b39d63333872af3746fe9276aacf5eba30bf903b51d80dfef","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"580fa1db01a6fa7691d618f123f9117ce39b25e6478460ceac46c1e650d6b454","network_fault.py":"94340720d8601f79ac77b95d1e855be25195c19b67db3103bbf054d82c02472b","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","production_environment.py":"607a0bc37396a5a86da1d408b384ee4a54d920b849009717587150242bd47d73","production_journey.py":"1b019d80eace9687cbd6acd21b3e1978ae2e8885c2c81dff4fbe9a3b7be3e314","production_setup.py":"eac6cda2c2bff17364e72512b70ecfc3b6dad8c70088c1fe83d59f4ebaa395a0","provider_readback.py":"d576768208985b3544f146597d181d796f2a5e2eca5026dae3fa15cadcfe65b2","resource_io.py":"b0ed0223fd11a1a28c25278de539a9b2ed63881b26a8e00e386f25d4d9aa9384","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","retained_author.py":"bfd01c7df44f5f525326dfbda13b5ebc6b854f15787a8b2923de883fe20fdcf9","sign_release.py":"d0aa7697cc6889538dfd54f9101a5b7bc2e8f7aede729da2d382b6466781df99","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489","tls_fault.py":"10e125f9623bc32a420a1d83e6d46fe30aa1ca8ff4da97a3e2422fc0e11ec42d"},"source_recipe_sha256":"c0f21ff1d3c8e344fee20a9a0c25bb14a264417ed53418ad536789a6096fb16e"} \ No newline at end of file +{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"32241d9b4811a55abcdd224ef567df3857dbec34d761ef7a35d1044cdfa52d9f","family":"airtable-record-update-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"af7f984509ab11a3676cacc85eda2fa638c25bf91f7bfedf3ff3c119e47f3c41","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","application_probe.py":"5e2dd6a91eb0a2acf2df1079cead5bd67ae5d6743abce6e48201e7326f63daa2","artifact_wait.py":"56efcf5a34103955e43c1d3be7fd58843efdc8095187d74dc890cf3342863f55","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","close_proposal.py":"9a6927722ada8eaba720ff13168101244880da3fe6f2c95f653bc3840ef81756","commission.py":"f4495d6e3d2b9c50e72e339e9571eacd9b3628ebebe7c86c601b94e785a5c9fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","controller_socket.py":"10519cc775e963360870eac51c7fcac1ffb988b04d5de89dac1dbf3524ba6531","custody_fault.py":"f5e95620a1bb3fccc733be13c6ab68b6e84c0b134a6b54252766e4e57410907f","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"a3662539a9a130f5272cbd8b3750be3ebb46d4ad903aba7afa10880f99a2f601","family_harness.py":"0e0a42be6cf75dfb3f674b26cbdfbb4c473edea71083dfaad89ecb40dec039ba","family_operations.py":"3741c3fdbcc4ef884d36abc113706281b6dd409d90e6bbb3a4866b4a3d29beb6","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","installed_submit.mjs":"9d57a91c4a052fbb9103582689ee99a6d087758dcfee00defa4c762b87187468","installed_submit.py":"f9151c2dffa1a02327b0ba05bdeb180654918a2b913195185a6649d010783dc7","journey_session.py":"3c807ce45dcabe3b39d63333872af3746fe9276aacf5eba30bf903b51d80dfef","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"580fa1db01a6fa7691d618f123f9117ce39b25e6478460ceac46c1e650d6b454","network_fault.py":"94340720d8601f79ac77b95d1e855be25195c19b67db3103bbf054d82c02472b","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","production_environment.py":"607a0bc37396a5a86da1d408b384ee4a54d920b849009717587150242bd47d73","production_journey.py":"1b019d80eace9687cbd6acd21b3e1978ae2e8885c2c81dff4fbe9a3b7be3e314","production_setup.py":"eac6cda2c2bff17364e72512b70ecfc3b6dad8c70088c1fe83d59f4ebaa395a0","provider_readback.py":"d576768208985b3544f146597d181d796f2a5e2eca5026dae3fa15cadcfe65b2","resource_io.py":"18d9b11674cc9f0df6c6050b375e476675735927bed03f5a94d78674d4a35885","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","retained_author.py":"bfd01c7df44f5f525326dfbda13b5ebc6b854f15787a8b2923de883fe20fdcf9","sign_release.py":"d0aa7697cc6889538dfd54f9101a5b7bc2e8f7aede729da2d382b6466781df99","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489","tls_fault.py":"10e125f9623bc32a420a1d83e6d46fe30aa1ca8ff4da97a3e2422fc0e11ec42d"},"source_recipe_sha256":"c0f21ff1d3c8e344fee20a9a0c25bb14a264417ed53418ad536789a6096fb16e"} \ No newline at end of file diff --git a/qualification/families/stripe-platform-refund-v1/contract.json b/qualification/families/stripe-platform-refund-v1/contract.json index a00524a10..c631acf29 100644 --- a/qualification/families/stripe-platform-refund-v1/contract.json +++ b/qualification/families/stripe-platform-refund-v1/contract.json @@ -1 +1 @@ -{"api_release":"2025-03-31.basil","corpus_manifest_sha256":"54050ff518d37580f9f19d57a7406720360c87c0e2218446708196e324eae1de","declarations":{"idempotency_sha256":"425a0dca2f279765debfc847c4a01bff60fea5be68dd9d761ae6bb60ce0b8a7b","observation_sha256":"d0ce5a34d987821c69c0a839d9ed66805c625f8324dd42031fcccf0752a8821e","recovery_sha256":"bf2303abce165c175360ac975586431bbc4cf03167489ea317a27de2f0b04abb","retention_sha256":"846c2164e26d1144d9aa146034b4f7ea4dc305136a59ffd94f999d19f2c360ee"},"environment_class":"provider-test-mode","manual_assumptions":["Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","Stripe idempotency is tested only inside the declared 86400-second retention interval.","Stripe test mode and the installed platform are checked by the declared guard on each lease.","The 50-percent payment basis is a read, not an atomic provider balance reservation.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths."],"oracle_version":"auths-reviewed-reference-v2","provider":"stripe","schema":"auths.provider-contract/1"} \ No newline at end of file +{"api_release":"2025-03-31.basil","corpus_manifest_sha256":"b259f0ff26aabbd17fcafc72cea5c284fb264186fc5a1b9cb9519d92d9becdce","declarations":{"idempotency_sha256":"425a0dca2f279765debfc847c4a01bff60fea5be68dd9d761ae6bb60ce0b8a7b","observation_sha256":"d0ce5a34d987821c69c0a839d9ed66805c625f8324dd42031fcccf0752a8821e","recovery_sha256":"bf2303abce165c175360ac975586431bbc4cf03167489ea317a27de2f0b04abb","retention_sha256":"846c2164e26d1144d9aa146034b4f7ea4dc305136a59ffd94f999d19f2c360ee"},"environment_class":"provider-test-mode","manual_assumptions":["Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","Stripe idempotency is tested only inside the declared 86400-second retention interval.","Stripe test mode and the installed platform are checked by the declared guard on each lease.","The 50-percent payment basis is a read, not an atomic provider balance reservation.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths."],"oracle_version":"auths-reviewed-reference-v2","provider":"stripe","schema":"auths.provider-contract/1"} \ No newline at end of file diff --git a/qualification/families/stripe-platform-refund-v1/corpus-manifest.json b/qualification/families/stripe-platform-refund-v1/corpus-manifest.json index dee9157d0..949aa3027 100644 --- a/qualification/families/stripe-platform-refund-v1/corpus-manifest.json +++ b/qualification/families/stripe-platform-refund-v1/corpus-manifest.json @@ -1 +1 @@ -{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"a72c557b69103a52eb477deb8364ded53cd58407b9ba7ab33ccbda74389fec1e","family":"stripe-platform-refund-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"99901e36cb7c4f5882897603c874698d582e859b5d6b08d53cd80975e89aa01c","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","application_probe.py":"5e2dd6a91eb0a2acf2df1079cead5bd67ae5d6743abce6e48201e7326f63daa2","artifact_wait.py":"56efcf5a34103955e43c1d3be7fd58843efdc8095187d74dc890cf3342863f55","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","close_proposal.py":"9a6927722ada8eaba720ff13168101244880da3fe6f2c95f653bc3840ef81756","commission.py":"f4495d6e3d2b9c50e72e339e9571eacd9b3628ebebe7c86c601b94e785a5c9fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","controller_socket.py":"10519cc775e963360870eac51c7fcac1ffb988b04d5de89dac1dbf3524ba6531","custody_fault.py":"f5e95620a1bb3fccc733be13c6ab68b6e84c0b134a6b54252766e4e57410907f","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"a3662539a9a130f5272cbd8b3750be3ebb46d4ad903aba7afa10880f99a2f601","family_harness.py":"0e0a42be6cf75dfb3f674b26cbdfbb4c473edea71083dfaad89ecb40dec039ba","family_operations.py":"37dca5e6ed97a5edbff3408663589258a3db2aac400b2d9e12ae8f603f61bda1","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","installed_submit.mjs":"9d57a91c4a052fbb9103582689ee99a6d087758dcfee00defa4c762b87187468","installed_submit.py":"f9151c2dffa1a02327b0ba05bdeb180654918a2b913195185a6649d010783dc7","journey_session.py":"3c807ce45dcabe3b39d63333872af3746fe9276aacf5eba30bf903b51d80dfef","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"580fa1db01a6fa7691d618f123f9117ce39b25e6478460ceac46c1e650d6b454","network_fault.py":"94340720d8601f79ac77b95d1e855be25195c19b67db3103bbf054d82c02472b","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","production_environment.py":"607a0bc37396a5a86da1d408b384ee4a54d920b849009717587150242bd47d73","production_journey.py":"1b019d80eace9687cbd6acd21b3e1978ae2e8885c2c81dff4fbe9a3b7be3e314","production_setup.py":"eac6cda2c2bff17364e72512b70ecfc3b6dad8c70088c1fe83d59f4ebaa395a0","provider_readback.py":"d576768208985b3544f146597d181d796f2a5e2eca5026dae3fa15cadcfe65b2","resource_io.py":"b0ed0223fd11a1a28c25278de539a9b2ed63881b26a8e00e386f25d4d9aa9384","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","retained_author.py":"bfd01c7df44f5f525326dfbda13b5ebc6b854f15787a8b2923de883fe20fdcf9","sign_release.py":"d0aa7697cc6889538dfd54f9101a5b7bc2e8f7aede729da2d382b6466781df99","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489","tls_fault.py":"10e125f9623bc32a420a1d83e6d46fe30aa1ca8ff4da97a3e2422fc0e11ec42d"},"source_recipe_sha256":"b1972d556f28433932a449636755077f7ee485ef90cca412f153bc7f18881368"} \ No newline at end of file +{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"a72c557b69103a52eb477deb8364ded53cd58407b9ba7ab33ccbda74389fec1e","family":"stripe-platform-refund-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"99901e36cb7c4f5882897603c874698d582e859b5d6b08d53cd80975e89aa01c","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","application_probe.py":"5e2dd6a91eb0a2acf2df1079cead5bd67ae5d6743abce6e48201e7326f63daa2","artifact_wait.py":"56efcf5a34103955e43c1d3be7fd58843efdc8095187d74dc890cf3342863f55","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","close_proposal.py":"9a6927722ada8eaba720ff13168101244880da3fe6f2c95f653bc3840ef81756","commission.py":"f4495d6e3d2b9c50e72e339e9571eacd9b3628ebebe7c86c601b94e785a5c9fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","controller_socket.py":"10519cc775e963360870eac51c7fcac1ffb988b04d5de89dac1dbf3524ba6531","custody_fault.py":"f5e95620a1bb3fccc733be13c6ab68b6e84c0b134a6b54252766e4e57410907f","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"a3662539a9a130f5272cbd8b3750be3ebb46d4ad903aba7afa10880f99a2f601","family_harness.py":"0e0a42be6cf75dfb3f674b26cbdfbb4c473edea71083dfaad89ecb40dec039ba","family_operations.py":"3741c3fdbcc4ef884d36abc113706281b6dd409d90e6bbb3a4866b4a3d29beb6","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","installed_submit.mjs":"9d57a91c4a052fbb9103582689ee99a6d087758dcfee00defa4c762b87187468","installed_submit.py":"f9151c2dffa1a02327b0ba05bdeb180654918a2b913195185a6649d010783dc7","journey_session.py":"3c807ce45dcabe3b39d63333872af3746fe9276aacf5eba30bf903b51d80dfef","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"580fa1db01a6fa7691d618f123f9117ce39b25e6478460ceac46c1e650d6b454","network_fault.py":"94340720d8601f79ac77b95d1e855be25195c19b67db3103bbf054d82c02472b","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","production_environment.py":"607a0bc37396a5a86da1d408b384ee4a54d920b849009717587150242bd47d73","production_journey.py":"1b019d80eace9687cbd6acd21b3e1978ae2e8885c2c81dff4fbe9a3b7be3e314","production_setup.py":"eac6cda2c2bff17364e72512b70ecfc3b6dad8c70088c1fe83d59f4ebaa395a0","provider_readback.py":"d576768208985b3544f146597d181d796f2a5e2eca5026dae3fa15cadcfe65b2","resource_io.py":"18d9b11674cc9f0df6c6050b375e476675735927bed03f5a94d78674d4a35885","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","retained_author.py":"bfd01c7df44f5f525326dfbda13b5ebc6b854f15787a8b2923de883fe20fdcf9","sign_release.py":"d0aa7697cc6889538dfd54f9101a5b7bc2e8f7aede729da2d382b6466781df99","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489","tls_fault.py":"10e125f9623bc32a420a1d83e6d46fe30aa1ca8ff4da97a3e2422fc0e11ec42d"},"source_recipe_sha256":"b1972d556f28433932a449636755077f7ee485ef90cca412f153bc7f18881368"} \ No newline at end of file diff --git a/qualification/reference/README.md b/qualification/reference/README.md index d50ea0033..ad3018447 100644 --- a/qualification/reference/README.md +++ b/qualification/reference/README.md @@ -392,3 +392,10 @@ journals, while its operator identity is still available. It never enumerates AWS resources, deletes another connection, or reports native collection for a partial setup. Completed cohorts require native store-only revocation and collection. Failed phases remain invalid and cannot publish a qualification. + +Airtable fixture requests, independent reads and case starts share a source-only +1.1-second spacing window. This leaves room for the unmodified gateway under +the provider's [five requests per second per base limit](https://support.airtable.com/articles/7735693959-managing-api-call-limits-in-airtable). +The two-host race remains concurrent inside its case. This is rehearsal pacing, +not a production rate limiter or a trusted-clock input; a provider refusal remains +the actual failure, and no write is retried to manufacture a passing result. diff --git a/qualification/reference/family_operations.py b/qualification/reference/family_operations.py index e4661f6e8..e08adeefb 100644 --- a/qualification/reference/family_operations.py +++ b/qualification/reference/family_operations.py @@ -580,6 +580,8 @@ def step(self, case, index, operation): 'qualification.operations.phase') require((case, index) not in self.started, 'qualification.operations.repeated-step') self.started.add((case, index)) + if self.reference is airtable_record: + resource_io.pace_airtable() # Source-owned sequences, independent of candidate/corpus outcomes. if identifier in ['fresh-replay', 'proof-replay']: require(index in [0, 1] and operation == ['submit', 'replay'][index], diff --git a/qualification/reference/resource_io.py b/qualification/reference/resource_io.py index 6a850d97a..698bd4077 100644 --- a/qualification/reference/resource_io.py +++ b/qualification/reference/resource_io.py @@ -7,12 +7,30 @@ import stat import subprocess import sys +import threading +import time import urllib.error import urllib.request from common import Refusal, canonical, closed, require from fresh_evidence import decode +# Source-owned fixture/read traffic shares Airtable's base limit with the +# unmodified gateway. Leave a whole window between source calls/case starts; +# never retry a provider write or change a gateway result after a 429. +AIRTABLE_INTERVAL = 1.1 +_airtable_lock = threading.Lock() +_airtable_next = 0.0 + + +def pace_airtable(): + global _airtable_next + with _airtable_lock: + delay = _airtable_next - time.monotonic() + if delay > 0: + time.sleep(delay) + _airtable_next = time.monotonic() + AIRTABLE_INTERVAL + def run_id(value): require(type(value) is str and re.fullmatch(r'[a-z][a-z0-9-]{0,63}/[0-9]{1,20}/[0-9]{1,20}', value), @@ -44,6 +62,8 @@ def redirect_request(self, req, fp, code, msg, headers, newurl): def exchange(origin, method, path, key, body=None, headers=None): require(path.startswith('/') and not path.startswith('//') and '\r' not in path and '\n' not in path, 'qualification.resources.path-bound') + if origin == 'https://api.airtable.com': + pace_airtable() values = {'Authorization': 'Bearer ' + key, 'Accept': 'application/json'} values.update(headers or {}) outbound = urllib.request.Request(origin + path, method=method, data=body, headers=values) diff --git a/qualification/reference/tests/test_resources.py b/qualification/reference/tests/test_resources.py index c9abbf523..b550eb2bd 100644 --- a/qualification/reference/tests/test_resources.py +++ b/qualification/reference/tests/test_resources.py @@ -10,6 +10,7 @@ import sys import tempfile import unittest +from unittest.mock import patch import urllib.parse sys.path.insert(0, str(Path(__file__).resolve().parents[1])) @@ -104,6 +105,27 @@ def api(self, method, path, fields=None): class Resources(unittest.TestCase): + def test_airtable_pacing_preserves_spacing_after_oversleep_and_idle(self): + clock, waits = [100.0], [] + + def sleep(delay): + waits.append(delay) + clock[0] += delay + 0.25 + + with patch.object(resource_io, '_airtable_next', 0.0), \ + patch.object(resource_io.time, 'monotonic', lambda: clock[0]), \ + patch.object(resource_io.time, 'sleep', sleep): + resource_io.pace_airtable() + self.assertFalse(waits) + resource_io.pace_airtable() + self.assertAlmostEqual(waits[0], resource_io.AIRTABLE_INTERVAL) + second_start = clock[0] + resource_io.pace_airtable() + self.assertGreaterEqual(clock[0] - second_start, resource_io.AIRTABLE_INTERVAL) + clock[0] += 10 + resource_io.pace_airtable() + self.assertEqual(len(waits), 2, 'idle source traffic consumes no catch-up burst') + def workspace(self): temporary = tempfile.TemporaryDirectory() self.addCleanup(temporary.cleanup) From 0f3aca178ed4a4b5a996e9d2a6fdfbee55968eb4 Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 19:05:55 +0100 Subject: [PATCH 102/108] Drain source custody restoration before retiring rehearsal state --- .../airtable-record-update-v1/contract.json | 2 +- .../corpus-manifest.json | 2 +- .../stripe-platform-refund-v1/contract.json | 2 +- .../corpus-manifest.json | 2 +- qualification/reference/README.md | 7 +++++++ qualification/reference/production_journey.py | 13 +++++++++---- .../reference/tests/test_journey_session.py | 17 +++++++++++++++++ 7 files changed, 37 insertions(+), 8 deletions(-) diff --git a/qualification/families/airtable-record-update-v1/contract.json b/qualification/families/airtable-record-update-v1/contract.json index 426abdadb..73749c6dd 100644 --- a/qualification/families/airtable-record-update-v1/contract.json +++ b/qualification/families/airtable-record-update-v1/contract.json @@ -1 +1 @@ -{"api_release":"web-api-v0-reviewed-2026-10-07","corpus_manifest_sha256":"1879c108bdafa40d48d97291b7c1ac79f1ed5c02ec0a3dda967619b9f7bf42af","declarations":{"idempotency_sha256":"74234e98afe7498fb5daf1f36ac2d78acc339464f950703b8c019892f982b90b","observation_sha256":"9dd79dd204fa13a2df3c667d106c66c0526d174a2c018631e2b2f6b897eaf311","recovery_sha256":"7081a92b4cd2d13dab5e7c30e640675a252b62bca20d340e14d62d9c8c048eca","retention_sha256":"4a4b5048c97b16e041af55b032c0b8ac20f5142c4bbcbf31b31c6674770a70d0"},"environment_class":"disposable-live-resources","manual_assumptions":["Airtable supplies no idempotency key for this PATCH; durable gateway admission prevents a second entry.","Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only a fresh GET with the exact replacement and echo can reconcile a lost response.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths.","The reviewed fixed Airtable base and table contain only owner-authorized disposable qualification records."],"oracle_version":"auths-reviewed-reference-v2","provider":"airtable","schema":"auths.provider-contract/1"} \ No newline at end of file +{"api_release":"web-api-v0-reviewed-2026-10-07","corpus_manifest_sha256":"47f191e58efd16b0de63082484f7df56367c9f4842b9110a7cb2a7a1a5fe38e2","declarations":{"idempotency_sha256":"74234e98afe7498fb5daf1f36ac2d78acc339464f950703b8c019892f982b90b","observation_sha256":"9dd79dd204fa13a2df3c667d106c66c0526d174a2c018631e2b2f6b897eaf311","recovery_sha256":"7081a92b4cd2d13dab5e7c30e640675a252b62bca20d340e14d62d9c8c048eca","retention_sha256":"4a4b5048c97b16e041af55b032c0b8ac20f5142c4bbcbf31b31c6674770a70d0"},"environment_class":"disposable-live-resources","manual_assumptions":["Airtable supplies no idempotency key for this PATCH; durable gateway admission prevents a second entry.","Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only a fresh GET with the exact replacement and echo can reconcile a lost response.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths.","The reviewed fixed Airtable base and table contain only owner-authorized disposable qualification records."],"oracle_version":"auths-reviewed-reference-v2","provider":"airtable","schema":"auths.provider-contract/1"} \ No newline at end of file diff --git a/qualification/families/airtable-record-update-v1/corpus-manifest.json b/qualification/families/airtable-record-update-v1/corpus-manifest.json index d88dc70ec..2e8ea18b1 100644 --- a/qualification/families/airtable-record-update-v1/corpus-manifest.json +++ b/qualification/families/airtable-record-update-v1/corpus-manifest.json @@ -1 +1 @@ -{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"32241d9b4811a55abcdd224ef567df3857dbec34d761ef7a35d1044cdfa52d9f","family":"airtable-record-update-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"af7f984509ab11a3676cacc85eda2fa638c25bf91f7bfedf3ff3c119e47f3c41","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","application_probe.py":"5e2dd6a91eb0a2acf2df1079cead5bd67ae5d6743abce6e48201e7326f63daa2","artifact_wait.py":"56efcf5a34103955e43c1d3be7fd58843efdc8095187d74dc890cf3342863f55","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","close_proposal.py":"9a6927722ada8eaba720ff13168101244880da3fe6f2c95f653bc3840ef81756","commission.py":"f4495d6e3d2b9c50e72e339e9571eacd9b3628ebebe7c86c601b94e785a5c9fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","controller_socket.py":"10519cc775e963360870eac51c7fcac1ffb988b04d5de89dac1dbf3524ba6531","custody_fault.py":"f5e95620a1bb3fccc733be13c6ab68b6e84c0b134a6b54252766e4e57410907f","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"a3662539a9a130f5272cbd8b3750be3ebb46d4ad903aba7afa10880f99a2f601","family_harness.py":"0e0a42be6cf75dfb3f674b26cbdfbb4c473edea71083dfaad89ecb40dec039ba","family_operations.py":"3741c3fdbcc4ef884d36abc113706281b6dd409d90e6bbb3a4866b4a3d29beb6","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","installed_submit.mjs":"9d57a91c4a052fbb9103582689ee99a6d087758dcfee00defa4c762b87187468","installed_submit.py":"f9151c2dffa1a02327b0ba05bdeb180654918a2b913195185a6649d010783dc7","journey_session.py":"3c807ce45dcabe3b39d63333872af3746fe9276aacf5eba30bf903b51d80dfef","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"580fa1db01a6fa7691d618f123f9117ce39b25e6478460ceac46c1e650d6b454","network_fault.py":"94340720d8601f79ac77b95d1e855be25195c19b67db3103bbf054d82c02472b","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","production_environment.py":"607a0bc37396a5a86da1d408b384ee4a54d920b849009717587150242bd47d73","production_journey.py":"1b019d80eace9687cbd6acd21b3e1978ae2e8885c2c81dff4fbe9a3b7be3e314","production_setup.py":"eac6cda2c2bff17364e72512b70ecfc3b6dad8c70088c1fe83d59f4ebaa395a0","provider_readback.py":"d576768208985b3544f146597d181d796f2a5e2eca5026dae3fa15cadcfe65b2","resource_io.py":"18d9b11674cc9f0df6c6050b375e476675735927bed03f5a94d78674d4a35885","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","retained_author.py":"bfd01c7df44f5f525326dfbda13b5ebc6b854f15787a8b2923de883fe20fdcf9","sign_release.py":"d0aa7697cc6889538dfd54f9101a5b7bc2e8f7aede729da2d382b6466781df99","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489","tls_fault.py":"10e125f9623bc32a420a1d83e6d46fe30aa1ca8ff4da97a3e2422fc0e11ec42d"},"source_recipe_sha256":"c0f21ff1d3c8e344fee20a9a0c25bb14a264417ed53418ad536789a6096fb16e"} \ No newline at end of file +{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"32241d9b4811a55abcdd224ef567df3857dbec34d761ef7a35d1044cdfa52d9f","family":"airtable-record-update-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"af7f984509ab11a3676cacc85eda2fa638c25bf91f7bfedf3ff3c119e47f3c41","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","application_probe.py":"5e2dd6a91eb0a2acf2df1079cead5bd67ae5d6743abce6e48201e7326f63daa2","artifact_wait.py":"56efcf5a34103955e43c1d3be7fd58843efdc8095187d74dc890cf3342863f55","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","close_proposal.py":"9a6927722ada8eaba720ff13168101244880da3fe6f2c95f653bc3840ef81756","commission.py":"f4495d6e3d2b9c50e72e339e9571eacd9b3628ebebe7c86c601b94e785a5c9fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","controller_socket.py":"10519cc775e963360870eac51c7fcac1ffb988b04d5de89dac1dbf3524ba6531","custody_fault.py":"f5e95620a1bb3fccc733be13c6ab68b6e84c0b134a6b54252766e4e57410907f","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"a3662539a9a130f5272cbd8b3750be3ebb46d4ad903aba7afa10880f99a2f601","family_harness.py":"0e0a42be6cf75dfb3f674b26cbdfbb4c473edea71083dfaad89ecb40dec039ba","family_operations.py":"3741c3fdbcc4ef884d36abc113706281b6dd409d90e6bbb3a4866b4a3d29beb6","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","installed_submit.mjs":"9d57a91c4a052fbb9103582689ee99a6d087758dcfee00defa4c762b87187468","installed_submit.py":"f9151c2dffa1a02327b0ba05bdeb180654918a2b913195185a6649d010783dc7","journey_session.py":"3c807ce45dcabe3b39d63333872af3746fe9276aacf5eba30bf903b51d80dfef","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"580fa1db01a6fa7691d618f123f9117ce39b25e6478460ceac46c1e650d6b454","network_fault.py":"94340720d8601f79ac77b95d1e855be25195c19b67db3103bbf054d82c02472b","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","production_environment.py":"607a0bc37396a5a86da1d408b384ee4a54d920b849009717587150242bd47d73","production_journey.py":"db7f6dc7f0fdc1b5acff1339cdf5bf7f11f3ba826aeca626a76d761bec0121a8","production_setup.py":"eac6cda2c2bff17364e72512b70ecfc3b6dad8c70088c1fe83d59f4ebaa395a0","provider_readback.py":"d576768208985b3544f146597d181d796f2a5e2eca5026dae3fa15cadcfe65b2","resource_io.py":"18d9b11674cc9f0df6c6050b375e476675735927bed03f5a94d78674d4a35885","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","retained_author.py":"bfd01c7df44f5f525326dfbda13b5ebc6b854f15787a8b2923de883fe20fdcf9","sign_release.py":"d0aa7697cc6889538dfd54f9101a5b7bc2e8f7aede729da2d382b6466781df99","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489","tls_fault.py":"10e125f9623bc32a420a1d83e6d46fe30aa1ca8ff4da97a3e2422fc0e11ec42d"},"source_recipe_sha256":"c0f21ff1d3c8e344fee20a9a0c25bb14a264417ed53418ad536789a6096fb16e"} \ No newline at end of file diff --git a/qualification/families/stripe-platform-refund-v1/contract.json b/qualification/families/stripe-platform-refund-v1/contract.json index c631acf29..a75c721e4 100644 --- a/qualification/families/stripe-platform-refund-v1/contract.json +++ b/qualification/families/stripe-platform-refund-v1/contract.json @@ -1 +1 @@ -{"api_release":"2025-03-31.basil","corpus_manifest_sha256":"b259f0ff26aabbd17fcafc72cea5c284fb264186fc5a1b9cb9519d92d9becdce","declarations":{"idempotency_sha256":"425a0dca2f279765debfc847c4a01bff60fea5be68dd9d761ae6bb60ce0b8a7b","observation_sha256":"d0ce5a34d987821c69c0a839d9ed66805c625f8324dd42031fcccf0752a8821e","recovery_sha256":"bf2303abce165c175360ac975586431bbc4cf03167489ea317a27de2f0b04abb","retention_sha256":"846c2164e26d1144d9aa146034b4f7ea4dc305136a59ffd94f999d19f2c360ee"},"environment_class":"provider-test-mode","manual_assumptions":["Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","Stripe idempotency is tested only inside the declared 86400-second retention interval.","Stripe test mode and the installed platform are checked by the declared guard on each lease.","The 50-percent payment basis is a read, not an atomic provider balance reservation.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths."],"oracle_version":"auths-reviewed-reference-v2","provider":"stripe","schema":"auths.provider-contract/1"} \ No newline at end of file +{"api_release":"2025-03-31.basil","corpus_manifest_sha256":"5b55fc440715d9f18993910f9680d679371512f31748321b019c88f1e3b5de79","declarations":{"idempotency_sha256":"425a0dca2f279765debfc847c4a01bff60fea5be68dd9d761ae6bb60ce0b8a7b","observation_sha256":"d0ce5a34d987821c69c0a839d9ed66805c625f8324dd42031fcccf0752a8821e","recovery_sha256":"bf2303abce165c175360ac975586431bbc4cf03167489ea317a27de2f0b04abb","retention_sha256":"846c2164e26d1144d9aa146034b4f7ea4dc305136a59ffd94f999d19f2c360ee"},"environment_class":"provider-test-mode","manual_assumptions":["Fresh matching state and the action-derived echo are required; HTTP success is not effect confirmation.","Only the closed run-owned resource ledger is in scope; every cleanup must be freshly confirmed.","Stripe idempotency is tested only inside the declared 86400-second retention interval.","Stripe test mode and the installed platform are checked by the declared guard on each lease.","The 50-percent payment basis is a read, not an atomic provider balance reservation.","The provider is independently operated; availability and concurrent outside writes are not controlled by Auths."],"oracle_version":"auths-reviewed-reference-v2","provider":"stripe","schema":"auths.provider-contract/1"} \ No newline at end of file diff --git a/qualification/families/stripe-platform-refund-v1/corpus-manifest.json b/qualification/families/stripe-platform-refund-v1/corpus-manifest.json index 949aa3027..f41d69523 100644 --- a/qualification/families/stripe-platform-refund-v1/corpus-manifest.json +++ b/qualification/families/stripe-platform-refund-v1/corpus-manifest.json @@ -1 +1 @@ -{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"a72c557b69103a52eb477deb8364ded53cd58407b9ba7ab33ccbda74389fec1e","family":"stripe-platform-refund-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"99901e36cb7c4f5882897603c874698d582e859b5d6b08d53cd80975e89aa01c","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","application_probe.py":"5e2dd6a91eb0a2acf2df1079cead5bd67ae5d6743abce6e48201e7326f63daa2","artifact_wait.py":"56efcf5a34103955e43c1d3be7fd58843efdc8095187d74dc890cf3342863f55","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","close_proposal.py":"9a6927722ada8eaba720ff13168101244880da3fe6f2c95f653bc3840ef81756","commission.py":"f4495d6e3d2b9c50e72e339e9571eacd9b3628ebebe7c86c601b94e785a5c9fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","controller_socket.py":"10519cc775e963360870eac51c7fcac1ffb988b04d5de89dac1dbf3524ba6531","custody_fault.py":"f5e95620a1bb3fccc733be13c6ab68b6e84c0b134a6b54252766e4e57410907f","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"a3662539a9a130f5272cbd8b3750be3ebb46d4ad903aba7afa10880f99a2f601","family_harness.py":"0e0a42be6cf75dfb3f674b26cbdfbb4c473edea71083dfaad89ecb40dec039ba","family_operations.py":"3741c3fdbcc4ef884d36abc113706281b6dd409d90e6bbb3a4866b4a3d29beb6","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","installed_submit.mjs":"9d57a91c4a052fbb9103582689ee99a6d087758dcfee00defa4c762b87187468","installed_submit.py":"f9151c2dffa1a02327b0ba05bdeb180654918a2b913195185a6649d010783dc7","journey_session.py":"3c807ce45dcabe3b39d63333872af3746fe9276aacf5eba30bf903b51d80dfef","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"580fa1db01a6fa7691d618f123f9117ce39b25e6478460ceac46c1e650d6b454","network_fault.py":"94340720d8601f79ac77b95d1e855be25195c19b67db3103bbf054d82c02472b","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","production_environment.py":"607a0bc37396a5a86da1d408b384ee4a54d920b849009717587150242bd47d73","production_journey.py":"1b019d80eace9687cbd6acd21b3e1978ae2e8885c2c81dff4fbe9a3b7be3e314","production_setup.py":"eac6cda2c2bff17364e72512b70ecfc3b6dad8c70088c1fe83d59f4ebaa395a0","provider_readback.py":"d576768208985b3544f146597d181d796f2a5e2eca5026dae3fa15cadcfe65b2","resource_io.py":"18d9b11674cc9f0df6c6050b375e476675735927bed03f5a94d78674d4a35885","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","retained_author.py":"bfd01c7df44f5f525326dfbda13b5ebc6b854f15787a8b2923de883fe20fdcf9","sign_release.py":"d0aa7697cc6889538dfd54f9101a5b7bc2e8f7aede729da2d382b6466781df99","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489","tls_fault.py":"10e125f9623bc32a420a1d83e6d46fe30aa1ca8ff4da97a3e2422fc0e11ec42d"},"source_recipe_sha256":"b1972d556f28433932a449636755077f7ee485ef90cca412f153bc7f18881368"} \ No newline at end of file +{"compiled_corpus_schema":"auths.qualification-corpus/3","decision_record_sha256":"a72c557b69103a52eb477deb8364ded53cd58407b9ba7ab33ccbda74389fec1e","family":"stripe-platform-refund-v1","maximum_credential_leases":64,"packet_plan_schema":"auths.qualification-packet-plan/4","phases":["offline","commissioning","live"],"profile_lock_sha256":"99901e36cb7c4f5882897603c874698d582e859b5d6b08d53cd80975e89aa01c","public_packet_schema":"auths.qualification-public-packets/4","resource_count":16,"schema":"auths.qualification-reviewed-plan/1","source_files":{"airtable_record.py":"d5bf4d750fee75f02200d180f8654f426fe738bc86a281f1d015f391cc5e67fa","airtable_resources.py":"094f7d5c52a4557261c25fba6d5f1e4938091d946a05a422417b6dea22b7e76f","application_probe.py":"5e2dd6a91eb0a2acf2df1079cead5bd67ae5d6743abce6e48201e7326f63daa2","artifact_wait.py":"56efcf5a34103955e43c1d3be7fd58843efdc8095187d74dc890cf3342863f55","author_operator.py":"f3c66e5f6636bfdf317dc87915255f22a97466a34cbb5053b55cdf6e05d6921f","author_packets.py":"84d550b0f82c8501000ffde07ea13720f09caa9079b2c885f65a1f5cc08c2110","author_socket.py":"3d6a031c01d7d9a58213a8368f45b68c25081d059a8ff3cba4fe47c0f75a77fd","close_proposal.py":"9a6927722ada8eaba720ff13168101244880da3fe6f2c95f653bc3840ef81756","commission.py":"f4495d6e3d2b9c50e72e339e9571eacd9b3628ebebe7c86c601b94e785a5c9fd","common.py":"604d3d6598648fbc09611e663b4048b22fa748d0f6c6f1dbbceca5d83c02a2ce","controller_socket.py":"10519cc775e963360870eac51c7fcac1ffb988b04d5de89dac1dbf3524ba6531","custody_fault.py":"f5e95620a1bb3fccc733be13c6ab68b6e84c0b134a6b54252766e4e57410907f","expand.py":"892cf7b04c3847336f150926bfbf3e82665e9e2bc1b154be42e4f57d1922b816","family_corpus.py":"a3662539a9a130f5272cbd8b3750be3ebb46d4ad903aba7afa10880f99a2f601","family_harness.py":"0e0a42be6cf75dfb3f674b26cbdfbb4c473edea71083dfaad89ecb40dec039ba","family_operations.py":"3741c3fdbcc4ef884d36abc113706281b6dd409d90e6bbb3a4866b4a3d29beb6","fresh_evidence.py":"cb54ea66a4775c5af76fbc36c4f8c8a007c553de2b2303e80fd744aee1c54d2f","installed_submit.mjs":"9d57a91c4a052fbb9103582689ee99a6d087758dcfee00defa4c762b87187468","installed_submit.py":"f9151c2dffa1a02327b0ba05bdeb180654918a2b913195185a6649d010783dc7","journey_session.py":"3c807ce45dcabe3b39d63333872af3746fe9276aacf5eba30bf903b51d80dfef","measure.py":"b620be174bc012bc6b29f95e558fce1b6fb2cc99b5fa5a0f0c933c88696b4ca0","native_observation.py":"580fa1db01a6fa7691d618f123f9117ce39b25e6478460ceac46c1e650d6b454","network_fault.py":"94340720d8601f79ac77b95d1e855be25195c19b67db3103bbf054d82c02472b","packet_plan.py":"cf993ba17ba40bd528a08d446bfc7c2e8cf0291f3e202337bcfdafa4ab269a7c","production_environment.py":"607a0bc37396a5a86da1d408b384ee4a54d920b849009717587150242bd47d73","production_journey.py":"db7f6dc7f0fdc1b5acff1339cdf5bf7f11f3ba826aeca626a76d761bec0121a8","production_setup.py":"eac6cda2c2bff17364e72512b70ecfc3b6dad8c70088c1fe83d59f4ebaa395a0","provider_readback.py":"d576768208985b3544f146597d181d796f2a5e2eca5026dae3fa15cadcfe65b2","resource_io.py":"18d9b11674cc9f0df6c6050b375e476675735927bed03f5a94d78674d4a35885","resource_summary.py":"c75f3f23017529ce10197c09649e2d60b3c240b8b58992786b824e85869668e0","retained_author.py":"bfd01c7df44f5f525326dfbda13b5ebc6b854f15787a8b2923de883fe20fdcf9","sign_release.py":"d0aa7697cc6889538dfd54f9101a5b7bc2e8f7aede729da2d382b6466781df99","stripe_platform.py":"2da918e72f0ec3aed4f5a80701748e0d37c71292806bfa38c74ffbe69055c4ec","stripe_resources.py":"2e050b4f5f8654cfb3a7cf9ddaa73b3515a039d5b37071d2d9c0dbafe2561489","tls_fault.py":"10e125f9623bc32a420a1d83e6d46fe30aa1ca8ff4da97a3e2422fc0e11ec42d"},"source_recipe_sha256":"b1972d556f28433932a449636755077f7ee485ef90cca412f153bc7f18881368"} \ No newline at end of file diff --git a/qualification/reference/README.md b/qualification/reference/README.md index ad3018447..66e5cb7fc 100644 --- a/qualification/reference/README.md +++ b/qualification/reference/README.md @@ -399,3 +399,10 @@ the provider's [five requests per second per base limit](https://support.airtabl The two-host race remains concurrent inside its case. This is rehearsal pacing, not a production rate limiter or a trusted-clock input; a provider refusal remains the actual failure, and no write is retried to manufacture a passing result. + +Cleanup first drains the source operation worker, allowing up to 900 seconds +for its bounded native commands and exact AWS restoration attempts. The worker +cannot disappear as a daemon when the session exits. A native case still has +its original 120-second deadline and remains failed after that deadline. If the +worker remains active, cleanup refuses before retiring any credentials, +identity, database or provider resources; restoration cannot race deletion. diff --git a/qualification/reference/production_journey.py b/qualification/reference/production_journey.py index 030c8e716..de30a002c 100644 --- a/qualification/reference/production_journey.py +++ b/qualification/reference/production_journey.py @@ -40,6 +40,9 @@ ENVIRONMENT = 'gateway-custody-live' PHASES = ['prepare', 'commission', 'import-first', 'live', 'cleanup', 'final-proposal'] +# Draining covers the bounded native commands and both four-attempt AWS +# replacements/restorations. It does not extend a native case's 120-second gate. +CONTROLLER_DRAIN_SECONDS = 900 GITHUB_INPUTS = ['GITHUB_REPOSITORY', 'GITHUB_EVENT_NAME', 'GITHUB_REF', 'GITHUB_RUN_ID', 'GITHUB_RUN_ATTEMPT', 'GITHUB_SHA', 'GITHUB_ACTIONS', 'RUNNER_ENVIRONMENT'] @@ -132,7 +135,7 @@ def run(): except BaseException: self.worker_failed = True self.ready.set() - self.worker = threading.Thread(target=run, name='auths-family-operations', daemon=True) + self.worker = threading.Thread(target=run, name='auths-family-operations') self.worker.start() require(self.ready.wait(10) and not self.worker_failed and self.worker.is_alive(), 'qualification.journey.controller-not-ready') @@ -279,9 +282,11 @@ def attempt(action): failures.append(True) self.stopping.set() if self.worker is not None: - self.worker.join(timeout=130) - if self.worker.is_alive(): - failures.append(True) + self.worker.join(timeout=CONTROLLER_DRAIN_SECONDS) + # A worker may still be restoring the exact AWS credential after + # a native case timed out. Retiring its identity, database or + # provider resources here could race that restoration or a write. + require(not self.worker.is_alive(), 'qualification.journey.controller-not-drained') if self.deployment is not None: attempt(self.deployment.close) # Collect while the actual web identity is still renewing. A diff --git a/qualification/reference/tests/test_journey_session.py b/qualification/reference/tests/test_journey_session.py index 44eb4c4ca..692975f8e 100644 --- a/qualification/reference/tests/test_journey_session.py +++ b/qualification/reference/tests/test_journey_session.py @@ -101,6 +101,23 @@ def close(self): calls.append('retire-identity-and-database') self.assertFalse(value.retired) with self.assertRaisesRegex(Refusal, 'cleanup-required'): value.final_proposal() + def test_an_active_restoration_worker_prevents_every_cleanup_mutation(self): + with tempfile.TemporaryDirectory() as directory: + value = self.journey(Path(directory)) + value.stopping = threading.Event() + waits = [] + class Worker: + def join(self, timeout): waits.append(timeout) + def is_alive(self): return True + value.worker = Worker() + # No cleanup dependency is installed: touching any would fail the + # test before the precise controller refusal can be observed. + with self.assertRaisesRegex(Refusal, 'controller-not-drained'): value.cleanup() + self.assertTrue(value.stopping.is_set()) + self.assertEqual(waits, [production.CONTROLLER_DRAIN_SECONDS]) + self.assertFalse(value.retired) + with self.assertRaisesRegex(Refusal, 'cleanup-required'): value.final_proposal() + def test_partial_install_removes_its_database_before_exact_journal_retirement(self): with tempfile.TemporaryDirectory() as directory: value = self.journey(Path(directory)) From 6086c22ccf8fceb59da3962d95c0722fca643af1 Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 19:16:56 +0100 Subject: [PATCH 103/108] Match launch provenance to the exact protected custody environment --- .github/workflows/recipe-qualification.yml | 16 ++++++++++++ ...gateway-polish-and-recipe-qualification.md | 21 ++++++++++++++++ .../tests/protected_run.rs | 25 +++++++++++++++++++ .../auths-recipe-qualification/src/launch.rs | 16 ++++++++++-- .../auths-recipe-qualification/src/verify.rs | 6 +---- .../auths-gateway/semantic-closure.json | 2 +- .../auths-gateway/src/semantic_closure.rs | 2 +- qualification/README.md | 9 ++++--- 8 files changed, 85 insertions(+), 12 deletions(-) diff --git a/.github/workflows/recipe-qualification.yml b/.github/workflows/recipe-qualification.yml index 7fb1a0254..15d0abf75 100644 --- a/.github/workflows/recipe-qualification.yml +++ b/.github/workflows/recipe-qualification.yml @@ -361,6 +361,7 @@ jobs: permissions: contents: read actions: read + deployments: read id-token: write strategy: fail-fast: false @@ -369,6 +370,21 @@ jobs: env: FAMILY: ${{ matrix.family }} steps: + - name: Require reviewer protection and exact main-only custody policy + env: + GH_TOKEN: ${{ github.token }} + run: | + set -euo pipefail + gh api repos/auths-dev/auths-proof/environments/gateway-custody-live \ + > "${RUNNER_TEMP}/custody-environment.json" + jq -e '[.protection_rules[] | select(.type == "required_reviewers" and (.reviewers | length) > 0)] | length == 1' \ + "${RUNNER_TEMP}/custody-environment.json" > /dev/null + jq -e '.deployment_branch_policy.custom_branch_policies == true and .deployment_branch_policy.protected_branches == false' \ + "${RUNNER_TEMP}/custody-environment.json" > /dev/null + gh api 'repos/auths-dev/auths-proof/environments/gateway-custody-live/deployment-branch-policies?per_page=100' \ + > "${RUNNER_TEMP}/custody-branches.json" + jq -e '.total_count == 1 and (.branch_policies | length) == 1 and .branch_policies[0].name == "main" and .branch_policies[0].type == "branch"' \ + "${RUNNER_TEMP}/custody-branches.json" > /dev/null - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 with: persist-credentials: false diff --git a/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md b/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md index 8da40f660..baba3850a 100644 --- a/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md +++ b/docs/specs/0066-production-gateway-polish-and-recipe-qualification.md @@ -1870,3 +1870,24 @@ The private production controller binds the shipping executable, prepares two hosts for each trusted context, requires PostgreSQL/TLS and AWS custody, and compares all four installed tuples with the planned tuple. Complete protected provider orchestration and hosted verification are still pending. + +#### 22.9 Retained workflow and exact environment cutover + +The production reference now connects preparation, finite commissioning, +independent first-release signing, ordinary required-gate execution, cleanup +and independently reconstructed final signing. Its records name the existing +`gateway-custody-live` environment, which the launch projection requires +exactly. This supersedes §20.3 reading 18 and §20.4 item 6's proposed per-family +environment names; no alternate environment name is accepted. Before reaching +provider credentials, the live job checks actual required-reviewer protection +and exactly one deployment policy for the `main` branch. Missing protection +refuses. The workflow does not change shared environment policy or upload keys. + +Both purpose-separated signer jobs use `recipe-qualification-signing`; each +step receives only its own key. All family reconstruction completes before the +release key is read. Interrupted native installs retain approved cleanup inputs +without an execution floor; revocation is required before native collection can +retire them. Source cleanup drains any active restoration before deleting state. +Airtable rehearsal traffic is paced without serializing a race or retrying a +write. Hosted verification and both full protected runs remain pending. These +engineering changes issue no qualification or stable launch claim. diff --git a/product/qualification/auths-recipe-qualification-issuance/tests/protected_run.rs b/product/qualification/auths-recipe-qualification-issuance/tests/protected_run.rs index d926ee1e9..b099fcae6 100644 --- a/product/qualification/auths-recipe-qualification-issuance/tests/protected_run.rs +++ b/product/qualification/auths-recipe-qualification-issuance/tests/protected_run.rs @@ -200,6 +200,31 @@ fn signing_builds_are_independent_and_operator_exports_follow_scanning() { assert!(!text.contains("pull_request_target")); } +#[test] +fn custody_environment_protection_is_checked_before_provider_credentials() { + let text = std::fs::read_to_string(repository().join(WORKFLOW)).expect("workflow"); + let jobs = jobs(&text); + let live = &jobs["live"]; + let policy = live + .iter() + .position(|line| line.contains("custody-branches.json")) + .expect("actual environment branch policy check"); + let credential = live + .iter() + .position(|line| line.contains("secrets.STRIPE_QUALIFICATION_SETUP_KEY")) + .expect("provider credential step"); + assert!(policy < credential); + for required in [ + "required_reviewers", + ".total_count == 1", + ".branch_policies[0].name == \"main\"", + ".branch_policies[0].type == \"branch\"", + ] { + assert!(live.iter().any(|line| line.contains(required))); + } + assert!(!live.iter().any(|line| line.contains("--method"))); +} + #[test] fn other_workflows_cannot_reach_qualification_signing() { // No other workflow names the signer's key, and nothing in the diff --git a/product/qualification/auths-recipe-qualification/src/launch.rs b/product/qualification/auths-recipe-qualification/src/launch.rs index 21e600ecf..498a826f3 100644 --- a/product/qualification/auths-recipe-qualification/src/launch.rs +++ b/product/qualification/auths-recipe-qualification/src/launch.rs @@ -55,8 +55,7 @@ mod tests { deployment, ); body.provider_kind = ProviderKind::parse(*provider).expect("provider"); - body.provenance.environment = - bounded(&format!("recipe-qualification-live-{family}")); + body.provenance.environment = bounded("gateway-custody-live"); let artifacts = artifacts(&body, readiness); body.evidence = artifacts .iter() @@ -277,6 +276,19 @@ mod tests { ); } + #[test] + fn a_signed_record_from_another_environment_cannot_close_launch() { + for environment in [ + "recipe-qualification-live-refund-v1", + "recipe-qualification-signing", + "unprotected", + ] { + let mut fixture = Fixture::two(); + fixture.records[0].provenance.environment = bounded(environment); + assert!(!fixture.ready()); + } + } + #[test] fn candidate_drift_development_custody_and_untrusted_time_refuse() { let fixture = Fixture::two(); diff --git a/product/qualification/auths-recipe-qualification/src/verify.rs b/product/qualification/auths-recipe-qualification/src/verify.rs index 6b1e3ce28..39d620604 100644 --- a/product/qualification/auths-recipe-qualification/src/verify.rs +++ b/product/qualification/auths-recipe-qualification/src/verify.rs @@ -265,11 +265,7 @@ impl VerifiedQualifications { }) && record.provenance.repository.as_str() == "github.com/auths-dev/auths-proof" && record.provenance.workflow.as_str() == ".github/workflows/recipe-qualification.yml" - && record.provenance.environment.as_str() - == format!( - "recipe-qualification-live-{}", - record.tuple.recipe_family.as_str() - ) + && record.provenance.environment.as_str() == "gateway-custody-live" } /// Checks every signature under the pinned `root`. An input that does diff --git a/product/runtime/auths-gateway/semantic-closure.json b/product/runtime/auths-gateway/semantic-closure.json index 0e15e713c..0dce77209 100644 --- a/product/runtime/auths-gateway/semantic-closure.json +++ b/product/runtime/auths-gateway/semantic-closure.json @@ -1 +1 @@ -{"files":[{"path":"Cargo.lock","sha256":"0e75e2fdef44e79e57797ac6661295ae58ddb8de4a1990a6fd22ce6c54f78604"},{"path":"Cargo.toml","sha256":"6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24"},{"path":"core/adapters/auths-did-keri/Cargo.toml","sha256":"86ba3e3f9a0a70d970568bfb3113b7ba7bbdd81c3eebbb52743dd574a0c0ecaa"},{"path":"core/adapters/auths-did-keri/src/lib.rs","sha256":"a75674842f8a7142004369ccd206ab43e476459293f0ff4bed4d4e659031b3e3"},{"path":"core/adapters/auths-did-key/Cargo.toml","sha256":"d5a3ae07ecde83f91eed4c3785051dd0f44eab6c891754f3309b6b40596707d7"},{"path":"core/adapters/auths-did-key/src/lib.rs","sha256":"b76a3f4528a725df53cfa9242e6e414e1d26caa48468aaed497e28b121f4497c"},{"path":"core/adapters/auths-raw-key/Cargo.toml","sha256":"f49616bc18c19e6aaa7e6a02ccebcdb9f5c1422c1278ef9869e0dbf22ceda7be"},{"path":"core/adapters/auths-raw-key/src/lib.rs","sha256":"45eec1b295dac3bed65cd79c942870b926b06b3f5d38eaebaeb6140ac69315fa"},{"path":"core/crates/auths-algebra-kernel/Cargo.toml","sha256":"0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba"},{"path":"core/crates/auths-algebra-kernel/src/generated.rs","sha256":"ae4bcbef42a408c7ffa0c6a74a42f7de177a6f14479e51d205acf830bda05960"},{"path":"core/crates/auths-algebra-kernel/src/lib.rs","sha256":"6654667eeb9b353d6648954c9fd2e8838462a82ce6b2803eb49e1366892c68c6"},{"path":"core/crates/auths-assurance/Cargo.toml","sha256":"afcb12a97ddd09d7a264b9ecd3fcaefc865ff2c9b4539ee85b00883420ba333a"},{"path":"core/crates/auths-assurance/src/lib.rs","sha256":"0fb2ec844d674b25a9e20b1601452c89c2454901fa506adfa9bb38ef9a7fa213"},{"path":"core/crates/auths-author/Cargo.toml","sha256":"1e6f0e3bc079ddb558decf0db26b291c6e72fc47327b6df1b7650d41689b215f"},{"path":"core/crates/auths-author/src/lib.rs","sha256":"e14475f2f49715a1869d5fa6b11ff1fbb72497e39097e09f833b0bae7e5b3f2b"},{"path":"core/crates/auths-author/src/observations.rs","sha256":"dda7d6bfa6f4bd7e95a480ca283c2c0e996f69c5c15cb0c7197af328131a7066"},{"path":"core/crates/auths-authority/Cargo.toml","sha256":"4f68212938029f79ebd857b4f3038494eb85d0163d49f07e51376715cf959815"},{"path":"core/crates/auths-authority/src/lib.rs","sha256":"da88d5194de4e17449e69972c0fb042afa3c39798a8f570f30771e77c384f1eb"},{"path":"core/crates/auths-codec/Cargo.toml","sha256":"e20e51826e17814effd9d8925d18d5fbdd6c0d37bf50231e743ec2611314722c"},{"path":"core/crates/auths-codec/src/approval.rs","sha256":"fbff43bf4d57f69f8b7738a8647751cde75c5a932dee65d924a1fe9c7202f91f"},{"path":"core/crates/auths-codec/src/bounded_policy.rs","sha256":"d21f6728be2d8a04b6d94921f2b683f7e61cbb42e0ac6866f1c88a49caa534c3"},{"path":"core/crates/auths-codec/src/decode.rs","sha256":"ba2999584cdf53b1b517ecb9c7ea50d39efee17c666a9a38e2ad1ac94379f778"},{"path":"core/crates/auths-codec/src/encode.rs","sha256":"8491192053e2e15d62b4d2a491de22405b7487ead69ab6f6bca40669ce7ca5f7"},{"path":"core/crates/auths-codec/src/error.rs","sha256":"fecb0737c16deb42d859f1dc7727c698438d9ac12064fd99e0024629642c390c"},{"path":"core/crates/auths-codec/src/hash.rs","sha256":"f88e111f1dbb2cef6b7b5e9c948cb45ff92e366710c8a5f5c636138aa748479e"},{"path":"core/crates/auths-codec/src/lib.rs","sha256":"3b0e5c94c6f34f750b88a9333e1d5c8145746d845d3a23e0d2f61807cf592ea7"},{"path":"core/crates/auths-codec/src/observation.rs","sha256":"38328b0c71ff97a4196eeade8b4faa889527ff1f80bb168468bcd49082a3987e"},{"path":"core/crates/auths-composition/Cargo.toml","sha256":"331e13025eb82588b5269ed3975929eb41c823d588c49e4c296273d85c6fe80e"},{"path":"core/crates/auths-composition/src/lib.rs","sha256":"e42e3b0b6a9985b73c533aeb23799c638979aa27a9ce7d0f10a8d60340570fb1"},{"path":"core/crates/auths-model/Cargo.toml","sha256":"565c15302b0cc9270db1e28efa3862804846850ba933cc17aea8abcec4a65987"},{"path":"core/crates/auths-model/src/approval.rs","sha256":"54cf44a9ef747ec21546a4086aecfb130bc7803b0d646430e6082df51e6e305f"},{"path":"core/crates/auths-model/src/bounded.rs","sha256":"f90496abc0a06c028b4d850af6ddab7d850bfafeaa3d042f1b1246a41d8bbbc9"},{"path":"core/crates/auths-model/src/bounded_policy.rs","sha256":"306a8f049cc7cfc7635fe0e4de47eb7813eed63d3c14c3be2b51586aa4eea450"},{"path":"core/crates/auths-model/src/lib.rs","sha256":"e7cfe6bb9574c6b016aa63e70658c31e0b90903ec6479a49f4a2ceb64f5bad97"},{"path":"core/crates/auths-model/src/observation.rs","sha256":"b3ed3e3cc090afca2896a7d3de7988afccc1ee1ea0ebd91b51a8bc0f20ad8dbb"},{"path":"core/crates/auths-multikey/Cargo.toml","sha256":"858756c1197befcada06134742bffe8d58cf674cadd6c046bf710570e96efaf2"},{"path":"core/crates/auths-multikey/src/lib.rs","sha256":"f5177fffb11e40eeaaa665ba886c541fc1f24d5eacdd6983fb03dc20148733f0"},{"path":"core/crates/auths-ports/Cargo.toml","sha256":"596a9b0f5af3717c16a6d13f7054d8a106bcd9f01f5f72c2235dd2afcf0ab16c"},{"path":"core/crates/auths-ports/src/binding.rs","sha256":"a16c012d40aa4249e3ec54372b9611006d0bfe8c7dc3c741911c2194ad17736d"},{"path":"core/crates/auths-ports/src/diagnostics.rs","sha256":"aa596572503b5a65a918bb2ff38281c144ff53821ee914e9325c852828d852df"},{"path":"core/crates/auths-ports/src/lib.rs","sha256":"8da1debf86f9532df0660155d04298beb1ba3a1204508f8586e2e67cd2fb3449"},{"path":"core/crates/auths-ports/src/path.rs","sha256":"b68fc547b4e4d97a60cbbc1cc1939fc6b34a8233b81f840bd396914a707e3ea1"},{"path":"core/crates/auths-raw-key-core/Cargo.toml","sha256":"98c0bc8527a537512e43a74dd6ba9658c6f0cdc16610cf938e3f9b43785d836d"},{"path":"core/crates/auths-raw-key-core/src/lib.rs","sha256":"98c0500c41697aae28708ad0bf970b9a97583d96a3d2c18d23e7fa351e0f7d12"},{"path":"core/crates/auths-registries/Cargo.toml","sha256":"590e49e58b0622d9d6274fea46796dcdb07dec9550eff295cce6a6427ffa51e2"},{"path":"core/crates/auths-registries/src/lib.rs","sha256":"450d3886d85ee333b7e046317fb5b47cde62483d5f3e41d46265e2caf4c373ec"},{"path":"core/crates/auths-registries/src/template.rs","sha256":"1224039dd2b3ce6fa8357613d8cafbae40400493da7176da202b9ade62fa05e4"},{"path":"core/crates/auths-signature-core/Cargo.toml","sha256":"6bee2230eb30af1be0bd5c2d57bd3e1903497a70028d47290d4ac6e9e0e8bca0"},{"path":"core/crates/auths-signature-core/src/lib.rs","sha256":"6e3f9311ded5e49ea50d445eb21e6d8fa12442aa4362a73e0cb6fda15b7cd865"},{"path":"core/crates/auths-signature/Cargo.toml","sha256":"7f7b5682466ba439d8c59579022cb61068cad9fb4bd2d73e1cc21327c902b450"},{"path":"core/crates/auths-signature/src/lib.rs","sha256":"b3d9ac4cc3ba0797b9e1c09f2d6ac05089b25dac4e285a5af28c0165b33d925b"},{"path":"core/crates/auths-verifier/Cargo.toml","sha256":"c43358e06a33324b41a8b93e5cc7279c55f7d21f1f6cfaa539a3fc7b4c27a38f"},{"path":"core/crates/auths-verifier/src/approval.rs","sha256":"c3cae6a49e169051eb555bb092b1069a4d422516d6a2114623a89e5f31ff923f"},{"path":"core/crates/auths-verifier/src/causal.rs","sha256":"9635230f33b13a263573d319ac8a1976addbcc07677514a43e3c7bf28dc04587"},{"path":"core/crates/auths-verifier/src/lib.rs","sha256":"f22dec38dfa47ced8da4f605390da8453273bee1da010f57fd1fdfcb10e0b389"},{"path":"core/crates/auths-verifier/src/observation.rs","sha256":"0bb07f06a0f9524c88427df1c972b1de8ba038a9eeeb15d3134c25125ae84b1e"},{"path":"core/crates/auths-verifier/src/trace.rs","sha256":"2213d72023a1d9e0413a2cf2c51c3dad9e04775d86033a0caaa9d29a8f0036f8"},{"path":"exchange/crates/auths-proof-exchange-model/Cargo.toml","sha256":"34b2db64f93a288e942b5a3918d28cdcbef906e0dc9074ce848018d3d5f7a1fa"},{"path":"exchange/crates/auths-proof-exchange-model/src/lib.rs","sha256":"49fac5aff2339d3a57c41cb8bb2a82852538e8f77ecc4b157c88e264ff31fb55"},{"path":"exchange/crates/auths-proof-exchange-port/Cargo.toml","sha256":"7ff660f1b7579dc570c791090aeb450404fbbf44c92781e289f5ccdde746d739"},{"path":"exchange/crates/auths-proof-exchange-port/src/lib.rs","sha256":"b408fb40c6432edc1facb3d8b3e9433a033f8dc73fe2e0ba5a88c972ca675021"},{"path":"product/config/auths-config/Cargo.toml","sha256":"e4b568ab9f6d84f7d7e6d66443fe825f360db9c27bc7c31d6ddc0647ba3ab304"},{"path":"product/config/auths-config/src/lib.rs","sha256":"fecf00ea65cef9018fda9af2063326d7065b869266d0d9e73a4f06816f1102cc"},{"path":"product/errors/auths-errors/Cargo.toml","sha256":"3b3a199b6460ba75bda84475bb5accd35e1485448a3981038db85bf4772dd350"},{"path":"product/errors/auths-errors/src/lib.rs","sha256":"7feeb9069fa4003f94f1f07c1c94619cf1c883e0dbaaf2187f04d0f742264bdd"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/Cargo.toml","sha256":"716f1f2a117d6d69d8effe9ee9057e24ba3502f20af6a602b06facb638cdabed"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/api.rs","sha256":"9ea61dd7ddd93282b073b98e453e6b75b26dc49689c04e9782435d06a3a09e48"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/clock.rs","sha256":"73f0a6e0f5903883329fa6683f5888288f759512ac69e5c87efd2b6b87f7d79f"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/http.rs","sha256":"14c1fce14e24c984b2a275563a29b6326fb08367922b6e8d37ba38b9cb81aa2b"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/identity.rs","sha256":"186de11230c8b33375951c4368609f8976bf9795f171af3fd7fac26207a94361"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs","sha256":"0b4617d044f5254a5ab22f5a2578f91cc025206a8c1845be39c1c56dcdf7a5df"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/names.rs","sha256":"41bb23572d6002e23ee103d6fe70ecd68764861c6f2e48a1c53af998270a4afa"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs","sha256":"39fed883f4802e68d3b41a68fea0aba0737810996b33d13577de70faba004c29"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/store.rs","sha256":"fc60ee9c49b2f4f063c449b4c78100c5c4872779e94ca168f796603b380ef6e4"},{"path":"product/integrations/auths-custody/Cargo.toml","sha256":"1e14034185ad1ec24a977fd5f41d0abee219606245c046ce2a82287fadef448b"},{"path":"product/integrations/auths-custody/src/conformance.rs","sha256":"8ed1afd58f18fc6becc268908aa6419c9aa404c79da0197963eb2599df44acf6"},{"path":"product/integrations/auths-custody/src/key.rs","sha256":"70cbb0fd21b6f5652157845a22c35be2d0f6c05b3d138fc4b9bb6dbdc3d81c40"},{"path":"product/integrations/auths-custody/src/lib.rs","sha256":"8ee593c1f59b0fd2126bdda9138026f5bc531beb64d4489a99785842e7b98b43"},{"path":"product/operations/auths-operations/Cargo.toml","sha256":"73dde1e914ba5e1386f8d49c0d730423cc72ae77ec44c6554a6a75cc8e8922b1"},{"path":"product/operations/auths-operations/src/explanation.rs","sha256":"b4a39bcbd5712cb9e735ee7deeb281f3fa6af5ddca973735bf3d87dce427ef11"},{"path":"product/operations/auths-operations/src/lib.rs","sha256":"3f401a56555113b98f57bca172a2660eaecedf76247b83a3fdbb089c133a29cd"},{"path":"product/operations/auths-operations/src/render/json.rs","sha256":"2ae042639960afee123730e945d373bc5dda1d2b3af20ae16c939a7e99b9e418"},{"path":"product/operations/auths-operations/src/render/mod.rs","sha256":"b3b7f6fe473f49227ace5a68bfc3d8dc14b5db8dd9888fd9e207070337b1b8bf"},{"path":"product/operations/auths-operations/src/render/text.rs","sha256":"f216cf3bdb00e264523271b16e7059535ac6b1aabf271cebd7935af155e4bfec"},{"path":"product/policy/auths-bounded-policy/Cargo.toml","sha256":"babd5d200923137ead71d8c2528f847cea323ce98da942a1320b054436612c47"},{"path":"product/policy/auths-bounded-policy/src/arithmetic.rs","sha256":"75e43c5d4eab8d1f71c1daf53839f5f9fe45a400afc1f63a30c6f55ce3632627"},{"path":"product/policy/auths-bounded-policy/src/commitment.rs","sha256":"c5706f2d583454e1a7f570f7ada138d4d864bef0205dfae7c1296774f396bb3f"},{"path":"product/policy/auths-bounded-policy/src/eligibility.rs","sha256":"c9acdfb793074e687fc36efad506be27dbd99ffbf40387bc66c8de39ef238432"},{"path":"product/policy/auths-bounded-policy/src/identifier.rs","sha256":"0006a32bae9eb16c4178cf797df418d2b0a781f2bc6474b741dc1a908141831c"},{"path":"product/policy/auths-bounded-policy/src/kernel.rs","sha256":"99187c28b161ac70bee1afed60711f7f645adb4d1671a01863f9849b369811d5"},{"path":"product/policy/auths-bounded-policy/src/lib.rs","sha256":"76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c"},{"path":"product/policy/auths-bounded-policy/src/receipt.rs","sha256":"3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad"},{"path":"product/policy/auths-bounded-policy/src/registry.rs","sha256":"4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0"},{"path":"product/profiles/auths-profile-api/Cargo.toml","sha256":"7ae85761f58625b5d678f961fd052eebf3e000ef565c7312e3ac857763c0017f"},{"path":"product/profiles/auths-profile-api/src/lib.rs","sha256":"a194b82b20bf8aa864c2334ef6c6aec30b2154ded972862252d5dcefa488ab95"},{"path":"product/profiles/auths-profile-mcp/Cargo.toml","sha256":"db264fc25242f7b7e4133cbe5782545b3107b406c87168ae072683cfb59eac66"},{"path":"product/profiles/auths-profile-mcp/src/arguments.rs","sha256":"a5de696586d507e2aee4a49fee99ef1ef4c51a2e46603f8838f1af6d9009833f"},{"path":"product/profiles/auths-profile-mcp/src/lib.rs","sha256":"d0f8b733a09ef8408336cdebc8948d6a5861012ce6878598b11be7084dfd4280"},{"path":"product/profiles/auths-profile-mcp/src/session.rs","sha256":"166c281fa66333388e4760d6098dad02d3359e1d5de4b8f93312c014f97abb03"},{"path":"product/qualification/auths-recipe-qualification/Cargo.toml","sha256":"b7b15b30b9a3d96d4f089d514266d3a892de6608d30707aa44be31cca89ca9fe"},{"path":"product/qualification/auths-recipe-qualification/src/canonical.rs","sha256":"30a9b50777f0dcb4b606abfee2467d5a975d9f6ad941ab6c13ca3df5b359f667"},{"path":"product/qualification/auths-recipe-qualification/src/closure.rs","sha256":"0ad6aee9bd981e2863fa725f209ec84031db2ff12f4c7ac3aaf5120f0bb86039"},{"path":"product/qualification/auths-recipe-qualification/src/commissioning.rs","sha256":"db135c55e4e3079a73253ebae275536523eb36b545d1c152b4d7dce3c6b76828"},{"path":"product/qualification/auths-recipe-qualification/src/commissioning/tests.rs","sha256":"4dde3736d206099b1bea4c14e0092c6c1287d1af9065958777d7c54331dd8686"},{"path":"product/qualification/auths-recipe-qualification/src/error.rs","sha256":"52d5cf720a1e4579008fdda90a3ac2c31f0b8db57985f121f65e54b4da2b7dd1"},{"path":"product/qualification/auths-recipe-qualification/src/evidence.rs","sha256":"ba45a7409d67a8af26ab811af306412014557477a101ab2a8eb0faf8f2bd4b91"},{"path":"product/qualification/auths-recipe-qualification/src/ids.rs","sha256":"e81a906d571497ab2da753e1532d4443706410e0b75fdd59a7d2d788c7aec403"},{"path":"product/qualification/auths-recipe-qualification/src/launch.rs","sha256":"41f2e2de90e1e7d6440a66eda3eb9bea8d5e0741bc232305a76a363ab5f813c1"},{"path":"product/qualification/auths-recipe-qualification/src/lib.rs","sha256":"0e24b0f81191df0d078c7f4d73ced784ba9472372bfcdff3c7d0e2fb1687b323"},{"path":"product/qualification/auths-recipe-qualification/src/model.rs","sha256":"3484eb0ec287b23d4682ade7b1b0f8d1335985b3fb180f06fc28716076957d5f"},{"path":"product/qualification/auths-recipe-qualification/src/release.rs","sha256":"ec478e53f70052e566aac7e15be2f9e1b1cd46837ac6990ae955fa864d311586"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/mod.rs","sha256":"fa23a962fd90331152eed5edbcdf271955f7aed79b8da1e065bfe69a20b487a9"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/schemas.rs","sha256":"c59feec2805621f341a90f81fc005e2c12f7a70f9d264fdeacccb2be4fe1c046"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/verification.rs","sha256":"bdf5746fed4d10a7f577f7878619a917d29aa8b7d522f00d9f774e53eff4c8c1"},{"path":"product/qualification/auths-recipe-qualification/src/verify.rs","sha256":"2ec2784435d11e07295de77b2ee1b2c48b2fcf9609a00454c6e7374b621aed5c"},{"path":"product/receipts/auths-receipts/Cargo.toml","sha256":"6001fa1375899953aafcb07c23a6da0c8f57ea7ec08bb9c950b12a60a8cc6f0f"},{"path":"product/receipts/auths-receipts/src/disclosure.rs","sha256":"ba9ed439be0a320c8a01f5b6e9b51361c1a37e076947490d8e4a484ba6bb119c"},{"path":"product/receipts/auths-receipts/src/lib.rs","sha256":"547a57c4160256719cafb7d0ab972d9fc80b0da14fbbce4148c70c414070ff36"},{"path":"product/runtime/auths-connections/Cargo.toml","sha256":"babeb6e1dda3dfb66291713ce1e43dce5c349833d0b50ea4dccbf986030026b2"},{"path":"product/runtime/auths-connections/src/credential.rs","sha256":"82921413bb053f0f6c7931fbd4e6a86c8cc1d8c6b51debd9c2cef33a8d5b1c51"},{"path":"product/runtime/auths-connections/src/kernel.rs","sha256":"a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8"},{"path":"product/runtime/auths-connections/src/lib.rs","sha256":"79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22"},{"path":"product/runtime/auths-connections/src/model.rs","sha256":"de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77"},{"path":"product/runtime/auths-connections/src/registry.rs","sha256":"e57640e003e72ad3235c567c2bb944a262bd64e673f023b62ea091094cc7e946"},{"path":"product/runtime/auths-gateway-kernel/Cargo.toml","sha256":"34f864e67656af4ac7e5c7a347a23f01fc8ab31365b8e23c0ef474483b14a183"},{"path":"product/runtime/auths-gateway-kernel/src/construct.rs","sha256":"e9d65744bae273d65face4285e5d2da75c06a92ab48f7b8333d496604e31c63c"},{"path":"product/runtime/auths-gateway-kernel/src/lib.rs","sha256":"cfda6f8453426564c085475f183b6f790b438768a19668f1b65d33ba59dc8632"},{"path":"product/runtime/auths-gateway-kernel/src/order.rs","sha256":"e0045f877c4b7fe3860c291039853885064ddcdebba7c9b345ab65e81e646dda"},{"path":"product/runtime/auths-gateway-kernel/src/outcome.rs","sha256":"e9785b1afe70788c89b51b18655bcd5acff7b0c8e3d12fb79c6f05a202e67e6b"},{"path":"product/runtime/auths-gateway-kernel/src/ratio.rs","sha256":"7ace22264812e6fc1ef3a62afee402cf43494bb71ae0d3de219ad1b39d690bcb"},{"path":"product/runtime/auths-gateway-kernel/src/recovery.rs","sha256":"9f46dcd1685ab6e4d1ba04a3fc286a9f3afee8fb47829be1fbc670a7926a2dc6"},{"path":"product/runtime/auths-gateway-kernel/src/transition.rs","sha256":"cefb8f01d915880f6921f2501ff881ad94b9de61072c34d9cd19220992f97374"},{"path":"product/runtime/auths-gateway/Cargo.toml","sha256":"00b28be86921dcdc0ad90cce0c62c2961cafefe96ea6c2edf0e926c3d405ccad"},{"path":"product/runtime/auths-gateway/src/admin.rs","sha256":"0dee40a9fb67c5de10142fc37a7bbabdd8979fb0199fb26caf4bdb024e0a5a40"},{"path":"product/runtime/auths-gateway/src/app.rs","sha256":"6f80f63833ea0815bb44fbf3b0cc54624a08e9fb578b035819f2980dc04e8256"},{"path":"product/runtime/auths-gateway/src/audit.rs","sha256":"0edb2037eb7b5d6f13acfce85c54f62a82bf7fdd31bc7e626c4fec183cef61dd"},{"path":"product/runtime/auths-gateway/src/audit_tests.rs","sha256":"990969384a52d75bc2489d9d412a9e7dd814bca1c8f65c701d6205fae62a15d5"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway-harness.rs","sha256":"12b0c24d36b2e6a3be392d3c081a783b355fdd67dc5b54bacc0410e803116b8c"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway.rs","sha256":"3dba485deeb4d60f3f5603ad4ce9a0edf49a85c68c5c4ca072df73d2910da832"},{"path":"product/runtime/auths-gateway/src/binding.rs","sha256":"663b0ce878319511aa7d05722ab4ab2fa9be18817884ffb2ee9f131ff1e382d1"},{"path":"product/runtime/auths-gateway/src/bounds.rs","sha256":"38251ad6f22f9d07ef9a219c79fa265ca36f1526eca5f147d7efa46b52ad609d"},{"path":"product/runtime/auths-gateway/src/bounds_aggregate_tests.rs","sha256":"ab34f227b7c8692ba1da88ccb32bb3687a66adf8353d8282fae905d4a88eb612"},{"path":"product/runtime/auths-gateway/src/bounds_tests.rs","sha256":"74136bc570da7b9338b5a1a1ed9d3fd892c55135160964f9d3ac0e2cf5741375"},{"path":"product/runtime/auths-gateway/src/commissioning_budget.rs","sha256":"fab29da3269438cc62330f3eab7b5bd4dc482b4db8af243aae47df5d3aa1deb8"},{"path":"product/runtime/auths-gateway/src/commissioning_budget/tests.rs","sha256":"da104a1643c37515deec6397bca6db2054f2c9158ec3d230a1b1ec9c7d0f659f"},{"path":"product/runtime/auths-gateway/src/commissioning_floor.rs","sha256":"7fa6991c5ccd5ae1403be84b3da390323fab09f36e15ac01fd7a38ea350c6fdb"},{"path":"product/runtime/auths-gateway/src/commissioning_floor/tests.rs","sha256":"6b663d6e556adc0b455b81845bc4394d82c6c4de0c5f43e1310f3ddc6e4e40f7"},{"path":"product/runtime/auths-gateway/src/commissioning_session.rs","sha256":"24b48d5eaeaaa3c620e2dfc7ee1f9255fc4519a1eb404b8608cea7af6a910ee2"},{"path":"product/runtime/auths-gateway/src/commissioning_session/tests.rs","sha256":"37a097fc8a9261d3fffdaef3f905f40b22e3e6601bb5101fadd9414f963c0824"},{"path":"product/runtime/auths-gateway/src/connection.rs","sha256":"e8d24277d7e4a53610e091fe78b373b841245d8e59a2bc788716b76e7d912441"},{"path":"product/runtime/auths-gateway/src/credential_journal.rs","sha256":"7297fccaee5cd8622928e8e0a42bba50da7941970a6f682ecd300c41ee6509da"},{"path":"product/runtime/auths-gateway/src/echo_verify.rs","sha256":"6d453051665f823abd7354d5c50031d9524cf47d6092d2f09080ae814e3b9575"},{"path":"product/runtime/auths-gateway/src/engine.rs","sha256":"c16e9b0ead514b6357f5b09914fae9de9a8977e1a2dac20e3aefeecb1cc16ee4"},{"path":"product/runtime/auths-gateway/src/execution_witness.rs","sha256":"e8b1a8e41d5e3fa309760067849d390ef065feeb46701a83391832645a2f000c"},{"path":"product/runtime/auths-gateway/src/fuzzing.rs","sha256":"ed3b0028487eb546a3b0a91d115aa8f18bcea324b61620bfe8e35a9e6ab18758"},{"path":"product/runtime/auths-gateway/src/generation_floor.rs","sha256":"fe1510ec96ce0f67e9a78edbfa94b33eb7df64c0ac4d0a67901124dcd0164777"},{"path":"product/runtime/auths-gateway/src/harness.rs","sha256":"c87e479f3eb281960f6c9c80d43c7560d7ccb654b0154ec823d3fcec4884ac05"},{"path":"product/runtime/auths-gateway/src/lib.rs","sha256":"fad95d031f88072dd024c78facf0bb0267562b1ac743ddd7219fce47e64024f0"},{"path":"product/runtime/auths-gateway/src/listener.rs","sha256":"aa08239bcbc1fcb55e8a212fbdf6a84f12985b0d436dcb51dc58b06e59e435f2"},{"path":"product/runtime/auths-gateway/src/observed_tests.rs","sha256":"a22be071695f89ca2578a4d82fd80d9cb82289213c9bdb8f0470f6b2dc3d9201"},{"path":"product/runtime/auths-gateway/src/observer.rs","sha256":"562ffcaea071c3856e0708dc2fe33516917e145d2438aabb75af0a2b6ba01046"},{"path":"product/runtime/auths-gateway/src/onboarding.rs","sha256":"0dfd7d67e7f02f18a28d1c86ca1b7751d7463f5efcdbe3825de0ad8cbccb3891"},{"path":"product/runtime/auths-gateway/src/operator.rs","sha256":"c3c36954a3e86723df035b47f43b85fc8ab3a6292983522b6258d5c6b4e6c4e4"},{"path":"product/runtime/auths-gateway/src/pending_vectors/attempts.rs","sha256":"47ef3c8cb1c5504d47ae9a0088705ce6715fe86bac1671a34a56fb38a64d0dd3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/bounds.rs","sha256":"e612217307e1da5b0eb5ee6582a7458bb064b8aa8a529fc6555b1b334127ab68"},{"path":"product/runtime/auths-gateway/src/pending_vectors/codes.rs","sha256":"e00670a5ef24eb856cc2c6dcda8e5a263842f55c76bb939c0c27bd9df37e5522"},{"path":"product/runtime/auths-gateway/src/pending_vectors/keys.rs","sha256":"f84c56f2ea9cb34b2b79c72d13fbf2c6585010ec1ed450af58a78c80c1ea1edd"},{"path":"product/runtime/auths-gateway/src/pending_vectors/mod.rs","sha256":"5de8340f0ef71a0b57a09e323fefe473d3160c6ae952b9ba46f714825fbacafc"},{"path":"product/runtime/auths-gateway/src/pending_vectors/outcomes.rs","sha256":"8ec07b9511b48913af36ac999d2aa0e82924289f6acb23ddaeb9f00f99815166"},{"path":"product/runtime/auths-gateway/src/pending_vectors/production.rs","sha256":"772d032e0a0d9c924fb6d6c188528db85a97e71c9e466ddc19eee277baf83614"},{"path":"product/runtime/auths-gateway/src/pending_vectors/recipes.rs","sha256":"51693208270231c25c3aef2a32151d5962114c71e86b88cb9df83181c7af83d9"},{"path":"product/runtime/auths-gateway/src/pre_entry.rs","sha256":"06ea78ca140468bfaba17d9ab04912ad68673954c3203c98fed28272ff2a00c0"},{"path":"product/runtime/auths-gateway/src/property_tests.rs","sha256":"939c081e2e154aaf10186754044bdd65608932c899b970a04a71d0afaa999a93"},{"path":"product/runtime/auths-gateway/src/qualification.rs","sha256":"c597c83de2b94f0374ae54e40a8b57c2a64ec6e254704dca32185f448a908aca"},{"path":"product/runtime/auths-gateway/src/qualification_simulation.rs","sha256":"4ee7cadfb5f46a92713c80f3e55f499cb074d04d8b21ea89d57762af38642bfa"},{"path":"product/runtime/auths-gateway/src/qualification_tests.rs","sha256":"a9178a2e58eea459d5e5dafc53a3999ea7c84dbbffefe6e5eb1f3d098827f028"},{"path":"product/runtime/auths-gateway/src/quorum_tests.rs","sha256":"a78380b019104d688c11a4410082c7e08ded3106aab099954c4f8a1b4ae0fd89"},{"path":"product/runtime/auths-gateway/src/readiness.rs","sha256":"911c3f11892f94641574375e2da4c671c802738f71082f12c39832331052d43d"},{"path":"product/runtime/auths-gateway/src/recipe.rs","sha256":"fecf9af67e7afc48d080e9f8f55f8ce28e49d0e08988717a27908bbda461d6b6"},{"path":"product/runtime/auths-gateway/src/recipe/lower.rs","sha256":"8088b8751ed831dbb48247af953c6290ac95e2a438ccd5bd65eff54be06a1fd1"},{"path":"product/runtime/auths-gateway/src/recipe/review.rs","sha256":"c3eb7d9fdd98dacf52750b14b67ad7b7faaecbbdeafff1e0b049f67d0a2d0139"},{"path":"product/runtime/auths-gateway/src/recipe/runtime.rs","sha256":"c286f0d15f974402822c0810d8e97f98411dc1c557755cc23e540d85e2bb42d9"},{"path":"product/runtime/auths-gateway/src/recipe/source.rs","sha256":"1af50298fb1461e1b24cbdf560d43124d6b1c4c529586c911b1c4797214a69ff"},{"path":"product/runtime/auths-gateway/src/recipe/tests.rs","sha256":"aac551a2481bbc60864c64079bc667dcb232e45a0f41a04073ed84ab5dbe1fce"},{"path":"product/runtime/auths-gateway/src/recipe/validate.rs","sha256":"3711b17605cb7b0d639bc1b180449231f5882a306cab20e2c7782155cc63b0d4"},{"path":"product/runtime/auths-gateway/src/scenario_tests.rs","sha256":"025b53473b3af6900e03bc2fee91aa63ed26a8778bc8c8296fe08f5540794c39"},{"path":"product/runtime/auths-gateway/src/separation.rs","sha256":"be9306848ca5d801767cf6aa14247c8618312ef0e202f00ce0c24c4844491061"},{"path":"product/runtime/auths-gateway/src/simulation_attestation.rs","sha256":"88705e5d45415f760f1e3c3a065c35c48f4f4065bf7b3feb7882246983814d6f"},{"path":"product/runtime/auths-gateway/src/store.rs","sha256":"884bcad4d70d53e12eae9c8517f6ecd0643068ee0be0370015119d04d6cc2516"},{"path":"product/runtime/auths-gateway/src/store_testkit.rs","sha256":"88d82fee42f1b8ef521e8deef0216e938ebeaad822eb2f5020e70b89d145ea70"},{"path":"product/runtime/auths-gateway/src/submit.rs","sha256":"fe2eacb5ad8152eeecbd232c47a356fc72db0098e34fda99532bdf6ef0cf895c"},{"path":"product/runtime/auths-gateway/src/support.rs","sha256":"9fd979029793a22b15d9776a7fc172476fd7c126a80d4080c65d720845becbcb"},{"path":"product/runtime/auths-gateway/src/transport.rs","sha256":"978fc9fb34a33b3db265b5d1c3ce11696a5b9f08529e46dd2a1e7bb62afb9220"},{"path":"product/runtime/auths-kernel-runtime/Cargo.toml","sha256":"926bcd0053e5edd703be8f0027ad009e2982db013c8174c1366edbf38b48087d"},{"path":"product/runtime/auths-kernel-runtime/src/lib.rs","sha256":"7108faae9ca4bc32dc093ddaf885ac8f74f3c9b8d317b7c7d0ed00d1d0ab5972"},{"path":"product/runtime/auths-lifecycle/Cargo.toml","sha256":"c5053c705f8d5554b44e432fe75287a2faf11d644e5a2552e45ad6cd94176af5"},{"path":"product/runtime/auths-lifecycle/src/codec.rs","sha256":"51c4b746749150e8bfcd8ff972b3f6c1ef40bec15583448ec1b471d9ad737dc0"},{"path":"product/runtime/auths-lifecycle/src/digest.rs","sha256":"55282cd7d8aba37713c2dcb5357c9877819edb72a30eadefb860d28d7d3a3eb7"},{"path":"product/runtime/auths-lifecycle/src/identifier.rs","sha256":"31620e8c16de68d3d2d3b84d6353c1a5b9d4151d8247f91fa389b906a8e660f1"},{"path":"product/runtime/auths-lifecycle/src/kernel.rs","sha256":"2abb8c094b36d35b364e74d78091d14c5d6f3d1eb6552cca3b5538dbd017ce23"},{"path":"product/runtime/auths-lifecycle/src/lib.rs","sha256":"afe5a345cd309b5a4f08ffba3170a6d7f16ff914892b3f2006d5208ed24ec736"},{"path":"product/runtime/auths-lifecycle/src/model.rs","sha256":"1af12bbeeeaa65ec02ddcebd7d2c8c92ec1e339fa40ae85b45ab9b01a722a4fa"},{"path":"product/runtime/auths-lifecycle/src/operation.rs","sha256":"78e6d05fcf5d7ea4f148032a3fa26fdfcab77eb346019effe927b08e0d64d732"},{"path":"product/runtime/auths-lifecycle/src/registry.rs","sha256":"53495fe6f7a77422593a41623e28716f1c140dcc1e00f87f6b0ffbfb93a5ef90"},{"path":"product/runtime/auths-lifecycle/src/sealed.rs","sha256":"2e0c03b5813c926c159598bb7890d1523825edbe57cd687d42a5dfb3374a0c19"},{"path":"product/runtime/auths-lifecycle/src/test_support.rs","sha256":"221d9a5c5ef8e1f9f8fd66927484eaf813571d0568470278ecd8fa08a5eec8cd"},{"path":"product/runtime/auths-lifecycle/src/transition.rs","sha256":"011805a28efdd541f44ccea54dd0e34a1e58f4004447ee58013703b4fb6b2822"},{"path":"product/runtime/auths-runtime/Cargo.toml","sha256":"dd29d80a8b4bb56c869f036a6c9998f6e6d1c0383ac5dc03fa42b24abe2a7ff7"},{"path":"product/runtime/auths-runtime/src/lib.rs","sha256":"132ca03d58c14905d3a822a4972f42a22a5ad33a45f2ba9ca44f3a57d810b4b0"},{"path":"product/runtime/auths-runtime/src/production.rs","sha256":"fd4eff4270c571c10fcff6cf27df28961ebf074de8a1a028f500fda1ca376820"},{"path":"product/sdk/auths-approval-quorum/Cargo.toml","sha256":"df904971fca87a24194c5816738a331588fe8f164acb5d70839a35dca5f57114"},{"path":"product/sdk/auths-approval-quorum/src/lib.rs","sha256":"72e4086088a1c0912e4e1a9e980f26a5c280bf5ab16ea39c9f0f58d5096ac2ce"},{"path":"product/sdk/auths-approval-quorum/src/remote.rs","sha256":"9fa029c7c63003adf260f8aec55160c545681c60c1bace0d934e7525862aac7b"},{"path":"product/sdk/auths-approval-quorum/src/remote_tests.rs","sha256":"8a09ce17cfee82a035a74edd535f3ebeb3db0e078784740d3997b17dbdb10197"},{"path":"product/sdk/auths-approval-quorum/src/tests.rs","sha256":"0acbf12be3e497dcc6c2d8f29c9af3b1a7ed8e11b75f6399570d4f217a785060"},{"path":"product/stores/auths-stores/Cargo.toml","sha256":"a32c4b76d17b264be5d40d24497ff237e1ed87822e8bab86229b3db93106dbe3"},{"path":"product/stores/auths-stores/src/gateway_attempt.rs","sha256":"218841602d3d9b23b44625f50e5b54cf275ccedc2d5c89f02d2482b8524472af"},{"path":"product/stores/auths-stores/src/lib.rs","sha256":"e721262edf8a9ab5568ddc27639176312d4a366203b5f73e2d7c11fde2c554e9"},{"path":"product/stores/auths-stores/src/lifecycle.rs","sha256":"3f2cecfda13fdcd7c4a944518646bcc8abd1237f900c0332d5822281f8f9f1cd"}],"schema":"auths.gateway-semantic-closure/1"} \ No newline at end of file +{"files":[{"path":"Cargo.lock","sha256":"0e75e2fdef44e79e57797ac6661295ae58ddb8de4a1990a6fd22ce6c54f78604"},{"path":"Cargo.toml","sha256":"6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24"},{"path":"core/adapters/auths-did-keri/Cargo.toml","sha256":"86ba3e3f9a0a70d970568bfb3113b7ba7bbdd81c3eebbb52743dd574a0c0ecaa"},{"path":"core/adapters/auths-did-keri/src/lib.rs","sha256":"a75674842f8a7142004369ccd206ab43e476459293f0ff4bed4d4e659031b3e3"},{"path":"core/adapters/auths-did-key/Cargo.toml","sha256":"d5a3ae07ecde83f91eed4c3785051dd0f44eab6c891754f3309b6b40596707d7"},{"path":"core/adapters/auths-did-key/src/lib.rs","sha256":"b76a3f4528a725df53cfa9242e6e414e1d26caa48468aaed497e28b121f4497c"},{"path":"core/adapters/auths-raw-key/Cargo.toml","sha256":"f49616bc18c19e6aaa7e6a02ccebcdb9f5c1422c1278ef9869e0dbf22ceda7be"},{"path":"core/adapters/auths-raw-key/src/lib.rs","sha256":"45eec1b295dac3bed65cd79c942870b926b06b3f5d38eaebaeb6140ac69315fa"},{"path":"core/crates/auths-algebra-kernel/Cargo.toml","sha256":"0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba"},{"path":"core/crates/auths-algebra-kernel/src/generated.rs","sha256":"ae4bcbef42a408c7ffa0c6a74a42f7de177a6f14479e51d205acf830bda05960"},{"path":"core/crates/auths-algebra-kernel/src/lib.rs","sha256":"6654667eeb9b353d6648954c9fd2e8838462a82ce6b2803eb49e1366892c68c6"},{"path":"core/crates/auths-assurance/Cargo.toml","sha256":"afcb12a97ddd09d7a264b9ecd3fcaefc865ff2c9b4539ee85b00883420ba333a"},{"path":"core/crates/auths-assurance/src/lib.rs","sha256":"0fb2ec844d674b25a9e20b1601452c89c2454901fa506adfa9bb38ef9a7fa213"},{"path":"core/crates/auths-author/Cargo.toml","sha256":"1e6f0e3bc079ddb558decf0db26b291c6e72fc47327b6df1b7650d41689b215f"},{"path":"core/crates/auths-author/src/lib.rs","sha256":"e14475f2f49715a1869d5fa6b11ff1fbb72497e39097e09f833b0bae7e5b3f2b"},{"path":"core/crates/auths-author/src/observations.rs","sha256":"dda7d6bfa6f4bd7e95a480ca283c2c0e996f69c5c15cb0c7197af328131a7066"},{"path":"core/crates/auths-authority/Cargo.toml","sha256":"4f68212938029f79ebd857b4f3038494eb85d0163d49f07e51376715cf959815"},{"path":"core/crates/auths-authority/src/lib.rs","sha256":"da88d5194de4e17449e69972c0fb042afa3c39798a8f570f30771e77c384f1eb"},{"path":"core/crates/auths-codec/Cargo.toml","sha256":"e20e51826e17814effd9d8925d18d5fbdd6c0d37bf50231e743ec2611314722c"},{"path":"core/crates/auths-codec/src/approval.rs","sha256":"fbff43bf4d57f69f8b7738a8647751cde75c5a932dee65d924a1fe9c7202f91f"},{"path":"core/crates/auths-codec/src/bounded_policy.rs","sha256":"d21f6728be2d8a04b6d94921f2b683f7e61cbb42e0ac6866f1c88a49caa534c3"},{"path":"core/crates/auths-codec/src/decode.rs","sha256":"ba2999584cdf53b1b517ecb9c7ea50d39efee17c666a9a38e2ad1ac94379f778"},{"path":"core/crates/auths-codec/src/encode.rs","sha256":"8491192053e2e15d62b4d2a491de22405b7487ead69ab6f6bca40669ce7ca5f7"},{"path":"core/crates/auths-codec/src/error.rs","sha256":"fecb0737c16deb42d859f1dc7727c698438d9ac12064fd99e0024629642c390c"},{"path":"core/crates/auths-codec/src/hash.rs","sha256":"f88e111f1dbb2cef6b7b5e9c948cb45ff92e366710c8a5f5c636138aa748479e"},{"path":"core/crates/auths-codec/src/lib.rs","sha256":"3b0e5c94c6f34f750b88a9333e1d5c8145746d845d3a23e0d2f61807cf592ea7"},{"path":"core/crates/auths-codec/src/observation.rs","sha256":"38328b0c71ff97a4196eeade8b4faa889527ff1f80bb168468bcd49082a3987e"},{"path":"core/crates/auths-composition/Cargo.toml","sha256":"331e13025eb82588b5269ed3975929eb41c823d588c49e4c296273d85c6fe80e"},{"path":"core/crates/auths-composition/src/lib.rs","sha256":"e42e3b0b6a9985b73c533aeb23799c638979aa27a9ce7d0f10a8d60340570fb1"},{"path":"core/crates/auths-model/Cargo.toml","sha256":"565c15302b0cc9270db1e28efa3862804846850ba933cc17aea8abcec4a65987"},{"path":"core/crates/auths-model/src/approval.rs","sha256":"54cf44a9ef747ec21546a4086aecfb130bc7803b0d646430e6082df51e6e305f"},{"path":"core/crates/auths-model/src/bounded.rs","sha256":"f90496abc0a06c028b4d850af6ddab7d850bfafeaa3d042f1b1246a41d8bbbc9"},{"path":"core/crates/auths-model/src/bounded_policy.rs","sha256":"306a8f049cc7cfc7635fe0e4de47eb7813eed63d3c14c3be2b51586aa4eea450"},{"path":"core/crates/auths-model/src/lib.rs","sha256":"e7cfe6bb9574c6b016aa63e70658c31e0b90903ec6479a49f4a2ceb64f5bad97"},{"path":"core/crates/auths-model/src/observation.rs","sha256":"b3ed3e3cc090afca2896a7d3de7988afccc1ee1ea0ebd91b51a8bc0f20ad8dbb"},{"path":"core/crates/auths-multikey/Cargo.toml","sha256":"858756c1197befcada06134742bffe8d58cf674cadd6c046bf710570e96efaf2"},{"path":"core/crates/auths-multikey/src/lib.rs","sha256":"f5177fffb11e40eeaaa665ba886c541fc1f24d5eacdd6983fb03dc20148733f0"},{"path":"core/crates/auths-ports/Cargo.toml","sha256":"596a9b0f5af3717c16a6d13f7054d8a106bcd9f01f5f72c2235dd2afcf0ab16c"},{"path":"core/crates/auths-ports/src/binding.rs","sha256":"a16c012d40aa4249e3ec54372b9611006d0bfe8c7dc3c741911c2194ad17736d"},{"path":"core/crates/auths-ports/src/diagnostics.rs","sha256":"aa596572503b5a65a918bb2ff38281c144ff53821ee914e9325c852828d852df"},{"path":"core/crates/auths-ports/src/lib.rs","sha256":"8da1debf86f9532df0660155d04298beb1ba3a1204508f8586e2e67cd2fb3449"},{"path":"core/crates/auths-ports/src/path.rs","sha256":"b68fc547b4e4d97a60cbbc1cc1939fc6b34a8233b81f840bd396914a707e3ea1"},{"path":"core/crates/auths-raw-key-core/Cargo.toml","sha256":"98c0bc8527a537512e43a74dd6ba9658c6f0cdc16610cf938e3f9b43785d836d"},{"path":"core/crates/auths-raw-key-core/src/lib.rs","sha256":"98c0500c41697aae28708ad0bf970b9a97583d96a3d2c18d23e7fa351e0f7d12"},{"path":"core/crates/auths-registries/Cargo.toml","sha256":"590e49e58b0622d9d6274fea46796dcdb07dec9550eff295cce6a6427ffa51e2"},{"path":"core/crates/auths-registries/src/lib.rs","sha256":"450d3886d85ee333b7e046317fb5b47cde62483d5f3e41d46265e2caf4c373ec"},{"path":"core/crates/auths-registries/src/template.rs","sha256":"1224039dd2b3ce6fa8357613d8cafbae40400493da7176da202b9ade62fa05e4"},{"path":"core/crates/auths-signature-core/Cargo.toml","sha256":"6bee2230eb30af1be0bd5c2d57bd3e1903497a70028d47290d4ac6e9e0e8bca0"},{"path":"core/crates/auths-signature-core/src/lib.rs","sha256":"6e3f9311ded5e49ea50d445eb21e6d8fa12442aa4362a73e0cb6fda15b7cd865"},{"path":"core/crates/auths-signature/Cargo.toml","sha256":"7f7b5682466ba439d8c59579022cb61068cad9fb4bd2d73e1cc21327c902b450"},{"path":"core/crates/auths-signature/src/lib.rs","sha256":"b3d9ac4cc3ba0797b9e1c09f2d6ac05089b25dac4e285a5af28c0165b33d925b"},{"path":"core/crates/auths-verifier/Cargo.toml","sha256":"c43358e06a33324b41a8b93e5cc7279c55f7d21f1f6cfaa539a3fc7b4c27a38f"},{"path":"core/crates/auths-verifier/src/approval.rs","sha256":"c3cae6a49e169051eb555bb092b1069a4d422516d6a2114623a89e5f31ff923f"},{"path":"core/crates/auths-verifier/src/causal.rs","sha256":"9635230f33b13a263573d319ac8a1976addbcc07677514a43e3c7bf28dc04587"},{"path":"core/crates/auths-verifier/src/lib.rs","sha256":"f22dec38dfa47ced8da4f605390da8453273bee1da010f57fd1fdfcb10e0b389"},{"path":"core/crates/auths-verifier/src/observation.rs","sha256":"0bb07f06a0f9524c88427df1c972b1de8ba038a9eeeb15d3134c25125ae84b1e"},{"path":"core/crates/auths-verifier/src/trace.rs","sha256":"2213d72023a1d9e0413a2cf2c51c3dad9e04775d86033a0caaa9d29a8f0036f8"},{"path":"exchange/crates/auths-proof-exchange-model/Cargo.toml","sha256":"34b2db64f93a288e942b5a3918d28cdcbef906e0dc9074ce848018d3d5f7a1fa"},{"path":"exchange/crates/auths-proof-exchange-model/src/lib.rs","sha256":"49fac5aff2339d3a57c41cb8bb2a82852538e8f77ecc4b157c88e264ff31fb55"},{"path":"exchange/crates/auths-proof-exchange-port/Cargo.toml","sha256":"7ff660f1b7579dc570c791090aeb450404fbbf44c92781e289f5ccdde746d739"},{"path":"exchange/crates/auths-proof-exchange-port/src/lib.rs","sha256":"b408fb40c6432edc1facb3d8b3e9433a033f8dc73fe2e0ba5a88c972ca675021"},{"path":"product/config/auths-config/Cargo.toml","sha256":"e4b568ab9f6d84f7d7e6d66443fe825f360db9c27bc7c31d6ddc0647ba3ab304"},{"path":"product/config/auths-config/src/lib.rs","sha256":"fecf00ea65cef9018fda9af2063326d7065b869266d0d9e73a4f06816f1102cc"},{"path":"product/errors/auths-errors/Cargo.toml","sha256":"3b3a199b6460ba75bda84475bb5accd35e1485448a3981038db85bf4772dd350"},{"path":"product/errors/auths-errors/src/lib.rs","sha256":"7feeb9069fa4003f94f1f07c1c94619cf1c883e0dbaaf2187f04d0f742264bdd"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/Cargo.toml","sha256":"716f1f2a117d6d69d8effe9ee9057e24ba3502f20af6a602b06facb638cdabed"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/api.rs","sha256":"9ea61dd7ddd93282b073b98e453e6b75b26dc49689c04e9782435d06a3a09e48"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/clock.rs","sha256":"73f0a6e0f5903883329fa6683f5888288f759512ac69e5c87efd2b6b87f7d79f"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/http.rs","sha256":"14c1fce14e24c984b2a275563a29b6326fb08367922b6e8d37ba38b9cb81aa2b"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/identity.rs","sha256":"186de11230c8b33375951c4368609f8976bf9795f171af3fd7fac26207a94361"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs","sha256":"0b4617d044f5254a5ab22f5a2578f91cc025206a8c1845be39c1c56dcdf7a5df"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/names.rs","sha256":"41bb23572d6002e23ee103d6fe70ecd68764861c6f2e48a1c53af998270a4afa"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs","sha256":"39fed883f4802e68d3b41a68fea0aba0737810996b33d13577de70faba004c29"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/store.rs","sha256":"fc60ee9c49b2f4f063c449b4c78100c5c4872779e94ca168f796603b380ef6e4"},{"path":"product/integrations/auths-custody/Cargo.toml","sha256":"1e14034185ad1ec24a977fd5f41d0abee219606245c046ce2a82287fadef448b"},{"path":"product/integrations/auths-custody/src/conformance.rs","sha256":"8ed1afd58f18fc6becc268908aa6419c9aa404c79da0197963eb2599df44acf6"},{"path":"product/integrations/auths-custody/src/key.rs","sha256":"70cbb0fd21b6f5652157845a22c35be2d0f6c05b3d138fc4b9bb6dbdc3d81c40"},{"path":"product/integrations/auths-custody/src/lib.rs","sha256":"8ee593c1f59b0fd2126bdda9138026f5bc531beb64d4489a99785842e7b98b43"},{"path":"product/operations/auths-operations/Cargo.toml","sha256":"73dde1e914ba5e1386f8d49c0d730423cc72ae77ec44c6554a6a75cc8e8922b1"},{"path":"product/operations/auths-operations/src/explanation.rs","sha256":"b4a39bcbd5712cb9e735ee7deeb281f3fa6af5ddca973735bf3d87dce427ef11"},{"path":"product/operations/auths-operations/src/lib.rs","sha256":"3f401a56555113b98f57bca172a2660eaecedf76247b83a3fdbb089c133a29cd"},{"path":"product/operations/auths-operations/src/render/json.rs","sha256":"2ae042639960afee123730e945d373bc5dda1d2b3af20ae16c939a7e99b9e418"},{"path":"product/operations/auths-operations/src/render/mod.rs","sha256":"b3b7f6fe473f49227ace5a68bfc3d8dc14b5db8dd9888fd9e207070337b1b8bf"},{"path":"product/operations/auths-operations/src/render/text.rs","sha256":"f216cf3bdb00e264523271b16e7059535ac6b1aabf271cebd7935af155e4bfec"},{"path":"product/policy/auths-bounded-policy/Cargo.toml","sha256":"babd5d200923137ead71d8c2528f847cea323ce98da942a1320b054436612c47"},{"path":"product/policy/auths-bounded-policy/src/arithmetic.rs","sha256":"75e43c5d4eab8d1f71c1daf53839f5f9fe45a400afc1f63a30c6f55ce3632627"},{"path":"product/policy/auths-bounded-policy/src/commitment.rs","sha256":"c5706f2d583454e1a7f570f7ada138d4d864bef0205dfae7c1296774f396bb3f"},{"path":"product/policy/auths-bounded-policy/src/eligibility.rs","sha256":"c9acdfb793074e687fc36efad506be27dbd99ffbf40387bc66c8de39ef238432"},{"path":"product/policy/auths-bounded-policy/src/identifier.rs","sha256":"0006a32bae9eb16c4178cf797df418d2b0a781f2bc6474b741dc1a908141831c"},{"path":"product/policy/auths-bounded-policy/src/kernel.rs","sha256":"99187c28b161ac70bee1afed60711f7f645adb4d1671a01863f9849b369811d5"},{"path":"product/policy/auths-bounded-policy/src/lib.rs","sha256":"76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c"},{"path":"product/policy/auths-bounded-policy/src/receipt.rs","sha256":"3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad"},{"path":"product/policy/auths-bounded-policy/src/registry.rs","sha256":"4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0"},{"path":"product/profiles/auths-profile-api/Cargo.toml","sha256":"7ae85761f58625b5d678f961fd052eebf3e000ef565c7312e3ac857763c0017f"},{"path":"product/profiles/auths-profile-api/src/lib.rs","sha256":"a194b82b20bf8aa864c2334ef6c6aec30b2154ded972862252d5dcefa488ab95"},{"path":"product/profiles/auths-profile-mcp/Cargo.toml","sha256":"db264fc25242f7b7e4133cbe5782545b3107b406c87168ae072683cfb59eac66"},{"path":"product/profiles/auths-profile-mcp/src/arguments.rs","sha256":"a5de696586d507e2aee4a49fee99ef1ef4c51a2e46603f8838f1af6d9009833f"},{"path":"product/profiles/auths-profile-mcp/src/lib.rs","sha256":"d0f8b733a09ef8408336cdebc8948d6a5861012ce6878598b11be7084dfd4280"},{"path":"product/profiles/auths-profile-mcp/src/session.rs","sha256":"166c281fa66333388e4760d6098dad02d3359e1d5de4b8f93312c014f97abb03"},{"path":"product/qualification/auths-recipe-qualification/Cargo.toml","sha256":"b7b15b30b9a3d96d4f089d514266d3a892de6608d30707aa44be31cca89ca9fe"},{"path":"product/qualification/auths-recipe-qualification/src/canonical.rs","sha256":"30a9b50777f0dcb4b606abfee2467d5a975d9f6ad941ab6c13ca3df5b359f667"},{"path":"product/qualification/auths-recipe-qualification/src/closure.rs","sha256":"0ad6aee9bd981e2863fa725f209ec84031db2ff12f4c7ac3aaf5120f0bb86039"},{"path":"product/qualification/auths-recipe-qualification/src/commissioning.rs","sha256":"db135c55e4e3079a73253ebae275536523eb36b545d1c152b4d7dce3c6b76828"},{"path":"product/qualification/auths-recipe-qualification/src/commissioning/tests.rs","sha256":"4dde3736d206099b1bea4c14e0092c6c1287d1af9065958777d7c54331dd8686"},{"path":"product/qualification/auths-recipe-qualification/src/error.rs","sha256":"52d5cf720a1e4579008fdda90a3ac2c31f0b8db57985f121f65e54b4da2b7dd1"},{"path":"product/qualification/auths-recipe-qualification/src/evidence.rs","sha256":"ba45a7409d67a8af26ab811af306412014557477a101ab2a8eb0faf8f2bd4b91"},{"path":"product/qualification/auths-recipe-qualification/src/ids.rs","sha256":"e81a906d571497ab2da753e1532d4443706410e0b75fdd59a7d2d788c7aec403"},{"path":"product/qualification/auths-recipe-qualification/src/launch.rs","sha256":"805154ce931e3977f2a2a2c62909d90f7c0a22dc167bf4f1554dcf19316ffef8"},{"path":"product/qualification/auths-recipe-qualification/src/lib.rs","sha256":"0e24b0f81191df0d078c7f4d73ced784ba9472372bfcdff3c7d0e2fb1687b323"},{"path":"product/qualification/auths-recipe-qualification/src/model.rs","sha256":"3484eb0ec287b23d4682ade7b1b0f8d1335985b3fb180f06fc28716076957d5f"},{"path":"product/qualification/auths-recipe-qualification/src/release.rs","sha256":"ec478e53f70052e566aac7e15be2f9e1b1cd46837ac6990ae955fa864d311586"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/mod.rs","sha256":"fa23a962fd90331152eed5edbcdf271955f7aed79b8da1e065bfe69a20b487a9"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/schemas.rs","sha256":"c59feec2805621f341a90f81fc005e2c12f7a70f9d264fdeacccb2be4fe1c046"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/verification.rs","sha256":"bdf5746fed4d10a7f577f7878619a917d29aa8b7d522f00d9f774e53eff4c8c1"},{"path":"product/qualification/auths-recipe-qualification/src/verify.rs","sha256":"646ff0e52e915174ad183768706e35e5ce2118b83475455310b930a77a7877f6"},{"path":"product/receipts/auths-receipts/Cargo.toml","sha256":"6001fa1375899953aafcb07c23a6da0c8f57ea7ec08bb9c950b12a60a8cc6f0f"},{"path":"product/receipts/auths-receipts/src/disclosure.rs","sha256":"ba9ed439be0a320c8a01f5b6e9b51361c1a37e076947490d8e4a484ba6bb119c"},{"path":"product/receipts/auths-receipts/src/lib.rs","sha256":"547a57c4160256719cafb7d0ab972d9fc80b0da14fbbce4148c70c414070ff36"},{"path":"product/runtime/auths-connections/Cargo.toml","sha256":"babeb6e1dda3dfb66291713ce1e43dce5c349833d0b50ea4dccbf986030026b2"},{"path":"product/runtime/auths-connections/src/credential.rs","sha256":"82921413bb053f0f6c7931fbd4e6a86c8cc1d8c6b51debd9c2cef33a8d5b1c51"},{"path":"product/runtime/auths-connections/src/kernel.rs","sha256":"a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8"},{"path":"product/runtime/auths-connections/src/lib.rs","sha256":"79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22"},{"path":"product/runtime/auths-connections/src/model.rs","sha256":"de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77"},{"path":"product/runtime/auths-connections/src/registry.rs","sha256":"e57640e003e72ad3235c567c2bb944a262bd64e673f023b62ea091094cc7e946"},{"path":"product/runtime/auths-gateway-kernel/Cargo.toml","sha256":"34f864e67656af4ac7e5c7a347a23f01fc8ab31365b8e23c0ef474483b14a183"},{"path":"product/runtime/auths-gateway-kernel/src/construct.rs","sha256":"e9d65744bae273d65face4285e5d2da75c06a92ab48f7b8333d496604e31c63c"},{"path":"product/runtime/auths-gateway-kernel/src/lib.rs","sha256":"cfda6f8453426564c085475f183b6f790b438768a19668f1b65d33ba59dc8632"},{"path":"product/runtime/auths-gateway-kernel/src/order.rs","sha256":"e0045f877c4b7fe3860c291039853885064ddcdebba7c9b345ab65e81e646dda"},{"path":"product/runtime/auths-gateway-kernel/src/outcome.rs","sha256":"e9785b1afe70788c89b51b18655bcd5acff7b0c8e3d12fb79c6f05a202e67e6b"},{"path":"product/runtime/auths-gateway-kernel/src/ratio.rs","sha256":"7ace22264812e6fc1ef3a62afee402cf43494bb71ae0d3de219ad1b39d690bcb"},{"path":"product/runtime/auths-gateway-kernel/src/recovery.rs","sha256":"9f46dcd1685ab6e4d1ba04a3fc286a9f3afee8fb47829be1fbc670a7926a2dc6"},{"path":"product/runtime/auths-gateway-kernel/src/transition.rs","sha256":"cefb8f01d915880f6921f2501ff881ad94b9de61072c34d9cd19220992f97374"},{"path":"product/runtime/auths-gateway/Cargo.toml","sha256":"00b28be86921dcdc0ad90cce0c62c2961cafefe96ea6c2edf0e926c3d405ccad"},{"path":"product/runtime/auths-gateway/src/admin.rs","sha256":"0dee40a9fb67c5de10142fc37a7bbabdd8979fb0199fb26caf4bdb024e0a5a40"},{"path":"product/runtime/auths-gateway/src/app.rs","sha256":"6f80f63833ea0815bb44fbf3b0cc54624a08e9fb578b035819f2980dc04e8256"},{"path":"product/runtime/auths-gateway/src/audit.rs","sha256":"0edb2037eb7b5d6f13acfce85c54f62a82bf7fdd31bc7e626c4fec183cef61dd"},{"path":"product/runtime/auths-gateway/src/audit_tests.rs","sha256":"990969384a52d75bc2489d9d412a9e7dd814bca1c8f65c701d6205fae62a15d5"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway-harness.rs","sha256":"12b0c24d36b2e6a3be392d3c081a783b355fdd67dc5b54bacc0410e803116b8c"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway.rs","sha256":"3dba485deeb4d60f3f5603ad4ce9a0edf49a85c68c5c4ca072df73d2910da832"},{"path":"product/runtime/auths-gateway/src/binding.rs","sha256":"663b0ce878319511aa7d05722ab4ab2fa9be18817884ffb2ee9f131ff1e382d1"},{"path":"product/runtime/auths-gateway/src/bounds.rs","sha256":"38251ad6f22f9d07ef9a219c79fa265ca36f1526eca5f147d7efa46b52ad609d"},{"path":"product/runtime/auths-gateway/src/bounds_aggregate_tests.rs","sha256":"ab34f227b7c8692ba1da88ccb32bb3687a66adf8353d8282fae905d4a88eb612"},{"path":"product/runtime/auths-gateway/src/bounds_tests.rs","sha256":"74136bc570da7b9338b5a1a1ed9d3fd892c55135160964f9d3ac0e2cf5741375"},{"path":"product/runtime/auths-gateway/src/commissioning_budget.rs","sha256":"fab29da3269438cc62330f3eab7b5bd4dc482b4db8af243aae47df5d3aa1deb8"},{"path":"product/runtime/auths-gateway/src/commissioning_budget/tests.rs","sha256":"da104a1643c37515deec6397bca6db2054f2c9158ec3d230a1b1ec9c7d0f659f"},{"path":"product/runtime/auths-gateway/src/commissioning_floor.rs","sha256":"7fa6991c5ccd5ae1403be84b3da390323fab09f36e15ac01fd7a38ea350c6fdb"},{"path":"product/runtime/auths-gateway/src/commissioning_floor/tests.rs","sha256":"6b663d6e556adc0b455b81845bc4394d82c6c4de0c5f43e1310f3ddc6e4e40f7"},{"path":"product/runtime/auths-gateway/src/commissioning_session.rs","sha256":"24b48d5eaeaaa3c620e2dfc7ee1f9255fc4519a1eb404b8608cea7af6a910ee2"},{"path":"product/runtime/auths-gateway/src/commissioning_session/tests.rs","sha256":"37a097fc8a9261d3fffdaef3f905f40b22e3e6601bb5101fadd9414f963c0824"},{"path":"product/runtime/auths-gateway/src/connection.rs","sha256":"e8d24277d7e4a53610e091fe78b373b841245d8e59a2bc788716b76e7d912441"},{"path":"product/runtime/auths-gateway/src/credential_journal.rs","sha256":"7297fccaee5cd8622928e8e0a42bba50da7941970a6f682ecd300c41ee6509da"},{"path":"product/runtime/auths-gateway/src/echo_verify.rs","sha256":"6d453051665f823abd7354d5c50031d9524cf47d6092d2f09080ae814e3b9575"},{"path":"product/runtime/auths-gateway/src/engine.rs","sha256":"c16e9b0ead514b6357f5b09914fae9de9a8977e1a2dac20e3aefeecb1cc16ee4"},{"path":"product/runtime/auths-gateway/src/execution_witness.rs","sha256":"e8b1a8e41d5e3fa309760067849d390ef065feeb46701a83391832645a2f000c"},{"path":"product/runtime/auths-gateway/src/fuzzing.rs","sha256":"ed3b0028487eb546a3b0a91d115aa8f18bcea324b61620bfe8e35a9e6ab18758"},{"path":"product/runtime/auths-gateway/src/generation_floor.rs","sha256":"fe1510ec96ce0f67e9a78edbfa94b33eb7df64c0ac4d0a67901124dcd0164777"},{"path":"product/runtime/auths-gateway/src/harness.rs","sha256":"c87e479f3eb281960f6c9c80d43c7560d7ccb654b0154ec823d3fcec4884ac05"},{"path":"product/runtime/auths-gateway/src/lib.rs","sha256":"fad95d031f88072dd024c78facf0bb0267562b1ac743ddd7219fce47e64024f0"},{"path":"product/runtime/auths-gateway/src/listener.rs","sha256":"aa08239bcbc1fcb55e8a212fbdf6a84f12985b0d436dcb51dc58b06e59e435f2"},{"path":"product/runtime/auths-gateway/src/observed_tests.rs","sha256":"a22be071695f89ca2578a4d82fd80d9cb82289213c9bdb8f0470f6b2dc3d9201"},{"path":"product/runtime/auths-gateway/src/observer.rs","sha256":"562ffcaea071c3856e0708dc2fe33516917e145d2438aabb75af0a2b6ba01046"},{"path":"product/runtime/auths-gateway/src/onboarding.rs","sha256":"0dfd7d67e7f02f18a28d1c86ca1b7751d7463f5efcdbe3825de0ad8cbccb3891"},{"path":"product/runtime/auths-gateway/src/operator.rs","sha256":"c3c36954a3e86723df035b47f43b85fc8ab3a6292983522b6258d5c6b4e6c4e4"},{"path":"product/runtime/auths-gateway/src/pending_vectors/attempts.rs","sha256":"47ef3c8cb1c5504d47ae9a0088705ce6715fe86bac1671a34a56fb38a64d0dd3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/bounds.rs","sha256":"e612217307e1da5b0eb5ee6582a7458bb064b8aa8a529fc6555b1b334127ab68"},{"path":"product/runtime/auths-gateway/src/pending_vectors/codes.rs","sha256":"e00670a5ef24eb856cc2c6dcda8e5a263842f55c76bb939c0c27bd9df37e5522"},{"path":"product/runtime/auths-gateway/src/pending_vectors/keys.rs","sha256":"f84c56f2ea9cb34b2b79c72d13fbf2c6585010ec1ed450af58a78c80c1ea1edd"},{"path":"product/runtime/auths-gateway/src/pending_vectors/mod.rs","sha256":"5de8340f0ef71a0b57a09e323fefe473d3160c6ae952b9ba46f714825fbacafc"},{"path":"product/runtime/auths-gateway/src/pending_vectors/outcomes.rs","sha256":"8ec07b9511b48913af36ac999d2aa0e82924289f6acb23ddaeb9f00f99815166"},{"path":"product/runtime/auths-gateway/src/pending_vectors/production.rs","sha256":"772d032e0a0d9c924fb6d6c188528db85a97e71c9e466ddc19eee277baf83614"},{"path":"product/runtime/auths-gateway/src/pending_vectors/recipes.rs","sha256":"51693208270231c25c3aef2a32151d5962114c71e86b88cb9df83181c7af83d9"},{"path":"product/runtime/auths-gateway/src/pre_entry.rs","sha256":"06ea78ca140468bfaba17d9ab04912ad68673954c3203c98fed28272ff2a00c0"},{"path":"product/runtime/auths-gateway/src/property_tests.rs","sha256":"939c081e2e154aaf10186754044bdd65608932c899b970a04a71d0afaa999a93"},{"path":"product/runtime/auths-gateway/src/qualification.rs","sha256":"c597c83de2b94f0374ae54e40a8b57c2a64ec6e254704dca32185f448a908aca"},{"path":"product/runtime/auths-gateway/src/qualification_simulation.rs","sha256":"4ee7cadfb5f46a92713c80f3e55f499cb074d04d8b21ea89d57762af38642bfa"},{"path":"product/runtime/auths-gateway/src/qualification_tests.rs","sha256":"a9178a2e58eea459d5e5dafc53a3999ea7c84dbbffefe6e5eb1f3d098827f028"},{"path":"product/runtime/auths-gateway/src/quorum_tests.rs","sha256":"a78380b019104d688c11a4410082c7e08ded3106aab099954c4f8a1b4ae0fd89"},{"path":"product/runtime/auths-gateway/src/readiness.rs","sha256":"911c3f11892f94641574375e2da4c671c802738f71082f12c39832331052d43d"},{"path":"product/runtime/auths-gateway/src/recipe.rs","sha256":"fecf9af67e7afc48d080e9f8f55f8ce28e49d0e08988717a27908bbda461d6b6"},{"path":"product/runtime/auths-gateway/src/recipe/lower.rs","sha256":"8088b8751ed831dbb48247af953c6290ac95e2a438ccd5bd65eff54be06a1fd1"},{"path":"product/runtime/auths-gateway/src/recipe/review.rs","sha256":"c3eb7d9fdd98dacf52750b14b67ad7b7faaecbbdeafff1e0b049f67d0a2d0139"},{"path":"product/runtime/auths-gateway/src/recipe/runtime.rs","sha256":"c286f0d15f974402822c0810d8e97f98411dc1c557755cc23e540d85e2bb42d9"},{"path":"product/runtime/auths-gateway/src/recipe/source.rs","sha256":"1af50298fb1461e1b24cbdf560d43124d6b1c4c529586c911b1c4797214a69ff"},{"path":"product/runtime/auths-gateway/src/recipe/tests.rs","sha256":"aac551a2481bbc60864c64079bc667dcb232e45a0f41a04073ed84ab5dbe1fce"},{"path":"product/runtime/auths-gateway/src/recipe/validate.rs","sha256":"3711b17605cb7b0d639bc1b180449231f5882a306cab20e2c7782155cc63b0d4"},{"path":"product/runtime/auths-gateway/src/scenario_tests.rs","sha256":"025b53473b3af6900e03bc2fee91aa63ed26a8778bc8c8296fe08f5540794c39"},{"path":"product/runtime/auths-gateway/src/separation.rs","sha256":"be9306848ca5d801767cf6aa14247c8618312ef0e202f00ce0c24c4844491061"},{"path":"product/runtime/auths-gateway/src/simulation_attestation.rs","sha256":"88705e5d45415f760f1e3c3a065c35c48f4f4065bf7b3feb7882246983814d6f"},{"path":"product/runtime/auths-gateway/src/store.rs","sha256":"884bcad4d70d53e12eae9c8517f6ecd0643068ee0be0370015119d04d6cc2516"},{"path":"product/runtime/auths-gateway/src/store_testkit.rs","sha256":"88d82fee42f1b8ef521e8deef0216e938ebeaad822eb2f5020e70b89d145ea70"},{"path":"product/runtime/auths-gateway/src/submit.rs","sha256":"fe2eacb5ad8152eeecbd232c47a356fc72db0098e34fda99532bdf6ef0cf895c"},{"path":"product/runtime/auths-gateway/src/support.rs","sha256":"9fd979029793a22b15d9776a7fc172476fd7c126a80d4080c65d720845becbcb"},{"path":"product/runtime/auths-gateway/src/transport.rs","sha256":"978fc9fb34a33b3db265b5d1c3ce11696a5b9f08529e46dd2a1e7bb62afb9220"},{"path":"product/runtime/auths-kernel-runtime/Cargo.toml","sha256":"926bcd0053e5edd703be8f0027ad009e2982db013c8174c1366edbf38b48087d"},{"path":"product/runtime/auths-kernel-runtime/src/lib.rs","sha256":"7108faae9ca4bc32dc093ddaf885ac8f74f3c9b8d317b7c7d0ed00d1d0ab5972"},{"path":"product/runtime/auths-lifecycle/Cargo.toml","sha256":"c5053c705f8d5554b44e432fe75287a2faf11d644e5a2552e45ad6cd94176af5"},{"path":"product/runtime/auths-lifecycle/src/codec.rs","sha256":"51c4b746749150e8bfcd8ff972b3f6c1ef40bec15583448ec1b471d9ad737dc0"},{"path":"product/runtime/auths-lifecycle/src/digest.rs","sha256":"55282cd7d8aba37713c2dcb5357c9877819edb72a30eadefb860d28d7d3a3eb7"},{"path":"product/runtime/auths-lifecycle/src/identifier.rs","sha256":"31620e8c16de68d3d2d3b84d6353c1a5b9d4151d8247f91fa389b906a8e660f1"},{"path":"product/runtime/auths-lifecycle/src/kernel.rs","sha256":"2abb8c094b36d35b364e74d78091d14c5d6f3d1eb6552cca3b5538dbd017ce23"},{"path":"product/runtime/auths-lifecycle/src/lib.rs","sha256":"afe5a345cd309b5a4f08ffba3170a6d7f16ff914892b3f2006d5208ed24ec736"},{"path":"product/runtime/auths-lifecycle/src/model.rs","sha256":"1af12bbeeeaa65ec02ddcebd7d2c8c92ec1e339fa40ae85b45ab9b01a722a4fa"},{"path":"product/runtime/auths-lifecycle/src/operation.rs","sha256":"78e6d05fcf5d7ea4f148032a3fa26fdfcab77eb346019effe927b08e0d64d732"},{"path":"product/runtime/auths-lifecycle/src/registry.rs","sha256":"53495fe6f7a77422593a41623e28716f1c140dcc1e00f87f6b0ffbfb93a5ef90"},{"path":"product/runtime/auths-lifecycle/src/sealed.rs","sha256":"2e0c03b5813c926c159598bb7890d1523825edbe57cd687d42a5dfb3374a0c19"},{"path":"product/runtime/auths-lifecycle/src/test_support.rs","sha256":"221d9a5c5ef8e1f9f8fd66927484eaf813571d0568470278ecd8fa08a5eec8cd"},{"path":"product/runtime/auths-lifecycle/src/transition.rs","sha256":"011805a28efdd541f44ccea54dd0e34a1e58f4004447ee58013703b4fb6b2822"},{"path":"product/runtime/auths-runtime/Cargo.toml","sha256":"dd29d80a8b4bb56c869f036a6c9998f6e6d1c0383ac5dc03fa42b24abe2a7ff7"},{"path":"product/runtime/auths-runtime/src/lib.rs","sha256":"132ca03d58c14905d3a822a4972f42a22a5ad33a45f2ba9ca44f3a57d810b4b0"},{"path":"product/runtime/auths-runtime/src/production.rs","sha256":"fd4eff4270c571c10fcff6cf27df28961ebf074de8a1a028f500fda1ca376820"},{"path":"product/sdk/auths-approval-quorum/Cargo.toml","sha256":"df904971fca87a24194c5816738a331588fe8f164acb5d70839a35dca5f57114"},{"path":"product/sdk/auths-approval-quorum/src/lib.rs","sha256":"72e4086088a1c0912e4e1a9e980f26a5c280bf5ab16ea39c9f0f58d5096ac2ce"},{"path":"product/sdk/auths-approval-quorum/src/remote.rs","sha256":"9fa029c7c63003adf260f8aec55160c545681c60c1bace0d934e7525862aac7b"},{"path":"product/sdk/auths-approval-quorum/src/remote_tests.rs","sha256":"8a09ce17cfee82a035a74edd535f3ebeb3db0e078784740d3997b17dbdb10197"},{"path":"product/sdk/auths-approval-quorum/src/tests.rs","sha256":"0acbf12be3e497dcc6c2d8f29c9af3b1a7ed8e11b75f6399570d4f217a785060"},{"path":"product/stores/auths-stores/Cargo.toml","sha256":"a32c4b76d17b264be5d40d24497ff237e1ed87822e8bab86229b3db93106dbe3"},{"path":"product/stores/auths-stores/src/gateway_attempt.rs","sha256":"218841602d3d9b23b44625f50e5b54cf275ccedc2d5c89f02d2482b8524472af"},{"path":"product/stores/auths-stores/src/lib.rs","sha256":"e721262edf8a9ab5568ddc27639176312d4a366203b5f73e2d7c11fde2c554e9"},{"path":"product/stores/auths-stores/src/lifecycle.rs","sha256":"3f2cecfda13fdcd7c4a944518646bcc8abd1237f900c0332d5822281f8f9f1cd"}],"schema":"auths.gateway-semantic-closure/1"} \ No newline at end of file diff --git a/product/runtime/auths-gateway/src/semantic_closure.rs b/product/runtime/auths-gateway/src/semantic_closure.rs index 994940746..c6055da6f 100644 --- a/product/runtime/auths-gateway/src/semantic_closure.rs +++ b/product/runtime/auths-gateway/src/semantic_closure.rs @@ -10,7 +10,7 @@ /// SHA-256 of the schema, a NUL byte, and `semantic-closure.json`. /// Regenerate through `semantic_closure_is_current` with `AUTHS_UPDATE_FIXTURES=1`. pub const GATEWAY_SEMANTIC_CLOSURE_SHA256: &str = - "d2535ce12c2c5b369e5bf3ff27c6943d4be6bcba88759a1632de61d90af34073"; + "882b7d420db79dadd3ca735b4391d072f82adc8ee8d289f705259b6548fef4de"; #[cfg(test)] mod tests { diff --git a/qualification/README.md b/qualification/README.md index cff34448a..bbace1059 100644 --- a/qualification/README.md +++ b/qualification/README.md @@ -225,9 +225,12 @@ job. ## Environments -Each family's live environment, `recipe-qualification-live-`, must be -created with a required reviewer and the default branch only **before** its -credential is stored in it. The signing environment already has both rules. +The live matrix uses the existing `gateway-custody-live` environment. Its first +step checks an actual required reviewer and exactly one deployment branch policy, +`main`, before reaching a credential-bearing step. Missing protection refuses; +the workflow never creates an environment or changes its policy. Both family +records name that exact environment, which the launch verifier requires. +The signing environment already has reviewer and default-branch rules. The harness of a family is trusted as reviewed code on the default branch; the run does not execute anything a harness leaves behind as a program in the jobs that assemble, sign, or verify. From e82c47f00e5a235844472f1b1643d43575dbb82a Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 19:18:09 +0100 Subject: [PATCH 104/108] Supersede obsolete credential-free qualification PR runs --- .github/workflows/recipe-qualification.yml | 2 +- .../tests/protected_run.rs | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/.github/workflows/recipe-qualification.yml b/.github/workflows/recipe-qualification.yml index 15d0abf75..bb8f696cb 100644 --- a/.github/workflows/recipe-qualification.yml +++ b/.github/workflows/recipe-qualification.yml @@ -26,7 +26,7 @@ permissions: concurrency: group: recipe-qualification-${{ github.ref }} - cancel-in-progress: false + cancel-in-progress: ${{ github.event_name == 'pull_request' }} jobs: candidate: diff --git a/product/qualification/auths-recipe-qualification-issuance/tests/protected_run.rs b/product/qualification/auths-recipe-qualification-issuance/tests/protected_run.rs index b099fcae6..5586a9e4e 100644 --- a/product/qualification/auths-recipe-qualification-issuance/tests/protected_run.rs +++ b/product/qualification/auths-recipe-qualification-issuance/tests/protected_run.rs @@ -225,6 +225,13 @@ fn custody_environment_protection_is_checked_before_provider_credentials() { assert!(!live.iter().any(|line| line.contains("--method"))); } +#[test] +fn only_credential_free_pull_request_runs_can_be_superseded() { + let text = std::fs::read_to_string(repository().join(WORKFLOW)).expect("workflow"); + assert!(text.contains("cancel-in-progress: ${{ github.event_name == 'pull_request' }}")); + assert!(!text.contains("cancel-in-progress: true")); +} + #[test] fn other_workflows_cannot_reach_qualification_signing() { // No other workflow names the signer's key, and nothing in the From dc823739b04b4dc579ec4a42bf0e2af6b32cee8f Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 19:24:00 +0100 Subject: [PATCH 105/108] Stop obsolete credential-free package builds from piling up --- .github/workflows/gateway-isolation.yml | 4 ++++ .github/workflows/gateway-operator-package.yml | 4 ++++ .github/workflows/python-sdk.yml | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/.github/workflows/gateway-isolation.yml b/.github/workflows/gateway-isolation.yml index e3aa27d47..252326fd5 100644 --- a/.github/workflows/gateway-isolation.yml +++ b/.github/workflows/gateway-isolation.yml @@ -11,6 +11,10 @@ on: permissions: contents: read +concurrency: + group: gateway-isolation-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} + jobs: distinct-uid: if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository diff --git a/.github/workflows/gateway-operator-package.yml b/.github/workflows/gateway-operator-package.yml index d866b672c..49024f6b0 100644 --- a/.github/workflows/gateway-operator-package.yml +++ b/.github/workflows/gateway-operator-package.yml @@ -13,6 +13,10 @@ on: permissions: contents: read +concurrency: + group: gateway-operator-package-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} + jobs: package: runs-on: ubuntu-latest diff --git a/.github/workflows/python-sdk.yml b/.github/workflows/python-sdk.yml index 261202adf..022cc1701 100644 --- a/.github/workflows/python-sdk.yml +++ b/.github/workflows/python-sdk.yml @@ -35,6 +35,10 @@ on: permissions: contents: read +concurrency: + group: python-sdk-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} + jobs: source-contract: name: source behavior and contracts From b19e79353b95569d21c5eec80ae6e9697b822be6 Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 20:09:33 +0100 Subject: [PATCH 106/108] Explain recipe verification settings without internal terminology --- bindings/recipes/tools/generate-docs.mjs | 4 ++-- docs/product/recipes/02_VERIFY_AUTHORITY.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/bindings/recipes/tools/generate-docs.mjs b/bindings/recipes/tools/generate-docs.mjs index 87bc12e43..258bfab19 100644 --- a/bindings/recipes/tools/generate-docs.mjs +++ b/bindings/recipes/tools/generate-docs.mjs @@ -11,7 +11,7 @@ const descriptions = { }; const authoritySetup = [ - "This recipe reads existing canonical proof, action and trusted-context bytes. Put them in one directory as `workflow.proof.cbor`, `workflow.action.cbor` and `workflow.context.cbor`, and set `AUTHS_RECIPE_FIXTURE` to that directory.", + "This recipe reads a signed proof, its exact action and verification settings describing which signing identities you accept. Put them in one directory as `workflow.proof.cbor`, `workflow.action.cbor` and `workflow.context.cbor`, and set `AUTHS_RECIPE_FIXTURE` to that directory.", "", "For a disposable example, run this with the installed Python package. It generates its own in-memory signing key and public test artifacts; it needs no checkout, provider credential or downloaded fixture. The generated context trusts that disposable key only and is not production trust.", "", @@ -41,7 +41,7 @@ const authoritySetup = [ ].join("\n"); const protectedClaims = { "01-authenticate-identity": "The native Rust implementation checks the identity, signature and exact message binding. This authenticates bytes; it grants no authority and performs no provider write.", - "02-verify-authority": "The native Rust verifier checks the supplied proof against the exact action and explicit trusted context. An authorized result is an offline verification result; it acquires no credential and performs no provider write.", + "02-verify-authority": "The native Rust verifier checks the supplied proof against the exact action and your explicit verification settings. An authorized result is an offline verification result; it acquires no credential and performs no provider write.", }; const failureExercises = { "01-authenticate-identity": "The Python example changes the message while keeping the original signature and requires authentication to fail. No provider is contacted.", diff --git a/docs/product/recipes/02_VERIFY_AUTHORITY.md b/docs/product/recipes/02_VERIFY_AUTHORITY.md index a8ee9ab09..93969718b 100644 --- a/docs/product/recipes/02_VERIFY_AUTHORITY.md +++ b/docs/product/recipes/02_VERIFY_AUTHORITY.md @@ -8,7 +8,7 @@ Verify existing proof, action, and trust bytes without gaining an execution capa Use a supported Node.js or CPython runtime and install the single Auths package. The executable source below is run against the packed npm artifact and wheel in CI. -This recipe reads existing canonical proof, action and trusted-context bytes. Put them in one directory as `workflow.proof.cbor`, `workflow.action.cbor` and `workflow.context.cbor`, and set `AUTHS_RECIPE_FIXTURE` to that directory. +This recipe reads a signed proof, its exact action and verification settings describing which signing identities you accept. Put them in one directory as `workflow.proof.cbor`, `workflow.action.cbor` and `workflow.context.cbor`, and set `AUTHS_RECIPE_FIXTURE` to that directory. For a disposable example, run this with the installed Python package. It generates its own in-memory signing key and public test artifacts; it needs no checkout, provider credential or downloaded fixture. The generated context trusts that disposable key only and is not production trust. @@ -112,7 +112,7 @@ print( ## What Auths protected -The native Rust verifier checks the supplied proof against the exact action and explicit trusted context. An authorized result is an offline verification result; it acquires no credential and performs no provider write. +The native Rust verifier checks the supplied proof against the exact action and your explicit verification settings. An authorized result is an offline verification result; it acquires no credential and performs no provider write. ## Break it safely From 9c7b893b81a9bacd6ccaf64b5026bef71ea8805e Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 20:29:34 +0100 Subject: [PATCH 107/108] Refresh the frozen recipe vocabulary after documentation correction --- release/semantic-freeze-versions.toml | 6 +++--- release/semantic-freeze.json | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/release/semantic-freeze-versions.toml b/release/semantic-freeze-versions.toml index ae344f8e6..f5d8e7158 100644 --- a/release/semantic-freeze-versions.toml +++ b/release/semantic-freeze-versions.toml @@ -1,4 +1,4 @@ -freeze_version = 384 +freeze_version = 385 # Semantic identity counters live outside the xtask source tree deliberately. # The formal source closure binds xtask's executable code, while the semantic @@ -64,7 +64,7 @@ freeze_version = 384 "auths.product.receipts" = 13 "auths.product.release-assurance" = 7 "auths.product.simplified-waist" = 19 -"auths.product.vocabulary" = 25 +"auths.product.vocabulary" = 26 "auths.release.benchmark-contract" = 1 "auths.release.evolution-contract" = 79 -"auths.release.public-surface" = 384 +"auths.release.public-surface" = 385 diff --git a/release/semantic-freeze.json b/release/semantic-freeze.json index 1fe86b1dc..3db6982e2 100644 --- a/release/semantic-freeze.json +++ b/release/semantic-freeze.json @@ -1,6 +1,6 @@ { "schema": "auths.semantic-freeze/1", - "freezeVersion": 384, + "freezeVersion": 385, "publicSurface": { "rustRoots": [ "auths", @@ -947,7 +947,7 @@ }, { "id": "auths.product.vocabulary", - "version": 25, + "version": 26, "classification": "frozen-meaning", "categories": [ "customer-vocabulary", @@ -965,7 +965,7 @@ "product/sdk/auths-sdk/Cargo.toml", "xtask/src/sdk_vocabulary.rs" ], - "sha256": "628e240b6eef2c93490d8604349446427a7c906598714472edd611a6aa3311f7" + "sha256": "f40e2656eed0d34ce4914753a92e4d67806d40b6b20bb7693cf13d36bb01575f" }, { "id": "auths.release.benchmark-contract", @@ -1011,7 +1011,7 @@ }, { "id": "auths.release.public-surface", - "version": 384, + "version": 385, "classification": "release-metadata", "categories": [ "package-names", @@ -1104,7 +1104,7 @@ "xtask/src/release_launch.rs", "xtask/src/semantic_freeze.rs" ], - "sha256": "6a53aad1cf6bb3e1da1698f8128db89024bdefa4acd10f7732cdbf7af01ff949" + "sha256": "50c5f5c6352019bfcfc61f23e15b4552e7f8b4d32e4305f36b10120802439107" } ] } From 096579ad5d41ac34cfd4a424ab64eed6cf14f9ea Mon Sep 17 00:00:00 2001 From: bordumb Date: Wed, 7 Oct 2026 20:51:25 +0100 Subject: [PATCH 108/108] Use the existing private temp directory in interrupted-install cleanup regression --- product/runtime/auths-gateway/semantic-closure.json | 2 +- product/runtime/auths-gateway/src/engine.rs | 3 ++- product/runtime/auths-gateway/src/semantic_closure.rs | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/product/runtime/auths-gateway/semantic-closure.json b/product/runtime/auths-gateway/semantic-closure.json index 0dce77209..b5d7f2261 100644 --- a/product/runtime/auths-gateway/semantic-closure.json +++ b/product/runtime/auths-gateway/semantic-closure.json @@ -1 +1 @@ -{"files":[{"path":"Cargo.lock","sha256":"0e75e2fdef44e79e57797ac6661295ae58ddb8de4a1990a6fd22ce6c54f78604"},{"path":"Cargo.toml","sha256":"6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24"},{"path":"core/adapters/auths-did-keri/Cargo.toml","sha256":"86ba3e3f9a0a70d970568bfb3113b7ba7bbdd81c3eebbb52743dd574a0c0ecaa"},{"path":"core/adapters/auths-did-keri/src/lib.rs","sha256":"a75674842f8a7142004369ccd206ab43e476459293f0ff4bed4d4e659031b3e3"},{"path":"core/adapters/auths-did-key/Cargo.toml","sha256":"d5a3ae07ecde83f91eed4c3785051dd0f44eab6c891754f3309b6b40596707d7"},{"path":"core/adapters/auths-did-key/src/lib.rs","sha256":"b76a3f4528a725df53cfa9242e6e414e1d26caa48468aaed497e28b121f4497c"},{"path":"core/adapters/auths-raw-key/Cargo.toml","sha256":"f49616bc18c19e6aaa7e6a02ccebcdb9f5c1422c1278ef9869e0dbf22ceda7be"},{"path":"core/adapters/auths-raw-key/src/lib.rs","sha256":"45eec1b295dac3bed65cd79c942870b926b06b3f5d38eaebaeb6140ac69315fa"},{"path":"core/crates/auths-algebra-kernel/Cargo.toml","sha256":"0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba"},{"path":"core/crates/auths-algebra-kernel/src/generated.rs","sha256":"ae4bcbef42a408c7ffa0c6a74a42f7de177a6f14479e51d205acf830bda05960"},{"path":"core/crates/auths-algebra-kernel/src/lib.rs","sha256":"6654667eeb9b353d6648954c9fd2e8838462a82ce6b2803eb49e1366892c68c6"},{"path":"core/crates/auths-assurance/Cargo.toml","sha256":"afcb12a97ddd09d7a264b9ecd3fcaefc865ff2c9b4539ee85b00883420ba333a"},{"path":"core/crates/auths-assurance/src/lib.rs","sha256":"0fb2ec844d674b25a9e20b1601452c89c2454901fa506adfa9bb38ef9a7fa213"},{"path":"core/crates/auths-author/Cargo.toml","sha256":"1e6f0e3bc079ddb558decf0db26b291c6e72fc47327b6df1b7650d41689b215f"},{"path":"core/crates/auths-author/src/lib.rs","sha256":"e14475f2f49715a1869d5fa6b11ff1fbb72497e39097e09f833b0bae7e5b3f2b"},{"path":"core/crates/auths-author/src/observations.rs","sha256":"dda7d6bfa6f4bd7e95a480ca283c2c0e996f69c5c15cb0c7197af328131a7066"},{"path":"core/crates/auths-authority/Cargo.toml","sha256":"4f68212938029f79ebd857b4f3038494eb85d0163d49f07e51376715cf959815"},{"path":"core/crates/auths-authority/src/lib.rs","sha256":"da88d5194de4e17449e69972c0fb042afa3c39798a8f570f30771e77c384f1eb"},{"path":"core/crates/auths-codec/Cargo.toml","sha256":"e20e51826e17814effd9d8925d18d5fbdd6c0d37bf50231e743ec2611314722c"},{"path":"core/crates/auths-codec/src/approval.rs","sha256":"fbff43bf4d57f69f8b7738a8647751cde75c5a932dee65d924a1fe9c7202f91f"},{"path":"core/crates/auths-codec/src/bounded_policy.rs","sha256":"d21f6728be2d8a04b6d94921f2b683f7e61cbb42e0ac6866f1c88a49caa534c3"},{"path":"core/crates/auths-codec/src/decode.rs","sha256":"ba2999584cdf53b1b517ecb9c7ea50d39efee17c666a9a38e2ad1ac94379f778"},{"path":"core/crates/auths-codec/src/encode.rs","sha256":"8491192053e2e15d62b4d2a491de22405b7487ead69ab6f6bca40669ce7ca5f7"},{"path":"core/crates/auths-codec/src/error.rs","sha256":"fecb0737c16deb42d859f1dc7727c698438d9ac12064fd99e0024629642c390c"},{"path":"core/crates/auths-codec/src/hash.rs","sha256":"f88e111f1dbb2cef6b7b5e9c948cb45ff92e366710c8a5f5c636138aa748479e"},{"path":"core/crates/auths-codec/src/lib.rs","sha256":"3b0e5c94c6f34f750b88a9333e1d5c8145746d845d3a23e0d2f61807cf592ea7"},{"path":"core/crates/auths-codec/src/observation.rs","sha256":"38328b0c71ff97a4196eeade8b4faa889527ff1f80bb168468bcd49082a3987e"},{"path":"core/crates/auths-composition/Cargo.toml","sha256":"331e13025eb82588b5269ed3975929eb41c823d588c49e4c296273d85c6fe80e"},{"path":"core/crates/auths-composition/src/lib.rs","sha256":"e42e3b0b6a9985b73c533aeb23799c638979aa27a9ce7d0f10a8d60340570fb1"},{"path":"core/crates/auths-model/Cargo.toml","sha256":"565c15302b0cc9270db1e28efa3862804846850ba933cc17aea8abcec4a65987"},{"path":"core/crates/auths-model/src/approval.rs","sha256":"54cf44a9ef747ec21546a4086aecfb130bc7803b0d646430e6082df51e6e305f"},{"path":"core/crates/auths-model/src/bounded.rs","sha256":"f90496abc0a06c028b4d850af6ddab7d850bfafeaa3d042f1b1246a41d8bbbc9"},{"path":"core/crates/auths-model/src/bounded_policy.rs","sha256":"306a8f049cc7cfc7635fe0e4de47eb7813eed63d3c14c3be2b51586aa4eea450"},{"path":"core/crates/auths-model/src/lib.rs","sha256":"e7cfe6bb9574c6b016aa63e70658c31e0b90903ec6479a49f4a2ceb64f5bad97"},{"path":"core/crates/auths-model/src/observation.rs","sha256":"b3ed3e3cc090afca2896a7d3de7988afccc1ee1ea0ebd91b51a8bc0f20ad8dbb"},{"path":"core/crates/auths-multikey/Cargo.toml","sha256":"858756c1197befcada06134742bffe8d58cf674cadd6c046bf710570e96efaf2"},{"path":"core/crates/auths-multikey/src/lib.rs","sha256":"f5177fffb11e40eeaaa665ba886c541fc1f24d5eacdd6983fb03dc20148733f0"},{"path":"core/crates/auths-ports/Cargo.toml","sha256":"596a9b0f5af3717c16a6d13f7054d8a106bcd9f01f5f72c2235dd2afcf0ab16c"},{"path":"core/crates/auths-ports/src/binding.rs","sha256":"a16c012d40aa4249e3ec54372b9611006d0bfe8c7dc3c741911c2194ad17736d"},{"path":"core/crates/auths-ports/src/diagnostics.rs","sha256":"aa596572503b5a65a918bb2ff38281c144ff53821ee914e9325c852828d852df"},{"path":"core/crates/auths-ports/src/lib.rs","sha256":"8da1debf86f9532df0660155d04298beb1ba3a1204508f8586e2e67cd2fb3449"},{"path":"core/crates/auths-ports/src/path.rs","sha256":"b68fc547b4e4d97a60cbbc1cc1939fc6b34a8233b81f840bd396914a707e3ea1"},{"path":"core/crates/auths-raw-key-core/Cargo.toml","sha256":"98c0bc8527a537512e43a74dd6ba9658c6f0cdc16610cf938e3f9b43785d836d"},{"path":"core/crates/auths-raw-key-core/src/lib.rs","sha256":"98c0500c41697aae28708ad0bf970b9a97583d96a3d2c18d23e7fa351e0f7d12"},{"path":"core/crates/auths-registries/Cargo.toml","sha256":"590e49e58b0622d9d6274fea46796dcdb07dec9550eff295cce6a6427ffa51e2"},{"path":"core/crates/auths-registries/src/lib.rs","sha256":"450d3886d85ee333b7e046317fb5b47cde62483d5f3e41d46265e2caf4c373ec"},{"path":"core/crates/auths-registries/src/template.rs","sha256":"1224039dd2b3ce6fa8357613d8cafbae40400493da7176da202b9ade62fa05e4"},{"path":"core/crates/auths-signature-core/Cargo.toml","sha256":"6bee2230eb30af1be0bd5c2d57bd3e1903497a70028d47290d4ac6e9e0e8bca0"},{"path":"core/crates/auths-signature-core/src/lib.rs","sha256":"6e3f9311ded5e49ea50d445eb21e6d8fa12442aa4362a73e0cb6fda15b7cd865"},{"path":"core/crates/auths-signature/Cargo.toml","sha256":"7f7b5682466ba439d8c59579022cb61068cad9fb4bd2d73e1cc21327c902b450"},{"path":"core/crates/auths-signature/src/lib.rs","sha256":"b3d9ac4cc3ba0797b9e1c09f2d6ac05089b25dac4e285a5af28c0165b33d925b"},{"path":"core/crates/auths-verifier/Cargo.toml","sha256":"c43358e06a33324b41a8b93e5cc7279c55f7d21f1f6cfaa539a3fc7b4c27a38f"},{"path":"core/crates/auths-verifier/src/approval.rs","sha256":"c3cae6a49e169051eb555bb092b1069a4d422516d6a2114623a89e5f31ff923f"},{"path":"core/crates/auths-verifier/src/causal.rs","sha256":"9635230f33b13a263573d319ac8a1976addbcc07677514a43e3c7bf28dc04587"},{"path":"core/crates/auths-verifier/src/lib.rs","sha256":"f22dec38dfa47ced8da4f605390da8453273bee1da010f57fd1fdfcb10e0b389"},{"path":"core/crates/auths-verifier/src/observation.rs","sha256":"0bb07f06a0f9524c88427df1c972b1de8ba038a9eeeb15d3134c25125ae84b1e"},{"path":"core/crates/auths-verifier/src/trace.rs","sha256":"2213d72023a1d9e0413a2cf2c51c3dad9e04775d86033a0caaa9d29a8f0036f8"},{"path":"exchange/crates/auths-proof-exchange-model/Cargo.toml","sha256":"34b2db64f93a288e942b5a3918d28cdcbef906e0dc9074ce848018d3d5f7a1fa"},{"path":"exchange/crates/auths-proof-exchange-model/src/lib.rs","sha256":"49fac5aff2339d3a57c41cb8bb2a82852538e8f77ecc4b157c88e264ff31fb55"},{"path":"exchange/crates/auths-proof-exchange-port/Cargo.toml","sha256":"7ff660f1b7579dc570c791090aeb450404fbbf44c92781e289f5ccdde746d739"},{"path":"exchange/crates/auths-proof-exchange-port/src/lib.rs","sha256":"b408fb40c6432edc1facb3d8b3e9433a033f8dc73fe2e0ba5a88c972ca675021"},{"path":"product/config/auths-config/Cargo.toml","sha256":"e4b568ab9f6d84f7d7e6d66443fe825f360db9c27bc7c31d6ddc0647ba3ab304"},{"path":"product/config/auths-config/src/lib.rs","sha256":"fecf00ea65cef9018fda9af2063326d7065b869266d0d9e73a4f06816f1102cc"},{"path":"product/errors/auths-errors/Cargo.toml","sha256":"3b3a199b6460ba75bda84475bb5accd35e1485448a3981038db85bf4772dd350"},{"path":"product/errors/auths-errors/src/lib.rs","sha256":"7feeb9069fa4003f94f1f07c1c94619cf1c883e0dbaaf2187f04d0f742264bdd"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/Cargo.toml","sha256":"716f1f2a117d6d69d8effe9ee9057e24ba3502f20af6a602b06facb638cdabed"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/api.rs","sha256":"9ea61dd7ddd93282b073b98e453e6b75b26dc49689c04e9782435d06a3a09e48"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/clock.rs","sha256":"73f0a6e0f5903883329fa6683f5888288f759512ac69e5c87efd2b6b87f7d79f"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/http.rs","sha256":"14c1fce14e24c984b2a275563a29b6326fb08367922b6e8d37ba38b9cb81aa2b"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/identity.rs","sha256":"186de11230c8b33375951c4368609f8976bf9795f171af3fd7fac26207a94361"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs","sha256":"0b4617d044f5254a5ab22f5a2578f91cc025206a8c1845be39c1c56dcdf7a5df"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/names.rs","sha256":"41bb23572d6002e23ee103d6fe70ecd68764861c6f2e48a1c53af998270a4afa"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs","sha256":"39fed883f4802e68d3b41a68fea0aba0737810996b33d13577de70faba004c29"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/store.rs","sha256":"fc60ee9c49b2f4f063c449b4c78100c5c4872779e94ca168f796603b380ef6e4"},{"path":"product/integrations/auths-custody/Cargo.toml","sha256":"1e14034185ad1ec24a977fd5f41d0abee219606245c046ce2a82287fadef448b"},{"path":"product/integrations/auths-custody/src/conformance.rs","sha256":"8ed1afd58f18fc6becc268908aa6419c9aa404c79da0197963eb2599df44acf6"},{"path":"product/integrations/auths-custody/src/key.rs","sha256":"70cbb0fd21b6f5652157845a22c35be2d0f6c05b3d138fc4b9bb6dbdc3d81c40"},{"path":"product/integrations/auths-custody/src/lib.rs","sha256":"8ee593c1f59b0fd2126bdda9138026f5bc531beb64d4489a99785842e7b98b43"},{"path":"product/operations/auths-operations/Cargo.toml","sha256":"73dde1e914ba5e1386f8d49c0d730423cc72ae77ec44c6554a6a75cc8e8922b1"},{"path":"product/operations/auths-operations/src/explanation.rs","sha256":"b4a39bcbd5712cb9e735ee7deeb281f3fa6af5ddca973735bf3d87dce427ef11"},{"path":"product/operations/auths-operations/src/lib.rs","sha256":"3f401a56555113b98f57bca172a2660eaecedf76247b83a3fdbb089c133a29cd"},{"path":"product/operations/auths-operations/src/render/json.rs","sha256":"2ae042639960afee123730e945d373bc5dda1d2b3af20ae16c939a7e99b9e418"},{"path":"product/operations/auths-operations/src/render/mod.rs","sha256":"b3b7f6fe473f49227ace5a68bfc3d8dc14b5db8dd9888fd9e207070337b1b8bf"},{"path":"product/operations/auths-operations/src/render/text.rs","sha256":"f216cf3bdb00e264523271b16e7059535ac6b1aabf271cebd7935af155e4bfec"},{"path":"product/policy/auths-bounded-policy/Cargo.toml","sha256":"babd5d200923137ead71d8c2528f847cea323ce98da942a1320b054436612c47"},{"path":"product/policy/auths-bounded-policy/src/arithmetic.rs","sha256":"75e43c5d4eab8d1f71c1daf53839f5f9fe45a400afc1f63a30c6f55ce3632627"},{"path":"product/policy/auths-bounded-policy/src/commitment.rs","sha256":"c5706f2d583454e1a7f570f7ada138d4d864bef0205dfae7c1296774f396bb3f"},{"path":"product/policy/auths-bounded-policy/src/eligibility.rs","sha256":"c9acdfb793074e687fc36efad506be27dbd99ffbf40387bc66c8de39ef238432"},{"path":"product/policy/auths-bounded-policy/src/identifier.rs","sha256":"0006a32bae9eb16c4178cf797df418d2b0a781f2bc6474b741dc1a908141831c"},{"path":"product/policy/auths-bounded-policy/src/kernel.rs","sha256":"99187c28b161ac70bee1afed60711f7f645adb4d1671a01863f9849b369811d5"},{"path":"product/policy/auths-bounded-policy/src/lib.rs","sha256":"76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c"},{"path":"product/policy/auths-bounded-policy/src/receipt.rs","sha256":"3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad"},{"path":"product/policy/auths-bounded-policy/src/registry.rs","sha256":"4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0"},{"path":"product/profiles/auths-profile-api/Cargo.toml","sha256":"7ae85761f58625b5d678f961fd052eebf3e000ef565c7312e3ac857763c0017f"},{"path":"product/profiles/auths-profile-api/src/lib.rs","sha256":"a194b82b20bf8aa864c2334ef6c6aec30b2154ded972862252d5dcefa488ab95"},{"path":"product/profiles/auths-profile-mcp/Cargo.toml","sha256":"db264fc25242f7b7e4133cbe5782545b3107b406c87168ae072683cfb59eac66"},{"path":"product/profiles/auths-profile-mcp/src/arguments.rs","sha256":"a5de696586d507e2aee4a49fee99ef1ef4c51a2e46603f8838f1af6d9009833f"},{"path":"product/profiles/auths-profile-mcp/src/lib.rs","sha256":"d0f8b733a09ef8408336cdebc8948d6a5861012ce6878598b11be7084dfd4280"},{"path":"product/profiles/auths-profile-mcp/src/session.rs","sha256":"166c281fa66333388e4760d6098dad02d3359e1d5de4b8f93312c014f97abb03"},{"path":"product/qualification/auths-recipe-qualification/Cargo.toml","sha256":"b7b15b30b9a3d96d4f089d514266d3a892de6608d30707aa44be31cca89ca9fe"},{"path":"product/qualification/auths-recipe-qualification/src/canonical.rs","sha256":"30a9b50777f0dcb4b606abfee2467d5a975d9f6ad941ab6c13ca3df5b359f667"},{"path":"product/qualification/auths-recipe-qualification/src/closure.rs","sha256":"0ad6aee9bd981e2863fa725f209ec84031db2ff12f4c7ac3aaf5120f0bb86039"},{"path":"product/qualification/auths-recipe-qualification/src/commissioning.rs","sha256":"db135c55e4e3079a73253ebae275536523eb36b545d1c152b4d7dce3c6b76828"},{"path":"product/qualification/auths-recipe-qualification/src/commissioning/tests.rs","sha256":"4dde3736d206099b1bea4c14e0092c6c1287d1af9065958777d7c54331dd8686"},{"path":"product/qualification/auths-recipe-qualification/src/error.rs","sha256":"52d5cf720a1e4579008fdda90a3ac2c31f0b8db57985f121f65e54b4da2b7dd1"},{"path":"product/qualification/auths-recipe-qualification/src/evidence.rs","sha256":"ba45a7409d67a8af26ab811af306412014557477a101ab2a8eb0faf8f2bd4b91"},{"path":"product/qualification/auths-recipe-qualification/src/ids.rs","sha256":"e81a906d571497ab2da753e1532d4443706410e0b75fdd59a7d2d788c7aec403"},{"path":"product/qualification/auths-recipe-qualification/src/launch.rs","sha256":"805154ce931e3977f2a2a2c62909d90f7c0a22dc167bf4f1554dcf19316ffef8"},{"path":"product/qualification/auths-recipe-qualification/src/lib.rs","sha256":"0e24b0f81191df0d078c7f4d73ced784ba9472372bfcdff3c7d0e2fb1687b323"},{"path":"product/qualification/auths-recipe-qualification/src/model.rs","sha256":"3484eb0ec287b23d4682ade7b1b0f8d1335985b3fb180f06fc28716076957d5f"},{"path":"product/qualification/auths-recipe-qualification/src/release.rs","sha256":"ec478e53f70052e566aac7e15be2f9e1b1cd46837ac6990ae955fa864d311586"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/mod.rs","sha256":"fa23a962fd90331152eed5edbcdf271955f7aed79b8da1e065bfe69a20b487a9"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/schemas.rs","sha256":"c59feec2805621f341a90f81fc005e2c12f7a70f9d264fdeacccb2be4fe1c046"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/verification.rs","sha256":"bdf5746fed4d10a7f577f7878619a917d29aa8b7d522f00d9f774e53eff4c8c1"},{"path":"product/qualification/auths-recipe-qualification/src/verify.rs","sha256":"646ff0e52e915174ad183768706e35e5ce2118b83475455310b930a77a7877f6"},{"path":"product/receipts/auths-receipts/Cargo.toml","sha256":"6001fa1375899953aafcb07c23a6da0c8f57ea7ec08bb9c950b12a60a8cc6f0f"},{"path":"product/receipts/auths-receipts/src/disclosure.rs","sha256":"ba9ed439be0a320c8a01f5b6e9b51361c1a37e076947490d8e4a484ba6bb119c"},{"path":"product/receipts/auths-receipts/src/lib.rs","sha256":"547a57c4160256719cafb7d0ab972d9fc80b0da14fbbce4148c70c414070ff36"},{"path":"product/runtime/auths-connections/Cargo.toml","sha256":"babeb6e1dda3dfb66291713ce1e43dce5c349833d0b50ea4dccbf986030026b2"},{"path":"product/runtime/auths-connections/src/credential.rs","sha256":"82921413bb053f0f6c7931fbd4e6a86c8cc1d8c6b51debd9c2cef33a8d5b1c51"},{"path":"product/runtime/auths-connections/src/kernel.rs","sha256":"a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8"},{"path":"product/runtime/auths-connections/src/lib.rs","sha256":"79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22"},{"path":"product/runtime/auths-connections/src/model.rs","sha256":"de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77"},{"path":"product/runtime/auths-connections/src/registry.rs","sha256":"e57640e003e72ad3235c567c2bb944a262bd64e673f023b62ea091094cc7e946"},{"path":"product/runtime/auths-gateway-kernel/Cargo.toml","sha256":"34f864e67656af4ac7e5c7a347a23f01fc8ab31365b8e23c0ef474483b14a183"},{"path":"product/runtime/auths-gateway-kernel/src/construct.rs","sha256":"e9d65744bae273d65face4285e5d2da75c06a92ab48f7b8333d496604e31c63c"},{"path":"product/runtime/auths-gateway-kernel/src/lib.rs","sha256":"cfda6f8453426564c085475f183b6f790b438768a19668f1b65d33ba59dc8632"},{"path":"product/runtime/auths-gateway-kernel/src/order.rs","sha256":"e0045f877c4b7fe3860c291039853885064ddcdebba7c9b345ab65e81e646dda"},{"path":"product/runtime/auths-gateway-kernel/src/outcome.rs","sha256":"e9785b1afe70788c89b51b18655bcd5acff7b0c8e3d12fb79c6f05a202e67e6b"},{"path":"product/runtime/auths-gateway-kernel/src/ratio.rs","sha256":"7ace22264812e6fc1ef3a62afee402cf43494bb71ae0d3de219ad1b39d690bcb"},{"path":"product/runtime/auths-gateway-kernel/src/recovery.rs","sha256":"9f46dcd1685ab6e4d1ba04a3fc286a9f3afee8fb47829be1fbc670a7926a2dc6"},{"path":"product/runtime/auths-gateway-kernel/src/transition.rs","sha256":"cefb8f01d915880f6921f2501ff881ad94b9de61072c34d9cd19220992f97374"},{"path":"product/runtime/auths-gateway/Cargo.toml","sha256":"00b28be86921dcdc0ad90cce0c62c2961cafefe96ea6c2edf0e926c3d405ccad"},{"path":"product/runtime/auths-gateway/src/admin.rs","sha256":"0dee40a9fb67c5de10142fc37a7bbabdd8979fb0199fb26caf4bdb024e0a5a40"},{"path":"product/runtime/auths-gateway/src/app.rs","sha256":"6f80f63833ea0815bb44fbf3b0cc54624a08e9fb578b035819f2980dc04e8256"},{"path":"product/runtime/auths-gateway/src/audit.rs","sha256":"0edb2037eb7b5d6f13acfce85c54f62a82bf7fdd31bc7e626c4fec183cef61dd"},{"path":"product/runtime/auths-gateway/src/audit_tests.rs","sha256":"990969384a52d75bc2489d9d412a9e7dd814bca1c8f65c701d6205fae62a15d5"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway-harness.rs","sha256":"12b0c24d36b2e6a3be392d3c081a783b355fdd67dc5b54bacc0410e803116b8c"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway.rs","sha256":"3dba485deeb4d60f3f5603ad4ce9a0edf49a85c68c5c4ca072df73d2910da832"},{"path":"product/runtime/auths-gateway/src/binding.rs","sha256":"663b0ce878319511aa7d05722ab4ab2fa9be18817884ffb2ee9f131ff1e382d1"},{"path":"product/runtime/auths-gateway/src/bounds.rs","sha256":"38251ad6f22f9d07ef9a219c79fa265ca36f1526eca5f147d7efa46b52ad609d"},{"path":"product/runtime/auths-gateway/src/bounds_aggregate_tests.rs","sha256":"ab34f227b7c8692ba1da88ccb32bb3687a66adf8353d8282fae905d4a88eb612"},{"path":"product/runtime/auths-gateway/src/bounds_tests.rs","sha256":"74136bc570da7b9338b5a1a1ed9d3fd892c55135160964f9d3ac0e2cf5741375"},{"path":"product/runtime/auths-gateway/src/commissioning_budget.rs","sha256":"fab29da3269438cc62330f3eab7b5bd4dc482b4db8af243aae47df5d3aa1deb8"},{"path":"product/runtime/auths-gateway/src/commissioning_budget/tests.rs","sha256":"da104a1643c37515deec6397bca6db2054f2c9158ec3d230a1b1ec9c7d0f659f"},{"path":"product/runtime/auths-gateway/src/commissioning_floor.rs","sha256":"7fa6991c5ccd5ae1403be84b3da390323fab09f36e15ac01fd7a38ea350c6fdb"},{"path":"product/runtime/auths-gateway/src/commissioning_floor/tests.rs","sha256":"6b663d6e556adc0b455b81845bc4394d82c6c4de0c5f43e1310f3ddc6e4e40f7"},{"path":"product/runtime/auths-gateway/src/commissioning_session.rs","sha256":"24b48d5eaeaaa3c620e2dfc7ee1f9255fc4519a1eb404b8608cea7af6a910ee2"},{"path":"product/runtime/auths-gateway/src/commissioning_session/tests.rs","sha256":"37a097fc8a9261d3fffdaef3f905f40b22e3e6601bb5101fadd9414f963c0824"},{"path":"product/runtime/auths-gateway/src/connection.rs","sha256":"e8d24277d7e4a53610e091fe78b373b841245d8e59a2bc788716b76e7d912441"},{"path":"product/runtime/auths-gateway/src/credential_journal.rs","sha256":"7297fccaee5cd8622928e8e0a42bba50da7941970a6f682ecd300c41ee6509da"},{"path":"product/runtime/auths-gateway/src/echo_verify.rs","sha256":"6d453051665f823abd7354d5c50031d9524cf47d6092d2f09080ae814e3b9575"},{"path":"product/runtime/auths-gateway/src/engine.rs","sha256":"c16e9b0ead514b6357f5b09914fae9de9a8977e1a2dac20e3aefeecb1cc16ee4"},{"path":"product/runtime/auths-gateway/src/execution_witness.rs","sha256":"e8b1a8e41d5e3fa309760067849d390ef065feeb46701a83391832645a2f000c"},{"path":"product/runtime/auths-gateway/src/fuzzing.rs","sha256":"ed3b0028487eb546a3b0a91d115aa8f18bcea324b61620bfe8e35a9e6ab18758"},{"path":"product/runtime/auths-gateway/src/generation_floor.rs","sha256":"fe1510ec96ce0f67e9a78edbfa94b33eb7df64c0ac4d0a67901124dcd0164777"},{"path":"product/runtime/auths-gateway/src/harness.rs","sha256":"c87e479f3eb281960f6c9c80d43c7560d7ccb654b0154ec823d3fcec4884ac05"},{"path":"product/runtime/auths-gateway/src/lib.rs","sha256":"fad95d031f88072dd024c78facf0bb0267562b1ac743ddd7219fce47e64024f0"},{"path":"product/runtime/auths-gateway/src/listener.rs","sha256":"aa08239bcbc1fcb55e8a212fbdf6a84f12985b0d436dcb51dc58b06e59e435f2"},{"path":"product/runtime/auths-gateway/src/observed_tests.rs","sha256":"a22be071695f89ca2578a4d82fd80d9cb82289213c9bdb8f0470f6b2dc3d9201"},{"path":"product/runtime/auths-gateway/src/observer.rs","sha256":"562ffcaea071c3856e0708dc2fe33516917e145d2438aabb75af0a2b6ba01046"},{"path":"product/runtime/auths-gateway/src/onboarding.rs","sha256":"0dfd7d67e7f02f18a28d1c86ca1b7751d7463f5efcdbe3825de0ad8cbccb3891"},{"path":"product/runtime/auths-gateway/src/operator.rs","sha256":"c3c36954a3e86723df035b47f43b85fc8ab3a6292983522b6258d5c6b4e6c4e4"},{"path":"product/runtime/auths-gateway/src/pending_vectors/attempts.rs","sha256":"47ef3c8cb1c5504d47ae9a0088705ce6715fe86bac1671a34a56fb38a64d0dd3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/bounds.rs","sha256":"e612217307e1da5b0eb5ee6582a7458bb064b8aa8a529fc6555b1b334127ab68"},{"path":"product/runtime/auths-gateway/src/pending_vectors/codes.rs","sha256":"e00670a5ef24eb856cc2c6dcda8e5a263842f55c76bb939c0c27bd9df37e5522"},{"path":"product/runtime/auths-gateway/src/pending_vectors/keys.rs","sha256":"f84c56f2ea9cb34b2b79c72d13fbf2c6585010ec1ed450af58a78c80c1ea1edd"},{"path":"product/runtime/auths-gateway/src/pending_vectors/mod.rs","sha256":"5de8340f0ef71a0b57a09e323fefe473d3160c6ae952b9ba46f714825fbacafc"},{"path":"product/runtime/auths-gateway/src/pending_vectors/outcomes.rs","sha256":"8ec07b9511b48913af36ac999d2aa0e82924289f6acb23ddaeb9f00f99815166"},{"path":"product/runtime/auths-gateway/src/pending_vectors/production.rs","sha256":"772d032e0a0d9c924fb6d6c188528db85a97e71c9e466ddc19eee277baf83614"},{"path":"product/runtime/auths-gateway/src/pending_vectors/recipes.rs","sha256":"51693208270231c25c3aef2a32151d5962114c71e86b88cb9df83181c7af83d9"},{"path":"product/runtime/auths-gateway/src/pre_entry.rs","sha256":"06ea78ca140468bfaba17d9ab04912ad68673954c3203c98fed28272ff2a00c0"},{"path":"product/runtime/auths-gateway/src/property_tests.rs","sha256":"939c081e2e154aaf10186754044bdd65608932c899b970a04a71d0afaa999a93"},{"path":"product/runtime/auths-gateway/src/qualification.rs","sha256":"c597c83de2b94f0374ae54e40a8b57c2a64ec6e254704dca32185f448a908aca"},{"path":"product/runtime/auths-gateway/src/qualification_simulation.rs","sha256":"4ee7cadfb5f46a92713c80f3e55f499cb074d04d8b21ea89d57762af38642bfa"},{"path":"product/runtime/auths-gateway/src/qualification_tests.rs","sha256":"a9178a2e58eea459d5e5dafc53a3999ea7c84dbbffefe6e5eb1f3d098827f028"},{"path":"product/runtime/auths-gateway/src/quorum_tests.rs","sha256":"a78380b019104d688c11a4410082c7e08ded3106aab099954c4f8a1b4ae0fd89"},{"path":"product/runtime/auths-gateway/src/readiness.rs","sha256":"911c3f11892f94641574375e2da4c671c802738f71082f12c39832331052d43d"},{"path":"product/runtime/auths-gateway/src/recipe.rs","sha256":"fecf9af67e7afc48d080e9f8f55f8ce28e49d0e08988717a27908bbda461d6b6"},{"path":"product/runtime/auths-gateway/src/recipe/lower.rs","sha256":"8088b8751ed831dbb48247af953c6290ac95e2a438ccd5bd65eff54be06a1fd1"},{"path":"product/runtime/auths-gateway/src/recipe/review.rs","sha256":"c3eb7d9fdd98dacf52750b14b67ad7b7faaecbbdeafff1e0b049f67d0a2d0139"},{"path":"product/runtime/auths-gateway/src/recipe/runtime.rs","sha256":"c286f0d15f974402822c0810d8e97f98411dc1c557755cc23e540d85e2bb42d9"},{"path":"product/runtime/auths-gateway/src/recipe/source.rs","sha256":"1af50298fb1461e1b24cbdf560d43124d6b1c4c529586c911b1c4797214a69ff"},{"path":"product/runtime/auths-gateway/src/recipe/tests.rs","sha256":"aac551a2481bbc60864c64079bc667dcb232e45a0f41a04073ed84ab5dbe1fce"},{"path":"product/runtime/auths-gateway/src/recipe/validate.rs","sha256":"3711b17605cb7b0d639bc1b180449231f5882a306cab20e2c7782155cc63b0d4"},{"path":"product/runtime/auths-gateway/src/scenario_tests.rs","sha256":"025b53473b3af6900e03bc2fee91aa63ed26a8778bc8c8296fe08f5540794c39"},{"path":"product/runtime/auths-gateway/src/separation.rs","sha256":"be9306848ca5d801767cf6aa14247c8618312ef0e202f00ce0c24c4844491061"},{"path":"product/runtime/auths-gateway/src/simulation_attestation.rs","sha256":"88705e5d45415f760f1e3c3a065c35c48f4f4065bf7b3feb7882246983814d6f"},{"path":"product/runtime/auths-gateway/src/store.rs","sha256":"884bcad4d70d53e12eae9c8517f6ecd0643068ee0be0370015119d04d6cc2516"},{"path":"product/runtime/auths-gateway/src/store_testkit.rs","sha256":"88d82fee42f1b8ef521e8deef0216e938ebeaad822eb2f5020e70b89d145ea70"},{"path":"product/runtime/auths-gateway/src/submit.rs","sha256":"fe2eacb5ad8152eeecbd232c47a356fc72db0098e34fda99532bdf6ef0cf895c"},{"path":"product/runtime/auths-gateway/src/support.rs","sha256":"9fd979029793a22b15d9776a7fc172476fd7c126a80d4080c65d720845becbcb"},{"path":"product/runtime/auths-gateway/src/transport.rs","sha256":"978fc9fb34a33b3db265b5d1c3ce11696a5b9f08529e46dd2a1e7bb62afb9220"},{"path":"product/runtime/auths-kernel-runtime/Cargo.toml","sha256":"926bcd0053e5edd703be8f0027ad009e2982db013c8174c1366edbf38b48087d"},{"path":"product/runtime/auths-kernel-runtime/src/lib.rs","sha256":"7108faae9ca4bc32dc093ddaf885ac8f74f3c9b8d317b7c7d0ed00d1d0ab5972"},{"path":"product/runtime/auths-lifecycle/Cargo.toml","sha256":"c5053c705f8d5554b44e432fe75287a2faf11d644e5a2552e45ad6cd94176af5"},{"path":"product/runtime/auths-lifecycle/src/codec.rs","sha256":"51c4b746749150e8bfcd8ff972b3f6c1ef40bec15583448ec1b471d9ad737dc0"},{"path":"product/runtime/auths-lifecycle/src/digest.rs","sha256":"55282cd7d8aba37713c2dcb5357c9877819edb72a30eadefb860d28d7d3a3eb7"},{"path":"product/runtime/auths-lifecycle/src/identifier.rs","sha256":"31620e8c16de68d3d2d3b84d6353c1a5b9d4151d8247f91fa389b906a8e660f1"},{"path":"product/runtime/auths-lifecycle/src/kernel.rs","sha256":"2abb8c094b36d35b364e74d78091d14c5d6f3d1eb6552cca3b5538dbd017ce23"},{"path":"product/runtime/auths-lifecycle/src/lib.rs","sha256":"afe5a345cd309b5a4f08ffba3170a6d7f16ff914892b3f2006d5208ed24ec736"},{"path":"product/runtime/auths-lifecycle/src/model.rs","sha256":"1af12bbeeeaa65ec02ddcebd7d2c8c92ec1e339fa40ae85b45ab9b01a722a4fa"},{"path":"product/runtime/auths-lifecycle/src/operation.rs","sha256":"78e6d05fcf5d7ea4f148032a3fa26fdfcab77eb346019effe927b08e0d64d732"},{"path":"product/runtime/auths-lifecycle/src/registry.rs","sha256":"53495fe6f7a77422593a41623e28716f1c140dcc1e00f87f6b0ffbfb93a5ef90"},{"path":"product/runtime/auths-lifecycle/src/sealed.rs","sha256":"2e0c03b5813c926c159598bb7890d1523825edbe57cd687d42a5dfb3374a0c19"},{"path":"product/runtime/auths-lifecycle/src/test_support.rs","sha256":"221d9a5c5ef8e1f9f8fd66927484eaf813571d0568470278ecd8fa08a5eec8cd"},{"path":"product/runtime/auths-lifecycle/src/transition.rs","sha256":"011805a28efdd541f44ccea54dd0e34a1e58f4004447ee58013703b4fb6b2822"},{"path":"product/runtime/auths-runtime/Cargo.toml","sha256":"dd29d80a8b4bb56c869f036a6c9998f6e6d1c0383ac5dc03fa42b24abe2a7ff7"},{"path":"product/runtime/auths-runtime/src/lib.rs","sha256":"132ca03d58c14905d3a822a4972f42a22a5ad33a45f2ba9ca44f3a57d810b4b0"},{"path":"product/runtime/auths-runtime/src/production.rs","sha256":"fd4eff4270c571c10fcff6cf27df28961ebf074de8a1a028f500fda1ca376820"},{"path":"product/sdk/auths-approval-quorum/Cargo.toml","sha256":"df904971fca87a24194c5816738a331588fe8f164acb5d70839a35dca5f57114"},{"path":"product/sdk/auths-approval-quorum/src/lib.rs","sha256":"72e4086088a1c0912e4e1a9e980f26a5c280bf5ab16ea39c9f0f58d5096ac2ce"},{"path":"product/sdk/auths-approval-quorum/src/remote.rs","sha256":"9fa029c7c63003adf260f8aec55160c545681c60c1bace0d934e7525862aac7b"},{"path":"product/sdk/auths-approval-quorum/src/remote_tests.rs","sha256":"8a09ce17cfee82a035a74edd535f3ebeb3db0e078784740d3997b17dbdb10197"},{"path":"product/sdk/auths-approval-quorum/src/tests.rs","sha256":"0acbf12be3e497dcc6c2d8f29c9af3b1a7ed8e11b75f6399570d4f217a785060"},{"path":"product/stores/auths-stores/Cargo.toml","sha256":"a32c4b76d17b264be5d40d24497ff237e1ed87822e8bab86229b3db93106dbe3"},{"path":"product/stores/auths-stores/src/gateway_attempt.rs","sha256":"218841602d3d9b23b44625f50e5b54cf275ccedc2d5c89f02d2482b8524472af"},{"path":"product/stores/auths-stores/src/lib.rs","sha256":"e721262edf8a9ab5568ddc27639176312d4a366203b5f73e2d7c11fde2c554e9"},{"path":"product/stores/auths-stores/src/lifecycle.rs","sha256":"3f2cecfda13fdcd7c4a944518646bcc8abd1237f900c0332d5822281f8f9f1cd"}],"schema":"auths.gateway-semantic-closure/1"} \ No newline at end of file +{"files":[{"path":"Cargo.lock","sha256":"0e75e2fdef44e79e57797ac6661295ae58ddb8de4a1990a6fd22ce6c54f78604"},{"path":"Cargo.toml","sha256":"6e0240aa432bcdb5b4f855618994582d2e428afe5ee4e4f6a3f8d21a518f8d24"},{"path":"core/adapters/auths-did-keri/Cargo.toml","sha256":"86ba3e3f9a0a70d970568bfb3113b7ba7bbdd81c3eebbb52743dd574a0c0ecaa"},{"path":"core/adapters/auths-did-keri/src/lib.rs","sha256":"a75674842f8a7142004369ccd206ab43e476459293f0ff4bed4d4e659031b3e3"},{"path":"core/adapters/auths-did-key/Cargo.toml","sha256":"d5a3ae07ecde83f91eed4c3785051dd0f44eab6c891754f3309b6b40596707d7"},{"path":"core/adapters/auths-did-key/src/lib.rs","sha256":"b76a3f4528a725df53cfa9242e6e414e1d26caa48468aaed497e28b121f4497c"},{"path":"core/adapters/auths-raw-key/Cargo.toml","sha256":"f49616bc18c19e6aaa7e6a02ccebcdb9f5c1422c1278ef9869e0dbf22ceda7be"},{"path":"core/adapters/auths-raw-key/src/lib.rs","sha256":"45eec1b295dac3bed65cd79c942870b926b06b3f5d38eaebaeb6140ac69315fa"},{"path":"core/crates/auths-algebra-kernel/Cargo.toml","sha256":"0cb078915287b8c47d20fb97b6fa14135ed1c61c4985c4de2753855563c27bba"},{"path":"core/crates/auths-algebra-kernel/src/generated.rs","sha256":"ae4bcbef42a408c7ffa0c6a74a42f7de177a6f14479e51d205acf830bda05960"},{"path":"core/crates/auths-algebra-kernel/src/lib.rs","sha256":"6654667eeb9b353d6648954c9fd2e8838462a82ce6b2803eb49e1366892c68c6"},{"path":"core/crates/auths-assurance/Cargo.toml","sha256":"afcb12a97ddd09d7a264b9ecd3fcaefc865ff2c9b4539ee85b00883420ba333a"},{"path":"core/crates/auths-assurance/src/lib.rs","sha256":"0fb2ec844d674b25a9e20b1601452c89c2454901fa506adfa9bb38ef9a7fa213"},{"path":"core/crates/auths-author/Cargo.toml","sha256":"1e6f0e3bc079ddb558decf0db26b291c6e72fc47327b6df1b7650d41689b215f"},{"path":"core/crates/auths-author/src/lib.rs","sha256":"e14475f2f49715a1869d5fa6b11ff1fbb72497e39097e09f833b0bae7e5b3f2b"},{"path":"core/crates/auths-author/src/observations.rs","sha256":"dda7d6bfa6f4bd7e95a480ca283c2c0e996f69c5c15cb0c7197af328131a7066"},{"path":"core/crates/auths-authority/Cargo.toml","sha256":"4f68212938029f79ebd857b4f3038494eb85d0163d49f07e51376715cf959815"},{"path":"core/crates/auths-authority/src/lib.rs","sha256":"da88d5194de4e17449e69972c0fb042afa3c39798a8f570f30771e77c384f1eb"},{"path":"core/crates/auths-codec/Cargo.toml","sha256":"e20e51826e17814effd9d8925d18d5fbdd6c0d37bf50231e743ec2611314722c"},{"path":"core/crates/auths-codec/src/approval.rs","sha256":"fbff43bf4d57f69f8b7738a8647751cde75c5a932dee65d924a1fe9c7202f91f"},{"path":"core/crates/auths-codec/src/bounded_policy.rs","sha256":"d21f6728be2d8a04b6d94921f2b683f7e61cbb42e0ac6866f1c88a49caa534c3"},{"path":"core/crates/auths-codec/src/decode.rs","sha256":"ba2999584cdf53b1b517ecb9c7ea50d39efee17c666a9a38e2ad1ac94379f778"},{"path":"core/crates/auths-codec/src/encode.rs","sha256":"8491192053e2e15d62b4d2a491de22405b7487ead69ab6f6bca40669ce7ca5f7"},{"path":"core/crates/auths-codec/src/error.rs","sha256":"fecb0737c16deb42d859f1dc7727c698438d9ac12064fd99e0024629642c390c"},{"path":"core/crates/auths-codec/src/hash.rs","sha256":"f88e111f1dbb2cef6b7b5e9c948cb45ff92e366710c8a5f5c636138aa748479e"},{"path":"core/crates/auths-codec/src/lib.rs","sha256":"3b0e5c94c6f34f750b88a9333e1d5c8145746d845d3a23e0d2f61807cf592ea7"},{"path":"core/crates/auths-codec/src/observation.rs","sha256":"38328b0c71ff97a4196eeade8b4faa889527ff1f80bb168468bcd49082a3987e"},{"path":"core/crates/auths-composition/Cargo.toml","sha256":"331e13025eb82588b5269ed3975929eb41c823d588c49e4c296273d85c6fe80e"},{"path":"core/crates/auths-composition/src/lib.rs","sha256":"e42e3b0b6a9985b73c533aeb23799c638979aa27a9ce7d0f10a8d60340570fb1"},{"path":"core/crates/auths-model/Cargo.toml","sha256":"565c15302b0cc9270db1e28efa3862804846850ba933cc17aea8abcec4a65987"},{"path":"core/crates/auths-model/src/approval.rs","sha256":"54cf44a9ef747ec21546a4086aecfb130bc7803b0d646430e6082df51e6e305f"},{"path":"core/crates/auths-model/src/bounded.rs","sha256":"f90496abc0a06c028b4d850af6ddab7d850bfafeaa3d042f1b1246a41d8bbbc9"},{"path":"core/crates/auths-model/src/bounded_policy.rs","sha256":"306a8f049cc7cfc7635fe0e4de47eb7813eed63d3c14c3be2b51586aa4eea450"},{"path":"core/crates/auths-model/src/lib.rs","sha256":"e7cfe6bb9574c6b016aa63e70658c31e0b90903ec6479a49f4a2ceb64f5bad97"},{"path":"core/crates/auths-model/src/observation.rs","sha256":"b3ed3e3cc090afca2896a7d3de7988afccc1ee1ea0ebd91b51a8bc0f20ad8dbb"},{"path":"core/crates/auths-multikey/Cargo.toml","sha256":"858756c1197befcada06134742bffe8d58cf674cadd6c046bf710570e96efaf2"},{"path":"core/crates/auths-multikey/src/lib.rs","sha256":"f5177fffb11e40eeaaa665ba886c541fc1f24d5eacdd6983fb03dc20148733f0"},{"path":"core/crates/auths-ports/Cargo.toml","sha256":"596a9b0f5af3717c16a6d13f7054d8a106bcd9f01f5f72c2235dd2afcf0ab16c"},{"path":"core/crates/auths-ports/src/binding.rs","sha256":"a16c012d40aa4249e3ec54372b9611006d0bfe8c7dc3c741911c2194ad17736d"},{"path":"core/crates/auths-ports/src/diagnostics.rs","sha256":"aa596572503b5a65a918bb2ff38281c144ff53821ee914e9325c852828d852df"},{"path":"core/crates/auths-ports/src/lib.rs","sha256":"8da1debf86f9532df0660155d04298beb1ba3a1204508f8586e2e67cd2fb3449"},{"path":"core/crates/auths-ports/src/path.rs","sha256":"b68fc547b4e4d97a60cbbc1cc1939fc6b34a8233b81f840bd396914a707e3ea1"},{"path":"core/crates/auths-raw-key-core/Cargo.toml","sha256":"98c0bc8527a537512e43a74dd6ba9658c6f0cdc16610cf938e3f9b43785d836d"},{"path":"core/crates/auths-raw-key-core/src/lib.rs","sha256":"98c0500c41697aae28708ad0bf970b9a97583d96a3d2c18d23e7fa351e0f7d12"},{"path":"core/crates/auths-registries/Cargo.toml","sha256":"590e49e58b0622d9d6274fea46796dcdb07dec9550eff295cce6a6427ffa51e2"},{"path":"core/crates/auths-registries/src/lib.rs","sha256":"450d3886d85ee333b7e046317fb5b47cde62483d5f3e41d46265e2caf4c373ec"},{"path":"core/crates/auths-registries/src/template.rs","sha256":"1224039dd2b3ce6fa8357613d8cafbae40400493da7176da202b9ade62fa05e4"},{"path":"core/crates/auths-signature-core/Cargo.toml","sha256":"6bee2230eb30af1be0bd5c2d57bd3e1903497a70028d47290d4ac6e9e0e8bca0"},{"path":"core/crates/auths-signature-core/src/lib.rs","sha256":"6e3f9311ded5e49ea50d445eb21e6d8fa12442aa4362a73e0cb6fda15b7cd865"},{"path":"core/crates/auths-signature/Cargo.toml","sha256":"7f7b5682466ba439d8c59579022cb61068cad9fb4bd2d73e1cc21327c902b450"},{"path":"core/crates/auths-signature/src/lib.rs","sha256":"b3d9ac4cc3ba0797b9e1c09f2d6ac05089b25dac4e285a5af28c0165b33d925b"},{"path":"core/crates/auths-verifier/Cargo.toml","sha256":"c43358e06a33324b41a8b93e5cc7279c55f7d21f1f6cfaa539a3fc7b4c27a38f"},{"path":"core/crates/auths-verifier/src/approval.rs","sha256":"c3cae6a49e169051eb555bb092b1069a4d422516d6a2114623a89e5f31ff923f"},{"path":"core/crates/auths-verifier/src/causal.rs","sha256":"9635230f33b13a263573d319ac8a1976addbcc07677514a43e3c7bf28dc04587"},{"path":"core/crates/auths-verifier/src/lib.rs","sha256":"f22dec38dfa47ced8da4f605390da8453273bee1da010f57fd1fdfcb10e0b389"},{"path":"core/crates/auths-verifier/src/observation.rs","sha256":"0bb07f06a0f9524c88427df1c972b1de8ba038a9eeeb15d3134c25125ae84b1e"},{"path":"core/crates/auths-verifier/src/trace.rs","sha256":"2213d72023a1d9e0413a2cf2c51c3dad9e04775d86033a0caaa9d29a8f0036f8"},{"path":"exchange/crates/auths-proof-exchange-model/Cargo.toml","sha256":"34b2db64f93a288e942b5a3918d28cdcbef906e0dc9074ce848018d3d5f7a1fa"},{"path":"exchange/crates/auths-proof-exchange-model/src/lib.rs","sha256":"49fac5aff2339d3a57c41cb8bb2a82852538e8f77ecc4b157c88e264ff31fb55"},{"path":"exchange/crates/auths-proof-exchange-port/Cargo.toml","sha256":"7ff660f1b7579dc570c791090aeb450404fbbf44c92781e289f5ccdde746d739"},{"path":"exchange/crates/auths-proof-exchange-port/src/lib.rs","sha256":"b408fb40c6432edc1facb3d8b3e9433a033f8dc73fe2e0ba5a88c972ca675021"},{"path":"product/config/auths-config/Cargo.toml","sha256":"e4b568ab9f6d84f7d7e6d66443fe825f360db9c27bc7c31d6ddc0647ba3ab304"},{"path":"product/config/auths-config/src/lib.rs","sha256":"fecf00ea65cef9018fda9af2063326d7065b869266d0d9e73a4f06816f1102cc"},{"path":"product/errors/auths-errors/Cargo.toml","sha256":"3b3a199b6460ba75bda84475bb5accd35e1485448a3981038db85bf4772dd350"},{"path":"product/errors/auths-errors/src/lib.rs","sha256":"7feeb9069fa4003f94f1f07c1c94619cf1c883e0dbaaf2187f04d0f742264bdd"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/Cargo.toml","sha256":"716f1f2a117d6d69d8effe9ee9057e24ba3502f20af6a602b06facb638cdabed"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/api.rs","sha256":"9ea61dd7ddd93282b073b98e453e6b75b26dc49689c04e9782435d06a3a09e48"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/clock.rs","sha256":"73f0a6e0f5903883329fa6683f5888288f759512ac69e5c87efd2b6b87f7d79f"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/http.rs","sha256":"14c1fce14e24c984b2a275563a29b6326fb08367922b6e8d37ba38b9cb81aa2b"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/identity.rs","sha256":"186de11230c8b33375951c4368609f8976bf9795f171af3fd7fac26207a94361"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/lib.rs","sha256":"0b4617d044f5254a5ab22f5a2578f91cc025206a8c1845be39c1c56dcdf7a5df"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/names.rs","sha256":"41bb23572d6002e23ee103d6fe70ecd68764861c6f2e48a1c53af998270a4afa"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/sigv4.rs","sha256":"39fed883f4802e68d3b41a68fea0aba0737810996b33d13577de70faba004c29"},{"path":"product/integrations/auths-credentials-aws-secrets-manager/src/store.rs","sha256":"fc60ee9c49b2f4f063c449b4c78100c5c4872779e94ca168f796603b380ef6e4"},{"path":"product/integrations/auths-custody/Cargo.toml","sha256":"1e14034185ad1ec24a977fd5f41d0abee219606245c046ce2a82287fadef448b"},{"path":"product/integrations/auths-custody/src/conformance.rs","sha256":"8ed1afd58f18fc6becc268908aa6419c9aa404c79da0197963eb2599df44acf6"},{"path":"product/integrations/auths-custody/src/key.rs","sha256":"70cbb0fd21b6f5652157845a22c35be2d0f6c05b3d138fc4b9bb6dbdc3d81c40"},{"path":"product/integrations/auths-custody/src/lib.rs","sha256":"8ee593c1f59b0fd2126bdda9138026f5bc531beb64d4489a99785842e7b98b43"},{"path":"product/operations/auths-operations/Cargo.toml","sha256":"73dde1e914ba5e1386f8d49c0d730423cc72ae77ec44c6554a6a75cc8e8922b1"},{"path":"product/operations/auths-operations/src/explanation.rs","sha256":"b4a39bcbd5712cb9e735ee7deeb281f3fa6af5ddca973735bf3d87dce427ef11"},{"path":"product/operations/auths-operations/src/lib.rs","sha256":"3f401a56555113b98f57bca172a2660eaecedf76247b83a3fdbb089c133a29cd"},{"path":"product/operations/auths-operations/src/render/json.rs","sha256":"2ae042639960afee123730e945d373bc5dda1d2b3af20ae16c939a7e99b9e418"},{"path":"product/operations/auths-operations/src/render/mod.rs","sha256":"b3b7f6fe473f49227ace5a68bfc3d8dc14b5db8dd9888fd9e207070337b1b8bf"},{"path":"product/operations/auths-operations/src/render/text.rs","sha256":"f216cf3bdb00e264523271b16e7059535ac6b1aabf271cebd7935af155e4bfec"},{"path":"product/policy/auths-bounded-policy/Cargo.toml","sha256":"babd5d200923137ead71d8c2528f847cea323ce98da942a1320b054436612c47"},{"path":"product/policy/auths-bounded-policy/src/arithmetic.rs","sha256":"75e43c5d4eab8d1f71c1daf53839f5f9fe45a400afc1f63a30c6f55ce3632627"},{"path":"product/policy/auths-bounded-policy/src/commitment.rs","sha256":"c5706f2d583454e1a7f570f7ada138d4d864bef0205dfae7c1296774f396bb3f"},{"path":"product/policy/auths-bounded-policy/src/eligibility.rs","sha256":"c9acdfb793074e687fc36efad506be27dbd99ffbf40387bc66c8de39ef238432"},{"path":"product/policy/auths-bounded-policy/src/identifier.rs","sha256":"0006a32bae9eb16c4178cf797df418d2b0a781f2bc6474b741dc1a908141831c"},{"path":"product/policy/auths-bounded-policy/src/kernel.rs","sha256":"99187c28b161ac70bee1afed60711f7f645adb4d1671a01863f9849b369811d5"},{"path":"product/policy/auths-bounded-policy/src/lib.rs","sha256":"76a18638b810e62e594d6e951504679305ce21841388e0c282ad51cd7841b91c"},{"path":"product/policy/auths-bounded-policy/src/receipt.rs","sha256":"3b9eae82f349956d3e7f29b57b254bff5ce67cc703e6cf43445ce2827676d1ad"},{"path":"product/policy/auths-bounded-policy/src/registry.rs","sha256":"4e251ea5833559841f8ee0bd9b66c0c01c39fa5e3a21720a19c4e8adbfcb99d0"},{"path":"product/profiles/auths-profile-api/Cargo.toml","sha256":"7ae85761f58625b5d678f961fd052eebf3e000ef565c7312e3ac857763c0017f"},{"path":"product/profiles/auths-profile-api/src/lib.rs","sha256":"a194b82b20bf8aa864c2334ef6c6aec30b2154ded972862252d5dcefa488ab95"},{"path":"product/profiles/auths-profile-mcp/Cargo.toml","sha256":"db264fc25242f7b7e4133cbe5782545b3107b406c87168ae072683cfb59eac66"},{"path":"product/profiles/auths-profile-mcp/src/arguments.rs","sha256":"a5de696586d507e2aee4a49fee99ef1ef4c51a2e46603f8838f1af6d9009833f"},{"path":"product/profiles/auths-profile-mcp/src/lib.rs","sha256":"d0f8b733a09ef8408336cdebc8948d6a5861012ce6878598b11be7084dfd4280"},{"path":"product/profiles/auths-profile-mcp/src/session.rs","sha256":"166c281fa66333388e4760d6098dad02d3359e1d5de4b8f93312c014f97abb03"},{"path":"product/qualification/auths-recipe-qualification/Cargo.toml","sha256":"b7b15b30b9a3d96d4f089d514266d3a892de6608d30707aa44be31cca89ca9fe"},{"path":"product/qualification/auths-recipe-qualification/src/canonical.rs","sha256":"30a9b50777f0dcb4b606abfee2467d5a975d9f6ad941ab6c13ca3df5b359f667"},{"path":"product/qualification/auths-recipe-qualification/src/closure.rs","sha256":"0ad6aee9bd981e2863fa725f209ec84031db2ff12f4c7ac3aaf5120f0bb86039"},{"path":"product/qualification/auths-recipe-qualification/src/commissioning.rs","sha256":"db135c55e4e3079a73253ebae275536523eb36b545d1c152b4d7dce3c6b76828"},{"path":"product/qualification/auths-recipe-qualification/src/commissioning/tests.rs","sha256":"4dde3736d206099b1bea4c14e0092c6c1287d1af9065958777d7c54331dd8686"},{"path":"product/qualification/auths-recipe-qualification/src/error.rs","sha256":"52d5cf720a1e4579008fdda90a3ac2c31f0b8db57985f121f65e54b4da2b7dd1"},{"path":"product/qualification/auths-recipe-qualification/src/evidence.rs","sha256":"ba45a7409d67a8af26ab811af306412014557477a101ab2a8eb0faf8f2bd4b91"},{"path":"product/qualification/auths-recipe-qualification/src/ids.rs","sha256":"e81a906d571497ab2da753e1532d4443706410e0b75fdd59a7d2d788c7aec403"},{"path":"product/qualification/auths-recipe-qualification/src/launch.rs","sha256":"805154ce931e3977f2a2a2c62909d90f7c0a22dc167bf4f1554dcf19316ffef8"},{"path":"product/qualification/auths-recipe-qualification/src/lib.rs","sha256":"0e24b0f81191df0d078c7f4d73ced784ba9472372bfcdff3c7d0e2fb1687b323"},{"path":"product/qualification/auths-recipe-qualification/src/model.rs","sha256":"3484eb0ec287b23d4682ade7b1b0f8d1335985b3fb180f06fc28716076957d5f"},{"path":"product/qualification/auths-recipe-qualification/src/release.rs","sha256":"ec478e53f70052e566aac7e15be2f9e1b1cd46837ac6990ae955fa864d311586"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/mod.rs","sha256":"fa23a962fd90331152eed5edbcdf271955f7aed79b8da1e065bfe69a20b487a9"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/schemas.rs","sha256":"c59feec2805621f341a90f81fc005e2c12f7a70f9d264fdeacccb2be4fe1c046"},{"path":"product/qualification/auths-recipe-qualification/src/vectors/verification.rs","sha256":"bdf5746fed4d10a7f577f7878619a917d29aa8b7d522f00d9f774e53eff4c8c1"},{"path":"product/qualification/auths-recipe-qualification/src/verify.rs","sha256":"646ff0e52e915174ad183768706e35e5ce2118b83475455310b930a77a7877f6"},{"path":"product/receipts/auths-receipts/Cargo.toml","sha256":"6001fa1375899953aafcb07c23a6da0c8f57ea7ec08bb9c950b12a60a8cc6f0f"},{"path":"product/receipts/auths-receipts/src/disclosure.rs","sha256":"ba9ed439be0a320c8a01f5b6e9b51361c1a37e076947490d8e4a484ba6bb119c"},{"path":"product/receipts/auths-receipts/src/lib.rs","sha256":"547a57c4160256719cafb7d0ab972d9fc80b0da14fbbce4148c70c414070ff36"},{"path":"product/runtime/auths-connections/Cargo.toml","sha256":"babeb6e1dda3dfb66291713ce1e43dce5c349833d0b50ea4dccbf986030026b2"},{"path":"product/runtime/auths-connections/src/credential.rs","sha256":"82921413bb053f0f6c7931fbd4e6a86c8cc1d8c6b51debd9c2cef33a8d5b1c51"},{"path":"product/runtime/auths-connections/src/kernel.rs","sha256":"a456af19526ef7b19278551fd8d97606b6e7aa5a195e70bdd85d1e0786090ce8"},{"path":"product/runtime/auths-connections/src/lib.rs","sha256":"79209249a0acba0e854d9937255ea0e30a9a6f8e1c2baad77ab83646d392de22"},{"path":"product/runtime/auths-connections/src/model.rs","sha256":"de34a089cac9702acb889b7602b3e4732306c9e61029ec892582b7e02b73fc77"},{"path":"product/runtime/auths-connections/src/registry.rs","sha256":"e57640e003e72ad3235c567c2bb944a262bd64e673f023b62ea091094cc7e946"},{"path":"product/runtime/auths-gateway-kernel/Cargo.toml","sha256":"34f864e67656af4ac7e5c7a347a23f01fc8ab31365b8e23c0ef474483b14a183"},{"path":"product/runtime/auths-gateway-kernel/src/construct.rs","sha256":"e9d65744bae273d65face4285e5d2da75c06a92ab48f7b8333d496604e31c63c"},{"path":"product/runtime/auths-gateway-kernel/src/lib.rs","sha256":"cfda6f8453426564c085475f183b6f790b438768a19668f1b65d33ba59dc8632"},{"path":"product/runtime/auths-gateway-kernel/src/order.rs","sha256":"e0045f877c4b7fe3860c291039853885064ddcdebba7c9b345ab65e81e646dda"},{"path":"product/runtime/auths-gateway-kernel/src/outcome.rs","sha256":"e9785b1afe70788c89b51b18655bcd5acff7b0c8e3d12fb79c6f05a202e67e6b"},{"path":"product/runtime/auths-gateway-kernel/src/ratio.rs","sha256":"7ace22264812e6fc1ef3a62afee402cf43494bb71ae0d3de219ad1b39d690bcb"},{"path":"product/runtime/auths-gateway-kernel/src/recovery.rs","sha256":"9f46dcd1685ab6e4d1ba04a3fc286a9f3afee8fb47829be1fbc670a7926a2dc6"},{"path":"product/runtime/auths-gateway-kernel/src/transition.rs","sha256":"cefb8f01d915880f6921f2501ff881ad94b9de61072c34d9cd19220992f97374"},{"path":"product/runtime/auths-gateway/Cargo.toml","sha256":"00b28be86921dcdc0ad90cce0c62c2961cafefe96ea6c2edf0e926c3d405ccad"},{"path":"product/runtime/auths-gateway/src/admin.rs","sha256":"0dee40a9fb67c5de10142fc37a7bbabdd8979fb0199fb26caf4bdb024e0a5a40"},{"path":"product/runtime/auths-gateway/src/app.rs","sha256":"6f80f63833ea0815bb44fbf3b0cc54624a08e9fb578b035819f2980dc04e8256"},{"path":"product/runtime/auths-gateway/src/audit.rs","sha256":"0edb2037eb7b5d6f13acfce85c54f62a82bf7fdd31bc7e626c4fec183cef61dd"},{"path":"product/runtime/auths-gateway/src/audit_tests.rs","sha256":"990969384a52d75bc2489d9d412a9e7dd814bca1c8f65c701d6205fae62a15d5"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway-harness.rs","sha256":"12b0c24d36b2e6a3be392d3c081a783b355fdd67dc5b54bacc0410e803116b8c"},{"path":"product/runtime/auths-gateway/src/bin/auths-gateway.rs","sha256":"3dba485deeb4d60f3f5603ad4ce9a0edf49a85c68c5c4ca072df73d2910da832"},{"path":"product/runtime/auths-gateway/src/binding.rs","sha256":"663b0ce878319511aa7d05722ab4ab2fa9be18817884ffb2ee9f131ff1e382d1"},{"path":"product/runtime/auths-gateway/src/bounds.rs","sha256":"38251ad6f22f9d07ef9a219c79fa265ca36f1526eca5f147d7efa46b52ad609d"},{"path":"product/runtime/auths-gateway/src/bounds_aggregate_tests.rs","sha256":"ab34f227b7c8692ba1da88ccb32bb3687a66adf8353d8282fae905d4a88eb612"},{"path":"product/runtime/auths-gateway/src/bounds_tests.rs","sha256":"74136bc570da7b9338b5a1a1ed9d3fd892c55135160964f9d3ac0e2cf5741375"},{"path":"product/runtime/auths-gateway/src/commissioning_budget.rs","sha256":"fab29da3269438cc62330f3eab7b5bd4dc482b4db8af243aae47df5d3aa1deb8"},{"path":"product/runtime/auths-gateway/src/commissioning_budget/tests.rs","sha256":"da104a1643c37515deec6397bca6db2054f2c9158ec3d230a1b1ec9c7d0f659f"},{"path":"product/runtime/auths-gateway/src/commissioning_floor.rs","sha256":"7fa6991c5ccd5ae1403be84b3da390323fab09f36e15ac01fd7a38ea350c6fdb"},{"path":"product/runtime/auths-gateway/src/commissioning_floor/tests.rs","sha256":"6b663d6e556adc0b455b81845bc4394d82c6c4de0c5f43e1310f3ddc6e4e40f7"},{"path":"product/runtime/auths-gateway/src/commissioning_session.rs","sha256":"24b48d5eaeaaa3c620e2dfc7ee1f9255fc4519a1eb404b8608cea7af6a910ee2"},{"path":"product/runtime/auths-gateway/src/commissioning_session/tests.rs","sha256":"37a097fc8a9261d3fffdaef3f905f40b22e3e6601bb5101fadd9414f963c0824"},{"path":"product/runtime/auths-gateway/src/connection.rs","sha256":"e8d24277d7e4a53610e091fe78b373b841245d8e59a2bc788716b76e7d912441"},{"path":"product/runtime/auths-gateway/src/credential_journal.rs","sha256":"7297fccaee5cd8622928e8e0a42bba50da7941970a6f682ecd300c41ee6509da"},{"path":"product/runtime/auths-gateway/src/echo_verify.rs","sha256":"6d453051665f823abd7354d5c50031d9524cf47d6092d2f09080ae814e3b9575"},{"path":"product/runtime/auths-gateway/src/engine.rs","sha256":"692ff372ffab10f27fcc45b7aa28457ca3fd6f9ca0ca06212f20f34c4431b491"},{"path":"product/runtime/auths-gateway/src/execution_witness.rs","sha256":"e8b1a8e41d5e3fa309760067849d390ef065feeb46701a83391832645a2f000c"},{"path":"product/runtime/auths-gateway/src/fuzzing.rs","sha256":"ed3b0028487eb546a3b0a91d115aa8f18bcea324b61620bfe8e35a9e6ab18758"},{"path":"product/runtime/auths-gateway/src/generation_floor.rs","sha256":"fe1510ec96ce0f67e9a78edbfa94b33eb7df64c0ac4d0a67901124dcd0164777"},{"path":"product/runtime/auths-gateway/src/harness.rs","sha256":"c87e479f3eb281960f6c9c80d43c7560d7ccb654b0154ec823d3fcec4884ac05"},{"path":"product/runtime/auths-gateway/src/lib.rs","sha256":"fad95d031f88072dd024c78facf0bb0267562b1ac743ddd7219fce47e64024f0"},{"path":"product/runtime/auths-gateway/src/listener.rs","sha256":"aa08239bcbc1fcb55e8a212fbdf6a84f12985b0d436dcb51dc58b06e59e435f2"},{"path":"product/runtime/auths-gateway/src/observed_tests.rs","sha256":"a22be071695f89ca2578a4d82fd80d9cb82289213c9bdb8f0470f6b2dc3d9201"},{"path":"product/runtime/auths-gateway/src/observer.rs","sha256":"562ffcaea071c3856e0708dc2fe33516917e145d2438aabb75af0a2b6ba01046"},{"path":"product/runtime/auths-gateway/src/onboarding.rs","sha256":"0dfd7d67e7f02f18a28d1c86ca1b7751d7463f5efcdbe3825de0ad8cbccb3891"},{"path":"product/runtime/auths-gateway/src/operator.rs","sha256":"c3c36954a3e86723df035b47f43b85fc8ab3a6292983522b6258d5c6b4e6c4e4"},{"path":"product/runtime/auths-gateway/src/pending_vectors/attempts.rs","sha256":"47ef3c8cb1c5504d47ae9a0088705ce6715fe86bac1671a34a56fb38a64d0dd3"},{"path":"product/runtime/auths-gateway/src/pending_vectors/bounds.rs","sha256":"e612217307e1da5b0eb5ee6582a7458bb064b8aa8a529fc6555b1b334127ab68"},{"path":"product/runtime/auths-gateway/src/pending_vectors/codes.rs","sha256":"e00670a5ef24eb856cc2c6dcda8e5a263842f55c76bb939c0c27bd9df37e5522"},{"path":"product/runtime/auths-gateway/src/pending_vectors/keys.rs","sha256":"f84c56f2ea9cb34b2b79c72d13fbf2c6585010ec1ed450af58a78c80c1ea1edd"},{"path":"product/runtime/auths-gateway/src/pending_vectors/mod.rs","sha256":"5de8340f0ef71a0b57a09e323fefe473d3160c6ae952b9ba46f714825fbacafc"},{"path":"product/runtime/auths-gateway/src/pending_vectors/outcomes.rs","sha256":"8ec07b9511b48913af36ac999d2aa0e82924289f6acb23ddaeb9f00f99815166"},{"path":"product/runtime/auths-gateway/src/pending_vectors/production.rs","sha256":"772d032e0a0d9c924fb6d6c188528db85a97e71c9e466ddc19eee277baf83614"},{"path":"product/runtime/auths-gateway/src/pending_vectors/recipes.rs","sha256":"51693208270231c25c3aef2a32151d5962114c71e86b88cb9df83181c7af83d9"},{"path":"product/runtime/auths-gateway/src/pre_entry.rs","sha256":"06ea78ca140468bfaba17d9ab04912ad68673954c3203c98fed28272ff2a00c0"},{"path":"product/runtime/auths-gateway/src/property_tests.rs","sha256":"939c081e2e154aaf10186754044bdd65608932c899b970a04a71d0afaa999a93"},{"path":"product/runtime/auths-gateway/src/qualification.rs","sha256":"c597c83de2b94f0374ae54e40a8b57c2a64ec6e254704dca32185f448a908aca"},{"path":"product/runtime/auths-gateway/src/qualification_simulation.rs","sha256":"4ee7cadfb5f46a92713c80f3e55f499cb074d04d8b21ea89d57762af38642bfa"},{"path":"product/runtime/auths-gateway/src/qualification_tests.rs","sha256":"a9178a2e58eea459d5e5dafc53a3999ea7c84dbbffefe6e5eb1f3d098827f028"},{"path":"product/runtime/auths-gateway/src/quorum_tests.rs","sha256":"a78380b019104d688c11a4410082c7e08ded3106aab099954c4f8a1b4ae0fd89"},{"path":"product/runtime/auths-gateway/src/readiness.rs","sha256":"911c3f11892f94641574375e2da4c671c802738f71082f12c39832331052d43d"},{"path":"product/runtime/auths-gateway/src/recipe.rs","sha256":"fecf9af67e7afc48d080e9f8f55f8ce28e49d0e08988717a27908bbda461d6b6"},{"path":"product/runtime/auths-gateway/src/recipe/lower.rs","sha256":"8088b8751ed831dbb48247af953c6290ac95e2a438ccd5bd65eff54be06a1fd1"},{"path":"product/runtime/auths-gateway/src/recipe/review.rs","sha256":"c3eb7d9fdd98dacf52750b14b67ad7b7faaecbbdeafff1e0b049f67d0a2d0139"},{"path":"product/runtime/auths-gateway/src/recipe/runtime.rs","sha256":"c286f0d15f974402822c0810d8e97f98411dc1c557755cc23e540d85e2bb42d9"},{"path":"product/runtime/auths-gateway/src/recipe/source.rs","sha256":"1af50298fb1461e1b24cbdf560d43124d6b1c4c529586c911b1c4797214a69ff"},{"path":"product/runtime/auths-gateway/src/recipe/tests.rs","sha256":"aac551a2481bbc60864c64079bc667dcb232e45a0f41a04073ed84ab5dbe1fce"},{"path":"product/runtime/auths-gateway/src/recipe/validate.rs","sha256":"3711b17605cb7b0d639bc1b180449231f5882a306cab20e2c7782155cc63b0d4"},{"path":"product/runtime/auths-gateway/src/scenario_tests.rs","sha256":"025b53473b3af6900e03bc2fee91aa63ed26a8778bc8c8296fe08f5540794c39"},{"path":"product/runtime/auths-gateway/src/separation.rs","sha256":"be9306848ca5d801767cf6aa14247c8618312ef0e202f00ce0c24c4844491061"},{"path":"product/runtime/auths-gateway/src/simulation_attestation.rs","sha256":"88705e5d45415f760f1e3c3a065c35c48f4f4065bf7b3feb7882246983814d6f"},{"path":"product/runtime/auths-gateway/src/store.rs","sha256":"884bcad4d70d53e12eae9c8517f6ecd0643068ee0be0370015119d04d6cc2516"},{"path":"product/runtime/auths-gateway/src/store_testkit.rs","sha256":"88d82fee42f1b8ef521e8deef0216e938ebeaad822eb2f5020e70b89d145ea70"},{"path":"product/runtime/auths-gateway/src/submit.rs","sha256":"fe2eacb5ad8152eeecbd232c47a356fc72db0098e34fda99532bdf6ef0cf895c"},{"path":"product/runtime/auths-gateway/src/support.rs","sha256":"9fd979029793a22b15d9776a7fc172476fd7c126a80d4080c65d720845becbcb"},{"path":"product/runtime/auths-gateway/src/transport.rs","sha256":"978fc9fb34a33b3db265b5d1c3ce11696a5b9f08529e46dd2a1e7bb62afb9220"},{"path":"product/runtime/auths-kernel-runtime/Cargo.toml","sha256":"926bcd0053e5edd703be8f0027ad009e2982db013c8174c1366edbf38b48087d"},{"path":"product/runtime/auths-kernel-runtime/src/lib.rs","sha256":"7108faae9ca4bc32dc093ddaf885ac8f74f3c9b8d317b7c7d0ed00d1d0ab5972"},{"path":"product/runtime/auths-lifecycle/Cargo.toml","sha256":"c5053c705f8d5554b44e432fe75287a2faf11d644e5a2552e45ad6cd94176af5"},{"path":"product/runtime/auths-lifecycle/src/codec.rs","sha256":"51c4b746749150e8bfcd8ff972b3f6c1ef40bec15583448ec1b471d9ad737dc0"},{"path":"product/runtime/auths-lifecycle/src/digest.rs","sha256":"55282cd7d8aba37713c2dcb5357c9877819edb72a30eadefb860d28d7d3a3eb7"},{"path":"product/runtime/auths-lifecycle/src/identifier.rs","sha256":"31620e8c16de68d3d2d3b84d6353c1a5b9d4151d8247f91fa389b906a8e660f1"},{"path":"product/runtime/auths-lifecycle/src/kernel.rs","sha256":"2abb8c094b36d35b364e74d78091d14c5d6f3d1eb6552cca3b5538dbd017ce23"},{"path":"product/runtime/auths-lifecycle/src/lib.rs","sha256":"afe5a345cd309b5a4f08ffba3170a6d7f16ff914892b3f2006d5208ed24ec736"},{"path":"product/runtime/auths-lifecycle/src/model.rs","sha256":"1af12bbeeeaa65ec02ddcebd7d2c8c92ec1e339fa40ae85b45ab9b01a722a4fa"},{"path":"product/runtime/auths-lifecycle/src/operation.rs","sha256":"78e6d05fcf5d7ea4f148032a3fa26fdfcab77eb346019effe927b08e0d64d732"},{"path":"product/runtime/auths-lifecycle/src/registry.rs","sha256":"53495fe6f7a77422593a41623e28716f1c140dcc1e00f87f6b0ffbfb93a5ef90"},{"path":"product/runtime/auths-lifecycle/src/sealed.rs","sha256":"2e0c03b5813c926c159598bb7890d1523825edbe57cd687d42a5dfb3374a0c19"},{"path":"product/runtime/auths-lifecycle/src/test_support.rs","sha256":"221d9a5c5ef8e1f9f8fd66927484eaf813571d0568470278ecd8fa08a5eec8cd"},{"path":"product/runtime/auths-lifecycle/src/transition.rs","sha256":"011805a28efdd541f44ccea54dd0e34a1e58f4004447ee58013703b4fb6b2822"},{"path":"product/runtime/auths-runtime/Cargo.toml","sha256":"dd29d80a8b4bb56c869f036a6c9998f6e6d1c0383ac5dc03fa42b24abe2a7ff7"},{"path":"product/runtime/auths-runtime/src/lib.rs","sha256":"132ca03d58c14905d3a822a4972f42a22a5ad33a45f2ba9ca44f3a57d810b4b0"},{"path":"product/runtime/auths-runtime/src/production.rs","sha256":"fd4eff4270c571c10fcff6cf27df28961ebf074de8a1a028f500fda1ca376820"},{"path":"product/sdk/auths-approval-quorum/Cargo.toml","sha256":"df904971fca87a24194c5816738a331588fe8f164acb5d70839a35dca5f57114"},{"path":"product/sdk/auths-approval-quorum/src/lib.rs","sha256":"72e4086088a1c0912e4e1a9e980f26a5c280bf5ab16ea39c9f0f58d5096ac2ce"},{"path":"product/sdk/auths-approval-quorum/src/remote.rs","sha256":"9fa029c7c63003adf260f8aec55160c545681c60c1bace0d934e7525862aac7b"},{"path":"product/sdk/auths-approval-quorum/src/remote_tests.rs","sha256":"8a09ce17cfee82a035a74edd535f3ebeb3db0e078784740d3997b17dbdb10197"},{"path":"product/sdk/auths-approval-quorum/src/tests.rs","sha256":"0acbf12be3e497dcc6c2d8f29c9af3b1a7ed8e11b75f6399570d4f217a785060"},{"path":"product/stores/auths-stores/Cargo.toml","sha256":"a32c4b76d17b264be5d40d24497ff237e1ed87822e8bab86229b3db93106dbe3"},{"path":"product/stores/auths-stores/src/gateway_attempt.rs","sha256":"218841602d3d9b23b44625f50e5b54cf275ccedc2d5c89f02d2482b8524472af"},{"path":"product/stores/auths-stores/src/lib.rs","sha256":"e721262edf8a9ab5568ddc27639176312d4a366203b5f73e2d7c11fde2c554e9"},{"path":"product/stores/auths-stores/src/lifecycle.rs","sha256":"3f2cecfda13fdcd7c4a944518646bcc8abd1237f900c0332d5822281f8f9f1cd"}],"schema":"auths.gateway-semantic-closure/1"} \ No newline at end of file diff --git a/product/runtime/auths-gateway/src/engine.rs b/product/runtime/auths-gateway/src/engine.rs index 1117bb224..3d0370443 100644 --- a/product/runtime/auths-gateway/src/engine.rs +++ b/product/runtime/auths-gateway/src/engine.rs @@ -2355,7 +2355,8 @@ pub(crate) mod tests { let host = &mut installation.first; let record = host.record().await; let directory = tempfile::tempdir().expect("private cleanup root"); - private_directory(directory.path()); + std::fs::set_permissions(directory.path(), std::fs::Permissions::from_mode(0o700)) + .expect("private cleanup mode"); let journal = crate::CredentialJournal::new(directory.path().to_path_buf()); journal.initialize(record.connection_id()).expect("journal"); journal diff --git a/product/runtime/auths-gateway/src/semantic_closure.rs b/product/runtime/auths-gateway/src/semantic_closure.rs index c6055da6f..d78159007 100644 --- a/product/runtime/auths-gateway/src/semantic_closure.rs +++ b/product/runtime/auths-gateway/src/semantic_closure.rs @@ -10,7 +10,7 @@ /// SHA-256 of the schema, a NUL byte, and `semantic-closure.json`. /// Regenerate through `semantic_closure_is_current` with `AUTHS_UPDATE_FIXTURES=1`. pub const GATEWAY_SEMANTIC_CLOSURE_SHA256: &str = - "882b7d420db79dadd3ca735b4391d072f82adc8ee8d289f705259b6548fef4de"; + "5de8b12ec7c774cb49f8292b350c7ebe9f294a7f565cd311b2ca5c748db9ea64"; #[cfg(test)] mod tests {