Add SecurityPractice.md, Security Genome record, and deny-escalation lockout
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>
This commit is contained in:
parent
78eb2a819c
commit
3faf1fed71
9 changed files with 655 additions and 1 deletions
86
specs/security-genome.yaml
Normal file
86
specs/security-genome.yaml
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
# 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
|
||||
Loading…
Add table
Add a link
Reference in a new issue