| name | fused-infra |
| description | Reference for the infrastructure managed by fused — what resources exist, why each one is needed, and when they are created, updated, or deleted. Covers the AWS backend (IAM, Lambda, ECR, S3) and the local backend (data directories + venvs, see "Local backend infra"). Use when helping users understand, provision, or troubleshoot the resources that back an fused environment. |
fused AWS infrastructure
Part of the Fused skill set. This covers the AWS resources only. For install
and provisioning see fused-setup; see fused-guide for the full set.
fused manages a small, fixed set of AWS resources per environment. All resources are scoped to the environment's function_prefix (default openfused-). Nothing outside that scope is touched.
Resources managed
IAM role
Name: <prefix> with trailing - stripped (e.g. openfused- → fused), or overridden with --role-name / role_name in the env config.
Why: Every Lambda function must assume an IAM role to run. fused creates and owns this role so users don't have to wire one up manually.
What's in the inline policy (openfused-default):
| Statement | Permissions | Scope |
|---|
S3Access | GetObject, PutObject, DeleteObject, ListBucket | All S3 (arn:aws:s3:::*) |
LambdaSelfInvoke | lambda:InvokeFunction | arn:aws:lambda:<region>:<account>:function:<prefix>* |
SecretsRead | secretsmanager:GetSecretValue | arn:aws:secretsmanager:<region>:<account>:secret:<prefix>* |
CloudWatchLogs | CreateLogGroup, CreateLogStream, PutLogEvents | All (arn:aws:logs:*:*:*) |
ECRPull (only when docker_image is set) | ecr:GetAuthorizationToken, ecr:BatchGetImage, ecr:GetDownloadUrlForLayer | All (*) |
The policy is re-applied on every infra apply, so it self-heals if manually changed.
When managed: created on first infra apply (or env create without --no-provision). Updated any time the policy diverges from the desired state (e.g. adding docker_image to an env adds the ECR statement).
Lambda function
Naming: one function per environment, <prefix>container. Example: openfused-container.
Why: Lambda execution is container-based — the env's docker_image (an ECR image URI, built with fused infra build-image) is the function's code. Packages are baked into the image (env update -p <pkg> + infra build-image); fused never pip-installs packages at invocation time.
Runtime: the env's docker_image ECR URI (PackageType: Image).
Configuration applied on infra apply:
Code: the image URI from docker_image
Timeout: value from lambda_timeout in the env config (default 300 s)
MemorySize: value from lambda_memory_mb (default 1024 MB)
EphemeralStorage: value from lambda_tmp_storage_mb (when not the 512 MB default)
Architectures: value from lambda_architecture — changing it is a REPLACE (delete + recreate), since architecture cannot be updated on an Image-type function
TenancyConfig: {"TenantIsolationMode": "PER_TENANT"} — every compute function fused invokes is created with AWS Lambda tenant isolation mode, so each invocation runs in an execution environment dedicated to its tenant id (the caller identity, or a shared placeholder).
infra plan compares the live function's image URI, memory size, ephemeral storage, architecture, and tags against the desired state and reports drift (a leftover zip-packaged function from an old install is reported as REPLACE). infra apply reconciles them. Tenant isolation is not drift-checked: AWS only allows it to be set at function creation.
What's NOT managed: Lambda functions outside <prefix>* are never touched. The deployed serve Lambda (behind API Gateway) is intentionally not tenant-isolated — API Gateway can't attach a tenant id on invoke; isolation happens on its call into the compute function instead.
ECR repository
Name: extracted from the docker_image URI (registry host stripped, tag stripped) — e.g. 123.dkr.ecr.us-east-1.amazonaws.com/myapp:latest → myapp — or, before a first image exists, image_build.repo (default: the prefix minus the trailing dash).
Why: the Lambda function's container image must live in ECR in the same account. fused ensures the repo exists before docker push.
When managed: infra apply creates the repository if missing. infra build-image also creates it during the build workflow.
Teardown: deleted (with force=True, removing all images) when infra teardown is run and a docker_image is configured.
Serve repo: infra serve creates a separate ECR repository,
<prefix.rstrip('-')>-serve, holding the dispatcher image (content-tagged).
It is created on first infra serve and removed by infra teardown.
S3 cache bucket (optional — only when cache_bucket is set)
Name: auto-derived as <prefix without trailing dash>-cache (e.g. openfused-cache), or set explicitly with --cache-bucket / --no-cache-bucket.
Why: execute_code supports an input_files parameter that uploads local files into the Lambda execution context. Those files are staged in this bucket as a temporary zip, then downloaded and extracted inside Lambda before user code runs.
When managed: infra apply creates the bucket if it does not exist. S3 bucket creation is region-aware (us-east-1 does not accept a LocationConstraint).
Lifecycle rules: infra apply also reconciles three openfused-managed expiry rules on the bucket (and infra plan reports them as drift when absent):
| Rule ID | Prefix | Expiration | Purpose |
|---|
openfused-expire-spill | spill/ | 1 day | One-shot large-result spills (caching off) — read once, then garbage |
openfused-expire-context | context/ | 1 day | Staged input_files zips |
openfused-gc-results | results/ | 30 days | Storage GC backstop for cache entries — not the freshness mechanism (that's cache_max_age at read time), so keep TTLs under 30d |
Rules are merged idempotently: any customer-defined rule (one whose ID does not start with openfused-) is preserved. Requires s3:GetLifecycleConfiguration and s3:PutLifecycleConfiguration.
Teardown: all objects are deleted first, then the bucket itself is deleted when infra teardown runs.
What's NOT managed: user data buckets (the ones you pass to files list, files get, etc.) are never created or deleted by fused infra.
Lifecycle
When invoked as MCP tools (infra_plan, infra_apply, env_create, infra_build_image, infra_lambda_reset, infra_teardown), these long-running operations stream live progress notifications to the client as each resource change, build step, or deletion happens. Progress reporting is best-effort: a disconnected client never aborts the operation.
On env create (AWS, default)
- Config is written to
~/.openfused/envs.json.
infra apply runs automatically — provisions the IAM role, the S3 bucket (if cache_bucket set), and — when docker_image or image_build is configured — the ECR repo, the container image (built and pushed during apply if missing from ECR), and the <prefix>container Lambda function.
Pass --no-provision to skip step 2 (useful when the role already exists or you want to review the plan first).
On first execute_code call
If infra apply has not already created it, the <prefix>container function is created lazily on the first call from the env's docker_image and waited on until Active (~15–30 s). With no image configured, the call fails with guidance to run fused infra build-image first. Subsequent calls reuse the function.
infra plan
Dry run. Compares current AWS state against desired state and prints a diff. Exits 0 if nothing to change, 1 if there is drift. Useful in CI.
infra apply
Reconciles all managed resources to the desired state. Safe to run repeatedly — idempotent.
infra teardown
Deletes Lambda functions (all matching <prefix>*), the IAM role and its inline policy, the CodeBuild project and its service role (if the env uses the codebuild builder), the ECR repository (if docker_image set), and the cache bucket (if set). Prompts for confirmation unless --yes is passed.
Does NOT delete: user S3 buckets, Secrets Manager secrets.
infra build-image
Builds a Docker image and pushes it to ECR, then writes the resulting digest URI back into the resolved env's docker_image field. The next infra apply will update the <prefix>container Lambda function to use it.
By default the build runs remotely in AWS CodeBuild — no Docker daemon needed on the host. Pass --builder local (or set the env's builder to local) to fall back to a host docker build instead. CodeBuild builds in your own account, requires a cache bucket (the build source is uploaded there under codebuild-source/), and pushes via a service role whose ECR push is scoped to just this env's repo (the broad Lambda-execution ECR-pull grant stays *). The CodeBuild project (<prefix>build) + role are provisioned on demand and also appear in infra plan/infra apply and are removed by infra teardown. It accepts a user Dockerfile via --context-dir/--dockerfile. With no cache bucket (a deliberate --no-cache-bucket), the CodeBuild build fails fast with guidance to set one or pass --builder local. Limitation: concurrent same-tag builds aren't supported (digest resolved by mutable tag). The managed Fused-hosted build server (per-tenant ECR + immutable tags) is designed but not yet implemented.
When to run infra apply
| Situation | Action needed |
|---|
| New environment | env create does it automatically |
Changed lambda_timeout in env config | infra apply |
Changed docker_image (e.g. after build-image) | infra apply |
| fused handler code updated (new release) | infra build-image (the handler files are baked into the image), then infra apply |
| IAM policy manually modified in AWS console | infra apply — self-heals |
docker_image added to an existing env | infra apply — adds ECR pull permission to IAM role |
Permissions required to run infra commands
The AWS credentials used to run infra apply / teardown must have:
iam:CreateRole, iam:GetRole, iam:PutRolePolicy, iam:DeleteRole, iam:DeleteRolePolicy, iam:GetRolePolicy
lambda:CreateFunction, lambda:GetFunction, lambda:ListFunctions, lambda:UpdateFunctionCode, lambda:UpdateFunctionConfiguration, lambda:DeleteFunction, lambda:TagResource
ecr:DescribeRepositories, ecr:CreateRepository, ecr:DeleteRepository
s3:HeadBucket, s3:CreateBucket, s3:DeleteBucket, s3:ListBucket, s3:DeleteObject, s3:GetLifecycleConfiguration, s3:PutLifecycleConfiguration (if cache_bucket set)
tag:GetResources (Resource Groups Tagging API — discovers deployed resources by their fused:* tags)
sts:GetCallerIdentity
Local backend infra
For a local environment (backend: "local"), "infra" is the
data/secrets/venvs directories and the cached venv holding the env's packages,
managed by LocalPythonInfraManager. No cloud resources; the only
prerequisites are a Python interpreter and (optionally) uv. The same infra_*
MCP tools and fused infra CLI commands dispatch to it.
| What's managed | Detail |
|---|
| Data directory | local_path (default ~/.openfused/data) — created on apply. |
| Secrets directory | the parent dir of secrets_file — created on apply. |
| Venvs directory | venvs_path (default ~/.openfused/venvs) — created on apply. |
infra plan — reports missing dirs; exits 1 on drift.
infra apply — creates the dirs and the packages venv. Idempotent.
infra build-image — errors for local envs (no image; run infra apply).
infra teardown — removes the venvs dir (always — venvs are a reproducible
cache) and (destructive) local_path. Background code serve endpoints survive;
they are detached host processes — stop them by killing the process (Ctrl-C, or
kill <pid>).
infra lambda-reset — clears the in-process venv ready-cache; nothing is
deleted from disk.