Skip to content

Type to search pages.

View .md

Antifailure manifest schema

The file antifailure.yaml at the root of a repository. It describes what to build, where the database comes from, what the environment may reach on the network, who the agents log in as, and what they do. It is the whole configuration surface: nothing about an environment is configured anywhere else.

Field Type Required Notes
auth auth no How personas come to exist.
change Change no How a pull request’s diff is classified.
database Database no Where the environment’s Postgres comes from, and how the production copy is made safe before anyone can branch from it.
egress Egress no What the environment may reach on the network.
explore Explore no Agents that pursue a goal with no declared workflow, discover the paths an application offers, and report where it costs somebody effort without failing.
fidelity Fidelity no The component inventory: what the environment reproduces, what stands in for something, and what it could not reproduce at all.
github GitHub no How Antifailure appears on a pull request: what runs it, whether it comments, what it does with forks, and when it tears the environment down.
insights Insights no The Postgres native checks that turn a preview environment into a database review.
invariants list of Invariant no Read only statements that must hold after every workflow. They are the assertions a test cannot make from the outside: no orphaned rows, no negative balances, no subscription without a customer. Max items 100.
load Load no Traffic shaped like production, compared between the base branch and this one.
name string no A short name for this application, used in environment hostnames and in the control plane. Defaults to the repository directory name. Max length 40, matches ^[a-z0-9]([a-z0-9-]{0,38}[a-z0-9])?$.
oracle Oracle no Deploy a baseline version alongside the candidate, send both the same requests, and report every difference in what came back and in what ended up in the database.
personas list of Persona no The accounts agents log in as. Each is created or reconciled in the golden by the authentication adapter, so a persona is a real user of the application rather than a bypass. Max items 50.
policy Policy no What each class of finding does to the pull request check.
runtime Runtime no Where and how long the environment runs.
services list of Service no Every process the environment runs: web servers, API servers, background workers, and scheduled jobs. Min items 1, max items 50.
version 1 yes The manifest schema version. Increment only for a breaking change; the engine refuses a version it does not understand rather than guessing.
workflows list of Workflow no What the agents do, written as sentences. A workflow is a goal, not a script: the runner decides the actions and verifies the outcome. Max items 200.

How personas come to exist. Absent from most manifests, because detection answers it; present when detection is wrong, when the users table has names nothing could guess, or when the application’s users live somewhere only a script can reach.

Field Type Required Notes
adapter auto, direct, supabase, supabase_api, nextauth, clerk, auth0, workos, seed no Which authentication scheme personas are created in. auto picks it from the dependency list and the live schema. Defaults to auto.
connection string no The Auth0 database connection users are created in. Defaults to Username-Password-Authentication. Max length 128.
domain string no The tenant, for Auth0, for example dev-abc123.us.auth0.com. Max length 253.
password password rules no The application’s password policy, so the generated password satisfies it.
sandbox boolean no That the configured tenant is a sandbox, development or staging tenant rather than the production one. A hosted adapter refuses to create anybody without this, because the only tenant it could otherwise fall back to is the real one. Defaults to false.
seed string no The command the seed adapter runs, once per persona, with the persona in the environment as AF_PERSONA_NAME, AF_PERSONA_EMAIL, AF_PERSONA_PASSWORD, AF_PERSONA_TOTP_SECRET, AF_PERSONA_ROLE, AF_PERSONA_LOGIN and AF_PERSONA_ATTRIBUTES. It must be idempotent, because it runs again on every branch. Max length 2000.
sessions list of string no Extra tables holding sessions or tokens, emptied so that no real session survives into a branch. Masking does not touch them, because a session token is not personal data by any rule a scanner applies. Max items 50.
table auth table no The columns of an application’s own users table, for the direct adapter.
token_env string no The variable holding the provider’s admin credential. The variable name, never the credential. Max length 128.
url string no The project’s API root, for Supabase. Max length 2048.

The columns of an application’s own users table, for the direct adapter. Named rather than guessed, because guessing a column name is how provisioning writes a row the application cannot read.

Field Type Required Notes
attributes object no Maps a persona attribute name to the column it is stored in. Max properties 50.
email string no Defaults to email. Max length 63.
id string no Defaults to id. Max length 63.
json string no A JSONB column that persona attributes with no column of their own are written into. Max length 63.
name string yes Max length 63.
password string no The column the bcrypt hash goes in. Absent for a table that keeps no password. Max length 63.
role string no Max length 63.
schema string no Defaults to public. Max length 63.
timestamps list of string no Columns set to now() on insert, and on update where the name contains ‘updated’. Max items 10.

How to turn the service directory into an image. Omitted means detect: a Dockerfile if there is one, otherwise a buildpack.

Field Type Required Notes
allow_hosts list of string no Hosts the build is declared to reach, such as a package registry or an engine download. DECLARED RATHER THAN ENFORCED in this release: the list is validated and shown by af explain, and the local builder does not yet seal a build or apply it. Write it as the record of what your build needs, and do not rely on it as a control. Max items 50.
args object no Build arguments. Never secrets: build arguments are recorded in image metadata and are visible to anyone who can pull the image. Secrets are mounted, and the linter rejects a secret shaped argument. Max properties 50.
context string no Build context directory, relative to the repository root. Defaults to the repository root so that a service can copy from a shared package. Max length 512.
dockerfile string no Path to the Dockerfile, relative to the repository root. Max length 512.
image string no A prebuilt image reference, used with the image strategy. Pinned by digest is strongly preferred. Max length 512.
strategy auto, dockerfile, buildpack, image no Defaults to auto.
target string no Stage to build in a multi stage Dockerfile. Max length 128.

How a pull request’s diff is classified. The built in rules cover the layouts most projects use; these are for the ones they do not. A rule says what a path is, never which checks to run: an unrecognised path always selects every check, and no rule here can take a check away.

Field Type Required Notes
rules list of Change rule no Path patterns this repository wants classified its own way. The longest matching pattern wins, so order does not decide. Max items 100.

One path pattern and what the paths it matches are. It says what a file IS, never which checks to run.

Field Type Required Notes
note string no The sentence the report prints for this rule, replacing the default one that restates the pattern. Max length 200.
path string yes A glob against the repository relative path. A single star does not cross a slash and a double star does. A pattern that matches everything is refused, because it would defeat the rule that an unrecognised path selects every check. Min length 1, max length 256.
surface schema, code, asset, build, dependency, config, infrastructure, pipeline, test, docs yes What the matched paths are. Surfaces the engine assigns from the manifest itself, such as a service or the masking rules file, cannot be set here.

Where the environment’s Postgres comes from, and how the production copy is made safe before anyone can branch from it.

Field Type Required Notes
api_key_env string no The name of the variable holding the provider’s API key. Named rather than carried: a manifest is committed and a key is not. Defaults to NEON_API_KEY for the neon provider.
golden Golden no The masked, verified copy every environment branches from.
masking_rules string no Path to the masking rules file, relative to the repository root. Defaults to masking.yaml. Max length 512.
max_branches integer no The plan’s concurrent branch limit, where the provider has one it cannot read from its own API. Reaching it fails with AF-DB-006 rather than hanging. Minimum 1.
project string no The account-side project a hosted provider creates branches in, such as a Neon project. Not a secret, which is why it lives here and the key that reaches it does not.
provider docker, neon, supabase, dblab no Which provider creates branches. docker is local and needs nothing; neon, supabase, and dblab talk to a service. Defaults to docker.
seed string no Command that fills the golden with data, for a project with no production database yet. It runs once per refresh with DATABASE_URL set, and every branch is a copy of what it made, so the cost is paid once rather than per environment. Mutually exclusive with source_url_env. Max length 1024.
source_url_env string no Name of the environment variable holding the read only connection string of the production database. The value is read once, during a golden refresh, on the operator’s machine or runner, and never stored. Max length 128, matches ^[A-Za-z_][A-Za-z0-9_]*$.
subset Subset no Take a production shaped slice rather than the whole database.
url_env string no Name of the environment variable to inject into services with the branch’s connection string. Defaults to DATABASE_URL. Max length 128, matches ^[A-Za-z_][A-Za-z0-9_]*$.
version 14, 15, 16, 17, 18 no Postgres major version. Match it to the source: a golden built on a different major is an environment running a Postgres your application does not. Defaults to 17.

What the environment may reach on the network. Everything leaves through the sidecar, and everything not named here is blocked.

Field Type Required Notes
allow_ipv6 boolean no Whether the environment may open IPv6 connections. Off by default, because an IPv6 path that bypasses the proxy is the most common way an egress control is silently defeated. Defaults to false.
default block, allow, capture, mock, sandbox, synth no What happens to a host with no rule. Changing this away from block is a deliberate act with a real cost: it is how a preview environment emails a real customer. Defaults to block.
rules list of Egress rule no What the environment may do with one host. Max items 500.

What the environment may do with one host. A rule is per host because that is the unit a person can reason about: allowed, blocked, answered from a fixture, or sent to the provider’s own sandbox.

Field Type Required Notes
credential string no Name of the environment variable holding the sandbox credential for this host. Max length 128, matches ^[A-Za-z_][A-Za-z0-9_]*$.
fixtures string no Path to a fixture pack or an OpenAPI document for mock mode, relative to the repository root. Max length 512.
host string yes Host to match. A leading *. matches one or more labels. An IP literal matches only itself. Max length 253.
methods list of string no Restrict the rule to these HTTP methods. Max items 10.
mode block, allow, capture, mock, sandbox, synth yes block refuses with a readable decision. allow passes through with a rate limit. sandbox substitutes test credentials and forwards to the provider’s sandbox. capture records the message into the inbox and returns the provider’s success shape. mock answers from a fixture or an offline pack. synth asks a model to invent a response and marks every result that touched it as unverified.
note string no Why this rule exists. Rendered in the network policy view, because a rule nobody can explain is a rule nobody dares remove. Max length 512.
paths list of string no Restrict the rule to these path prefixes. Anything else on the same host falls through to the next rule. Max items 100.
rate_limit string no Token bucket rate, for example 10/s or 600/m. Applies to allow and sandbox. Matches ^[0-9]+/(s|m|h)$.
webhook_path string no Path on the application that this provider posts webhooks to. The sandbox forwarder and the offline pack both deliver here. Max length 512.

One variable a service needs. The manifest declares the name and where the value comes from; it never holds the value itself, which is why the file is safe to commit.

Field Type Required Notes
from string no Where to read the value: a secrets adapter name, or the name of a different variable to copy. Max length 256.
name string yes Max length 128, matches ^[A-Za-z_][A-Za-z0-9_]*$.
required boolean no Whether the environment fails to start without it. Defaults to true, because a service silently missing configuration is the failure this product exists to prevent. Defaults to true.
sandbox boolean no Marks a credential that must be a sandbox one. The secrets subsystem refuses a value carrying a known live prefix, and the proxy trips a wire if one reaches the network anyway. Defaults to false.
value string no A literal value for a variable that is configuration rather than a secret, such as a feature flag or a public URL. A value that looks like a credential is rejected. Max length 2048.

Agents that pursue a goal with no declared workflow, discover the paths an application offers, and report where it costs somebody effort without failing. An exploration is reproducible from its seed and never counts against the change.

Field Type Required Notes
enabled boolean no Defaults to false.
goals list of Goal no One thing an exploratory agent tries to achieve. Max items 50.

The component inventory: what the environment reproduces, what stands in for something, and what it could not reproduce at all.

Field Type Required Notes
enabled boolean no Defaults to true.
require list of string no Dimensions every component of which must be reproduced. A dimension that could not be measured neither satisfies a requirement nor breaks one.

How Antifailure appears on a pull request: what runs it, whether it comments, what it does with forks, and when it tears the environment down.

Field Type Required Notes
comment boolean no Whether to maintain a single comment on the pull request. It is updated in place rather than appended, so a busy pull request does not accumulate twenty bot comments. Set false and af change and af ci write comment=false to GITHUB_OUTPUT for the workflow to gate its comment step on. The report files are still written, because the report is also the job summary and the payload a control plane is sent. Defaults to true.
fork_policy never, label, always no What to do with a pull request from a fork. label requires a maintainer to add antifailure:allow first, which is the only safe default: a fork’s code would otherwise run with the environment’s credentials. Enforced by af ci, af up, af test and af load run before an environment is created, on pull_request and pull_request_target, and read from the base branch rather than from the pull request, because the pull request’s copy of this file belongs to the contributor. Defaults to label.
mode actions, app, off no actions runs everything inside a workflow with no server. app uses the GitHub App and the control plane. Defaults to actions.
teardown_on list of string no Accepted and read by nothing. Teardown is unconditional: af ci tears down whatever the outcome, and the control plane asks for teardown on close, merge, supersession and timeout without reading your manifest. The lifetime ceiling is runtime.max_ttl. Defaults to [close merge ttl]. Max items 5.

One thing an exploratory agent tries to achieve. Unlike a workflow this declares no outcome, so it cannot fail: what it produces is the path it took and the friction it met on the way.

Field Type Required Notes
budget object no Hard caps. An exploration that exhausts its budget reports what it found up to that point and says the budget ran out.
goal string yes What somebody is trying to do, in one sentence. The agent has no script, so this is the only thing telling it where to go, and its words are what decide whether the goal was reached. Min length 10, max length 1000.
name string yes Max length 64, matches ^[a-z0-9]([a-z0-9-]{0,62}[a-z0-9])?$.
persona string no Which persona explores. Defaults to the first persona. Max length 40.
seed string no Decides every choice the agent makes. The same seed against the same application takes the same path, step for step, which is what lets a finding be replayed. Defaults to the goal’s name. Max length 64.
slow_ms integer no How long one step may take before it is reported as friction. Defaults to 3000. Minimum 1, maximum 600000.
start_path string no Where to begin. Defaults to the application root. Defaults to /. Max length 512.

The masked, verified copy every environment branches from.

Field Type Required Notes
max_age string no How stale a golden may be before af up refreshes it first. Defaults to 168h. Matches ^[0-9]+(h|d)$.
retain integer no How many versions to keep. A referenced version is never collected regardless of this. Defaults to 5. Minimum 1, maximum 100.
schedule string no Cron expression for automatic refreshes, with an optional CRON_TZ prefix. A refresh that would overlap a running one is skipped with an event rather than queued. Max length 128.
storage local, azure_blob, s3 no Where dumps and attestations live. Defaults to local.
storage_url string no Container or bucket URL for a remote store. Credentials come from the secrets subsystem, never from this URL. Max length 1024.

The Postgres native checks that turn a preview environment into a database review.

Field Type Required Notes
enabled boolean no Defaults to true.
large_table_rows integer no Row count above which a migration lint treats a table as large, where a rewrite or an exclusive lock is an outage rather than a pause. Defaults to 100000. Minimum 0.
migration_rehearsal boolean no Apply pending migrations to a fresh branch, recording per statement duration and the strongest lock held per table. Defaults to true.
plan_diff boolean no Compare query plans between branches to catch an index that stopped being used. Defaults to true.
query_regression boolean no Diff pg_stat_statements between the base branch and this one after running the same workflows, to catch a query loop before it reaches production. Defaults to true.
regression_factor number no How much slower a query may get before it is reported. Defaults to 1.5. Minimum 1.
regression_min_ms number no Minimum absolute change in mean milliseconds before a regression is reported, so that a query going from 0.1 to 0.2 milliseconds is not news. Defaults to 5. Minimum 0.
rolling_compatibility Rolling compatibility no Run the previous release against the migrated schema and see whether its workflows still pass, which is the invariant a rolling deploy actually depends on.

One read only statement that must hold after every workflow. Invariants are the assertions a test cannot make from the outside, checked against the database rather than the interface.

Field Type Required Notes
description string no What is wrong when this fails, in one sentence. It becomes the failure message. Max length 512.
name string yes Max length 64, matches ^[a-z0-9]([a-z0-9-]{0,62}[a-z0-9])?$.
sql string yes A single read only statement. It runs inside a read only transaction with a statement timeout, so a write is refused by Postgres as well as by validation. The invariant fails when the statement returns any row, so write it to select the violations. Min length 6, max length 4000.

Traffic shaped like production, compared between the base branch and this one. Results are always deltas, never absolute capacity claims.

Field Type Required Notes
duration string no How long to run. Capped at fifteen minutes. Defaults to 2m. Matches ^[0-9]+(s|m)$.
enabled boolean no Defaults to false.
safe_routes list of string no Routes that may be called freely because they do not mutate state. Max items 500.
scale number no Fraction of production arrival rate to reproduce. Defaults to 0.05. Minimum 0.001, maximum 1.
scenarios list of Load scenario no Declared journeys run against the environment beside the mix. Each entry names a scenario document in the repository. Max items 50.
source none, otel, access_log no Where the endpoint mix comes from. An OpenTelemetry trace export or a combined format access log, both read from a file named in source_config.path. Defaults to none.
source_config object no Adapter specific settings. Both sources take a path: the OTLP/JSON trace export, or the access log. Credentials come from the secrets subsystem. Max properties 20.
thresholds object no Deltas that fail the run. Applied to the difference against the base branch, never to absolute numbers.
unsafe_routes list of string no Routes that mutate state destructively. They are included only against a fresh branch that is reset afterwards. Max items 500.

One journey document and how hard to run it.

Field Type Required Notes
iterations integer no How many times each session walks it. Defaults to 1. Minimum 1, maximum 1000.
path string yes The scenario document, relative to the repository root. Max length 512.
sessions integer no How many sessions walk the journey at once. Defaults to 1. Minimum 1, maximum 1000.
start_after string no Delay before this scenario starts, so one journey can burst while another is already running. Matches ^[0-9]+(ms|s|m)$.

Deploy a baseline version alongside the candidate, send both the same requests, and report every difference in what came back and in what ended up in the database.

Field Type Required Notes
base_ref string no The git ref the baseline comes from, or the ref the merge base is taken against. Empty tries origin/HEAD, then origin/main, then origin/master, and says which it used. Max length 256.
baseline merge_base, ref no How the version to compare against is chosen. merge_base answers what this branch changes; ref answers what changes when it ships. Defaults to merge_base.
compare_timestamps boolean no Compare timestamp strings exactly instead of treating two well formed timestamps as equal. Turn it on when timestamps come from the data rather than from the clock. Defaults to false.
compare_uuids boolean no Compare UUIDs exactly instead of treating two well formed UUIDs as equal. Turn it on when identifiers are stored rather than generated per request. Defaults to false.
database Oracle database no The comparison of the two branches’ contents.
enabled boolean no Whether the comparison runs. Present but false is how a project keeps its probe plan and turns the check off for a while. Defaults to true.
fail_on none, minor, major, critical no The lowest severity that fails the command. critical is a request the baseline served and the candidate did not, a status that fell into an error class, or a row the baseline wrote and the candidate did not. Defaults to critical.
ignore Oracle ignore no What the comparison is told not to look at.
probes list of Probe no The requests sent to both versions, in order, byte for byte the same on each side. Max items 200.

The comparison of the two branches’ contents.

Field Type Required Notes
enabled boolean no Defaults to true.
exclude list of string no Tables to leave out, applied after tables. Max items 500.
max_rows integer no How many rows a table may hold and still be compared. A table over the bound is reported as not compared, never silently skipped. Defaults to 10000. Minimum 1, maximum 1e+06.
tables list of string no Tables to compare. Empty compares every table. A pattern is schema.table, and either half may be an asterisk. Max items 500.

What the comparison is told not to look at. Everything here is printed in the report along with the defaults, because an oracle that silently ignores a field is worse than one that reports it.

Field Type Required Notes
fields list of string no JSON paths to skip, in a response body and in a table row alike. $.token, $.orders[*].placed_at and $..created_at are all accepted. Max items 200.
headers list of string no Response headers to skip, in addition to the defaults. Max items 100.

The application’s password policy, so the generated password satisfies it. Without this, an application stricter than the generator refuses a correct password at sign in and the run reports a login failure that looks like the application’s fault.

Field Type Required Notes
forbid string no Characters the application will not accept. Max length 32.
min_length integer no Minimum 1, maximum 128.
symbols string no Replaces the default symbol set, for an application that rejects the ones it uses. Max length 32.

One account an agent logs in as. Personas are created or reconciled in the golden by the authentication adapter, so an agent signs in the way a person does rather than through a bypass.

Field Type Required Notes
attributes object no Extra columns to set on the persona’s row, for a schema with application specific fields. Max properties 50.
email string no Login address. Defaults to name@example.test, which is a reserved domain that can never receive mail. Max length 254.
login none, password, magic_link, email_code, sms_code, totp, session no How this persona signs in. none is for an application with no sign in, or a page that is public: the agent goes straight to start_path. magic_link and email_code read the message from the captured inbox, so they work with no mail provider at all. The runner drives none, password, magic_link, email_code and sms_code today; a persona set to totp or session is reported as blocked with the reason, rather than failing the change. Defaults to password.
mfa boolean no Whether to enroll a time based one time password secret, which the runner holds so that it can complete a challenge. Defaults to false.
name string yes Max length 40, matches ^[a-z0-9]([a-z0-9-]{0,38}[a-z0-9])?$.
phone string no Number an SMS code is sent to. Defaults to a number in the +1 555 0100 block, which is reserved for fictional use and can never reach a real handset. Only sms_code uses it. Max length 32.
role string no Application role to provision, for example admin or member. Interpreted by the authentication adapter. Max length 64.

What each class of finding does to the pull request check. A finding at ‘fail’ fails the check, one at ‘warn’ is reported and the check still passes, and one at ‘ignore’ is not reported at all. Every key here is read when the report is built, so the answer to why a check failed is always one of these keys.

Field Type Required Notes
cleanup ignore, warn, fail no Teardown left a resource behind. The journal remembers what is left, so ‘af down’ can finish the job. Defaults to fail.
egress_surprise ignore, warn, fail no The environment tried to reach a host the manifest does not mention. The request was refused either way; this decides whether the attempt stops the merge. Defaults to fail.
load_regression ignore, warn, fail no A load threshold from the load block being exceeded. Defaults to warn.
masking ignore, warn, fail no The environment’s own branch read back with something in it that still parses as real data. Defaults to fail.
migration_failed ignore, warn, fail no A migration that did not apply to a branch with production’s shape in it. A migration that fails here is one that would have failed in production. Defaults to fail.
migration_lint ignore, warn, fail no Any of the seventeen migration lint rules. They share one setting because the rules are already scoped by table size. Defaults to warn.
migration_lock object no How long a migration may hold a lock on a table. Both figures are compared against a sampled lower bound, so a breach really did hold the lock at least that long.
migration_rewrite ignore, warn, fail no A statement Postgres reported as rewriting a table, which copies every row under a lock nothing can read through. Defaults to warn.
plan_regression ignore, warn, fail no A query plan that got worse in one of three plan regressions: a table is now read end to end, an index is no longer used, or the planner’s estimate grew. Defaults to warn.
query_regression ignore, warn, fail no A statement that runs more often, or slower, than the saved baseline did. Needs a baseline to compare against. Defaults to warn.
workflows_unverified ignore, warn, fail no A run in which no workflow reached a verdict about the application, because every one was blocked or unverified or because none was declared. Distinct from a single blocked workflow, which is never counted against the application: one gap in the tooling is not evidence, and a run where every workflow was a gap has tested nothing at all, so reporting it as a pass says the application was checked when it was not. Set it to warn if the project has no workflows yet and you would rather record that choice than be told about it. Defaults to fail.

One request sent to both versions.

Field Type Required Notes
body string no The request body, sent byte for byte to both sides. Max length 65536.
headers object no Headers sent on both sides. Credentials come from the secrets subsystem, never from here. Max properties 20.
method GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS no Defaults to GET.
name string yes Identifies the request in the report. Min length 1, max length 64, matches ^[a-z0-9][a-z0-9-]*$.
path string yes The path and query, starting with a slash. Min length 1, max length 2048.

What one replica of a service is allowed to use. Absent means the runtime decides, which locally means no limit and on a cluster means the namespace default.

Field Type Required Notes
cpu string no CPU limit, in cores or millicores. Defaults to 1. Matches ^[0-9]+(\.[0-9]+)?m?$.
memory string no Memory limit. Defaults to 1Gi. Matches ^[0-9]+(Mi|Gi|M|G)$.

Run the previous release against the migrated schema and see whether its workflows still pass, which is the invariant a rolling deploy actually depends on.

Field Type Required Notes
against string no Which commit the previous release is: merge-base, previous-commit, or any revision git can resolve, such as a release tag. Defaults to merge-base. Max length 256.
when never, risky, always no risky runs the check only when the pending migrations contain a change the previous release could notice, such as a dropped or renamed column. always runs it for every migration, and costs a second image build and a second environment every time. Defaults to risky.

Where and how long the environment runs. The provider decides the machinery; the rest is the lifetime, the address, and the naming the environment gets.

Field Type Required Notes
domain string no Wildcard domain for environment hostnames. Defaults to localhost, which needs no DNS at all. Defaults to localhost. Max length 253.
idle_sleep string no How long an environment may sit idle before it is scaled to zero. It wakes on the next request. Defaults to 30m. Matches ^[0-9]+(m|h)$.
kubeconfig_context string no Which kubeconfig context to use. Naming it prevents an environment landing on whatever cluster happened to be current. Max length 253.
max_ttl string no The furthest af env extend may push an environment’s expiry, measured from when it was created. A lifetime that can be extended forever is not a lifetime, and this is the bound. Defaults to 168h. Matches ^[0-9]+(h|d)$.
namespace_prefix string no Prefix for Kubernetes namespaces. Defaults to af. Max length 40.
provider local, kubernetes no Defaults to local.
ttl string no How long an environment lives before the reaper tears it down. Extend one you are still using with af env extend, up to max_ttl. Defaults to 24h. Matches ^[0-9]+(h|d)$.

One process the environment runs. A service is built from the repository, given the variables it declared, attached to the environment’s private network, and started in dependency order.

Field Type Required Notes
build Build no How to turn the service directory into an image.
command string no Command that starts the service, overriding the image’s own. Executed with an argument vector, never through a shell. Max length 1024.
depends_on list of string no Services that must be ready first. A cycle is rejected at validation. Max items 50.
env list of Environment variable no Names of environment variables this service needs. Names only. Values come from the secrets subsystem, and a name with no value anywhere fails with AF-SEC-001 rather than starting a service that will misbehave. Max items 200.
health_path string no HTTP path that reports readiness. A service is not considered up until this returns a 2xx or 3xx status. Defaults to /. Max length 512.
health_timeout string no How long to wait for readiness before failing with AF-RUN-004. Defaults to 180s. Matches ^[0-9]+(ms|s|m)$.
kind web, worker, cron no What the service is. A web service gets a hostname and a readiness check; a worker gets neither; a cron service is invoked on a schedule instead of run continuously. Defaults to web.
migrate string no Command that applies pending migrations. Run once against a fresh branch before the services start, and rehearsed with timing and lock analysis when insights are on. Max length 1024.
name string yes Unique within the manifest. Appears in hostnames, logs, and container names. Max length 40, matches ^[a-z0-9]([a-z0-9-]{0,38}[a-z0-9])?$.
path string no Directory containing the service, relative to the repository root. Defaults to the root. A path outside the repository is rejected. Max length 512.
port integer no Port the service listens on. Required for a web service unless detection found it. Minimum 1, maximum 65535.
replicas integer no How many instances to run. Defaults to 1. Minimum 1, maximum 10.
resources Resources no What one replica of a service is allowed to use.
schedule string no Cron expression for a cron service, with an optional CRON_TZ prefix. Evaluated in the declared zone. Max length 128.

Take a production shaped slice rather than the whole database. The closure is computed over foreign keys, so a subset always satisfies every constraint the schema declares.

Field Type Required Notes
enabled boolean no Defaults to false.
follow_dependents integer no How many levels of rows that reference the seed to include. Zero includes only what the seed rows reference, which is the minimum that satisfies foreign keys. Defaults to 1. Minimum 0, maximum 5.
max_rows integer no Upper bound on rows per table, applied deterministically so two runs produce the same subset. Defaults to 1e+06. Minimum 1.
seed_table string no Table the selection starts from, for example the tenant or account table. Max length 128.
seed_where string no A SQL predicate selecting the seed rows, for example created_at > now() - interval ‘90 days’. Max length 2048.
virtual_relationships list of object no Relationships the schema does not declare as foreign keys but the application relies on. Without these, a subset can look complete and still break the application. Max items 200.

One thing the agents do, written as a goal rather than a script. The runner decides the actions and verifies the outcome, so a workflow survives a redesign of the page it happens on.

Field Type Required Notes
budget object no Hard caps. A workflow that exhausts its budget ends as blocked with the reason, never as a partial pass.
description string yes What a person would do, in sentences. Say the goal and what proves it happened, not the selectors. Min length 10, max length 4000.
expect list of string no Observations that must hold for a pass, written as sentences. These are assertions about what the user can see, not about the DOM. Max items 50.
independent boolean no Whether this workflow can run at the same time as others. Workflows that share an environment run one at a time unless this says otherwise, because two agents mutating the same data produce failures nobody can reproduce. Defaults to false.
name string yes Max length 64, matches ^[a-z0-9]([a-z0-9-]{0,62}[a-z0-9])?$.
persona string no Which persona runs it. Defaults to the first persona. Max length 40.
start_path string no Where to begin. Defaults to the application root. Defaults to /. Max length 512.
tags list of string no Max items 20.