Files
home-network-k3s-impl/platform/kyverno/admission
jakman85andClaude Opus 5 c5b5b8672a
gate / gate (pull_request) Failing after 1m51s
gate / conformance (pull_request) Has been skipped
feat(pm-agent): an in-cluster AI Program Manager that turns Gitea issues into pull requests
A service that reads this repository's Gitea issues, decides what to do about each
thread as the Program Manager persona, and runs one worker agent per assignment that
authors a change, runs the merge gate and opens a pull request. It reacts to issue
creation and to comments; the assignment and all correspondence travel through the
issue thread and the PR. It authenticates with an Anthropic subscription token. It
never pushes to main and never merges.

Three choices carry the design, with alternatives recorded in docs/plans/:
 - it POLLS rather than receiving webhooks (Gitea's webhook SSRF guard, lost
   deliveries, and no inbound reach needed at all);
 - it keeps NO state: the trigger is "the newest thing in this thread was not
   written by me", so the issue thread is the state — no PVC, no backup obligation;
 - the model holds NO tools: its reply is one JSON object this code validates, so
   nothing in the path executes text.

The boundary is platform/kyverno/admission/pm-agent-job-shape.yaml (Enforce,
failurePolicy: Fail), not the RBAC: Kubernetes places no `use` check on
serviceAccountName, so "may create Jobs" is "may run arbitrary code as the
namespace's most privileged identity". Six rules admit only the committed shape, and
the worker identity is bound to nothing with no token mounted, so there is nothing to
escalate to. 28/28 offline Kyverno assertions.

Nothing has run: the image has never been built or pushed, and both the image digest
and the two credentials are deliberate placeholders. See the handoff entry's
"What I did NOT verify".

Refs CLAUDE.md §1/§3/§6, R-SEC-02, R-GITOPS-02.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
2026-10-05 22:28:10 -05:00
..

In-cluster admission enforcement (scaffolding — Phase 2 / T-2.7)

Installs Kyverno and runs the same L0 policies as an in-cluster admission controller, so a non-conforming resource that somehow bypassed CI still cannot be admitted (defense in depth — docs/07, ADR-0011). Not applied in Phase 0 (no cluster exists yet); this is scaffolding wired up in task T-2.7.

Enforcement COMPLEMENTS, never REPLACES, behavior tests

A policy admitting a manifest is not proof the runtime behaves (docs/14 principle 1, R-TEST-01). Kyverno confirms a resource is shaped correctly; it does not prove default-deny actually blocks a packet, that the VPN kill-switch fails closed, or that a PVC survives a rebuild. Those are proven only by the L2/L3 Chainsaw behavior and fault-injection tests (conformance/, ADR-0011), which remain mandatory. Admission is a gate, not a guarantee of behavior.

Authored once, shared

kustomization.yaml references the policy files in ../policies/ verbatim — the identical objects the CI kyverno test gate validates — plus the Kyverno install. No policy is forked between CI and admission, with one deliberate exception:

The one deliberate CI vs admission divergence — Secrets

../policies/disallow-plaintext-secrets.yaml (CI) requires a top-level sops block on the Secret manifest. Flux decrypts SOPS before admission, so that block is gone by the time the API server sees the Secret — the CI policy cannot run in-cluster. The admission equivalent is secret-provenance.yaml, which enforces provenance (Secret came from Flux / is an exempt controller Secret) instead of ciphertext. This is escalated in the T-0.5 report because docs/07's literal wording ("reject a plaintext Secret at admission") is not achievable post-decrypt.

Operational note (from ADR-0011)

Admission enforcement adds a failure mode: a bad policy can block legitimate reconciliation. Mitigations: policies ship with their own kyverno test suite (this directory's ../tests), roll out via GitOps, and the webhook failurePolicy: Fail is chosen so the system fails closed (coordination-protocol.md #8) — validate for bootstrap deadlocks in dev/test before prod.