qonto-assistant/INTENT.md

136 lines
5.6 KiB
Markdown
Raw Normal View History

# INTENT
> This file explains why **qonto-assistant** exists — the problem it solves,
> the principle that governs its boundaries, and what it must never become.
> Blueprint: `specs/ArchitectureBlueprint.md`. Origin: binky-control
> BINKY-WP-0005 (Qonto custody + first read-only pull) and the multi-harness
> policy-drift problem (2026-07-21).
## Why it exists
Binky (and later other tenants) need agents to **see** bank reality —
balances, transactions, cost-run-rate signals — so the company control plane
can operate without founder spreadsheet archaeology. Credentials already live
in OpenBao (`tenants/binky/qonto-api`); the thirdparty REST API works.
What fails as scale:
- Wiring vendor MCP or bank keys into **every** coding agent / harness
(Claude, Codex, Cursor, Grok, agent-harness, …) creates **policy drift**.
- Qonto API keys are **not** scope-limited server-side: there is no
“read-only key.” Spend and volume-cost actions must be blocked **before**
the vendor sees them.
- Agent-harness is the session policy shell, not the place to reimplement
bank rules per runtime. llm-connect is LLM routing, not domain tools.
**qonto-assistant** exists so that **one governed domain service** is the
only component allowed to hold the bank credential and speak Qontos
protocol. All harnesses are clients of that service. Policy is code + tests
in one place.
## Purpose
`qonto-assistant` is a **policy-governed Qonto domain assistant**: a dual
surface (**REST + MCP**) for agentic and scripted finance awareness under a
hard **no spend / no volume-cost** policy (v1).
Core principle:
> Harnesses never hold the bank key. The assistant is the choke point.
> Default deny. Reads for control-plane awareness; payments stay Red lane
> (human in the Qonto app).
## Primary utility
### As a multi-harness finance tool
- Streamable-HTTP **MCP** for interactive agents (one client config, no
secrets in MCP configs).
- Stable **REST** for rhythm sessions, CostRunRate refresh, CI smoke, and
non-MCP clients.
- Shared **policy kernel** on every call (tool id + arguments + actor
claims) — not connect-time allow-lists alone.
### As a custody-aware connector
- Fetches secrets only via the sanctioned OpenBao path (ops-warden catalog
`binky-qonto-api` / CCR-2026-0008 pattern).
- Optional flex-auth gate: `finance.qonto.read` (and later finer scopes).
- Audit metadata (who/what/decision) without logging secret material.
### As dogfood for Operational Knowledge
- Internal use on Binky is product evidence (governed bank access for agent
fleets). May graduate to multi-tenant `tenants/<slug>/qonto-api` later.
## Strategic role
```text
OpenBao custody (existing)
+ sole Qonto client identity
+ default-deny tool catalog
+ dual MCP + REST
= consistent finance awareness across every harness
```
It sits **below** agent-harness (session runtime) and **beside** other domain
connectors (email-connect). It does not replace DATEV/StB/DUO; it complements
them with operational bank visibility.
## Governing principles
1. **One policy, many clients** — never reimplement bank rules per harness.
2. **Default deny** — only explicitly allowed read capabilities exist in v1.
3. **No token passthrough** — clients authenticate *to the assistant*; the
assistant alone authenticates *to Qonto*.
4. **Semantic policy, not vendor dump** — we design a safe catalog; we do
not auto-mirror vendor write tools.
2026-07-22 00:31:50 +02:00
5. **Platform fit** — flex-auth, OpenBao, ops-warden, State Hub evidence; no
parallel IAM.
6. **Autonomy lanes** — map to binky-control AutonomyPolicy: reads Green/Blue;
plan change / transfers / API key minting remain Red.
## What it must never become
- **Not a payments engine.** No transfers, SEPA, card issuance, or
fee-bearing create operations in v1 (and only via explicit future DEC +
Red/Yellow gates thereafter).
- **Not a full accounting system.** DATEV / StB / DUO stay authoritative for
books.
- **Not a generic MCP gateway.** Fleet gateways may sit *in front* later;
domain policy lives here.
- **Not an LLM router.** Provider selection stays in llm-connect.
- **Not a scheduler.** Cadence stays in activity-core / agent-harness.
- **Not a secret store.** OpenBao remains custody; this service is a
short-lived consumer.
- **Not a per-harness plugin bag.** Client integration is thin: URL +
workload identity + tool profile name.
## Relationship to other repos
| Repo | Relationship |
| --- | --- |
| `binky-control` | First tenant / consumer; CostRunRate, AutonomyPolicy, business policy source |
| `ops-warden` / `railiance-platform` | Credential front door and CCR/policy for `tenants/…/qonto-api` |
| `agent-harness` | Grants profile `finance-qonto-read` pointing at this service only |
| `llm-connect` | Models that *talk*; this service *acts* on bank data |
| `flex-auth` | Authorization decisions for who may call |
| `email-connect` | Sibling pattern: purpose-built connector, not raw vendor wiring |
## Success looks like
1. Every agent that needs Qonto data uses **only** this service.
2. A single policy change (e.g. tighten export) applies fleet-wide.
3. No bank API key appears in harness env, MCP client configs, or chat.
4. Deny decisions are tested and audited; spend tools are not registered.
5. CostRunRate and Finance Steward can refresh from REST without ad-hoc scripts
holding secrets.
## Normative references
- `specs/ArchitectureBlueprint.md` — architecture and phased delivery
- `research/2026-07-21-mcp-gateway-and-governed-domain-assistant.md` — external
pattern research
- binky-control `integrations/qonto-mcp.md` — custody and first-pull evidence
- agent-harness ADR-001 / INTENT — session runtime boundaries