feat(binjovi): run one BuildKit daemon for Change and Release #405

Merged
binjovi-bot merged 2 commits from feat/binjovi-single-buildkit into trunk 2026-09-07 12:52:14 +00:00
Owner

Merges the Binjovi admission and release BuildKit lanes into one daemon.

Why. The split existed so untrusted Change code could not poison the cache feeding a signed Release. That threat model does not describe this cluster: every committer is authenticated and binjovi-bot is the only merge identity, so a Change carries the trust of the trunk it targets. buildctl du showed 15.26 GB on release and 18.34 GB on admission, including the same 2.57 GB layer twice.

Additive for now. The merged daemon stands up alongside the two it replaces; sean/binjovi still points both lanes at the old addresses, so the cutover and the removal are later commits.

The CA becomes a ClusterIssuer. The daemon is in binjovi-builds but binjovi-agent is in workflows, a Secret cannot be mounted across namespaces, and both clients must present a certificate the one CA signed.

It does NOT widen binjovi-untrusted-credential-guard. Dry-running its CEL against the live binjovi-builds namespace denied 12 running pods — native package agents legitimately mounting binjovi-native-*-build-s3 as default, caught by the packageCandidateCredential rule, which is not gated on the untrusted label. With failurePolicy: Fail that is a Binjovi-wide outage, and it is the same over-capture recorded in the policy's own comments from 2026-09-02. The reasoning is in the manifest header so the next reader does not walk into it.

The merged daemon adopts the stricter posture package and ibmi-rpg already carry (untrusted label, binjovi-build-untrusted, no mounted token) which release did not have. Package and ibmi-rpg stay separate — split by egress profile, not trust.

Scheduling note. Four persistent-cache pods currently occupy four of five workers; the fifth daemon lands on the free node with zero slack until the retirement commit removes two.

tests/binjovi-buildkit.sh added, verified against six mutations. tests/check.sh green.

https://claude.ai/code/session_01KZoQin34jeyt6nDGqvJA76

Merges the Binjovi admission and release BuildKit lanes into one daemon. **Why.** The split existed so untrusted Change code could not poison the cache feeding a signed Release. That threat model does not describe this cluster: every committer is authenticated and `binjovi-bot` is the only merge identity, so a Change carries the trust of the trunk it targets. `buildctl du` showed 15.26 GB on release and 18.34 GB on admission, including the same 2.57 GB layer twice. **Additive for now.** The merged daemon stands up alongside the two it replaces; `sean/binjovi` still points both lanes at the old addresses, so the cutover and the removal are later commits. **The CA becomes a ClusterIssuer.** The daemon is in `binjovi-builds` but `binjovi-agent` is in `workflows`, a Secret cannot be mounted across namespaces, and both clients must present a certificate the one CA signed. **It does NOT widen `binjovi-untrusted-credential-guard`.** Dry-running its CEL against the live `binjovi-builds` namespace denied **12 running pods** — native package agents legitimately mounting `binjovi-native-*-build-s3` as `default`, caught by the `packageCandidateCredential` rule, which is not gated on the untrusted label. With `failurePolicy: Fail` that is a Binjovi-wide outage, and it is the same over-capture recorded in the policy's own comments from 2026-09-02. The reasoning is in the manifest header so the next reader does not walk into it. The merged daemon adopts the stricter posture package and ibmi-rpg already carry (untrusted label, `binjovi-build-untrusted`, no mounted token) which release did not have. Package and ibmi-rpg stay separate — split by egress profile, not trust. **Scheduling note.** Four persistent-cache pods currently occupy four of five workers; the fifth daemon lands on the free node with zero slack until the retirement commit removes two. `tests/binjovi-buildkit.sh` added, verified against six mutations. `tests/check.sh` green. https://claude.ai/code/session_01KZoQin34jeyt6nDGqvJA76
Binjovi ran two persistent BuildKit daemons so that untrusted Change code
could not poison the cache that fed a signed Release. That threat model does
not describe this cluster: every committer is an authenticated user and
binjovi-bot is the only merge identity, so a Change carries the trust of the
trunk it targets. The split bought duplication -- buildctl du reported
15.26 GB on release and 18.34 GB on admission, including the same 2.57 GB
layer twice.

This adds the merged daemon alongside the two it replaces. Nothing is removed
here: sean/binjovi still points both lanes at the old addresses, so the
cutover is a later commit once the control plane has moved.

The CA becomes a ClusterIssuer. The daemon runs in binjovi-builds but
binjovi-agent runs in workflows, a Secret cannot be mounted across namespaces,
and both clients must present a certificate the daemon's one CA signed.

The merged daemon adopts the stricter posture the package and ibmi-rpg
daemons already carry -- the untrusted label, binjovi-build-untrusted, and no
mounted token -- which release did not have.

It does NOT widen binjovi-untrusted-credential-guard to binjovi-builds. That
guard's packageCandidateCredential rule is not gated on the untrusted label,
so it polices every pod in the namespace it covers. Dry-running the policy
against the live namespace denied 12 running pods, all native package agents
legitimately mounting binjovi-native-*-build-s3 as the default identity; with
failurePolicy Fail that is a Binjovi-wide outage. The same over-capture is
recorded in the policy's own comments from 2026-09-02. Scoping those ungated
rules is its own change.

The Zelnet package and IBM i RPG daemons stay separate. They are split by
egress profile, not trust, and share almost no cache.

Claude-Session: https://claude.ai/code/session_01KZoQin34jeyt6nDGqvJA76
docs(binjovi): say why the package daemon survived the lane merge
All checks were successful
binjovi/ci Binjovi completed the frozen plan
719b20fa4d
The header claimed the cache does not share state with "Binjovi admission or
image Release". Those two lanes became one daemon on 2026-09-07, so the
sentence named objects that no longer exist and left the real reason for this
daemon unstated. It is separate because of its egress profile -- TN3270 to
gibson and world 23/992 -- not because of trust.

Claude-Session: https://claude.ai/code/session_01KZoQin34jeyt6nDGqvJA76
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
sean/seanfarm!405
No description provided.