Skip to content

greenlight.yml

Reference

Every Greenlight-managed repository has a greenlight.yml at the root. It is the contract for what the deployed pod sees: identity, documentation, and declared infrastructure (workloads, resources, grants, and env-var names). The agent edits it with ordinary file tools and opens a PR; on merge, the reconciler applies it. Env-var values are written separately through envSet and never live in this file.

The agent reads app_id from this file on a fresh clone, then calls getApp for everything else.

schema_version: 1
app_id: app_k9x2m3p
slug: expense-tracker
owner: jane@contoso.com
docs:
summary: Reimbursement tracker for finance ops.
purpose: Replace the shared spreadsheet finance currently uses.
architecture: |
Single Node.js web service. Postgres for records.
SSO-gated; UI is shadcn + Tailwind.

registerApp seeds this file with app_id, the docs block, the Greenlight pipeline workflow, and a .gitignore — plus commented-out scaffold for the workloads, resources, grants, env, and tags blocks below. Those scaffold comments link back to these public docs pages so a builder agent in the customer repo never needs the private Greenlight monorepo. No Dockerfile is seeded; the agent authors it for the app’s stack in the first code PR. The app stays in registered state, with no infrastructure, until that first PR declares its workload and merges.

schema_version: 1
app_id: app_k9x2m3p
slug: expense-tracker
owner: jane@contoso.com
docs:
summary: Reimbursement tracker for finance ops.
purpose: Replace the shared spreadsheet finance currently uses.
architecture: Single Node.js web service backed by Postgres.
workloads:
web:
kind: web
dockerfile: Dockerfile
port: 8080
routes: ['/*']
resources:
- kind: postgres
name: db
- kind: blob
name: receipts
grants:
- integration: snowflake-prod
credential: analytics-read
reason: Read the sales mart for the dashboard.
env:
- { name: APPROVAL_SECRET, sensitive: true }
- { name: FEATURE_FLAGS, sensitive: false }
tags:
- finance
- productivity
Field Required Description
schema_version yes Manifest format version. 1 is the only accepted value; written at registration.
app_id yes Greenlight app identifier; written at registration.
slug no URL-safe identifier; informational after registration.
owner no Owning user.
co_owners no Additional editors. Editors are managed on the app’s Access tab, or with addCoOwner / removeCoOwner; this field is informational.
created_at no ISO 8601 timestamp; written at registration.
docs yes Deploy-time app documentation projected into the dashboard (see below).

The manifest is parsed strictly — a key that isn’t in this reference fails the check rather than being ignored.

Declared infrastructure (applied on merge)

Section titled “Declared infrastructure (applied on merge)”

These blocks are the desired state the merge-time reconciler converges to:

  • workloads — the app’s runnable shape: a web workload with kind, dockerfile, port, and routes. Omit compute: unless you have evidence you need more than the baseline; declaring it sets request = limit, so the capacity stays reserved for as long as the app is deployed whether or not the app uses it. Size it against a measured need rather than copying a value from another app: above cpu: 250m or memory: 512Mi the pull request carries a sizing warning (it never blocks the merge), and getMetrics reports what the app reserves beside what it actually uses.
  • resources — managed resources by kind (postgres, blob) and name. Provisioning these is what injects their managed env vars (DATABASE_URL for Postgres; GREENLIGHT_DATA_KEY + GREENLIGHT_PROXY_URL for blob).
  • grants — the app’s integration access. Each entry names the integration, the credential (the IT-registered slug), and an optional reason. One entry per integration: an app binds exactly one credential to a given system, so a second entry naming an integration already granted is rejected when the pull request is opened. When the app needs a system for two jobs, grant the one credential whose upstream permissions cover both. Auto-approved grants work immediately on merge; the rest land in IT’s review queue while the app deploys. Manifest grants bind the app only — a person’s own access to an integration is requested imperatively via requestCredentialAccess, never declared here (see Local development). A grant on a user passthrough integration needs nothing more: the app renders for everyone, and each person connects their own account from a Connect button the app shows when a feature needs it.
  • env — the names (and sensitive flags) of user-controlled env vars. Values are written via envSet; every declared name must have a value at merge time or the deploy fails.
  • tags — optional org-wide category labels for the dashboard’s app catalog filter. Free-form, up to 12 tags of 50 characters each; prefer a fitting term from the suggested set (productivity, marketing, finance, project management, games, test) before inventing one.

runtime and build details live in the repo’s Dockerfile and source code, not here.

The docs block is required deploy-time documentation:

  • docs.summary, docs.purpose, and docs.architecture are projected into apps.doc_* after a successful deployment.
  • The app detail page renders that projection in its read-only “About this app” section.
  • App Knowledge is separate and starts empty; owners create entries and agents propose them only when useful context emerges.

Changes to greenlight.yml docs.* update the deployment projection on a successful merge. They do not create or overwrite Knowledge entries.

On every pipeline run, the policy gate validates greenlight.yml: required identity and docs fields, and the manifest blocks above — for example, it rejects an env: entry that collides with a platform-reserved name or a second grants: entry for an integration already granted, and the deploy fails if a declared env: name has no value in the vault. Approved changes are applied by the reconciler on merge.