From e5500207255627895146b54b3df683c6588d8a36 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 22 Sep 2026 03:33:02 +0900 Subject: [PATCH 1/5] test(actions): bind centralized hourly admission contract (#647) --- tests/quality/test_hourly_nim_product_development.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/quality/test_hourly_nim_product_development.py b/tests/quality/test_hourly_nim_product_development.py index e2a1a03a0..5864465a7 100644 --- a/tests/quality/test_hourly_nim_product_development.py +++ b/tests/quality/test_hourly_nim_product_development.py @@ -37,12 +37,12 @@ class HourlyNimProductDevelopmentContractTests(unittest.TestCase): """Structural tests for the credential-separated product-development loop.""" def test_hourly_workflow_schedule_credentials_and_queue_gate(self) -> None: - """Run at minute 47 with provider discovery and fail closed around inventory.""" + """Require central admission and fail closed around inventory and credentials.""" text = _text(WORKFLOW) bootstrap = _text(BOOTSTRAP) for token in ( - 'cron: "47 * * * *"', + "# cwl-org-commercial-entrypoint: v1", "workflow_dispatch:", "dry_run:", "hourly-nim-product-development-${{ github.repository }}", @@ -79,6 +79,8 @@ def test_hourly_workflow_schedule_credentials_and_queue_gate(self) -> None: self.assertIn(token, text) for token in ("discover_all_models", "register_credential", "PROVIDER_CREDENTIAL_NAMES"): self.assertIn(token, bootstrap) + self.assertNotIn("\nschedule:", text) + self.assertNotIn("cron:", text) self.assertNotIn("COPILOT_GITHUB_TOKEN", text) self.assertNotIn("CONTEXTUAL_ORCHESTRATOR_TOKEN=", text) self.assertEqual(text.count("gh pr create"), 1) @@ -278,6 +280,7 @@ def test_hourly_queue_reflects_current_open_inventory(self) -> None: for pull_request in (93, 94, 97, 101, 102, 104, 108, 109, 111, 112): with self.subTest(pull_request=pull_request): self.assertNotIn(f"PR #{pull_request}", runbook) + def test_bootstrap_registers_each_provider_key_and_removes_environment_values(self) -> None: """Exercise the real bootstrap loop with a key-counting KV double.""" @@ -435,4 +438,4 @@ def __init__(self, auth_token: str) -> None: if __name__ == "__main__": - unittest.main() + unittest.main() \ No newline at end of file From 482388d525a3c59aae3ab40adfb4374f4c974076 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 22 Sep 2026 03:33:36 +0900 Subject: [PATCH 2/5] docs(actions): document central hourly cadence ownership (#647) --- .../HOURLY_NIM_PRODUCT_DEVELOPMENT.md | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/docs/operations/HOURLY_NIM_PRODUCT_DEVELOPMENT.md b/docs/operations/HOURLY_NIM_PRODUCT_DEVELOPMENT.md index cd78f1ca8..820f235f2 100644 --- a/docs/operations/HOURLY_NIM_PRODUCT_DEVELOPMENT.md +++ b/docs/operations/HOURLY_NIM_PRODUCT_DEVELOPMENT.md @@ -6,12 +6,13 @@ issue. It is separate from the deterministic minute-17 quality sentinel and never merges, releases, deploys, approves, or changes reviewer credentials. -## Schedule and queue behavior +## Admission and queue behavior -`.github/workflows/hourly-nim-product-development.yml` runs at minute 47 of every -hour and supports `workflow_dispatch` with `dry_run=true`. The nonzero minute -avoids the busiest scheduler boundary. A repository-scoped concurrency group -does not cancel an active run. +`.github/workflows/hourly-nim-product-development.yml` is the TEPP dispatchable +commercial entrypoint and supports `workflow_dispatch` with `dry_run=true`. +Recurring cadence is supplied by the central CWL scheduler/admission owner; the +repository workflow intentionally has no local `schedule` or `cron` trigger. A +repository-scoped concurrency group does not cancel an active run. Before checkout or model execution, the proposal job reads at most one open pull request and one open issue. Unreadable inventory, any open PR or issue, any @@ -55,7 +56,7 @@ Do not place GitHub App credentials in the proposal or verifier jobs. Do not reuse the existing review App or alter its variable, secret, identity, or provider route. Do not configure `COPILOT_GITHUB_TOKEN`. -A manual dry run verifies scheduling, queue, and prompt contracts without model +A manual dry run verifies admission, queue, and prompt contracts without model or publication credentials. Missing production credentials leave the hourly developer disabled rather than falling back to `GITHUB_TOKEN`. @@ -160,10 +161,12 @@ write token. ## Disablement and rollback -Disable scheduled development by disabling the workflow, removing its schedule, -or removing any one of the five provider credentials. Removing any provider key -stops model execution; removing the Maintainer App values stops publication. -The minute-17 deterministic quality sentinel continues independently. +Recurring cadence is disabled at the central CWL scheduler/admission owner; the +TEPP repository workflow owns no local schedule to remove. Repository-side +execution can be disabled by disabling the workflow or removing any one of the +five provider credentials. Removing any provider key stops model execution; +removing the Maintainer App values stops publication. The minute-17 deterministic +quality sentinel continues independently. Rollback a faulty workflow through a reviewed revert PR. Do not edit branch protection, review workflows, or release workflows as an incident shortcut. @@ -177,7 +180,7 @@ references them. inference broker could keep upstream secrets outside the runner. - Each configured provider may process repository source; operators must review confidentiality, retention, regional, and contractual obligations for every - provider before enabling the schedule. + provider before enabling the centrally owned cadence. - The verifier executes untrusted code on an ephemeral hosted runner with outbound network access, but receives no publication, provider, OIDC, artifact/cache runtime, command-file, or reviewer credential. From 844b06b343e844fffd89b13af347a54f6b4ae005 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 22 Sep 2026 03:34:46 +0900 Subject: [PATCH 3/5] docs(changelog): record centralized hourly admission repair (#647) --- CHANGELOG.d/central-hourly-admission-contract.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 CHANGELOG.d/central-hourly-admission-contract.md diff --git a/CHANGELOG.d/central-hourly-admission-contract.md b/CHANGELOG.d/central-hourly-admission-contract.md new file mode 100644 index 000000000..b6bc32144 --- /dev/null +++ b/CHANGELOG.d/central-hourly-admission-contract.md @@ -0,0 +1 @@ +- The hourly commercial-development quality contract now follows the protected-main centralized admission boundary: `cwl-org-commercial-entrypoint: v1` plus repository-local `workflow_dispatch`/`dry_run` remain required, while repository-local `schedule`/`cron` triggers are explicitly forbidden. The operations runbook now assigns recurring cadence and disablement to the central CWL scheduler/admission owner without changing TEPP workflow credentials, queue gates, verification, or late-publication controls. From 0be133ae0e0a58c1a0f88a8c59df839eae971ead Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 22 Sep 2026 03:37:31 +0900 Subject: [PATCH 4/5] test(actions): refuse any repository-local schedule trigger (#647) --- tests/quality/test_hourly_nim_product_development.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/quality/test_hourly_nim_product_development.py b/tests/quality/test_hourly_nim_product_development.py index 5864465a7..68d04d688 100644 --- a/tests/quality/test_hourly_nim_product_development.py +++ b/tests/quality/test_hourly_nim_product_development.py @@ -79,7 +79,7 @@ def test_hourly_workflow_schedule_credentials_and_queue_gate(self) -> None: self.assertIn(token, text) for token in ("discover_all_models", "register_credential", "PROVIDER_CREDENTIAL_NAMES"): self.assertIn(token, bootstrap) - self.assertNotIn("\nschedule:", text) + self.assertNotIn("schedule:", text) self.assertNotIn("cron:", text) self.assertNotIn("COPILOT_GITHUB_TOKEN", text) self.assertNotIn("CONTEXTUAL_ORCHESTRATOR_TOKEN=", text) @@ -438,4 +438,4 @@ def __init__(self, auth_token: str) -> None: if __name__ == "__main__": - unittest.main() \ No newline at end of file + unittest.main() From 5094c06056a80a87b4b0e935c3c25dbd6e0e2493 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 13 Oct 2026 23:14:33 +0900 Subject: [PATCH 5/5] fix(deps): compose verified rustls advisory repair onto hourly PR648 Reuse exact Cargo and changelog bytes from PR526@04ef5a46 and PR538@5f070a6c. Primary RustSec record requires >=0.23.45. Preserve deny.toml unchanged; no exemptions or coverage threshold changes. Local candidate only. --- CHANGELOG.d/rustls-tls-handshake-advisory.md | 6 ++++++ Cargo.lock | 4 ++-- Cargo.toml | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) create mode 100644 CHANGELOG.d/rustls-tls-handshake-advisory.md diff --git a/CHANGELOG.d/rustls-tls-handshake-advisory.md b/CHANGELOG.d/rustls-tls-handshake-advisory.md new file mode 100644 index 000000000..662aa6f8f --- /dev/null +++ b/CHANGELOG.d/rustls-tls-handshake-advisory.md @@ -0,0 +1,6 @@ +# rustls TLS 1.3 handshake advisory repair + +- The workspace `rustls` pin moves from `=0.23.43` to `=0.23.45`, clearing RUSTSEC-2026-0285 / GHSA-2mjx-qc3c-rqvc, whose affected TLS 1.3 path could accept handshake messages across encryption-level boundaries. +- The pin reaches TEPP through `service_tls` directly and through `sqlx-core`, so this is a repository-wide dependency-policy prerequisite rather than a leaf TLS-only change. +- `CVE-2025-61730` is intentionally not attributed to `rustls`; the RustSec advisory mentions it only as the functionally similar Go `crypto/tls` issue. +- This fragment preserves the security release note while #526 remains stacked on #523; the surviving root changelog can absorb it after the parent lands without carrying the former incorrect CVE attribution. diff --git a/Cargo.lock b/Cargo.lock index 454a7d612..1b4fed0cd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1446,9 +1446,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustls" -version = "0.23.43" +version = "0.23.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0283386ce02abc0151e1761d08802dfe86c173b0b494af5cbc086574e453da06" +checksum = "0d41d731c7d2f962d1ccc364cec258de3c0e93b38c2fb3ba97ac74513048d634" dependencies = [ "once_cell", "ring", diff --git a/Cargo.toml b/Cargo.toml index dac992821..b8da76d0b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -143,7 +143,7 @@ sha2 = { version = "=0.10.9", default-features = false } uuid = { version = "=1.24.0", features = ["serde", "v7"] } tokio = { version = "=1.47.1", default-features = false, features = ["rt-multi-thread", "macros", "time"] } sqlx = { version = "=0.8.6", default-features = false, features = ["runtime-tokio", "postgres", "tls-rustls-ring-webpki"] } -rustls = { version = "=0.23.43", default-features = false, features = ["std", "tls12", "ring"] } +rustls = { version = "=0.23.45", default-features = false, features = ["std", "tls12", "ring"] } [workspace.lints.rust] unsafe_code = "deny"