Core concepts
Lock, sync, diff and drift
Uses the Ahena CLI (beta). Install it with npm install -g @ahena/cli, or prefix commands with npx @ahena/cli. See Installation. The dashboard covers projects, connections, Doctor, the Stack Graph, plans and approvals without it.
ahena.config.ts says what the app wants. ahena.lock records what the stack is:
per environment, which provider fills each capability, the non-secret identifiers needed to
reach the same resources, and the live values Ahena manages. Both files are git-safe and
meant to be committed.
# ahena.lock
version: 1
organization: acme
project: leo
environments:
production:
providers:
cloudflare:
settings:
CLOUDFLARE_ACCOUNT_ID: 0123…
state:
r2.bucket.leo:
label: R2 bucket leo exists
severity: high
value: true
r2.bucket.leo.cors:
label: R2 leo CORS origins
severity: high
value:
- https://leo.app
supabase:
settings:
SUPABASE_PROJECT_REF: abcdefghijklmnopqrst
state:
auth.siteUrl:
label: Auth site URL
severity: high
value: https://leo.app
stack:
auth: supabase
storage: cloudflare
ahena lock
Reads every connected provider (read-only) and writes ahena.lock. Keys are sorted, so
re-locking an unchanged stack produces no git diff. Local providers (Ollama) are listed with
their settings but never read by Ahena's servers.
After Ahena applies changes (ahena configure, ahena doctor --fix, ahena diff --apply,
ahena apply, MCP), it re-reads only the providers it changed into ahena.lock, so its own
changes aren't reported as drift. Every other provider keeps its locked values: a change made
elsewhere stays reported until someone reviews it with ahena drift, or takes everything as
it is now with ahena lock.
Git-safety: only non-secret connection settings are written, provider state passes through redaction in core, and the CLI refuses to write the file if any value looks like a credential.
ahena sync
For a developer who just cloned the repository:
$ ahena sync
Leo acme/leo · developer
This application requires:
Production
✓ cloudflare healthy
✗ supabase not connected
? Connect 1 provider now? Yes
Provider connections live in Ahena per environment, so teammates in the organization see the
connections that already exist. Missing ones are connected with the usual flow (secrets from
the environment, stdin or a hidden prompt), with the identifiers from ahena.lock pre-filled
so everyone connects to the same resources. --no-connect only reports; -e limits it to one
environment.
ahena diff
Plans every connected provider against ahena.config.ts, grouped by environment, like an
infrastructure-as-code plan:
PROPOSED CHANGES
── Production ──
Cloudflare
+ Create R2 bucket leo (production) [BILLABLE]
Creating an R2 bucket may be billed to your Cloudflare account.
~ Set CORS on leo: https://leo.app [CONFIRMATION_REQUIRED]
No destructive changes.
? Apply? (y/N)
- Read-only until you approve.
--jsonprints the plan without applying. - Billable/destructive changes need their own approval (
--yes --allow-billablein scripts). - Changes that matter (beyond SAFE in production, billable or destructive anywhere) are then
approved in the Ahena dashboard, signed in: the CLI opens the link and waits, once per
provider.
--yesdoesn't replace it. See approvals. - What you saw is what runs: each provider applies only with the fingerprint of the plan shown. If the provider changed in between, Ahena refuses and asks you to diff again.
- Email DNS records are included for the Cloudflare zone when
dnsand Resend'semail.domainare both declared.
ahena drift
Compares the live values with ahena.lock to find changes made outside Ahena (for example
in a provider's dashboard):
Configuration Drift Detected
Cloudflare · Production
R2 leo CORS origins
Expected: https://leo.app
Actual: *
Severity: HIGH
? Cloudflare · Production
❯ Fix: restore what ahena.config.ts declares
Accept current configuration: update ahena.lock
Skip
- Fix re-applies what
ahena.config.tsdeclares (notahena.lock's values) with the same approvals asahena doctor --fix, then checks again: CONFIRMATION_REQUIRED changes ask (or take--yes); billable/destructive ones also need--allow-billablewith--yes; changes that matter are then approved in the Ahena dashboard (the CLI opens it and waits). Valuesahena.config.tsdoesn't declare can't be restored automatically; Ahena says so. - Ignore for 7 days keeps the provider as it is and stops reporting those values until
then. It's recorded in
ahena.lock(ignore), so teammates and CI see the same decision. - Accept records the current values in
ahena.lock. Ifahena.config.tsdeclares those values, update it too, or Doctor reports the mismatch. --fix/--acceptchoose for every provider without the menu (--fixstill asks for approval unless--yes);--jsonreports and exits 1 when drift is found (useful in CI). A disconnected provider is reported as high-severity drift.
Server-side drift
Ahena also checks drift without your checkout, from the ahena.lock the CLI last shared
(every CLI command shares the lock with the blueprint). The comparison is ahena drift's
(shared code in @ahena/stack, tested against the CLI's): only values in the lock are
compared, a missing or disconnected connection is one high-severity item, local providers
(Ollama) are left to the CLI, and the lock's "ignore for 7 days" entries are honoured. Each
provider is read with that environment's own credentials. A provider that can't be read is
noted and the check is partial, never guessed.
- Dashboard: project → Drift lists, per environment, each changed setting with expected (lock) and actual values, severity, provider and capability, when it was first seen, and the recommended repair. "Check now" runs a fresh check. The Stack Graph shows the count per provider and when it was last checked.
- Continuous Doctor runs it on its schedule and emails on new drift (doctor.md).
- API:
GET /v1/orgs/:org/projects/:project/environments/:env/driftreturns the latest check (ornull);POSTon the same path runs one now. CI tokens may use both.
It never repairs: provider state is only read. Repairs are what ahena drift --fix does (a
plan you review and approve, with the same rules as any plan, including dashboard approval for
production), or keep the new value with ahena drift --accept. Without an ahena.lock entry
for an environment, the result is no_lock: run ahena lock and commit it.
Provider SDK
Providers opt in with state(ctx, expected): a read-only list of { key, label, value, severity } for the values Ahena manages, with arrays sorted so reordering isn't drift.
Shipped: Supabase (auth URLs and policies), Cloudflare (bucket, CORS, declared DNS records,
zone status), Resend (domain status, webhooks), Stripe (key mode, account readiness,
webhooks), Firebase (registered apps). AI providers have no infrastructure to track.