Commit 9b28b611 authored by Sergio Gimenez's avatar Sergio Gimenez
Browse files

docs(fm): align persistence model with develop §J/§K

parent b9e1dacc
Loading
Loading
Loading
Loading
+17 −12
Changes for fm/persistence-model.md: 17 added lines, 12 removed lines.
Original line number Diff line number Diff line
@@ -66,8 +66,11 @@ connection status. Exactly one current row per partner in `partner_ops`; updates

**FederationAgreement** — the rules governing what may be shared with one partner: permitted API
types, permitted zones, usage limits, validity window, and — crucially — the `service_spec_mappings`
that resolve a partner-facing `appId` / API family to a local `service_specification_id` (ADR-0018).
It is the resolution authority for SRM dispatch. Stored in `federation_agreements`.
that resolve a partner request to local catalog entries (ADR-0018): an InstallApp mapping keys on the
full `(appId, appVersion, flavourId)` tuple and yields the local `service_specification_id` plus the
deployable artifact/version and resource profile; a Service API mapping keys on the API family and
yields the local `service_specification_id`. It is the resolution authority for SRM dispatch. Stored
in `federation_agreements`.

**FederationContext** — one directed OPG.04 federation relationship. FM issues the opaque
`federationContextId` for inbound federation; the partner issues it for outbound federation. The
@@ -181,8 +184,8 @@ Constraint: `UNIQUE (partner_op_id, direction, federation_context_id)`.
| `id` | UUID | PK, DEFAULT gen_random_uuid() | |
| `partner_op_id` | UUID | NOT NULL, FK → partner_ops(id) | |
| `permitted_api_types` | JSONB | NOT NULL | API types allowed under this agreement |
| `permitted_zone_ids` | JSONB | DEFAULT '[]' | Edge zone UUIDs (`zone.id`, ADR-0017) the partner may access |
| `service_spec_mappings` | JSONB | NOT NULL, DEFAULT '{}' | Partner `appId` / API family → local `service_specification_id` (ADR-0018) |
| `permitted_zone_ids` | JSONB | DEFAULT '[]' | OPG.04 `ZoneIdentifier` strings permitted in this directed federation. Local zones map explicitly to SRM `zone.id` UUIDs; partner-issued values remain opaque strings |
| `service_spec_mappings` | JSONB | NOT NULL, DEFAULT '{}' | `(appId, appVersion, flavourId)` → local service specification + deployable artifact/resource profile; Service API family → local `service_specification_id` (ADR-0018) |
| `usage_limits` | JSONB | DEFAULT '{}' | Rate/volume limits per API type |
| `valid_from` | TIMESTAMPTZ | NOT NULL | |
| `valid_until` | TIMESTAMPTZ | | NULL = indefinite |
@@ -215,7 +218,7 @@ Indexes: `idx_routing_rules_type_value` on `(identifier_type, value_range)`, `id
| `partner_op_id` | UUID | NOT NULL, FK → partner_ops(id) | |
| `direction` | VARCHAR(10) | NOT NULL | `inbound` (partner→us) or `outbound` (us→partner) |
| `resource_type` | VARCHAR(50) | NOT NULL | `edge_zone`, `network_capability`, … |
| `resource_data` | JSONB | NOT NULL | Zone details, capability metadata, availability |
| `resource_data` | JSONB | NOT NULL | OPG.04 zone details/capability metadata, including the opaque external `zoneId` and the explicit local `zone.id` mapping where we own the zone |
| `synced_at` | TIMESTAMPTZ | NOT NULL, DEFAULT now() | |
| `created_at` | TIMESTAMPTZ | NOT NULL, DEFAULT now() | |
| `updated_at` | TIMESTAMPTZ | NOT NULL, DEFAULT now() | |
@@ -242,7 +245,7 @@ Indexes: `idx_shared_catalogue_partner_direction` on `(partner_op_id, direction)
| `status` | VARCHAR(20) | NOT NULL, DEFAULT 'pending' | Internal lowercase audit state: `pending`, `in_progress`, `completed`, `partially_completed`, `failed` |
| `request_summary` | JSONB | NOT NULL | Sanitized request metadata |
| `response_summary` | JSONB | | Sanitized response metadata |
| `error_detail` | JSONB | | RFC 7807 error if failed |
| `error_detail` | JSONB | | Sanitized OPG.04 `ProblemDetails` if failed |
| `callback_url` | TEXT | | Required operation callback URL, when applicable |
| `callback_status` | VARCHAR(20) | | `pending`, `delivered`, `failed`; NULL without callback |
| `callback_attempts` | INTEGER | NOT NULL, DEFAULT 0 | Durable callback delivery attempts |
@@ -261,7 +264,7 @@ status remains `federation_transactions` in PostgreSQL.

| Stream | Subjects | Role |
|---|---|---|
| `OOP_TASKS` | `command.srm.service.{deploy,scale,terminate}`, `command.srm.network.capability.{activate,update,deactivate}` | FM publishes; SRM consumes. Every command carries `CommandEnvelopeV1` with `source=federation`, `federation_partner_ref`, `app_provider_id=partner.id` (ADR-0001, ADR-0018) |
| `OOP_TASKS` | `command.srm.service.{deploy,terminate}`, `command.srm.network.capability.{activate,deactivate}` | FM publishes; SRM consumes. Every command carries `CommandEnvelopeV1` with `source=federation`, `federation_partner_ref`, `app_provider_id=partner.id` (ADR-0001, ADR-0018); network-capability payloads carry `source_spec` `family=gsma_opg` (RD §K.2). FM does not publish `service.scale` (no OPG.04 v1.4.0 operation maps to it) or `network.capability.update` (needs an explicit OPG.04 profile/extension first; REQ-FED-16) |
| `OOP_EVENTS` | `event.srm.operation.status`, `event.srm.operation.completed`, `event.srm.catalog.updated` | FM consumes via durable `fm-event-worker` (explicit ack, max-deliver 3) |

OEG-proxied federation establishment is a separate FM command input under
@@ -290,13 +293,15 @@ federation-manager/
│   ├── application/              # inbound / outbound / partner / agreement / catalogue services
│   ├── adapters/
│   │   ├── database/             # SQLAlchemy async: engine, tables, per-entity repos
│   │   ├── databus/              # command.srm.* publisher, event.srm.* consumer
│   │   └── http/                 # SRM internal client, outbound EWBI client
│   │   ├── databus/              # command.srm.* publisher, event.srm.* / command.fm.* consumers
│   │   ├── http/                 # SRM internal client, outbound EWBI client
│   │   └── security/             # Keycloak JWT/JWKS validation, outbound token provider
│   ├── api/
│   │   ├── ewbi/v1/              # partner-facing EWBI routes
│   │   ├── internal/             # operator-facing admin routes
│   │   ├── ewbi/v1/              # partner-facing OPG.04 routes
│   │   ├── internal/             # operator-facing admin routes, OEG/SRM hand-offs
│   │   ├── security.py           # OAuth2 scheme + Bearer extraction
│   │   └── platform/health.py
│   ├── middleware/               # mtls_auth, topology_hiding, federation_correlation
│   ├── middleware/               # topology_hiding, federation_correlation
│   ├── dependencies.py           # DI wiring (repo/adapter selection)
│   └── main.py                   # composition root + lifespan
└── tests/  unit | integration | e2e