diff --git a/.github/agent-policy-channels.json b/.github/agent-policy-channels.json index 7807366..7165e0a 100644 --- a/.github/agent-policy-channels.json +++ b/.github/agent-policy-channels.json @@ -1,29 +1,26 @@ { - "assignments": { - "R_kgDOQ09NVg": "candidate", - "R_kgDOQDruXg": "candidate" - }, + "assignments": {}, "channels": { - "candidate": { - "artifact": "ghcr.io/happyvertical/agent-policy@sha256:a19abb221522c3fe6a8acc9fe07e57cd1f1da08e17aa7d8a57faa8d8966d4511", - "generation": 21, - "policy_revision": "1.0.0", - "schema": "hv-agent-policy-lock:v1", - "source_commit": "a61f995c3458cc2e18b3143f4dd163608810da40", - "source_tree_sha256": "d71e22bb60bb8b1c7881f5ef0a3f879e528d2c15e3b35ddce483d57d80accf05" - }, - "stable": { + "rollback": { "artifact": "ghcr.io/happyvertical/agent-policy@sha256:69cc70871f1007ae1e8fa7dc0ec525de55417aded59c82d7babb6d93696ad896", "generation": 17, "policy_revision": "1.0.0", "schema": "hv-agent-policy-lock:v1", "source_commit": "b7b490438947f313ba5ca246739ce3a9292dcec0", "source_tree_sha256": "f137f5a684f4b48edb441d8cef721a1feab73a10e442501652a3ee31736af270" + }, + "stable": { + "artifact": "ghcr.io/happyvertical/agent-policy@sha256:a19abb221522c3fe6a8acc9fe07e57cd1f1da08e17aa7d8a57faa8d8966d4511", + "generation": 21, + "policy_revision": "1.0.0", + "schema": "hv-agent-policy-lock:v1", + "source_commit": "a61f995c3458cc2e18b3143f4dd163608810da40", + "source_tree_sha256": "d71e22bb60bb8b1c7881f5ef0a3f879e528d2c15e3b35ddce483d57d80accf05" } }, "default_channel": "stable", "promotion": { - "canary_evidence_sha256": null, + "canary_evidence_sha256": "ff947d36258d3b26de455a5d8b0701a5c7d174df8bdb733da17d0252d1cd0ab1", "canary_repository_ids": [ "R_kgDOQ09NVg", "R_kgDOQDruXg" @@ -36,7 +33,7 @@ "source_commit": "a61f995c3458cc2e18b3143f4dd163608810da40", "source_tree_sha256": "d71e22bb60bb8b1c7881f5ef0a3f879e528d2c15e3b35ddce483d57d80accf05" }, - "phase": "canary", + "phase": "smoke", "previous_stable": { "artifact": "ghcr.io/happyvertical/agent-policy@sha256:69cc70871f1007ae1e8fa7dc0ec525de55417aded59c82d7babb6d93696ad896", "generation": 17, @@ -53,14 +50,14 @@ "R_kgDOQmZFRQ" ] }, - "revision": 23, + "revision": 24, "schema": "hv-agent-policy-channels:v1", "transition": { - "action": "prepare", + "action": "promote", "artifact": "ghcr.io/happyvertical/agent-policy@sha256:a19abb221522c3fe6a8acc9fe07e57cd1f1da08e17aa7d8a57faa8d8966d4511", - "evidence_sha256": null, - "from_revision": 22, + "evidence_sha256": "ff947d36258d3b26de455a5d8b0701a5c7d174df8bdb733da17d0252d1cd0ab1", + "from_revision": 23, "previous_artifact": "ghcr.io/happyvertical/agent-policy@sha256:69cc70871f1007ae1e8fa7dc0ec525de55417aded59c82d7babb6d93696ad896", - "to_revision": 23 + "to_revision": 24 } } diff --git a/.github/agent-policy-evidence/revision-24.bundle b/.github/agent-policy-evidence/revision-24.bundle new file mode 100644 index 0000000..7766408 --- /dev/null +++ b/.github/agent-policy-evidence/revision-24.bundle @@ -0,0 +1 @@ +{"mediaType":"application/vnd.dev.sigstore.bundle.v0.3+json", "verificationMaterial":{"certificate":{"rawBytes":"MIIHVDCCBtqgAwIBAgIUSFEjXGvpHnWVCPNSHLjpEu1GAEowCgYIKoZIzj0EAwMwNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwHhcNMjYwNzMwMDU1ODU3WhcNMjYwNzMwMDYwODU3WjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE+cHHyleeoSqecicb1BWDl2oP10iDTNiLvh/jYAUy4bY10/eRgmQfMkeXcKyfttHoH08BJLHQLHtJqqf6Qs4nyaOCBfkwggX1MA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUOvfYEoPG4wYQqg6BZAcKLx8zlQwwHwYDVR0jBBgwFoAU39Ppz1YkEZb5qNjpKFWixi4YZD8wcQYDVR0RAQH/BGcwZYZjaHR0cHM6Ly9naXRodWIuY29tL2hhcHB5dmVydGljYWwvLmdpdGh1Yi8uZ2l0aHViL3dvcmtmbG93cy9hZ2VudC1wb2xpY3ktcm9sbG91dC55bWxAcmVmcy9oZWFkcy9tYWluMDkGCisGAQQBg78wAQEEK2h0dHBzOi8vdG9rZW4uYWN0aW9ucy5naXRodWJ1c2VyY29udGVudC5jb20wIQYKKwYBBAGDvzABAgQTcmVwb3NpdG9yeV9kaXNwYXRjaDA2BgorBgEEAYO/MAEDBChhNjEzYTg1ZTI3MTNmOTY2YjdlMTQ5MWRiYTEyYmQ4MTM3MjQ3OTJkMCIGCisGAQQBg78wAQQEFEFnZW50IFBvbGljeSBSb2xsb3V0MCMGCisGAQQBg78wAQUEFWhhcHB5dmVydGljYWwvLmdpdGh1YjAdBgorBgEEAYO/MAEGBA9yZWZzL2hlYWRzL21haW4wOwYKKwYBBAGDvzABCAQtDCtodHRwczovL3Rva2VuLmFjdGlvbnMuZ2l0aHVidXNlcmNvbnRlbnQuY29tMHMGCisGAQQBg78wAQkEZQxjaHR0cHM6Ly9naXRodWIuY29tL2hhcHB5dmVydGljYWwvLmdpdGh1Yi8uZ2l0aHViL3dvcmtmbG93cy9hZ2VudC1wb2xpY3ktcm9sbG91dC55bWxAcmVmcy9oZWFkcy9tYWluMDgGCisGAQQBg78wAQoEKgwoYTYxM2E4NWUyNzEzZjk2NmI3ZTE0OTFkYmExMmJkODEzNzI0NzkyZDAdBgorBgEEAYO/MAELBA8MDWdpdGh1Yi1ob3N0ZWQwOAYKKwYBBAGDvzABDAQqDChodHRwczovL2dpdGh1Yi5jb20vaGFwcHl2ZXJ0aWNhbC8uZ2l0aHViMDgGCisGAQQBg78wAQ0EKgwoYTYxM2E4NWUyNzEzZjk2NmI3ZTE0OTFkYmExMmJkODEzNzI0NzkyZDAfBgorBgEEAYO/MAEOBBEMD3JlZnMvaGVhZHMvbWFpbjAaBgorBgEEAYO/MAEPBAwMCjExMjkyNzA2MTQwMAYKKwYBBAGDvzABEAQiDCBodHRwczovL2dpdGh1Yi5jb20vaGFwcHl2ZXJ0aWNhbDAZBgorBgEEAYO/MAERBAsMCTEzMTQ4MDczNDBzBgorBgEEAYO/MAESBGUMY2h0dHBzOi8vZ2l0aHViLmNvbS9oYXBweXZlcnRpY2FsLy5naXRodWIvLmdpdGh1Yi93b3JrZmxvd3MvYWdlbnQtcG9saWN5LXJvbGxvdXQueW1sQHJlZnMvaGVhZHMvbWFpbjA4BgorBgEEAYO/MAETBCoMKGE2MTNhODVlMjcxM2Y5NjZiN2UxNDkxZGJhMTJiZDgxMzcyNDc5MmQwIwYKKwYBBAGDvzABFAQVDBNyZXBvc2l0b3J5X2Rpc3BhdGNoMFwGCisGAQQBg78wARUETgxMaHR0cHM6Ly9naXRodWIuY29tL2hhcHB5dmVydGljYWwvLmdpdGh1Yi9hY3Rpb25zL3J1bnMvMzA1MTgxMzAzOTEvYXR0ZW1wdHMvMTAWBgorBgEEAYO/MAEWBAgMBnB1YmxpYzA+BgorBgEEAYO/MAEYBDAMLnJlcG86aGFwcHl2ZXJ0aWNhbC8uZ2l0aHViOnJlZjpyZWZzL2hlYWRzL21haW4wgYkGCisGAQQB1nkCBAIEewR5AHcAdQDdPTBqxscRMmMZHhyZZzcCokpeuN48rf+HinKALynujgAAAZ+xmsRQAAAEAwBGMEQCIEAcoKZWOOmthnpTgauCJbYJdEMk7rPUG3sW+Qrhwb+RAiBMlzZXRX2AfdvFFGuOQ2WssuY5OpGhBx4CYENkPTwyWTAKBggqhkjOPQQDAwNoADBlAjEA1O5S2HFXoLl24ezfuQJNcEc4oqkYdLvabl3oS2uU4T52DnOIf3KivJxFrMMCNGMYAjB6o5K5SNub8nxM7qack5yflWGoSi0Aq/GcXSSzXnhJKqF0kieZ19gicmDlkHCgxyE="}, "tlogEntries":[{"logIndex":"2287488315", "logId":{"keyId":"wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0="}, "kindVersion":{"kind":"hashedrekord", "version":"0.0.1"}, "integratedTime":"1785391138", "inclusionPromise":{"signedEntryTimestamp":"MEQCIGysBwGDSX4yUNa+d4/pcWf5NI4dPRiaIjtWECDp7WAQAiAkGsT/ivogs1QOIyQ8qb+8RlshhZ2A00ZcuhFMLp/w1A=="}, "inclusionProof":{"logIndex":"2165584053", "rootHash":"HarnvlaeliQUIenIrxPbODs+x3ob28n7p2y03iEWWc8=", "treeSize":"2165584105", "hashes":["OkpSB621BKasMudVbJ8uF7Mw/4MwkTqkgCWXV/eiq34=", "FHMwnjBqKwfoamRxpwWj6I13i5kW1vBtW7YMrWv8w3E=", "wuOmptkOXV1XQZRkHOd6lWMW34kbhw2UCVI73U7/4fs=", "NuSIWFz1RRyVy8DTCxZLht5sGgFzQWiAsMhLMnvGao8=", "K+ocGIecTq4iUEweVxg2JSHd5xqB2l08I4Kw1sojpGU=", "UTemHfwdLWoaNEm0VSU2MyokWIrybNV8cxh5YLBhNU4=", "V1WxIXTtyoLxXUZppqAKNT1P3vAxc83fxDvqzQ7rS+0=", "Mg4eBsw+q8CIE7Rv7aIVkVnSl/ae6OjgOyExrVowVVA=", "8piH476tcydBUaHgUCjXaUh67QcR5zPSHuOC4c6pFRc=", "wn8/zMlVIF2EPSl974UWJVgY4BXI53Sv9pOa9vjiPRw=", "+l4CEQOcyTYHlwfkHEyoZhrbUF+VQ7Uor53ATNpGRFk=", "BqJoKSe0eoxHcBb4zAPUdVxdJwxYnVn2dyKLT284wEk=", "gFCDLuUICPUD+cTxcpdc20bh3Ddh2oUrPn7Cy0NnyoE=", "xH/DCseLHr9eKoYT8qsORZK7zVdEGYWHuVtsVrD95wY="], "checkpoint":{"envelope":"rekor.sigstore.dev - 1193050959916656506\n2165584105\nHarnvlaeliQUIenIrxPbODs+x3ob28n7p2y03iEWWc8=\n\n— rekor.sigstore.dev wNI9ajBFAiEAmcGh1hXBjIuQF8xyMed8rcMk2As0WH2nECSmih3oR74CIHjaplhAlQ2nLRroroUW0jXQSMD7MsXJ+Z9Z/k3AIVkV\n"}}, "canonicalizedBody":"eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiI3M2U2NjBmYzhhNTg1MGIwMzU1MDZmMWY4NGEyN2RiZmI3MWJlNWRiYzJiODBlZWZhNzRhM2E5YmU5NzNlODA2In19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FWUNJUUNiS2dsZFI2aml2RFoyalZBZUpzTnRCeTBmMEEvd05DUGRLQTgrdDJrVURBSWhBTW0wTjVwZjBVa2JCRUhuTThKdHoxSS9RSjlYUWZTeTB1RFpFT3ZBWEpIZSIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVaFdSRU5EUW5SeFowRjNTVUpCWjBsVlUwWkZhbGhIZG5CSWJsZFdRMUJPVTBoTWFuQkZkVEZIUVVWdmQwTm5XVWxMYjFwSmVtb3dSVUYzVFhjS1RucEZWazFDVFVkQk1WVkZRMmhOVFdNeWJHNWpNMUoyWTIxVmRWcEhWakpOVWpSM1NFRlpSRlpSVVVSRmVGWjZZVmRrZW1SSE9YbGFVekZ3WW01U2JBcGpiVEZzV2tkc2FHUkhWWGRJYUdOT1RXcFpkMDU2VFhkTlJGVXhUMFJWTTFkb1kwNU5hbGwzVG5wTmQwMUVXWGRQUkZVelYycEJRVTFHYTNkRmQxbElDa3R2V2tsNmFqQkRRVkZaU1V0dldrbDZhakJFUVZGalJGRm5RVVVyWTBoSWVXeGxaVzlUY1dWamFXTmlNVUpYUkd3eWIxQXhNR2xFVkU1cFRIWm9MMm9LV1VGVmVUUmlXVEV3TDJWU1oyMVJaazFyWlZoalMzbG1kSFJJYjBnd09FSktURWhSVEVoMFNuRnhaalpSY3pSdWVXRlBRMEptYTNkbloxZ3hUVUUwUndwQk1WVmtSSGRGUWk5M1VVVkJkMGxJWjBSQlZFSm5UbFpJVTFWRlJFUkJTMEpuWjNKQ1owVkdRbEZqUkVGNlFXUkNaMDVXU0ZFMFJVWm5VVlZQZG1aWkNrVnZVRWMwZDFsUmNXYzJRbHBCWTB0TWVEaDZiRkYzZDBoM1dVUldVakJxUWtKbmQwWnZRVlV6T1ZCd2VqRlphMFZhWWpWeFRtcHdTMFpYYVhocE5Ga0tXa1E0ZDJOUldVUldVakJTUVZGSUwwSkhZM2RhV1ZwcVlVaFNNR05JVFRaTWVUbHVZVmhTYjJSWFNYVlpNamwwVERKb2FHTklRalZrYlZaNVpFZHNhZ3BaVjNkMlRHMWtjR1JIYURGWmFUaDFXakpzTUdGSVZtbE1NMlIyWTIxMGJXSkhPVE5qZVRsb1dqSldkV1JETVhkaU1uaHdXVE5yZEdOdE9YTmlSemt4Q21SRE5UVmlWM2hCWTIxV2JXTjVPVzlhVjBaclkzazVkRmxYYkhWTlJHdEhRMmx6UjBGUlVVSm5OemgzUVZGRlJVc3lhREJrU0VKNlQyazRkbVJIT1hJS1dsYzBkVmxYVGpCaFZ6bDFZM2sxYm1GWVVtOWtWMG94WXpKV2VWa3lPWFZrUjFaMVpFTTFhbUl5TUhkSlVWbExTM2RaUWtKQlIwUjJla0ZDUVdkUlZBcGpiVlozWWpOT2NHUkhPWGxsVmpscllWaE9kMWxZVW1waFJFRXlRbWR2Y2tKblJVVkJXVTh2VFVGRlJFSkRhR2hPYWtWNldWUm5NVnBVU1ROTlZFNXRDazlVV1RKWmFtUnNUVlJSTlUxWFVtbFpWRVY1V1cxUk5FMVVUVE5OYWxFelQxUkthMDFEU1VkRGFYTkhRVkZSUW1jM09IZEJVVkZGUmtWR2JscFhOVEFLU1VaQ2RtSkhiR3BsVTBKVFlqSjRjMkl6VmpCTlEwMUhRMmx6UjBGUlVVSm5OemgzUVZGVlJVWlhhR2hqU0VJMVpHMVdlV1JIYkdwWlYzZDJURzFrY0Fwa1IyZ3hXV3BCWkVKbmIzSkNaMFZGUVZsUEwwMUJSVWRDUVRsNVdsZGFla3d5YUd4WlYxSjZUREl4YUdGWE5IZFBkMWxMUzNkWlFrSkJSMFIyZWtGQ0NrTkJVWFJFUTNSdlpFaFNkMk42YjNaTU0xSjJZVEpXZFV4dFJtcGtSMngyWW01TmRWb3liREJoU0ZacFpGaE9iR050VG5aaWJsSnNZbTVSZFZreU9YUUtUVWhOUjBOcGMwZEJVVkZDWnpjNGQwRlJhMFZhVVhocVlVaFNNR05JVFRaTWVUbHVZVmhTYjJSWFNYVlpNamwwVERKb2FHTklRalZrYlZaNVpFZHNhZ3BaVjNkMlRHMWtjR1JIYURGWmFUaDFXakpzTUdGSVZtbE1NMlIyWTIxMGJXSkhPVE5qZVRsb1dqSldkV1JETVhkaU1uaHdXVE5yZEdOdE9YTmlSemt4Q21SRE5UVmlWM2hCWTIxV2JXTjVPVzlhVjBaclkzazVkRmxYYkhWTlJHZEhRMmx6UjBGUlVVSm5OemgzUVZGdlJVdG5kMjlaVkZsNFRUSkZORTVYVlhrS1RucEZlbHBxYXpKT2JVa3pXbFJGTUU5VVJtdFpiVVY0VFcxS2EwOUVSWHBPZWtrd1RucHJlVnBFUVdSQ1oyOXlRbWRGUlVGWlR5OU5RVVZNUWtFNFRRcEVWMlJ3WkVkb01WbHBNVzlpTTA0d1dsZFJkMDlCV1V0TGQxbENRa0ZIUkhaNlFVSkVRVkZ4UkVOb2IyUklVbmRqZW05MlRESmtjR1JIYURGWmFUVnFDbUl5TUhaaFIwWjNZMGhzTWxwWVNqQmhWMDVvWWtNNGRWb3liREJoU0ZacFRVUm5SME5wYzBkQlVWRkNaemM0ZDBGUk1FVkxaM2R2V1ZSWmVFMHlSVFFLVGxkVmVVNTZSWHBhYW1zeVRtMUpNMXBVUlRCUFZFWnJXVzFGZUUxdFNtdFBSRVY2VG5wSk1FNTZhM2xhUkVGbVFtZHZja0puUlVWQldVOHZUVUZGVHdwQ1FrVk5SRE5LYkZwdVRYWmhSMVpvV2toTmRtSlhSbkJpYWtGaFFtZHZja0puUlVWQldVOHZUVUZGVUVKQmQwMURha1Y0VFdwcmVVNTZRVEpOVkZGM0NrMUJXVXRMZDFsQ1FrRkhSSFo2UVVKRlFWRnBSRU5DYjJSSVVuZGplbTkyVERKa2NHUkhhREZaYVRWcVlqSXdkbUZIUm5kalNHd3lXbGhLTUdGWFRtZ0tZa1JCV2tKbmIzSkNaMFZGUVZsUEwwMUJSVkpDUVhOTlExUkZlazFVVVRSTlJHTjZUa1JDZWtKbmIzSkNaMFZGUVZsUEwwMUJSVk5DUjFWTldUSm9NQXBrU0VKNlQyazRkbG95YkRCaFNGWnBURzFPZG1KVE9XOVpXRUozWlZoYWJHTnVVbkJaTWtaelRIazFibUZZVW05a1YwbDJURzFrY0dSSGFERlphVGt6Q21JelNuSmFiWGgyWkROTmRsbFhaR3hpYmxGMFkwYzVjMkZYVGpWTVdFcDJZa2Q0ZG1SWVVYVmxWekZ6VVVoS2JGcHVUWFpoUjFab1draE5kbUpYUm5BS1ltcEJORUpuYjNKQ1owVkZRVmxQTDAxQlJWUkNRMjlOUzBkRk1rMVVUbWhQUkZac1RXcGplRTB5V1RWT2FscHBUakpWZUU1RWEzaGFSMHBvVFZSS2FRcGFSR2Q0VFhwamVVNUVZelZOYlZGM1NYZFpTMHQzV1VKQ1FVZEVkbnBCUWtaQlVWWkVRazU1V2xoQ2RtTXliREJpTTBvMVdESlNjR016UW1oa1IwNXZDazFHZDBkRGFYTkhRVkZSUW1jM09IZEJVbFZGVkdkNFRXRklVakJqU0UwMlRIazVibUZZVW05a1YwbDFXVEk1ZEV3eWFHaGpTRUkxWkcxV2VXUkhiR29LV1ZkM2RreHRaSEJrUjJneFdXazVhRmt6VW5CaU1qVjZURE5LTVdKdVRYWk5la0V4VFZSbmVFMTZRWHBQVkVWMldWaFNNRnBYTVhka1NFMTJUVlJCVndwQ1oyOXlRbWRGUlVGWlR5OU5RVVZYUWtGblRVSnVRakZaYlhod1dYcEJLMEpuYjNKQ1owVkZRVmxQTDAxQlJWbENSRUZOVEc1S2JHTkhPRFpoUjBaM0NtTkliREphV0Vvd1lWZE9hR0pET0hWYU1td3dZVWhXYVU5dVNteGFhbkI1V2xkYWVrd3lhR3haVjFKNlRESXhhR0ZYTkhkbldXdEhRMmx6UjBGUlVVSUtNVzVyUTBKQlNVVmxkMUkxUVVoalFXUlJSR1JRVkVKeGVITmpVazF0VFZwSWFIbGFXbnBqUTI5cmNHVjFUalE0Y21ZclNHbHVTMEZNZVc1MWFtZEJRUXBCV2l0NGJYTlNVVUZCUVVWQmQwSkhUVVZSUTBsRlFXTnZTMXBYVDA5dGRHaHVjRlJuWVhWRFNtSlpTbVJGVFdzM2NsQlZSek56Vnl0UmNtaDNZaXRTQ2tGcFFrMXNlbHBZVWxneVFXWmtka1pHUjNWUFVUSlhjM04xV1RWUGNFZG9RbmcwUTFsRlRtdFFWSGQ1VjFSQlMwSm5aM0ZvYTJwUFVGRlJSRUYzVG04S1FVUkNiRUZxUlVFeFR6VlRNa2hHV0c5TWJESTBaWHBtZFZGS1RtTkZZelJ2Y1d0WlpFeDJZV0pzTTI5VE1uVlZORlExTWtSdVQwbG1NMHRwZGtwNFJncHlUVTFEVGtkTldVRnFRalp2TlVzMVUwNTFZamh1ZUUwM2NXRmphelY1Wm14WFIyOVRhVEJCY1M5SFkxaFRVM3BZYm1oS1MzRkdNR3RwWlZveE9XZHBDbU50Ukd4clNFTm5lSGxGUFFvdExTMHRMVVZPUkNCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2c9PSJ9fX19"}], "timestampVerificationData":{"rfc3161Timestamps":[{"signedTimestamp":"MIICyjADAgEAMIICwQYJKoZIhvcNAQcCoIICsjCCAq4CAQMxDTALBglghkgBZQMEAgEwgbcGCyqGSIb3DQEJEAEEoIGnBIGkMIGhAgEBBgkrBgEEAYO/MAIwMTANBglghkgBZQMEAgEFAAQgq9ywbVkS2keJyYoN01Hfs6pSLJ3sm0CFXfqXrktX1WYCFEYS1EjulQbRvx7ZA1E9LPamb+EyGA8yMDI2MDczMDA1NTg1OFowAwIBAaAypDAwLjEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MRUwEwYDVQQDEwxzaWdzdG9yZS10c2GgADGCAdwwggHYAgEBMFEwOTEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MSAwHgYDVQQDExdzaWdzdG9yZS10c2Etc2VsZnNpZ25lZAIUOhNULwyQYe68wUMvy4qOiyojiwwwCwYJYIZIAWUDBAIBoIH8MBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAcBgkqhkiG9w0BCQUxDxcNMjYwNzMwMDU1ODU4WjAvBgkqhkiG9w0BCQQxIgQg4JG2Gi//jfWERN6ffyQV4jCvE47vqx24KQeEkZWTJVkwgY4GCyqGSIb3DQEJEAIvMX8wfTB7MHkEIIX5J7wHq2LKw7RDVsEO/IGyxog/2nq55thw2dE6zQW3MFUwPaQ7MDkxFTATBgNVBAoTDHNpZ3N0b3JlLmRldjEgMB4GA1UEAxMXc2lnc3RvcmUtdHNhLXNlbGZzaWduZWQCFDoTVC8MkGHuvMFDL8uKjosqI4sMMAoGCCqGSM49BAMCBGgwZgIxAIpBuATa9LfQpiXtHsZo4/n90KFezdpfvC7DbwOFzU2f7nbnqq0ciqGoXR/VsvaJuQIxAOcTULGkCOBDDaKyk0c2bE1qERMMC+JIvMic1/BWwNGuJwCwxdoBxIf702bDP7FW4Q=="}]}}, "messageSignature":{"messageDigest":{"algorithm":"SHA2_256", "digest":"c+Zg/IpYULA1UG8fhKJ9v7cb5dvCuA7vp0o6m+lz6AY="}, "signature":"MEYCIQCbKgldR6jivDZ2jVAeJsNtBy0f0A/wNCPdKA8+t2kUDAIhAMm0N5pf0UkbBEHnM8Jtz1I/QJ9XQfSy0uDZEOvAXJHe"}} \ No newline at end of file diff --git a/.github/agent-policy-evidence/revision-24.json b/.github/agent-policy-evidence/revision-24.json new file mode 100644 index 0000000..8659859 --- /dev/null +++ b/.github/agent-policy-evidence/revision-24.json @@ -0,0 +1,32 @@ +{ + "artifact": "ghcr.io/happyvertical/agent-policy@sha256:a19abb221522c3fe6a8acc9fe07e57cd1f1da08e17aa7d8a57faa8d8966d4511", + "errors": [], + "generation": 21, + "phase": "canary", + "results": [ + { + "conclusion": "success", + "default_branch": "main", + "head_oid": "a613a85e2713f966b7e1491dba12bd813724792d", + "repository_id": "R_kgDOQ09NVg", + "run_id": 30518138150, + "selected_artifact": "ghcr.io/happyvertical/agent-policy@sha256:a19abb221522c3fe6a8acc9fe07e57cd1f1da08e17aa7d8a57faa8d8966d4511", + "selected_channel": "candidate", + "started_at": "2026-07-30T05:58:09Z", + "workflow_path": ".github/workflows/agent-policy.yml" + }, + { + "conclusion": "success", + "default_branch": "main", + "head_oid": "28b821e098764f5558e5dc494604507bd494cab8", + "repository_id": "R_kgDOQDruXg", + "run_id": 30518157493, + "selected_artifact": "ghcr.io/happyvertical/agent-policy@sha256:a19abb221522c3fe6a8acc9fe07e57cd1f1da08e17aa7d8a57faa8d8966d4511", + "selected_channel": "candidate", + "started_at": "2026-07-30T05:58:33Z", + "workflow_path": ".github/workflows/agent-policy.yml" + } + ], + "schema": "hv-agent-policy-channel-evidence:v1", + "state_revision": 23 +} diff --git a/.github/agent-policy-lock.json b/.github/agent-policy-lock.json index e9fea7d..c483588 100644 --- a/.github/agent-policy-lock.json +++ b/.github/agent-policy-lock.json @@ -1,8 +1,8 @@ { - "artifact": "ghcr.io/happyvertical/agent-policy@sha256:69cc70871f1007ae1e8fa7dc0ec525de55417aded59c82d7babb6d93696ad896", - "generation": 17, + "artifact": "ghcr.io/happyvertical/agent-policy@sha256:a19abb221522c3fe6a8acc9fe07e57cd1f1da08e17aa7d8a57faa8d8966d4511", + "generation": 21, "policy_revision": "1.0.0", "schema": "hv-agent-policy-lock:v1", - "source_commit": "b7b490438947f313ba5ca246739ce3a9292dcec0", - "source_tree_sha256": "f137f5a684f4b48edb441d8cef721a1feab73a10e442501652a3ee31736af270" + "source_commit": "a61f995c3458cc2e18b3143f4dd163608810da40", + "source_tree_sha256": "d71e22bb60bb8b1c7881f5ef0a3f879e528d2c15e3b35ddce483d57d80accf05" } diff --git a/.github/workflows/agent-policy-rollout.yml b/.github/workflows/agent-policy-rollout.yml index 63967aa..977a391 100644 --- a/.github/workflows/agent-policy-rollout.yml +++ b/.github/workflows/agent-policy-rollout.yml @@ -18,7 +18,7 @@ concurrency: jobs: rollout: - runs-on: ubuntu-latest + runs-on: ${{ format('arc-{0}', github.repository_owner) }} timeout-minutes: 120 steps: - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5 @@ -26,9 +26,93 @@ jobs: fetch-depth: 0 persist-credentials: false - uses: oras-project/setup-oras@22ce207df3b08e061f537244349aac6ae1d214f6 # v1 - - uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2 - with: - cosign-release: v3.0.6 + # cosign-installer v4 shells out to envsubst, which is not part of the + # provider-neutral general runner contract. Download the publisher- + # compatible cosign v3 binary directly and verify its pinned SHA-256. + - name: Install signature verifier + env: + COSIGN_VERSION: v3.0.6 + COSIGN_SHA256_AMD64: c956e5dfcac53d52bcf058360d579472f0c1d2d9b69f55209e256fe7783f4c74 + COSIGN_SHA256_ARM64: bedac92e8c3729864e13d4a17048007cfafa79d5deca993a43a90ffe018ef2b8 + run: | + set -euo pipefail + case "$(uname -m)" in + x86_64) asset=cosign-linux-amd64; expected="$COSIGN_SHA256_AMD64" ;; + aarch64 | arm64) asset=cosign-linux-arm64; expected="$COSIGN_SHA256_ARM64" ;; + *) echo "unsupported runner architecture: $(uname -m)" >&2; exit 1 ;; + esac + install_dir="$RUNNER_TEMP/hv-cosign" + mkdir -p "$install_dir" + curl -fsSL -o "$install_dir/cosign" \ + "https://github.com/sigstore/cosign/releases/download/$COSIGN_VERSION/$asset" + actual=$(python3 - "$install_dir/cosign" <<'PY' + import hashlib + import pathlib + import sys + + print(hashlib.sha256(pathlib.Path(sys.argv[1]).read_bytes()).hexdigest()) + PY + ) + test "$actual" = "$expected" || { + echo "cosign checksum mismatch: expected $expected, got $actual" >&2 + exit 1 + } + chmod +x "$install_dir/cosign" + echo "$install_dir" >> "$GITHUB_PATH" + "$install_dir/cosign" version + - name: Install GitHub CLI + env: + GH_VERSION: 2.96.0 + GH_SHA256_AMD64: 83d5c2ccad5498f58bf6368acb1ab32588cf43ab3a4b1c301bf36328b1c8bd60 + GH_SHA256_ARM64: 06f86ec7103d41993b76cd78072f43595c34aaa56506d971d9860e67140bf909 + run: | + set -euo pipefail + case "$(uname -m)" in + x86_64) asset_arch=amd64; expected="$GH_SHA256_AMD64" ;; + aarch64 | arm64) asset_arch=arm64; expected="$GH_SHA256_ARM64" ;; + *) echo "unsupported runner architecture: $(uname -m)" >&2; exit 1 ;; + esac + install_dir="$RUNNER_TEMP/hv-gh" + archive="$install_dir/gh.tar.gz" + mkdir -p "$install_dir" + curl -fsSL -o "$archive" \ + "https://github.com/cli/cli/releases/download/v${GH_VERSION}/gh_${GH_VERSION}_linux_${asset_arch}.tar.gz" + actual=$(python3 - "$archive" <<'PY' + import hashlib + import pathlib + import sys + + print(hashlib.sha256(pathlib.Path(sys.argv[1]).read_bytes()).hexdigest()) + PY + ) + test "$actual" = "$expected" || { + echo "GitHub CLI checksum mismatch: expected $expected, got $actual" >&2 + exit 1 + } + gh_dir="$install_dir/gh_${GH_VERSION}_linux_${asset_arch}/bin" + python3 - "$archive" "$install_dir" "$gh_dir/gh" <<'PY' + import pathlib + import stat + import sys + import tarfile + + archive = pathlib.Path(sys.argv[1]) + destination = pathlib.Path(sys.argv[2]) + binary = pathlib.Path(sys.argv[3]) + with tarfile.open(archive, "r:gz") as bundle: + for member in bundle.getmembers(): + path = pathlib.PurePosixPath(member.name) + if ( + path.is_absolute() + or ".." in path.parts + or not (member.isfile() or member.isdir()) + ): + raise SystemExit(f"unsafe GitHub CLI archive member: {member.name}") + bundle.extractall(destination) + binary.chmod(binary.stat().st_mode | stat.S_IXUSR) + PY + echo "$gh_dir" >> "$GITHUB_PATH" + "$gh_dir/gh" version - name: Mint ring dispatch token id: dispatch-token uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 @@ -221,11 +305,14 @@ jobs: git push origin "$branch" body="$RUNNER_TEMP/promotion-pr.md" issue_body="$RUNNER_TEMP/promotion-issue.md" + session="policy-rollout-$GITHUB_RUN_ID" { echo "Protected policy-channel transition generated by the rollout workflow." echo echo "- Action: \`$action\`" echo "- Revision: \`$revision\`" + echo "- Claim runtime: \`github-actions\`" + echo "- Claim session: \`$session\`" echo echo "Claim and release this issue through the canonical lifecycle before merging its PR." } > "$issue_body" @@ -233,15 +320,42 @@ jobs: --title "chore(agent-policy): ${action} channel revision ${revision}" \ --body-file "$issue_body") issue_number=${issue_url##*/} + runtime_policy_revision=$( + jq -er '.policy_revision | select(type == "string" and length > 0)' \ + .github/agent-policy-lock.json + ) + canonical_evidence_sha256=$( + jq -er \ + '.transition.evidence_sha256 + | select(type == "string" and test("^[0-9a-f]{64}$"))' \ + .github/agent-policy-channels.json + ) { echo "Automated protected policy-channel transition." echo echo "- Action: \`$action\`" echo "- Revision: \`$revision\`" - echo "- Evidence SHA-256: \`$(jq -cS . "$RUNNER_TEMP/evidence.json" | shasum -a 256 | awk '{print $1}')\`" + echo "- Canonical evidence SHA-256: \`$canonical_evidence_sha256\`" echo "- Signed bundle SHA-256: \`$(shasum -a 256 "$RUNNER_TEMP/evidence.bundle" | awk '{print $1}')\`" echo echo "Closes #$issue_number" + echo + echo "" + jq -cn \ + --arg session "$session" \ + --arg issue "$issue_number" \ + --arg policy_revision "$runtime_policy_revision" \ + '{ + schema: "hv-agent-run:v1", + runtime: "github-actions", + session: $session, + issue: $issue, + policy_revision: $policy_revision, + validation: [ + "protected rollout recorded a signed exact-default-head evidence bundle", + "canonical channel transition applied at the expected revision" + ] + }' } > "$body" url=$(gh pr create --repo happyvertical/.github --base main --head "$branch" \ --title "chore(agent-policy): ${action} channel revision ${revision}" \ diff --git a/.github/workflows/agent-policy.yml b/.github/workflows/agent-policy.yml index 01c07ed..4a3d241 100644 --- a/.github/workflows/agent-policy.yml +++ b/.github/workflows/agent-policy.yml @@ -32,14 +32,99 @@ concurrency: jobs: lifecycle: name: lifecycle - runs-on: ubuntu-latest + runs-on: ${{ format('arc-{0}', github.repository_owner) }} timeout-minutes: 10 steps: - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5 - uses: oras-project/setup-oras@22ce207df3b08e061f537244349aac6ae1d214f6 # v1 - - uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2 - with: - cosign-release: v3.0.6 + # cosign-installer v4 shells out to envsubst, which is not part of the + # provider-neutral general runner contract. Download the publisher- + # compatible cosign v3 binary directly and verify its pinned SHA-256 so + # lifecycle enforcement has the same dependencies on every provider. + - name: Install signature verifier + env: + COSIGN_VERSION: v3.0.6 + COSIGN_SHA256_AMD64: c956e5dfcac53d52bcf058360d579472f0c1d2d9b69f55209e256fe7783f4c74 + COSIGN_SHA256_ARM64: bedac92e8c3729864e13d4a17048007cfafa79d5deca993a43a90ffe018ef2b8 + run: | + set -euo pipefail + case "$(uname -m)" in + x86_64) asset=cosign-linux-amd64; expected="$COSIGN_SHA256_AMD64" ;; + aarch64 | arm64) asset=cosign-linux-arm64; expected="$COSIGN_SHA256_ARM64" ;; + *) echo "unsupported runner architecture: $(uname -m)" >&2; exit 1 ;; + esac + install_dir="$RUNNER_TEMP/hv-cosign" + mkdir -p "$install_dir" + curl -fsSL -o "$install_dir/cosign" \ + "https://github.com/sigstore/cosign/releases/download/$COSIGN_VERSION/$asset" + actual=$(python3 - "$install_dir/cosign" <<'PY' + import hashlib + import pathlib + import sys + + print(hashlib.sha256(pathlib.Path(sys.argv[1]).read_bytes()).hexdigest()) + PY + ) + test "$actual" = "$expected" || { + echo "cosign checksum mismatch: expected $expected, got $actual" >&2 + exit 1 + } + chmod +x "$install_dir/cosign" + echo "$install_dir" >> "$GITHUB_PATH" + "$install_dir/cosign" version + - name: Install GitHub CLI + env: + GH_VERSION: 2.96.0 + GH_SHA256_AMD64: 83d5c2ccad5498f58bf6368acb1ab32588cf43ab3a4b1c301bf36328b1c8bd60 + GH_SHA256_ARM64: 06f86ec7103d41993b76cd78072f43595c34aaa56506d971d9860e67140bf909 + run: | + set -euo pipefail + case "$(uname -m)" in + x86_64) asset_arch=amd64; expected="$GH_SHA256_AMD64" ;; + aarch64 | arm64) asset_arch=arm64; expected="$GH_SHA256_ARM64" ;; + *) echo "unsupported runner architecture: $(uname -m)" >&2; exit 1 ;; + esac + install_dir="$RUNNER_TEMP/hv-gh" + archive="$install_dir/gh.tar.gz" + mkdir -p "$install_dir" + curl -fsSL -o "$archive" \ + "https://github.com/cli/cli/releases/download/v${GH_VERSION}/gh_${GH_VERSION}_linux_${asset_arch}.tar.gz" + actual=$(python3 - "$archive" <<'PY' + import hashlib + import pathlib + import sys + + print(hashlib.sha256(pathlib.Path(sys.argv[1]).read_bytes()).hexdigest()) + PY + ) + test "$actual" = "$expected" || { + echo "GitHub CLI checksum mismatch: expected $expected, got $actual" >&2 + exit 1 + } + gh_dir="$install_dir/gh_${GH_VERSION}_linux_${asset_arch}/bin" + python3 - "$archive" "$install_dir" "$gh_dir/gh" <<'PY' + import pathlib + import stat + import sys + import tarfile + + archive = pathlib.Path(sys.argv[1]) + destination = pathlib.Path(sys.argv[2]) + binary = pathlib.Path(sys.argv[3]) + with tarfile.open(archive, "r:gz") as bundle: + for member in bundle.getmembers(): + path = pathlib.PurePosixPath(member.name) + if ( + path.is_absolute() + or ".." in path.parts + or not (member.isfile() or member.isdir()) + ): + raise SystemExit(f"unsafe GitHub CLI archive member: {member.name}") + bundle.extractall(destination) + binary.chmod(binary.stat().st_mode | stat.S_IXUSR) + PY + echo "$gh_dir" >> "$GITHUB_PATH" + "$gh_dir/gh" version - name: Select source-owned policy channel shell: bash env: @@ -60,20 +145,24 @@ jobs: protected_selector="$RUNNER_TEMP/hv-agent-policy-channel-select" protected_channels="$RUNNER_TEMP/hv_agent_policy_channels.py" channels_active=true - if gh api 'repos/happyvertical/.github/contents/.github/agent-policy-channels.json?ref=main' \ - --jq '.content' 2> "$active_state_error" \ - | base64 --decode > "$active_state"; then - gh api 'repos/happyvertical/.github/contents/scripts/hv-agent-policy-channel-select?ref=main' \ - --jq '.content' | base64 --decode > "$protected_selector" - gh api 'repos/happyvertical/.github/contents/scripts/hv_agent_policy_channels.py?ref=main' \ - --jq '.content' | base64 --decode > "$protected_channels" - gh api 'repos/happyvertical/.github/contents/.github/agent-policy-lock.json?ref=main' \ - --jq '.content' | base64 --decode > "$active_lock" + if gh api -H 'Accept: application/vnd.github.raw+json' \ + 'repos/happyvertical/.github/contents/.github/agent-policy-channels.json?ref=main' \ + > "$active_state" 2> "$active_state_error"; then + gh api -H 'Accept: application/vnd.github.raw+json' \ + 'repos/happyvertical/.github/contents/scripts/hv-agent-policy-channel-select?ref=main' \ + > "$protected_selector" + gh api -H 'Accept: application/vnd.github.raw+json' \ + 'repos/happyvertical/.github/contents/scripts/hv_agent_policy_channels.py?ref=main' \ + > "$protected_channels" + gh api -H 'Accept: application/vnd.github.raw+json' \ + 'repos/happyvertical/.github/contents/.github/agent-policy-lock.json?ref=main' \ + > "$active_lock" chmod +x "$protected_selector" elif grep -q 'HTTP 404' "$active_state_error"; then channels_active=false - gh api 'repos/happyvertical/.github/contents/.github/agent-policy-lock.json?ref=main' \ - --jq '.content' | base64 --decode > "$active_lock" + gh api -H 'Accept: application/vnd.github.raw+json' \ + 'repos/happyvertical/.github/contents/.github/agent-policy-lock.json?ref=main' \ + > "$active_lock" python3 - "$active_lock" "$active_state" <<'PY' import json import re