Commit da7c5a45 authored by Dimitrios Gogos's avatar Dimitrios Gogos
Browse files

docs: update OEG-proxied federation establishment and SRM's zone locality determination

parent 3db701ef
Loading
Loading
Loading
Loading
+94 −0
Changes for decisions/0043-oeg-proxied-federation-establishment.md: 94 added lines, 0 removed lines.
Original line number Diff line number Diff line
---
type: Decision Record
title: "ADR-0043: Operator-triggered federation establishment is proxied through OEG over the DataBus; FM also supports config-driven bootstrap federation"
description: "Operator-triggered federation establishment is proxied through OEG over the DataBus; FM also supports config-driven bootstrap federation"
tags: [adr]
timestamp: 2026-09-04T00:00:00Z
status: "accepted"
---

# ADR-0043: Operator-triggered federation establishment is proxied through OEG over the DataBus; FM also supports config-driven bootstrap federation

**Status:** accepted
**Date:** 2026-09-04
**Affects:** [oeg/architecture.md](/oeg/architecture.md), [oeg/interface-contract.md](/oeg/interface-contract.md), [fm/overview-and-architecture.md](/fm/overview-and-architecture.md), [fm/requirements-and-design.md](/fm/requirements-and-design.md), [platform/architecture.md](/platform/architecture.md)

## Context

[fm/requirements-and-design.md](/fm/requirements-and-design.md) §L.2 documents FM's own internal
admin API (`http://fm:8082/internal/partners`, `/internal/agreements`, `/internal/routing-rules`)
as the sole path for an operator to create a partner OP profile, a federation agreement, and
routing rules — reached "via Portal or internal tools" directly against FM (REQ-FED-19,
UC-FM-06), bypassing OEG entirely. Every other operator- or developer-triggered action on the
platform goes through OEG for auth, policy, and audit (platform/architecture.md's Component
Boundary Matrix: "Public CAMARA/TMF API termination — OEG; not SRM, FM"). Release 1 exposed the
federation-trigger endpoints through OEG (a `/partner` create endpoint plus zone subscription),
which then forwarded to FM. The 2026-09-01 TSC+MDL meeting revisited this for Release 2 and
confirmed the release-1 pattern should continue rather than moving the trigger onto FM's own
admin surface.

Options considered:

- Option A: Keep FM's L.2 internal admin API as the sole entry point (current documented state).
- Option B: Front the "create/trigger a new federation" action with OEG — an operator-role-gated
  endpoint that persists an operation record the same way OEG does for other async actions, and
  publishes an async command to FM over the DataBus using a thin envelope (analogous to
  `CommandEnvelopeV1`, ADR-0001) wrapping the same payload FM's L.2 `POST /internal/partners` /
  `/internal/agreements` already define. OEG performs no orchestration or GSMA-protocol logic
  itself — pure proxy.
- Option C: Add a config/bootstrap-driven path alongside Option B — FM reads a
  `federation_enabled`-style startup configuration naming pre-approved partners and zones, and
  self-initiates federation without any API trigger, for environments where a manual operator
  action per federation is unnecessary overhead (dev/test, pre-integrated deployments).

## Decision

Option B + Option C. OEG becomes the operator-facing trigger for creating a new outbound
federation relationship and its accompanying zone subscription. It forwards asynchronously to FM
over the DataBus using a new namespaced command family, following the existing `command.srm.*`
convention (ADR-0001) — e.g. `command.fm.federation.create`, `command.fm.federation.zone_subscribe`
— with a thin envelope wrapping the same payload shape FM's L.2 endpoints already define. FM
remains the sole owner of actual OPG.04 EWBI protocol execution: the mandatory inbound EWBI
termination (partner OPs calling our `POST /partner` directly, per OPG.04) is unaffected, and FM
still makes the outbound `CreateFederation` call to the partner's FM.

FM additionally supports self-initiated bootstrap federation: a startup configuration section
naming partner endpoints and zones to federate with automatically. Both triggers (OEG-proxied and
config-bootstrap) converge on the same internal FM logic, so there is one code path regardless of
how federation setup was initiated.

FM's L.2 admin API is retained for direct read/list/update/decommission operations on existing
partner records — this decision narrows L.2's scope only for the *create* action, which now
normally arrives via the OEG-proxied command. L.2's create/update endpoints stay available for
operational or break-glass use but are no longer the primary product-facing path for standing up
a new federation.

## Consequences

What becomes easier:

- Federation setup follows the same auth/policy/audit convention as every other operator action —
  one `operations` ledger in `oeg_db` captures federation-trigger requests the same way it
  captures deploys.
- Environments that pre-establish federation (dev/test, demo rigs) skip the manual API trigger
  entirely via bootstrap config.

What becomes harder:

- A new DataBus command namespace (`command.fm.*`) is introduced that FM must consume. Today
  `OOP_TASKS` binds only to `command.srm.>` with SRM as sole consumer (ADR-0001); FM needs either
  a second consumer binding on `OOP_TASKS` or a dedicated subject/stream carve-out.

Deferred or excluded:

- Exact subject names, schema artifacts, and stream topology for `command.fm.*` are left to
  fm/requirements-and-design.md and platform/architecture.md's DataBus section to finalize.
- No change to FM's mandatory inbound EWBI termination or to `partner_ops`/`federation_agreements`
  read/update/decommission operations on L.2.

Revisit trigger:

- Introduction of a distinct `operator-admin` Keycloak role that would let this stay purely on
  FM's own admin surface without losing the platform's centralized-gateway convention; or a
  platform-infra decision that a second `command.*` producer/consumer namespace does not fit the
  current single-stream `OOP_TASKS` design.
+109 −0
Changes for decisions/0044-srm-owns-federated-zone-locality-and-hand-off.md: 109 added lines, 0 removed lines.
Original line number Diff line number Diff line
---
type: Decision Record
title: "ADR-0044: SRM resolves Edge Cloud Zone locality for deployment targets and forwards non-local deploys to FM (interim runtime-coordination layer)"
description: "SRM resolves Edge Cloud Zone locality for deployment targets and forwards non-local deploys to FM (interim runtime-coordination layer)"
tags: [adr]
timestamp: 2026-09-04T00:00:00Z
status: "accepted"
---

# ADR-0044: SRM resolves Edge Cloud Zone locality for deployment targets and forwards non-local deploys to FM (interim runtime-coordination layer)

**Status:** accepted
**Date:** 2026-09-04
**Affects:** [srm/architecture.md](/srm/architecture.md), [srm/interface-contract.md](/srm/interface-contract.md), [oeg/architecture.md](/oeg/architecture.md), [fm/overview-and-architecture.md](/fm/overview-and-architecture.md), [platform/architecture.md](/platform/architecture.md), [platform/future-architecture.md](/platform/future-architecture.md)

## Context

[oeg/architecture.md](/oeg/architecture.md) UC-OEG-05 and [fm/overview-and-architecture.md](/fm/overview-and-architecture.md)
§G3 currently assign "is this deploy target zone local, or does it need federation" to OEG, which
— per §G3's recommendation — hands off directly to FM over internal HTTP when the target isn't
local, bypassing SRM entirely. Release-1 code instead checked this at the SRM boundary (whether
the target `edgeCloudZoneId` exists in the local zone table). platform/architecture.md's
Component Boundary Matrix already assigns "Placement decisions (which zone, which domain)" to
SRM, not OEG or FM — so whether a target zone is local or federated is itself a placement
decision, and belongs with SRM by the platform's own existing ownership rule. The 2026-09-01
TSC+MDL meeting confirmed this and also referenced an earlier-agreed but never-documented
end-state: a future "runtime coordinator" component, sitting above SRM and below OEG, will
eventually own cross-domain routing between local fulfillment (SRM) and federated fulfillment
(FM). That component does not exist today and is out of scope to build now; until it does, this
responsibility is carried as a thin, deliberately minimal layer inside SRM.

Options considered:

- Option A: Keep the current documented model — OEG determines locality and hands off directly to
  FM (current state, UC-OEG-05 / FM §G3).
- Option B: Move locality determination and the federated hand-off into SRM. SRM checks its own
  zone inventory first; when the target zone isn't found locally, it queries FM for federated
  zone data and, if found there, forwards fulfillment to FM using FM's internal command schema
  (not raw GSMA/OPG.04).
- Option C: Build the future "runtime coordinator" component now, ahead of the rest of Release 2
  SRM/FM work, to own this from day one.

## Decision

Option B, scoped specifically to Edge Cloud Zone-based deployment targeting — the
`command.srm.service.deploy` path (CAMARA Edge Application Management `/appinstances` and
`/deployments`). OEG stops evaluating zone locality for deploys; it already unconditionally
persists and publishes `command.srm.service.deploy` (oeg/architecture.md §A.1), and that does not
change.

SRM, on receiving a deploy command, resolves the target zone the same way it resolves placement
generally: first against its own zone inventory. When the zone is not present locally, SRM queries
FM (a new SRM→FM internal HTTP call — the only FM↔SRM internal HTTP direction until now was FM
calling SRM) for federated zone/capability data, and if the zone resolves there, forwards the
deploy to FM using FM's internal schema — SRM does not attempt GSMA/EWBI translation itself. FM
then runs the outbound EWBI handshake with the partner FM through the same code path it already
uses for inbound federation-originated deploys (srm/architecture.md UC-SRM-03), so FM's
fulfillment pipeline is uniform regardless of whether the request originated as an inbound
federation request or an outbound one relayed by SRM.

SRM's internal zone-listing read (the internal equivalent of `GET /internal/zones`) includes FM's
federated zones in its result, so downstream consumers keep one merged view during this interim
period.

This is explicitly a **stopgap**. SRM's federation-hand-off logic must stay minimal — locality
check plus forward only, no GSMA-shaping, no partner-catalogue ownership — specifically so that
extracting it into the future "runtime coordinator" component is a lift-and-shift rather than a
rewrite. Option C is rejected for now: building the component ahead of need is out of scope for
this release. This ADR records the interim placement and reserves the intent to revisit, it does
not scope or design that future component.

**Explicitly out of scope / unaffected by this decision:** subscriber-identifier-based federation
routing (MSISDN/IP) for synchronous query APIs (Device Location, Device Status). UC-FM-02's
existing OEG→FM hand-off model is untouched — the meeting discussed Edge Cloud Zone-based
deployment targeting only.

## Consequences

What becomes easier:

- Placement (local or federated) becomes one coherent SRM-owned decision instead of being split
  between OEG (locality check) and FM (fulfillment).
- FM's fulfillment pipeline for federation-originated work becomes uniform regardless of request
  origin, matching the existing principle that SRM/FM treat OEG- and FM-originated commands
  identically.
- OEG gets simpler: no locality logic to build out for UC-OEG-05 / Phase 2.

What becomes harder:

- SRM gains a new outbound dependency on FM. SRM's mental model ("OEG and FM are the upstream
  gateways" — srm/architecture.md) needs correcting: SRM is no longer purely a command consumer.
- A new internal API surface is required on FM's side (federated-zone query + deploy hand-off
  intake).
- Deploy latency for federated targets now depends on FM's, and transitively a partner's,
  responsiveness — srm/architecture.md §A.2's latency targets apply to local placement only.

Deferred or excluded:

- The exact transport for the SRM→FM deploy hand-off (synchronous internal HTTP vs. a new async
  command family) is left open — the meeting did not conclude this point. Flagged as an open
  question in srm/interface-contract.md rather than decided here.
- The design and scope of the future "runtime coordinator" component itself is deferred entirely;
  this ADR only reserves its eventual existence as the revisit trigger.

Revisit trigger:

- When the "runtime coordinator" component is scoped and built, this ADR is superseded — SRM's
  locality-check/forward logic moves out to that component, and OEG's and FM's hand-off targets
  are repointed at it.
+2 −0
Changes for decisions/index.md: 2 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -45,3 +45,5 @@ the reasoning lives here. Never renumber; supersede instead (see the record-deci
* [ADR-0040](0040-target-serveability-is-a-tri-state.md) - can_serve_target answers can_serve | unknown_subscriber | unsupported_identifier; a boolean cannot carry the 404/422 split §E.2 requires, and 404 needs positive evidence (supersedes ADR-0038's boolean)
* [ADR-0041](0041-tfsdk-owns-adapter-construction.md) - TF-SDK builds adapters behind a factory keyed by adapter kind; SRM resolves control_path_ref to an instance but never enumerates adapter kinds
* [ADR-0042](0042-ewbi-oauth2-client-credentials-mtls-deferred.md) - E/WBI authorization is OAuth2 Client-Credentials: local Keycloak for inbound, partner Authorization Server for outbound; mTLS deferred
* [ADR-0043](0043-oeg-proxied-federation-establishment.md) - operator-triggered federation establishment is proxied through OEG over the DataBus (command.fm.federation.*); FM also supports config-driven bootstrap federation
* [ADR-0044](0044-srm-owns-federated-zone-locality-and-hand-off.md) - SRM resolves Edge Cloud Zone locality for deployment targets and forwards non-local deploys to FM; interim layer pending a future runtime-coordinator component
+43 −8
Changes for fm/overview-and-architecture.md: 43 added lines, 8 removed lines.
Original line number Diff line number Diff line
@@ -23,6 +23,8 @@ If you are new to FM, this is the simplest useful way to think about it:
- **FM does not fulfill requests itself.** For OPG.04 lifecycle mutations (install/remove application and supported network-capability operations), it publishes the same `command.srm.*` commands to DataBus that OEG publishes (ADR-0001). For stateless queries (device location, device status), it calls SRM's internal HTTP endpoints synchronously. Either way, SRM handles all fulfillment identically regardless of whether the request came from OEG or FM.
- **FM enforces topology hiding.** Before any response leaves the operator boundary, FM strips internal IPs, cluster names, namespace names, pod UIDs, node names, and internal trace IDs. Partner operators never see our internal infrastructure details.
- **FM manages partner relationships.** It stores partner operator profiles, federation agreements, routing rules, and shared resource catalogues in its own PostgreSQL database (`fm_db`).
- **Establishing a new federation is triggered two ways (ADR-0043):** an operator-facing action proxied through OEG (persist + publish `command.fm.federation.*`, no orchestration in OEG), or FM self-initiating from bootstrap configuration at startup. Either way, FM alone executes the outbound OPG.04 `CreateFederation`/`ZoneSubscribe` handshake.
- **For zone-based deployment targeting, SRM — not OEG — determines locality and hands off to FM (ADR-0044).** SRM checks its own zone inventory first, queries FM for federated zone data when the target isn't found locally, and forwards the deploy using FM's internal schema. This is an interim layer pending a future "runtime coordinator" component (see [platform/future-architecture.md](/platform/future-architecture.md) §6.1). OEG's outbound hand-off to FM (below) is now scoped to subscriber-identifier (MSISDN/IP) routing only.

```text
                   Partner Operators
@@ -225,7 +227,11 @@ A partner operator requests deployment of an edge application on our infrastruct

### UC-FM-02: Outbound Federation Routing (Our App Provider → Partner Infrastructure)

A locally connected App Provider makes a request that targets a subscriber or resource on a partner network. OEG detects that the target cannot be served locally and hands off to FM.
**Scope (ADR-0044):** this use case covers subscriber-identifier-based routing (MSISDN/IP) for
synchronous query APIs (Device Location, Device Status) only. Zone-based deployment targeting is
UC-FM-07 below — the hand-off there comes from SRM, not OEG.

A locally connected App Provider makes a request that targets a subscriber on a partner network. OEG detects that the target cannot be served locally and hands off to FM.

- **Actor:** FM (on behalf of local App Provider, triggered by OEG)
- **Trigger:** OEG determines the request target (MSISDN, IP) belongs to a partner network.
@@ -287,14 +293,31 @@ A partner operator queries device location or device status for a subscriber tha

An operator onboards, updates, or decommissions a federation partner.

- **Actor:** Operator (via Portal admin console or internal API)
- **Trigger:** New bilateral agreement signed, OAuth2 credential rotation, endpoint change, or partner decommission.
- **Actor:** Operator, normally via OEG's proxied federation-establishment trigger (ADR-0043); Portal or FM's own internal admin API (L.2) remain available for direct read/update/decommission operations on existing partner records.
- **Trigger:** New bilateral agreement signed, OAuth2 credential rotation, endpoint change, or partner decommission — or FM's own bootstrap configuration at startup (ADR-0043).
- **Main flow:**
  1. Operator creates/updates partner profile (EWBI/token endpoints, inbound and outbound OAuth2 client IDs, mounted-secret reference, supported APIs, SLA limits).
  1. Operator triggers creation via OEG (`command.fm.federation.create`) or FM self-initiates from bootstrap config; profile fields are the same either way (EWBI/token endpoints, inbound and outbound OAuth2 client IDs, mounted-secret reference, supported APIs, SLA limits).
  2. FM stores profile in `partner_ops` table.
  3. FM creates/updates federation agreement in `federation_agreements` table.
  4. FM populates routing rules.
  5. FM uses OPG.04 federation-management operations (`CreateFederation`, `GetFederationHealth`, `RenewFederation`) with the partner.
  6. Subsequent read/update/decommission operations on an existing partner use FM's L.2 internal admin API directly (unchanged by ADR-0043).

### UC-FM-07: Outbound Federated Deployment via SRM (ADR-0044)

A locally connected App Provider deploys to an Edge Cloud Zone that turns out to be on a partner network. SRM — not OEG — detects this and hands off to FM.

- **Actor:** FM (on behalf of local App Provider, triggered by SRM)
- **Trigger:** SRM's zone-locality check finds the target `zone_id` is absent from its own inventory and present in FM's federated zone data.
- **Main flow:**
  1. OEG publishes `command.srm.service.deploy` unconditionally, as it does for every deploy (no locality check in OEG).
  2. SRM checks its own zone inventory; not found locally, so it queries FM for federated zone/capability data.
  3. FM returns the matching federated zone entry (from `shared_resource_catalogues`).
  4. SRM forwards the deploy to FM using FM's internal schema (not raw GSMA/OPG.04) — exact request/response contract, retry, and timeout semantics are an open item (§G4).
  5. FM maps the request to OPG.04 `InstallApp` and executes the outbound EWBI call to the partner's FM, through the same code path used for inbound federation-originated deploys (UC-FM-01's fulfillment pipeline).
  6. FM reports the result back to SRM, which resumes its normal `event.srm.operation.completed` lifecycle for the original command.
- **Why this exists:** Keeps placement (local-vs-federated) a single SRM-owned decision instead of splitting it between OEG and FM; see ADR-0044.
- **Interim status:** this SRM-side hand-off is a deliberate stopgap pending a future "runtime coordinator" component (platform/future-architecture.md §6.1) that will eventually own it.

---

@@ -330,7 +353,7 @@ An operator onboards, updates, or decommissions a federation partner.
FM sits between **partner operators** and **internal platform services**:

- **Upstream:** Partner Operator Platforms (over EWBI)
- **Lateral:** OEG (for outbound federation hand-off)
- **Lateral:** OEG (federation-establishment trigger, ADR-0043; subscriber-identifier outbound hand-off, UC-FM-02); SRM (federated zone query and zone-based deploy hand-off, ADR-0044)
- **Downstream:** SRM (via DataBus for mutations, internal HTTP for reads/capacity checks)

Per the component boundary matrix:
@@ -342,8 +365,9 @@ Per the component boundary matrix:
| Topology hiding for federation responses | **FM** |
| Federation usage-record generation toward the charging integration | **FM** |
| Async command dispatch (`command.srm.*` publishing) | **FM** (shared with OEG) |
| Consuming `command.fm.federation.*` (ADR-0043) | **FM** (published by OEG) |
| TF-SDK adapter invocation | **SRM** (not FM) |
| Placement decisions | **SRM** (not FM) |
| Placement decisions, including local-vs-federated zone determination for deployment targets (ADR-0044) | **SRM** (not FM) |
| Service and resource inventory | **SRM** (not FM) |

---
@@ -375,11 +399,21 @@ Per the component boundary matrix:

**Recommendation:** Initially, FM does not implement consent forwarding. Consent is enforced at the leading OP's OEG before the request is federated. When the CAMARA ICM spec stabilizes, FM forwards an opaque consent reference in EWBI headers. This is a cross-cutting concern with the Consent domain in TF-SDK's future architecture.

### G3. OEG → FM Hand-off for Outbound Federation
### G3. OEG → FM Hand-off for Outbound Federation (subscriber-identifier routing only)

**Scope note (ADR-0044):** this question, and its recommendation, cover subscriber-identifier
(MSISDN/IP) routing for synchronous query APIs only. Zone-based deployment targeting no longer
goes through OEG at all — see G4.

**The question:** When OEG detects that a request requires federation (target MSISDN/IP is not local), what is the hand-off mechanism to FM?

**Recommendation:** Internal HTTP from OEG to FM for all outbound federation hand-offs (synchronous queries and lifecycle forwards). OEG calls FM with the routing identifiers and original request context; FM resolves the partner, forwards over EWBI, and returns the result to OEG. This keeps EWBI protocol knowledge inside FM and avoids a second async hop on the developer-facing latency path. Initially, OEG rejects non-local requests with a 400/404 (federation not yet available). The OEG spec already anticipates this pattern in UC-OEG-05.
**Recommendation:** Internal HTTP from OEG to FM for all outbound federation hand-offs (synchronous queries). OEG calls FM with the routing identifiers and original request context; FM resolves the partner, forwards over EWBI, and returns the result to OEG. This keeps EWBI protocol knowledge inside FM and avoids a second async hop on the developer-facing latency path. Initially, OEG rejects non-local requests with a 400/404 (federation not yet available). The OEG spec already anticipates this pattern in UC-OEG-05.

### G4. SRM → FM Hand-off for Federated Deployment (ADR-0044)

**The question:** When SRM determines a deploy target zone is federated (UC-FM-07), what is the exact hand-off contract to FM — synchronous internal HTTP (matching every other FM↔SRM internal call in this document) or a new async DataBus command?

**Status:** unresolved. The 2026-09-01 TSC+MDL meeting decided SRM (not OEG) owns this hand-off, but did not conclude the transport. **Recommendation:** default to synchronous internal HTTP for consistency with L.4's existing FM↔SRM pattern, with SRM treating the call as part of its own already-async `command.srm.service.deploy` handling (SRM owns retry/timeout toward FM, not OEG). Revisit once FM/SRM implementation work starts on UC-FM-07.

---

@@ -388,3 +422,4 @@ Per the component boundary matrix:
| Version | Date | Summary |
|---------|------|---------|
| 2.0 | 2026-07-07 | OOP Release 2.0. |
| 2.0 | 2026-09-04 | Added OEG-proxied federation-establishment trigger and FM bootstrap config (ADR-0043, UC-FM-06 updated). Added UC-FM-07: SRM (not OEG) now owns zone-based deployment locality and the hand-off to FM (ADR-0044); UC-FM-02/G3 narrowed to subscriber-identifier routing; added G4 for the open SRM→FM transport question. |
+51 −6

File changed.

Preview size limit exceeded, changes collapsed.

Loading