Skip to main content
Version: 0.2 (next)

CRD reference

Infrared keeps everything it knows in its own custom resources, so kubectl get shows you the same state the UI does. This page lists every kind, what it is for, and the fields worth knowing. Most of the time you change these through the UI, ir or the API, which check what you ask for before they write it. Read them here when you script against the cluster, debug a stuck object, or want to know exactly what a setting does.

All kinds are in the API group infrared.darkshift.io, version v1alpha1. Cluster-scoped kinds describe the control plane. Namespaced kinds belong to one org and live in its namespace, ir-org-<org>.

Most kinds also have status.observedGeneration and status.conditions (Ready, Progressing, Degraded). BreakGlass, User, GitConnector, Domain and Incident don't. The tables below leave these common fields out and list only the extra conditions a kind adds.

Resources Infrared creates carry the label app.kubernetes.io/managed-by: infrared. Org resources carry infrared.darkshift.io/org, and resources seeded from the catalog carry infrared.darkshift.io/catalog.

KindShort nameScope
InstallationirinstCluster
OrganizationirorgCluster
ClusterirclusterCluster
BreakGlassnoneCluster
UsernoneCluster
GitConnectornoneCluster
GitProviderirgitir-org-<org>
GitopsRepoirgitopsir-org-<org>
Productirproductir-org-<org>
AgentRolearir-org-<org>
AgentWorkflowawir-org-<org>
AgentWorkflowRunawrir-org-<org>
Releaseirrelir-org-<org>
ReleaseCutircutir-org-<org>
Teamirteamir-org-<org>
Humanirhumanir-org-<org>
Domainnoneir-org-<org>
Incidentirincir-org-<org>
CloudAccountcloudacctir-org-<org>
Registryregir-org-<org>

Installation​

The singleton that tracks the setup wizard and holds the install's own settings. It must be named infrared. The API fills in the spec as the wizard advances, and the operator works out the phase from it.

FieldMeaning
spec.tokenVerifiedSet once someone has presented the one-time setup token.
spec.admin.emailThe root user's address. The root user is the first platform admin, made by the setup wizard, and its password's hash is in the BreakGlass named root.
spec.admin.passwordSecretRefDeprecated, and only on installs set up before BreakGlass existed. The API copies the hash from this Secret once, then clears the reference after you delete the Secret.
spec.platformOrgThe Organization that administers the control plane.
spec.managementClusterThe Cluster Infrared runs on.
spec.gitProviderRef, spec.gitopsRepoRefThe platform org's GitProvider and GitopsRepo.
spec.previewsHow zones get their addresses. domain is the platform domain: a zone answers at https://<zone>.<domain>, except a Production zone named <product>-production or <product>-prod, which answers at https://<product>.<domain>. A wildcard DNS record for the domain must point at the management cluster's ingress. signInURL is Infrared's public https:// address, where visitors sign in. ingressHost and ingressIP are what an org's own domains point at, with a CNAME or an A record. See the rows below for the rest.
spec.previews.managedRoots[], cloudflareTokenSecret, cloudflareTokenKeyDomains Infrared manages in Cloudflare, under which any org can claim a subdomain, and the Secret in Infrared's namespace (and its key, api-token by default) that holds a token allowed to edit their DNS. See Domains and addresses.
spec.previews.customHostnames, acmeEmail, domainTokenKeyOn the gateway edge behind Cloudflare: serve addresses under an org's own domains as Cloudflare for SaaS custom hostnames, the address Let's Encrypt writes to about their certificates, and the key of a separate Cloudflare token when the platform domain is in another Cloudflare zone from Infrared's own address.
spec.edgeHow traffic from outside reaches Infrared and its zones: traefik (the default, through Traefik Ingresses) or gateway (one shared Gateway, run by Envoy Gateway).
spec.modelstiers maps each model tier (frontier, balanced, fast) to a model ID. Empty tiers use claude-opus-5-5, claude-sonnet-5-5 and claude-haiku-4-5-20251001. prices[] sets model, inputUSD, outputUSD, cacheReadUSD and cacheWriteUSD per million tokens for cost estimates; leave it empty to use the built-in list prices. See Models and costs.
spec.backupWhere backups go and how they are made. destination holds provider (linode, s3 or gcs), bucket, endpoint, region, prefix (default: the management cluster's name) and credentials. Credentials are kind: accessKey with a secretRef to the Secret that holds the key, for linode and s3, or kind: serviceAccount for gcs, which uses the identity of whatever runs and keeps nothing in a Secret. The key itself is never here. Then schedule (default 5 * * * *, UTC), mirror.schedule (default 17 * * * *), retention (default 7d), recipients[] (age public keys; without one no backup is made) and postgres.archive (not with gcs). Set it in Settings → Backups. See Back up and restore.
spec.summaryVideos.enabledWhether this install makes summary videos, switched in Settings → Install features. Off or unset, no org can make one. See Summary videos.
spec.signIn.google.allowedDomainsThe Google Workspace domains whose people may sign in with Google, such as example.com. A sign-in needs both the ID token's hd claim and the email address's domain on the list. Each entry is lower-case with at least one dot and no wildcard. Empty means nobody signs in with Google. Platform admins change it in Settings → Sign-in, signed in with Google or as the root user. The Google OAuth client, and whether the root user's password still signs in, are chart values, not fields here. See Sign in with Google.
spec.signIn.google.groupRolessince and by. The API sets it once, when a platform-admin access group of the platform org first has a Workspace group that holds an active person. From then on, Google sign-ins take their roles from Workspace groups, and an allowed domain no longer makes everyone a platform admin. Infrared never clears it. See What a Google session can do.
spec.signIn.google.selfSignUpOpens Sign in with Google to anyone with a verified Google account, as a hosted control plane does. enabled gives a first sign-in that holds no role an org of its own on the install's Gitea. products, people, newTeams and publicEnvironments are the limits that org starts with (see the Organization's spec.limits). A platform admin sets it in Settings → Sign-in. It is refused on an install without Gitea.
status.phaseAwaitingToken, AwaitingAdmin, AwaitingOrg, AwaitingCluster, AwaitingGitProvider, AwaitingGitopsRepo, Syncing or Ready.
status.versionThe Infrared control plane version.
status.backupWhat the operator last saw of backups: lastBackup, lastBackupAt, lastMirrorRun, lastPoint, lastPointAt and message. Stamps are UTC, such as 20261006T010500Z. The condition BackupsHealthy says whether they are on time.
status.postgresServerNameThe name the platform's Postgres archives under in the backup bucket. Chosen once and never changed.

Organization​

An org: the tenancy and RBAC boundary. A name is at most 56 characters, so ir-org-<name> fits a namespace, and a few names are reserved, such as platform, infrared, argocd, builds, default and new.

FieldMeaning
spec.displayNameThe name people see in the UI.
spec.platformTrue for the org that administers the control plane.
spec.clusterAllowlistThe workload clusters this org may place zones on. A platform admin sets it. See Workload clusters.
spec.clusterSelfServiceLets the org's admins register and build workload clusters of their own, by kubeconfig or through one of the org's cloud accounts. A platform admin sets it; off by default. See Workload clusters.
spec.accessGroups[]Who holds which role in the org, one entry per access group. name is a DNS label. role is platform-admin (platform org only), org-admin, member or viewer. googleGroup is a Google Workspace group's address in an allowed domain; its people hold the role when they sign in with Google. members[] are GitHub logins: people who sign in with GitHub, and, on an access group with no googleGroup, people who sign in with Google and linked that login. emails[] are people by their Google address, for people with no Workspace group or linked login, such as an org made by self-service sign-up; adding an address is the invitation. githubTeam is the slug of a GitHub team in the org's GitHub organization that infrared-operator keeps in step, one per access group. description is free text. See Access groups.
spec.teams[]Deprecated: the old name of spec.accessGroups. It is read only while spec.accessGroups is empty, and you can't set both. Move its entries to spec.accessGroups.
spec.limitsBounds on what the org may hold, beyond the license's install-wide limits. products caps its Products, people caps the people it names (in its access groups, and its Humans), newTeams caps the Teams it may make beyond the catalog's default Teams, and publicEnvironments: false stops it making an environment public. Zero or unset means no cap, except that newTeams: 0 means none. Self-service sign-up sets them; a platform admin may change them, and may go past them.
spec.schedulingenabled turns on the cron triggers of the org's AgentWorkflows (off when absent). timeZone, such as America/New_York, is the zone schedules are read in; empty means UTC. See Triggers and scheduling.
spec.modelTiersThe org's own tier-to-model mapping: frontier, balanced, fast. Empty fields use the Installation's. See Models and costs.
spec.summaryVideosenabled gives each Change that finishes or stops a short summary video. monthlyCapUSD stops making them once the month's videos cost that much (default 5). timeZone is the zone a video's greeting uses (default America/New_York). See Summary videos.
spec.slackThe org's Slack workspaces and where Infrared posts. workspaces[] each have teamID, teamName, tokenSecret (the Secret in the org's namespace with the bot token) and who connected it. destinations[] each have name, teamID, channelID, channelName and kinds[], what goes there (summary for summary videos; empty means everything). Older single-workspace fields (teamID, channelID and the like) are still read until the org's Slack settings are next saved. See Slack.
spec.buildRegistryThe Registry, in the org's namespace, that its Products build into from their next build. Empty means the install's default registry. See The build registry.
status.namespaceThe org's namespace, ir-org-<name>.
status.accessGroups[]For each access group, by name, infrared-operator's last sync of its GitHub team, under githubTeam: slug, url, members[] on GitHub after the sync, skipped[] (each login it didn't add or remove, with the reason), syncedAt, and message when the sync couldn't run. See GitHub teams.

A non-platform org carries the finalizer infrared.darkshift.io/org-cleanup. When you delete the org, it holds the Organization until Infrared has removed the org's Argo CD objects and its builds namespace.

Cluster​

A management or workload cluster.

FieldMeaning
spec.typemanagement or workload.
spec.flavork3s or eks. Selects the distribution's own components.
spec.provider, spec.regionaws, gcp, linode or local, and the provider's region.
spec.template.module, spec.template.versionThe cluster template (a module in infrared-iac-modules, gcp/gke-cluster or aws/eks-cluster) and its tag.
spec.serverThe API server URL Argo CD uses. Empty means the kubeconfig's server, or in-cluster.
spec.connectionHow Infrared and Argo CD reach a workload cluster. inCluster: true places its zones on the management cluster itself. kubeconfigSecretRef (name, key) names a kubeconfig in namespace infrared with a token or client-certificate user. When you give the API a kubeconfig, it stores it as cluster-<name>-kubeconfig, key kubeconfig. See Workload clusters.
spec.provisionRuns the cluster template with OpenTofu. action is plan (the default), apply, which creates billable cloud resources, or destroy, which lifts the template's guards and deletes what it built. source defaults to the template's module in infrared-iac-modules at template.version. variables are the module's inputs. image defaults to ghcr.io/opentofu/opentofu:1.10. Without a cloud account, the Job's credentials are the keys of the Secret cluster-<name>-credentials in namespace infrared, such as AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and AWS_REGION. credentialsSecretRef is deprecated and ignored. See Build a cluster with OpenTofu.
spec.provision.cloudAccountA Verified CloudAccount of the platform org, for the same cloud as spec.provider. Before each OpenTofu run, Infrared mints its short-lived credentials as cluster-<name>-credentials and deletes them when the Job ends. See Cloud accounts and registries.
spec.ownerThe org a workload cluster belongs to: org and registeredBy (org when one of the org's admins registered it, so its registry lives in the org's gitops repo, or platform). Empty means the platform's. An org's cluster is reached by kubeconfig or built through the org's own cloud accounts, and the org may place zones on it without the cluster allowlist. It can't change.
status.kubernetesVersion, status.nodesThe version and node count Infrared last saw.
status.detectedTrue for the cluster Infrared found itself running on.
status.argoServer, status.argoSecretThe server URL Argo CD Applications use for the cluster, and the Argo CD cluster Secret Infrared wrote (cluster-<name> in argocd; none for inCluster).
status.gitopsPathThe gitops repo folder whose Applications run on the cluster, registry/clusters/<name>/components.
status.provisionThe last OpenTofu Job: job (in namespace infrared), action, phase (Waiting for the credentials Secret, Running, Succeeded or Failed), message, and the Cluster generation it ran for.
status.inventoryWhat deleting the cluster would remove, read every ten minutes while it is reachable: whether Infrared built it, an hourlyCost estimate, volumes[], loadBalancers[] and applications[].
status.deletionOnce you delete the cluster: its phase, its mode (destroy for a cluster Infrared built, disconnect for one it only registered), whether volumes are backed up first, its steps[] (each Pending, Running, Waiting, Stuck, Done, Skipped, Failed or Forced), the volume snapshots[], and leaks[], anything it may have left behind. See Delete a cluster.
status.conditionsBesides the common ones, Connected (Infrared reaches the API server) and Registered (Argo CD can deploy to it and the gitops repo has its app-of-apps).

A workload Cluster carries the finalizer infrared.darkshift.io/cluster-deletion until its deletion has run. The API sets infrared.darkshift.io/delete-backup (false skips the volume backup), infrared.darkshift.io/delete-by and, to move a stuck step on, infrared.darkshift.io/delete-force.

BreakGlass​

The root user: the install's first platform admin, a break-glass account whose password lives only in a vault outside Infrared. There is one object, named root, and only the API writes it. Nothing in it is the password. See Break glass.

FieldMeaning
spec.emailThe root user's sign-in address.
spec.passwordHashThe bcrypt hash of the root password. Nothing else of the password is kept.
spec.vaults[]Up to 5 links to the vaults that hold the password: name, as people know the vault, and url (https://). Links only, never a secret.
spec.itemThe vault item's name.
spec.holdersGroupThe Workspace group of the people who should be able to open the vault. It is a record only; the vault decides who opens it.
status.passwordSetAt, status.passwordSetByWhen the password was last set, and by whom: a platform admin's address, setup or migration. A root session signed in before then is signed out.
status.rotations[]The password's last 20 changes, newest first: at and by.
status.uses[]The root user's last 100 uses, newest first: at, method (password, sign-in-link or token), client (the caller's address), host (the address Infrared was opened at), userAgent and detail.
status.useCount, status.lastUsedAtHow many uses there have been in all, and when the last one was.
status.refusalscount and lastAt of refused password sign-ins, written at most once a minute.
status.migratedFrom, status.generatedPasswordRemovedOn an install set up before this record existed: where the hash was copied from, and whether the API removed a generated plain-text password, in which case rotate the password.

User​

A person who signs in with Google, as Infrared knows them. The API makes it at their first Sign in with Google and names it google-<subject>, after the Google account's stable ID. See Linked accounts.

FieldMeaning
spec.google.subject, spec.google.emailThe Google account's stable ID (the ID token's sub claim) and its address, as last read at sign-in.
spec.displayNameThe name Google gives the person.
spec.links[]The person's linked git accounts, one per git connector, at most 20: connector, kind (github, gitlab or gitea), id (the forge's numeric user ID), login (as last read from the forge) and linkedAt. Each link also sets the label links.infrared.darkshift.io/<connector>: <id>, so an account belongs to one person.
status.lastSignInAtThe person's last Sign in with Google.
status.directoryWhat Google Workspace's directory said of the person: checkedAt, suspended, and groups[], the mapped Workspace groups they are in, nested groups included. After 10 minutes it no longer counts.

GitConnector​

A forge people link their git accounts on: GitHub, GitLab or Gitea, at an address. Named by a DNS label; the API writes it. See Git connectors.

FieldMeaning
spec.kindgithub, gitlab or gitea.
spec.displayNameWhat people see, as in Link GitHub.
spec.baseURLThe forge's https:// address in a browser, such as https://github.com or https://git.example.com.
spec.githubApp.organizationLink through the OAuth client of that Infrared org's GitHub App (kind github only).
spec.oauth.clientID, spec.oauth.clientSecretRefAn OAuth application made on the forge for Infrared. The secret is the key <connector>.client-secret of the Secret infrared-git-connectors in Infrared's namespace. A connector has exactly one of githubApp and oauth.
spec.managedTrue when Infrared registered the OAuth application on its own Gitea.
status.conditionsReady: the last check found the forge accepting the client.
status.checkedAtWhen the connector was last checked.

GitProvider​

Connects an org to its forge: GitHub through a GitHub App (github-app), or the Gitea the chart runs (gitea).

FieldMeaning
spec.typegithub-app or gitea.
spec.ownerThe GitHub organization (or Gitea owner) Infrared manages.
spec.github.appID, spec.github.slugThe GitHub App.
spec.github.installationIDSet once the App is installed on the owner.
spec.github.privateKeySecretRefThe Secret key that holds the App's PEM private key.
spec.github.webhookSecretRefThe Secret key that holds the webhook secret. Optional.
spec.github.apiURLOverrides https://api.github.com, for GitHub Enterprise Server.
spec.giteaFor gitea: url (the Gitea server as the cluster reaches it), user (the Gitea user Infrared acts as, such as ir-acme) and secretRef, the Secret with its username, password, token and read-token.
status.installationVerified, status.lastVerifiedTimeWhether and when the App last minted an installation token.

GitopsRepo​

An org's gitops repo, which Infrared creates, hydrates and bootstraps.

FieldMeaning
spec.providerRefThe GitProvider that owns the repo.
spec.name, spec.visibility, spec.defaultBranchDefault gitops, private (or internal, public) and main.
spec.template.repo, spec.template.versionThe gitops template (default https://github.com/darkshiftio/infrared-gitops-template) and the tag or full commit it is hydrated from.
spec.cluster, spec.clusterFlavorThe management cluster the registry bootstraps, and its flavor (default k3s).
spec.bootstrapApply Argo CD and the root Application after hydration. Default true.
spec.modemanagement (the default) for the platform org's repo, which runs the whole management cluster. org for any other org's repo, which holds only that org's Products: Infrared applies its Applications itself, each inside the org's own AppProject (org-<org>), and never installs Argo CD from it.
spec.infraredSubchartWhen set, the infrared Application installs an umbrella chart that wraps Infrared's chart under this name, such as infrared-core, and every render nests its values there.
status.phasePending, Created, Hydrated, Bootstrapped or Synced.
status.url, status.commit, status.hydratedVersionThe repo's URL, the last hydration commit and the template version used.
status.hydratedChartVersion, status.hydratedByChartVersionThe Infrared chart version the last hydration rendered, and the chart version of the operator that ran it. When either moves, the operator hydrates again.
status.bootstrappedCommitThe hydration commit whose Argo CD install and registry Application were last applied. Bootstrap runs again only when status.commit moves past it.
status.restorePointThe backup stamp a restore in progress came from, while the hydration renders a restore.
status.components[]Each component of the template as the last hydration rendered it: name, rendered, and for one left out, reason (Disabled or NotApplicable) and message.
status.waves[]Per sync wave, each Application's sync (Synced, OutOfSync, Unknown) and health (Healthy, Progressing, Degraded, Suspended, Missing, Unknown).

Product​

The unit Infrared builds, deploys and manages change for. A few names are reserved, because a Product's zones are the namespaces <name>-*: among them argocd, builds, infrared, kube, kpack and monitoring. The condition NameAllowed says whether the name may be used.

FieldMeaning
spec.displayName, spec.descriptionShown in the UI.
spec.ownerThe Product's product owner: a Human in the org, by name.
spec.providerRefThe forge the Product's repos are on, github or gitea, for an org with both. Empty means the org's forge. It can't change once set.
spec.repos[]The repos in the Product, each an app that is built and deployed: owner (empty means the GitProvider's owner) and name. At least one. A repo belongs to one Product.
spec.currentReleaseThe release in progress, such as 2.4.
spec.logorepo (default: the first repo) and path (default: found where logos usually live). See Products.
spec.deliveryHow deployments ship. Without it, Infrared starts no deployments for the Product. strategy is isolated (the default) or umbrella, one version of the umbrella chart with every repo's image; see Deliver several repos as one chart. repo is the repo deployed and tagged vX.Y.Z (empty means the first; with umbrella delivery, the repo that runs from the chart itself). buildImage is the kpack Image in namespace builds (empty means the Product's name). scaffold has kind (static, node, go, or auto for a new repo whose code is still to come) and root for a static site; Infrared then writes the build, a generic web chart and the zones' files into the gitops repo and starts the first deployment. zones[] lists the zones in promotion order. See Deliver a single app.
spec.delivery.zones[]name (also its namespace), environment (pre-release, the default, or release), approval (auto or human; empty means auto for pre-release and human for release), preview (an address under the platform domain, behind sign-in), public (open it to anyone; org admins only), replicas (0 to 20), resources (cpu and memory per pod) and storage[] (up to 8 volumes: name, size, mountPath). The rows below cover addresses, checks, variables and placement. See Environments and instances.
spec.delivery.zones[].addresses[], primaryAddressUp to 10 more addresses: domain, name (empty for the domain itself) and redirect (send visitors to the zone's first address that doesn't redirect). primaryAddress is the address Infrared opens the zone at: custom (the default, the first non-redirecting address while it serves) or automatic (its address on the platform domain). See Domains and addresses.
spec.delivery.zones[].verifyA smoke check after Argo CD reports the zone Healthy: url, expectStatus (default 200), contains and soak (default 2m).
spec.delivery.zones[].guardThe release guard. hold defaults to 5m (0s for none). rollback is rollback (put back what the zone ran before when it fails the guard) or notify (report it and keep the new version); notify applies when it is unset, and the API sets rollback on every zone it adds. checks[] adds up to 10 more checks shaped like verify. sloBurn is the error budget check, on when unset: threshold is the burn rate that fails the zone (default "14.4", "0" turns it off), and slos[] names the SLOs it reads (default all of the zone's).
spec.delivery.zones[].env[], secretEnv[]The zone's environment variables. Plain ones (name, value) go into its values file in the gitops repo. Secret ones list only their name: the values live in the Secret <product>-<zone>-env in the org's namespace, which Infrared copies into the zone as <product>-env. See Environment variables.
spec.delivery.zones[].cluster, valuesPath, applicationPathWhere the zone runs (empty means the gitops repo's management cluster; otherwise a cluster on the org's allowlist or one it owns), and where its files are, by default products/<product>/zones/<zone>/values.yaml and registry/clusters/<cluster>/components/product-<zone>.yaml.
spec.delivery.zones[].targetEmpty for a zone that is one of the Product's namespaces, or controlPlane: the install's own control plane. A deployment then upgrades the control plane to the umbrella chart's version behind the upgrade guard, a Job running the operator that was there before, which rolls a bad upgrade back. Only the platform org may hold such a zone, as the Product's only zone, with strategy: umbrella, components and charts. controlPlane holds application (the Argo CD Application that installs the chart, default infrared) and guardTimeout (default 15m).
spec.delivery.components[], spec.delivery.chartsFor a Product with a control plane zone. Each component has name, repo, buildImage (or none, to carry its pin), valuesKey and repository. charts says where a release goes: releaseRegistry (images, copied by digest and tagged with the version), chartRegistry (the umbrella chart, pushed to OCI), subchart (name, repo, path), firstVersion, historyFrom and buildsNamespace.
spec.slos[]Service level objectives, measured per zone: name, description, objective (a percent, such as 99.5), window (default 168h), zones[] (empty means every delivery zone) and one indicator. The indicator is availability (metric, errors (default code=~"5.."), filter), latency (histogram, threshold in seconds, filter), uptime (the share of minutes with a ready pod, from kube-state-metrics; optional deployment), or, on the gateway edge, edgeErrors or edgeLatency (thresholdMS), read from Envoy. Every Product with zones gets an uptime SLO (99.5%, 168h), and on the gateway edge also edge-errors (99.5%) and edge-latency (99% within one second), unless it defines its own by those names. See SLOs.
spec.statusPagepublic serves the status page to anyone at /status/<org>/<product>. zones[] picks the zones it shows; empty means the Production zones. See Status page.
spec.humanApprovalsWhether people approve the Product's Changes and deployments. false makes triage, human approval and promotions to approval zones approve themselves. A reviewer's BLOCK, a failed step and a dead-lettered step still wait for a person. Omitted means true. See Turn human approvals off.
spec.slackThe Product's own Slack destinations: mode (add, the default, adds them to the org's; replace uses them alone) and destinations[], shaped like the org's. Omitted means the org's. See Destinations per Product.
spec.umbrellaWhere a Product with more than one repo, or with umbrella delivery, keeps its umbrella chart: repo (the org's charts repo, default charts), chart (default: the Product's name) and disabled (refused with umbrella delivery).
spec.kind, spec.platformDeprecated. They described Infrared itself as a platform Product. A Product with umbrella delivery and a controlPlane zone does the same now, and converting one clears both fields.
status.logorepo, path, sha, contentType, bytes, source (detected or uploaded), syncedAt, pending and message. Cached in the ConfigMap <product>-logo.
status.zones[]What each zone runs, as the deployments that promoted to it recorded: name, version, image (the pin), release, chart (the umbrella chart's tag, with umbrella delivery) and promotedAt. Then addresses[], what each address does now, checked every few minutes: host, dns, certificate (Ready, Pending or Failed), serving (the HTTP status it answered), records[] to add at your DNS provider, message and checkedAt. And rollout, which follows the zone's latest address or access change until it is live: commit, summary, at, phase (committed, syncing, certificate or live) and liveAt.
status.zoneFilesWhether every zone has its values file and Application in the gitops repo: ready, message, scaffolded[] (zones whose files Infrared copied from another zone), zones[] (every zone whose files Infrared has seen, with name, values, application, applicationName, namespace and cluster), removing[], and envNotice, which says why the chart can't take environment variables yet.
status.observabilityThe VMRule that holds the SLOs' recording and alerting rules: rules, ready, message, and edgeZones[], the zones the edge SLOs read.
status.teams[]The Teams that work on the Product: name and responsibility (own or contribute).
status.umbrella, status.platformThe state of the Product's umbrella chart, and for a Product with a control plane zone, its components, their builds and the version running.

When you take a zone out of spec.delivery.zones, Infrared removes it. It deletes the zone's files from the gitops repo with a pull request it merges, Argo CD deletes what the zone's Application deployed, and Infrared deletes the zone's namespace on the management cluster. Deleting a Product does the same for every zone, its build and its chart. The finalizer infrared.darkshift.io/zones holds the Product until that is done, and status.zoneFiles.message says what it is waiting for.

AgentRole​

A job an agent performs. See AgentRoles, AgentWorkflows and AgentWorkflowRuns.

FieldMeaning
spec.displayName, spec.summaryThe name, and a one-sentence summary of at most 280 characters.
spec.categoryarchitect, change-review, scheduled or builder.
spec.missionThe outcome the role is accountable for.
spec.responsibilities[]Its steps, in order.
spec.triggers[]type (adhoc, onChange, cron or event), schedule, event, description, and optional filters labels[], paths[] (globs) and branches[].
spec.inputs[]source and description.
spec.outputs[]What the role leaves behind.
spec.evidence[]kind (screenshot, video, report, log, comment, diff, sarif, metric, document, trace or sbom), description and required.
spec.successCriteria[]Statements you can check, which must all hold.
spec.guardrails[]What the role must never do.
spec.permissionsallowedTools, deniedTools, git, cluster, network (none, allowlist, the default, or open), egressAllowlist, mayMerge and publish. Deny wins over allow. egressAllowlist may contain $(ZONE_HOSTS), which the runner expands to the Product's zone hostnames. publish lets the role's steps push images and charts to the install's registry under <org>/<product>; the agent never sees the key.
spec.escalationwhen[], to (a GitHub team or user handle) and after (a duration such as 30m).
spec.opinions[]name, title, guidance, origin (catalog, org or tailored) and enabled. Omitted means on; false keeps the opinion, but the agent doesn't receive it.
spec.verdicts[]The verdicts a step may end with, such as VERIFIED, MERGE WITH FOLLOW-UPS or BLOCK. Every step ends with exactly one.
spec.instructionsMarkdown added to the role's prompt for the org.
spec.skills[], spec.mcpServers[]The skills and MCP servers the org configured for the role, by name.
spec.modelproviderRef, model (a model ID, which wins over tier), tier (frontier, balanced or fast; omitted means frontier), reason, maxBudgetUSD (a decimal string) and maxTurns. See Models and costs.
spec.enabledWhether the role runs. An AgentWorkflow step that uses a disabled role is Skipped, and the steps that need it continue.
spec.origincatalog (the catalog version it was seeded from), tailored and tailoredFrom[].
status.statsruns7d, succeeded7d, medianTokens and lastRunTime.
status.differsFromCatalogTrue when the org edited the role after it was seeded.

AgentWorkflow​

Orders AgentRoles and gates into a workflow you can run again and again.

FieldMeaning
spec.displayName, spec.descriptionShown in the UI.
spec.triggers[]Shaped like an AgentRole's triggers.
spec.steps[]name, type (agentRole, human, auto, ci or promote), agentRole, zone, required, onFailure (deadLetter, fail or continue), maxAttempts, needs[], independent, when, approvers[], minApprovals, timeout and description. Empty needs means the previous step, and independent: true starts the step with the workflow. approvers, minApprovals (default 1) and timeout set up human gates; timeout works on any step. A step whose AgentRole is switched off is Skipped.
spec.steps[].whenA condition such as change.author in [human], agentRole.enabled, label:security or pullRequest.conflicted (true when the Change's pull request can't merge cleanly into its base), combined with && and negated with !. A merge step that meets conflicts goes back to the latest pullRequest.conflicted step, up to 3 rounds.
spec.steps[].modeWhat an agentRole step works on: build, review, issue, resolve (apply a conflicted Change again on its base branch) or report (no Change; read and report). Empty means build for the first agentRole step and review after it, or report in a run without an issue or pull request.
spec.steps[].model, spec.steps[].maxBudgetUSDOverride the AgentRole's model for this step (a tier or a model ID), and cap what one attempt of it may spend. See Models and costs.
spec.steps[].returnTo, spec.steps[].maxReturnsAn earlier agentRole step the run goes back to when this step ends with CODE CHANGE NEEDED: QA or a reviewer found that the builder must fix the code. The builder fixes it on the same branch and every step from it runs again. maxReturns (1 to 5, default 2) bounds how often; after that the step fails and onFailure hands the Change to a person.
spec.steps[].deliverWhere a report step's output goes: issue (an issue on the Product's backlog, the default) or slack (a draft to the org's Slack; nothing is opened on the forge).
spec.deadLetterto (default: the human reviewer) and notify[] channels, such as slack:#checkout-changes.
spec.maxConcurrencyHow many runs may go at once. Default 3.
spec.budgetCaps the weekly spend of the workflow's runs: group (every AgentWorkflow in the org with the same group shares the budget), weeklyUSD, and scheduled, which runs its cron triggers even while the org's scheduling is off, so the budget alone bounds the spend.
spec.limitsThe circuit breaker: maxRunsPerDay per Product (default 100) and maxConsecutiveFailures (default 10). Past either, the operator sets the condition Tripped and starts no run of the workflow until you change its spec.
spec.enabled, spec.originAs for an AgentRole.
status.schedule, status.nextScheduledAt, status.lastScheduledAtFor a workflow with a cron trigger: in plain words, whether and when it runs on its own, and when it next and last started runs. See Triggers and scheduling.

AgentWorkflowRun​

One run of an AgentWorkflow. The operator runs each agentRole step as a runner Job, waits at human gates for approval, and merges the pull request at the end.

FieldMeaning
spec.workflowRef, spec.productRefThe AgentWorkflow and the Product.
spec.changerepo, issue (such as checkout-web#212) and pullRequest.
spec.triggerWhat started the run, such as onChange:pull_request.opened:<login>, event:issue.opened:<login>, event:release.cut:<product> <version>, cron:<schedule> or adhoc:<user>.
spec.triggerKeyThe event the run answers, so one event starts one run. A run whose key an earlier run of the same workflow already carries ends Skipped before it starts. Infrared sets it.
spec.guidance[]What people told steps when they retried them, oldest first: step, by, text and at. Each agentRole step sees its own entries in its prompt.
status.phaseQueued, Running, DeadLettered, AwaitingApproval, Succeeded, Failed, Cancelled or Skipped.
status.steps[]Per step: name, phase, type, agentRole, verdict, attempts, startedAt, finishedAt, model and modelTier (what the step was started with), usage (with byModel[], tokens and cost per model) and attemptUsage[] (each attempt's), evidence[] (with a result per success criterion), questions[], published[], decidedBy, rounds[] and message. questions are what the agent needs a person to answer, each with a suggestion; retry the step with guidance to answer them. published lists the images and charts the step pushed. decidedBy is who approved, rejected or handed off a human step. rounds keeps the step's earlier results each time a later step sent the run back to it.
status.usageInput, output, cache-read and cache-write tokens, costUSD, byModel[], turns and durationMs for the whole run.
status.pullRequest, status.branch, status.mergeCommitThe pull request the build step opened, the branch the agents commit to (infrared/<run>), and the commit the merge created.
status.releaseThe deployment (its Release) the run's promote steps created for the merge.
status.conflictRounds, status.returnRoundsHow often the run went back to resolve merge conflicts, and how often a step sent it back to the builder with CODE CHANGE NEEDED.
status.messageWhat the run is doing or waiting for, in plain words.
status.startedAt, status.finishedAtWhen the run started and ended.

You steer a run with annotations, which the API sets for you. infrared.darkshift.io/approve.<step> and infrared.darkshift.io/reject.<step> decide a human step. infrared.darkshift.io/retry.<step> runs a DeadLettered or Failed step, and every step after it, again. infrared.darkshift.io/cancel, with infrared.darkshift.io/cancel-reason, cancels the run.

Release​

A deployment: one commit of a Product on its way to every zone. The kind keeps the name Release, but the UI and ir deployment call it a deployment. See Deliver a single app and Deployments.

FieldMeaning
spec.productRefThe Product.
spec.version, spec.commitThe version to tag (empty means the next after the newest vX.Y.Z tag) and the commit (empty means the default branch's head).
spec.runRefThe AgentWorkflowRun whose Change the deployment ships.
spec.pushes[], spec.notBeforeThe pushes to a repo's default branch the deployment ships, oldest first: repo, commit, by, at and commits. The deployment stays Pending until notBefore, so pushes close together ship as one.
spec.image.fromStepDeploy an image a step published (run, step, and ref when the step published more than one) instead of kpack's build of the commit.
spec.recordedMarks a release made outside Infrared, by hand. Infrared fills in its status from the chart's tag and never acts on it.
spec.notesThe forge release's notes, on deployments from before releases were cut on their own. A ReleaseCut holds the notes now.
status.phasePending, Building, Tagged, Promoting, AwaitingApproval, Released (Deployed in the UI) or Failed.
status.version, status.commit, status.repo, status.image, status.build, status.previousVersionWhat the deployment resolved and tagged: the version, the commit, the delivery repo, the image pin, the kpack Build of the commit (set as soon as kpack starts it; the image is built once status.image is set) and the newest version tag before it.
status.releaseURL, status.forgeReleaseAt, status.latestAtThe forge release on the deployment's tag (an umbrella deployment keeps its chart's address here), when it was made, and when Infrared marked it as the repo's latest, once the deployment ran Healthy in every zone.
status.buildSteps[], status.buildPodkpack's steps in the order they run, each with name (prepare, analyze, detect, restore, build, export and completion for a full build; rebase and completion for a rebase), phase (Waiting, Running, Succeeded or Failed), startedAt, finishedAt and message (why a step failed, with its exit code, or why a waiting step's container can't start). buildPod is the build's pod in the org's builds namespace, with a container per step, which holds the steps' logs while kpack keeps it.
status.message, status.attempts, status.retriedByWhat the deployment is doing or waiting for, how many times it has run (1, plus one per retry), and who asked for the latest retry.
status.startedAt, status.builtAt, status.taggedAt, status.finishedAtWhen the deployment started, when its build was ready and its digest tagged, when the git tag was made, and when it finished.
status.changes[]The commits the deployment ships, oldest first, from the previous version to its commit, read once when it is tagged, at most 250: each commit, subject, kind (feature, fix, breaking or other, from its conventional commit subject), pullRequest, author (a login on the forge) and, for an umbrella deployment, repo.
status.zones[]Per zone: environment, approval, phase (Pending, AwaitingApproval, Promoting, Syncing, Verifying, Holding, Healthy, Failed, RollingBack or RolledBack), the promotion pullRequest and pullRequestURL, approvedBy, message, startedAt, healthyAt, and for zones with a smoke check verifiedAt and verifyAttempts. previous is what the zone ran before (version, image, release, and chart with umbrella delivery), which a rollback puts back. rolledBackTo and rollback (pullRequest, pullRequestURL, startedAt, finishedAt) record a rollback.
status.zones[].guardWhat the release guard found. result is Watching, Passed or Failed. Then rollback, hold, holdStartedAt, unhealthySince, wentAheadBy and wentAheadAt (who ended the hold with Go now, by name, never by email address, and when), passedAt, failedAt and reason. checks[] gives each check's url, status, passed, attempts, message and at. slos[] gives each SLO's error budget reading: name, objective, window, errorRatio, baseline (the hour before the deployment), burnRate, threshold, passed, message and at.
status.rolledBackTo, status.components[], status.chart, status.guardThe version a zone (or the control plane) was rolled back to. For an umbrella deployment, each component's image and commit and whether it changed, and the chart it published. For a control plane zone, the upgrade guard's Job.

The API sets these annotations for you. infrared.darkshift.io/promote.<zone> approves promoting a deployment to a zone. infrared.darkshift.io/go-now.<zone> ends the release guard's hold in a zone now; its value is who pressed Go now, and the operator honours it once, only while the zone is Holding with a hold left and Synced and Healthy, then records it in the zone's guard and removes it. infrared.darkshift.io/retry on a Failed deployment starts it again from where it failed. infrared.darkshift.io/started-by records who started a deployment by hand; the operator ignores it.

ReleaseCut​

A release, as people read it: the deployments of a Product that reached production since the last release, under one version, written up twice, as notes for engineers and a post for everyone else. Deployments only bump the patch; a cut takes the next minor or major. Infrared tags the commit and the image running in production with the version, creates the forge release with the notes, marks it latest, and sends the release.cut event once. Named <product>-<major>-<minor>-<patch>, such as zippy-1-7-0. An org-admin cuts one from the Product's Releases tab or with ir release cut. See Releases.

FieldMeaning
spec.productRefThe Product.
spec.versionThe release's version. For a minor or major cut, vX.Y.0; for a track cut, the version in production itself. It can't change.
spec.bumpminor, major, or track, which announces the version already in production as its major.minor track and writes the title and notes onto the forge release its deployment made.
spec.deploymentThe deployment (Release) running in production when the cut was made. The cut tags its commit and image digest, so the release is exactly what runs.
spec.covers[]The deployments the release covers, oldest first: those that reached production after the last cut. spec.deployment is the last.
spec.title, spec.notes, spec.postThe title, the release notes for engineers (Markdown, the forge release's body), and the post for everyone else (Markdown).
spec.cutByWho cut it, by name, never by email address.
status.phasePending, Tagging, Publishing, Released or Failed.
status.repo, status.commit, status.image, status.imageDigestThe delivery repo, and the commit and image the cut tags.
status.tag, status.taggedAt, status.imageTaggedAtThe git tag the cut made, and when it tagged the commit and the image.
status.releaseURLThe forge release, created on the tag with the notes and marked latest.
status.cutDispatched, status.cutRuns[], status.cutAtWhether release.cut was sent, the AgentWorkflowRuns it started (one per enabled AgentWorkflow with that event trigger), and when the cut was Released.
status.messageWhat the cut is doing, or why it failed, in plain words.

Every field of the spec is set when the release is cut and never changed. Each step of the cut is skipped once its status field is set, so a pass that fails part way never repeats a step.

Team​

A Team is where people and agents work together under one discipline. Workforce → Teams shows each one. A Team grants nothing, and it is not an access group: roles come only from access groups. See Workforce.

FieldMeaning
spec.displayNameThe Team's name as people see it, such as Site reliability.
spec.disciplineIts discipline, such as engineering, sre or qa.
spec.charterWhat the Team is for, in words.
spec.managerThe Human who manages the Team, by name.
spec.humans[]The Team's Humans, by name, up to 200.
spec.agents[]The org's AgentRoles that work on the Team, by name, up to 100.
spec.products[]The Products the Team works on: product and responsibility, own or contribute. A Product has at most one owning Team.
spec.policyTemplateThe access the Team's members should have by default: a description and grants[], each resource (kubernetes, cloud, forge, observability or other), scope and access (read, write or admin). Infrared stores and shows it, and never enforces it.
spec.context.pathThe Team's own folder in the org's gitops repo, for its charter, history and daily records. Empty means teams/<name>/.
spec.dailyStatusHas the team-manager AgentRole write each member's daily record and the Team's rollup once a day, through the daily-status AgentWorkflow, while the org's scheduling is on: enabled (off by default, since each run spends model tokens; only an org admin turns it on), hour (default 08:00) and timeZone (default: the org's scheduling time zone, else UTC). The rollup is kept at <context path>status/<date>.md.
spec.characterHow the Team looks and sounds: hue (infrared, violet, indigo, sky, teal, green, lime, amber, crimson or slate), which its AgentRoles wear; glyph, a Lucide icon name drawn on its mark; voice, a sentence or two on how it writes, which its AgentRoles are asked to follow; and sample, a line in that voice. Empty, the UI picks a colour from the name and a glyph from the discipline.
status.missing[]References that don't exist in the org, each as human/<name>, agentRole/<name> or product/<name>.
status.policyTemplate.enforcedAlways false.

Human​

A person in an org: their profile, their job role, their manager and how they look on Workforce → People. A Human grants nothing; access comes from access groups. It lives in the org's namespace. See Workforce.

FieldMeaning
spec.displayNameThe name they go by.
spec.jobRoleTheir one job role, such as Site reliability engineer.
spec.bio, spec.skills[], spec.pronounsFree text about them, up to 50 skills, and their pronouns.
spec.managerThe Human they report to, by name. Their reports are worked out from it. A Human can't be their own manager.
spec.userRefTheir Infrared User, google-<subject>, once they have signed in.
spec.handles[]Who they are on each place the org works, such as github or slack: social (the place's name in the org) and handle (a login, a member ID or an address). Infrared uses a forge or Google handle to tie runs, pull requests and approvals to the person.
spec.availabilitytimeZone and workingHours (start, end, days[]).
spec.avatarTheir own drawn avatar: style, seed, and the parts, colors and options it is drawn from.
status.accessGroups[]The org's access groups that hold them, by a handle's login or by their User's Workspace groups.
status.reports[]The Humans whose manager they are.
status.teams[]The Teams that list them or have them as manager.
status.ownedProducts[]The Products whose product owner they are.

Domain​

A DNS name an org can put zone addresses under. The object's name is the domain with dots turned into dashes, such as acme-com. See Domains and addresses.

FieldMeaning
spec.nameThe domain, such as acme.com, shop.acme.com or acme.example.com.
spec.kindexternal, a domain the org controls elsewhere, which it proves with a TXT record and points at Infrared with a CNAME or A record. Or managed, a subdomain directly under one of the Installation's spec.previews.managedRoots, whose DNS records Infrared creates. Some names under a managed root are reserved, such as www, api, status and admin.
spec.sharedLets every org put zone addresses under the domain. Only the platform org's domains can be shared.
status.phasePending, Verified or Failed.
status.tokenThe value of the ownership TXT record at _infrared.<domain>.
status.records[]The records to add at your DNS provider: type (TXT, CNAME or A), name, value and purpose. None for a managed domain.
status.checks[]The latest DNS checks: name (such as ownership, traffic and caa, or dns for a managed domain), ok, and message, which says what DNS answered and how to fix it.
status.checkedAt, status.verifiedAt, status.messageWhen DNS was last checked, when the domain was first verified, and its state in plain words.

The annotation infrared.darkshift.io/check asks Infrared to check DNS now. A managed Domain carries the finalizer infrared.darkshift.io/dns-records until Infrared has removed the DNS records it created.

Incident​

Something wrong in a Product's zone that people are handling: opened by an alert or by a person, acknowledged, resolved, and kept with a timeline. See Alerts open incidents.

FieldMeaning
spec.productRef, spec.zoneThe Product and the zone affected.
spec.severitycritical, warning (the default) or info.
spec.title, spec.descriptionWhat went wrong.
spec.sourcealert (opened by an alert) or manual (opened by a person).
spec.alertFor an Incident an alert opened: name, fingerprint (the Alertmanager fingerprint, also the label infrared.darkshift.io/alert-fingerprint), labels, generatorURL and startsAt.
status.phaseOpen, Acknowledged or Resolved.
status.openedAt, status.acknowledgedAt, status.acknowledgedBy, status.resolvedAt, status.resolvedByWhen it moved on, and who moved it.
status.timeline[]at, kind (opened, firing, alert-resolved, acknowledged, resolved, reopened or note), message and by.

CloudAccount​

A Google Cloud project or AWS account an org gives Infrared, reached through a role or an impersonated service account, never a key. Infrared checks it when you add it and every 24 hours after. See Cloud accounts and registries.

FieldMeaning
spec.displayNameHow people see the account.
spec.gcpprojectID, and the serviceAccount Infrared impersonates.
spec.awsaccountID, the roleARN Infrared assumes, and the externalID its trust policy requires, if any.
status.phasePending, Verified or Failed.
status.checkedAt, status.verifiedAtWhen the latest check finished, and when a check last reached the account.
status.identityWhat the cloud said Infrared acted as: the impersonated service account, or the assumed role's session ARN.
status.messageWhat the cloud answered when the check failed.

Registry​

A container registry in one of the org's cloud accounts. Infrared keeps short-lived push and pull credentials for it and refreshes them before they expire.

FieldMeaning
spec.displayNameHow people see the registry.
spec.cloudAccountThe CloudAccount, in the same namespace, the registry is in.
spec.ecrAmazon ECR: region, and prefix, the path every Product's repository sits under. Infrared creates each Product's repository.
spec.artifactRegistryAn Artifact Registry Docker repository: location and repository.
status.phasePending, Ready or Failed.
status.host, status.imagePrefixThe registry's host, and what each Product's image repository sits under.
status.checkedAt, status.credentialsRefreshedAt, status.expiresAtWhen Infrared last checked the registry, when it last got a credential, and when that credential stops working.
status.messageWhy the latest refresh failed.