Design doc for hardening qonto-assistant before deployment to railiance01: this is the first fleet service that must be internet-reachable (external harness clients, not just in-cluster jobs) while holding a real bank credential. Covers identity (key-cape in place of the interim bearer token), authorization (finance.qonto.read in flex-auth + tenant-engine capability roles instead of the hardcoded default_tenant_id), network exposure (facade-only internet address), isolation profile, and a Kings Guard mapping (the existing audit stream is already Immune-Observation-shaped; nothing to rebuild later). Ships one concrete, dependency-free piece of that design now: DenyEscalationTracker locks out an actor who repeatedly triggers arg_constraint/credential_exfil denies within a short window, closing the gap where a probing client could retry indefinitely at whatever rate the existing rate limiter otherwise allows. Wired through CapabilityService, on by default, configurable via QONTO_DENY_ESCALATION_* env vars. Ordinary denies (authz_denied, tenant_scope) never count toward it. Also adds specs/security-genome.yaml (kings-guard's genome-record shape, populated now so no rework is needed once a consumer exists). Verified: pytest -> 39 passed (8 new); REST and MCP smoke scripts both pass against fixtures; compileall clean. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
86 lines
3.1 KiB
YAML
86 lines
3.1 KiB
YAML
# Security Genome record for qonto-assistant.
|
|
#
|
|
# Schema per kings-guard/specs/NetKingdomImmuneArchitecture.md §9.1
|
|
# ("Minimum Genome Record"). Kings Guard does not exist as a running system
|
|
# yet — this record is written now so no rework is needed once an admission
|
|
# or posture-assessment consumer does exist. See docs/SecurityPractice.md.
|
|
|
|
security_genome_record:
|
|
id: kg:genome:qonto-assistant
|
|
version: 0.1.0
|
|
|
|
ownership:
|
|
tenant_id: binky
|
|
accountable_owner: bernd.worsch
|
|
operational_owner: qonto-assistant
|
|
|
|
purpose:
|
|
intent: >
|
|
Sole holder of the company Qonto bank API credential; exposes
|
|
read-only finance capabilities (org summary, transactions,
|
|
CostRunRate hints) to authorized agent harnesses and operators via a
|
|
governed REST + MCP surface, so no client ever holds the bank key
|
|
directly.
|
|
criticality: high
|
|
|
|
identities:
|
|
workload_identity: "TBD — pending key-cape/workload-identity integration (QONTO-WP-0004)"
|
|
deployment_identity: "TBD — pending Railiance placement decision"
|
|
|
|
capabilities:
|
|
provides:
|
|
- finance.qonto.read
|
|
consumes:
|
|
- openbao-secret.read # tenants/binky/qonto-api
|
|
- qonto-thirdparty-api.read
|
|
|
|
communication:
|
|
ingress:
|
|
- caller: facade-activator # not yet built — see docs/SecurityPractice.md §6
|
|
protocol: https
|
|
egress:
|
|
- destination: openbao
|
|
protocol: https
|
|
- destination: qonto-thirdparty-api
|
|
protocol: https
|
|
# No other egress is expected or permitted. Any additional outbound
|
|
# destination observed at runtime is, by definition, a deviation from
|
|
# this genome.
|
|
|
|
data:
|
|
classifications:
|
|
- tenant-confidential
|
|
- financial
|
|
persistence: ephemeral
|
|
export_allowed: false
|
|
|
|
provenance:
|
|
signed_artifact_required: false # not yet implemented fleet-wide
|
|
approved_registry: "TBD"
|
|
sbom_required: false # not yet implemented; tracked as a gap
|
|
reproducible_build_preferred: true
|
|
|
|
expected_behavior:
|
|
max_request_rate: "per QONTO_RATE_LIMIT_REQUESTS / QONTO_RATE_LIMIT_WINDOW_SECONDS (config.py)"
|
|
external_network_access: false # beyond the two declared egress destinations
|
|
interactive_shell: prohibited
|
|
privilege_escalation: prohibited
|
|
|
|
recovery:
|
|
redeployable: true
|
|
maximum_recovery_time: PT5M # stateless; cold-start dominated by scale-to-zero wake latency
|
|
maximum_data_loss: PT0S # no persisted state
|
|
|
|
tolerances:
|
|
- id: local-dev-shared-secret-auth
|
|
description: >
|
|
QONTO_ASSISTANT_MCP_TOKEN shared-secret bearer auth is tolerated
|
|
only for fixture-backed local development, never for a deployment
|
|
holding real Qonto credentials.
|
|
expires_at: null # revisit once key-cape integration (QONTO-WP-0004) lands
|
|
- id: self-asserted-actor-claims
|
|
description: >
|
|
X-Actor-* headers are self-asserted, not yet cryptographically
|
|
bound to verified identity. Tolerated until key-cape/flex-auth
|
|
integration (QONTO-WP-0004) closes this.
|
|
expires_at: null
|