Commit 1be4d65f authored by Dimitrios Gogos's avatar Dimitrios Gogos
Browse files

docs(oeg): describe TI devices, deferred deletes and operation types

OEG dfd9b69 serves POST /traffic-influence-devices (201; a device
without ipv4Address is 422 SERVICE_NOT_APPLICABLE), defers the
deactivate command when a QoD or TI DELETE arrives before activation
completes, and stores per-family operation types, rewriting the legacy
network_capability values on startup. PATCH stays 501. Gap-register
line references keep the 68ff79a pin.

Co-Authored-By: default avatarClaude Opus 5.5 <noreply@anthropic.com>
parent 8b88bd07
Loading
Loading
Loading
Loading
+3 −1
Changes for oeg/implementation-and-delivery.md: 3 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -26,6 +26,8 @@ Implementation statements refer to the immutable code revisions below. They iden
| portal | `c030811fc28319c954f685b107f950660dd401d9` |
| ai2 | `de66ac36519af3baace5360161ada0e8de284d53` |

Traffic Influence device-scoped create, deferred network deletes and the `operation_type` startup rewrite are described from open-exposure-gateway `dfd9b697b889622b29254e07ea62730c0e619a09`.

OEG source is under `src/open_exposure_gateway/`. It is a single FastAPI service with ports and adapters. Import rules protect business logic from transport dependencies; the project is hexagonal-inspired rather than a strict abstract model.

| Folder | Holds |
@@ -167,7 +169,7 @@ Unknown acceptance is written explicitly; code absence is not a justification fo
| C18 quota/usage/subscription/charging context | Rate limits explicitly deferred by REQ-OEG-09; other acceptance and owner Unspecified | Scopes authorize product access; logs are not billing records |
| C19 TMF catalog facade/cache invalidation/drift alerts | Requirements retained; acceptance/owner Unspecified | EAM SRM-backed reads exist; no equivalent full facade/cache workaround established |
| C23 consent, token/device mapping, subscriber routing | Decisions F2–F4 remain open; acceptance/owner Unspecified | Explicit Location device is supported; it does not solve consent |
| C24 PATCH/clusters, QoD extend/retrieve and TI update/devices stubs | Acceptance/owner Unspecified | Use supported operations listed in contract §1 |
| C24 PATCH/clusters, QoD extend/retrieve and TI update stubs | Acceptance/owner Unspecified | Use supported operations listed in contract §1 |
| Schema evolution, retention/PII purge, backup/key rotation | Acceptance/owner and operational targets Unspecified | Preserve database/key pair; no complete recovery or deletion procedure established |
| C27/C28 correlator storage and combined CPU/GPU mapping/topology | Acceptance/owner Unspecified | No agreed workaround; align lengths, preserve required totals, decide topology precedence and verify failures |
| Subscription max-events/detail/initial-event ignored | Acceptance/owner Unspecified | No enforcement workaround established |
+6 −4
Changes for oeg/interface-contract.md: 6 added lines, 4 removed lines.
Original line number Diff line number Diff line
@@ -29,7 +29,7 @@ The [EAM vendored snapshot](/external-specs/camara-edge-application-management/V
|---|---|---|---|
| Edge Application Management | `0.1.0-alpha.1` | `/edge-application-management/v0.1alpha1` | Zones, apps, instances and deployments; deployment PATCH and cluster listing are 501 |
| Quality on Demand | `1.1.0` | `/quality-on-demand/v1` | Create/get/delete sessions; extend and retrieve sessions are 501 |
| Traffic Influence | `0.10.0` | `/traffic-influence/v0.10` | Create/list/get/delete; devices and update are 501 |
| Traffic Influence | `0.10.0` | `/traffic-influence/v0.10` | Create/list/get/delete and device-scoped create; update is 501 |
| Location Retrieval | `0.5.0` | `/location-retrieval/v0.5` | `POST /retrieve`; explicit device required |
| GSMA federation relay | OPG.04 v6.0 artifact `1.4.0` profile | `/platform/v1/federation` | Sixteen synchronous routes (§5) |
| Native health | Platform implementation | `/platform/healthz`, `/platform/readyz` | Conflicts with root-path REQ-OEG-14 |
@@ -2442,7 +2442,7 @@ in `app_instances.state`).
| `idempotency_key` | VARCHAR(128) | NULLABLE; composite UNIQUE(`tenant_id`, `idempotency_key`) — scoped per tenant to avoid cross-tenant collision |
| `tenant_id` | VARCHAR(255) | token `organization` claim, else `sub` (ADR-0048) |
| `app_provider_id` | VARCHAR(255) | token `app_provider_id` claim, else `sub` (ADR-0048, ADR-0066) |
| `operation_type` | VARCHAR(32) | `deploy`, `scale`, `terminate`, `network_capability_activate`, `network_capability_deactivate`. The activate/deactivate split exists because teardown is its own operation with its own `operation_id` (ADR-0034); the capability family is distinguished by the record the operation points at, not by the type. |
| `operation_type` | VARCHAR(32) | `deploy`, `scale`, `terminate`, `qod_session`, `qod_session_deactivate`, `traffic_influence`, `traffic_influence_deactivate`. The activate/deactivate split exists because teardown is its own operation with its own `operation_id` (ADR-0034). OEG routes each `event.srm.operation.completed` and `event.srm.operation.status` to QoD or Traffic Influence by this type. On startup OEG rewrites stored `network_capability` rows to `qod_session` and `network_capability_deactivate` rows to `qod_session_deactivate`. |
| `status` | VARCHAR(32) | CHECK IN (`PENDING`,`IN_PROGRESS`,`COMPLETED`,`PARTIALLY_COMPLETED`,`FAILED`). Exposed on `GET /platform/v1/operations/{operationId}` as JSON field `status` with the same name and values (no mapping layer). Completion can bypass IN_PROGRESS; `PARTIALLY_COMPLETED` when a multi-zone operation's `instances[]` has a mix of per-instance outcomes (ADR-0005); Selected EAM handles early status (C13). Note: this column's values are UPPERCASE and exposed as-is (no mapping), unlike `app_instances.state`/`app_deployments.state` below, which are lowercase with mapping on external instance reads: internal `terminated` becomes `unknown`. Deployment rollup is cached state, not an added public aggregate status field. The intended operation status itself is uppercase without rename. |
| `app_registration_id` | UUID FK -> `app_registrations` | NULLABLE (not all operations concern an app); resolved from the request's `appId` (ADR-0010) |
| `subject` | VARCHAR(128) | Published DataBus subject, e.g. `command.srm.service.deploy` |
@@ -2757,7 +2757,7 @@ Illustrative 201 resource, before activation:
}
```

Activation includes configured specification id, `service_instance_id=sessionId`, `capability_type=qod_session`, `profile_ref=qosProfile`, canonical device/server/ports, `duration_seconds` and `source_spec={family: camara, api: quality-on-demand, version: 1.1.0}`. An AVAILABLE session has start/expiry times; selected service stores them locally. DELETE returns 204 and immediately hides teardown-derived states with 404 while asynchronous deactivation completes. Selected QoD creation does not consume `Idempotency-Key`; repeat creates are not covered by the EAM replay path. Extending/retrieving sessions is 501, despite mounted routes. QoS profile catalog exposure is not established by the configured seed.
Activation includes configured specification id, `service_instance_id=sessionId`, `capability_type=qod_session`, `profile_ref=qosProfile`, canonical device/server/ports, `duration_seconds` and `source_spec={family: camara, api: quality-on-demand, version: 1.1.0}`. An AVAILABLE session has start/expiry times; selected service stores them locally. DELETE returns 204 and immediately hides teardown-derived states with 404 while asynchronous deactivation completes. A DELETE that arrives while the activate operation is still pending is accepted the same way, but OEG publishes the deactivate command only after the activate completion event arrives; if the activation failed, OEG marks the session deleted without publishing. Selected QoD creation does not consume `Idempotency-Key`; repeat creates are not covered by the EAM replay path. Extending/retrieving sessions is 501, despite mounted routes. QoS profile catalog exposure is not established by the configured seed.

### Traffic Influence 0.10

@@ -2781,7 +2781,9 @@ Content-Type: application/json

The 201 resource adds minted `trafficInfluenceID` and `state=ordered`; activation later makes it active/error. The activate command carries traffic filters, application reference, selected zone and source provenance (`traffic-influence`, `0.10.0`). Its `service_specification_id` is the platform-seeded TI specification from OEG configuration, and `appId` travels as `application_reference` (ADR-0035 amendment); the referenced SRM revision predates that seed (C02). This example validates request shape, not end-to-end TI fulfilment.

DELETE accepts asynchronously with 202, moving through `deletion in progress` to `deleted`. Individual deleted reads remain 200; collection excludes them. Selected update/devices routes return 501. A ready instance reported in `selected_appInstanceId` must belong to the pinned zone, and only the requested instance may be selected when supplied.
DELETE accepts asynchronously with 202, moving through `deletion in progress` to `deleted`. Individual deleted reads remain 200; collection excludes them. A DELETE that arrives while the activate operation is still pending is accepted the same way, but OEG publishes the deactivate command only after the activate completion event arrives. The update route returns 501.

`POST /traffic-influence/v0.10/traffic-influence-devices` takes the same body plus `device` and follows the same flow, returning 201 with a `Location` header that points at `/traffic-influences/{trafficInfluenceID}`. A missing `device` is 422 `MISSING_IDENTIFIER`; a device without `ipv4Address` is 422 `SERVICE_NOT_APPLICABLE`. OEG drops `networkAccessIdentifier` before publishing. A ready instance reported in `selected_appInstanceId` must belong to the pinned zone, and only the requested instance may be selected when supplied.

## Revision History

+4 −4
Changes for oeg/requirements-and-design.md: 4 added lines, 4 removed lines.
Original line number Diff line number Diff line
@@ -160,7 +160,7 @@ Why: [ADR-0033](/decisions/0033-async-network-capability-caller-id.md), [ADR-003
2. OEG mints `sessionId`, creates `REQUESTED` plus an activate operation, and publishes `command.srm.network.capability.activate` with `capability_type=qod_session`, configured specification id and `source_spec`.
3. OEG returns 201 with the session identity and REQUESTED status. This is asynchronous fulfilment despite the 201 resource response.
4. SRM completion/status updates the holder to `AVAILABLE` or `UNAVAILABLE`. Selected code starts timing when leaving REQUESTED; initial reads omit `startedAt`/`expiresAt`.
5. The caller deletes the session. OEG publishes a distinct deactivate operation against the same runtime id, returns 204 and moves through `DELETION_REQUESTED` to `DELETED`/`ERROR`. Teardown states read 404. AVAILABLE deletion emits `UNAVAILABLE`/`DELETE_REQUESTED`, then revokes its credential.
5. The caller deletes the session. OEG publishes a distinct deactivate operation against the same runtime id (after the activate completion event, if activation is still pending), returns 204 and moves through `DELETION_REQUESTED` to `DELETED`/`ERROR`. Teardown states read 404. AVAILABLE deletion emits `UNAVAILABLE`/`DELETE_REQUESTED`, then revokes its credential.

The platform seeds QoD `ref=qod-session`, no deployment units, one `qod_session`/`network` requirement with empty policy. Profile names are free strings passed as `profile_ref` for the adapter/network to accept or refuse; they are not validated against a local profile catalog. A future per-offering lookup and `/qos-profiles` mapping is a proposal, not a deployed feature.

@@ -173,8 +173,8 @@ Why: [ADR-0033](/decisions/0033-async-network-capability-caller-id.md), [ADR-003
1. The client posts `/traffic-influences` with a registered app, traffic filters and optional location/instance. OEG verifies app ownership.
2. OEG resolves a requested region or instance to a zone; unresolved requested location is 404, never silently unpinned. With no location, SRM chooses the control path. A pin narrows candidates; OEG must not probe or substitute a different resolved target.
3. OEG mints the policy/runtime id, prepares `ordered` plus activate operation, and publishes network activation with source provenance.
4. Completion/status moves to `active`/`error`. Pinned-zone ready instances scope `selected_appInstanceId`; the reviewed implementation returns 501 for device/update routes.
5. DELETE publishes a distinct deactivate operation, returns 202 and advances `deletion in progress` → `deleted`. A deleted individual resource remains representable with 200; it is excluded from active collection results.
4. Completion/status moves to `active`/`error`. Pinned-zone ready instances scope `selected_appInstanceId`. `POST /traffic-influence-devices` follows the same flow for one device and needs its `ipv4Address`; the update route returns 501.
5. DELETE publishes a distinct deactivate operation, returns 202 and advances `deletion in progress` → `deleted`. A DELETE that arrives before activation completes is accepted at once; OEG publishes the deactivate command after the activate completion event. A deleted individual resource remains representable with 200; it is excluded from active collection results.

**C02 (decided, not yet integrated):** TI uses a platform-seeded specification from OEG configuration, as QoD does, and sends `appId` as `application_reference` for SRM to resolve the workload ([ADR-0035](/decisions/0035-qod-session-service-specification.md) amendment). The app registration serves OEG ownership and notification scoping only. The referenced SRM revision predates the TI seed, so TI cannot complete against it. [Contract §11](interface-contract.md#11-network-api-contracts) retains field rules and examples.

@@ -345,7 +345,7 @@ Specification links identify the current rule or open question. Code evidence re
| **C21** Idempotency/concurrent acceptance prevents duplicates | REQ-OEG-07; [§M.3](#m3-idempotency-and-concurrency); [contract §10](interface-contract.md#10-transient-controls-and-delivery-guidance) | OEG SQL UNIQUE(tenant_id,idempotency_key); EAM/TI prechecks and replay paths; unit fakes | Selected EAM replay can mix incoming fields, contrary to the required same-provider changed-request 409 rule; complete fingerprint/active-app-zone uniqueness and replica safety are not proven | Same-provider non-equivalent EAM request reuse requires 409. Define equivalence/error code, replay representation, races/retention and uncertain-ack redelivery versus no-duplicate-publication wording. QoD/TI extension is not implied. |
| **C22** Accepted ADRs are not implementation evidence | [§I.1](#i1-authentication-and-ownership), [§K.2](#k2-traffic-influence), [§M.4](#m4-callbacks); ADR-0047/0048/0053/0063/0066 metadata | Frontmatter status of each record is accepted | Acceptance of a record is not evidence that the selected commits implement every consequence | Track the actual gaps in C03, C11, C20, C23 and the callback/idempotency rows (C07, C10, C21) |
| **C23** Consent is enforced; token/device and subscriber routing are complete | REQ-OEG-15; [overview F2–F4](overview-and-architecture.md#f-open-questions); [platform consent claim](/platform/future-architecture.md) | OEG Location service/schema/mapper; exposed router inventory | No established carrier/claim consent mapping; omitted device422, empty device400; echo fallback guesses; Device Status not exposed | Define product consent, device mapping, authoritative echo and routing metadata; Number Verification remains excluded |
| **C24** Deployment lifecycle details are settled | [Overview OQ-D1–D3](overview-and-architecture.md#f-open-questions); [§J.3–J.4](#j3-multi-zone-deployment) | OEG EAM mapper build_deploy_targets:752–768; service teardown; versioned route stubs | Pins positional, too many400, shorter list unpinned; PATCH/clusters/QoD extend-retrieve/TI update-devices501; aggregate failure cases vary | Treat incidental behaviour as observed; decide pins, PATCH operations, rollback, partial teardown, required broker-acknowledgment set and inline no-command responses |
| **C24** Deployment lifecycle details are settled | [Overview OQ-D1–D3](overview-and-architecture.md#f-open-questions); [§J.3–J.4](#j3-multi-zone-deployment) | OEG EAM mapper build_deploy_targets:752–768; service teardown; versioned route stubs | Pins positional, too many400, shorter list unpinned; PATCH/clusters/QoD extend-retrieve/TI update501; aggregate failure cases vary | Treat incidental behaviour as observed; decide pins, PATCH operations, rollback, partial teardown, required broker-acknowledgment set and inline no-command responses |
| **C26** Deployment readiness and operating policies | [Delivery §P–Q](implementation-and-delivery.md#q-build-and-deployment); [§T–U](implementation-and-delivery.md#t-known-gaps) | OEG core/config.py, Dockerfile, CI; Helm OEG values/templates at selected commits | Production resource sizing, migration/rollback, backup and recovery policies are not established by these implementation defaults. | Define production resources, TLS/ingress, migration/rollback, backup, RPO/RTO and accountable operator; do not assume unmeasured sizing or acceptance. |
| **C27** Correlation is an opaque string of up to 256 characters, but stored in 128 | Vendored CAMARA common XCorrelator; [contract §1](interface-contract.md#correlation-string-boundary), [§9](interface-contract.md#9-data-dictionary) | OEG api/camara/common.py:7–12; api/error_handlers.py:35–52; adapters/database/sql.py:113 | Header validation and storage lengths disagree; generated UUIDs fit, but accepted 129–256-character caller values may fail persistence. Exact response/escaped side effects were not tested. | Align external validation, storage and migration without silent truncation; decide/verify async failure behaviour. |
| **C28** Combined CPU/GPU resource totals sum; topology merge is not defined | [§J.1](#j1-registration); [contract §6](interface-contract.md#combined-pools-and-topology-limits); [ADR-0019](/decisions/0019-gpu-accelerator-units-fixed-not-camara-sourced.md) | OEG application/mappers/edge_application_mapper.py:563–608; GPU-only mapper tests:776–824 | Selected GPU values overwrite CPU/memory instead of summing. CPU topology wins when present, GPU topology supplies minima otherwise; GPU minimum memory is appended. No agreed combined-topology precedence is established. | Preserve required totals and fix or resolve the implementation mismatch. Decide topology precedence and add combined/GPU-only verification. |