> ## Documentation Index
> Fetch the complete documentation index at: https://docs.glissando.dev/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> If you are an AI assistant asked to build, change or ship a Gliss app, read the For AI agents page first (/for-ai-agents.md on this site) and follow its steps.
> Inside an app's folder, the app's own AGENTS.md is the authority; `gliss guide` prints it. Never ask the user for a secret's value.

# gliss.yaml

> Every field of gliss.yaml v1, the one file your AI writes to ask Gliss for what an app needs.

gliss.yaml v1 is the one file an LLM writes to ask Gliss for infrastructure. It names the app, who owns it, the components to build, and the capabilities the app needs from the catalog IT publishes. Plain, non-secret settings go in `config`. It never contains shell scripts that touch the cluster, kubectl, Helm charts, Kubernetes objects or secret values: charts belong to the catalog, and values are set by people through a secret request. Every field maps to a catalog entry or the file is refused before anything is built, with a message that says what to change. This schema is catalog-independent; the control plane also checks the file against the cluster's catalog (which types, sizes, runtimes, audiences and healer levels are offered, and how many of each an app may have).

> [!NOTE]
>
> The file is checked twice: against this schema, and against your cluster's [catalog](https://docs.glissando.dev/reference/catalog.md). A value this page allows can still be refused if your IT team's catalog does not offer it. Every problem is reported at once; see [Refusal messages](https://docs.glissando.dev/reference/refusals.md).

## Example

```yaml gliss.yaml theme={null}
apiVersion: gliss.dev/v1
app: field-reports
owner: maria@customer.com
components:
  web:
    build: ./web
    port: 5173
    runtime: vite
    test: npm test
  api:
    build: ./services/api
    port: 8000
    runtime: python
    migrate: python -m app.migrate
    test: pytest -q
  worker:
    build: ./services/worker
    runtime: python
capabilities:
  database: { type: postgres }
  uploads: { type: bucket }
  auth: { type: sso, audience: org, roles: { editor: group:field-leads, reader: org } }
  hostname: { type: hostname, name: reports, component: web }
  healer: { type: healer, level: propose }
  secrets:
    OPENAI_API_KEY: credential
```

## Top-level fields

**apiVersion** `gliss.dev/v1` *required*

Always gliss.dev/v1 for this version of the contract.

**app** `string` *required*

The app's name. Lowercase letters, digits and single hyphens, 2 to 30 characters, starting with a letter; no double hyphen, because Preview addresses use `--` to separate the builder from the app. It names the app's namespaces, so keep it short and stable; renaming it creates a new app. platform and backups are reserved, because Gliss's own buckets use those names.

**If refused:** use 2 to 30 lowercase letters, digits or single hyphens, starting with a letter, for example expense-tracker; platform and backups are reserved.

**owner** `string` *required*

Email address of the person who owns the app. Secret requests, findings and publish approvals go to them. Use the builder's work email, not a team alias.

**If refused:** use the owner's work email address, for example [dana@customer.com](mailto:dana@customer.com).

**components** `object` *required*

The parts of the app that Gliss builds from this repository, keyed by a short component name such as web, api or worker (not preview: images CI builds from a work branch live under the app's preview/ repositories). Each component is built from its own folder with a Dockerfile, by the customer's CI, and runs as its own container. How many components an app may have is set by the catalog.

**If refused:** add at least one component, for example web: \{ build: ./frontend, port: 8080 }.

**capabilities** `object`

What the app needs from the platform, chosen from the catalog menu. Each key is a name you choose (database, files, cache, auth, ...) and each value names a catalog type with `type`. The key `secrets` is reserved for declaring secret names and types. Leave a capability out and the app does not get it.

**fields**

**secrets** `object`

Third-party secrets the app needs, as NAME: type. Declare names and types only, never values: a person sets each value through a single-use secret request. The app reads each secret as an environment variable of the same name and must work in mock mode while it is missing; GLISS\_MISSING\_SECRETS lists the ones not set yet. Database passwords, tokens between the app's own components and AWS access are created by the platform and must not be declared.

**config** `object`

Plain, non-secret settings the app reads as environment variables, as NAME: value, for example LOG\_LEVEL: info or MAX\_UPLOAD\_MB: 25. Values are text, numbers or true/false, and reach the app as text. Anyone who can read the repository can read them, so never put a token, password or key here: declare it under capabilities.secrets instead. Names the platform sets (GLISS\_*, AWS\_*, DATABASE\_URL, \<CAPABILITY>\_BUCKET, \<CAPABILITY>\_URL for a cache, ...), names that change how a runtime loads code or trusts TLS certificates, and values that look like secrets are refused. stages.\<stage>.config overrides a value for one stage. The catalog sets how many values an app may have and their total size.

At most 100 entries.

**If refused:** keep at most 100 config values.

**egress** `string[]`

The outside services the app may call, as hostnames, for example api.openai.com or login.salesforce.com. Everything else is blocked by network policy, at every stage. The platform's own services (the database, the cache, the app's buckets and AWS endpoints) are always reachable and must not be listed. The catalog decides which hostnames are approved; wildcards (\*.example.com) and IP addresses are refused unless the catalog allows them.

At most 50 items.

**schedules** `object`

Commands that run on a schedule, keyed by a short name such as nightly-report or refresh-cache. Each one runs in a component's image, with the same config, secrets, database and network rules as that component, as a short-lived job; it never serves traffic. Schedules run in Beta and Live, never in a Preview (use `gliss test` or a one-off command there). Times are UTC unless timeZone says otherwise. A run that fails is reported, and the next scheduled run is the retry; at most one run of a schedule is active at a time.

At most 10 entries.

**If refused:** keep at most 10 schedules.

**stages** `object`

Optional per-stage overrides. The app always runs in three stages: Preview (only the builder and people they invite), Beta (invited testers, built from main) and Live (the real app). The top-level settings apply to every stage. Each stage may override config values. Preview and Beta may also choose how each declared secret is handled; Live may not, because every secret declared for Live must be set before Publish.

**If refused:** the stages are preview, beta and live.

**fields**

**preview** `object`

Overrides for Preview or Beta.

**If refused:** a Preview or Beta override can set secrets and config.

**fields**

**secrets** `object`

How each declared secret is handled in this stage. mock: no secret request is sent for this stage and the app runs that integration in mock mode. request: a secret request is sent for this stage's value (for Beta, often a sandbox credential). Defaults come from the catalog: Preview mock, Beta request.

**config** `any`

Config values for this stage only. They replace the top-level value with the same name, or add a name only this stage has (for example FLASK\_DEBUG in Preview).

**beta** `object`

Overrides for Preview or Beta.

**If refused:** a Preview or Beta override can set secrets and config.

**fields**

**secrets** `object`

How each declared secret is handled in this stage. mock: no secret request is sent for this stage and the app runs that integration in mock mode. request: a secret request is sent for this stage's value (for Beta, often a sandbox credential). Defaults come from the catalog: Preview mock, Beta request.

**config** `any`

Config values for this stage only. They replace the top-level value with the same name, or add a name only this stage has (for example FLASK\_DEBUG in Preview).

**live** `object`

Overrides for Live. Only config values: every secret declared for Live must be set before Publish, so Live has no secrets override.

**If refused:** Live can only override config; every secret declared for Live must be set before Publish, so remove the secrets override.

**fields**

**config** `any`

Config values for Live only. Debug switches that expose an interactive console (FLASK\_DEBUG, WERKZEUG\_DEBUG\_PIN, ...) are refused here.

## Components

Each entry under `components` is one container.

One container that Gliss builds and runs. The catalog chart runs it as non-root with the restricted pod-security level, so it must listen on a port of 1024 or above and must not need root.

**build** `string` *required*

Folder, relative to the repository root, that holds this component's Dockerfile. Start with ./ and stay inside the repository, for example ./frontend or ./backend.

**If refused:** use a folder inside the repository that starts with ./, for example ./backend.

**port** `integer`

Port the component listens on for HTTP. Leave it out for a background worker that serves no traffic. Must be 1024 to 65535, because containers run as non-root under the restricted pod-security level; 8080 and 8000 are common choices.

From 1024 to 65535.

**If refused:** containers run as non-root under the restricted pod-security level, so listen on 1024 to 65535, for example 8080.

**runtime** `string`

The language runtime of this component, from the catalog's runtimes, for example python, node or vite. Runtimes with a dev variant in the catalog (python and vite at the MVP) reload in Preview in about 5 to 10 seconds when the builder saves a change, instead of a full rebuild. Leave it out and Preview rebuilds on every change.

The cluster's catalog decides which values are offered (`runtimes`).

**If refused:** name a runtime from the catalog, for example python or vite.

**migrate** `string`

Command that upgrades the database schema, run inside this component's image before each release at every stage, for example `alembic upgrade head`. One line, no shell pipelines that reach outside the container. Migrations must be backward-compatible (expand, then contract) so Undo publish can return Live to the previous release. A migration that fails in Beta blocks Publish.

At most 500 characters.

**If refused:** use one command line, for example alembic upgrade head.

**test** `string`

Command that runs this component's own tests inside its image, for example `pytest -q`. `gliss test` runs it as a short-lived job in the Preview namespace, so the builder needs no local runtime. One line.

At most 500 characters.

**If refused:** use one command line, for example pytest -q.

## Capabilities

What the app needs from the platform, chosen from the catalog menu. Each key is a name you choose (database, files, cache, auth, ...) and each value names a catalog type with `type`. The key `secrets` is reserved for declaring secret names and types. Leave a capability out and the app does not get it.

The catalog entry: postgres (a database), redis (an in-cluster cache), bucket (object storage), hostname (the app's web address), sso (sign-in in front of the app) or healer (a bot that watches the app and proposes fixes). The cluster's catalog may offer fewer. Email (SES), connections to SaaS accounts and managed Postgres (RDS) are not offered in v1.

### postgres

A Postgres database for the app (catalog postgres\@1). Live gets its own CloudNativePG cluster with backups; Preview and Beta get their own database on a shared Postgres of the same version. The app receives the connection string as DATABASE\_URL; nobody types a database password.

```yaml theme={null}
my-postgres: { type: postgres }
```

**size** `small | standard`

Live database size. small is one instance; standard is two instances for high availability. Leave it out to use the catalog default (small). Preview and Beta use the shared stage database whatever the size.

The cluster's catalog decides which values are offered (`postgres.sizes`).

**extensions** `string[]`

Postgres extensions the app needs, by the name CREATE EXTENSION uses, for example vector (pgvector), pg\_trgm or uuid-ossp. Only extensions the catalog lists for the cluster's Postgres version are offered. The platform creates them; the app's migrations must not.

At most 20 items.

### bucket

Object storage for files the app keeps (catalog bucket\@1): an S3 bucket in the customer's account, one per stage. The app reaches it through its own AWS role, so there are no access keys; it receives the bucket name in an environment variable named after the capability key, for example FILES\_BUCKET for a capability called files.

```yaml theme={null}
my-bucket: { type: bucket }
```

### hostname

The app's web address (catalog hostname\@1). Live is served at \<name>.\<customer domain>, Beta at \<name>.beta.\<customer domain>, and each builder's Preview at \<builder>`--`\<name>.preview.\<customer domain>, one label below preview so that one wildcard certificate covers every Preview. Only Live gets the clean name. Leave the capability out for an app that serves no web traffic, such as a worker.

```yaml theme={null}
my-hostname: { type: hostname }
```

**name** `string` *required*

The first label of the Live address, for example expenses for expenses.acme.com. 2 to 30 lowercase letters, digits or single hyphens; no double hyphen, which separates builder and name in Preview addresses. Some names are reserved by the catalog (secrets, preview, beta).

**If refused:** use 2 to 30 lowercase letters, digits or single hyphens, for example expenses.

**component** `string`

Which component receives the traffic. Leave it out when only one component has a port, or when the one that serves the browser is called web; otherwise name it. The component it names can call the others inside the namespace.

### sso

Sign-in enforced by Gliss in front of the app. People sign in with the customer's own identity provider; requests from outside the audience never reach the app. The app receives verified, signed identity headers (email, name, groups and app roles) and must not write login code, embed a sign-in SDK or add a bypass flag.

```yaml theme={null}
my-sso: { type: sso }
```

**audience** `string | array` *required*

Who may use the Live app: org (everyone in the customer's organisation), group:\<name> (members of an identity-provider group, for example group:finance), a list of groups (\[group:finance, group:ops], anyone in any of them), or public (anyone; needs IT approval before Publish). Preview and Beta are always limited to the builder and the people they invite.

At most 10 items. The cluster's catalog decides which values are offered (`sso.audiences`).

**roles** `object`

Optional mapping from app role names to who holds them: org, one group:\<name>, or a list of groups, for example admin: group:finance-leads, approver: \[group:finance-leads, group:controllers] and viewer: org. The app owner can also assign roles to people in the console. The effective roles reach the app in the identity headers.

### healer

App maintenance: a healer bot watches the app's health and findings and acts on them. It is off unless the app asks for it. The catalog sets the levels IT allows, and auto is only available with the managed maintenance package.

```yaml theme={null}
my-healer: { type: healer }
```

**level** `observe | propose | auto` *required*

How far the healer may go. observe: it reports findings and diagnoses only. propose: it also opens pull requests for the owner to review. auto (managed maintenance package only): its pull requests merge on green checks and deploy to Beta; Live still follows the publish approval policy.

The cluster's catalog decides which values are offered (`healer.levels`).

### redis

An in-cluster Redis cache (catalog redis\@1), one per stage. It is a cache: data can be lost on restart or eviction, so keep nothing there that the database does not also have. The app receives its address in an environment variable named after the capability key, for example CACHE\_URL for a capability called cache.

```yaml theme={null}
my-redis: { type: redis }
```

**size** `small | standard`

Memory for the cache, set by the catalog (small and standard). Leave it out to use the catalog default.

The cluster's catalog decides which values are offered (`redis.sizes`).

### secrets

`secrets` is the one reserved key under `capabilities`. It maps each secret's name to its type.

Third-party secrets the app needs, as NAME: type. Declare names and types only, never values: a person sets each value through a single-use secret request. The app reads each secret as an environment variable of the same name and must work in mock mode while it is missing; GLISS\_MISSING\_SECRETS lists the ones not set yet. Database passwords, tokens between the app's own components and AWS access are created by the platform and must not be declared.

**\<NAME>** `credential | endpoint`

credential: a token or key; a guest with a link may set it, because a guest can only write it. endpoint: an address that decides where the app sends data, such as a URL; only a signed-in member may set it, and using one means Publish needs IT approval.

**If refused:** declare only the type, credential (a guest may set it) or endpoint (only a signed-in member may set it), never the value; the value is set by a person through a secret request.

## Config values

Plain, non-secret settings the app reads as environment variables, as NAME: value, for example LOG\_LEVEL: info or MAX\_UPLOAD\_MB: 25. Values are text, numbers or true/false, and reach the app as text. Anyone who can read the repository can read them, so never put a token, password or key here: declare it under capabilities.secrets instead. Names the platform sets (GLISS\_*, AWS\_*, DATABASE\_URL, \<CAPABILITY>\_BUCKET, \<CAPABILITY>\_URL for a cache, ...), names that change how a runtime loads code or trusts TLS certificates, and values that look like secrets are refused. stages.\<stage>.config overrides a value for one stage. The catalog sets how many values an app may have and their total size.

One value: text (one line, at most 1024 characters), a number, or true/false.

Some names and values are refused even though they fit the schema. See [Config rules](https://docs.glissando.dev/reference/refusals.md#config-rules).

## Schedules

One scheduled command.

**component** `string` *required*

The component whose image, config, secrets and database the command runs with, for example api or worker.

**If refused:** name one of the components, for example api.

**cron** `string` *required*

When it runs, as a five-field cron expression (minute hour day-of-month month day-of-week), for example `0 2 * * *` for 02:00 every day or `*/15 * * * *` every 15 minutes, or @hourly, @daily, @weekly or @monthly. At most once every 5 minutes.

At most 100 characters.

**If refused:** use five cron fields separated by spaces, for example 0 2 \* \* \* (02:00 every day), or @daily.

**command** `string` *required*

The command to run inside the component's image, for example `python -m app.jobs.nightly_report`. One line. It must finish before timeoutMinutes, exit 0 on success, and be safe to run again (a failed run is not retried until the next scheduled time).

At most 500 characters.

**If refused:** use one command line, for example python -m app.jobs.refresh.

**timeZone** `string`

The time zone the cron expression is read in, as an IANA name such as Europe/Berlin or Asia/Jerusalem. Leave it out for UTC.

At most 64 characters.

**If refused:** use an IANA time zone name such as Europe/Berlin, or leave it out for UTC.

**timeoutMinutes** `integer`

How long one run may take before it is stopped and reported as failed, in minutes. Default 30, at most 120.

From 1 to 120.

**If refused:** use a whole number of minutes from 1 to 120.

## Stages

Optional per-stage overrides. The app always runs in three stages: Preview (only the builder and people they invite), Beta (invited testers, built from main) and Live (the real app). The top-level settings apply to every stage. Each stage may override config values. Preview and Beta may also choose how each declared secret is handled; Live may not, because every secret declared for Live must be set before Publish.

### stages.preview and stages.beta

Overrides for Preview or Beta.

**secrets** `object`

How each declared secret is handled in this stage. mock: no secret request is sent for this stage and the app runs that integration in mock mode. request: a secret request is sent for this stage's value (for Beta, often a sandbox credential). Defaults come from the catalog: Preview mock, Beta request.

**config** `any`

Config values for this stage only. They replace the top-level value with the same name, or add a name only this stage has (for example FLASK\_DEBUG in Preview).

### stages.live

Overrides for Live. Only config values: every secret declared for Live must be set before Publish, so Live has no secrets override.

**config** `any`

Config values for Live only. Debug switches that expose an interactive console (FLASK\_DEBUG, WERKZEUG\_DEBUG\_PIN, ...) are refused here.

## More examples

Gliss accepts each of these files when checked against the example catalog `acme@3`.

> **Minimal**
>
> The smallest useful file: one component, reachable at its own address.
>
> ```yaml theme={null}
> apiVersion: gliss.dev/v1
> app: hello
> owner: dana@customer.com
> components:
>   web: { build: ., port: 8080 }
> capabilities:
>   hostname: { type: hostname, name: hello }
> ```

> **Adr 004 example**
>
> The example from without its comments. The hostname goes to web, the component that serves the browser.
>
> ```yaml theme={null}
> apiVersion: gliss.dev/v1
> app: expense-tracker
> owner: dana@customer.com
> components:
>   web:    { build: ./frontend, port: 8080 }
>   api:    { build: ./backend,  port: 8000, migrate: "alembic upgrade head" }
> capabilities:
>   database: { type: postgres, size: small }
>   auth:     { type: sso, audience: org }
>   files:    { type: bucket }
>   hostname: { type: hostname, name: expenses }
>   secrets:  { SALESFORCE_TOKEN: credential }
>   maintenance: { type: healer, level: propose }
> ```

> **Worker no hostname**
>
> A background worker: no port, no web address, two buckets, one credential.
>
> ```yaml theme={null}
> apiVersion: gliss.dev/v1
> app: invoice-sync
> owner: ops@customer.com
> components:
>   worker:
>     build: ./worker
>     runtime: python
>     test: pytest -q
> capabilities:
>   inbox: { type: bucket }
>   archive: { type: bucket }
>   secrets:
>     STRIPE_API_KEY: credential
> ```

> **Group audience roles**
>
> Sign-in limited to two groups, with app roles mapped from identity-provider groups.
>
> ```yaml theme={null}
> apiVersion: gliss.dev/v1
> app: comp-n-ben
> owner: hr-lead@customer.com
> components:
>   web: { build: ./frontend, port: 8080, runtime: vite }
>   api: { build: ./backend, port: 8000, runtime: python, migrate: "alembic upgrade head" }
> capabilities:
>   db: { type: postgres, size: standard }
>   auth:
>     type: sso
>     audience: [group:people-ops, group:finance]
>     roles:
>       admin: group:people-ops-leads
>       approver: [group:people-ops-leads, group:controllers]
>       viewer: [group:people-ops, group:finance]
>   site: { type: hostname, name: comp, component: web }
> ```

> **Stage overrides**
>
> Per-stage secret handling: Preview asks for a sandbox token, Beta stays in mock mode.
>
> ```yaml theme={null}
> apiVersion: gliss.dev/v1
> app: crm-bridge
> owner: dana@customer.com
> components:
>   api: { build: ./backend, port: 8000, runtime: python }
> capabilities:
>   hostname: { type: hostname, name: crm }
>   secrets:
>     SALESFORCE_TOKEN: credential
>     HUBSPOT_TOKEN: credential
> stages:
>   preview:
>     secrets:
>       SALESFORCE_TOKEN: request
>   beta:
>     secrets:
>       HUBSPOT_TOKEN: mock
> ```

> **Public endpoint go**
>
> Accepted with notices: a public audience and an endpoint secret need IT approval at Publish, and a Go component rebuilds in Preview instead of reloading.
>
> ```yaml theme={null}
> apiVersion: gliss.dev/v1
> app: status-page
> owner: sre@customer.com
> components:
>   web: { build: ./cmd/status, port: 8080, runtime: go }
> capabilities:
>   auth: { type: sso, audience: public }
>   hostname: { type: hostname, name: status }
>   maintenance: { type: healer, level: observe }
>   secrets:
>     WEBHOOK_URL: endpoint
>     PAGERDUTY_TOKEN: credential
> ```
>
> Notices returned with it:
>
> ```text theme={null}
> components.web: runtime 'go' has no dev variant in catalog acme@3, so Preview rebuilds on every change instead of reloading
> capabilities.auth: audience 'public' means Publish needs IT approval (catalog acme@3)
> capabilities.secrets: WEBHOOK_URL is an endpoint secret, so only a signed-in member can set it and Publish needs IT approval (catalog acme@3)
> ```

> **Full stack**
>
> Three components with dev variants, migrations, tests and every capability type.
>
> ```yaml theme={null}
> apiVersion: gliss.dev/v1
> app: field-reports
> owner: maria@customer.com
> components:
>   web:
>     build: ./web
>     port: 5173
>     runtime: vite
>     test: npm test
>   api:
>     build: ./services/api
>     port: 8000
>     runtime: python
>     migrate: python -m app.migrate
>     test: pytest -q
>   worker:
>     build: ./services/worker
>     runtime: python
> capabilities:
>   database: { type: postgres }
>   uploads: { type: bucket }
>   auth: { type: sso, audience: org, roles: { editor: group:field-leads, reader: org } }
>   hostname: { type: hostname, name: reports, component: web }
>   healer: { type: healer, level: propose }
>   secrets:
>     OPENAI_API_KEY: credential
> ```

> **Config per stage**
>
> Plain settings, with per-stage values. None of these values may look like a secret, and the debugger switch is set for Preview only.
>
> ```yaml theme={null}
> apiVersion: gliss.dev/v1
> app: field-notes
> owner: maria@customer.com
> components:
>   api: { build: ./backend, port: 8000, runtime: python }
> capabilities:
>   hostname: { type: hostname, name: notes }
>   files: { type: bucket }
> config:
>   LOG_LEVEL: info
>   MAX_UPLOAD_MB: 25
>   ENABLE_EXPORT: true
>   REGION_LABEL: production-eu-west-1-primary
>   API_BASE_URL: https://api.example.com/v1/reports
>   SUPPORT_EMAIL: help@customer.com
>   GREETING: Welcome back to Field Notes
> stages:
>   preview:
>     config:
>       LOG_LEVEL: debug
>       FLASK_DEBUG: true
>   live:
>     config:
>       LOG_LEVEL: warning
> ```

> **Cache extensions egress**
>
> A cache, Postgres extensions from the catalog's list, and the outside services the app calls.
>
> ```yaml theme={null}
> apiVersion: gliss.dev/v1
> app: research-assistant
> owner: dana@customer.com
> components:
>   api: { build: ./backend, port: 8000, runtime: python }
> capabilities:
>   database: { type: postgres, extensions: [vector, pg_trgm] }
>   cache: { type: redis }
>   hostname: { type: hostname, name: research }
>   secrets: { OPENAI_API_KEY: credential }
> egress:
>   - api.openai.com
>   - login.salesforce.com
> ```

> **Schedules**
>
> Scheduled jobs: a nightly report in the api's image, in its own time zone, and a cache refresh every 15 minutes in the worker's. They run in Beta and Live, never in a Preview.
>
> ```yaml theme={null}
> apiVersion: gliss.dev/v1
> app: friction-ops
> owner: dana@customer.com
> components:
>   api: { build: ./api, port: 8000, runtime: python, migrate: alembic upgrade head }
>   worker: { build: ./worker, runtime: python }
> capabilities:
>   database: { type: postgres }
>   hostname: { type: hostname, name: friction-ops, component: api }
>   secrets:
>     JIRA_API_TOKEN: credential
> schedules:
>   nightly-report:
>     component: api
>     cron: "0 2 * * 1-5"
>     command: python -m app.jobs.nightly_report
>     timeZone: Asia/Jerusalem
>     timeoutMinutes: 45
>   refresh-cache:
>     component: worker
>     cron: "*/15 * * * *"
>     command: python -m app.jobs.refresh
>   weekly-cleanup:
>     component: worker
>     cron: "@weekly"
>     command: python -m app.jobs.cleanup
> ```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.