Skip to main content
What shipped, newest first, across the fjall CLI, the @fjall/* infrastructure constructs, and the fjall.io control plane.
About version numbers. The CLI and the infrastructure constructs ship as one deploy engine on a shared version line, so a change to what a construct synthesises is a major even when no command, flag, or output moved. You are not expected to track them. Your application pins its constructs, and the engine refuses to run against infrastructure newer than itself rather than deploying something different from what you wrote. Upgrading the CLI never locks you out of redeploying an older application. See Engine compatibility.
Asia Pacific target names, SSH is no longer part of an instance size
fjall 32 is not published yet. The four changes below are merged and ship in the next release. Until it lands, npm install -g fjall@latest installs fjall 31, and there is no fjall 32 on npm to install, so none of this behaviour is available yet.

Asia Pacific, Africa and southern Europe target names changed

A deployment target is named <accountname>-<regionabbrev>, and the region part is the only thing that says where a deploy lands. Abbreviating the compass word to a single letter gave ap-southeast-1 and ap-south-1 the same code, aps1, and likewise aps2 for ap-southeast-2 and ap-south-2.Compound and ambiguous directions now get two letters:The same applies to the rest of ap-southeast-*, ap-northeast-*, ap-south-*, plus af-south-1, eu-south-1, eu-south-2 and me-south-1. Every other region keeps the name it had, so production-use2, staging-euw1 and development-euc1 are untouched.The old codes are retired rather than re-pointed. Naming one is refused with the replacement to use, so a command written against aps1 stops rather than resolving to a region you did not name. Run fjall target list for the current names, then fjall target set <name>.Requires fjall 32. See fjall target.

SSH is no longer part of choosing an instance size

The “Standard instance” preset in the fjall add compute wizard enabled SSH. Because presets skip the advanced step, nothing asked first, so picking a size also put the instance in a public subnet with a public IP and opened port 22 to 0.0.0.0/0.Choosing a size now decides only the size. Pick “Custom” to be asked about SSH, or set ssh in infrastructure.ts yourself. Existing applications are unchanged: this is the wizard’s default for new compute, not a change to what your file already says.Requires fjall 32. See EC2 Instance.

The VPC peering companion command is runnable

When the two halves of a peering pair live in different repositories, the wizard prints the command to run in the other one. That line named a --for flag that does not exist and carried none of the properties the peer half needs. It is now rendered from the same properties the single-repository path writes, so it can be pasted as printed.Requires fjall 32. See VPC peering.

fjall target set <name> honours the name at a terminal

Naming a target opened the account and region pickers anyway and ignored the argument, so setting a named target took --non-interactive. It now sets what you named, at a terminal or not. fjall target set with no name still opens the pickers.Requires fjall 32. See fjall target.
Deploy-role permissions boundary, object versioning on resilient buckets

Deploy roles are capped by a permissions boundary

Every deploy role Fjall creates in a connected AWS account now carries a FjallDeployBoundary permissions boundary, rendered by default by both the CloudFormation quick-create template and its CDK equivalent. The boundary caps what a mistaken or compromised deploy can reach, and it protects itself at every tier: a deploy cannot widen or delete the policy that constrains it.The policy is an account-global singleton, adopted by name if it already exists and created if it does not, through a custom resource rather than a stack-owned managed policy. Connecting a second account, or re-connecting an existing one, no longer risks an EntityAlreadyExists refusal or a connector stack stuck in DELETE_FAILED. fjall org destroy removes the policy only when the last stack referencing it goes.Requires fjall 31. See Configure deployment credentials.

Resilient and enterprise buckets version their objects

S3 buckets provisioned at the resilient or enterprise backup tier now enable object versioning by default, so an overwrite or an accidental delete stays recoverable. Buckets at other tiers are unchanged, and an explicit versioned setting always wins.Requires fjall 30. See S3 Bucket.
Destruction consent covers five more stateful types

The destruction gate covers log groups, secrets, KMS keys, hosted zones and user pools

The data-loss oracle already recognised databases, buckets, volumes and file systems. It did not recognise five types whose destruction is equally irreversible, so a deploy whose plan deleted or replaced one of them went through ungated:All five are now stateful to the oracle, so deleting or replacing one requires the same per-resource consent as a database.Requires fjall 13. See Destructive changes.
ECS on EC2 rejects impossible container placements at synth

Containers that cannot fit their instance type fail at synth

On the EC2 launch type, ECS places a task only if the sum of its containers’ hard memory limits fits the memory an instance actually registers with the cluster. That is always strictly below the instance type’s nominal figure, because the ECS agent and OS reserve a slice first. A t4g.medium registers 3835 of its nominal 4096 MiB. A task sized against the nominal number can never be placed, on any instance count.The constructs now reject that shape during synth, with the numbers, instead of leaving you to read a placement failure at deploy time.

The ECS on EC2 default instance type is now t4g.small

The previous default, t4g.micro, was structurally unable to run an all-defaults service: roughly 896 MiB usable against a 1024 MiB default container limit. The default is now t4g.small, where the default container fits both on its own and alongside the schema-gate sidecar.Requires fjall 12. See ECS Cluster.
Scaffolds no longer overwrite your edits

Scaffold commands refuse to overwrite files you have edited

fjall create account, fjall create organisation and fjall domain import used to render their scaffold straight over whatever was on disk. Re-running create account after a failed install step silently reverted a hand-edited infrastructure.ts to the template; a domain re-import clobbered the previous one without comment.All three now guard every scaffold write and stop rather than discard your work.Requires fjall 8. See fjall create.
Domains are typed infrastructure, with classification and ceremonies

Domains are declared in infrastructure.ts

A domain is now declared with the typed Domain construct in fjall/domains/<zone>/infrastructure.ts, a discriminated union on registrar. The older directive-driven pipeline is gone, and BIND survives as an import and export format rather than a source of truth.

New domain verbs

Zone safety

Every live record classifies as declared, satellite (owned by another live stack), residue (provably orphaned) or unknown. The classifier fails closed: an evidence gap yields unknown, never residue, and unknown records are never remediable.Destructive domain paths run the same consent ceremony as deploys. Consent is per row and by exact name, and a withheld ceremony exits 4: success-shaped, with nothing mutated.Requires fjall 3. See fjall domain and Custom domains.
Static sites, and recovering a wedged deploy slot from the CLI

Static sites

fjall create app --pattern staticsite deploys a pre-built static site from a private S3 bucket behind CloudFront with Origin Access Control, at roughly $0 per month. Single-page and multi-page routing, form handling, and a custom domain are all flags on the create.See Static site pattern.

Recover a wedged deploy slot without the dashboard

  • fjall deployments cancel <id> requests co-operative cancellation of the deployment holding the slot. If the occupier is a dead remote source, the response distinguishes “still progressing, wait” from “demonstrably silent” and prints the exact force-release command.
  • fjall deployments force-release <id> --confirm <id> clears the slot. It is owner and admin gated, audited server-side, and requires a signed-in user credential, so agents and CI tokens route it through a human.
See fjall deployments.
Drift repair, destructive-change consent, and remote deploy control
A deploy whose plan would delete or replace a stateful resource now stops with exit code 4 until every such resource is consented individually, by exact physical name and verb. No flag bypasses the gate: --auto-approve, --skip-confirmation and --force never satisfy it.Interactive deploys walk a per-resource ceremony. CI passes --remediate <physicalName>=<verb>, optionally pinned to the reviewed plan with --destruction-consent-digest, and a consent minted against a plan that has since moved is refused. A withheld deploy mutates nothing and frees the organisation’s deploy slot immediately.See Destructive changes.

fjall drift detects and repairs out-of-band deletions

Deleting a stack resource in the AWS console used to wedge deploys indefinitely, because CloudFormation keeps failing NotFound.
  • fjall drift detect probes each stack’s resources against their owning services and reports confirmed, unconfirmed and recovered verdicts.
  • fjall drift repair runs the consent-gated repair (forensics capture, retain flip, surgical template removal), journalled and resumable with fjall drift resume.
  • A failed deploy whose root cause is a confirmed out-of-band deletion now names the resources and prints the exact repair command.
See fjall drift.

Deploys are observable and cancellable from fjall.io

Tracked deploys send a liveness heartbeat, consult the deployment lease before every mutating CloudFormation boundary, and honour a cancel initiated from the dashboard across deploy, destroy, rollout and rollback. A remote cancel renders a cancelled outcome with exit code 2, never a false success, and lands before the next stack mutation with completed stacks left standing.
CI should treat exit code 2 as “stopped without failure” rather than as a deploy failure. It covers a remote cancel and a plan halted at the approval gate.
Releases, rollback, in-place rollouts, and the CI command group

Releases and rollback

fjall releases lists the releases minted from your deploys, and rollback is release-addressed with per-service granularity. Application ECR repositories moved from count-based lifecycle retention to release-aware retention, so a rollback target is not garbage-collected out from under you.See fjall releases.

fjall rollout restarts services in place

fjall rollout <app> restarts an application’s services without a full deploy: the lightweight way to apply a secret or connection change. fjall secrets set and delete now detect consuming services and offer the roll.See fjall rollout.

The CI command group

fjall ci covers setup, token, status, verify and run. Both CI plugins, the GitHub Action and the Buildkite plugin, are thin shims over fjall ci run, so all three surfaces share one code path and behave identically. CI deploy tokens are capped at 90-day expiry at mint time.See fjall ci and CI/CD.

Upgrading

Then bump @fjall/components-infrastructure in your application to match, and redeploy. If the two drift apart in the unsafe direction, the deploy refuses before it changes anything in AWS and tells you which version to install. See Engine compatibility.