Move configuration from .env to a YAML config file #32

Closed
opened 2026-09-08 22:32:09 +00:00 by dev-agent · 0 comments
Collaborator

Filed for later. Not blocking the first demonstration, which runs fine on .env.

Why

Environment variables are flat, and the things we already know are coming are not:

  • #26 multiple forges needs a list of named connections, each with a kind, base URL, credential and operator allowlist. In env vars that becomes NISSE_FORGE_1_KIND, NISSE_FORGE_1_URL, … which is a struct encoded in variable names.
  • #27 multiple projects needs a list of projects, each with a forge connection, repo, and clone path.
  • A4's per-channel allowlists are already comma-splitting inside a single variable, which has no room for per-connection scoping.

YAML expresses all three directly. It is also closer to the spec's own illustration: A11 renders the role mapping as YAML, and we implemented it as four flat variables.

roles:
  executor: claude-haiku-4-5
  planner: claude-opus-5
forges:
  - id: home-gitea
    kind: gitea
    url: https://gitea.dongar.net
    operators: [dongar]
projects:
  - name: demo
    forge: home-gitea
    repo: dongar/demo
    workspace: ~/nisse-demo-workspace/project

Design points to settle when it is built

Secrets should probably not live in the file. A5 keeps vendor credentials off the agent entirely — it holds one LiteLLM token — and A7 puts secrets in a Bitwarden machine account. So the YAML should carry structure, with tokens either still read from the environment or referenced (token: ${NISSE_LLM_TOKEN}) so the file itself can be committed or reviewed without leaking. That also keeps the A7 migration a change of one resolver rather than the whole file format.

Environment must still win. Deployment overrides without editing files, and it keeps CI able to inject values as it does today.

The layout guard applies unchanged. Startup refuses to run when the state store or the config file sits inside the workspace clone, because git add -A would commit and push it. That check keys on paths, not on format, so it carries over.

Validation stays fail-fast. The current behaviour — report every missing value at once, treat whitespace as missing — is worth preserving rather than reinventing; a schema check should produce one message listing everything wrong.

Related

#26 multiple forges · #27 per-project state · #30 agent per project

Filed for later. Not blocking the first demonstration, which runs fine on `.env`. ### Why Environment variables are flat, and the things we already know are coming are not: - **#26 multiple forges** needs a *list* of named connections, each with a kind, base URL, credential and operator allowlist. In env vars that becomes `NISSE_FORGE_1_KIND`, `NISSE_FORGE_1_URL`, … which is a struct encoded in variable names. - **#27 multiple projects** needs a list of projects, each with a forge connection, repo, and clone path. - **A4's per-channel allowlists** are already comma-splitting inside a single variable, which has no room for per-connection scoping. YAML expresses all three directly. It is also closer to the spec's own illustration: **A11 renders the role mapping as YAML**, and we implemented it as four flat variables. ```yaml roles: executor: claude-haiku-4-5 planner: claude-opus-5 forges: - id: home-gitea kind: gitea url: https://gitea.dongar.net operators: [dongar] projects: - name: demo forge: home-gitea repo: dongar/demo workspace: ~/nisse-demo-workspace/project ``` ### Design points to settle when it is built **Secrets should probably not live in the file.** A5 keeps vendor credentials off the agent entirely — it holds one LiteLLM token — and A7 puts secrets in a Bitwarden machine account. So the YAML should carry *structure*, with tokens either still read from the environment or referenced (`token: ${NISSE_LLM_TOKEN}`) so the file itself can be committed or reviewed without leaking. That also keeps the A7 migration a change of one resolver rather than the whole file format. **Environment must still win.** Deployment overrides without editing files, and it keeps CI able to inject values as it does today. **The layout guard applies unchanged.** Startup refuses to run when the state store or the config file sits inside the workspace clone, because `git add -A` would commit and push it. That check keys on paths, not on format, so it carries over. **Validation stays fail-fast.** The current behaviour — report every missing value at once, treat whitespace as missing — is worth preserving rather than reinventing; a schema check should produce one message listing everything wrong. ### Related #26 multiple forges · #27 per-project state · #30 agent per project
Sign in to join this conversation.