Repository navigation
feat(gitops): a render refuses what the cell's admission would, and a publish holds a tree to its declaration - #1290
Merged
Conversation
… publish holds a tree to its declaration
Three defects reached a cell through every gate in one day. Each was
visible from the rendered tree alone, and nothing in the render path looked.
1. An exec probe. A service's agent rendered `livenessProbe.exec`; the cell's
execution-admission policy refuses a pod with an exec hook or probe
("a command of the delivering party's choosing inside the pod that already
holds the workload identity"), so the workload ran with zero replicas for a
day while render, doctor and the promotion's checks were all green. The
cell derivation now refuses such a workload by container and field
(refuseUnadmittedExecution), and a pod template opting out of the mesh
with it: the two rules of that policy that read only the pod template.
The cell file this render writes is what generates the policy, so a
workload it would describe and the policy would refuse is refused here.
2. A tree of a module the workspace no longer composes. A solution withdrawn
from the composition kept its rendered tree, and a module nothing pinned
kept one from an earlier composition. deriveCell walked the modules
directory and described every tree for the environment, so the cell file
approved what the composition had withdrawn; once a cell file was derived
without one, the cell refused that tree's pods while the delivery still
ran them. refuseUncomposedRender names the tree for removal; with
refuseUnrenderedModules the rendered trees and the composed modules are
now the same set.
3. A tree rendered before the environment's declaration changed. A commit
moved a service's service-config and service-identity rows and nothing
compared the rendered tree with the declaration it came from, so the
delivery branch ran the pod on the value before the change. The inventory
now records a digest of those rows for the module's services
(environmentDeclarationDigest, beside the workspace configuration group
digests), and publish refuses a tree whose stamp is not the environment's
current one, naming the module and the render that lifts it. The services
are read from the inventory at both ends, so a tree is never refused for a
service the publish could not see; a tree with no stamp is held to nothing.
The byte-identical fixture digest moves with the new inventory field, as it
has for every inventory change before it; both cases still agree.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Review found the mesh opt-out check a false pass for CronJobs: the template metadata was read at spec.template, and a CronJob keeps its pod template under spec.jobTemplate.spec.template, so an opt-out label there passed the render and would be refused by the cell at run time. The metadata is read through podTemplate, as the pod spec already was, and the opt-out test adds a CronJob. Also drops a stray context import from the declaration test and states that solution units are outside the declaration digest. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
antoinetoussaint-byte
enabled auto-merge
November 4, 2026 04:43
antoinetoussaint-byte
added a commit
that referenced
this pull request
Nov 4, 2026
#1290 made the derivation refuse a tree of a module the workspace does not compose and ask for its removal. The prune now runs before the derivation, so a render satisfies that hold by removing the tree rather than skipping it; the hold stays for any derivation nothing pruned first, and its test asserts it there. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
antoinetoussaint-byte
added a commit
that referenced
this pull request
Nov 4, 2026
#1290 made the derivation refuse a tree of a module the workspace does not compose and ask for its removal. The prune now runs before the derivation, so a render satisfies that hold by removing the tree rather than skipping it; the hold stays for any derivation nothing pruned first, and its test asserts it there. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This was referenced Nov 4, 2026
Closed
Closed
Closed
Merged
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.
Three escapes, one seam
Three defects reached a cell (obin-ai/platform-obin, env blue) through every gate on 2026-11-03. Each was visible from the rendered tree alone; nothing in the render path looked.
livenessProbe.exec; the cell's execution-admission policy refuses an exec hook/probe, so the pod ran 0 replicas for a daydeploy gitops render(the cell derivation is what generates that policy)renderedContainerread only name and image; no rule of the policy was mirrored in the render pathrefuseUnadmittedExecution: the two policy rules that read only the pod template (exec hooks/probes; mesh opt-out labels/annotations), refused by container and fielddeploy gitops renderderiveCelldescribed every tree for the environment, whatever the workspace composes; only the converse (refuseUnrenderedModules) existedrefuseUncomposedRender: a tree of a module the workspace does not compose refuses the cell file and names the tree for removal; rendered trees and composed modules are now the same setservice-config/service-identityrows after its tree was rendered; nothing compared the tree with the declaration it came fromdeploy gitops publish(as the workspace-configuration-group hold already does)environmentDeclarationDigeststamped in the inventory (Targetrenders),refuseStaleDeclarationat publish; services read from the inventory at both ends so a tree is never refused for a service the publish could not see; an unstamped tree is held to nothingTests (fail before, pass after)
TestCellFileRefusesAnExecProbeTheCellWouldRefuse(liveness/startup/postStart exec refused; an httpGet probe admitted)TestCellFileRefusesAPodThatOptsOutOfTheMeshTestCellFileRefusesATreeOfAModuleTheWorkspaceDoesNotComposeTestTheDeclarationDigestFollowsTheModulesOwnRows,TestAPublishRefusesATreeRenderedBeforeTheDeclarationMovedgo test ./pkg/gitops/passes locally.What this does to a cell carrying the defects today
The next
render --allwith this CLI refuses blue until (1) the parse agent's exec probe is an HTTP/TCP/gRPC probe (obin-ai/service-parsetemplates/deployment/kustomize/base/deployment.yaml.tmpl:81) and (2) the proposals and compute trees are removed from the environment's modules directory. That is the gate working; both refusals name the exact tree/container.Classification: fixes at the owner of the render path. Not done here: the probe itself (service-parse), the tree removals (platform-obin), and a
doctor --envreport of the declaration stamp (the publish hold is the gate; doctor is a follow-up).🤖 Generated with Claude Code