merge: T009 config conventions
This commit is contained in:
commit
368b1c3a28
1 changed files with 130 additions and 0 deletions
130
docs/config.md
Normal file
130
docs/config.md
Normal 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.
|
||||||
Loading…
Reference in a new issue