diff --git a/registry/routing/catalog.yaml b/registry/routing/catalog.yaml index 03c33ce..1ebb0c9 100644 --- a/registry/routing/catalog.yaml +++ b/registry/routing/catalog.yaml @@ -421,6 +421,36 @@ 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: active + risk: high + # CCR-2026-0008: policy + OIDC role applied; secret at tenants/binky/qonto-api + # (fields API_KEY, API_USER). Map to QONTO_API_KEY / QONTO_ORGANIZATION_ID for + # qonto-mcp-server. First read-only pull 2026-07-21 (BINKY-WP-0005-T05). + # 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=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 API_KEY=@file` (and API_USER=@file if the login/org slug changed); shred the mode-0600 input file(s)." + - "Re-run read-only pull with warden access --exec (map API_KEY→QONTO_API_KEY, API_USER→QONTO_ORGANIZATION_ID); 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..9dc5831 100644 --- a/wiki/CredentialRouting.md +++ b/wiki/CredentialRouting.md @@ -100,6 +100,7 @@ run the owner's tool as the caller and preserve owner custody. | `railiance-backup-offsite-lane` | "railiance-platform OpenBao KV for Nextcloud WebDAV + age recovery" | `warden access railiance-backup-offsite-lane --out FILE` (`risk: high`; agents: no raw stream) | | `forgejo-admin-api-token` | "railiance-platform OpenBao KV for Forgejo admin PAT" | `warden access forgejo-admin-api-token --out FILE` (`risk: high`) | | `binky-company-email-imap` | "tenant IMAP on `tenants/binky/company-email/imap` (IONOS)" | `warden access binky-company-email-imap --out FILE` (`risk: high`) | +| `binky-qonto-api` | "tenant Qonto API on `tenants/binky/qonto-api` (API_KEY+API_USER)" | `warden access binky-qonto-api --out FILE` (`risk: high`) | Promotion criteria: `wiki/playbooks/catalog-lane-promotion.md`. High-risk / agent boundary: `wiki/playbooks/agent-read-boundary.md`. diff --git a/wiki/playbooks/binky-qonto-api.md b/wiki/playbooks/binky-qonto-api.md new file mode 100644 index 0000000..37176cc --- /dev/null +++ b/wiki/playbooks/binky-qonto-api.md @@ -0,0 +1,124 @@ +# Binky Qonto bank API + +Date: 2026-07-21 +Catalog: `binky-qonto-api` (status `active`, `resolvable: true`, `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 read-only balance and +transaction pulls can feed control-plane finance (`finance/CostRunRate.md`, +Finance Steward rhythm). Prefer self-hosted `qonto/qonto-mcp-server` or the +Qonto thirdparty REST API with the same credentials. + +**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 | login (`API_USER`) + secret (`API_KEY`) → `Authorization: login:key` | +| MCP env map | `API_KEY`→`QONTO_API_KEY`, `API_USER`→`QONTO_ORGANIZATION_ID` | +| MCP server | `qonto/qonto-mcp-server` (self-hosted; not the hosted OAuth connector) | +| API host | `https://thirdparty.qonto.com` | + +Design: `binky-control/integrations/qonto-mcp.md` + +## OpenBao pointers + +| Field | Value | +| --- | --- | +| Mount | `tenants` | +| Path | `tenants/binky/qonto-api` | +| Fields | `API_KEY`, `API_USER` | +| 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: + + ```bash + bao login -method=oidc -path=netkingdom role=binky-qonto-api-workload-kv-read + ``` + +2. Fetch via sanctioned transport (never paste into chat): + + ```bash + # lengths / presence only when debugging + warden access binky-qonto-api --all --no-policy --exec -- \ + sh -c 'export QONTO_API_KEY="$API_KEY" QONTO_ORGANIZATION_ID="$API_USER"; + # then: qonto-mcp-server or curl thirdparty with Authorization login:key + :' + ``` + + Dual-field inject via bao (files mode 0600): + + ```bash + umask 077 + bao kv get -field=API_KEY tenants/binky/qonto-api > /tmp/qonto.key + bao kv get -field=API_USER tenants/binky/qonto-api > /tmp/qonto.user + chmod 600 /tmp/qonto.key /tmp/qonto.user + export QONTO_API_KEY="$(cat /tmp/qonto.key)" + export QONTO_ORGANIZATION_ID="$(cat /tmp/qonto.user)" + shred -u /tmp/qonto.key /tmp/qonto.user + ``` + +3. Run **read-only** 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 login/org slug +umask 077 +bao kv put tenants/binky/qonto-api \ + API_KEY=@/tmp/qonto.key \ + API_USER=@/tmp/qonto.user +shred -u /tmp/qonto.key /tmp/qonto.user +``` + +## 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