fix(eam): show refused attempts and hide confirmed deletions
Instance list, refused partner deployment:
sequenceDiagram
participant AP as App Provider
participant OEG
participant SRM
participant FM
AP->>OEG: POST /appinstances (Paris zone)
OEG-->>AP: 202
OEG->>SRM: command.srm.service.deploy
SRM->>FM: command.fm.service.deploy
FM-->>SRM: partner refused
SRM-->>OEG: event.srm.operation.completed (failed + error)
OEG->>OEG: save failed attempt, release zone
AP->>OEG: GET /appinstances
OEG->>SRM: GET /internal/service-instances
SRM-->>OEG: nothing for the refused attempt
Note over OEG: before: attempt missing from the list<br/>now: listed as failed for its App Provider
OEG-->>AP: SRM rows + failed attempt, minus confirmed deletionsApp list (second commit):
flowchart LR
G["GET /apps"] -- "GET /internal/catalog/service-specifications" --> S["SRM specs<br/>(retired specs still listed)"] --> Q{"OEG registration<br/>DELETED?"}
Q -- "yes" --> X["left out<br/>(same as GET /apps/{appId}, 404)"]
Q -- "no, or never registered here" --> L["listed"]flowchart LR
I["fix/instance-list-lifecycle<br/>OEG !43 (this MR)"] -- "targets now" --> A["feat/agreements-relay<br/>OEG !42"] -- "merges first" --> D["develop"]
I -. "retarget after !42 merges" .-> DA partner deployment refused before fulfillment has no runtime instance for SRM to return. Even after OEG consumes the failure, GET /appinstances omitted the accepted attempt. A confirmed delete could also reappear as unknown from an old runtime transaction.
Supplement SRM results with OEG's saved failed attempts, scoped by the original operation's App Provider. Apply app, instance and region filters, retain the requested name, and return SRM's runtime result once when both sources have an instance. Suppress a runtime row when OEG has confirmed that instance as terminated. Historical rows that missed earlier terminal events are not rewritten.
A second commit fixes GET /apps listing an app after DELETE /apps/{appId} answered 204. SRM only retires the specification of an app that ever had instances, and its list still returns it. The list now skips specifications whose registration here is marked deleted, which matches GET /apps/{appId} (404 for the same app). Specifications OEG never registered are listed as before.
The accompanying architecture amendment explicitly changes the previous SRM-only read contract. Please review that decision with this MR. SRM remains the runtime source, and failed attempts receive no invented endpoints or cluster references.
Validation: 1234 unit tests passed, 1 skipped (2 new for the app list); 40 integration tests passed, including provider isolation against Postgres; mypy, ruff and import-linter passed. The portal UI showed two refused attempts as failed, accepted the retry with 202, and removed a successfully deleted Paris instance.
Target feat/agreements-relay to exclude its parent commit from the initial diff; retarget to develop after that merges. The stale-409 fix also requires SRM to emit valid failed completion entries with errors.