# Lease One Customer Account per Concurrent Session

Concurrent BYOC dogfood is supported by a pre-provisioned pool with one customer
AWS account per simultaneous CP9 session. Multiple sessions may share the
control-plane account, but they may not share a customer account because the
official setup contract uses account-global fixed IAM role names and fixed
CloudFormation stack names. The first slice requires users to select an account
and local profile explicitly; it does not create AWS Organizations child
accounts or automatically broker pool allocation.

The account pool is necessary but not sufficient for every concurrency shape.
The current nextgen global-service public API selects a BYOC Region by tenant,
cloud provider, physical region, and service plan; customer account and logical
Region are not part of that selector. Two sessions for the same tenant in the
same AWS Region would therefore be ambiguous even with different customer
accounts. The read-only catalog preflight catches existing Regions but cannot
serialize two simultaneous empty-slot observations. Activation therefore first
atomically reserves a durable control-plane-account selector slot keyed by
tenant, AWS physical Region, and BYOC service plan, before it touches the
customer account. Concurrent first-slice trains require both different
customer accounts and either different tenant IDs or different physical
Regions. Supporting same-tenant/same-Region concurrency requires a product
API/selector design change rather than CP9 naming changes.

Tenant identity has one accepted spelling: a positive canonical base-10 value
without leading zeros. Config validation rejects numeric aliases before the
activation fingerprint, selector-slot digest, quota identity, or catalog SQL
can diverge for what the product schema treats as one numeric tenant.

The catalog's BYOC RCU quota is tenant-global by schema, not Region-owned.
CP9 therefore gives it a deterministic `tenant + BYOC` identity and shares it
across same-tenant Regions. Destroy deletes that quota only after the last
active BYOC Region for the tenant is gone; its absence proof treats a quota
retained for another active Region as valid and still rejects an orphaned row.

Activation completes its global read-only preflight, then atomically acquires
two durable, cross-machine reservations in order. The control-plane-account
selector slot binds provider, physical Region, service plan, tenant, both
accounts, owner, session, server, and activation fingerprint. Only after that
succeeds does CP9 atomically acquire the customer account-global lease, which
binds owner, session, server, and fingerprint. Under both reservations it
repeats all three fixed-name stack reads immediately before the official
deploys, closing both preflight-to-mutation races. A competing session fails
before any customer-account mutation and reports the current holder. Because
SSM Parameter Store itself is regional, CP9 anchors both parameters in one
fixed region per AWS partition (`us-east-1` for commercial AWS), independent of
the target Region. The reservations are not released by TTL or a failed
activation. Explicit destroy first proves every live reservation still matches
the complete activation binding before its first protected mutation. It then
proves the owned closure absent while allowing only those exact tagged
reservations, releases the customer lease and selector slot in that order, and
repeats the reservation/tag absence proof. Activation and destroy use the same
session lifecycle lock, so closeout cannot release reservations underneath an
in-flight apply and activation cannot reopen an in-flight closeout. Destroy
acquires that lock before it decides the journal is absent or loads its
authoritative stage snapshot, and retains it through terminal checkpoint
publication; a pre-lock snapshot is never an ownership input.

The reservation stage is journaled as running before either atomic parameter
create. If the process stops after creating only the selector slot, or after
creating both parameters but before recording their artifacts, explicit
destroy reads and releases each live reservation only when its complete binding
matches this activation. If a create never happened and no protected layer was
attempted, destroy accepts the proven absence. A missing or foreign reservation
still blocks mutation of a protected layer, but it does not block an exact
zero-state retry: destroy first proves every session-owned object absent, then
releases only reservations still bound to this activation. A losing selector
claim therefore closes without touching the winner, and a session that owns
its selector but loses the customer lease releases only its selector.

After the final reservation release and repeated exact absence proof, destroy
atomically persists terminal journal state `destroyed`. Re-running closeout is
an idempotent local checkpoint read/write with no external calls, because a
later enclosing-destroy phase may already have removed the Kubernetes or AWS
observation substrate. If a process stops after release but before checkpoint
publication, the same zero-state proof safely recovers and publishes the
terminal checkpoint; foreign reservations at either shared key are never
touched. A terminal journal cannot be resumed by activation.

If the authoritative journal is absent under the lock, no CP9 BYOC mutation
can have started because activation persists its journal before its first
apply. Destroy records a terminal empty-lifecycle fence before releasing the
lock, preventing a new activation from starting in the gap before ordinary
host teardown.

A fresh lease holder requires all three official fixed-name setup stacks to be
absent. A pre-existing stack without the same session's matching journal is
foreign: CP9 does not update, adopt, or delete it, and the first slice exposes
no `--adopt` option. Before the official script can invoke any deploy, CP9
atomically persists a separate intent for each stack: observed absence time,
customer account, Region, pinned-template digest, and exact-parameter digest.
The wrapper then rechecks the matching stack boundary immediately before each
deploy. If the process stops after CloudFormation creates
a stack but before the journal records its ID, resume may bind it only when the
same in-flight intent and exact account, region, creation time, template digest,
and parameters match. Destroy targets only immutable stack IDs bound this way,
in reverse creation order; a fixed name alone never grants deletion authority.
For an unbound crash-window stack, destroy compares the live template and
parameter digests directly to that journaled intent, not to the current
embedded bundle or current parameter contract, so a later reviewed bump cannot
strand the prior session.
