Daari Secrets
Daari Secrets are project-scoped key/value secrets you can bind to apps. They live alongside the LLM Gateway and Postgres entries in the Daari service catalog. Bound values appear in your app's container as part of the standard C2A_SYSTEM_ENV JSON.
| Surface | Where |
|---|---|
| Web | /daari → Secrets tab (pinned first). Deep link to detail: /daari/secrets/<k8sName> |
| CLI | c2a daari secrets ... |
| iOS | Daari tab → Secrets (read-only on iOS) |
CLI quick reference
# Create a secret with one or more key=value pairs
c2a daari secrets create stripe-prod --from-literal STRIPE_KEY=sk_live_xxx
c2a daari secrets create combo --from-literal KEY1=a --from-literal KEY2=b
# List secrets in the current project
c2a daari secrets list
# Show one (keys + metadata + bindings; values never echoed)
c2a daari secrets show 1768874379514-stripe-prod
# Rotate values — keys not in the rotate set are left alone
c2a daari secrets rotate 1768874379514-stripe-prod --from-literal STRIPE_KEY=sk_live_NEW
# See which apps are bound to this secret
c2a daari secrets bindings 1768874379514-stripe-prod
# Bind to an app (same primitive as c2a llm bind)
c2a daari secrets bind expense-backend 1768874379514-stripe-prod
# Delete (refuses if still bound — use --force to override)
c2a daari secrets delete 1768874379514-stripe-prod
What "bind" actually does
Binding routes the secret's keys + values through the platform's existing service-binding lifecycle:
- Coordinator reads the secret's decoded data
- Merges it into the per-app
<app>-service-bindingSecret'sC2A_SYSTEM_ENVJSON, keyed by the bound secret's display name - The ksvc reads
C2A_SYSTEM_ENVvia envFrom, so the new keys appear in the app's container env on the next pod start - By default, also restarts the ksvc so the binding is immediately live (
--no-restartto skip)
At runtime your app parses C2A_SYSTEM_ENV once at startup:
import json, os
c2a = json.loads(os.environ["C2A_SYSTEM_ENV"])
stripe = c2a["binding"]["stripe-prod"] # bound secret's display name
api_key = stripe["STRIPE_KEY"]
The same C2A_SYSTEM_ENV carries three lanes: variables (plain env), secrets (masked env), and binding (decoded service references). Apps read all three from one place.
Values are never echoed back
No surface — UI, CLI, or API — ever returns the value of an existing Daari Secret. You can list keys, inspect bindings, see metadata, rotate (write-only), and delete. You cannot read.
Rotation is the only write verb. If you need to check a value, you've lost it — rotate to a known new value instead.
cert-manager-managed TLS secrets
TLS secrets owned by cert-manager (those auto-issued for your custom domains) surface in the Daari Secrets list with a "managed by cert-manager" badge. They're read-only — Daari won't let you rotate or delete them, because cert-manager owns the lifecycle. To force a re-issue, delete the underlying Certificate resource; cert-manager will recreate the secret.
Quotas
50 secrets per project, regardless of tier. The cap exists to catch runaway loops; if you legitimately need more, ping us. Hitting the cap gives a clear error from c2a daari secrets create.
Rotation propagation (v1 behaviour)
c2a daari secrets rotate updates the underlying K8s Secret in place. Bound apps don't automatically see the new value until the next pod restart. To force propagation:
c2a app restart my-app
(A future v2 enhancement will auto-restart bound consumers on rotate, with a --skip-restart opt-out. Tracking issue lives in the Daari Secrets spec.)
Where this fits in the shared responsibility model
- You decide what to store, when to rotate, and which apps consume which secret.
- The platform stores it, decodes it into
C2A_SYSTEM_ENVon bind, surfaces cert-manager-managed read-only. - The platform (manual) will provide AWS Secrets Manager backing on request (Phase 2 — not yet live).
See the Shared Responsibility Model for the broader split.