feat(estate): name the identity the operating loop runs as, on the loop's own box (#357) - #385
Merged
Conversation
…op's own box (#357) The estate graph already showed the operating loop — an OperatorStack is a Namespace and a CronJob per ConvergeOp, so the loop draws as ordinary cards, and #324 marked its namespace box with a glyph. What the picture never said is the thing an operator actually asks: WHO it acts as. That identity is Kubernetes RBAC — the ServiceAccount the tick's pods run under, one per hosted ConvergeOp by OperatorStack's own least-privilege shape. It is read off the CronJob's pod spec, where the cluster reads it, rather than matched by label to a ServiceAccount card: a label match would agree with the truth by construction and disagree silently the moment a caller overrides `defs.cronJob`. `operatorIdentity` makes the home-level claim, and the three cases are genuinely different rather than one with holes: one every tick runs as the same account, and the box names it many the ticks run as N accounts — the ordinary shape — and the box says how many; the names are on the tick cards unknown no tick named one. Below detail 3 the IR carries no pod spec at all, so this is "not read", and it is reported as nothing rather than as `default`. Absence stays silent, which is what #357 asked for: a namespace with no loop is untouched, and a loop the projection never boxed gets no badge rather than an invented box. The badge needed a channel that did not exist. pinhole's `GroupBox.mark` (#119) is a glyph from a fixed vocabulary, and an identity is a name; the only way to put text on a box was its title, which #119 itself established is load-bearing because behold re-parses it. pinhole 0.3.8 adds `GroupBox.badge?: string` for exactly this (pinhole#122), and behold takes it: `renderArchitecture` gains `groupBadges`, keyed by container id like `groupMarks`, threaded through all four architecture call sites. Verified rendered: a one-tick loop's box reads "runs as staging-converge-sa" and a two-tick loop's reads "runs as 2 identities". Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0124XP1LJTZxgJRy7Dh1UfXt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #357. Takes pinhole 0.3.8 (INTENTIUS/pinhole#122), published for this.
What it answers
The estate already drew the operating loop and #324 marked its namespace with a glyph. The glyph says a loop lives here. This says who it acts as — "who is allowed to do this", readable off the picture instead of by opening a card.
The identity is Kubernetes RBAC, not IAM: the ServiceAccount the tick's pods run under.
OperatorStackgives each hosted ConvergeOp its own, which is why the home-level claim has three answers rather than one:runs as staging-converge-saruns as 2 identitiesThat last row matters. Below detail 3 the IR carries no pod spec, so "no account named" means not read, not
default. Reportingdefaultthere would be a claim about the cluster that behold has not earned. Absence stays silent, which is what the issue asked for.Read where the cluster reads it
spec.jobTemplate.spec.template.spec.serviceAccountNameon the CronJob, not a label match to a ServiceAccount card. A label match agrees with the truth by construction and disagrees silently the moment someone overridesdefs.cronJob.The channel did not exist
GroupBox.mark(pinhole#119) is a glyph from a fixed vocabulary. An identity is a name, and the only way to get text onto a box was its title — which #119 itself established is load-bearing, because behold re-parsesnamespace <ns>to re-parent helm releases. So pinhole 0.3.8 addsGroupBox.badge?: string, purely additive, and behold takes it:renderArchitecturegainsgroupBadges, keyed by container id exactly asgroupMarksis, threaded through all four architecture call sites.Verified rendered
Tests
just checkgreen: 88 files, 1725 tests. The operator fixture gains the pod specOperatorStackreally emits; new cases cover the one/many/unknown claim, the badge wording, the box keyed by its structural id, and silence for a namespace with no loop, a loop with no box, and a loop below the spec tier.render.test.tscovers the plumbing, a mark and a badge coexisting, and byte-identical output with no badges.🤖 Generated with Claude Code
https://claude.ai/code/session_0124XP1LJTZxgJRy7Dh1UfXt