SIGN IN SIGN UP

feat: plan many domains, approve once, apply bounded (#130)

A multi-domain DNS setup — plan N attached domains, review one digest,
approve
once, apply with bounded concurrency, resume what failed — is an
aggregate every
host was rebuilding over `Storage.attempts`. That is the argument ADR
0003
already made one level down, so the batch moves into DomainKit.

## What lands

- **`Storage.batches`** — create under an owner-unique idempotency key,
point
each item at the attempt carrying its plan, approve every attempt beside
the
batch's own approval in one transaction, decline the batch with its
planned
attempts, and list what an owner still owes a move on. Items are
pointers:
  plan, approval, receipt, lease and failure stay on the attempt.
- **`@domainkit/capsuledb`** — `domainkit_batches` and
`domainkit_batch_items`
as additive migration 4. The first migration keeps rendering the six
tables it
  always did.
- **`Provision.batch`** — the lifecycle over that seam, with
  `Policy.batchConcurrency`.
- **`domainkit/server`** — the batch routes, authorized by endpoint name
like
  every other route.

The stored status is recomputed from the items' attempts after every
transition,
inside the transaction that locked the batch row, so a planning pass
still in
flight cannot land state on a declined batch and the unfinished index
never
disagrees with the attempts it summarizes.

## Checks

`bun run --filter domainkit typecheck|test`,
`bun run --filter @domainkit/capsuledb typecheck|test` (conformance on a
real
PostgreSQL container), `bun run release:check`.
S
Saatvik Arya committed
a7c6528b808bcf2d9c10bb7bc06aa9b86e1a397b
Parent: 356276f
Committed by GitHub <noreply@github.com> on 9/19/2026, 12:39:14 PM