Commit 77ba1347 authored by Dimitrios Gogos's avatar Dimitrios Gogos
Browse files

fix: clarify region filtering in app instances and service instances endpoints

parent 31fa314e
Loading
Loading
Loading
Loading
+15 −5
Changes for oeg/app-instance-flow.md: 15 added lines, 5 removed lines.
Original line number Diff line number Diff line
@@ -549,11 +549,20 @@ Location: https://api.example.com/edge-application-management/vwip/appinstances/
## Response 2 — GET /appinstances (200 — List)

Returns the app instances for the authenticated client, optionally filtered by the CAMARA query
parameters `appId`, `appInstanceId`, and `region` (a real, distinct CAMARA-defined free-text
geography filter — "human readable name of the geographical Edge Cloud Region" — not an alias
for `edgeCloudZoneId`). OEG resolves the client's `app_instances`
rows and proxies a live SRM read per instance to fill live fields. Returns an empty array when
nothing matches.
parameters `appId`, `appInstanceId`, and `region`. `region` is a real, distinct CAMARA-defined
free-text geography filter — "human readable name of the geographical Edge Cloud Region" — not
an alias for `edgeCloudZoneId`; it resolves through the instance's zone
(`zone.metadata.location.region`, same free-form field `GET /edge-cloud-zones?region=...` reads),
but SRM's collection read doesn't join that yet, so it's accepted but **not yet filterable**
(OQ-05 below).

OEG resolves `appId` to `app_registration_id` via `oeg_db` (unchanged from the single-instance
path), then calls `GET /internal/service-instances?service_specification_id=...&service_instance_id=...`
(`srm/interface-contract.md` §E.1). SRM itself scopes the result to the caller's own
`app_provider_id` from auth context, so OEG does not pre-resolve or post-filter by tenant — the
collection SRM returns is already the correct set. Each row carries `service_specification_id`,
which OEG resolves back to `appId` per row via `oeg_db` (`app_registrations`) to build the
response. Returns an empty array when nothing matches.

```json
[
@@ -686,6 +695,7 @@ CloudEvent if a callback is registered.
| OQ-02 | `event.srm.operation.status` handling: should OEG map event payload `state=failed_before_start` to `operations.status=FAILED` in Phase 1, or defer to Phase 2? | Minor; only affects time-to-failure-visibility for the App Provider |
| OQ-03 | Webhook callback retry policy — number of retries, backoff, dead-letter handling | Needed before UC7 implementation |
| OQ-04 | `componentEndpointInfo` in webhook — should OEG make a live SRM read before delivering the callback to include endpoint data? | Affects callback delivery latency |
| OQ-05 | `GET /appinstances?region=...` — mechanism identified: `service_instance.zone_id → zone.metadata.location.region` (same path `GET /zones?region=...` already uses, `srm/interface-contract.md` §E.1/§E.3), but the join isn't implemented on `GET /service-instances` yet, and `metadata.location.region` isn't guaranteed set on every zone. Build the join, or reject `region` with `501` until it is? | Affects listing correctness for callers relying on `region` |

---

+27 −8
Changes for srm/interface-contract.md: 27 added lines, 8 removed lines.
Original line number Diff line number Diff line
@@ -402,13 +402,22 @@ diagnostics, trusted catalog/admin, and synchronous query/data only.
  Because `appInstanceId == service_instance_id` (ADR-0005), OEG uses this endpoint directly to
  resolve the target of `DELETE /appinstances/{appInstanceId}` before publishing
  `command.srm.service.terminate` — no separate by-`external_ref` lookup is needed.
- `GET /service-instances` — collection form of the above, filterable by `app_provider_id`
  (always, from auth context), and optionally `service_specification_id` and `zone_id`; same
  response shape as the single-instance form, as a list. OEG uses this to serve
  `GET /appinstances?appId=...&appInstanceId=...&region=...` (ADR-0007 collection query reads),
  translating CAMARA `appId`/`appInstanceId`/`region` to `service_specification_id`/
  `service_instance_id`/`zone_id` at the mapper boundary; `ref` is surfaced to CAMARA as `name`
  (same rename pattern as elsewhere in this contract — no new SRM-side mechanism).
- `GET /service-instances` — collection form of the above, always scoped to the caller's own
  `app_provider_id` (from auth context, never client-supplied), and optionally filtered further
  by `service_specification_id` and/or `service_instance_id`; same response shape as the
  single-instance form, as a list; ids/specs not found are simply omitted, not a 404 for the
  whole call. OEG uses this to serve `GET /appinstances?appId=...&appInstanceId=...`
  (ADR-0007 collection query reads), translating CAMARA `appId`/`appInstanceId` to
  `service_specification_id`/`service_instance_id` at the mapper boundary; `ref` is surfaced to
  CAMARA as `name` (same rename pattern as elsewhere in this contract — no new SRM-side
  mechanism).
  **`region` must not be translated to `zone_id` — they are distinct** (a region groups many
  zones; `zone_id` is one realized zone). CAMARA `region` is properly a filter on the
  *instance's zone*, not on `service_instance` directly: it resolves through
  `service_instance.zone_id → zone.metadata.location.region` (same free-form, not-guaranteed
  JSON path as the `GET /zones` `region` filter above). This endpoint does not yet perform that
  join — `region` is accepted but not filtered server-side today (open question, see
  [oeg/app-instance-flow.md](/oeg/app-instance-flow.md) Open Questions, OQ-05).
- `GET /operations/by-operation-id/{operation_id}` — latest `service_order` row +
  derived inventory state; read-only; tenant-scoped; RFC 7807 on 404.

@@ -429,8 +438,18 @@ Number Verification is **not** part of this contract; model separately.

- `POST /capacity-check` — capacity query against a zone (or a specific
  `domain_id`); best-effort via `query_available_resources`.
- `GET /zones` — zones with compute/network domain summaries. `metadata.provider` is guaranteed non-null on every zone (ADR-0029).
- `GET /zones` — zones with compute/network domain summaries. `metadata.provider` is guaranteed
  non-null on every zone (ADR-0029). Optionally filterable by `state` (`zone.state` column) and
  `region` (matched against the free-form `metadata.location.region` JSON path — not a dedicated
  column, and not guaranteed set on every zone, per persistence-cross-standards-view.md). OEG
  passes CAMARA `region`/`status` through to these two params unchanged.
- `GET /domains`, `GET /capabilities` — topology reads.
- `GET /service-instances?scope=all` — same response shape as the §E.1 collection read, but
  bypasses the auth-context `app_provider_id` filter: all `service_instance` rows, all
  tenants/apps. Requires an elevated/ops credential, not a tenant's own auth context.
  Diagnostics/ops use only — `service_instance` rows are soft-deleted, never removed (§F
  Terminate), so this list grows without bound over the platform's lifetime. OEG's
  tenant-facing `GET /appinstances` must use the scoped §E.1 form, never this one.

### E.4 Trusted catalog/admin

+1 −1
Changes for srm/persistence-cross-standards-view.md: 1 added line, 1 removed line.
Original line number Diff line number Diff line
@@ -178,7 +178,7 @@ site — *the "where" of edge*. Other kinds (`authority`, `federation_business`,
| `name` | Text | CAMARA: `edgeCloudZoneName`. TMF674 v4: `GeographicSite.name`. GSMA OPG.04: `zoneName`. | The friendly name of the site. | EDGE-DEPLOY: `"London-East"`. | Not null |
| `kind` | Text | OOP-internal taxonomy. | What this zone scopes: `resource` zones host compute/network domains; `authority` zones host trust domains. | EDGE-DEPLOY: `resource`. | Not null. Values: `resource`, `authority`, `federation_business`, `logical`, `custom`. |
| `state` | Text | CAMARA: `edgeCloudZoneStatus` (`active`/`inactive`/`unknown`) — OEG maps `inactive` ↔ SRM `offline`. TMF674 v4: `lifecycleStatus`. GSMA OPG.04: `zoneStatus`. | Whether the site is usable right now. | EDGE-DEPLOY: `active`. | Not null, default `active`. Values: `active`, `offline`, `unknown`. |
| `metadata` | Document | OOP-internal geographic / operator annotations (not a CAMARA object). Closest CAMARA fields: `edgeCloudRegion`, `edgeCloudProvider`. TMF674 v4: `place.geographicLocation` (similar). | Where this site is in the world, and anything else the operator records. | EDGE-DEPLOY: `{"provider":"oop-provider","city":"London","country":"GB","lat":51.50,"lon":-0.06}`. | Not null, default `{}`. **Exception:** the `provider` key is guaranteed, never absent — SRM populates it from configuration, falling back to a hardcoded default (e.g. `"oop-provider"`) when unconfigured (ADR-0029). Every other key remains free-form/optional. |
| `metadata` | Document | OOP-internal geographic / operator annotations (not a CAMARA object). Closest CAMARA fields: `edgeCloudRegion` (`metadata.location.region`), `edgeCloudProvider` (`metadata.provider`). TMF674 v4: `place.geographicLocation` (similar). | Where this site is in the world, and anything else the operator records. | EDGE-DEPLOY: `{"provider":"oop-provider","location":{"city":"London","country":"GB","lat":51.50,"lon":-0.06,"region":"Europe"}}`. | Not null, default `{}`. **Exception:** the `provider` key is guaranteed, never absent — SRM populates it from configuration, falling back to a hardcoded default (e.g. `"oop-provider"`) when unconfigured (ADR-0029). `location.region` is the recognized (OEG-consumed) key for CAMARA `edgeCloudRegion`, but is optional/free-form like the rest of `location` — SRM does not guarantee it is set. |
| `created_at` / `updated_at` | Timestamp | — | Bookkeeping. | `2025-11-10 08:00 UTC`. | Not null, default `now()` |

> **Standards note:** GSMA distinguishes *Availability Zone* (the logical deployment target —