Deploy Quickstart
FDAI is provisioned from infrastructure-as-code under infra/. Terraform is the
execution engine and the source of truth. Two paths stand up the same minimum
Azure inventory: a turnkey azd wrapper, or Terraform on its own. Both preview
first, so you can review the plan before you run the separate apply step.
Before you start
Section titled “Before you start”- An Azure subscription you can create resources in, and the Azure CLI
(
az). The turnkey path also needs the Azure Developer CLI (azd). - A completed deployment preflight. It collects quota, permission, connectivity, and rollback blockers before the control loop starts.
- Per-environment values in a
*.tfvarsfile. Never commit that file. - The approved target exported as
AZURE_SUBSCRIPTION_IDandAZURE_TENANT_ID. Bootstrap and turnkey helpers stop before making any change if the active identity or the selectedazdenvironment does not match that exact pair. - An attested FDAI runtime image from
container-supply-chain.yml. An Executor plan verifies theghcr.io/<owner>/<repo>/fdai-core-control-planeattestation forruntime_image_revisionand binds the identical digest in the ACRfdairepository. Usepromote_runtime_image=trueonly to import that verified digest before planning; exact apply never promotes or rebuilds an image. - Network access from the deployment host to every private endpoint. In a private-only environment, run Terraform from the VNet-connected deployment runner rather than an operator workstation. A Premium registry in that environment is private too, so build and push the image from the same runner.
- For a protected remote plan, set the non-secret
DEPLOY_PREFLIGHT_INPUT_JSONrepository variable with every required live category. A missing profile stops the run before Azure login, and a blocked probe logs only sanitized check results and detected issues. After Terraform planning, the runner-ownedrun_live_preflight.pychecks Azure Policy, Compute quota, executor RBAC, and value-blind Key Vault secret metadata. An incomplete check stops before the plan artifact is stored. - To preview the internal Isolated Executor, select
deploy_isolated_executorin the private-runner workflow. It remains plan-only until you separately approve apply, and the observation mode identity receives no action-specific effect role. - To provision the bounded OHL scale-out evidence target, enable
enable_ohl_scale_out_evidence_targetonly indevwith private networking and the development operations gateway. Supply an exact image version, the protected workflow’s SSH public-key input, a retry-stable campaign ID, and the human initiator’s principal ID. The target starts at capacity1. Its manual proposal Job publishes one observation mode proposal through the normal ingress and has no provider-effect authority; protected provider staging may increase capacity only to2before verified rollback.
Provision the minimum inventory
Section titled “Provision the minimum inventory”Preview first, and apply only when the plan matches what you expect. Both paths
provision the same infra/ Terraform, so pick whichever fits your workflow.
During a protected move to private networking, the only delete FDAI accepts is retiring the broad PostgreSQL Azure-services firewall rule. If the plan shows a replacement at that address, or any other delete, stop the apply.
When the development operations gateway uses a protected targeted plan, verify that the AI
account and its role collection are both present. This lets network and authorization changes
converge in the same apply instead of leaving a post-apply plan behind. When you also select
deploy_isolated_executor, verify that the isolated Executor module and its dependency graph
appear in that targeted plan.
azd auth login
azd env new fdai-dev
export AZURE_SUBSCRIPTION_ID="<expected-subscription-id>"
export AZURE_TENANT_ID="<expected-tenant-id>"
# safe preview - runs `azd provision --preview`, applies nothing
scripts/deployment/azure/azd-up.sh
# provision for real - second gate prevents an accidental apply
FDAI_AZD_CONFIRM=1 scripts/deployment/azure/azd-up.shaz login
export AZURE_SUBSCRIPTION_ID="<expected-subscription-id>"
export AZURE_TENANT_ID="<expected-tenant-id>"
scripts/deployment/azure/verify-azure-context.sh \
"$AZURE_SUBSCRIPTION_ID" "$AZURE_TENANT_ID"
terraform -chdir=infra init
# copy a template and fill in your values (tfvars are never committed)
cp infra/envs/dev.tfvars.example infra/envs/dev.tfvars
terraform -chdir=infra plan -var-file=envs/dev.tfvars
terraform -chdir=infra apply -var-file=envs/dev.tfvarsAfter provisioning
Section titled “After provisioning”- Verify the inventory. Check that the resources exist and that the executor
identity holds only its scoped, minimum permissions (least privilege). Then
confirm each of these:
- Subscription Event Grid delivery uses the inventory managed identity to
reach
aw.inventory.rawon the operational Event Hubs shard. - The primary shard stays inside its ten-entity Standard limit, and Huginn projects a test resource change.
- The Inventory Job wakes every 10 minutes, PostgreSQL keeps healthy full scans at six hours, and a failed or abandoned attempt retries on the next tick without giving the core a job-start role.
- With private networking on, PostgreSQL and both Event Hubs shards resolve to private addresses from the runtime subnet or a peered runner, pass their TLS checks, and keep Event Hubs public access disabled.
- Subscription Event Grid delivery uses the inventory managed identity to
reach
- Verify runtime health and identity. Confirm the internal core probes are
healthy, all 15 agents report through the health snapshot, and the first canary
publisher Job finished. Then check the features you enabled:
- Operator API: browser Entra App Roles work, and its read and command credentials stay separate from Thor’s executor managed identity.
- Isolated Executor: when enabled, its internal
/liveand/readyprobes pass, its latest revision is active, and its dedicated identity has only image pull, command receive, receipt or DLQ send, and state-secret read. It has no action-specific effect role before authority cutover. - Email notifications: an incident-open message arrives as multipart HTML and plain text. When the Console is enabled, its detail link uses the Static Web App origin and Settings > Integrations shows the same renderer with synthetic placeholders.
- Document OCR: the ingestion identity has
Cognitive Services Useronly on the configured Document Intelligence resource. - Case history: only its dedicated managed identity has Blob data access,
its private network rules retain Defender scanner private-link access, the
executor has no case-history Blob role, and
FDAI_CASE_HISTORY_RETENTION_TICK_SECONDSmatches the approved deletion cadence. - Forecast learning: its opt-in Job publishes raw ticks only, and the core
has the reviewed
FDAI_FORECAST_TARGETS_JSONdocument. - Analyzer tick: when
FDAI_INVENTORY_DSNis configured, the Job merges explicit targets with only the supported resources in the durable inventory projection and reports the configured discovery bound. Unsupported resource types stay omitted, and a fully resolved empty target set exits as a clean no-op. For a protected deployment, set theTRACE_TOPOLOGIES_JSONrepository variable; the workflow passes it to the Job asFDAI_TRACE_TOPOLOGIES_JSON. The same Job and reader identity query bounded workspace-based Application Insights evidence. A complete trace reports no detected issue, while a missing or disconnected hop reports one in observation mode. An empty value disables only the continuity check. - OHL scale-out evidence: when enabled, start the manual proposal Job and confirm exactly one observation mode proposal reaches the normal ingress with the configured campaign and initiator. Its identity has only image pull and primary Event Hubs send permissions, with no provider-effect authority.
- Verify the development operations gateway. It is a development tool: it
terminates a public inbound endpoint behind Easy Auth, and Terraform refuses
to plan it outside
env=dev. Leave it off on a closed network. If you enabled it, confirm:- The protected source archive was deployed after the Terraform apply, and the current remote-build deployment succeeded.
- Both Function triggers are registered, host and idempotency storage use the reader managed identity, and registered network reads succeed.
- With the executor principal, plan one bounded change, submit it with the
returned one-time receipt, replay it to prove no second ARM call happens, and
poll the idempotency key while ARM reports
submitted.
- Onboard one bounded scope. Start with a single resource-group-sized scope and name its owner.
- Watch it in observation mode. Let FDAI judge and audit without changing anything, and review the actions it would have taken.
- Promote one action. Turn on enforcement only for an action that clears its promotion gate, and leave the rest in observation mode.
The Get started guide walks through this first safe rollout in depth, and deploy and onboard is the full deployment reference.