binky-control/workplans/BINKY-WP-0007-qonto-governed-assistant.md
tegwick ea568558a8
Some checks failed
Work Records / validate (push) Has been cancelled
BINKY-WP-0007: close out against qonto-assistant's actual delivery
qonto-assistant (sibling repo) already shipped Phase 1 (QONTO-WP-0002)
and Phase 2 MCP surface (QONTO-WP-0003), both finished, 31 tests
passing, ahead of this workplan's original sequencing. Reconciled
T02-T04 against what actually landed there instead of duplicating it.

The one piece qonto-assistant explicitly left for this repo -- the
CostRunRate consumer cutover -- is implemented here:
scripts/qonto-costrunrate-refresh.py calls GET /v1/snapshot and writes
dated, redacted evidence under finance/ for a human to reconcile
against CostRunRate.md. Verified end-to-end against a local
fixture-backed qonto-assistant instance (no real credentials); a real
pull against the live account awaits qonto-assistant getting an actual
deployment, called out as a known gap rather than faked.

Workplan closed (status: finished); remaining gaps (OIDC federation,
harness tool profile registration, Phase 3/4) are carried forward in
qonto-assistant's own closure notes, not duplicated here.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-23 14:02:11 +02:00

7.6 KiB
Raw Blame History

id type title domain repo status owner topic_slug created updated state_hub_workstream_id
BINKY-WP-0007 workplan Qonto Governed Assistant: policy kernel + REST (Phase 1) infotech binky-control finished claude the-custodian 2026-07-22 2026-07-23 8a691acb-3500-4f17-84fe-dcfc7a979fdc

Follow-on from BINKY-WP-0005 (custody lane + first read-only pull, finished). Blueprint: integrations/qonto-governed-assistant/ArchitectureBlueprint.md.

Recommendation being executed: build a small Qonto Governed Assistant service — the only component allowed to hold the bank API key — exposing a default-deny policy-shaped MCP server and thin REST API, so every harness (Claude Code, Codex, Cursor, Grok, agent-harness sessions, scripts) is a dumb client of one governed endpoint instead of each wiring vendor MCP + local allow-lists directly. No spend / no volume-cost tools in v1 — payments, transfers, card ops, and plan changes stay Red lane (human in the Qonto app).

This workplan tracks Phase 1 (policy kernel + REST — minimum useful product, per blueprint §6) plus the binky-control-side consumer cutover. Phase 3 (flex-auth/fleet) and Phase 4 (productization) remain follow-on work.

2026-07-23 status check: implementation is happening in the sibling qonto-assistant repo (registered in the state-hub as qonto-assistant, domain infotech), which has its own workplans mirroring this one: QONTO-WP-0001 (bootstrap, finished), QONTO-WP-0002 (Phase 1 — policy kernel + REST, finished), and QONTO-WP-0003 (Phase 2 — MCP surface, finished, ahead of this workplan's original sequencing which expected Phase 2 to wait). All three ratified DEC-2026-005 decisions hold (option B, dedicated repo, hard v1 freeze, streamable-HTTP transport, no vendor MCP backend). 31 unit tests pass (pytest); REST and MCP smoke scripts both pass against fixture data with no real Qonto credentials. Tasks T02T04 below are rescoped to reflect what actually landed there, plus the one piece that was explicitly left for binky-control: the CostRunRate consumer cutover (T03).

Task: Ratify architecture decisions (blueprint §9)

id: BINKY-WP-0007-T01
status: done
priority: high
state_hub_task_id: "34474d61-0238-4321-a6c0-27c3ad3b8fe3"

2026-07-22: DEC-2026-005 approved as recommended (all five). See DecisionQueue.md for the ratified answers.

Bring the five decision requests from the blueprint to the founder via DecisionQueue.md:

  1. Adopt the domain-assistant architecture (option B) for Qonto.
  2. Repo home: new dedicated qonto-assistant repo (already present in the state-hub repo registry) vs. waiting for a generic finance-connect.
  3. v1 policy freeze: hard deny on all spend / volume-cost tools.
  4. MCP transport: remote streamable-HTTP only for production clients.
  5. Whether to ever run vendor qonto-mcp-server as an internal-only backend (blueprint default: no).

Done when: DEC entry filed, founder decision recorded, blueprint updated with the ratified answers.

Task: Service skeleton — decision function + custody wiring

id: BINKY-WP-0007-T02
status: done
priority: high
state_hub_task_id: "8978dbd9-c7a1-4b5b-9c0c-acf3e08c74bf"

2026-07-23: Delivered in the qonto-assistant repo as QONTO-WP-0002 (T01T07, all done), not as new work in binky-control — the decision from T01 already routed the implementation there. Shipped: protocol-neutral capability core, declarative policy/qonto-v1.yaml + pure PolicyEngine.decide() (default-deny; allows org_summary, list_transactions, cost_run_rate_hints, snapshot_bundle; hard-denies spend, volume_cost, credential_exfil), a Qonto REST client with Authorization: login:key injection and no secret logging, plus guardrails beyond the original ask: bounded pagination/timeouts, rate limiting, bounded concurrency, and redaction tests (IBAN → last-4 only). OpenBao fetch (tenants/binky/qonto-api) is isolated to a dedicated runtime path, never harness env. Verified: pytest → 31 passed (includes Phase 2 additions), python3 -m compileall.

Task: REST surface + CostRunRate consumer cutover

id: BINKY-WP-0007-T03
status: done
priority: medium
state_hub_task_id: "a35e2565-e520-491e-8587-8ec4961f898c"

2026-07-23: REST surface (GET /v1/accounts, /v1/transactions, /v1/snapshot, /v1/health) shipped in qonto-assistant as QONTO-WP-0002-T04, behind the same policy kernel as T02. That repo explicitly scoped the binky-control-side write out of its own runbook (docs/operator-runbook.md: "The repo does not write directly into binky-control/finance/CostRunRate.md. That consumer-side write remains outside this repo.") — so the consumer cutover is this repo's own deliverable, done here: scripts/qonto-costrunrate-refresh.py calls GET /v1/snapshot, writes a dated evidence file under finance/ (redacted — IBAN last-4 only, no secrets, matching the 2026-07-21 first-pull shape), and prints recurring-debit hints for a human to reconcile against finance/CostRunRate.md prose (the script does not edit that file directly — same judgment-call boundary as the original first pull).

Verified end-to-end against a locally started qonto-assistant instance using QONTO_FIXTURE_DIR (no real Qonto credentials): /v1/health reachable, snapshot fetched, evidence file written and inspected clean (no IBAN, no key material), then removed since it was fixture data, not a real pull.

Known gap, not closed by this task: qonto-assistant isn't deployed anywhere yet (local dev only) — a real CostRunRate refresh against the live dogfood account still needs that service running somewhere reachable (railiance, per the blueprint's placement options) with the OpenBao lane wired to it. That's deployment/ops scope, not scripting scope, and belongs to a follow-on task once qonto-assistant has a runtime home.

Task: Smoke tests and closure

id: BINKY-WP-0007-T04
status: done
priority: medium
state_hub_task_id: "a16ef7df-ddd7-474b-8327-0eca5c89ede7"

2026-07-23: REST smoke (scripts/smoke_rest_api.py) and MCP smoke (scripts/smoke_mcp.py) both live in qonto-assistant and both pass against fixtures with no real credentials (QONTO-WP-0002-T07, QONTO-WP-0003-T06). Phase 2 (MCP surface for all harnesses) was not held for a hand-off — it was already built and closed as QONTO-WP-0003 (T01T07, all done, 2026-07-23) while T02/T03 above were still open here: streamable-HTTP MCP adapter on the same policy kernel, three capability tools (qonto_org_summary, qonto_list_transactions, qonto_cost_run_rate_hints), shared-secret bearer-token workload auth with the real OIDC gap called out explicitly (no issuer exists in the fleet yet), REST/MCP audit-schema parity pinned by test, and a documented (not yet registered) finance-qonto-read agent-harness tool profile contract.

This workplan (Phase 1 + consumer cutover) is closed. Known gaps carried forward, tracked in qonto-assistant's own closure notes, not duplicated into new binky-control tasks: real OIDC/workload-identity federation; per-actor identity not yet cryptographically bound to the workload-auth token; finance-qonto-read documented but not registered in agent-harness/agent_harness/profiles.py; Phase 3 (flex-auth resource finance.qonto.read, graduated quotas, redaction profiles) and Phase 4 (productization) not started. Any of these becoming binky-control-actionable (e.g. deploying qonto-assistant, wiring the harness profile) should be a new workplan or an AutopilotWorkQueue.md residual, not a reopening of this one.

Done when: statehub fix-consistency run clean.