Skip to content

Catalog fields

This page lists the fields of the catalog’s files, the values each one accepts, and what the platform does with it. Use it when you write or review a catalog entry: a field that drives something changes real resources once its merge request merges, and a field marked designed is accepted, or planned, but nothing acts on it yet.

The catalog page explains the files themselves and why intent lives there. The examples come from a demo organization, a fictional online retailer.

Each row is one field, with four facts:

  • Required: whether a file must have it, and its default when it may be left out.
  • Values: what the catalog’s checks accept. The catalog’s JSON Schemas and its lint refuse anything else, including any field the schema does not define (enforced: the catalog’s pipeline runs the lint on every merge request).
  • What it drives: what the platform builds or decides from it, and which part of the platform does so.
  • Source: the files that define the field and the code that reads it.

The tables describe the platform at release 2026.10.01-1, as the catalog’s schemas, its lint and the code that reads each field stand on 2026-10-01. A row marked designed is a field the platform’s contracts specify that nothing reads yet, or, for the last four product fields, one the schema does not accept yet.

A product’s file is products/<journey>.<domain>.<context>.<product>.yaml.

product

Required
Yes.
Values
A slug of 2 to 10 characters: lowercase letters and digits, words joined by single hyphens, starting with a letter. It is the last part of the file name, unique within its domain, and never a name the domain has retired.
What it drives
The product's identity everywhere: its repository path, its two project ids, its users group, its state prefixes and its hostname.
Source
catalog schema/common.schema.json, scripts/lint.mjs, docs/derivations.md

journey

Required
Yes.
Values
A journey slug, 3 to 10 lowercase letters, listed in catalog.yaml. It is the first part of the file name.
What it drives
The first level of the product's path, and the DNS zone its hostnames sit in, <journey>.projectairframe.dev.
Source
catalog scripts/lint.mjs; landing-zone roots/network/edge.tf

domain

Required
Yes.
Values
A domain slug, 3 to 8 lowercase letters. It is the second part of the file name, and the pair <journey>/<domain> is listed in catalog.yaml.
What it drives
The project ids, lk-<domain>-<product>, and which domain's project factory root creates the projects and which domain's GitLab root creates the repository.
Source
catalog scripts/lint.mjs; landing-zone roots/project-factory/

context

Required
Yes.
Values
A slug of 3 to 12 characters. It is the third part of the file name, and its context file must exist.
What it drives
The context's GitLab group, which holds the repository, and the context's folder, which holds the projects.
Source
catalog scripts/lint.mjs; landing-zone roots/project-factory/

team

Required
Yes.
Values
A team slug. The team must exist and live in the product's context, and at least one person who may merge, among the team's developers and lead and the leads above the product, must have a GitLab account.
What it drives
Who approves and who may merge, with the leads of the context, domain and journey; the members of the product's users group; the team group's read access to the projects; the team label; the Grafana team.
Source
catalog scripts/lint.mjs; landing-zone roots/groups/main.tf, roots/project-factory/; control-plane gate/src/core/ownership.ts

lifecycle

Required
No. Default { status: active }.
Values
status is active, retiring or removed. retire_after, a date, is required for the last two. removed comes only after retiring, and only once that date has passed.
What it drives
Retiring takes the product's services off the shared edge and keeps every resource. Removed deletes its projects, users group and repository, and needs a tombstone so the name is never reused. A change of status needs the lifecycle label and two approvals: one from the team, one from a domain lead or the platform team.
Source
catalog scripts/lint.mjs, scripts/lifecycle-check.mjs; control-plane gate/src/core/ownership.ts; golden-path modules/cloud-run-service/main.tf

criticality

Required
Yes.
Values
1, 2 or 3; 1 is the most critical.
What it drives
The criticality label; the production database's tier and, at 1, its regional availability; the cap on each service's instances; whether production waits for the sandbox's apply (1 and 2). At 1 or 2 the team needs two on-call members, and at 1 on-call hours always.
Source
golden-path modules/cloud-sql/main.tf, modules/cloud-run-service/main.tf, template/.gitlab-ci.yml.jinja; catalog scripts/lint.mjs

data_classification

Required
Yes.
Values
public, internal, confidential or restricted. restricted requires inner_source: false.
What it drives
The data_classification label on the product's resources.
Source
golden-path modules/airframe-context/main.tf; catalog scripts/lint.mjs

rto, rpo

Required
Yes.
Values
A positive whole number followed by m, h or d, such as 1h or 15m; the lint checks this for rpo. An rpo below 5m needs criticality 1.
What it drives
The production database's recovery: an rpo under a day turns on point-in-time recovery, and the golden path's Cloud SQL module refuses an objective it cannot meet.
Source
catalog scripts/lint.mjs; golden-path modules/cloud-sql/main.tf

monthly_budget

Required
Yes.
Values
Whole US dollars, at least 1. All product and playground budgets together must not exceed the folder's budget in catalog.yaml.
What it drives
A Google Cloud budget on each billed project, 70 percent production and 30 percent non-production, alerting at 80 and 100 percent. The Airframe cost check refuses a change whose priced plans go over it. Raising it needs a domain lead.
Source
landing-zone roots/project-factory/; control-plane policy/airframe/cost.rego, gate/src/core/ownership.ts; catalog scripts/lint.mjs

template

Required
Yes.
Values
fullstack or none. none requires source_repo or repos.
What it drives
Whether the render job writes the repository's first commit from the golden path's template. With none the repository the platform creates stays empty.
Source
control-plane lifecycle/render.sh; catalog scripts/lint.mjs

stack

Required
No. Default node.
Values
node, python-fastapi or java-spring.
What it drives
The application the template renders. The injected build and test job is then chosen by the files that stack leaves in the repository.
Source
catalog schema/product.schema.json; control-plane templates/build-test/template.yml

slo

Required
Yes.
Values
availability, a percentage from 90 to 99.99, and latency_p95_ms, a whole number of milliseconds.
What it drives
The targets on the product's SLO dashboard and its error budget alert rule in Grafana.
Source
operations roots/grafana/pack.tf

quality

Required
No. Default: coverage 80, no ratchet, findings never fail.
Values
minimum_coverage, 0 to 100; coverage_ratchet, true or false; block_on_quality, one of off, info, minor, major, critical or blocker.
What it drives
The injected build:quality job reads it from the catalog at run time and fails below the coverage, below main's coverage when the ratchet is on, or on findings at or above the severity. A change needs a team lead or a domain lead.
Source
control-plane templates/build-test/template.yml, gate/src/core/ownership.ts

external_ingressdesigned

Required
No. Default false.
Values
true or false.
What it drives
Meant to let a route the product declares public skip single sign-on. The golden path passes it to the product's modules, but every product backend still has single sign-on, and the policy pack denies one without it: the building block for a public route is not built.
Source
golden-path modules/service-project/main.tf, modules/cloud-run-service/main.tf; control-plane policy/airframe/cloud_run.rego

inner_source

Required
No. Default true.
Values
true or false.
What it drives
With false, in a domain that has a restricted group, the repository goes there and is private. Elsewhere the repository is public.
Source
control-plane modules/product-repositories/main.tf; landing-zone roots/project-factory/

agentic_opsdesigned

Required
No. Default diagnose.
Values
diagnose, act, auto or propose.
What it drives
How far the operations agent may act on the product. Nothing reads it: that agent is not built.
Source
catalog schema/product.schema.json; landing-zone docs/contracts.md 1.4

preview_concurrency

Required
No. Default 2.
Values
1 to 16.
What it drives
The size of the shared preview database instance, when preview_db is shared.
Source
golden-path modules/preview-substrate/variables.tf, template/infra/np/main.tf.jinja

preview_db

Required
No. Default sidecar.
Values
sidecar or shared.
What it drives
How a preview gets its database: a PostgreSQL container beside the preview's service, or a database of its own in one shared Cloud SQL instance per product.
Source
golden-path modules/preview-substrate/variables.tf, template/infra/eph/main.tf.jinja

preview_ttl_hours

Required
No. Default 72.
Values
1 to 168.
What it drives
How long a preview lives after its latest apply, carried as the expires label on its services; after that it is destroyed.
Source
golden-path modules/preview-substrate/variables.tf, modules/cloud-run-service/main.tf

previewdesigned

Required
No. Default standard.
Values
standard or custom.
What it drives
Whether the product brings its own preview component. Nothing reads it; every preview uses the standard router.
Source
catalog schema/product.schema.json; landing-zone docs/contracts.md 1.4

conformance_leveldesigned

Required
No.
Values
1, 2 or 3.
What it drives
How far along the adoption ladder the product is. Nothing reads it yet.
Source
catalog schema/product.schema.json; landing-zone docs/contracts.md 1.4

residency_profiledesigned

Required
No. Default default.
Values
Only default.
What it drives
Where the product's data may live. Only one profile exists, and nothing reads the field.
Source
catalog schema/product.schema.json; landing-zone docs/contracts.md 1.4

componentsdesigned

Required
No.
Values
A list of name, with an optional criticality and data_classification. The product's name, a hyphen and the component's name are at most 10 characters together.
What it drives
Separate projects for a part of the product with a different profile. No project factory creates them yet.
Source
catalog schema/product.schema.json, scripts/lint.mjs; landing-zone roots/project-factory/

database

Required
No.
Values
tier, a Cloud SQL tier name starting with db-.
What it drives
The tier of the product's Cloud SQL instances, in place of the module's default: the smallest outside production, the criticality's tier in production.
Source
catalog schema/product.schema.json; golden-path template/infra/prod/main.tf.jinja, template/infra/np/main.tf.jinja

services

Required
No.
Values
Names of files in the catalog's services/, each a Google Cloud service the platform has approved.
What it drives
Each service's API is enabled on the product's billed projects and its roles are granted to the product's apply identities. Adding one needs a domain lead.
Source
catalog scripts/lint.mjs; landing-zone roots/project-factory/; control-plane gate/src/core/ownership.ts

sandbox

Required
No. Default false.
Values
true, or tier with a Cloud SQL tier name. Required when another product consumes this product's events or calls it.
What it drives
A permanent environment at main's version in the non-production project, with its own database at the smallest tier or the one named, for other products to test against.
Source
catalog scripts/lint.mjs; golden-path template/infra/sandbox/main.tf.jinja

egress

Required
No.
Values
Hostnames, with no wildcards and no addresses.
What it drives
The egress proxy's allow rules for the product's services. The proxy is off by default because it costs money while idle, and while it is off a product that declares egress cannot deploy.
Source
landing-zone roots/network/egress.tf

egress_tcpdesigned

Required
No.
Values
A list of name, cidrs and port.
What it drives
Outbound connections other than web requests, to named address ranges. Nothing reads it yet.
Source
catalog schema/product.schema.json; landing-zone roots/network/variables.tf

consumes

Required
No.
Values
A list of topic, the publisher's path and event as <journey>/<domain>/<context>/<product>/<event>, and subscription, unique in the product. The publisher must declare the event.
What it drives
Adding one needs the approval of the publisher's owners, unless the event is marked inner_source. The event appears as received on the product's page in the architecture catalog. No module creates the subscription yet, so that part is designed.
Source
catalog scripts/lint.mjs; control-plane gate/src/core/ownership.ts, cli/fragment.py

topics

Required
No.
Values
A list of event, two lowercase words joined by a dot such as order.placed; schema, a path in the product's repository; and inner_source, default false.
What it drives
The events other products may consume, and their pages in the architecture catalog. No module creates the Pub/Sub topic yet, so that part is designed.
Source
catalog scripts/lint.mjs; control-plane cli/fragment.py

calls

Required
No.
Values
Product paths, <journey>/<domain>/<context>/<product>, never the product itself.
What it drives
Adding one needs the approval of the called product's owners, and the called product must run a sandbox. The call appears in the architecture catalog.
Source
catalog scripts/lint.mjs; control-plane gate/src/core/ownership.ts, cli/fragment.py

iap_accessdesigned

Required
No.
Values
A list of team or group.
What it drives
Who else may reach the product behind single sign-on. Nothing reads it yet: the product's users group holds its own team's members.
Source
catalog schema/product.schema.json; landing-zone roots/groups/main.tf

source_repodesigned

Required
No.
Values
The address of the one repository an existing system lives in. Only with template: none.
What it drives
Nothing reads it yet: the repository the platform creates stays empty.
Source
catalog scripts/lint.mjs; control-plane lifecycle/render.sh

reposdesigned

Required
No.
Values
A list of name and role, the role being infra, service, worker, migration or frontend. Only with template: none.
What it drives
A product spread over several repositories. Nothing reads it yet.
Source
catalog schema/product.schema.json; landing-zone docs/adr/0017-multi-repository-products-and-adoption-by-moving-the-group.md

runtimedesigned

Required
Not accepted yet.
Values
cloud-run or gke, in the contracts.
What it drives
Where the product runs: Cloud Run, or namespaces on a shared GKE cluster. The schema does not accept the field yet, so the lint refuses an entry that uses it.
Source
landing-zone docs/contracts.md 1.4; catalog schema/product.schema.json

source_groupdesigned

Required
Not accepted yet.
Values
A GitLab group path, in the contracts.
What it drives
The group an adopted product's repositories live in before they move under the platform's path. The lint refuses it today.
Source
landing-zone docs/contracts.md 1.4; catalog schema/product.schema.json

hostnamesdesigned

Required
Not accepted yet.
Values
Hostnames under a zone the organization holds, in the contracts.
What it drives
The hostnames an adopted product arrives with, which the shared edge would serve as aliases of its own. The lint refuses it today.
Source
landing-zone docs/contracts.md 1.4 and 8; catalog schema/product.schema.json

dependenciesdesigned

Required
Not accepted yet.
Values
A list of name, kind, host and port, in the contracts.
What it drives
A data store or service the product keeps running outside the platform; the network would open the way to it. The lint refuses it today.
Source
landing-zone docs/contracts.md 1.4; catalog schema/product.schema.json

Secrets are never in the catalog. A product’s repository lists them by name in its own secrets file, without values.

A team’s file is teams/<team>.yaml.

team

Required
Yes.
Values
A slug, equal to the file name.
What it drives
The team group, lk-team-<team>@, which holds viewer access to the team's product projects, and the team, its contact point and its alert routing in Grafana.
Source
catalog scripts/lint.mjs; landing-zone roots/groups/main.tf, roots/project-factory/; operations roots/grafana/

context

Required
Yes.
Values
The path of the context the team lives in, <journey>/<domain>/<context>, or platform.
What it drives
Which products the team may manage: a product's team must live in the product's context.
Source
catalog scripts/lint.mjs

lead

Required
Yes.
Values
A person who is a member with the role team_lead.
What it drives
The team's primary contact, on its page in the architecture catalog. The platform team's lead administers the Grafana organization.
Source
catalog scripts/lint.mjs; control-plane cli/fragment.py; operations roots/grafana/members.tf

timezone

Required
No. Default Etc/UTC.
Values
A time zone name, such as Europe/Lisbon.
What it drives
Shown on the team's page in the architecture catalog. Nothing else reads it yet.
Source
catalog schema/team.schema.json; control-plane cli/fragment.py

members

Required
Yes, at least one.
Values
A list of person and roles; the roles are developer, team_lead, oncall and oncall-secondary. A member is active or pending, never departed.
What it drives
Every member may approve changes to the team's products; developers and team leads may also merge them. Active members join the team group, the users groups of the team's products and the team in Grafana.
Source
catalog scripts/lint.mjs, ownership/protected-paths.yaml; landing-zone roots/groups/main.tf

oncalldesigned

Required
No. A criticality 1 product's team needs it.
Values
rotation, weekly or daily; layers, the on-call roles; hours, business or always. A criticality 1 product needs always.
What it drives
The team's on-call schedule, which is not built. Today the values only appear on the team's page in the architecture catalog.
Source
catalog scripts/lint.mjs; control-plane cli/fragment.py

A person’s file is people/<person>.yaml.

person

Required
Yes.
Values
The local part of the email address, such as sam.okafor, equal to the file name.
What it drives
The person's identity in every team, lead list and approval.
Source
catalog schema/common.schema.json, scripts/lint.mjs

email

Required
Yes.
Values
An address in the organization's domain, projectairframe.dev.
What it drives
Group memberships: the groups root adds each active person to their groups by this address.
Source
catalog schema/common.schema.json; landing-zone roots/groups/main.tf

name

Required
Yes.
Values
Any text.
What it drives
The person's page in the architecture catalog.
Source
control-plane cli/fragment.py

status

Required
Yes.
Values
active, pending or departed.
What it drives
Only active people join groups. A pending person, with no account yet, keeps their roles and lead positions. The lint refuses a departed person in a team or a lead list.
Source
catalog scripts/lint.mjs; landing-zone roots/groups/main.tf

gitlab_username

Required
No.
Values
A GitLab username.
What it drives
GitLab memberships and merge rights, and the approval policy's named approvers: only active people with a username count.
Source
catalog scripts/lint.mjs; security-policies scripts/approvers.py; control-plane roots/gitlab/

grafana_username

Required
No.
Values
The person's Grafana Cloud login, once single sign-on has created the account.
What it drives
Membership of the Grafana organization and of the person's teams there.
Source
operations roots/grafana/members.tf

profile

Required
No.
Values
about, expertise, links and hours. A change to it needs the person: their approval, or a merge request they opened with only their own commits.
What it drives
The person's page in the architecture catalog.
Source
catalog ownership/protected-paths.yaml; control-plane gate/src/core/ownership.ts, cli/fragment.py

A journey’s file is journeys/<journey>.yaml.

journey

Required
Yes.
Values
3 to 10 lowercase letters, equal to the file name and listed in catalog.yaml.
What it drives
The journey's folder, its GitLab group and its DNS zone, <journey>.projectairframe.dev.
Source
catalog scripts/lint.mjs, docs/derivations.md

leads

Required
Yes, at least one.
Values
People, the first being the primary contact. None may be departed.
What it drives
The group lk-journey-<journey>-leads@. Journey leads may merge on every product below.
Source
catalog schema/journey.schema.json, scripts/lint.mjs; landing-zone roots/groups/main.tf

description

Required
Yes.
Values
Text.
What it drives
The journey's page in the architecture catalog.
Source
control-plane cli/fragment.py

A domain’s file is domains/<journey>.<domain>.yaml.

domain

Required
Yes.
Values
3 to 8 lowercase letters, equal to the second part of the file name and listed as <journey>/<domain> in catalog.yaml.
What it drives
The domain's folder, its leads group and its two subnets in each network come from the catalog. Its GitLab groups, its project factory root and its GitLab domain root are changes to the platform itself.
Source
landing-zone roots/folders/, roots/groups/, roots/network/; control-plane roots/gitlab/

journey

Required
Yes.
Values
The journey it belongs to, equal to the first part of the file name. The journey's file must exist.
What it drives
Where the domain sits, under the journey's folder and group.
Source
catalog scripts/lint.mjs

leads

Required
Yes, at least one.
Values
People, as for a journey.
What it drives
The group lk-<journey>-<domain>-leads@. Domain leads may merge on every product below and approve its entries; one must approve a raised budget or a new service, and a domain lead or the platform team gives one of the two approvals a lifecycle change needs.
Source
landing-zone roots/groups/main.tf; control-plane gate/src/core/ownership.ts

description

Required
Yes.
Values
Text, at most 200 characters.
What it drives
The domain's page in the architecture catalog.
Source
catalog schema/domain.schema.json; control-plane cli/fragment.py

restricted_subtree

Required
No. Default false.
Values
true or false.
What it drives
A restricted group inside the domain's GitLab group, where products with inner_source: false get private repositories.
Source
control-plane roots/gitlab/groups.tf, modules/product-repositories/main.tf

A context’s file is contexts/<journey>.<domain>.<context>.yaml. A small domain still declares one context, named after the domain.

context

Required
Yes.
Values
A slug of 3 to 12 characters, equal to the third part of the file name.
What it drives
The context's folder, and its GitLab group, which holds the repositories of its products.
Source
catalog scripts/lint.mjs; landing-zone roots/folders/; control-plane roots/gitlab/

domain

Required
Yes.
Values
Its domain, equal to the second part of the file name. The domain's file must exist.
What it drives
Where the context sits, under the domain's folder and group.
Source
catalog scripts/lint.mjs

journey

Required
Yes.
Values
Its journey, equal to the first part of the file name.
What it drives
Where the context sits.
Source
catalog scripts/lint.mjs

leads

Required
Yes, at least one.
Values
People, as for a journey.
What it drives
The group lk-<journey>-<domain>-<context>-leads@. Context leads may merge on every product of the context and approve its entries.
Source
landing-zone roots/groups/main.tf; catalog ownership/protected-paths.yaml

description

Required
Yes.
Values
Text.
What it drives
Shown with the context on its domain's page in the architecture catalog.
Source
control-plane cli/fragment.py

Where it lives

In the catalog repository:

In the landing-zone repository:

MIT license. Copyright Airframe contributors.

This site describes platform release 2026.10.20-1.