Adr 024 deployment profiles
ADR-024: Deployment profiles and regional capability validation
Section titled “ADR-024: Deployment profiles and regional capability validation”Status: proposed Date: 2026-10-25 Issue: #836
Per the ADR lifecycle, this decision remains proposed until its implementing PR merges.
Context
Section titled “Context”The application stack deploys Slack, Linear, Jira, deploy-preview screenshots and the Agent Registry whether or not an operator uses them. Each adds Lambdas, tables, secrets, IAM grants, API routes and alarms, so unused integrations cost money, slow deploys, widen the security-review surface and consume the root stack’s 490-resource budget (ADR-023). Some depend on Region-limited services: AWS Agent Registry is available in nine Regions, and AgentCore Memory, which every deployment uses, in sixteen. An unsupported Region fails late, inside CloudFormation, with an opaque service error.
Issue #836 also suggests moving substantial optional modules into nested stacks. Slack, Linear, Jira and screenshots each attach methods to the shared Task API RestApi. ADR-023 §1 and the #852 proof of concept record that extracting such integrations loses deployment dependencies, CORS, attribution and tags even when synthesis passes, and moving their tables and secrets would replace them.
Decision
Section titled “Decision”-
One validated selection.
DeploymentFeatures(cdk/src/deployment/features.ts) is resolved once inmain.tsand passed toAgentStack. Constructs read the selection, never feature context directly. Optional features:slack,linear,jira,deployPreviewScreenshots,agentRegistry,toolGateway. Authentication, Cedar HITL, secure egress, task state, admission control, GitHub workflow, alarms and diagnostics are core and not selectable. -
Persistent profile.
abca.deployment.jsonat the repository root (schemaVersion: 1, every feature an explicit boolean, unknown keys rejected) is the shared input for local and CI synthesis. Precedence: per-feature context switch (enableSlack,enableLinear,enableJira,enableDeployPreviewScreenshots,enableAgentRegistry,enableToolGateway) → profile → legacy topology.-c deploymentProfile=<path>selects another file;-c deploymentProfile=noneignores it (used by the synthesis census so a developer’s profile cannot change its results). -
Absent profile = legacy topology. Without a profile, everything that deploys today still deploys (Tool Gateway stays opt-in). Shipping profiles deletes nothing from existing installations.
-
Omit, do not relocate. A disabled feature synthesizes no routes, WAF body-size exemptions, Lambdas, grants, tables, secrets, wiring, alarms or outputs. Enabled features stay in the application stack, with the existing Registry nested stacks unchanged. Headroom comes from omission, which is safe; relocation is not safe without the populated migration rehearsal that ADR-023 defers. The stranded-orchestration sweep and iteration heartbeat deploy only with Linear or Jira. Screenshot-to-Linear/Jira wiring exists only when screenshots and that tracker are both enabled. Two parts of the issue’s “shared orchestration” scope stay core. The orchestration table and live reconciler remain because the reconciler also owns the per-task budget rollup. The task table’s
LinearIssueIndex/JiraIssueIndexremain because removing a GSI is a schema change outside this decision. ADeploymentFeaturesoutput records the selection so tools can read it back. -
Regional capability catalog.
contracts/deployment-capabilities.jsonrecords, per capability, the required services, supported Regions, remediation, maturity, footprint and statefulness, with the source URL and last-verified date. CDK reads the JSON directly; the CLI keeps a package-safe literal mirror enforced by a parity test (thecontracts/constants.jsonpattern).AgentStackrejects an unsupported concrete Region during synthesis, so the CLI is not the only enforcement point. Environment-agnostic synthesis is not checked. -
bgagent setup. The wizard runs these steps in order:- resolves the Region first and checks core availability;
- lists every feature but marks unavailable ones as unselectable;
- preselects features already deployed, read from
DeploymentFeaturesor inferred for older stacks; - recommends the minimal profile for new stacks;
- diffs a temporary candidate profile, so cancelling leaves the repository untouched;
- asks for explicit confirmation before deleting or replacing state-bearing resources, then writes the profile and deploys through the existing mise task.
Non-interactive runs fail on an unsupported feature, and require
--accept-data-lossin addition to--yesto remove state-bearing resources. Operator subcommands for an omitted feature fail early with a pointer tobgagent setupwhen they can identify the stack: from--stack-name, or the stack the CLI was configured from. -
First-install compute and account preparation. Issue #836 kept compute out of the first wizard; this record extends it for new installations only, where no backend can be removed.
- The wizard asks where agents run (AgentCore, ECS, or both) and records the ordered list as the profile’s optional
compute. Contextcompute_types/compute_typestill wins. - On existing stacks the deployed backends are read from
ComputeTypes. Stacks from before #912 publish onlyComputeSubstrate; if that names a backend other than AgentCore, the wizard requires--computerather than guessing. Adding a backend is allowed; removing one is refused in favour of the COMPUTE.md transition procedure. - Before the deploy, after confirmation, it installs or updates ABCA’s least-privilege CDK bootstrap and sets the bootstrap
ComputeTypesparameter (AgentCore always included). It never modifies a standard CDK bootstrap that other apps may share.
- The wizard asks where agents run (AgentCore, ECS, or both) and records the ordered list as the profile’s optional
-
Several deployments per checkout and account. The wizard confirms the caller’s account (STS), lists existing ABCA stacks in the Region and offers to update one or create a named new one. Each non-default stack reads only
abca.deployment.<stackName>.json, never the shared file, which belongs to the default stack. A stack without its own file therefore keeps the legacy topology (rule 3), and one checkout can drive several deployments without one profile deleting another’s modules. When the account uses ABCA’s least-privilege bootstrap, whose deploy role is scoped tobackgroundagent-devandbackgroundagent-dev-*, the wizard only creates stacks with those names; a create outside that scope fails and cannot roll back its IAM roles. A bootstrap parameter for other prefixes is a follow-up.
Consequences
Section titled “Consequences”- (+) The minimal profile synthesizes 317 root resources against 463 for the legacy topology (−146), with the corresponding IAM, secrets and routes, and fails fast in unsupported Regions.
- (+) The shared census grows to 142 profiles. The new cells cover minimal, each single feature, the paired trackers/screenshots and all features in both topologies. They assert that disabled features leave nothing behind and that catalogued footprints track synthesis.
- (+) One input file feeds local deploys, CI and the wizard; existing context switches keep working.
- (-) Disabling a stateful feature deletes its tables and secrets (
RemovalPolicy.DESTROYtoday). Re-enabling creates empty resources; operators must re-run the feature’s setup command. No import path is provided. - (-) Regional data is a maintained copy of AWS documentation and can go stale. A stale entry blocks a newly supported Region until the catalog is updated (fail closed); the update process is in the deployment guide.
- (!) Strict boolean parsing now rejects malformed
enableToolGateway,enableAgentRegistry(unchanged) and the new switches; values that were previously treated asfalse, such asenableToolGateway=yes, now fail synthesis.enableLinearIdentityVaultkeeps its lenient reading. - (!) Legacy-default stacks in core Regions without AWS Agent Registry (7 of 16) now fail synthesis rather than at the registry custom resource; such stacks could never deploy the registry. The error names the profile key and context switch that disable it.
- (!) Enabling every feature leaves the root stack where it is today; nested-stack extraction of route-owning integrations remains out of scope until ADR-023’s migration criteria are met.