Skip to content

mithran.yaml reference

mithran.yaml lives at your repo root and describes the app Forge builds and serves. map onboard scaffolds a starter when run with --repo-dir <checkout> and no mithran.yaml exists. That starter is a basic HTTP MithranApp skeleton; review its app ID, project/app ref, runtime, startup command, exposure, and app-environment policy before the first deploy.

The manifest is reviewed before the image is built. A review block means Forge could read the file and found a contract or policy problem; it does not mean your Dockerfile or app process has run yet.

See Account context and app environments for setup context and app-environment naming. See the Glossary for tenant, account, project, app, deploy, publish, public, protected, and MAP naming terms.

apiVersion: map.mithran/v1
kind: MithranApp
metadata:
  app_id: my-app
  name: My App
identity:
  project_ref: app:my-app
capabilities:
  - kind: http
    route: /
    runtime: nodejs22
    startup:
      command: npm start
resources:
  requests:
    cpu: 250m
non_secret_env:
  - { name: NODE_ENV, value: production }
public_edge:
  type: platform
  exposure: protected
app_env:
  preview:
    branch_pattern: "^refs/heads/main$"
    image_tag: preview
  production:
    branch_pattern: "^refs/(heads/release/.*|tags/release/.*)$"
    image_tag: prod

Required shape

A deployable self-service HTTP app manifest needs four groups:

Group Purpose
API identity apiVersion and kind tell Forge which manifest schema to parse.
App identity metadata names the app. In the self-service path, use the same label in the served app ref, such as app:my-app, so route and publish commands address the expected hostname.
Project identity identity.project_ref records the project/app ref agreed during onboarding.
Capabilities capabilities describes the HTTP service Forge starts and routes.

Everything else controls resources, environment variables, edge exposure, or environment mapping.

Read the reference by ownership:

Field group Use
Required app contract apiVersion, kind, metadata.app_id, metadata.name, identity.project_ref, and capabilities[]. A self-service HTTP app needs these before Forge can build and route it.
Runtime configuration resources, non_secret_env, and app_env values. These describe build/runtime shape and app-environment metadata.
Route exposure public_edge.type and public_edge.exposure. These set the reviewed app-route exposure value. public serves anonymously; all other values keep Forge auth required.
Account-reviewed policy metadata secret_bindings, oauth_api, public_edge.tier, public_edge.allow, and public_edge.review_exceptions. Use these only when the account has approved the corresponding policy.
Descriptive metadata metadata.description, metadata.tags, metadata.domain, metadata.labels, and identity.environment. These are accepted manifest metadata; they do not select app environments or account context.

Minimal deployable shape:

apiVersion: map.mithran/v1
kind: MithranApp
metadata:
  app_id: my-app
  name: My App
identity:
  project_ref: app:my-app
capabilities:
  - kind: http
    route: /
    runtime: nodejs22
    startup:
      command: npm start

This is the smallest useful shape for review. The app still needs a repo-root Dockerfile and a process that follows the HTTP app contract before runtime can become ready.

Field reference

Field Required Notes
apiVersion yes map.mithran/v1. MAP is the manifest API namespace; keep this value as shown.
kind yes MithranApp.
metadata.app_id yes App ID used in manifest review and evidence. For self-service apps, choose a DNS-friendly value and keep it aligned with the app ref label, usually app:<metadata.app_id>, so the published clean public URL uses the expected hostname.
metadata.name yes Human-readable name.
metadata.description no Optional human-readable description.
metadata.tags[] no Optional tags. Forge normalizes tags in sorted order.
metadata.domain no Optional key/value metadata. This does not configure DNS or route ownership.
metadata.labels no Optional key/value metadata.
identity.project_ref yes Project/app ref agreed during onboarding. In the self-service path this is the served app ref, commonly app:<metadata.app_id>.
identity.environment no Optional identity metadata. It does not select account context or the app environment.
capabilities[] yes One or more app capabilities. Accepted kind values are http, worker, and scheduler. The self-service docs cover HTTP apps. See Capability support.
resources.requests.* no Resource request values, such as cpu: 250m or memory: 512Mi.
resources.limits.* no Resource limit values, such as cpu: "2" or memory: 2Gi.
resources.concurrency.max_in_flight no Maximum in-flight work for the app process.
resources.replicas.min / max no Requested replica bounds.
non_secret_env[] no Plain config as { name, value }. Committed to the repo, so never secrets.
secret_bindings[] no Account-reviewed secret binding metadata only. Each entry needs name, mount.kind, mount.target, purpose, required, and rotation.required. Do not include secret values or raw provider refs.
oauth_api.* no Account-reviewed OAuth API policy metadata. When the block is present, include enabled, path, and scope.default. When enabled: true, audience and allowed_methods must also be non-empty.
public_edge.type no Required when public_edge is present. Must be platform.
public_edge.exposure no Required when public_edge is present. Supported values are protected, none, public-redirect, and public. public-redirect is a manifest exposure value, not an access-policy value. See App access and sharing.
public_edge.tier no Account-reviewed placement metadata. reserved selects reserved placement. Omit it, or use free, for the default free-app placement. Unrecognized values are normalized to free.
public_edge.allow[] no Account-reviewed typed public-edge allow entries. Supported type values are oauth_api and admin_redirect; unknown fields are rejected.
public_edge.review_exceptions[] no Account-reviewed review exception metadata. Each entry requires policy_ref and reason; scope is optional.
app_env.<env>.branch_pattern yes, when the app environment exists Regex metadata for the refs associated with that app environment.
app_env.<env>.auto_deploy_refs[] no Git ref patterns for app-env resolution on webhook auto-deploy candidates. Entries must start with refs/; exact refs and a single trailing * prefix glob are supported.
app_env.<env>.image_tag yes, when the app environment exists Image tag for that environment.
app_env.<env>.env_overrides[] no Non-secret environment overrides for that app environment. Same secret checks as non_secret_env.
app_env.<env>.replicas.min / max no Replica bounds for that app environment.
app_env.<env>.policy.* no Review policy switches: protect_in_review, require_map_review, and allow_traffic_without_review. Unknown policy fields are rejected.

App ID and App Ref

metadata.app_id identifies the app in manifest review and evidence:

metadata:
  app_id: inventory-portal
  name: Inventory Portal
identity:
  project_ref: app:inventory-portal

For self-service apps, use the same label in the served app ref you pass as map onboard --app-ref, map versions, and map publish. With app:inventory-portal, the production clean public URL is:

https://inventory-portal.apps.mithran.cloud/

Choose an app_id that is:

  • stable across releases;
  • short enough to type and recognize in logs;
  • lowercase and DNS-friendly;
  • specific enough that operators can identify the app without opening the repo.

If an operator gives you an app ref that does not match metadata.app_id, use the operator-provided app ref for onboarding, route, version, and publish commands. The hostname follows the served app ref; keep the manifest, onboarding record, and release evidence aligned before publishing.

HTTP capability

The common app shape is one HTTP service:

capabilities:
  - kind: http
    route: /
    runtime: nodejs22
    startup:
      command: npm start

The startup command must start a process that listens on the port in $PORT. Forge waits for runtime readiness after the artifact starts. If the container starts but the app never becomes ready, check the startup command, port binding, Dockerfile, deploy status, deploy evidence when available, and serving probe behavior together.

For framework examples and local Docker checks, see HTTP app contract.

Capability support

Manifest review validates capability shape before build. It does not prove the runtime process starts or that the route is ready.

Capability kind Route required by manifest review Runtime required Startup command required Covered by the self-service app docs
http yes yes yes yes
worker no yes yes no
scheduler yes yes yes no

Use kind: http for the customer self-service path documented here. The worker and scheduler manifest kinds are accepted by manifest review, but these docs do not define their customer runtime contract, deploy evidence, or operator runbook. Do not use them as substitutes for a documented HTTP app.

runtime is manifest metadata for the app capability. Forge still builds from the repo-root Dockerfile, records the first capability runtime in deploy evidence, and starts the declared startup.command.

Environment variables

Use non_secret_env only for configuration that is safe to commit:

non_secret_env:
  - name: NODE_ENV
    value: production
  - name: LOG_LEVEL
    value: info

Do not put API keys, tokens, private keys, passwords, customer credentials, or secrets in this file. The manifest is source-controlled and visible to anyone with repo read access.

Forge rejects obvious secret-looking names and values in non_secret_env, such as names containing secret, token, password, or private_key, the name api_key, values starting with sk_live_, ghp_, or github_pat_, private keys, password= strings, client_secret, and GitHub Actions expression values such as ${{ ... }}.

Secret bindings

secret_bindings can describe how a secret should be mounted, but it cannot carry a secret value or a raw provider reference:

secret_bindings:
  - name: db-secret
    mount:
      kind: env
      target: DATABASE_URL
    purpose: database
    required: true
    rotation:
      required: never

Use this only when the binding metadata is approved for the account. Each entry needs name, mount.kind, mount.target, purpose, required, and rotation.required. The validator accepts mount.kind: env and mount.kind: file; rotation.required must be always or never. It rejects value, secret_ref, key, and provider_ref inside secret_bindings.

Public edge

public_edge.exposure sets the reviewed app-route exposure value:

public_edge:
  type: platform
  exposure: protected
Exposure Effect
protected Forge keeps platform auth required before forwarding requests to the app.
none Forge keeps the non-public route shape.
public-redirect Forge keeps platform auth required. Use only when the reviewed manifest for the app requires this exact value.
public Forge serves the route without platform auth. Use only for apps approved for anonymous access.

public_edge.tier: reserved selects reserved placement for accounts approved for that policy. Omit tier, or use free, for the default free-app placement. Values other than reserved are normalized to free.

public_edge.allow accepts typed entries only. The supported type values are oauth_api and admin_redirect. public_edge.review_exceptions entries must include policy_ref and reason; scope is optional. Use these fields only when they are part of the account's reviewed edge policy.

public_edge accepts typed policy only. Do not put WAF expressions, Cloud Armor expressions, or provider-specific ingress expressions in the manifest.

OAuth API metadata

The optional oauth_api block is policy metadata for account-reviewed OAuth API use cases:

oauth_api:
  enabled: true
  path: /oauth/callback
  audience:
    - https://api.example.internal
  allowed_methods: [GET, POST]
  scope:
    default: read
    optional: [write]

When the oauth_api block is present, include:

  • enabled
  • path
  • scope.default

When enabled: true, manifest review also requires:

  • at least one audience
  • at least one allowed_methods entry

Unknown oauth_api fields are rejected. Do not add API keys or raw credential material to this block.

Review exposure changes with the same care as code changes. If a customer app should require signed-in access, review the protected access policy and verify allowed and denied results. See App access and sharing for the customer-owned access controls.

Environment mapping

app_env records named app environments, image tags, and optional auto-deploy ref patterns:

app_env:
  preview:
    branch_pattern: "^refs/heads/main$"
    auto_deploy_refs:
      - "refs/heads/main"
    image_tag: preview
  production:
    branch_pattern: "^refs/(heads/release/.*|tags/release/.*)$"
    auto_deploy_refs:
      - "refs/heads/release/*"
      - "refs/tags/release/*"
    image_tag: prod

Built-in webhook intake creates deploy candidates for these refs: refs/heads/main, refs/heads/release/*, and refs/tags/release/*. Without manifest auto_deploy_refs, refs/heads/main targets preview, while refs/heads/release/* and refs/tags/release/* target production.

When the manifest declares auto_deploy_refs, Forge uses those reviewed patterns to resolve the app environment for built-in webhook candidates after it snapshots the manifest. auto_deploy_refs does not make arbitrary refs deployable through the built-in webhook path; use map deploy or custom CI for refs outside the built-in webhook intake set.

Explicit deploy requests can also use map deploy --repo <owner/repo> --env production --ref <git-ref> --installation-ref <installation-ref>. The --env value is an app environment. It does not change the customer account context.

Validation rules

Forge validates mithran.yaml before build. It rejects:

  • YAML that cannot be parsed into the map.mithran/v1 manifest shape;
  • unknown top-level fields;
  • top-level fields outside the accepted mithran.yaml v1 schema, including public_api, boolean public, body_size_limit_mb, roles, grants, and live_grants;
  • unknown nested fields in non_secret_env, secret_bindings, oauth_api, public_edge.allow, app_env, and app_env.*.policy;
  • public_edge provider expressions such as WAF or Cloud Armor expressions;
  • app_env entries with empty branch_pattern or image_tag;
  • secret-looking names, values, or raw secret refs in non-secret fields.

Common validation results:

Result Meaning Fix
ERR_MANIFEST_PARSE The YAML could not be parsed into the required manifest shape. This can include malformed YAML or missing structurally required fields. Fix the YAML and include the required manifest fields shown in the minimal shape.
ERR_API_VERSION or ERR_KIND The file is not a map.mithran/v1 MithranApp. Use the required header exactly as shown.
ERR_METADATA_APP_ID or ERR_METADATA_NAME App identity is blank. Set non-empty metadata.app_id and metadata.name.
ERR_IDENTITY_PROJECT_REF Project identity is blank. Set a non-empty identity.project_ref.
ERR_CAPABILITY_* Capability kind, route, runtime, or startup command is missing or unsupported. Fix capabilities[]; HTTP capabilities require route, runtime, and startup.command.
ERR_SECRET_VALUE or ERR_SECRET_REF A non-secret field looks like credential material or a raw secret reference. Remove it from the manifest and rotate exposed credentials if needed.
ERR_PUBLIC_EDGE_* Edge type, exposure, allow rule, exception, or provider expression is invalid. Use public_edge.type: platform and one supported exposure value.
ERR_APP_ENV App-environment metadata is blank, or an auto-deploy ref pattern is invalid. Set non-empty branch_pattern and image_tag for each app_env entry, and make any auto_deploy_refs entries start with refs/.
ERR_UNKNOWN_FIELD A field is not in the accepted schema. Remove the field or move that policy to the documented surface that owns it.

Review checklist

Before merging a manifest change, confirm:

  • metadata.app_id and the served app ref are aligned for the intended hostname;
  • identity.project_ref is the correct project/app ref for the served app;
  • each HTTP capability has a route, runtime, and startup command;
  • the process listens on $PORT;
  • the repo contains a Dockerfile that builds the app started by the manifest;
  • non_secret_env contains no secrets;
  • public_edge.exposure matches the approved access model;
  • app_env metadata and any auto_deploy_refs match the intended app environments;
  • release, publish, or route-impacting changes have an owner for verification.

Change impact

Use this table during review to decide who needs to inspect a manifest change:

Change Primary risk Review owner
metadata.app_id or app ref Hostname expectations change. Developer and operator.
identity.project_ref App attaches to the wrong project/app boundary. Operator.
capabilities[].startup.command Runtime starts the wrong process or exits. Developer.
non_secret_env or app_env.*.env_overrides Config drift or accidental secret exposure. Developer.
public_edge.exposure App-route exposure intent changes. Operator.
app_env.*.branch_pattern, auto_deploy_refs, or image_tag App-environment metadata, auto-deploy routing, or build-profile image tag changes. Developer and operator.
secret_bindings Secret mount metadata changes. Operator.

Conventions

  • Your process must listen on $PORT and satisfy Forge runtime readiness. The examples in these docs return HTTP 200 at / and GET /health for local checks.
  • By default, a refs/heads/main push sends a GitHub App webhook that deploys to preview.
  • By default, a refs/heads/release/* branch or refs/tags/release/* tag sends a GitHub App webhook that deploys to production.
  • Reviewed auto_deploy_refs can change app-environment resolution for those built-in webhook candidates, but cannot add new webhook intake refs.
  • The build comes from your Dockerfile. The manifest declares the app; the Dockerfile builds it.
  • Use App access and sharing when changing public_edge.exposure.