Onboard a new app¶
Create an App CR and get a governed namespace: perimeter, quotas, and governance defaults applied by the platform, not by you. This is the manual path for app owners; the full prompt-to-running-app flow is the first governed app tutorial.
Preconditions¶
- A running platform (
make verify-platformgreen, or the local path). kubectlaccess with permission to createapps.tendtech.ioresources intend-system.
Steps¶
1. Write the minimal App CR¶
Only the boundary tier is needed from you:
apiVersion: tendtech.io/v1alpha1
kind: App
metadata:
name: expense-helper
namespace: tend-system
spec:
tier: tier1
2. Apply it¶
At admission, the app-field-defaults mutate policy fills in every
governance field you left out, using the GitOps-delivered policy-defaults
ConfigMap (namespace kyverno):
| Field | Defaulted to |
|---|---|
spec.owner |
your identity (the applying user) |
spec.expiry |
now + 90 days (defaultTTL: 2160h) |
spec.dataScopes |
[{name: synthetic, sourceType: synthetic, access: readwrite}] |
spec.resourceCaps |
cpu: "1", memory: "1Gi" |
spec.costCap |
50.00 EUR, monthly |
spec.llmBudget |
10.00 USD, monthly |
spec.purpose is never defaulted. It stays empty until you set it, and
promotion refuses without it — see
Promote an app to production.
Verify it worked¶
kubectl get app expense-helper -n tend-system
# STATE=sandbox, OWNER=<you>, EXPIRY=<now+90d>
kubectl get app expense-helper -n tend-system \
-o jsonpath='{.status.state} {.status.namespace}'
# sandbox tend-app-expense-helper
kubectl get app expense-helper -n tend-system \
-o jsonpath='{range .status.conditions[*]}{.type}={.status} {end}'
# expect Ready=True and Isolated=True among the conditions
The operator has rendered the generated perimeter and caps into the app namespace — you never write these objects yourself:
kubectl get ciliumnetworkpolicies,resourcequota,limitranges \
-n tend-app-expense-helper
# ciliumnetworkpolicy/tend-default-deny
# ciliumnetworkpolicy/tend-allow-platform-gateways
# ciliumnetworkpolicy/tend-allow-edge-ingress
# resourcequota/tend-resource-caps
# limitrange/tend-limit-defaults
Every one of them carries the provenance label
tendtech.io/generated-by=tend-operator (make policy-provenance asserts
this cluster-wide). Field semantics live in the
App CRD reference; the perimeter shape is rendered
by the operator and its decision is recorded in
ADR-0007.
Getting a workload into the namespace¶
A bare App CR provisions a governed (empty) namespace. To also generate, build, attest, and deploy an app from a description, use the builder path:
It needs the builder environment set (GATEWAY_URL, OIDC_TOKEN_URL or
KEYCLOAK_URL+OIDC_REALM, OIDC_CLIENT_ID, OIDC_CLIENT_SECRET,
GITEA_URL, GITEA_TOKEN) — the
first governed app tutorial walks it end to end.
Troubleshooting¶
Isolated=False— the Cilium CRD is absent (for example on the GitOps-less local path). Reconciliation still progresses, but the network perimeter is not enforced there; attestation and isolation are only verified on the full stack.- Namespace missing — check the operator logs in
tend-system; the namespace is created by the App reconciler, not by admission.