Governance model: contract, not code¶
The central design bet of Tend is that AI-generated application code is never reviewed for safety — and never needs to be. Instead, every app, however it was built, runs under the same platform-enforced runtime contract. The platform team reviews the contract once instead of reviewing every app's code. This is what makes user-built software safe at enterprise scale without a static-analysis gate on generated code (Principle II).
The contract¶
An app declares its needs on its App CR; the platform enforces exactly that and denies everything else:
flowchart TB
subgraph declared["Declared on the App CR"]
S[Data scopes]
C[Resource + cost caps]
P[Purpose classification]
O[Owner + expiry]
end
subgraph enforced["Enforced at the platform layer"]
DG["Data gateway\nper-request scope decisions,\nundeclared access → 403"]
NP["Cilium perimeter\ndefault-deny, egress only to the two gateways,\nKeycloak's token endpoint, DNS,\nand the app's own namespace"]
KY["Kyverno admission\nregistry-only images,\nno embedded secrets,\nworkloads within caps,\nattestation verified"]
RQ["ResourceQuota / LimitRange\nrendered from declared caps"]
CO["Cost reconciler\nwarn at 75% / 90%,\nsuspend at breach"]
end
S --> DG
O --> KY
C --> RQ
C --> CO
declared -.->|"rendered by the operator,\nnever hand-written"| enforced
Five clauses, from the constitution:
- Declared data scopes are enforced at the data gateway; undeclared access is denied per request.
- Default-deny networking; only declared ingress and egress exist. In practice v1 goes further: the perimeter is generated with a static shape (the two gateways, the identity provider's token endpoint, and DNS), so free-form egress is not even declarable.
- Dependencies resolve exclusively through the internal registry (Harbor); external-registry images are refused at admission.
- Credentials are injected at runtime; apps with embedded secrets are rejected at admission.
- Resource and cost caps are enforced, with throttle or suspend on breach.
Why not review the code?¶
Reviewing generated code puts an engineer back in the loop — exactly the bottleneck Tend exists to remove — and it doesn't scale with the volume or the churn of AI-built apps. Worse, it creates false confidence: a review gate implies the reviewed code is trusted, which invites privilege. The contract model inverts this: the code is never trusted, so nothing depends on its quality. A malicious or broken app can only do what its declared contract allows, and every attempt beyond it is denied and logged as evidence.
Three properties make the contract credible:
Generated, not authored. Perimeters, quotas, and defaults are rendered by the operator from the App CR. No hand-written per-app policy objects exist, so there is no drift between "what was declared" and "what is enforced" — and no bespoke exception can creep in through a manually edited policy.
Fail closed, everywhere. Gateway errors deny. An unverifiable attestation refuses admission. A gateway that cannot write its access log refuses to serve ("can't log → don't serve"). The one deliberate exception runs the other way: missing cost telemetry never enforces — an app is never punished because OpenCost was unreachable (ADR-0012).
Proven by counter-example. Nearly every policy ships with a violating manifest that must be rejected in CI, and the Kyverno gate fails the build if a ClusterPolicy has no counter-example directory. Sandbox isolation is proven by probes that must fail; the attestation gate is proven by an unattested image being refused.
Three limits on that sentence, because it is the load-bearing one:
- Two per-app Cilium policies have no counter-example at all —
edge-ingress-allowandtekton-build-confinement— and the first is rendered into every app namespace. - The attestation gate's admit direction does not run in CI. The refusal half runs; admitting a correctly signed image needs a signed fixture and runs only in the full quickstart.
- The workflow carrying these proofs is path-filtered. A green check means the gate blocked when the change touched a watched path, not on every pull request — and that filter has been wrong three times, twice letting a policy change merge with no policy job run at all.
Closing all three is open work.
Where each clause lives¶
| Contract clause | Enforcement point | Reference |
|---|---|---|
| Data scopes | Data gateway, per request | Data gateway API |
| Network perimeter | CiliumNetworkPolicy, per namespace, operator-rendered | ADR-0007 |
| Registry-only, no secrets, caps, defaulting | Kyverno ClusterPolicies at admission | ADR-0006 |
| Attestation required | Kyverno verifyImages at admission |
Evidence chain |
| Resource caps | ResourceQuota/LimitRange at namespace reconcile | App CRD |
| Cost caps | Operator cost reconciler ← OpenCost | App lifecycle |
The governance plane itself is governed: the policy baseline is versioned in git and delivered by Argo CD like everything else (Principle VI) — a policy change is a reviewable diff, not a kubectl apply.