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.
These are not style guidelines. They are structural invariants the model checks — the boundaries that keep capabilities independent and the system composable.
Every capability publishes an OpenAPI spec. Customer, partner, and external systems reach it only through that contract.
Every capability publishes an AsyncAPI spec of the events it emits on the shared bus. Peers subscribe; they do not call the REST API.
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.
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.
If capability A needs data owned by B, A subscribes to B's events. Share contracts, not implementations.
Every DS-XXX belongs to one capability. Every entity lives in exactly one store, whose data classification equals or exceeds every entity it holds.
The data model lives with the capability that owns it. Journeys reference entities by ID; they do not define them.
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.
A journey initiates many sequences, each attached to a phase. There are no capability-level or service-level sequence diagrams.
Everything a capability can legitimately do to reach the outside world reduces to these.
Channels and external consumers call the capability's published OpenAPI contract.
Capabilities emit and subscribe to events on the shared bus — the only path between them.
Services within one capability call each other over their own OpenAPI specs.
Services publish and consume events via their own AsyncAPI specs on the bus.
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_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"]
}{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "capability.schema.json",
"title": "Capability",
"description": "A mandate-backed business function within an organisation, bounded by what the organisation is obliged or chooses to do. A capability is the primary unit of architectural decomposition: it owns its data, exposes a curated external API for channels to call, and publishes events on the shared bus for other capabilities to consume. Capabilities do not share sub-capabilities, databases, or implementations. The capability file carries the six-part bundle: mandate, market context (competitive landscape, regulatory horizon, build-vs-buy), sub-capabilities, and design decisions.",
"type": "object",
"required": [
"capability_id",
"name",
"description",
"status",
"mandate_source",
"sub_capabilities",
"owned_data_domains"
],
"additionalProperties": false,
"properties": {
"capability_id": {
"type": "string",
"pattern": "^CAP-[0-9]{3}$",
"description": "Stable unique identifier. Format: CAP-XXX where XXX is a zero-padded integer."
},
"name": {
"type": "string",
"minLength": 1,
"description": "Human-readable capability name."
},
"description": {
"type": "string",
"minLength": 1,
"description": "One paragraph explaining what the capability is, who it serves, and why the organisation must hold it."
},
"status": {
"type": "string",
"enum": [
"Draft",
"In review",
"Approved",
"Baselined",
"Revised"
],
"description": "Lifecycle status of the capability specification."
},
"mandate_source": {
"type": "array",
"minItems": 1,
"description": "The reasons the organisation holds this capability. At least one entry is required. Entries can be statutory (legislation, regulation), internal (policy, charter), or strategic.",
"items": {
"type": "object",
"required": [
"type",
"reference"
],
"additionalProperties": false,
"properties": {
"type": {
"type": "string",
"enum": [
"legislation",
"regulation",
"policy",
"charter",
"strategy"
],
"description": "The category of mandate. Legislation and regulation are external-statutory. Policy and charter are internal-binding. Strategy is internal-discretionary."
},
"reference": {
"type": "string",
"minLength": 1,
"description": "Citation of the specific instrument (e.g. 'Financial Services and Markets Act 2000, Part IV' or 'Board resolution 2024-07: commercial expansion strategy')."
},
"url_or_doc_ref": {
"type": "string",
"description": "Optional URL or internal document reference where the mandate can be retrieved."
}
}
}
},
"outcomes": {
"type": "array",
"description": "Optional. The outcomes the capability is intended to produce, expressed as observable states of the world.",
"items": {
"type": "string"
}
},
"owned_data_domains": {
"type": "array",
"minItems": 1,
"description": "The data domains this capability owns. A data domain is a coherent set of entities under unified stewardship. No two capabilities may own the same domain. Cross-capability data access is via events on the bus, not by reading another capability's store.",
"items": {
"type": "string",
"minLength": 1
}
},
"sub_capabilities": {
"type": "array",
"description": "The sub-capabilities that compose this capability. Each sub-capability belongs to exactly one parent — no sub-capability appears in more than one capability. Use $ref to sub-capability.schema.json.",
"items": {
"$ref": "sub-capability.schema.json"
}
},
"market_context": {
"type": "object",
"description": "The external forces shaping the capability. Three blocks: competitive_landscape describes where the organisation sits relative to others; regulatory_horizon lists the regulatory picture in force and incoming; build_vs_buy describes where the organisation should build in-house versus buy from vendors. Content is prose arrays in each sub-slot.",
"additionalProperties": false,
"properties": {
"competitive_landscape": {
"type": "object",
"additionalProperties": false,
"properties": {
"table_stakes": {
"type": "array",
"items": {
"type": "string"
},
"description": "Baseline features the capability must offer to be credible in its market."
},
"differentiators": {
"type": "array",
"items": {
"type": "string"
},
"description": "Features that distinguish the organisation from peers offering the same capability."
},
"disruptors": {
"type": "array",
"items": {
"type": "string"
},
"description": "Organisations or technologies challenging the incumbent model for this capability."
},
"unbundling": {
"type": "array",
"items": {
"type": "string"
},
"description": "Observations of component functions being separated from the traditional bundle for this capability."
},
"rebundling": {
"type": "array",
"items": {
"type": "string"
},
"description": "Observations of new bundles that combine this capability's functions with adjacent ones."
},
"switching_drivers": {
"type": "array",
"items": {
"type": "string"
},
"description": "Reasons customers or counterparties switch provider for this capability."
}
}
},
"regulatory_horizon": {
"type": "object",
"additionalProperties": false,
"properties": {
"current": {
"type": "array",
"items": {
"type": "string"
},
"description": "Regulations, standards, or rulebooks currently in force for this capability."
},
"incoming": {
"type": "array",
"items": {
"type": "string"
},
"description": "Regulations expected to take effect within the planning horizon."
},
"enforcement_signals": {
"type": "array",
"items": {
"type": "string"
},
"description": "Observable regulator behaviour (enforcement actions, dear-CEO letters, market studies) indicating the direction of travel."
}
}
},
"build_vs_buy": {
"type": "object",
"additionalProperties": false,
"properties": {
"platform_options": {
"type": "array",
"items": {
"type": "string"
},
"description": "Commercial platforms or vendor offerings available for this capability."
},
"must_build_in_house": {
"type": "array",
"items": {
"type": "string"
},
"description": "Elements of the capability that must be built in-house because they embed proprietary knowledge, commercial sensitivity, or non-delegable accountability."
},
"buy_candidates": {
"type": "array",
"items": {
"type": "string"
},
"description": "Elements of the capability where buying from a vendor is preferred over in-house build."
}
}
}
}
},
"design_decisions": {
"type": "array",
"description": "Recorded architectural decisions made about this capability. Includes any overrides to the default promotion_test outcome for sub-capabilities (e.g. retaining a sub-capability that scored 3 of 4).",
"items": {
"type": "object",
"required": [
"id",
"decision",
"rationale"
],
"additionalProperties": false,
"properties": {
"id": {
"type": "string",
"pattern": "^DD-[0-9]{3}$",
"description": "Stable unique identifier within this capability's decision log."
},
"decision": {
"type": "string",
"minLength": 1,
"description": "The decision taken, stated as a positive assertion."
},
"rationale": {
"type": "string",
"minLength": 1,
"description": "Why the decision was taken. Must be non-empty; a design decision without rationale is not a decision."
},
"alternatives_considered": {
"type": "array",
"items": {
"type": "string"
},
"description": "The options considered and not chosen."
},
"rejected_because": {
"type": "string",
"description": "Summary of why the alternatives were rejected."
}
}
}
}
}
}{
"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."
}
}{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "sub-capability.schema.json",
"title": "Sub-capability",
"description": "A bounded area of responsibility within a single capability. Sub-capabilities belong to exactly one parent capability — no sub-capability may be shared across capabilities. Each sub-capability carries a promotion_test recording whether it should remain a sub-capability or be promoted to a standalone capability, against four boundary criteria.",
"type": "object",
"required": [
"id",
"name",
"description",
"promotion_test"
],
"additionalProperties": false,
"properties": {
"id": {
"type": "string",
"pattern": "^SUB-[0-9]{3}$",
"description": "Stable unique identifier for the sub-capability. Format: SUB-XXX where XXX is a zero-padded integer. Sub-capabilities exist in their own namespace, distinct from capabilities (CAP-XXX)."
},
"name": {
"type": "string",
"minLength": 1,
"description": "Human-readable name for the sub-capability."
},
"description": {
"type": "string",
"minLength": 1,
"description": "One to three sentence explanation of what the sub-capability is responsible for within its parent capability."
},
"promotion_test": {
"type": "object",
"description": "The four-criteria test determining whether this sub-capability should be promoted to a standalone capability. Each criterion is a boolean. criteria_met is the count of true values. promoted is the decision; the prima facie rule is promoted=true if criteria_met>=3, but an override is allowed provided the parent capability records a matching design_decision justifying the deviation.",
"required": [
"distinct_participants",
"separate_regulatory_framework",
"distinct_lifecycle",
"independent_scalability",
"criteria_met",
"promoted"
],
"additionalProperties": false,
"properties": {
"distinct_participants": {
"type": "boolean",
"description": "True if the sub-capability involves actors, counterparties, or external participants that do not appear in other sub-capabilities of the parent."
},
"separate_regulatory_framework": {
"type": "boolean",
"description": "True if the sub-capability is governed by a body of regulation, standards, or rulebooks that is materially distinct from those governing other sub-capabilities of the parent."
},
"distinct_lifecycle": {
"type": "boolean",
"description": "True if the sub-capability has phases of operation (origination, approval, settlement, dispute, closure, etc.) that are not present in the parent capability's other sub-capabilities."
},
"independent_scalability": {
"type": "boolean",
"description": "True if the sub-capability's demand drivers and throughput requirements vary independently of the parent capability's broader workload."
},
"criteria_met": {
"type": "integer",
"minimum": 0,
"maximum": 4,
"description": "Count of the four boolean criteria set to true. Must equal the actual count; validators should enforce this."
},
"promoted": {
"type": "boolean",
"description": "The decision. If criteria_met >= 3, promoted defaults to true. Any deviation (criteria_met >= 3 but promoted=false, or criteria_met < 3 but promoted=true) requires a corresponding entry in the parent capability's design_decisions explaining the override."
},
"rationale": {
"type": "string",
"description": "Free-text explanation of the promotion_test outcome, typically summarising the market evidence and why the boolean criteria are set as they are."
}
}
}
}
}{
"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
}
]
}
]
}{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "data-model.schema.json",
"title": "Data Model (capability-scoped)",
"description": "The canonical data model for a capability. Defines all entities owned by the capability's services. Capability-scoped: every entity belongs to exactly one capability via its owning service. Cross-capability data access is forbidden — if another capability needs access to an entity, it subscribes to events published by the owning service on the bus. Journeys reference entities by ID but do not define them.",
"type": "object",
"required": [
"capability_id",
"status",
"entities"
],
"additionalProperties": false,
"properties": {
"capability_id": {
"type": "string",
"pattern": "^CAP-[0-9]{3}$",
"description": "The capability that owns this data model."
},
"document_version": {
"type": "string",
"pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
},
"status": {
"type": "string",
"enum": [
"Draft",
"In review",
"Stable",
"Revised"
]
},
"design_principle": {
"type": "string",
"description": "Optional statement of the data-model design principle governing this capability's entities (e.g. aggregate boundaries, ownership rules)."
},
"entities": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"required": [
"id",
"name",
"description",
"owning_service",
"fields"
],
"additionalProperties": false,
"properties": {
"id": {
"type": "string",
"pattern": "^ENT-[0-9]{3}$",
"description": "Stable unique identifier within the capability's data model."
},
"name": {
"type": "string",
"minLength": 1,
"description": "Entity name, typically PascalCase."
},
"description": {
"type": "string",
"minLength": 1,
"description": "What this entity represents in the business domain."
},
"owning_service": {
"type": "string",
"pattern": "^SVC-[0-9]{3}$",
"description": "The service within this capability that owns the entity. Must resolve to a service in the capability's service-boundaries."
},
"aggregate_root": {
"type": "boolean",
"description": "True if this entity is an aggregate root in DDD terms — the consistency boundary for a cluster of related entities."
},
"fields": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"required": [
"name",
"type"
],
"additionalProperties": false,
"properties": {
"name": {
"type": "string",
"minLength": 1
},
"type": {
"type": "string",
"minLength": 1,
"description": "Logical type (e.g. UUID, string, date, enum, object, array<T>). Not tied to any specific database or language."
},
"required": {
"type": "boolean"
},
"validation_rule": {
"type": "string",
"description": "Natural-language or formal validation rule."
},
"source": {
"type": "string",
"description": "Phase or event that supplies this field (e.g. PH-XXX or EVT-XXX)."
},
"governed_by": {
"type": [
"string",
"null"
],
"description": "Governance rule ID (e.g. GOV-XXX) that applies to this field, if any."
},
"transparency_note": {
"type": "string",
"description": "How this field is or is not exposed to customers or external participants, where relevant to fair-value or transparency obligations."
},
"computed_from": {
"oneOf": [
{
"type": "object",
"additionalProperties": false,
"properties": {
"formula": {
"type": "string"
},
"source_fields": {
"type": "array",
"items": {
"type": "string"
}
}
}
},
{
"type": "string"
},
{
"type": "null"
}
]
}
}
}
},
"relationships": {
"type": "array",
"description": "References to other entities. Relationships to entities in other capabilities are forbidden — cross-capability data flow is via events only. Relationships here are intra-capability."
},
"design_decisions": {
"type": "array",
"items": {
"type": "object",
"required": [
"id",
"decision",
"rationale"
],
"additionalProperties": false,
"properties": {
"id": {
"type": "string",
"pattern": "^DD-[0-9]{3}$"
},
"decision": {
"type": "string",
"minLength": 1
},
"rationale": {
"type": "string",
"minLength": 1
},
"alternatives_considered": {
"type": "array",
"items": {
"type": "string"
}
},
"rejected_because": {
"type": "string"
}
}
}
}
}
}
}
}
}{
"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 }
}{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "data-store.schema.json",
"title": "Data Store (capability-scoped)",
"description": "A persistence boundary inside a capability. Every entity owned by the organisation is stored in exactly one data store. Data stores are capability-scoped: they may be shared between services within the same capability, but never across capabilities. Cross-capability data access is via events on the bus, never by reading another capability's store. A data store has its own technology type, data classification, and optional deployment posture; these are physical-layer concerns that a sector pack may tighten.",
"type": "object",
"required": [
"data_store_id",
"name",
"capability_id",
"status",
"technology_type",
"data_classification",
"owning_services",
"stored_entities"
],
"additionalProperties": false,
"properties": {
"data_store_id": {
"type": "string",
"pattern": "^DS-[0-9]{3}$",
"description": "Stable unique identifier. Format: DS-XXX where XXX is a zero-padded integer."
},
"name": {
"type": "string",
"minLength": 1,
"description": "Human-readable name for the data store."
},
"description": {
"type": "string",
"description": "Optional. What the store holds and why it exists as a separate persistence boundary."
},
"capability_id": {
"type": "string",
"pattern": "^CAP-[0-9]{3}$",
"description": "The capability that owns this data store. A data store belongs to exactly one capability — never shared across capabilities. Every service listed in owning_services must belong to this capability."
},
"status": {
"type": "string",
"enum": [
"Draft",
"In review",
"Approved",
"Baselined",
"Revised"
],
"description": "Lifecycle status of the data store specification."
},
"technology_type": {
"type": "string",
"enum": [
"relational",
"document",
"key-value",
"event-log",
"graph",
"time-series",
"object-store"
],
"description": "The category of storage technology. relational: SQL/ACID table store. document: JSON/BSON document store. key-value: cache or simple KV. event-log: append-only log (Kafka, Kinesis). graph: graph database. time-series: metrics or time-indexed observations. object-store: blob/file storage. Packs may tighten this enum to specific engines."
},
"data_classification": {
"type": "string",
"enum": [
"public",
"internal",
"confidential",
"regulated"
],
"description": "The sensitivity classification of data held in this store. Validators should enforce that this classification is greater than or equal to the classification of every entity stored in it (regulated > confidential > internal > public)."
},
"owning_services": {
"type": "array",
"minItems": 1,
"uniqueItems": true,
"description": "Services within the owning capability that read from and write to this store. At least one required. Every service listed must belong to the same capability as the store (capability_id on technical-service matches this store's capability_id).",
"items": {
"type": "string",
"pattern": "^SVC-[0-9]{3}$"
}
},
"stored_entities": {
"type": "array",
"minItems": 1,
"uniqueItems": true,
"description": "The entities (ENT-XXX) persisted in this store. Every entity in the organisation must appear in exactly one data store's stored_entities array. An entity's owning_service (from data-model) must appear in this store's owning_services.",
"items": {
"type": "string",
"pattern": "^ENT-[0-9]{3}$"
}
},
"deployment": {
"type": "object",
"description": "Optional deployment posture. Physical-layer concerns; a pack may tighten or require these.",
"additionalProperties": false,
"properties": {
"hosting": {
"type": "string",
"enum": [
"managed-cloud",
"self-hosted",
"saas",
"on-premise"
],
"description": "Where the store runs. managed-cloud: cloud-vendor managed service (e.g. RDS, DynamoDB). self-hosted: operated by the organisation on IaaS. saas: third-party SaaS. on-premise: organisation data centre."
},
"vendor_or_engine": {
"type": "string",
"description": "Concrete technology (e.g. 'PostgreSQL 16', 'Amazon DynamoDB', 'Apache Kafka 3.7'). Optional at meta-model level; packs typically tighten."
},
"region_strategy": {
"type": "string",
"enum": [
"single-region",
"multi-region-active-passive",
"multi-region-active-active"
],
"description": "Geographic deployment posture. Drives RTO/RPO achievability and regulatory data-residency compliance."
}
}
},
"backup_policy": {
"type": "object",
"description": "Optional backup and recovery targets for this store. Values here should compose with the SLAs declared on the services that own the store.",
"additionalProperties": false,
"properties": {
"rto_minutes": {
"type": [
"number",
"null"
],
"minimum": 0,
"description": "Recovery time objective in minutes."
},
"rpo_minutes": {
"type": [
"number",
"null"
],
"minimum": 0,
"description": "Recovery point objective in minutes."
},
"retention_days": {
"type": [
"number",
"null"
],
"minimum": 0,
"description": "How long backups are retained. Regulatory retention requirements typically live here."
}
}
},
"design_decisions": {
"type": "array",
"description": "Architectural decisions about the data store itself (choice of technology, sharing scope within the capability, region strategy). Capability-level decisions about data ownership live on the capability, not here.",
"items": {
"type": "object",
"required": [
"id",
"decision",
"rationale"
],
"additionalProperties": false,
"properties": {
"id": {
"type": "string",
"pattern": "^DD-[0-9]{3}$"
},
"decision": {
"type": "string",
"minLength": 1
},
"rationale": {
"type": "string",
"minLength": 1
},
"alternatives_considered": {
"type": "array",
"items": {
"type": "string"
}
},
"rejected_because": {
"type": "string"
}
}
}
}
}
}{
"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"
]
}
]
}{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "service-boundaries.schema.json",
"title": "Service Boundaries (capability-scoped)",
"description": "The service boundary map for a capability. Enumerates the services that compose the capability, what entities each owns, what events each publishes and consumes, and what other services each depends on. Capability-scoped: services live inside exactly one capability. Inter-service communication within the capability may use REST or gRPC; communication to other capabilities is via events on the bus only. Channels reach the capability via the capability API, not directly by calling individual services.",
"type": "object",
"required": [
"capability_id",
"status",
"services"
],
"additionalProperties": false,
"properties": {
"capability_id": {
"type": "string",
"pattern": "^CAP-[0-9]{3}$"
},
"document_version": {
"type": "string",
"pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
},
"status": {
"type": "string",
"enum": [
"Draft",
"In review",
"Stable",
"Revised"
]
},
"architectural_principles": {
"type": "array",
"items": {
"type": "string"
},
"description": "Optional statements of the architectural rules this capability's service boundaries observe (e.g. single-ownership, event-driven cross-capability communication, share-contracts-not-implementations)."
},
"services": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"required": [
"service_id",
"service_name",
"owned_entities",
"published_events",
"consumed_events"
],
"additionalProperties": false,
"properties": {
"service_id": {
"type": "string",
"pattern": "^SVC-[0-9]{3}$"
},
"service_name": {
"type": "string",
"minLength": 1
},
"owned_entities": {
"type": "array",
"description": "Entities this service owns. Each entity is owned by exactly one service across the entire organisation.",
"items": {
"type": "string",
"pattern": "^ENT-[0-9]{3}$"
}
},
"published_events": {
"type": "array",
"description": "Events this service publishes on the bus. Event IDs must resolve to entries in an event catalogue.",
"items": {
"type": "string",
"pattern": "^EVT-[0-9]{3}$"
}
},
"consumed_events": {
"type": "array",
"description": "Events this service consumes from the bus. Consumed events may be published by services in other capabilities — that is how cross-capability data flows.",
"items": {
"type": "object",
"required": [
"event_id"
],
"additionalProperties": false,
"properties": {
"event_id": {
"type": "string",
"pattern": "^EVT-[0-9]{3}$"
},
"source_capability": {
"type": "string",
"pattern": "^CAP-[0-9]{3}$",
"description": "The capability whose service publishes this event. Informational."
},
"maps_to": {
"type": "object",
"additionalProperties": false,
"properties": {
"target_entity": {
"type": "string",
"pattern": "^ENT-[0-9]{3}$"
},
"field_mapping": {
"type": "object"
}
}
}
}
}
},
"consumed_apis": {
"type": "array",
"description": "Intra-capability APIs this service consumes. Cross-capability API consumption is forbidden.",
"items": {
"type": "object",
"required": [
"provider_service_id",
"call_pattern",
"dependency_criticality"
],
"additionalProperties": false,
"properties": {
"provider_service_id": {
"type": "string",
"pattern": "^SVC-[0-9]{3}$"
},
"provider_service_name": {
"type": "string"
},
"api_description": {
"type": "string"
},
"call_pattern": {
"type": "string",
"enum": [
"synchronous",
"asynchronous",
"streaming"
]
},
"dependency_criticality": {
"type": "string",
"enum": [
"hard",
"soft"
]
},
"governance_note": {
"type": "string"
}
}
}
},
"external_system_dependencies": {
"type": "array",
"description": "Third-party systems or platforms the service depends on, outside the organisation.",
"items": {
"type": "object",
"required": [
"system_name",
"call_pattern"
],
"additionalProperties": false,
"properties": {
"system_name": {
"type": "string",
"minLength": 1
},
"base_url": {
"type": "string"
},
"call_pattern": {
"type": "string"
},
"data_retrieved": {
"type": "array",
"items": {
"type": "string"
}
},
"auth_method": {
"type": "string"
},
"latency_target_ms": {
"type": "integer",
"minimum": 0
},
"async_fallback": {
"type": "string"
},
"notes": {
"type": "string"
}
}
}
},
"design_decisions": {
"type": "array",
"items": {
"type": "object",
"required": [
"id",
"decision",
"rationale"
],
"additionalProperties": false,
"properties": {
"id": {
"type": "string",
"pattern": "^DD-[0-9]{3}$"
},
"decision": {
"type": "string",
"minLength": 1
},
"rationale": {
"type": "string",
"minLength": 1
},
"alternatives_considered": {
"type": "array",
"items": {
"type": "string"
}
},
"rejected_because": {
"type": "string"
}
}
}
}
}
}
}
}
}{
"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"
}
]
}{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "event-catalogue.schema.json",
"title": "Event Catalogue (capability-scoped)",
"description": "The canonical catalogue of events published by a capability's services. Capability-scoped: a capability is the source of record for all events its services emit. Consumers of these events may live in other capabilities — that is the permitted cross-capability communication mechanism. Each entry in the catalogue is a full event definition; the schema uses $ref to event.schema.json.",
"type": "object",
"required": [
"capability_id",
"document_version",
"status",
"events"
],
"additionalProperties": false,
"properties": {
"capability_id": {
"type": "string",
"pattern": "^CAP-[0-9]{3}$"
},
"document_version": {
"type": "string",
"pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
},
"status": {
"type": "string",
"enum": [
"Draft",
"In review",
"Stable",
"Revised"
]
},
"events": {
"type": "array",
"minItems": 1,
"description": "All events published by services belonging to this capability. Every event's source_service must belong to this capability.",
"items": {
"$ref": "event.schema.json"
}
}
}
}{
"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"
}{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "event.schema.json",
"title": "Event (catalogue entry)",
"description": "Definition of a single event that flows on the shared event bus. Events are how capabilities communicate with each other — no capability reads another's data store, but any capability may subscribe to events another capability publishes. Each event has an owning service within an owning capability, a payload schema, and one or more consumers.",
"type": "object",
"required": [
"event_id",
"name",
"source_service",
"trigger",
"payload_schema",
"consumers",
"ordering_guarantees",
"topic",
"data_classification",
"retention",
"cloudevents_type"
],
"additionalProperties": false,
"properties": {
"event_id": {
"type": "string",
"pattern": "^EVT-[0-9]{3}$"
},
"name": {
"type": "string",
"pattern": "^[A-Z][A-Za-z0-9]+(ed|en|n)$",
"description": "PascalCase, past tense. Events describe things that have happened (e.g. AccountOpened, PaymentSettled, LoanDecided)."
},
"source_service": {
"type": "string",
"pattern": "^SVC-[0-9]{3}$",
"description": "The service that publishes this event."
},
"source_capability": {
"type": "string",
"pattern": "^CAP-[0-9]{3}$",
"description": "The capability the publishing service belongs to."
},
"source_entity": {
"type": "string",
"pattern": "^ENT-[0-9]{3}$",
"description": "The entity whose state change the event reports. Optional for events that do not correspond to a single entity change."
},
"trigger": {
"type": "string",
"minLength": 1,
"description": "What causes the event to be published."
},
"payload_schema": {
"type": "object",
"description": "The structure of the event payload. Can be an inline JSON Schema or a reference to an external schema."
},
"derived_from": {
"type": "object",
"additionalProperties": {
"type": "string"
},
"description": "Mapping of payload field paths to source-entity field paths, where the event payload is derived from entity state."
},
"consumers": {
"type": "array",
"description": "Services that subscribe to this event. May include services in other capabilities — that is the permitted cross-capability communication pattern.",
"items": {
"type": "object",
"required": [
"service_id"
],
"additionalProperties": false,
"properties": {
"service_id": {
"type": "string",
"pattern": "^SVC-[0-9]{3}$"
},
"capability_id": {
"type": "string",
"pattern": "^CAP-[0-9]{3}$"
},
"maps_to": {
"type": "object",
"additionalProperties": {
"type": "string"
}
}
}
}
},
"ordering_guarantees": {
"type": "string",
"description": "Ordering semantics (e.g. 'per-aggregate', 'per-partition', 'best-effort')."
},
"topic": {
"type": "string",
"minLength": 1,
"description": "The bus topic or subject on which the event is published."
},
"data_classification": {
"type": "string",
"enum": [
"public",
"internal",
"confidential",
"regulated"
]
},
"worm_audit_pipeline": {
"type": "boolean",
"description": "Whether this event must be written to a write-once-read-many audit store for compliance purposes."
},
"retention": {
"type": "string",
"description": "Retention period for the event and its payload."
},
"cloudevents_type": {
"type": "string",
"description": "The CloudEvents-compliant type value for this event (reverse-DNS style, e.g. com.acme.capability.entity.event)."
}
}
}{
"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"
}
]
}{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "governance.schema.json",
"title": "Governance rules (capability-scoped)",
"description": "The governance rules applicable to a capability. Capability-scoped: each capability has its own governance file listing the rules it must observe. The rule structure is universal; the rule content (which statutes, which regulators, which obligations) is pack-specific. Journeys reference rule IDs at the phase level via journey-detail.governance_rules; the resolution of those IDs lives here.",
"type": "object",
"required": [
"capability_id",
"rules"
],
"additionalProperties": false,
"properties": {
"capability_id": {
"type": "string",
"pattern": "^CAP-[0-9]{3}$"
},
"document_version": {
"type": "string",
"pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
},
"status": {
"type": "string",
"enum": [
"Draft",
"In review",
"Approved",
"Baselined",
"Revised"
]
},
"rules": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"required": [
"id",
"name",
"source",
"description"
],
"additionalProperties": false,
"properties": {
"id": {
"type": "string",
"pattern": "^GOV-[0-9]{3}(-R[0-9]{2})?$",
"description": "Stable identifier. Plain form GOV-XXX or the GOV-XXX-RYY variant where YY is a sub-rule within a rule set."
},
"name": {
"type": "string",
"minLength": 1
},
"source": {
"type": "object",
"required": [
"type",
"reference"
],
"additionalProperties": false,
"properties": {
"type": {
"type": "string",
"enum": [
"legislation",
"regulation",
"standard",
"policy",
"contract",
"charter"
]
},
"reference": {
"type": "string",
"minLength": 1
},
"url_or_doc_ref": {
"type": "string"
},
"jurisdiction": {
"type": "string",
"description": "Jurisdiction in which the source has legal force, where applicable."
},
"effective_date": {
"type": "string"
},
"review_cadence": {
"type": "string"
}
}
},
"description": {
"type": "string",
"minLength": 1
},
"scope": {
"type": "object",
"additionalProperties": false,
"properties": {
"applies_to_personas": {
"type": "array",
"items": {
"type": "string",
"pattern": "^PER-[0-9]{3}$"
}
},
"applies_to_phases": {
"type": "array",
"items": {
"type": "string",
"pattern": "^PH-[0-9]{3}$"
}
},
"applies_to_entities": {
"type": "array",
"items": {
"type": "string",
"pattern": "^ENT-[0-9]{3}$"
}
},
"applies_to_events": {
"type": "array",
"items": {
"type": "string",
"pattern": "^EVT-[0-9]{3}$"
}
}
}
},
"enforcement_points": {
"type": "array",
"items": {
"type": "string"
},
"description": "The specific phases, services, or controls where the rule is enforced."
},
"data_requirements": {
"type": "array",
"items": {
"type": "string"
}
},
"retention_requirement": {
"type": "string"
},
"audit_requirement": {
"type": "string"
},
"status_effective": {
"type": "string",
"enum": [
"current",
"incoming",
"under_review",
"superseded"
]
}
}
}
},
"incoming_regulation": {
"type": "array",
"description": "Rules not yet in force but expected to apply within the planning horizon.",
"items": {
"type": "object",
"required": [
"id",
"regulation"
],
"additionalProperties": false,
"properties": {
"id": {
"type": "string",
"minLength": 1
},
"regulation": {
"type": "string",
"minLength": 1
},
"jurisdiction": {
"type": "string"
},
"earliest_effective_date": {
"type": "string"
},
"capability_impact": {
"type": "string"
},
"readiness_assessment": {
"type": "string"
}
}
}
}
}
}{
"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"
}
]
}{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "journey-inventory.schema.json",
"title": "Journey Inventory",
"description": "The registry of all business journeys in the organisation. A journey is a discrete end-to-end scenario in which a persona achieves a goal by exercising one or more capabilities. Journeys are the primary unit of behavioural modelling and the thing against which an organisation delivers. The inventory is a flat list: each entry summarises a journey and references the capabilities and sub-capabilities it exercises.",
"type": "object",
"required": [
"document_version",
"status",
"journeys"
],
"additionalProperties": false,
"properties": {
"document_version": {
"type": "string",
"pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$",
"description": "Semantic version of this inventory document."
},
"status": {
"type": "string",
"enum": [
"Draft",
"Review",
"Approved",
"Superseded"
],
"description": "Lifecycle status of the inventory."
},
"recommended_first_journey": {
"type": "object",
"description": "Optional. The journey an event-storming programme should model first. Usually chosen because it establishes the foundational domain entities the greatest number of other journeys depend on.",
"required": [
"id",
"rationale"
],
"additionalProperties": false,
"properties": {
"id": {
"type": "string",
"pattern": "^JRN-[0-9]{3}$",
"description": "JRN-XXX reference to a journey in the journeys array."
},
"rationale": {
"type": "string",
"minLength": 1,
"description": "Why this journey should be modelled first."
}
}
},
"journeys": {
"type": "array",
"minItems": 1,
"description": "All identified business journeys. Ordering is informational; use priority and depends_on_journeys for sequencing decisions.",
"items": {
"$ref": "#/$defs/Journey"
}
}
},
"$defs": {
"Journey": {
"type": "object",
"required": [
"id",
"name",
"description",
"triggering_persona",
"capabilities_touched",
"sub_capabilities_involved",
"cross_capability",
"priority",
"priority_rationale",
"estimated_complexity",
"happy_path_summary",
"depends_on_journeys"
],
"additionalProperties": false,
"properties": {
"id": {
"type": "string",
"pattern": "^JRN-[0-9]{3}$",
"description": "Stable unique identifier. Format: JRN-XXX."
},
"name": {
"type": "string",
"minLength": 5,
"maxLength": 100,
"description": "Short human-readable name."
},
"description": {
"type": "string",
"minLength": 20,
"description": "One to three sentence explanation of the journey scope: who, what, and why. Includes the regulatory or commercial driver where material."
},
"triggering_persona": {
"type": "string",
"pattern": "^PER-[0-9]{3}$",
"description": "The primary persona who initiates the journey. References a persona ID."
},
"capabilities_touched": {
"type": "array",
"minItems": 1,
"uniqueItems": true,
"description": "Top-level capabilities exercised by this journey. At least one required.",
"items": {
"type": "string",
"pattern": "^CAP-[0-9]{3}$"
}
},
"sub_capabilities_involved": {
"type": "array",
"minItems": 1,
"uniqueItems": true,
"description": "Sub-capabilities exercised by this journey. Each must belong to one of the capabilities in capabilities_touched.",
"items": {
"type": "string",
"pattern": "^SUB-[0-9]{3}$"
}
},
"cross_capability": {
"type": "boolean",
"description": "True if the journey exercises sub-capabilities from two or more top-level capabilities. Validators should enforce consistency with capabilities_touched."
},
"priority": {
"type": "string",
"enum": [
"critical",
"high",
"medium",
"low"
],
"description": "Delivery priority tier. critical = the organisation cannot legally or operationally function without it; high = significant commercial or regulatory weight; medium = material but not blocking; low = deferrable without consequence."
},
"priority_rationale": {
"type": "string",
"minLength": 20,
"description": "Explanation of the priority assignment, citing the specific driver."
},
"estimated_complexity": {
"type": "string",
"enum": [
"simple",
"moderate",
"complex"
],
"description": "Indicative complexity for modelling-workshop planning. simple = single capability, linear happy path; moderate = 1-2 capabilities, branching; complex = multi-capability, significant branching, real-time or regulatory constraints."
},
"happy_path_summary": {
"type": "string",
"minLength": 30,
"description": "A terse numbered-step or prose description of the successful end-to-end flow, sufficient to orient a modelling facilitator."
},
"depends_on_journeys": {
"type": "array",
"uniqueItems": true,
"description": "Other journeys that must be modelled first because they establish domain entities or aggregate roots this journey references. Empty array means no prerequisites. This is a modelling dependency, not a technical runtime dependency.",
"items": {
"type": "string",
"pattern": "^JRN-[0-9]{3}$"
}
}
}
}
}
}{
"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"
]
}
}
}{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "journey-detail.schema.json",
"title": "Journey detail",
"description": "The detailed specification of a single journey. Owned by the journey, not by any capability. Phases decompose the journey into ordered steps; paths describe the happy, alternative, and exception flows through those phases. Entities, services, and events are referenced by ID — they are defined canonically in capability-scoped data-model, service-boundaries, and event-catalogue artifacts, not here.",
"type": "object",
"required": [
"journey_id",
"name",
"status",
"triggering_persona",
"capabilities_touched",
"phases",
"paths"
],
"additionalProperties": false,
"properties": {
"journey_id": {
"type": "string",
"pattern": "^JRN-[0-9]{3}$",
"description": "Reference to the journey this artefact details. Must match the journey folder it lives in."
},
"name": {
"type": "string",
"minLength": 1,
"description": "Human-readable journey name. Should match the name in the journey inventory."
},
"description": {
"type": "string",
"description": "Expanded description of the journey. Optional here; the authoritative short description is in the journey inventory."
},
"status": {
"type": "string",
"enum": [
"Draft",
"In review",
"Stable",
"Revised"
],
"description": "Lifecycle status of this detailed specification."
},
"document_version": {
"type": "string",
"pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$",
"description": "Semantic version of this document."
},
"triggering_persona": {
"type": "string",
"pattern": "^PER-[0-9]{3}$",
"description": "The primary persona who initiates the journey."
},
"capabilities_touched": {
"type": "array",
"minItems": 1,
"uniqueItems": true,
"description": "Capabilities exercised by this journey. Must match the inventory entry.",
"items": {
"type": "string",
"pattern": "^CAP-[0-9]{3}$"
}
},
"sub_capabilities_involved": {
"type": "array",
"uniqueItems": true,
"description": "Sub-capabilities exercised by this journey.",
"items": {
"type": "string",
"pattern": "^SUB-[0-9]{3}$"
}
},
"phases": {
"type": "array",
"minItems": 1,
"description": "Ordered list of phases decomposing the journey. Each phase represents a distinct step with its own entry/exit conditions.",
"items": {
"type": "object",
"required": [
"id",
"name",
"description"
],
"additionalProperties": false,
"properties": {
"id": {
"type": "string",
"pattern": "^PH-[0-9]{3}$",
"description": "Stable unique phase identifier within this journey."
},
"name": {
"type": "string",
"minLength": 1,
"description": "Human-readable phase name."
},
"description": {
"type": "string",
"minLength": 1,
"description": "What happens in this phase."
},
"actors": {
"type": "array",
"items": {
"type": "string"
},
"description": "Personas or roles that participate in this phase."
},
"channels": {
"type": "array",
"items": {
"type": "string",
"pattern": "^CHN-[0-9]{3}$"
},
"description": "Channels through which actors interact with the capability in this phase."
},
"services": {
"type": "array",
"items": {
"type": "string",
"pattern": "^SVC-[0-9]{3}$"
},
"description": "Services involved in executing this phase. Defined canonically in technical-service files."
},
"governance_rules": {
"type": "array",
"items": {
"type": "string"
},
"description": "Governance rule IDs (e.g. GOV-XXX) applicable to this phase. Resolution to rule definitions is pack-specific."
},
"entry_conditions": {
"type": "array",
"items": {
"type": "string"
},
"description": "Preconditions that must hold before the phase may begin."
},
"exit_conditions": {
"type": "array",
"items": {
"type": "string"
},
"description": "Postconditions produced by successful completion of the phase."
},
"exit_conditions_failure": {
"type": "array",
"items": {
"type": "string"
},
"description": "Named failure conditions and their handling."
}
}
}
},
"paths": {
"type": "object",
"description": "The flows through the phases. Every journey has a happy path with at least one phase. Alternative paths describe valid variants; exception paths describe failure-handling flows.",
"required": [
"happy_path",
"alternative_paths",
"exception_paths"
],
"additionalProperties": false,
"properties": {
"happy_path": {
"type": "object",
"required": [
"description",
"phases"
],
"additionalProperties": false,
"properties": {
"description": {
"type": "string",
"minLength": 1,
"description": "Prose description of the happy path."
},
"phases": {
"type": "array",
"minItems": 1,
"description": "Ordered list of phase IDs making up the happy path.",
"items": {
"type": "string",
"pattern": "^PH-[0-9]{3}$"
}
}
}
},
"alternative_paths": {
"type": "array",
"description": "Valid variant flows. Empty array permitted.",
"items": {
"type": "object",
"required": [
"id",
"name",
"description",
"phases"
],
"additionalProperties": false,
"properties": {
"id": {
"type": "string",
"minLength": 1
},
"name": {
"type": "string",
"minLength": 1
},
"description": {
"type": "string",
"minLength": 1
},
"phases": {
"type": "array",
"items": {
"type": "string",
"pattern": "^PH-[0-9]{3}$"
}
}
}
}
},
"exception_paths": {
"type": "array",
"description": "Failure-handling flows.",
"items": {
"type": "object",
"required": [
"id",
"name",
"description"
],
"additionalProperties": false,
"properties": {
"id": {
"type": "string",
"minLength": 1
},
"name": {
"type": "string",
"minLength": 1
},
"description": {
"type": "string",
"minLength": 1
},
"phases": {
"type": "array",
"items": {
"type": "string",
"pattern": "^PH-[0-9]{3}$"
}
}
}
}
}
}
},
"design_decisions": {
"type": "array",
"description": "Journey-level design decisions.",
"items": {
"type": "object",
"required": [
"id",
"decision",
"rationale"
],
"additionalProperties": false,
"properties": {
"id": {
"type": "string",
"pattern": "^DD-[0-9]{3}$"
},
"decision": {
"type": "string",
"minLength": 1
},
"rationale": {
"type": "string",
"minLength": 1
},
"alternatives_considered": {
"type": "array",
"items": {
"type": "string"
}
},
"rejected_because": {
"type": "string"
}
}
}
}
}
}{
"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."
}
]
}{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "nfr.schema.json",
"title": "Non-Functional Requirements (journey-scoped)",
"description": "End-to-end non-functional requirements for a single journey. Journey-scoped: describes the behaviour of the journey as experienced by its triggering persona, not the properties of individual services. Per-service SLAs are declared on technical-service.schema.json and compose into these end-to-end journey NFRs.",
"type": "object",
"required": [
"journey_id",
"status",
"per_phase_nfrs",
"cross_cutting_nfrs"
],
"additionalProperties": false,
"properties": {
"journey_id": {
"type": "string",
"pattern": "^JRN-[0-9]{3}$"
},
"document_version": {
"type": "string",
"pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
},
"status": {
"type": "string",
"enum": [
"Draft",
"In review",
"Stable",
"Revised"
]
},
"per_phase_nfrs": {
"type": "array",
"description": "NFRs attached to individual phases of the journey.",
"items": {
"type": "object",
"required": [
"phase_id"
],
"additionalProperties": false,
"properties": {
"phase_id": {
"type": "string",
"pattern": "^PH-[0-9]{3}$"
},
"latency_target": {
"type": "object",
"additionalProperties": false,
"properties": {
"p50_ms": {
"type": [
"number",
"null"
]
},
"p95_ms": {
"type": [
"number",
"null"
]
},
"p99_ms": {
"type": [
"number",
"null"
]
}
}
},
"throughput_target": {
"type": "object",
"additionalProperties": false,
"properties": {
"peak_rps": {
"type": [
"number",
"null"
]
},
"sustained_rps": {
"type": [
"number",
"null"
]
}
}
},
"availability_target": {
"type": "string"
},
"notes": {
"type": "string"
}
}
}
},
"cross_cutting_nfrs": {
"type": "array",
"description": "Journey-wide NFRs (security, privacy, observability, auditability) that span all phases.",
"items": {
"type": "object",
"required": [
"id",
"category",
"requirement"
],
"additionalProperties": false,
"properties": {
"id": {
"type": "string",
"minLength": 1
},
"category": {
"type": "string",
"enum": [
"security",
"privacy",
"observability",
"auditability",
"accessibility",
"localisation",
"resilience",
"other"
]
},
"requirement": {
"type": "string",
"minLength": 1
},
"measured_by": {
"type": "string"
}
}
}
},
"regulatory_slas": {
"type": "array",
"description": "SLAs imposed by regulation or mandate on the end-to-end journey (e.g. 'APP fraud reimbursement within 5 business days'). Pack-specific content; structure is generic.",
"items": {
"type": "object",
"required": [
"id",
"requirement"
],
"additionalProperties": false,
"properties": {
"id": {
"type": "string",
"minLength": 1
},
"source": {
"type": "string",
"description": "The regulation, rule, or mandate imposing the SLA."
},
"requirement": {
"type": "string",
"minLength": 1
},
"measured_by": {
"type": "string"
}
}
}
}
}
}{
"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"
]
}
]
}{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "service-dependencies.schema.json",
"title": "Service Dependencies",
"description": "System-wide map of all services across capabilities, their deployment tier, and the dependencies between them. Used for build-order planning, impact analysis, and critical-path identification. This is a system-level artefact, not a capability-scoped one — it spans every capability.",
"type": "object",
"required": [
"document_version",
"status",
"tier_definitions",
"services",
"build_order"
],
"additionalProperties": false,
"properties": {
"document_version": {
"type": "string",
"pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
},
"status": {
"type": "string",
"enum": [
"Draft",
"Review",
"Approved",
"Superseded"
]
},
"description": {
"type": "string"
},
"tier_definitions": {
"type": "object",
"description": "Canonical definitions for each deployment tier. Tiers are T0 through T4; lower tiers must deploy before higher tiers.",
"additionalProperties": false,
"patternProperties": {
"^T[0-4]$": {
"type": "object",
"required": [
"label",
"description",
"deployment_order",
"availability_floor"
],
"additionalProperties": false,
"properties": {
"label": {
"type": "string",
"minLength": 1
},
"description": {
"type": "string",
"minLength": 1
},
"deployment_order": {
"type": "integer",
"minimum": 1,
"maximum": 5
},
"availability_floor": {
"type": "string",
"description": "Minimum availability SLA for services in this tier."
},
"rationale": {
"type": "string",
"description": "Why this tier must exist before downstream tiers."
}
}
}
}
},
"services": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"required": [
"id",
"name",
"classification",
"tier",
"dependencies"
],
"additionalProperties": false,
"properties": {
"id": {
"type": "string",
"pattern": "^SVC-[0-9]{3}$"
},
"name": {
"type": "string",
"minLength": 1
},
"classification": {
"type": "string",
"enum": [
"foundation",
"domain",
"cross_cutting",
"observability",
"security",
"channel"
]
},
"tier": {
"type": "string",
"enum": [
"T0",
"T1",
"T2",
"T3",
"T4"
]
},
"capability_id": {
"type": "string",
"pattern": "^CAP-[0-9]{3}$",
"description": "For domain services, the capability they belong to. Omitted for cross-cutting and foundation services."
},
"dependencies": {
"type": "array",
"items": {
"type": "object",
"required": [
"service_id",
"criticality"
],
"additionalProperties": false,
"properties": {
"service_id": {
"type": "string",
"pattern": "^SVC-[0-9]{3}$"
},
"criticality": {
"type": "string",
"enum": [
"hard",
"soft"
]
},
"rationale": {
"type": "string"
}
}
}
},
"notes": {
"type": "string"
}
}
}
},
"dependency_criticality_matrix": {
"type": "object",
"additionalProperties": false,
"properties": {
"hard_dependency_pairs": {
"type": "array",
"items": {
"type": "object",
"required": [
"from_service",
"to_service",
"criticality"
],
"additionalProperties": false,
"properties": {
"from_service": {
"type": "string",
"pattern": "^SVC-[0-9]{3}$"
},
"to_service": {
"type": "string",
"pattern": "^SVC-[0-9]{3}$"
},
"criticality": {
"type": "string",
"enum": [
"hard",
"soft"
]
}
}
}
},
"summary": {
"type": "object",
"additionalProperties": false,
"properties": {
"total_hard_dependencies": {
"type": "integer",
"minimum": 0
},
"total_soft_dependencies": {
"type": "integer",
"minimum": 0
},
"highest_fan_in_service": {
"type": "string"
},
"highest_fan_out_service": {
"type": "string"
}
}
}
}
},
"build_order": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"required": [
"phase",
"name",
"tiers",
"services_in_phase",
"gate_criteria"
],
"additionalProperties": false,
"properties": {
"phase": {
"type": "integer",
"minimum": 1
},
"name": {
"type": "string",
"minLength": 1
},
"tiers": {
"type": "array",
"items": {
"type": "string",
"enum": [
"T0",
"T1",
"T2",
"T3",
"T4"
]
}
},
"services_in_phase": {
"type": "array",
"items": {
"type": "string",
"pattern": "^SVC-[0-9]{3}$"
}
},
"rationale": {
"type": "string",
"description": "Why this phase's services must be delivered in this order."
},
"gate_criteria": {
"type": "array",
"items": {
"type": "string"
}
},
"estimated_duration_weeks": {
"type": "integer",
"minimum": 0
}
}
}
}
}
}{
"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"
}{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "persona.schema.json",
"title": "Persona",
"description": "A named type of actor that interacts with the organisation's capabilities. Personas are either internal (employees, role holders) or external (customers, counterparties, regulators, partners, public). Each persona has a description, the capabilities it accesses, and the channels through which it interacts.",
"type": "object",
"required": [
"persona_id",
"name",
"type",
"subtype",
"description"
],
"additionalProperties": false,
"properties": {
"persona_id": {
"type": "string",
"pattern": "^PER-[0-9]{3}$"
},
"name": {
"type": "string",
"minLength": 1
},
"type": {
"type": "string",
"enum": [
"internal",
"external"
]
},
"subtype": {
"type": "string",
"enum": [
"employee",
"customer",
"counterparty",
"regulator",
"partner",
"public",
"other"
]
},
"description": {
"type": "string",
"minLength": 1
},
"capabilities_accessed": {
"type": "array",
"items": {
"type": "object",
"required": [
"capability_id",
"purpose"
],
"additionalProperties": false,
"properties": {
"capability_id": {
"type": "string",
"pattern": "^CAP-[0-9]{3}$"
},
"purpose": {
"type": "string",
"minLength": 1
}
}
}
},
"channels": {
"type": "array",
"items": {
"type": "object",
"required": [
"channel_id"
],
"additionalProperties": false,
"properties": {
"channel_id": {
"type": "string",
"pattern": "^CHN-[0-9]{3}$"
},
"access_purpose": {
"type": "string"
},
"auth_model": {
"type": "string"
},
"rate_limit_class": {
"type": "string"
},
"data_projection": {
"type": "string"
}
}
}
},
"legal_basis": {
"type": "string",
"description": "Legal basis for the persona's interaction with the organisation (e.g. contract, consent, legitimate interest, statutory obligation). Relevant where data protection or access-rights law applies."
},
"data_classification_granted": {
"type": "string",
"enum": [
"public",
"internal",
"confidential",
"regulated"
]
}
}
}{
"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"
}
]
}{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "observability-model.schema.json",
"title": "Observability Model",
"description": "The organisation-wide observability posture: log routing, PII scrubbing, fan-out stores, per-service instrumentation obligations, logging schema taxonomy by category, and data freshness contracts. System-level artefact, not capability-scoped — all capabilities inherit from it.",
"type": "object",
"required": [
"document_version",
"status",
"log_routing_architecture",
"per_service_instrumentation_checklist",
"logging_schema_by_category",
"data_freshness"
],
"additionalProperties": false,
"properties": {
"document_version": {
"type": "string",
"pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
},
"status": {
"type": "string",
"enum": [
"Draft",
"Review",
"Approved",
"Superseded"
]
},
"log_routing_architecture": {
"type": "object",
"required": [
"ingestion_layer",
"pii_scrubbing",
"fan_out_stores"
],
"additionalProperties": false,
"properties": {
"ingestion_layer": {
"type": "object",
"required": [
"component",
"protocol",
"rationale"
],
"additionalProperties": false,
"properties": {
"component": {
"type": "string",
"minLength": 1
},
"protocol": {
"type": "string",
"minLength": 1
},
"rationale": {
"type": "string",
"minLength": 1
}
}
},
"pii_scrubbing": {
"type": "object",
"required": [
"stage",
"mechanism",
"fields_scrubbed",
"enforcement"
],
"additionalProperties": false,
"properties": {
"stage": {
"type": "string",
"minLength": 1
},
"mechanism": {
"type": "string",
"minLength": 1
},
"fields_scrubbed": {
"type": "array",
"items": {
"type": "string"
}
},
"enforcement": {
"type": "string",
"minLength": 1
}
}
},
"fan_out_stores": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"required": [
"name",
"purpose",
"retention",
"access_control"
],
"additionalProperties": false,
"properties": {
"name": {
"type": "string",
"minLength": 1
},
"purpose": {
"type": "string",
"minLength": 1
},
"retention": {
"type": "string",
"minLength": 1
},
"access_control": {
"type": "string",
"minLength": 1
},
"worm": {
"type": "boolean"
},
"technology_options": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
}
}
},
"per_service_instrumentation_checklist": {
"type": "array",
"minItems": 1,
"description": "Instrumentation obligations every service must meet. Validators for services should check against this list.",
"items": {
"type": "object",
"required": [
"id",
"name",
"description",
"mandatory"
],
"additionalProperties": false,
"properties": {
"id": {
"type": "string",
"minLength": 1
},
"name": {
"type": "string",
"minLength": 1
},
"description": {
"type": "string",
"minLength": 1
},
"mandatory": {
"type": "boolean"
},
"standards_reference": {
"type": "string"
}
}
}
},
"logging_schema_by_category": {
"type": "array",
"minItems": 1,
"description": "Structured logging field contracts by service category.",
"items": {
"type": "object",
"required": [
"category_id",
"category_name",
"applies_to_services",
"required_fields"
],
"additionalProperties": false,
"properties": {
"category_id": {
"type": "string",
"minLength": 1
},
"category_name": {
"type": "string",
"minLength": 1
},
"applies_to_services": {
"type": "array",
"items": {
"type": "string"
}
},
"required_fields": {
"type": "array",
"minItems": 1,
"items": {
"$ref": "#/$defs/LogField"
}
},
"extension_fields": {
"type": "array",
"items": {
"$ref": "#/$defs/LogField"
}
},
"critical_rules": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
},
"data_freshness": {
"type": "array",
"minItems": 1,
"description": "Freshness contracts for signals feeding dashboards, alerts, or regulatory reports.",
"items": {
"type": "object",
"required": [
"contract_id",
"signal_name",
"source",
"max_staleness",
"alert_threshold",
"rationale"
],
"additionalProperties": false,
"properties": {
"contract_id": {
"type": "string",
"minLength": 1
},
"signal_name": {
"type": "string",
"minLength": 1
},
"source": {
"type": "string",
"minLength": 1
},
"max_staleness": {
"type": "string",
"minLength": 1
},
"alert_threshold": {
"type": "string",
"minLength": 1
},
"rationale": {
"type": "string",
"minLength": 1
}
}
}
},
"design_decisions": {
"type": "array",
"items": {
"type": "object",
"required": [
"id",
"decision",
"rationale"
],
"additionalProperties": false,
"properties": {
"id": {
"type": "string",
"pattern": "^DD-[0-9]{3}$"
},
"decision": {
"type": "string",
"minLength": 1
},
"rationale": {
"type": "string",
"minLength": 1
},
"alternatives_considered": {
"type": "array",
"items": {
"type": "string"
}
},
"rejected_because": {
"type": "string"
}
}
}
}
},
"$defs": {
"LogField": {
"type": "object",
"required": [
"field",
"type",
"description"
],
"additionalProperties": false,
"properties": {
"field": {
"type": "string",
"minLength": 1
},
"type": {
"type": "string",
"minLength": 1
},
"description": {
"type": "string",
"minLength": 1
},
"example": {}
}
}
}
}{
"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."
}
]
}{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "security-model.schema.json",
"title": "Security Model",
"description": "The organisation-wide security posture: zero-trust controls, service-to-service authentication, data classification policy, and network segmentation. System-level artefact, not capability-scoped — all capabilities inherit from it and their services are classified against it.",
"type": "object",
"required": [
"document_version",
"status",
"security_posture_controls",
"service_to_service_auth",
"data_classification",
"network_segmentation"
],
"additionalProperties": false,
"properties": {
"document_version": {
"type": "string",
"pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
},
"status": {
"type": "string",
"enum": [
"Draft",
"Review",
"Approved",
"Superseded"
]
},
"security_posture_controls": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"required": [
"control_id",
"name",
"description",
"implementation"
],
"additionalProperties": false,
"properties": {
"control_id": {
"type": "string",
"minLength": 1
},
"name": {
"type": "string",
"minLength": 1
},
"description": {
"type": "string",
"minLength": 1
},
"implementation": {
"type": "string",
"minLength": 1
},
"dashboard_signal": {
"type": "string"
},
"regulatory_references": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
},
"service_to_service_auth": {
"type": "object",
"required": [
"primary_mechanism",
"workload_identity",
"jwt_propagation",
"policy_enforcement"
],
"additionalProperties": false,
"properties": {
"primary_mechanism": {
"type": "string",
"minLength": 1,
"description": "Primary service-to-service auth mechanism (e.g. mTLS, SPIFFE, mesh sidecar)."
},
"workload_identity": {
"type": "object",
"required": [
"standard",
"issuer",
"certificate_ttl"
],
"additionalProperties": false,
"properties": {
"standard": {
"type": "string",
"minLength": 1
},
"issuer": {
"type": "string",
"minLength": 1
},
"certificate_ttl": {
"type": "string",
"minLength": 1
}
}
},
"jwt_propagation": {
"type": "object",
"required": [
"header",
"claims_required",
"audience_enforcement"
],
"additionalProperties": false,
"properties": {
"header": {
"type": "string",
"minLength": 1
},
"claims_required": {
"type": "array",
"items": {
"type": "string"
}
},
"audience_enforcement": {
"type": "boolean"
}
}
},
"policy_enforcement": {
"type": "object",
"required": [
"engine",
"default_policy",
"exceptions_require"
],
"additionalProperties": false,
"properties": {
"engine": {
"type": "string",
"minLength": 1
},
"default_policy": {
"type": "string",
"minLength": 1
},
"exceptions_require": {
"type": "string",
"minLength": 1
}
}
}
}
},
"data_classification": {
"type": "object",
"required": [
"levels",
"service_classifications"
],
"additionalProperties": false,
"properties": {
"levels": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"required": [
"level_id",
"name",
"description",
"handling_requirements"
],
"additionalProperties": false,
"properties": {
"level_id": {
"type": "string",
"minLength": 1
},
"name": {
"type": "string",
"minLength": 1
},
"description": {
"type": "string",
"minLength": 1
},
"handling_requirements": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
},
"service_classifications": {
"type": "array",
"items": {
"type": "object",
"required": [
"service_id",
"data_level",
"rationale"
],
"additionalProperties": false,
"properties": {
"service_id": {
"type": "string",
"pattern": "^SVC-[0-9]{3}$"
},
"service_name": {
"type": "string"
},
"data_level": {
"type": "string",
"minLength": 1
},
"rationale": {
"type": "string",
"minLength": 1
},
"regulatory_scope_flags": {
"type": "array",
"items": {
"type": "string"
},
"description": "Pack-specific flags indicating which regulatory scopes a service falls within (e.g. PCI-DSS, HIPAA, GDPR-sensitive)."
}
}
}
}
}
},
"network_segmentation": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"required": [
"zone_id",
"name",
"description",
"services_in_zone",
"ingress_policy",
"egress_policy"
],
"additionalProperties": false,
"properties": {
"zone_id": {
"type": "string",
"minLength": 1
},
"name": {
"type": "string",
"minLength": 1
},
"description": {
"type": "string",
"minLength": 1
},
"services_in_zone": {
"type": "array",
"items": {
"type": "string",
"pattern": "^SVC-[0-9]{3}$"
}
},
"ingress_policy": {
"type": "string",
"minLength": 1
},
"egress_policy": {
"type": "string",
"minLength": 1
},
"regulated_zone_flags": {
"type": "array",
"items": {
"type": "string"
},
"description": "Pack-specific flags indicating which regulated zone designations this zone holds (e.g. PCI-DSS-CDE, healthcare-PHI)."
}
}
}
},
"design_decisions": {
"type": "array",
"items": {
"type": "object",
"required": [
"id",
"decision",
"rationale"
],
"additionalProperties": false,
"properties": {
"id": {
"type": "string",
"pattern": "^DD-[0-9]{3}$"
},
"decision": {
"type": "string",
"minLength": 1
},
"rationale": {
"type": "string",
"minLength": 1
},
"alternatives_considered": {
"type": "array",
"items": {
"type": "string"
}
},
"rejected_because": {
"type": "string"
}
}
}
}
}
}{
"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"
}
]
}{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "technical-service.schema.json",
"title": "Technical service",
"description": "Canonical definition of a single service. A service belongs to exactly one capability (or is classified as cross-cutting/foundation/observability/security if system-wide). Services own entities, publish and consume events, consume APIs from other services within the same capability, and have their own SLA. This is the authoritative per-service definition; service-boundaries reference it.",
"type": "object",
"required": [
"service_id",
"name",
"classification",
"description",
"tier"
],
"additionalProperties": false,
"properties": {
"service_id": {
"type": "string",
"pattern": "^SVC-[0-9]{3}$"
},
"name": {
"type": "string",
"minLength": 1
},
"classification": {
"type": "string",
"enum": [
"domain",
"cross-cutting",
"foundation",
"channel",
"observability",
"security"
],
"description": "domain = belongs to one capability; cross-cutting = used across capabilities via contracts; foundation = platform-level prerequisite; channel = customer-facing entry point; observability/security = system-level infrastructure."
},
"capability_id": {
"oneOf": [
{
"type": "string",
"pattern": "^CAP-[0-9]{3}$"
},
{
"type": "null"
}
],
"description": "For domain services, the capability they belong to. Null for cross-cutting, foundation, observability, and security services that do not sit within a single capability."
},
"description": {
"type": "string",
"minLength": 1
},
"tier": {
"type": "string",
"enum": [
"T0",
"T1",
"T2",
"T3",
"T4"
],
"description": "Deployment tier. T0 is the platform foundation; higher tiers depend on lower tiers."
},
"deployment_unit": {
"type": "string",
"enum": [
"own-repo",
"shared-repo"
]
},
"data_stores": {
"type": "array",
"uniqueItems": true,
"description": "The data stores this service reads from or writes to, referenced by DS-XXX ID. Canonical detail (technology, classification, stored entities, sharing scope) lives in the data-store.schema.json definition for each store. Every referenced store must belong to the same capability as this service, and this service's ID must appear in that store's owning_services.",
"items": {
"type": "string",
"pattern": "^DS-[0-9]{3}$"
}
},
"exposes": {
"type": "object",
"additionalProperties": false,
"properties": {
"capability_api_endpoints": {
"type": "array",
"description": "Endpoints that form part of the capability's external API. Only services at the capability boundary expose these."
},
"internal_apis": {
"type": "array",
"description": "Endpoints consumed by other services within the same capability."
}
}
},
"produces_events": {
"type": "array",
"items": {
"type": "string",
"pattern": "^EVT-[0-9]{3}$"
}
},
"consumes_events": {
"type": "array",
"items": {
"type": "string",
"pattern": "^EVT-[0-9]{3}$"
}
},
"depends_on": {
"type": "array",
"items": {
"type": "object",
"required": [
"service_id",
"protocol",
"criticality"
],
"additionalProperties": false,
"properties": {
"service_id": {
"type": "string",
"pattern": "^SVC-[0-9]{3}$"
},
"protocol": {
"type": "string",
"enum": [
"rest",
"grpc",
"event",
"direct"
]
},
"criticality": {
"type": "string",
"enum": [
"hard",
"soft"
]
}
}
}
},
"sla": {
"type": "object",
"description": "The service's own non-functional targets. Journey-level NFRs describe end-to-end behaviour and live in journey-level nfr files; these are the per-service targets that compose into those end-to-end numbers.",
"additionalProperties": false,
"properties": {
"availability": {
"type": "string",
"description": "E.g. '99.95%' or 'tier-1'."
},
"latency_p99_ms": {
"type": [
"number",
"null"
]
},
"latency_p50_ms": {
"type": [
"number",
"null"
]
},
"throughput_rps": {
"type": [
"number",
"null"
]
},
"rto_minutes": {
"type": [
"number",
"null"
],
"description": "Recovery time objective in minutes."
},
"rpo_minutes": {
"type": [
"number",
"null"
],
"description": "Recovery point objective in minutes."
}
}
},
"owner_role": {
"type": "string",
"description": "The role or team accountable for the service."
}
}
}{
"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"
}
]
}{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "api-manifest.schema.json",
"title": "API Manifest",
"description": "Indexes the OpenAPI and AsyncAPI specifications for a capability or a service. Each capability has a capability-scoped manifest listing its channel-facing OpenAPI spec and its bus-facing AsyncAPI spec. Each service has a service-scoped manifest listing its intra-capability OpenAPI spec and its bus-facing AsyncAPI spec. The manifest does not contain the API definitions themselves — those are standard OpenAPI 3.x and AsyncAPI 2.x files referenced by path. This schema enforces that every capability publishes both a channel API (for external consumers) and an event API (for other capabilities), and that every service publishes equivalent contracts.",
"type": "object",
"required": [
"scope",
"owner_id",
"document_version",
"specs"
],
"additionalProperties": false,
"properties": {
"scope": {
"type": "string",
"enum": [
"capability",
"service"
],
"description": "Which kind of thing this manifest belongs to. capability = a capability-level manifest indexing the capability's external contract; service = a service-level manifest indexing one service's contracts."
},
"owner_id": {
"type": "string",
"description": "The ID of the capability or service that owns the manifest. Pattern depends on scope: CAP-XXX for capability, SVC-XXX for service.",
"oneOf": [
{
"pattern": "^CAP-[0-9]{3}$"
},
{
"pattern": "^SVC-[0-9]{3}$"
}
]
},
"document_version": {
"type": "string",
"pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
},
"status": {
"type": "string",
"enum": [
"Draft",
"In review",
"Stable",
"Revised"
]
},
"specs": {
"type": "array",
"minItems": 2,
"description": "The API specs belonging to this owner. Every manifest must contain at least one OpenAPI spec and one AsyncAPI spec. A capability's OpenAPI spec describes the channel-facing external REST surface; its AsyncAPI spec describes the events it publishes on the bus. A service's OpenAPI spec describes the intra-capability REST calls it accepts; its AsyncAPI spec describes events it publishes and consumes.",
"items": {
"type": "object",
"required": [
"kind",
"title",
"version",
"path",
"role"
],
"additionalProperties": false,
"properties": {
"kind": {
"type": "string",
"enum": [
"openapi",
"asyncapi"
],
"description": "openapi = OpenAPI 3.x REST/HTTP spec; asyncapi = AsyncAPI 2.x event-driven spec."
},
"title": {
"type": "string",
"minLength": 1,
"description": "Human-readable title for the spec."
},
"version": {
"type": "string",
"minLength": 1,
"description": "Semantic version of the spec itself."
},
"path": {
"type": "string",
"minLength": 1,
"description": "Relative path to the spec file from the manifest location."
},
"format": {
"type": "string",
"enum": [
"yaml",
"json"
],
"description": "File format of the spec."
},
"role": {
"type": "string",
"enum": [
"channel-facing",
"bus-facing",
"intra-capability",
"consumes"
],
"description": "The role this spec plays. For a capability: channel-facing OpenAPI, bus-facing AsyncAPI. For a service: intra-capability OpenAPI, bus-facing AsyncAPI (what it publishes), consumes AsyncAPI (what it subscribes to)."
},
"consumers": {
"type": "array",
"items": {
"type": "string"
},
"description": "Informational list of known consumers of this spec."
},
"notes": {
"type": "string"
}
}
}
}
}
}{
"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"]
}
]
}{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "sequence-manifest.schema.json",
"title": "Sequence Manifest (journey-phase-scoped)",
"description": "Indexes the sequence diagrams owned by a single journey. Sequence diagrams are journey-phase-scoped: a journey may initiate many sequences, each attached to a phase. There are no capability-level or service-level sequence diagrams in this meta-model; if a service choreography needs illustrating, it is done in the context of the journey phase that exercises it. The diagrams themselves are Mermaid files referenced by path; this manifest provides the metadata and cross-references.",
"type": "object",
"required": [
"journey_id",
"document_version",
"sequences"
],
"additionalProperties": false,
"properties": {
"journey_id": {
"type": "string",
"pattern": "^JRN-[0-9]{3}$"
},
"document_version": {
"type": "string",
"pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
},
"status": {
"type": "string",
"enum": [
"Draft",
"In review",
"Stable",
"Revised"
]
},
"sequences": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"required": [
"id",
"phase_id",
"title",
"path",
"format",
"participants"
],
"additionalProperties": false,
"properties": {
"id": {
"type": "string",
"pattern": "^SEQ-[0-9]{3}$",
"description": "Stable identifier for the sequence within this journey."
},
"phase_id": {
"type": "string",
"pattern": "^PH-[0-9]{3}$",
"description": "The journey phase this sequence illustrates. Must resolve to a phase in the journey's journey-detail."
},
"title": {
"type": "string",
"minLength": 1,
"description": "Human-readable title for the sequence."
},
"description": {
"type": "string",
"description": "Optional. What the sequence shows."
},
"path": {
"type": "string",
"minLength": 1,
"description": "Relative path to the diagram file from the manifest location."
},
"format": {
"type": "string",
"enum": [
"mermaid"
],
"description": "Diagram format. Mermaid only in this meta-model."
},
"path_variant": {
"type": "string",
"enum": [
"happy",
"alternative",
"exception"
],
"description": "Which path variant the sequence depicts."
},
"participants": {
"type": "array",
"minItems": 1,
"description": "The actors, channels, and services participating in the sequence. Channel endpoints at the ends of the sequence carry the persona interactions.",
"items": {
"type": "object",
"required": [
"kind",
"ref"
],
"additionalProperties": false,
"properties": {
"kind": {
"type": "string",
"enum": [
"persona",
"channel",
"service",
"external_system"
]
},
"ref": {
"type": "string",
"minLength": 1,
"description": "ID of the participant (PER-XXX, CHN-XXX, SVC-XXX) or free-text name for external_system."
},
"role": {
"type": "string",
"description": "Informational role in this sequence (e.g. initiator, responder)."
}
}
}
},
"events_referenced": {
"type": "array",
"items": {
"type": "string",
"pattern": "^EVT-[0-9]{3}$"
}
},
"entities_referenced": {
"type": "array",
"items": {
"type": "string",
"pattern": "^ENT-[0-9]{3}$"
}
}
}
}
}
}
}| Prefix | Meaning | Format |
|---|---|---|
| CAP-XXX | Capability | 3 digits |
| SUB-XXX | Sub-capability | 3 digits |
| JRN-XXX | Journey | 3 digits |
| PH-XXX | Phase (within a journey) | 3 digits |
| PER-XXX | Persona | 3 digits |
| CHN-XXX | Channel | 3 digits |
| SVC-XXX | Service | 3 digits |
| ENT-XXX | Entity | 3 digits |
| DS-XXX | Data store | 3 digits |
| EVT-XXX | Event | 3 digits |
| GOV-XXX | Governance rule | 3 digits, optional sub-rule |
| DD-XXX | Design decision | 3 digits |
| SEQ-XXX | Sequence diagram | 3 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.