diff --git a/.github/agent-policy-channels.json b/.github/agent-policy-channels.json index d5adad1..3ded99d 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:591a3a6e6924e09a16e0b8b8669b5de40b34ec3b7c860556b502d113b8a3ae45", - "generation": 20, - "policy_revision": "1.0.0", - "schema": "hv-agent-policy-lock:v1", - "source_commit": "db310fe3f7e7bc089564dc0114a3a6cb3b5d5eaf", - "source_tree_sha256": "8fc22a9f31868e281a471c07069eb5d89421f1c9444290b99bc798057fe7c34a" - }, - "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:591a3a6e6924e09a16e0b8b8669b5de40b34ec3b7c860556b502d113b8a3ae45", + "generation": 20, + "policy_revision": "1.0.0", + "schema": "hv-agent-policy-lock:v1", + "source_commit": "db310fe3f7e7bc089564dc0114a3a6cb3b5d5eaf", + "source_tree_sha256": "8fc22a9f31868e281a471c07069eb5d89421f1c9444290b99bc798057fe7c34a" } }, "default_channel": "stable", "promotion": { - "canary_evidence_sha256": null, + "canary_evidence_sha256": "a5761422e6486cd3216dbff88a40afb512bb70d5a81110f6ebb6abed4b39d9dc", "canary_repository_ids": [ "R_kgDOQ09NVg", "R_kgDOQDruXg" @@ -36,7 +33,7 @@ "source_commit": "db310fe3f7e7bc089564dc0114a3a6cb3b5d5eaf", "source_tree_sha256": "8fc22a9f31868e281a471c07069eb5d89421f1c9444290b99bc798057fe7c34a" }, - "phase": "canary", + "phase": "smoke", "previous_stable": { "artifact": "ghcr.io/happyvertical/agent-policy@sha256:69cc70871f1007ae1e8fa7dc0ec525de55417aded59c82d7babb6d93696ad896", "generation": 17, @@ -53,14 +50,14 @@ "R_kgDOQmZFRQ" ] }, - "revision": 21, + "revision": 22, "schema": "hv-agent-policy-channels:v1", "transition": { - "action": "prepare", + "action": "promote", "artifact": "ghcr.io/happyvertical/agent-policy@sha256:591a3a6e6924e09a16e0b8b8669b5de40b34ec3b7c860556b502d113b8a3ae45", - "evidence_sha256": null, - "from_revision": 20, + "evidence_sha256": "a5761422e6486cd3216dbff88a40afb512bb70d5a81110f6ebb6abed4b39d9dc", + "from_revision": 21, "previous_artifact": "ghcr.io/happyvertical/agent-policy@sha256:69cc70871f1007ae1e8fa7dc0ec525de55417aded59c82d7babb6d93696ad896", - "to_revision": 21 + "to_revision": 22 } } diff --git a/.github/agent-policy-evidence/revision-22.bundle b/.github/agent-policy-evidence/revision-22.bundle new file mode 100644 index 0000000..bded0cf --- /dev/null +++ b/.github/agent-policy-evidence/revision-22.bundle @@ -0,0 +1 @@ +{"mediaType":"application/vnd.dev.sigstore.bundle.v0.3+json", "verificationMaterial":{"certificate":{"rawBytes":"MIIHVTCCBtqgAwIBAgIUIBlLVfFdsNyfYB+o6rKTVxNne7MwCgYIKoZIzj0EAwMwNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwHhcNMjYwNzMwMDQyMjMxWhcNMjYwNzMwMDQzMjMxWjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEzkrvJxkOvm5Kv0q6TLRxQ8nxHPqe7BETXXbWiPCzPNBPkDyzkzaMQulINkGb00/K/4+QzWzzAaq+kYUh4rL6o6OCBfkwggX1MA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQU75EnMCkFWSDgaLMcZx3ydfupDE0wHwYDVR0jBBgwFoAU39Ppz1YkEZb5qNjpKFWixi4YZD8wcQYDVR0RAQH/BGcwZYZjaHR0cHM6Ly9naXRodWIuY29tL2hhcHB5dmVydGljYWwvLmdpdGh1Yi8uZ2l0aHViL3dvcmtmbG93cy9hZ2VudC1wb2xpY3ktcm9sbG91dC55bWxAcmVmcy9oZWFkcy9tYWluMDkGCisGAQQBg78wAQEEK2h0dHBzOi8vdG9rZW4uYWN0aW9ucy5naXRodWJ1c2VyY29udGVudC5jb20wIQYKKwYBBAGDvzABAgQTcmVwb3NpdG9yeV9kaXNwYXRjaDA2BgorBgEEAYO/MAEDBCg2MDUyZTkyM2YwNjgyOWJkYzk1Y2RiZjQ2ZTBjZmI0NDQ4NWI3M2ZkMCIGCisGAQQBg78wAQQEFEFnZW50IFBvbGljeSBSb2xsb3V0MCMGCisGAQQBg78wAQUEFWhhcHB5dmVydGljYWwvLmdpdGh1YjAdBgorBgEEAYO/MAEGBA9yZWZzL2hlYWRzL21haW4wOwYKKwYBBAGDvzABCAQtDCtodHRwczovL3Rva2VuLmFjdGlvbnMuZ2l0aHVidXNlcmNvbnRlbnQuY29tMHMGCisGAQQBg78wAQkEZQxjaHR0cHM6Ly9naXRodWIuY29tL2hhcHB5dmVydGljYWwvLmdpdGh1Yi8uZ2l0aHViL3dvcmtmbG93cy9hZ2VudC1wb2xpY3ktcm9sbG91dC55bWxAcmVmcy9oZWFkcy9tYWluMDgGCisGAQQBg78wAQoEKgwoNjA1MmU5MjNmMDY4MjliZGM5NWNkYmY0NmUwY2ZiNDQ0ODViNzNmZDAdBgorBgEEAYO/MAELBA8MDWdpdGh1Yi1ob3N0ZWQwOAYKKwYBBAGDvzABDAQqDChodHRwczovL2dpdGh1Yi5jb20vaGFwcHl2ZXJ0aWNhbC8uZ2l0aHViMDgGCisGAQQBg78wAQ0EKgwoNjA1MmU5MjNmMDY4MjliZGM5NWNkYmY0NmUwY2ZiNDQ0ODViNzNmZDAfBgorBgEEAYO/MAEOBBEMD3JlZnMvaGVhZHMvbWFpbjAaBgorBgEEAYO/MAEPBAwMCjExMjkyNzA2MTQwMAYKKwYBBAGDvzABEAQiDCBodHRwczovL2dpdGh1Yi5jb20vaGFwcHl2ZXJ0aWNhbDAZBgorBgEEAYO/MAERBAsMCTEzMTQ4MDczNDBzBgorBgEEAYO/MAESBGUMY2h0dHBzOi8vZ2l0aHViLmNvbS9oYXBweXZlcnRpY2FsLy5naXRodWIvLmdpdGh1Yi93b3JrZmxvd3MvYWdlbnQtcG9saWN5LXJvbGxvdXQueW1sQHJlZnMvaGVhZHMvbWFpbjA4BgorBgEEAYO/MAETBCoMKDYwNTJlOTIzZjA2ODI5YmRjOTVjZGJmNDZlMGNmYjQ0NDg1YjczZmQwIwYKKwYBBAGDvzABFAQVDBNyZXBvc2l0b3J5X2Rpc3BhdGNoMFwGCisGAQQBg78wARUETgxMaHR0cHM6Ly9naXRodWIuY29tL2hhcHB5dmVydGljYWwvLmdpdGh1Yi9hY3Rpb25zL3J1bnMvMzA1MTM2NTM1MTcvYXR0ZW1wdHMvMTAWBgorBgEEAYO/MAEWBAgMBnB1YmxpYzA+BgorBgEEAYO/MAEYBDAMLnJlcG86aGFwcHl2ZXJ0aWNhbC8uZ2l0aHViOnJlZjpyZWZzL2hlYWRzL21haW4wgYkGCisGAQQB1nkCBAIEewR5AHcAdQDdPTBqxscRMmMZHhyZZzcCokpeuN48rf+HinKALynujgAAAZ+xQnkwAAAEAwBGMEQCIE2sNfrjscFXRZTppieS4kMwZsLbbKwtfiIvToK8WK4RAiBVS3GGnlLE2Bj+tqxLD/WtqvDOf1mdkpPmNWfAnoid8zAKBggqhkjOPQQDAwNpADBmAjEAlFS7HSo3kAzDfdWMQl1MAvcYAj+gD8BiCFEQAxz2JI8Zo6RwEqF2WwTFGZ7DX1QjAjEA43M7WCaUK8DY/QdLECrNTXR6BWd8xYJMNc9xw5E3s9zmJMyq38WS9l/+cJT6E5qB"}, "tlogEntries":[{"logIndex":"2287153510", "logId":{"keyId":"wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0="}, "kindVersion":{"kind":"hashedrekord", "version":"0.0.1"}, "integratedTime":"1785385351", "inclusionPromise":{"signedEntryTimestamp":"MEUCICIBS9sihIAH6j1nckMku/085G+F0I+26mErxuyDCffgAiEAlnK1dNpiM//RvlGTCaO59KBVYbZOSc7SCl0NtVcG98w="}, "inclusionProof":{"logIndex":"2165249248", "rootHash":"Eq2KObbCWqF1q+lH039B3N/3jYaeof5Tw9l10Bg17UY=", "treeSize":"2165249252", "hashes":["UKgFkNdsBdIEXK0F2UnwfznGxlbvgtkGyY839z3gjH0=", "u/Dz1OTwH1heaDddj/fJrkC29vf658tL8emjhY7LjrM=", "0znJQAd8q7lIvEuHNXDeDK+FSJc3brZxoD+XO4Sbm4U=", "IBgqPpnOPShSaHpg1oB6f+HJ9tprI+5uZthstApstkk=", "zvnbR/5pjOzBDtZ1Fd2npH2YWnDIFTs+lFQSWSsoY18=", "prUmz1VfwZ4+/EsQX67uHQVhzvJabDm97IMT9tcMPkY=", "AsKCnjXVWwbn9ZDiQ6L10RkF87Yr49ve7/nxAOb2qtU=", "2rWmXRuGtY1MNJGY25elbu2ps2FqFyTOBubAz5X/1fY=", "A3oVCJuADmW5pdH0rrrLZQG+vBYVzHfEiKfHllUixTY=", "jcJP2VjqJ/8SfPyt7UtlWj4rjV4OqiA6y9hXHpvOUSI=", "0KRQ6EWL7ykJC6OQ9Ih4FMEd2mXiKgsgOfHkCCmSRJU=", "gFCDLuUICPUD+cTxcpdc20bh3Ddh2oUrPn7Cy0NnyoE=", "xH/DCseLHr9eKoYT8qsORZK7zVdEGYWHuVtsVrD95wY="], "checkpoint":{"envelope":"rekor.sigstore.dev - 1193050959916656506\n2165249252\nEq2KObbCWqF1q+lH039B3N/3jYaeof5Tw9l10Bg17UY=\n\n— rekor.sigstore.dev wNI9ajBEAiAbsslG+pOoTGkxOo0KGYuOgUYFdeMjiqjZxpTSZycQGgIgOUk0af8BSZb9XgGSu/+/BxP/DgU7kuJb6NMxOOK4V8w=\n"}}, "canonicalizedBody":"eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiIxNTE4Yzg2ZDBhMmEyNzdiYjdiZGJlZTQ3OTRhNDdjNDg2OWM1ZmU0NjFhNGIxOTY4NjY4MjA4NGEwYzhlOWY3In19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FWUNJUUNIMlJjT0JadVNyclVlM1pBTGpOZ29pSzRsSWhSTWc3SjhtbnR0ejBXbmpBSWhBUGd1d2ZtelgvZGovMUhYdXIzWmcvMlkzUUpKMk1FQThkaWZUSjdWeS9rRyIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVaFdWRU5EUW5SeFowRjNTVUpCWjBsVlNVSnNURlptUm1SelRubG1XVUlyYnpaeVMxUldlRTV1WlRkTmQwTm5XVWxMYjFwSmVtb3dSVUYzVFhjS1RucEZWazFDVFVkQk1WVkZRMmhOVFdNeWJHNWpNMUoyWTIxVmRWcEhWakpOVWpSM1NFRlpSRlpSVVVSRmVGWjZZVmRrZW1SSE9YbGFVekZ3WW01U2JBcGpiVEZzV2tkc2FHUkhWWGRJYUdOT1RXcFpkMDU2VFhkTlJGRjVUV3BOZUZkb1kwNU5hbGwzVG5wTmQwMUVVWHBOYWsxNFYycEJRVTFHYTNkRmQxbElDa3R2V2tsNmFqQkRRVkZaU1V0dldrbDZhakJFUVZGalJGRm5RVVY2YTNKMlNuaHJUM1p0TlV0Mk1IRTJWRXhTZUZFNGJuaElVSEZsTjBKRlZGaFlZbGNLYVZCRGVsQk9RbEJyUkhsNmEzcGhUVkYxYkVsT2EwZGlNREF2U3k4MEsxRjZWM3A2UVdGeEsydFpWV2cwY2t3MmJ6WlBRMEptYTNkbloxZ3hUVUUwUndwQk1WVmtSSGRGUWk5M1VVVkJkMGxJWjBSQlZFSm5UbFpJVTFWRlJFUkJTMEpuWjNKQ1owVkdRbEZqUkVGNlFXUkNaMDVXU0ZFMFJVWm5VVlUzTlVWdUNrMURhMFpYVTBSbllVeE5ZMXA0TTNsa1puVndSRVV3ZDBoM1dVUldVakJxUWtKbmQwWnZRVlV6T1ZCd2VqRlphMFZhWWpWeFRtcHdTMFpYYVhocE5Ga0tXa1E0ZDJOUldVUldVakJTUVZGSUwwSkhZM2RhV1ZwcVlVaFNNR05JVFRaTWVUbHVZVmhTYjJSWFNYVlpNamwwVERKb2FHTklRalZrYlZaNVpFZHNhZ3BaVjNkMlRHMWtjR1JIYURGWmFUaDFXakpzTUdGSVZtbE1NMlIyWTIxMGJXSkhPVE5qZVRsb1dqSldkV1JETVhkaU1uaHdXVE5yZEdOdE9YTmlSemt4Q21SRE5UVmlWM2hCWTIxV2JXTjVPVzlhVjBaclkzazVkRmxYYkhWTlJHdEhRMmx6UjBGUlVVSm5OemgzUVZGRlJVc3lhREJrU0VKNlQyazRkbVJIT1hJS1dsYzBkVmxYVGpCaFZ6bDFZM2sxYm1GWVVtOWtWMG94WXpKV2VWa3lPWFZrUjFaMVpFTTFhbUl5TUhkSlVWbExTM2RaUWtKQlIwUjJla0ZDUVdkUlZBcGpiVlozWWpOT2NHUkhPWGxsVmpscllWaE9kMWxZVW1waFJFRXlRbWR2Y2tKblJVVkJXVTh2VFVGRlJFSkRaekpOUkZWNVdsUnJlVTB5V1hkT2FtZDVDazlYU210WmVtc3hXVEpTYVZwcVVUSmFWRUpxV20xSk1FNUVVVFJPVjBrelRUSmFhMDFEU1VkRGFYTkhRVkZSUW1jM09IZEJVVkZGUmtWR2JscFhOVEFLU1VaQ2RtSkhiR3BsVTBKVFlqSjRjMkl6VmpCTlEwMUhRMmx6UjBGUlVVSm5OemgzUVZGVlJVWlhhR2hqU0VJMVpHMVdlV1JIYkdwWlYzZDJURzFrY0Fwa1IyZ3hXV3BCWkVKbmIzSkNaMFZGUVZsUEwwMUJSVWRDUVRsNVdsZGFla3d5YUd4WlYxSjZUREl4YUdGWE5IZFBkMWxMUzNkWlFrSkJSMFIyZWtGQ0NrTkJVWFJFUTNSdlpFaFNkMk42YjNaTU0xSjJZVEpXZFV4dFJtcGtSMngyWW01TmRWb3liREJoU0ZacFpGaE9iR050VG5aaWJsSnNZbTVSZFZreU9YUUtUVWhOUjBOcGMwZEJVVkZDWnpjNGQwRlJhMFZhVVhocVlVaFNNR05JVFRaTWVUbHVZVmhTYjJSWFNYVlpNamwwVERKb2FHTklRalZrYlZaNVpFZHNhZ3BaVjNkMlRHMWtjR1JIYURGWmFUaDFXakpzTUdGSVZtbE1NMlIyWTIxMGJXSkhPVE5qZVRsb1dqSldkV1JETVhkaU1uaHdXVE5yZEdOdE9YTmlSemt4Q21SRE5UVmlWM2hCWTIxV2JXTjVPVzlhVjBaclkzazVkRmxYYkhWTlJHZEhRMmx6UjBGUlVVSm5OemgzUVZGdlJVdG5kMjlPYWtFeFRXMVZOVTFxVG0wS1RVUlpORTFxYkdsYVIwMDFUbGRPYTFsdFdUQk9iVlYzV1RKYWFVNUVVVEJQUkZacFRucE9iVnBFUVdSQ1oyOXlRbWRGUlVGWlR5OU5RVVZNUWtFNFRRcEVWMlJ3WkVkb01WbHBNVzlpTTA0d1dsZFJkMDlCV1V0TGQxbENRa0ZIUkhaNlFVSkVRVkZ4UkVOb2IyUklVbmRqZW05MlRESmtjR1JIYURGWmFUVnFDbUl5TUhaaFIwWjNZMGhzTWxwWVNqQmhWMDVvWWtNNGRWb3liREJoU0ZacFRVUm5SME5wYzBkQlVWRkNaemM0ZDBGUk1FVkxaM2R2VG1wQk1VMXRWVFVLVFdwT2JVMUVXVFJOYW14cFdrZE5OVTVYVG10WmJWa3dUbTFWZDFreVdtbE9SRkV3VDBSV2FVNTZUbTFhUkVGbVFtZHZja0puUlVWQldVOHZUVUZGVHdwQ1FrVk5SRE5LYkZwdVRYWmhSMVpvV2toTmRtSlhSbkJpYWtGaFFtZHZja0puUlVWQldVOHZUVUZGVUVKQmQwMURha1Y0VFdwcmVVNTZRVEpOVkZGM0NrMUJXVXRMZDFsQ1FrRkhSSFo2UVVKRlFWRnBSRU5DYjJSSVVuZGplbTkyVERKa2NHUkhhREZaYVRWcVlqSXdkbUZIUm5kalNHd3lXbGhLTUdGWFRtZ0tZa1JCV2tKbmIzSkNaMFZGUVZsUEwwMUJSVkpDUVhOTlExUkZlazFVVVRSTlJHTjZUa1JDZWtKbmIzSkNaMFZGUVZsUEwwMUJSVk5DUjFWTldUSm9NQXBrU0VKNlQyazRkbG95YkRCaFNGWnBURzFPZG1KVE9XOVpXRUozWlZoYWJHTnVVbkJaTWtaelRIazFibUZZVW05a1YwbDJURzFrY0dSSGFERlphVGt6Q21JelNuSmFiWGgyWkROTmRsbFhaR3hpYmxGMFkwYzVjMkZYVGpWTVdFcDJZa2Q0ZG1SWVVYVmxWekZ6VVVoS2JGcHVUWFpoUjFab1draE5kbUpYUm5BS1ltcEJORUpuYjNKQ1owVkZRVmxQTDAxQlJWUkNRMjlOUzBSWmQwNVVTbXhQVkVsNldtcEJNazlFU1RWWmJWSnFUMVJXYWxwSFNtMU9SRnBzVFVkT2JRcFphbEV3VGtSbk1WbHFZM3BhYlZGM1NYZFpTMHQzV1VKQ1FVZEVkbnBCUWtaQlVWWkVRazU1V2xoQ2RtTXliREJpTTBvMVdESlNjR016UW1oa1IwNXZDazFHZDBkRGFYTkhRVkZSUW1jM09IZEJVbFZGVkdkNFRXRklVakJqU0UwMlRIazVibUZZVW05a1YwbDFXVEk1ZEV3eWFHaGpTRUkxWkcxV2VXUkhiR29LV1ZkM2RreHRaSEJrUjJneFdXazVhRmt6VW5CaU1qVjZURE5LTVdKdVRYWk5la0V4VFZSTk1rNVVUVEZOVkdOMldWaFNNRnBYTVhka1NFMTJUVlJCVndwQ1oyOXlRbWRGUlVGWlR5OU5RVVZYUWtGblRVSnVRakZaYlhod1dYcEJLMEpuYjNKQ1owVkZRVmxQTDAxQlJWbENSRUZOVEc1S2JHTkhPRFpoUjBaM0NtTkliREphV0Vvd1lWZE9hR0pET0hWYU1td3dZVWhXYVU5dVNteGFhbkI1V2xkYWVrd3lhR3haVjFKNlRESXhhR0ZYTkhkbldXdEhRMmx6UjBGUlVVSUtNVzVyUTBKQlNVVmxkMUkxUVVoalFXUlJSR1JRVkVKeGVITmpVazF0VFZwSWFIbGFXbnBqUTI5cmNHVjFUalE0Y21ZclNHbHVTMEZNZVc1MWFtZEJRUXBCV2l0NFVXNXJkMEZCUVVWQmQwSkhUVVZSUTBsRk1uTk9abkpxYzJOR1dGSmFWSEJ3YVdWVE5HdE5kMXB6VEdKaVMzZDBabWxKZGxSdlN6aFhTelJTQ2tGcFFsWlRNMGRIYm14TVJUSkNhaXQwY1hoTVJDOVhkSEYyUkU5bU1XMWthM0JRYlU1WFprRnViMmxrT0hwQlMwSm5aM0ZvYTJwUFVGRlJSRUYzVG5BS1FVUkNiVUZxUlVGc1JsTTNTRk52TTJ0QmVrUm1aRmROVVd3eFRVRjJZMWxCYWl0blJEaENhVU5HUlZGQmVIb3lTa2s0V204MlVuZEZjVVl5VjNkVVJncEhXamRFV0RGUmFrRnFSVUUwTTAwM1YwTmhWVXM0UkZrdlVXUk1SVU55VGxSWVVqWkNWMlE0ZUZsS1RVNWpPWGgzTlVVemN6bDZiVXBOZVhFek9GZFRDamxzTHl0alNsUTJSVFZ4UWdvdExTMHRMVVZPUkNCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2c9PSJ9fX19"}], "timestampVerificationData":{"rfc3161Timestamps":[{"signedTimestamp":"MIICyjADAgEAMIICwQYJKoZIhvcNAQcCoIICsjCCAq4CAQMxDTALBglghkgBZQMEAgEwgbgGCyqGSIb3DQEJEAEEoIGoBIGlMIGiAgEBBgkrBgEEAYO/MAIwMTANBglghkgBZQMEAgEFAAQgPjPwQyfD5sRsbY9HJ/CVvDtGMitfA/tUZ70dZfs4bYwCFQC1tVV5Qz9/xRmuqiYuWcODMEmlrRgPMjAyNjA3MzAwNDIyMzFaMAMCAQGgMqQwMC4xFTATBgNVBAoTDHNpZ3N0b3JlLmRldjEVMBMGA1UEAxMMc2lnc3RvcmUtdHNhoAAxggHbMIIB1wIBATBRMDkxFTATBgNVBAoTDHNpZ3N0b3JlLmRldjEgMB4GA1UEAxMXc2lnc3RvcmUtdHNhLXNlbGZzaWduZWQCFDoTVC8MkGHuvMFDL8uKjosqI4sMMAsGCWCGSAFlAwQCAaCB/DAaBgkqhkiG9w0BCQMxDQYLKoZIhvcNAQkQAQQwHAYJKoZIhvcNAQkFMQ8XDTI2MDczMDA0MjIzMVowLwYJKoZIhvcNAQkEMSIEIMs5MORUlgwrPBg/Jq6vsrej5ruyW+aEa9pW1aVUDcFNMIGOBgsqhkiG9w0BCRACLzF/MH0wezB5BCCF+Se8B6tiysO0Q1bBDvyBssaIP9p6uebYcNnROs0FtzBVMD2kOzA5MRUwEwYDVQQKEwxzaWdzdG9yZS5kZXYxIDAeBgNVBAMTF3NpZ3N0b3JlLXRzYS1zZWxmc2lnbmVkAhQ6E1QvDJBh7rzBQy/Lio6LKiOLDDAKBggqhkjOPQQDAgRnMGUCMQDemmHQJLHUARvn66RrAnJ8On4IL2h2GZ2NVnoiSwwt91f+OKqSVL39nAK2ODJmE5ECMA8KzB192IKhzJVo7O744EgvtMrFp082TRr9O18kwYdBuooshoLrilQN0UXurCdZYw=="}]}}, "messageSignature":{"messageDigest":{"algorithm":"SHA2_256", "digest":"FRjIbQoqJ3u3vb7keUpHxIacX+RhpLGWhmgghKDI6fc="}, "signature":"MEYCIQCH2RcOBZuSrrUe3ZALjNgoiK4lIhRMg7J8mnttz0WnjAIhAPguwfmzX/dj/1HXur3Zg/2Y3QJJ2MEA8difTJ7Vy/kG"}} \ No newline at end of file diff --git a/.github/agent-policy-evidence/revision-22.json b/.github/agent-policy-evidence/revision-22.json new file mode 100644 index 0000000..7891308 --- /dev/null +++ b/.github/agent-policy-evidence/revision-22.json @@ -0,0 +1,32 @@ +{ + "artifact": "ghcr.io/happyvertical/agent-policy@sha256:591a3a6e6924e09a16e0b8b8669b5de40b34ec3b7c860556b502d113b8a3ae45", + "errors": [], + "generation": 20, + "phase": "canary", + "results": [ + { + "conclusion": "success", + "default_branch": "main", + "head_oid": "6052e923f06829bdc95cdbf46e0cfb44485b73fd", + "repository_id": "R_kgDOQ09NVg", + "run_id": 30513667492, + "selected_artifact": "ghcr.io/happyvertical/agent-policy@sha256:591a3a6e6924e09a16e0b8b8669b5de40b34ec3b7c860556b502d113b8a3ae45", + "selected_channel": "candidate", + "started_at": "2026-07-30T04:21:38Z", + "workflow_path": ".github/workflows/agent-policy.yml" + }, + { + "conclusion": "success", + "default_branch": "main", + "head_oid": "28b821e098764f5558e5dc494604507bd494cab8", + "repository_id": "R_kgDOQDruXg", + "run_id": 30513688680, + "selected_artifact": "ghcr.io/happyvertical/agent-policy@sha256:591a3a6e6924e09a16e0b8b8669b5de40b34ec3b7c860556b502d113b8a3ae45", + "selected_channel": "candidate", + "started_at": "2026-07-30T04:22:05Z", + "workflow_path": ".github/workflows/agent-policy.yml" + } + ], + "schema": "hv-agent-policy-channel-evidence:v1", + "state_revision": 21 +} diff --git a/.github/agent-policy-lock.json b/.github/agent-policy-lock.json index e9fea7d..db1df36 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:591a3a6e6924e09a16e0b8b8669b5de40b34ec3b7c860556b502d113b8a3ae45", + "generation": 20, "policy_revision": "1.0.0", "schema": "hv-agent-policy-lock:v1", - "source_commit": "b7b490438947f313ba5ca246739ce3a9292dcec0", - "source_tree_sha256": "f137f5a684f4b48edb441d8cef721a1feab73a10e442501652a3ee31736af270" + "source_commit": "db310fe3f7e7bc089564dc0114a3a6cb3b5d5eaf", + "source_tree_sha256": "8fc22a9f31868e281a471c07069eb5d89421f1c9444290b99bc798057fe7c34a" } 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