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

docs: amend ADR-0034 and add ADR-0047 to clarify terminal-record read behavior per CAMARA schema

parent 6a0be1d6
Loading
Loading
Loading
Loading
+7 −4
Changes for decisions/0034-network-capability-delete-is-async.md: 7 added lines, 4 removed lines.
Original line number Diff line number Diff line
@@ -9,7 +9,7 @@ status: "accepted"

# ADR-0034: Network-capability delete is async, and its completion is consumed to a terminal record state

**Status:** accepted
**Status:** accepted — the blanket "reads of a terminal record return `404`" rule and step 3's "returns `204`" are amended by [ADR-0047](/decisions/0047-terminal-record-read-follows-camara-schema.md) (each family follows its own vendored CAMARA schema: Traffic Influence reads a deleted policy as `200` and deletes with `202`); everything else stands
**Date:** 2026-08-05
**Affects:** [oeg/persistence-model.md](/oeg/persistence-model.md), [oeg/interface-contract.md](/oeg/interface-contract.md), [srm/interface-contract.md](/srm/interface-contract.md)

@@ -64,9 +64,12 @@ QoD. Because step 3 moves the record off that state synchronously, a repeat `DEL
idempotent — it neither re-publishes nor re-notifies. For QoD this satisfies the spec rule that no
event is sent when the status was already `UNAVAILABLE`.

**Read behaviour after deletion.** CAMARA has no representation for a deleted session or policy,
so reads of a terminal record return `404`. The row is retained for audit and for the
`operations` history; it is not removed.
**Read behaviour after deletion.** Reads of a terminal record return `404` where CAMARA has no
representation for a deleted resource — true of QoD, whose `QosStatus` enum is
`REQUESTED`/`AVAILABLE`/`UNAVAILABLE`. Traffic Influence's `state` enum does document
`deletion in progress` and `deleted`, so it reads them back as `200`
([ADR-0047](/decisions/0047-terminal-record-read-follows-camara-schema.md)). Either way the row is
retained for audit and for the `operations` history; it is not removed.

## Consequences

+115 −0
Changes for decisions/0047-terminal-record-read-follows-camara-schema.md: 115 added lines, 0 removed lines.
Original line number Diff line number Diff line
---
type: Decision Record
title: "ADR-0047: Terminal-record read behaviour follows each family's own CAMARA schema — Traffic Influence returns 200 with `state: deleted`, QoD stays 404"
description: "ADR-0034's rule that reads of a terminal record return 404 rests on CAMARA having no representation for a deleted resource. That holds for QoD's qosStatus enum and not for Traffic Influence, whose state enum documents 'deletion in progress' and 'deleted'. The rule is scoped to families whose vendored schema has no deleted representation."
tags: [adr]
timestamp: 2026-09-09T00:00:00Z
status: "proposed"
---

# ADR-0047: Terminal-record read behaviour follows each family's own CAMARA schema

**Status:** proposed
**Date:** 2026-09-09
**Affects:** amends [ADR-0034](/decisions/0034-network-capability-delete-is-async.md), [oeg/interface-contract.md](/oeg/interface-contract.md), [srm/interface-contract.md](/srm/interface-contract.md) §E.1

## Context

[ADR-0034](/decisions/0034-network-capability-delete-is-async.md) states:

> **Read behaviour after deletion.** CAMARA has no representation for a deleted session or
> policy, so reads of a terminal record return `404`.

The premise is a claim about the vendored CAMARA schemas, and it is true of only one of the two
families the sentence covers.

**CAMARA QoD** (`qod-api.yaml`, `info.version: 0.10.1`) — `QosStatus`:

```
['REQUESTED', 'AVAILABLE', 'UNAVAILABLE']
```

Nothing represents a deleted session. `404` is the only answer the schema permits, and ADR-0034
is correct for QoD.

**CAMARA Traffic Influence** (`traffic_influence.yaml`, `info.version: wip`) — `state`:

```
['ordered', 'created', 'active', 'error', 'deletion in progress', 'deleted']
```

with the enum's own description tying two of those values to the DELETE call:

> When the DELETE method is invoked the state is `'deletion in progress'`. After the resource is
> deleted (as a consequence of the previous invocation of the DELETE method) the state is
> `'deleted'`.

Under a blanket `404` those two values are unobservable: no caller could ever see a state the
specification defines and describes. The API also notifies `onTrafficInfluenceChanged` with the
full resource, so a subscriber is told `state: deleted` by callback while a read of the same
resource denies it exists.

ADR-0034 was written primarily about QoD and generalised the phrase "session or policy" without
checking Traffic Influence's enum.

A second, smaller instance of the same generalisation: ADR-0034 step 3 says `DELETE` "returns
`204`". CAMARA QoD documents `204`; CAMARA Traffic Influence documents `202` ("Deletion in
progress"). Both implementations already follow their own specification.

Options considered:

- **(a) Keep `404` uniformly.** Consistent across families and needs no change. Rejected: it
  contradicts the vendored Traffic Influence schema, which the platform treats as the governing
  contract for northbound shapes, and renders two documented enum values unreachable.
- **(b) Return `200` uniformly**, exposing a deleted representation for both. Rejected: QoD's
  schema has no value to put in `qosStatus`, so there is nothing to return.
- **(c) Let each family follow its own vendored schema.**

## Decision

Option (c). ADR-0034's read rule is scoped: **reads of a terminal record return `404` only for
families whose vendored CAMARA schema has no representation of a deleted resource.**

1. **QoD is unchanged.** `GET /sessions/{id}` on a terminal row returns `404`.
2. **Traffic Influence returns `200`** with the record's own `state` (`deletion in progress` or
   `deleted`) for `GET /traffic-influences/{trafficInfluenceID}`.
3. **The collection excludes deleted policies.** `GET /traffic-influences` omits `deleted` rows,
   matching SRM's `GET /network-capabilities` collection form, which excludes terminated and
   failed realizations. `error` and `deletion in progress` remain listed: both are
   still-present resources a caller may need to find in order to delete.
4. **SRM read failures are interpreted against the local state.** SRM holds a
   `capability_instance` only while the policy is realized, so a `404` from
   `GET /internal/network-capabilities/{id}` is expected before activation completes and after
   teardown starts, and is not an error. A `404` while OEG's record is `active` means SRM lost a
   live policy and surfaces. Transport failures always surface as `503`.
5. **`DELETE` status codes follow each family's specification** — `204` for QoD, `202` for
   Traffic Influence. ADR-0034 step 3's "`204`" is read as the QoD case, not a platform rule.

Everything else in ADR-0034 stands: delete is async, the deactivate completion is consumed, the
record reaches a terminal state, and repeat deletes neither republish nor re-notify.

## Consequences

What becomes easier:

- Traffic Influence's `deletion in progress` and `deleted` states become observable, as its
  specification describes, and the callback and the read agree.
- Each family's northbound behaviour is derivable from its vendored spec rather than from a
  cross-family rule that may not apply.

What becomes harder:

- The two families now differ in a way a reader may mistake for an inconsistency. Both call
  sites carry a comment naming this ADR and the enum difference that drives it.
- `GET` by id and the collection now disagree about deleted policies by design. This mirrors SRM's
  own collection semantics but is a rule someone must know rather than infer.

**Open question, not resolved here: retention.** A deleted Traffic Influence policy is readable by
id indefinitely, because nothing expires the row. CAMARA does not say how long a deleted resource
remains addressable. The row is retained for audit regardless (ADR-0034), so the question is only
how long it stays *readable*. Revisit when a data-retention policy exists for `oeg_db`, or if the
table's growth becomes material.

**Generalisation to future families.** Any new CAMARA family added to OEG must have this checked
against its own schema rather than inherited: if its resource representation carries a deleted
state, reads return it; if not, reads return `404`.
+1 −0
Changes for decisions/index.md: 1 added line, 0 removed lines.
Original line number Diff line number Diff line
@@ -48,3 +48,4 @@ the reasoning lives here. Never renumber; supersede instead (see the record-deci
* [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
* [ADR-0045](0045-pin-narrows-candidates-not-probing.md) - a zone/domain pin narrows the device-targeted candidate set rather than bypassing target probing; probing is triggered by how many candidates survive the pin (amends ADR-0038's unpinned scoping)
* [ADR-0047](0047-terminal-record-read-follows-camara-schema.md) - terminal-record read behaviour follows each family's own vendored CAMARA schema: Traffic Influence returns 200 with `state: deleted`, QoD stays 404 (amends ADR-0034's blanket 404 rule and its 204 delete code)
+6 −2
Changes for srm/interface-contract.md: 6 added lines, 2 removed lines.
Original line number Diff line number Diff line
@@ -595,8 +595,11 @@ diagnostics, trusted catalog/admin, and synchronous query/data only.
  Same response shape as the single form, as a list; ids not found are omitted rather than
  failing the whole call. Serves OEG's `GET /traffic-influences?appId=...`, translating CAMARA
  `appId` to `service_specification_id` at the mapper boundary (ADR-0011).
  Terminated and failed realizations are excluded unless explicitly requested — CAMARA has no
  representation for a deleted session or policy, so OEG maps their absence to `404` (ADR-0034).
  Terminated and failed realizations are excluded unless explicitly requested. How OEG maps that
  absence depends on the family's own CAMARA schema: `404` where the schema has no deleted
  representation (QoD), and the record's own state where it does — Traffic Influence reads a
  deleted policy back as `200` and omits it from its collection instead
  ([ADR-0047](/decisions/0047-terminal-record-read-follows-camara-schema.md), amending ADR-0034).
- `GET /operations/by-operation-id/{operation_id}` — latest `service_order` row +
  derived inventory state; read-only; tenant-scoped; RFC 7807 on 404.

@@ -876,3 +879,4 @@ component (platform/future-architecture.md §6.1, ADR-0044).
| 2.0 | 2026-07-07 | OOP Release 2.0. |
| 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-0047). 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`. |