Capability·Driven
The framework

The framework in depth.

Once you can define a capability, this is the model those capabilities live in: the invariants that keep them independent, and the artifacts they produce. A separate page covers the pipeline that produces them.

The invariants

The rules the meta-model enforces

These are not style guidelines. They are structural invariants the model checks — the boundaries that keep capabilities independent and the system composable.

Channels talk to capabilities via REST

Every capability publishes an OpenAPI spec. Customer, partner, and external systems reach it only through that contract.

Capabilities talk to each other via events — never REST

Every capability publishes an AsyncAPI spec of the events it emits on the shared bus. Peers subscribe; they do not call the REST API.

Every service has both contracts

Each service inside a capability publishes its own OpenAPI spec for intra-capability calls and an AsyncAPI spec for the events it publishes and consumes.

No shared sub-capabilities

Every sub-capability belongs to exactly one parent. If two capabilities seem to need the same one, either promote it or accept they solve different problems that merely sound alike.

No shared databases, entities, or codebases

If capability A needs data owned by B, A subscribes to B's events. Share contracts, not implementations.

DS

Data stores are capability-scoped and first-class

Every DS-XXX belongs to one capability. Every entity lives in exactly one store, whose data classification equals or exceeds every entity it holds.

ENT

Entities are capability-scoped, not journey-scoped

The data model lives with the capability that owns it. Journeys reference entities by ID; they do not define them.

NFR

NFRs are journey-scoped; SLAs compose

End-to-end latency and regulatory SLAs are journey-scoped. Per-service SLAs live on the technical-service spec and compose into the journey target.

SEQ

Sequence diagrams are journey-phase-scoped

A journey initiates many sequences, each attached to a phase. There are no capability-level or service-level sequence diagrams.

The four valid communication paths

Everything a capability can legitimately do to reach the outside world reduces to these.

Channel → REST

Inbound requests

Channels and external consumers call the capability's published OpenAPI contract.

Cap ⚡ Event

Cross-capability

Capabilities emit and subscribe to events on the shared bus — the only path between them.

Svc → REST

Intra-capability

Services within one capability call each other over their own OpenAPI specs.

Svc ⚡ Event

Intra-capability async

Services publish and consume events via their own AsyncAPI specs on the bus.

Principal artifacts

Eighteen schemas, one substrate

The meta-model is a sector-neutral set of JSON Schemas. A sector pack supplies concrete content that validates against them. Everything below is a first-class, versioned artifact — grouped by the scope that owns it. Expand any schema for an example modelled on a worked commercial-banking pack.

Capability-scoped — owned by the capability

capabilityA capability file — the six-part bundle.
{
  "capability_id": "CAP-003",
  "name": "Payment Operations",
  "description": "Originates, routes, clears and settles payment instructions across FPS, BACS, CHAPS, correspondent networks, card schemes, and open banking.",
  "status": "Baselined",

  "mandate_source": [
    { "type": "regulation", "reference": "Payment Services Regulations 2017 (SI 2017/752)" }
  ],

  "market_context": {
    "competitive_landscape": {
      "table_stakes": ["Direct FPS, BACS and CHAPS participation", "SWIFT correspondent access"],
      "differentiators": ["ISO 20022 payment-initiation APIs with 99%+ STP"],
      "disruptors": ["Wise, Revolut Business and Airwallex in cross-border"]
    },
    "regulatory_horizon": {
      "current": ["APP Fraud Mandatory Reimbursement — in force 7 October 2024"],
      "incoming": ["Interbank Infrastructure Renewal (IIR), replacing the NPA"],
      "enforcement_signals": ["PSR monitoring APP-fraud reimbursement rates across all PSPs"]
    },
    "build_vs_buy": {
      "must_build_in_house": ["Scheme-participation governance; the payment policy engine"],
      "buy_candidates": ["Central-infrastructure connectivity (Form3, Bottomline PTX)"]
    }
  },

  "sub_capabilities": [
    { "id": "CAP-003.04", "name": "International Payments", "promotion_test": { "criteria_met": 4, "promoted": true } },
    { "id": "CAP-003.03", "name": "CHAPS", "promotion_test": { "criteria_met": 0, "promoted": false } }
  ],

  "design_decisions": [
    {
      "id": "DD-004",
      "decision": "CHAPS is retained as a sub-capability despite the Bank of England's distinct governance role.",
      "rationale": "It shares the payment execution lifecycle and operations team with FPS and BACS; no separate platform is needed.",
      "rejected_because": "Promoting CHAPS would create a capability with no distinct lifecycle or independent scaling driver."
    }
  ],

  "owned_data_domains": ["Payment intents and executions", "CHAPS high-value payments"]
}
sub-capabilityA bounded area within one capability; defines the promotion test.
{
  "id": "CAP-003.01",
  "name": "Faster Payments",
  "description": "Origination, routing, and settlement of retail and corporate Faster Payments Service (FPS) transactions.",
  "promotion_test": {
    "distinct_participants": false,
    "separate_regulatory_framework": false,
    "distinct_lifecycle": false,
    "independent_scalability": false,
    "criteria_met": 0,
    "promoted": false,
    "rationale": "FPS is a domestic interbank rail; its lifecycle is co-extensive with the parent capability. No criteria met."
  }
}
data-modelThe entities a capability owns.
{
  "capability_id": "CAP-003",
  "status": "Draft",
  "entities": [
    {
      "id": "ENT-070",
      "name": "VrpConsent",
      "description": "A Variable Recurring Payment consent granted by a customer to a PISP/merchant. Lifecycle: pending_authorisation → active → revoked | expired.",
      "owning_service": "SVC-009",
      "fields": [
        {
          "name": "consent_id",
          "type": "UUID",
          "nullable": false
        },
        {
          "name": "max_single_payment_amount",
          "type": "decimal",
          "nullable": false
        }
      ]
    }
  ]
}
data-storeA persistence boundary; every entity is stored in exactly one.
{
  "data_store_id": "DS-014",
  "name": "Domestic Payments Store",
  "description": "Persistence boundary for VRP consents and payments owned by the Domestic Payments service.",
  "capability_id": "CAP-003",
  "status": "Draft",
  "technology_type": "relational",
  "data_classification": "regulated",
  "owning_services": ["SVC-009"],
  "stored_entities": ["ENT-070", "ENT-071"],
  "backup_policy": { "rto_minutes": 15, "rpo_minutes": 5, "retention_days": 1825 }
}
service-boundariesThe services composing a capability.
{
  "capability_id": "CAP-003",
  "status": "Draft",
  "architectural_principle": "Cross-capability communication is exclusively async events. Within a capability, services communicate freely.",
  "services": [
    {
      "service_id": "SVC-009",
      "service_name": "Domestic Payments",
      "capability_id": "CAP-003",
      "owned_entities": [
        "ENT-070",
        "ENT-071"
      ],
      "published_events": [
        "EVT-157"
      ]
    }
  ]
}
event-catalogueThe events a capability's services publish.
{
  "capability_id": "CAP-003",
  "document_version": "0.1.0",
  "status": "Draft",
  "description": "Domain events published by Payment Operations services.",
  "events": [
    {
      "event_id": "EVT-157",
      "name": "VrpPaymentExecuted",
      "source_service": "SVC-009",
      "source_entity": "ENT-071",
      "trigger": "VRP payment validated against consent and fraud score; Faster Payment executed successfully.",
      "topic": "payments.vrp",
      "capability_scope": "cross-capability"
    }
  ]
}
eventA single event on the shared bus.
{
  "event_id": "EVT-157",
  "name": "VrpPaymentExecuted",
  "source_service": "SVC-009",
  "source_entity": "ENT-071",
  "trigger": "VRP payment validated against consent parameters and fraud score; Faster Payment executed.",
  "payload_schema": {
    "vrp_payment_id": {
      "type": "string (UUID v4)"
    },
    "consent_id": {
      "type": "string (UUID v4)"
    },
    "amount": {
      "type": "string (decimal, GBP)"
    }
  },
  "consumers": [
    {
      "service": "SVC-001",
      "service_name": "Retail Banking Core",
      "action": "Debit source account; update transaction history."
    }
  ],
  "ordering_guarantees": "Per-consent ordering via consent_id partition key on topic payments.vrp.",
  "topic": "payments.vrp",
  "data_classification": "Financial + PII",
  "retention": "5 years",
  "cloudevents_type": "uk.bank.payments.vrp.executed"
}
governanceThe governance rules applicable to a capability.
{
  "id": "GOV-003",
  "capability_id": "CAP-003",
  "capability_name": "Payment Operations",
  "rules": [
    {
      "rule_id": "GOV-003-R01",
      "name": "APP Fraud Mandatory Reimbursement",
      "source_legislation": "PSR APP Fraud Reimbursement Policy (PS23/3); FPS Scheme Rules (Pay.UK)",
      "description": "From 7 October 2024 the bank must reimburse APP fraud victims up to £85,000 per claim within 5 business days unless stop-the-clock applies.",
      "authority_level": "senior_manager",
      "approval_chain": ["Head of Fraud Operations", "Senior Manager (Payment Services)"],
      "status": "current"
    }
  ]
}

Journey-scoped — owned by the journey

journey-inventoryThe flat, prioritised list of every journey.
{
  "document_version": "0.1.0",
  "status": "Draft",
  "recommended_first_journey": "JRN-001",
  "journeys": [
    {
      "id": "JRN-029",
      "name": "Commercial VRP (Variable Recurring Payment) Consent Setup",
      "description": "A customer grants a VRP consent to a PISP/merchant under the FCA cVRP scheme; the bank enforces parameters and processes payments without per-payment SCA.",
      "triggering_persona": "PER-006",
      "capabilities_touched": ["CAP-001", "CAP-003", "CAP-007"],
      "sub_capabilities_involved": ["CAP-001.01", "CAP-003.06", "CAP-007.03"],
      "cross_capability": true,
      "priority": "medium"
    }
  ]
}
journey-detailThe full specification of a single journey.
{
  "journey_id": "JRN-029",
  "name": "Commercial VRP (Variable Recurring Payment) Consent Setup",
  "status": "Stable",
  "triggering_persona": "PER-006",
  "capabilities_touched": [
    "CAP-001",
    "CAP-003",
    "CAP-007"
  ],
  "phases": [
    {
      "id": "PH-115",
      "name": "VRP Consent Request",
      "description": "A PISP/merchant submits a VRP consent request specifying max single amount, max monthly amount, category, and expiry.",
      "actors": [
        "PER-006",
        "SVC-017",
        "SVC-100"
      ],
      "services": [
        "SVC-017",
        "SVC-100"
      ],
      "governance_rules": [
        "GOV-007-R01"
      ]
    }
  ],
  "paths": {
    "happy_path": {
      "description": "PISP submits consent → customer authenticates and grants → consent active → PISP submits VRP payment → bank validates and executes as FPS.",
      "phases": [
        "PH-115",
        "PH-116",
        "PH-117"
      ]
    }
  }
}
nfrEnd-to-end non-functional requirements for a journey.
{
  "journey_id": "JRN-029",
  "status": "Draft",
  "per_phase_nfrs": [
    {
      "phase_id": "PH-115",
      "phase_name": "VRP Consent Request",
      "latency": {
        "consent_request_initiation_p95": "< 500ms",
        "tpp_redirect_p95": "< 1,000ms"
      },
      "availability": "99.5% — per FCA Open Banking API uptime obligation"
    }
  ],
  "cross_cutting_nfrs": [
    {
      "id": "XNFR-JRN029-01",
      "name": "VRP Consent Record Retention",
      "requirement": "VRP consent and payment records retained for a minimum of 5 years for PSR/FCA audit.",
      "rationale": "PSR 2017 and FCA record-keeping obligations."
    }
  ]
}

System-level — one per organisation

service-dependenciesThe system-wide dependency map and build order.
{
  "document_version": "0.1.0",
  "status": "Draft",
  "tier_definitions": [
    "T0",
    "T1",
    "T2",
    "T3",
    "T4"
  ],
  "services": [
    {
      "id": "SVC-009",
      "name": "Domestic Payments Service",
      "classification": "domain_specific",
      "tier": "T2",
      "capability_domain": "Payment Operations (CAP-003)",
      "dependencies": [
        {
          "service_id": "SVC-051",
          "criticality": "hard",
          "rationale": "Every outgoing payment must receive sanctions clearance before scheme submission."
        }
      ]
    }
  ],
  "build_order": [
    {
      "phase": 1,
      "name": "Platform Bedrock",
      "tiers": [
        "T0"
      ],
      "services_in_phase": [
        "SVC-100",
        "SVC-103"
      ]
    }
  ]
}
personaA type of actor in the system.
{
  "persona_id": "PER-006",
  "name": "Third Party Provider (TPP)",
  "type": "external",
  "subtype": "partner",
  "description": "An FCA-authorised AISP or PISP accessing the bank's Open Banking APIs under PSD2/PSR 2017 with explicit customer consent.",
  "capability_touchpoints": [
    "CAP-003",
    "CAP-007"
  ],
  "access_classification": "regulated_third_party",
  "channels": [
    "open_banking_api"
  ],
  "frequency": "real_time"
}
observability-modelOrganisation-wide observability posture.
{
  "document_version": "0.1.0",
  "status": "Draft",
  "log_routing_architecture": {
    "ingestion_layer": "OTel Collector per cluster",
    "fan_out_stores": [
      "hot: Elasticsearch (30d)",
      "cold: object storage (5y)"
    ],
    "pii_scrubbing": "At the collector, before any store"
  },
  "logging_schema_by_category": [
    {
      "category_id": "LOG-CAT-001",
      "category_name": "API / Edge",
      "applies_to_services": [
        "SVC-101",
        "SVC-017"
      ],
      "required_fields": [
        {
          "field": "timestamp",
          "type": "ISO8601 datetime"
        },
        {
          "field": "trace_id",
          "type": "string"
        }
      ]
    }
  ],
  "per_service_instrumentation_checklist": [
    {
      "id": "INST-001",
      "name": "Structured Logging",
      "description": "All log output emitted as structured JSON lines with correlation fields (trace_id, span_id, service_id) on every line.",
      "mandatory": true
    }
  ],
  "data_freshness": [
    {
      "contract_id": "FRS-001",
      "signal_name": "Service topology (dependency graph)",
      "source": "Service catalogue build pipeline",
      "max_staleness": "24h"
    }
  ]
}
security-modelOrganisation-wide security posture.
{
  "document_version": "0.1.0",
  "status": "Draft",
  "service_to_service_auth": {
    "primary_mechanism": "mTLS + SPIFFE workload identity",
    "jwt_propagation": "End-user context propagated as a signed JWT",
    "policy_enforcement": "Istio AuthorizationPolicy at the sidecar"
  },
  "data_classification": {
    "levels": [
      "public",
      "internal",
      "confidential",
      "regulated"
    ],
    "service_classifications": [
      {
        "service_id": "SVC-009",
        "level": "regulated"
      }
    ]
  },
  "network_segmentation": [
    {
      "zone_id": "ZONE-DMZ",
      "name": "DMZ (Demilitarised Zone)",
      "description": "Internet-facing ingress: API gateway, WAF, DDoS scrubbing, CDN edge."
    }
  ],
  "security_posture_controls": [
    {
      "control_id": "SEC-CTL-001",
      "name": "Zero-Trust Policy Map",
      "description": "A machine-readable allow-list of every permitted service-to-service call; any call not listed is blocked by default.",
      "implementation": "Istio AuthorizationPolicy manifests generated via CI; two-person approval."
    }
  ]
}

Service & index artifacts

technical-serviceThe canonical per-service definition, with SLA and its data stores.
{
  "service_id": "SVC-009",
  "name": "Domestic Payments Service",
  "description": "Authoritative service for originating, routing, clearing, and settling domestic sterling payments across FPS, BACS, and CHAPS rails.",
  "classification": "domain_specific",
  "tier": "T2",
  "capability_mappings": [
    {
      "capability_id": "CAP-003",
      "capability_name": "Payment Operations",
      "realisation_type": "realises_retained_sub_capabilities",
      "sub_capabilities_in_scope": [
        "CAP-003.01",
        "CAP-003.02",
        "CAP-003.03",
        "CAP-003.06"
      ]
    }
  ],
  "dependencies": [
    {
      "service_id": "SVC-051",
      "service_name": "Sanctions Screening Service",
      "dependency_type": "hard_blocking"
    }
  ]
}
api-manifestIndexes OpenAPI + AsyncAPI specs at capability or service scope.
{
  "scope": "service",
  "owner_id": "SVC-017",
  "document_version": "0.1.0",
  "status": "Draft",
  "specs": [
    {
      "kind": "openapi",
      "title": "Open Banking VRP API",
      "version": "0.1.0",
      "path": "api-contracts/open-banking-vrp.openapi.json",
      "role": "channel-facing",
      "consumers": ["PER-006"]
    },
    {
      "kind": "asyncapi",
      "title": "Domestic Payments Events",
      "version": "0.1.0",
      "path": "api-contracts/domestic-payments.asyncapi.yaml",
      "role": "bus-facing"
    }
  ]
}
sequence-manifestIndexes Mermaid sequence diagrams at journey-phase scope.
{
  "journey_id": "JRN-029",
  "document_version": "0.1.0",
  "status": "Draft",
  "sequences": [
    {
      "id": "SEQ-001",
      "phase_id": "PH-115",
      "title": "Happy Path — VRP Consent Grant and First Payment Execution",
      "path": "sequence-diagrams/happy-path.mmd",
      "format": "mermaid",
      "participants": [
        { "kind": "persona", "ref": "PER-006", "role": "initiator" },
        { "kind": "service", "ref": "SVC-017", "role": "responder" }
      ],
      "events_referenced": ["EVT-157"],
      "entities_referenced": ["ENT-070"]
    }
  ]
}

Identifier conventions

PrefixMeaningFormat
CAP-XXXCapability3 digits
SUB-XXXSub-capability3 digits
JRN-XXXJourney3 digits
PH-XXXPhase (within a journey)3 digits
PER-XXXPersona3 digits
CHN-XXXChannel3 digits
SVC-XXXService3 digits
ENT-XXXEntity3 digits
DS-XXXData store3 digits
EVT-XXXEvent3 digits
GOV-XXXGovernance rule3 digits, optional sub-rule
DD-XXXDesign decision3 digits
SEQ-XXXSequence diagram3 digits

Prefixes are conventions, not hard schema requirements. A pack may override them; the schema regex patterns move with it.

Next: how the artifacts get produced. A three-phase pipeline turns these capabilities and their journeys into buildable vertical slices.

See the pipeline →