Core concepts
Plan, apply and verify
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 plan # store a plan per environment with changes
ahena apply pln_… # review, approve, apply, refresh ahena.lock
ahena apply -e production # plan and apply in one step
The workflow: intent → plan → approval → apply → verify → generate → doctor.
A plan covers one environment and every provider in it. It contains:
- Provider operations, from each provider's own read-only plan (what
ahena.config.tsdeclares, plus email DNS records for a Cloudflare zone), with their classification (SAFE, CONFIRMATION_REQUIRED, MANUAL, DESTRUCTIVE, BILLABLE) and known cost. - Manual operations: steps only you can do (Doctor's manual fixes, providers to connect), shown with instructions. Ahena never marks them done.
Approval
ahena apply asks once for the plan, and separately for anything billable or destructive
(--yes --allow-billable in scripts). Approving needs provider.manage for the environment
(admin+ in production); billable/destructive needs operations.destructive. Declining
cancels the plan.
Changes that matter (anything that isn't SAFE in production, and billable or destructive
changes anywhere; needsBrowserApproval on each operation) are then approved in the Ahena
dashboard, signed in. The CLI's token can ask but not approve, and --yes doesn't change
that (approvals):
These changes need your approval in the Ahena dashboard: https://app.ahena.io/approvals/apr_…
Waiting for your decision in the browser. Nothing is applied without it.
✓ Approved in the dashboard.
The CLI opens the link (as ahena login does) and checks every 2 seconds. Approved: the plan
is applied. Declined or expired (60 minutes): nothing is applied, the plan is cancelled, and
the CLI exits 1. With --no-wait it prints the link and exits 4 without waiting; once
you've approved, ahena apply pln_… applies the approved operations without asking again
(within 60 minutes of the approval). Each operation records how it was approved
(approvedVia: web for the dashboard).
Apply
Providers run one after another (Cloudflare first, since other providers verify DNS against it). Each re-plans and compares its fingerprint with the reviewed plan; if the provider changed in between, nothing is applied for it and the operation fails with "changed since you reviewed".
Partial failure is reported, never hidden. If Stripe fails after Cloudflare succeeded, the
plan ends PARTIALLY_APPLIED with each operation's outcome: applied, failed (with the error),
skipped (not approved), or manual. Ahena never deletes what succeeded to fake atomicity across
providers. Retry with ahena apply: it creates a fresh plan, and providers check what already
exists, so completed steps aren't repeated.
A provider action that errors is recorded as failed with the provider's reason, and the CLI prints why, where, the impact, and whether a retry fixes it. It's never reported as skipped.
One apply per environment at a time. While a plan is APPLYING, another apply to the same
environment is refused, so a retry can't race a slow first run into creating something twice.
A plan with no progress for 5 minutes (planStaleAfterMs) is treated as interrupted: the next
apply closes it out as PARTIALLY_APPLIED or FAILED, marking the unconfirmed operations
"Interrupted before Ahena confirmed it". It audits plan.interrupted and then plans afresh
from the providers' live state. Work that did reach a provider is seen there, not repeated.
Verify
A provider answering "OK" isn't proof. After every write Ahena reads the provider back and compares what it finds with what was planned (a few attempts, for providers that are eventually consistent). Each operation ends as one of:
| Outcome | Meaning |
|---|---|
| verified | Ahena re-read the provider and the change is there |
| applied, unverified | The provider accepted the change, but Ahena couldn't confirm it yet |
| failed | The provider refused or errored, with its reason |
| unknown | Ahena can't tell whether the write reached the provider (for example a timeout or an interrupted apply). The next plan re-reads the provider and won't repeat it if it was made |
| skipped | Not approved, so not applied |
| manual | A step only you can do |
The plan's status follows from its operations and is never rounded up: APPLIED only when
every operation that ran was verified, APPLIED_UNVERIFIED when something couldn't be
confirmed, PARTIALLY_APPLIED or FAILED on failures, and NEEDS_REVIEW when an outcome is
unknown.
Statuses: READY, AWAITING_APPROVAL, APPROVED, APPLYING, APPLIED,
APPLIED_UNVERIFIED, PARTIALLY_APPLIED, NEEDS_REVIEW, FAILED, CANCELLED. Plans and
every operation are stored and visible in the dashboard (Project → Plans) and audited.
ahena diff remains the one-step version without a stored plan.
Intent: ahena add <capability>
ahena add payments (or email, storage, auth, push, ai, database) works out what
the capability means for this app from its type: a marketplace gets Stripe Connect and the
marketplace pack, a SaaS gets products, prices and subscriptions. It shows everything the
capability needs end to end, declares it in ahena.config.ts (never overwriting what's there),
connects the provider if needed, then plans and applies with the usual approvals, and offers
the related feature packs. Names that aren't capabilities are feature packs (ahena add teams);
in a list of packs, auth is the auth pack.