Commit 73a3dc2f authored by Sergio Gimenez's avatar Sergio Gimenez
Browse files

docs(fm,srm): align federated terminate with SRM's partner rows and add partner_not_found

§L.3a and SRM §F.4a still described terminate as firing when the
instance
isn't in SRM's inventory; since ADR-0053's 2026-09-25 amendment SRM
keeps a
hosted_by: partner row, and that row is the trigger. §L.3a also had FM
matching on external_resource_id, which holds the partner-issued
appInstIdentifier; FM resolves the instance through its outbound
install-app transaction instead. ADR-0053, FM RD §M.1 and SRM §F.4a gain
completion_basis partner_not_found for a RemoveApp answered 404.
parent 0a7f4d26
Loading
Loading
Loading
Loading
+2 −1
Changes for decisions/0053-srm-fm-federated-lifecycle-handoff-over-the-databus.md: 2 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -9,7 +9,7 @@ status: "proposed"

# ADR-0053: SRM hands federated deploys and terminates to FM over the DataBus, and FM reports the outcome the same way

**Status:** proposed (amended 2026-09-25: SRM keeps instance rows for partner targets)
**Status:** proposed (amended 2026-09-25: SRM keeps instance rows for partner targets; 2026-09-29: `partner_not_found`)
**Date:** 2026-09-22
**Affects:** [fm/overview-and-architecture.md](/fm/overview-and-architecture.md) (open item G4, UC-FM-07), [fm/requirements-and-design.md](/fm/requirements-and-design.md) (the SRM→FM hand-off section §L.3a, FM's DataBus sections §K.2 and §M), [srm/interface-contract.md](/srm/interface-contract.md) (stream configuration §D, the federated hand-off flow §F.4a), [platform/architecture.md](/platform/architecture.md) (DataBus configuration)
**Amends:** ADR-0001 and ADR-0022, where they make SRM the only consumer of `OOP_TASKS`; ADR-0046, where it keeps the DataBus to `command.srm.*` / `event.srm.*`
@@ -165,6 +165,7 @@ things:
| `partner_confirmed` | deploy | the partner's `onInstanceStatusEvent` arrives | the instance is running |
| `deadline_expired` | deploy | no callback before the deadline | failed; the partner never answered |
| `partner_accepted` | terminate | the partner answers `RemoveApp` with `200` | the partner said yes; removal isn't confirmed |
| `partner_not_found` | terminate | the partner answers `RemoveApp` with `404` | the partner no longer has the instance; the terminate is complete |

Termination gets the weaker claim because OPG.04 offers nothing stronger to observe. We don't build
machinery to chase a partner who accepts a removal and then leaves the app running: that partner
+10 −5
Changes for fm/requirements-and-design.md: 10 added lines, 5 removed lines.
Original line number Diff line number Diff line
@@ -574,7 +574,7 @@ SRM treats a `404` as an ordinary placement failure, the same path as an unresol
| Subject | Stream | Payload | Published by SRM when |
|---|---|---|---|
| `command.fm.service.deploy` | `OOP_TASKS` | `SrmServiceDeployV1`, as SRM received it | the target zone came back federated |
| `command.fm.service.terminate` | `OOP_TASKS` | `SrmServiceTerminateV1`, as SRM received it | the `service_instance_id` isn't in SRM's inventory |
| `command.fm.service.terminate` | `OOP_TASKS` | `SrmServiceTerminateV1`, as SRM received it | the instance's row says `metadata.hosted_by: partner` |

The envelope keeps the original `operation_id` and `correlation_id`. SRM does no GSMA shaping; FM
maps deploy to OPG.04 `InstallApp` and terminate to `RemoveApp`.
@@ -584,10 +584,13 @@ acknowledges only after writing the `federation_transactions` row. It keys on `o
redelivered command whose `operation_id` already has a transaction row starts no second EWBI
exchange.

**Terminate resolves the instance in FM.** SRM doesn't look it up first. FM matches the
`service_instance_id` against its `federation_transactions` records, using the stored
`external_resource_id`, which holds the `appInstIdentifier` in its wire spelling (hex, because
OPG.04's `InstanceIdentifier` forbids hyphens).
**Terminate resolves the instance in FM.** SRM doesn't look it up first. FM finds the outbound
`install-app` transaction that recorded this `service_instance_id` when SRM handed the deploy over,
and takes from it what `RemoveApp` needs: the `federationContextId`, `appId` and partner `zoneId`,
and the `appInstIdentifier` in `external_resource_id`. That identifier is the one the partner
issued in its `InstallApp` answer, not ours, so FM can't derive it from the `service_instance_id`.
FM records the removal as a `remove-app` transaction keyed on the terminate's `operation_id`; a
redelivered command sends no second `RemoveApp` and publishes the stored outcome again.

**Refusals.** When FM can't act on a command, it publishes `event.fm.operation.completed` with
`status: failed` and one of these as `error.type` (RFC 7807), alongside the `partner-not-active`,
@@ -791,6 +794,7 @@ operations different guarantees:
|---|---|---|
| `partner_confirmed` | deploy | The partner's `onInstanceStatusEvent` callback reported the instance running |
| `partner_accepted` | terminate | The partner answered `RemoveApp` with `200`. **Not** confirmation that removal finished — OPG.04 defines no callback for removal and no `TERMINATED` state to observe |
| `partner_not_found` | terminate | The partner answered `RemoveApp` with `404`: it no longer has the instance, which is what the terminate asked for; `status` is `completed` |
| `deadline_expired` | deploy | No callback arrived within FM's configured wait (default 30 minutes); `status` is `failed` |

Consumers must not treat `partner_accepted` as proof of removal. Detecting a termination a partner
@@ -896,3 +900,4 @@ A locally connected App Provider queries device location for a subscriber on a p
| 2.0 | 2026-09-08 | ADR-0051 corrects ADR-0046's scope/payload/namespace for the OEG-proxied surface (transport unchanged). §L.3b retitled "Federation-Lifecycle Proxy": now seven canonical OPG.04 operations (create/read/update/delete federation, `GetFederationContextId`, zone subscribe/unsubscribe) served by OEG on `/operatorplatform/federation/v1/*` for the operator-triggered *outbound* direction, with the raw GSMA payload forwarded byte-for-byte (no reshaping, no §L.2 admin shape) and a no-log/no-persist rule for the credential-bearing body. Inbound partner traffic on the same paths still terminates at FM — the two directions split at the ingress. REQ-FED-19/20 and the L.2 note rewritten; priority federation-management table note updated. |
| 2.0 | 2026-09-16 | ADR-0051 amended after FM-side review, reversing this file's own previous entry above: OEG's federation-lifecycle proxy goes back onto its own `/platform/v1/federation/partners/{partnerOpId}/federations/...` namespace, not the canonical OPG.04 prefix — the canonical URL loses partner addressing once there's an OEG hop in front of FM. §L.3b, the priority federation-management table, and REQ-FED-19/20 rewritten: eight operations now (`GetZoneData` added, `UpdateFederation` out of scope), query string forwarded, spec pinned to GSMA OPG.04 v6.0 / artifact v1.4.0, `partnerCallbackCredentials` dropped (not a v1.4.0 field), partner resolution tied to FM's not-yet-built partner registration (federation-manager#20). The "FM authenticates OEG's platform service credential (ADR-0042)" auth claim is corrected everywhere it appeared: this hop has no dedicated credential, only cluster-internal network-policy reachability; ADR-0042 is EWBI partner-facing auth only. ADR-0047/0048 renumbered to ADR-0050/0051. |
| 2.0 | 2026-09-29 | §L.3b: FM's status set on the `/internal` federation-lifecycle routes pinned to OPG.04 v1.4.0's declared statuses, with the mapping for FM's EWBI-side `403`/`502` and for partner rejections (REQ-FED-14; OEG §K.6a's `502` gate relies on it). |
| 2.0 | 2026-09-29 | §L.3a: `command.fm.service.terminate` fires on SRM's `hosted_by: partner` instance row (ADR-0053's 2026-09-25 amendment), and FM resolves the instance from the outbound `install-app` transaction, since the partner issues the `appInstIdentifier`. §M.1: new `completion_basis` `partner_not_found` for a `RemoveApp` answered `404`. |
+6 −2
Changes for srm/interface-contract.md: 6 added lines, 2 removed lines.
Original line number Diff line number Diff line
@@ -876,7 +876,8 @@ on the DataBus in both directions, with only the zone lookup as a synchronous re

**Terminate:**

1. SRM looks up `service_instance_id` in its own inventory. Not found locally.
1. SRM looks up `service_instance_id` in its own inventory and finds the row it wrote at deploy
   time with `metadata.hosted_by: partner`.
2. SRM writes its `service_order` row and publishes `command.fm.service.terminate` with the
   `SrmServiceTerminateV1` payload it received. There's no lookup step: FM resolves the instance
   from its own federation transaction records, and reports `instance-not-federated` if it can't.
@@ -892,7 +893,9 @@ stuck in `INSTANTIATING` or `TERMINATING`.
`metadata.completion_basis` says what the outcome rests on and has to be carried through, not
flattened: `partner_confirmed` (the partner's deploy callback reported the instance running),
`partner_accepted` (the partner accepted a termination; OPG.04 defines no removal callback and no
`TERMINATED` state, so removal isn't confirmed), or `deadline_expired` (no deploy callback within
`TERMINATED` state, so removal isn't confirmed), `partner_not_found` (the partner answered
`RemoveApp` with `404`: the instance is already gone there, so the terminate completed), or
`deadline_expired` (no deploy callback within
FM's configured wait). A refusal (zone not federated, agreement forbids it, partner suspended,
instance unknown) arrives as the same event with `status: failed` and the reason in `error`.

@@ -925,3 +928,4 @@ interim layer until the runtime coordinator in platform/future-architecture.md
| 2.0 | 2026-09-04 | Added F.4a: SRM resolves zone locality and forwards non-local deploys to FM (ADR-0044). `GET /zones` (§E.3) may now include FM-sourced federated zones. F.4a step 1 corrected to cite F.1's direct zone lookup, not §B's device-targeted candidate-probing mechanism (different, unrelated resolution path). |
| 2.0 | 2026-09-08 | §B: a zone/domain pin on a device-targeted capability narrows the candidate set rather than bypassing target probing (ADR-0045). Deploy §B.2's "SRM selects a domain in it" no longer carries over; probing is triggered by how many candidates survive the pin, so a zone-pinned request in a two-NEF zone is probed and a zone+domain pin still resolves without one. |
| 2.0 | 2026-09-09 | §E.1: terminal-record read behaviour is per-family, following each vendored CAMARA schema rather than a blanket `404` (ADR-0049). Traffic Influence's `state` enum documents `deletion in progress`/`deleted`, so it reads them back as `200`; QoD's `QosStatus` has no such value and stays `404`. |
| 2.0 | 2026-09-29 | §F.4a: terminate step 1 finds the `hosted_by: partner` row (ADR-0053's 2026-09-25 amendment) instead of "not found locally"; `partner_not_found` added to the `completion_basis` values. |