Skip to content

Preserve system-test root keys across certificate reissuance - #16377

Merged
agentydragon merged 1 commit into
agentydragon:develfrom
agentydragon-agent:agent/system-test-root-key
Nov 14, 2026
Merged

agentydragon merged 1 commit into
agentydragon:develfrom
agentydragon-agent:agent/system-test-root-key

Conversation

@agentydragon-agent

@agentydragon-agent agentydragon-agent commented Nov 14, 2026 •

Copy link
Copy Markdown
Contributor

The system-test root CA can reissue while its workload intermediate is already serving. With cert-manager’s default rotating-key policy, that replaces the root key and invalidates the existing intermediate: Runtime exits before the sampler-roll test reaches its scenario. Keep the root key through reissuance, as the intermediate already does. Fixture cleanup still deletes its Secret between actions.

Extend the real-controller PKI lifecycle test to force a root reissuance, check its key stays stable, and verify the already-issued intermediate against the renewed root in both cold and warm cycles.

This fixes the independent PKI failure exposed by #16372. That suite already omitted App token_subjects before the PR and uses an operator ID token for its App client; its Kubernetes tokens authenticate backend RPCs. Recent devel target history passed, including b6ee69d (cc0ee7e5-5034-5e93-8356-1678bcf294f5, 182.5s). The failing run’s captured intermediate verifies against its earlier issuing root and fails against root revision 2. No remaining special-agent-token caller was found in this suite.

Validation: scoped pre-commit and commit hooks passed. bbr build //agentplane/system_tests/deployment:fixture_chart passed (c93ec4c0-68ba-4a10-80bf-bd5ef4d662c7). bbr test //agentplane/system_tests/deployment:test_pki_lifecycle //agentplane/system_tests/suites/mcp:test_sampler_roll passed (050ba465-5a0f-4de7-a6c8-856e4113a572), including the forced-renewal assertion against the real cert-manager controllers.

Deliberately leaves out production CA changes and all auth rollout sequencing. There are no production traffic or diagram changes. Rollback: revert this fixture-only change; staging is unaffected. Confirm PKI lifecycle and sampler-roll tests before using the reverted fixture.

Questions for Claude

None.

@agentydragon
agentydragon enabled auto-merge (squash) November 14, 2026 07:57
@agentydragon
agentydragon merged commit 8b0021e into agentydragon:devel Nov 14, 2026
10 checks passed
agentydragon pushed a commit that referenced this pull request Nov 14, 2026
Staging no longer writes an App `token_subjects` allowlist. The field
and TokenReview path remain supported; omission uses the App's empty
default, which accepts no Kubernetes token caller.

## Compatibility evidence

- At the start of this work, staging pinned
`agentplane-app:devel-20261114070234-29f985c`, source commit
[`29f985c62698c841d97dbf96a5002ec7b8dbae24`](29f985c).
The current staging pin has since advanced to
`agentplane-app:devel-20261114071537-9e1f8fe`, source commit
[`9e1f8fe7fe1eb24e47e3cdd763849d9e9dc799a3`](9e1f8fe).
The relevant settings and Go loader files are identical at both commits.
- Both App revisions use `extra="forbid"` and declare `token_subjects`
with `default_factory=frozenset`. The Go loader accepts the missing
optional key and normalizes nil to an empty slice. A focused temporary
Bazel settings test removed the key from the YAML and passed; that
temporary test is not included here.
- The shared App settings model omits the field only when its value is
empty. Staging and direct deployment fixture synthesis tests assert that
the resulting YAML has no `token_subjects` key. `fixture_chart.py` did
not set the field explicitly.

## Rollout and rollback

After merge, Flux deploys the generated config without the allowlist;
the currently pinned App accepts the omission. Roll back by reverting
this PR and redeploying, which restores the explicit staging allowlist.
The App continues to accept both explicit `token_subjects` and omission.

## Deliberate omissions

This PR keeps the App model field, Go settings field, TokenReview
behavior, token audience, `agentplane-agent` ServiceAccount, and
token-request RBAC. Removing those requires a separate change after this
config rolls out. It does not change integration-test token fixtures.

## Validation

- `bbr test //cluster/cdk8s/agentplane:test_session_dispatcher
//agentplane/system_tests/deployment:test_render
//cluster/cdk8s:test_generate_manifests` passed (BuildBuddy invocation
`1ae29a82-195f-4830-b553-c88068970c61`).
- `bbr build //agentplane/app:settings` passed (invocation
`e3fa227b-2906-4461-a150-68b927ba7da7`).
- Scoped `pre-commit` checks passed.
- Local `bb run //cluster/cdk8s:generate_manifests` could not analyze
because this environment lacks `ldd`, required by Bazel's host-libc
detector. The remote generate-manifests test passed with the committed
two-line manifest removal.

## Questions for Claude

None.

CI diagnosis at `94c8277e`: `mcp:test_sampler_roll` failed before the
scenario, because Runtime could not verify its local certificate.
Captured certificates prove the workload CA was issued by the earlier
test root key, while root revision 2 held a different key. The same
suite already omitted App `token_subjects` before this PR; its App
client uses a fixture operator ID token, and its Kubernetes tokens
target backends. Recent devel history passed (b6ee69d,
`cc0ee7e5-5034-5e93-8356-1678bcf294f5`, 182.5s). No remaining
special-agent-token caller was found in that suite. #16377 (merged)
fixes the independent root-key churn and adds a real-controller renewal
regression; this PR now contains only the App manifest change on fresh
devel.

PKI correction validation: `bbr test
//agentplane/system_tests/deployment:test_pki_lifecycle
//agentplane/system_tests/suites/mcp:test_sampler_roll` passed
(`050ba465-5a0f-4de7-a6c8-856e4113a572`, 72.0s and 152.2s). Named
fixture library build passed (`c93ec4c0-68ba-4a10-80bf-bd5ef4d662c7`);
rebased scoped pre-commit passed.

After #16377 merged, rebased onto `8b0021e740` and dropped its included
commit. Current App-only head:
`d11f4db2a93a93b81427339cfb1a2a7b174802ec`. Scoped pre-commit (including
manifest consistency and kubeconform) and `git diff --check` passed.
Fresh devel still pins App `devel-20261114071537-9e1f8fe`; its
omission-compatible Go loader is unchanged. Previous-head Bazel CI
passed; fresh-head CI is pending.

Co-authored-by: agentydragon-agent <260791330+agentydragon-agent@users.noreply.github.com>
agentydragon pushed a commit that referenced this pull request Nov 14, 2026
Explicit `ResumeEnvironment` no longer reserves the shared wake budget,
for direct Pod-bound and service-SVID operator callers and Identity
resume grants. Automatic Dispatcher `RequestWake` alone reserves
`ReserveWakeAttempt`; authorization, operator-stop handling, generation
tokens and optimistic locking retain their existing behavior. This
implements the operator’s 2026-11-14 07:41 UTC decision, “No budget for
explicit resume,” recorded in [plan PR
#16368](#16368) at
`0675c37082`.

`TestExplicitResumeDoesNotReserveWakeBudget` exercises both caller paths
with exhausted and unavailable budget backends and requires successful
resume with zero reservations.
`TestEnvironmentServiceServiceRolesStayMethodScoped` checks a real mTLS
service operator resume succeeds with zero reservations; the
foreign-target Identity grant test also checks zero reservations.
Conflict and stale-token tests retain their coverage, with concurrent
requests synchronized at the Kubernetes patch boundary rather than
inside the budget fake.

Automatic wakes remain bounded:
`TestAutomaticWakeSharesPolicyBudgetAndReportsRetryFacts` still requires
rate limiting with retry facts when exhausted and refusal when the
backend is unavailable; Dispatcher’s
`TestMixedVersionWakeWritersShareCapAndGenerationDedup` and Store
integration tests cover durable shared reservations. Lifecycle SPEC,
README and interface comments now distinguish the two paths.

Validation:

- Changed-file pre-commit and all commit hooks passed (gofumpt applied
formatting first).
- `bbr test
//agentplane/runner_gateway/environments/lifecycle:lifecycle_test
//agentplane/runner_gateway/environments:environments_test
//agentplane/runner_gateway/dispatcher:store_integration_test
//agentplane/system_tests/suites:test_dispatcher --test_output=errors` —
all 4 passed
([45ead54e](https://app.buildbuddy.io/invocation/45ead54e-7d63-4603-837d-3ad3e388ce46));
3 executed, Dispatcher storage integration cached. The full Dispatcher
system suite passed in 228.3s and covers queue, automatic wake, delivery
and replica behavior. Full current-head GitHub CI pending.

Rollout: deploy/pin the Gateway behavior. No settings, manifests, schema
or wire contract changes, so no image-before-config ordering applies.
Independent of the identity-change fence PR #16373. Rollback: revert the
Gateway image pin; explicit resume again uses the existing budget.
Retain current Sandbox generations and budget rows. After Flux applies
the pin, check explicit resume and automatic queued wake, including
normal delivery and wake-budget retry facts.

Deliberately leaves out automatic-wake policy or limit changes,
settings/manifests, storage ownership or service extraction, Runtime
Identity defense, caller-authentication changes, and any new
cross-component call.

Rebased onto `9a955bd3` after Gateway service SVID admission #16364,
preserving its service roles and authentication behavior. Post-rebase
focused validation
([0fd41c23](https://app.buildbuddy.io/invocation/0fd41c23-f01e-45ce-9115-6f0652352163))
passed lifecycle, Dispatcher storage (cached), and the full Dispatcher
system suite (231.9s), but found the newly landed mTLS service-operator
test still asserting an explicit budget reservation. Commit `d63bccb9`
changes that assertion to zero reservations while retaining its
method-scoped authorization and desired-state checks. The corrected `bbr
test //agentplane/runner_gateway/environments:environments_test
--test_output=errors` executed and passed
([3fcea46b](https://app.buildbuddy.io/invocation/3fcea46b-f7c8-40f4-bb2d-b4f8d5f0c93a)).
Changed-file pre-commit and commit hooks passed. Full current-head CI
pending.

Latest rebase: head `9f01bc92f168218eb361383b6dd6c58b81224226` is based
on `a68e0de510d6ea10184705ab453a69259cb85801`, including service-SVID
admission and the system-test root-key renewal correction #16377. The
rebase was conflict-free; range-diff showed unchanged patches, and it
was published with `--force-with-lease`. GitHub confirms this head.
Current-head pre-commit, Nix and artifact/import checks passed; Bazel
and visual review are running, with no reported failures as of
2026-11-14 08:29 UTC. The focused RBE results above remain prior-base
validation. Fresh `origin/devel` is
`6e591f383864ab47d7a9370abb4bd6637f0faee3`; its two additional commits
change image pins and a Dispatcher documentation note, and GitHub
reports this PR mergeable.

## Questions for Claude

None.

---------

Co-authored-by: agentydragon-agent <260791330+agentydragon-agent@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants