merge: T009 config conventions

This commit is contained in:
m2 (AI Agent) 2026-07-02 02:26:15 +02:00
commit 368b1c3a28

130
docs/config.md Normal file
View file

@ -0,0 +1,130 @@
# m2-market configuration reference
Covers the CLI's local config/state files (per machine/operator) and the
`m2-ledger` service's environment variables. Sourced from
`specs/001-market-first-wedge/contracts/cli.md`,
`specs/001-market-first-wedge/contracts/ledger-api.md`, and
`specs/001-market-first-wedge/data-model.md` (§Operator, §InstallState).
## 1. `~/.m2-market/config.toml`
Per-machine CLI config (contracts/cli.md). One file per operator/machine —
`operator_id` and API keys are provisioned per machine, not shared (data-model.md
§Operator: "CLI config carries `operator_id` + API keys per machine").
```toml
# ~/.m2-market/config.toml
# Required: identifies this machine/operator for all ledger + catalog calls.
operator_id = "op_nasr"
# Required: tenant scope for catalog search/index filtering.
tenant = "machine-machine"
# m2-ledger HTTP API (contracts/ledger-api.md). CLI uses a "service"-class key
# (see §4 below) — never an admin key.
ledger_url = "http://m2-ledger:8000"
ledger_api_key = "svc_xxxxxxxxxxxxxxxxxxxx"
# Catalog semantic search / indexer backend.
memory_api_url = "https://memory.machinemachine.ai"
memory_api_key = "mem_xxxxxxxxxxxxxxxxxxxx"
# Registry (Forgejo) — used by `m2-market publish` to push branches/open listing PRs.
forgejo_url = "https://git.machinemachine.ai"
forgejo_token = "frg_xxxxxxxxxxxxxxxxxxxx"
# Which AdapterProtocol implementation `install` uses to plan/apply/verify bundles
# (contracts/apply-adapter.md). "local" is the only adapter in v1.
apply_adapter = "local"
```
Notes:
- All four `*_url` + `*_key`/`*_token` pairs are required for `install`/`publish`/`search`
to function; `wallet`/`show` need at least `ledger_url`+`ledger_api_key`.
- **File permissions must be `0600`** — this file holds live API keys. Treat it the
same as an SSH private key (see §5 Security rules).
- No secrets are ever baked into images or repos; this file is the runtime injection
point (constitution VI).
## 2. `~/.m2-market/state.json`
Per-machine install ledger for the local `AdapterProtocol` — the idempotency and
re-apply guard `install` checks before re-running work (Story 1 AC-3: re-run with an
existing grant + applied state is a no-op, exit 0). Shape defined in
`data-model.md` §InstallState; this is the file `m2core_sync` will merge into once
fedlearn rails land.
Shape: `{installs: {listing_id: {version, grant_id, ts, changeset_hash, status}}}`,
where `status` is one of `applied | failed | rolled_back`.
Example:
```json
{
"installs": {
"sol_pdf_export_v1": {
"version": "1.2.0",
"grant_id": "grant_8f3a1c",
"ts": "2026-06-30T14:02:11Z",
"changeset_hash": "sha256:9c1f...e42b",
"status": "applied"
}
}
}
```
## 3. `m2-ledger` service environment variables
`m2-ledger` is deployed as a Coolify app on the `coolify` network (constitution VI —
no secrets in the image; all of the below are injected at runtime as env vars, never
committed).
| Var | Purpose | Default | Notes |
|---|---|---|---|
| `LEDGER_DB_PATH` | Path to the SQLite tx-log database file. | — (required) | Single source of truth; balances are always derived by folding this log (data-model.md §Wallet), never a separately-writable balance table. |
| `LEDGER_SERVICE_KEYS` | Comma-separated list of valid `service`-class API keys. | — (required) | Accepted via `X-API-Key` header for service endpoints (§4). |
| `LEDGER_ADMIN_KEYS` | Comma-separated list of valid `admin`-class API keys. | — (required) | Accepted via `X-API-Key` header for admin endpoints (§4). Keep this set small; these mint credit and can trigger snapshots. |
| `LEDGER_PLATFORM_PCT` | Default platform cut applied on `/tx/install` when the request body omits `platform_pct`. | `0.10` | **UNCONFIRMED** — data-model.md/ledger-api.md flag this as a default pending confirmation, not a locked value. |
| `LEDGER_STARTER_GRANT` | Default credit amount minted by `/grant/starter` when the request body omits `amount`. | `100` | **UNCONFIRMED** — same flag as above; ledger-api.md invariant 5 lists both defaults as config-not-code. |
| `REGISTRY_REPO_URL` | Forgejo repo URL (`m2/market-registry`) that `/snapshot` commits `audit/YYYY-MM-DD.json` into. | — (required) | Used by both the admin-triggered snapshot and the daily cron snapshot. |
| `FORGEJO_TOKEN` | Forgejo API token used to author the snapshot commit above. | — (required) | Scope to the single registry repo; do not reuse the CLI's `forgejo_token` from config.toml. |
## 4. Key classes: service vs admin
Two API key classes, both passed via the `X-API-Key` header (contracts/ledger-api.md).
Callers: the CLI, the Store, and the indexer use `service` keys; only ledger operators
(humans/admin tooling) hold `admin` keys.
| Endpoint | Key class |
|---|---|
| `GET /health` | none |
| `GET /balance/{operator_id}` | service |
| `POST /tx/install` | service |
| `POST /tx/refund` | service |
| `GET /tx?operator_id=&reason=&since=` | service |
| `GET /license/{operator_id}/{listing_id}` | service |
| `POST /grant/starter` | admin |
| `POST /snapshot` | admin (also runs unauthenticated via daily cron, in-process) |
Rule of thumb: anything that **mints** credit (`starter` grants) or **exports** the
full ledger (`snapshot`) is admin-only. Everything a normal install/refund/balance-check
flow needs is service-scoped — this is the key class that belongs in
`~/.m2-market/config.toml`'s `ledger_api_key`.
## 5. Security rules
1. **No secrets in repos or container images.** All keys/tokens in this document
(`ledger_api_key`, `memory_api_key`, `forgejo_token`, `LEDGER_SERVICE_KEYS`,
`LEDGER_ADMIN_KEYS`, `FORGEJO_TOKEN`) are injected at runtime — via `config.toml`
on the machine for the CLI, or via Coolify env vars for `m2-ledger`. Never commit
real values; example values above are placeholders only (constitution VI:
canary-first, reversible deployment — "No secrets in repos or images; keys
injected at runtime").
2. **`~/.m2-market/config.toml` must be mode `0600`.** It is the only place all four
live credentials (ledger, memory, Forgejo) sit together on a machine.
```bash
chmod 600 ~/.m2-market/config.toml
```
3. **Admin keys (`LEDGER_ADMIN_KEYS`) are minting/export authority** — scope
distribution tightly (see §4); CLI configs should never carry an admin key.