diff --git a/registry/routing/catalog.yaml b/registry/routing/catalog.yaml index 03c33ce..085875d 100644 --- a/registry/routing/catalog.yaml +++ b/registry/routing/catalog.yaml @@ -421,6 +421,35 @@ entries: - "Re-run email-connect read-only scan with warden access --exec / env inject; confirm metadata-only evidence under binky-control/mailmeta/." - "Verify capabilities-safe on tenants/data/binky/company-email/imap; if EXPOSED taint was set, clear custom_metadata after rotation." + - id: binky-qonto-api + title: Binky Qonto bank API credentials (read-only MCP) + need_keywords: [binky, qonto, bank, api, finance, cost-run-rate, mcp, organization] + owner_repo: railiance-platform + subsystem: OpenBao + qonto-mcp-server + warden_executes: false + wiki_ref: wiki/playbooks/binky-qonto-api.md#worker-checklist + canon_ref: binky-control/integrations/qonto-mcp.md + reviewed: "2026-07-21" + status: draft + risk: high + # CCR-2026-0008: policy + OIDC role pending apply; founder Red provision + # (DEC-2026-004 / OH-2026-003) unblocks BINKY-WP-0005-T05 first read-only pull. + # Read-only is harness tool allow-list — Qonto keys are not scope-limited server-side. + auth_method: "caller's own OpenBao token (OIDC netkingdom role binky-qonto-api-workload-kv-read)" + path_template: "tenants/binky/qonto/api" + fetch_command: "bao kv get -field=QONTO_API_KEY tenants/binky/qonto/api" + exec_capable: true + lane: secret + rotation: + method: rotate + owner: binky-control + automatable: false + steps: + - "In the Qonto dashboard, revoke the old API key and mint a new one under /settings/integrations (do not paste it into chat or Git)." + - "`bao kv put tenants/binky/qonto/api QONTO_API_KEY=@file` (and QONTO_ORGANIZATION_ID=@file if the org id changed); shred the mode-0600 input file(s)." + - "Re-run qonto-mcp-server read-only pull with warden access --exec; update binky-control finance/CostRunRate.md metadata only." + - "Verify capabilities-safe on tenants/data/binky/qonto/api; if EXPOSED taint was set, clear custom_metadata after rotation." + - id: agent-harness-forgejo-deploy title: agent-harness Forgejo deploy key (write sandbox; binky-control at cutover) need_keywords: [agent-harness, forgejo, deploy, key, ssh, executor-sandbox, railiance, binky-control, deploy-key] diff --git a/wiki/CredentialRouting.md b/wiki/CredentialRouting.md index dfdbda7..86c095b 100644 --- a/wiki/CredentialRouting.md +++ b/wiki/CredentialRouting.md @@ -112,6 +112,7 @@ EXPOSED taint: `wiki/playbooks/exposed-taint.md` · `warden taint `. | Catalog `id` | Routing focus | Playbook | | --- | --- | --- | +| `binky-qonto-api` | tenant Qonto API on `tenants/binky/qonto/api` (CCR-2026-0008) | `wiki/playbooks/binky-qonto-api.md` | | `object-storage-sts` | NK-WP-0007 STS vending path | `wiki/playbooks/object-storage-sts.md` | | `database-dynamic-credentials` | OpenBao database secrets engine | `wiki/playbooks/database-dynamic-credentials.md` | diff --git a/wiki/playbooks/binky-qonto-api.md b/wiki/playbooks/binky-qonto-api.md new file mode 100644 index 0000000..0e19758 --- /dev/null +++ b/wiki/playbooks/binky-qonto-api.md @@ -0,0 +1,131 @@ +# Binky Qonto bank API + +Date: 2026-07-21 +Catalog: `binky-qonto-api` (status `draft` until provision; `risk: high`) +Owner: `railiance-platform` (CCR-2026-0008) · consumer need: `binky-control` +Workplan: BINKY-WP-0005 · Decision: DEC-2026-004 (approved) + +API credentials for the company Qonto account so the self-hosted +`qonto/qonto-mcp-server` can run **read-only** balance and transaction pulls for +control-plane finance feeds (`finance/CostRunRate.md`, Finance Steward rhythm). + +**Payments and transfers are Red lane forever** — never allow-list write/payment +tools in the harness. Qonto API keys are not scope-limited server-side; read-only +is enforced at the harness tool allow-list. + +--- + +## Provider (Qonto — non-secret) + +| Setting | Value | +| --- | --- | +| Dashboard | Qonto web app → `/settings/integrations` | +| Auth shape | API key + organization ID | +| MCP server | `qonto/qonto-mcp-server` (self-hosted; not the hosted OAuth connector) | +| Env names only | `QONTO_API_KEY`, `QONTO_ORGANIZATION_ID` | + +Design (variant decision, read-only boundary, consumers): +`binky-control/integrations/qonto-mcp.md` + +## OpenBao pointers + +| Field | Value | +| --- | --- | +| Mount | `tenants` | +| Path | `tenants/binky/qonto/api` | +| Fields | `QONTO_API_KEY`, `QONTO_ORGANIZATION_ID` | +| Policy | `workload-kv-read-binky-qonto-api` | +| OIDC role | `binky-qonto-api-workload-kv-read` (`groups=net-kingdom-admins`) | +| Risk | `high` | + +--- + +## Worker checklist + +1. Login as caller (after CCR-2026-0008 policy + role applied): + + ```bash + bao login -method=oidc -path=netkingdom role=binky-qonto-api-workload-kv-read + ``` + +2. Fetch via sanctioned transport (never paste into chat): + + ```bash + warden access binky-qonto-api --all --no-policy --exec -- \ + qonto-mcp-server + # or dual-field inject when wiring a harness session: + # warden access binky-qonto-api --all --no-policy --exec -- \ + # env | grep -E '^QONTO_' | sed 's/=.*/=/' + ``` + + Until catalog is `active` and resolvable, use bao as caller with files: + + ```bash + umask 077 + bao kv get -field=QONTO_API_KEY tenants/binky/qonto/api > /tmp/qonto.key + bao kv get -field=QONTO_ORGANIZATION_ID tenants/binky/qonto/api > /tmp/qonto.org + chmod 600 /tmp/qonto.key /tmp/qonto.org + export QONTO_API_KEY="$(cat /tmp/qonto.key)" + export QONTO_ORGANIZATION_ID="$(cat /tmp/qonto.org)" + shred -u /tmp/qonto.key /tmp/qonto.org + ``` + +3. Run **read-only** MCP tools only (organization, accounts, transactions, + statements metadata). Do **not** invoke card, invoicing, request, or transfer + tools. + +4. Store **metadata-only** evidence under `binky-control/finance/` (update + `CostRunRate.md` TBC rows; no bulk statement dumps in git). + +Agents (`WARDEN_AGENT_ID` set): raw value stream refused (exit 7). Use `--out` / +`--exec` / `--wrap` / `--fingerprint`. + +--- + +## Verify (capabilities-safe) + +```bash +LANE=$(bao token create -policy=workload-kv-read-binky-qonto-api -ttl=2m -field=token) +bao token capabilities "$LANE" tenants/data/binky/qonto/api # read +bao token revoke "$LANE" + +DEFAULT=$(bao token create -policy=default -ttl=2m -field=token) # deny of create is also pass +bao token capabilities "$DEFAULT" tenants/data/binky/qonto/api # deny +bao token revoke "$DEFAULT" +``` + +Never use `bao kv get` for deny tests. + +--- + +## Founder provision (Red lane) + +```bash +# In Qonto dashboard: /settings/integrations → create API key, note organization ID +# values only in mode-0600 files, never argv/chat +umask 077 +# key into /tmp/qonto.key, org id into /tmp/qonto.org — private terminal only +bao kv put tenants/binky/qonto/api \ + QONTO_API_KEY=@/tmp/qonto.key \ + QONTO_ORGANIZATION_ID=@/tmp/qonto.org +shred -u /tmp/qonto.key /tmp/qonto.org +``` + +Also note **plan tier + monthly fee** for `binky-control/finance/CostRunRate.md` +row 4 (and desk-rent amount for row 1 from recent debits when first pull runs). + +Then re-verify capabilities, promote catalog to `active`, set CCR +`access_frontdoor.resolvable: true` / `readiness: ready`. + +## Rotation + +```bash +warden rotate-guide binky-qonto-api +``` + +## See also + +- `binky-control/integrations/qonto-mcp.md` +- `wiki/playbooks/tenant-secret-onboarding.md` +- CCR-2026-0008 in railiance-platform +- DEC-2026-004 / OH-2026-003 in binky-control