Changes for decisions/0006-oeg-db-schema-consolidation.md: 1 added line, 1 removed line.
Original line number
Diff line number
Diff line
@@ -9,7 +9,7 @@ status: "accepted"
# ADR-0006: `oeg_db` schema — the flow docs' schema is authoritative; `app_registrations` is the CAMARA app record
**Status:** accepted
**Status:** accepted — "client identity is the JWT `client_id` (= `tenant_id`)" is amended by [ADR-0048](/decisions/0048-platform-roles.md): `tenant_id` is the token's `organization` claim, else its `sub`, and `app_provider_id` is the `sub`; `api_subscriptions` is reserved for per-product quota and validity. Everything else stands
Changes for decisions/0035-qod-session-service-specification.md: 1 added line, 1 removed line.
Original line number
Diff line number
Diff line
@@ -9,7 +9,7 @@ status: "accepted"
# ADR-0035: A QoD session references a single platform-seeded service specification
**Status:** accepted
**Status:** accepted — "per-tenant entitlement layers on through `api_subscriptions`" is amended by [ADR-0048](/decisions/0048-platform-roles.md): access to QoD is the `quality-on-demand` product grant, enforced through token scopes; `api_subscriptions` is reserved for per-product quota and validity. Everything else stands
The Roles table in [platform/architecture.md](/platform/architecture.md) lists two roles,
`app-provider` and `operator`. The portal backend additionally checks `platform-admin`, which the
realm did not define, so any route guarded only by it refused every user.
The platform has no mail server: nothing is sent by email, so there are no verification links and
no self-service password reset. A person has to reset passwords and fix accounts. That work needs
an owner, and it should not fall to operators by default: an operator who can manage users can
grant themselves roles or take over another account, which mixes running the platform with
controlling who may use it.
Helm attaches every CAMARA scope as a default scope of the portal client, so every user's token
carries all of them. Anyone who registers can call every API, including Location Retrieval, which
locates any device whose number the caller sends. Local development needs that openness; a
deployment that real developers use should grant access deliberately.
Tenancy was left open. OEG reads the token's `organization` claim and falls back to `sub`, while
ADR-0006 and the persistence model still say `tenant_id` is the JWT `client_id`, which no
component does. Two places also claim to decide who may call what: token scopes, which OEG checks
per operation, and `api_subscriptions`, a table OEG never populates.
## Decision
1.**Realm `oop` has exactly three realm roles.**
| Role | Who | Can do |
|---|---|---|
| `app-provider` | Developers (application providers; "Developer" in the UI) | Register and deploy apps, call CAMARA/TMF APIs through OEG for the products granted to them, see their own resources |
| `operator` | People who run the platform | Manage catalog, zones, domains and federation; see all operations |
| `platform-admin` | A few trusted people | Manage users through the portal: reset passwords, grant and revoke roles and products |
2.**Every new user, including self-registered ones, gets `app-provider` immediately** (the realm's
default role). There is no approval step for the role.
3.**`platform-admin` does not imply `operator`** and vice versa (no composite roles). One person
may hold both.
4.**User administration goes through Keycloak's Admin API using a dedicated confidential client,
`oop-portal-admin`,** whose service account holds only `realm-management``manage-users`,
`view-users`, `query-users` and `view-realm` in realm `oop`. The portal authorizes its user
pages with `platform-admin`; people never receive Keycloak administration rights through the
portal. `manage-users` can map any realm role, so the portal must restrict which roles its
admin pages offer.
5.**API access is granted per API product.**
- The API products are `edge-application-management`, `quality-on-demand`,
`location-retrieval` and `traffic-influence`. Each is a client role of the same name on the
`oeg` client. Client roles, so decision 1 still holds.
- Each CAMARA client scope has a role scope mapping to its product's role. Keycloak puts a scope
in a token only when the user, or the service account behind a client, holds that role. OEG
keeps checking scopes per operation and knows nothing about products.
- In normal mode a new user holds no product role. An administrator grants a product by adding
the user to that product's group.
- A deployment may list products every new user receives (a realm default group). The list is
empty by default, and `location-retrieval` may not be on it.
- A machine client holds `app-provider` and the product roles of the products it is entitled to.
6.**Tenancy is the token's `organization` claim, or its `sub` when there is none.** A
`platform-admin` sets `organization` on the user. `app_provider_id` is the token's `sub`.
Neither is a role.
7.**Token scopes are the only access check in Release 2.**`api_subscriptions` stays in OEG's
schema for per-product quota and validity, unpopulated until a release needs them.
8.**Development mode switches login off for the whole platform.** Helm's `global.auth.enabled:
false` sets the portal backend to `AUTH__SECURITY_MODE=none`, where every request acts as a
development user holding every role, and OEG to `KEYCLOAK_SETTINGS__ENFORCEMENT_ENABLED=false`,
where failed checks are logged instead of rejected. It is allowed only when the public host is
`localhost` or `127.0.0.1`. Normal mode always applies decisions 1–7.
9.**These are not roles:**
-*Federation partners* — realm `federation`, identified by client (`azp`) and the `fed-mgmt`
Changes for decisions/index.md: 1 added line, 0 removed lines.
Original line number
Diff line number
Diff line
@@ -49,4 +49,5 @@ the reasoning lives here. Never renumber; supersede instead (see the record-deci
*[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)
*[ADR-0048](0048-platform-roles.md) - three realm roles (app-provider, operator, platform-admin); new users get app-provider but call only the API products granted to them (each CAMARA scope gated by a product role); tenancy is the `organization` claim, else `sub`; development mode switches login off on localhost (amends ADR-0006's tenant identity and ADR-0035's entitlement note)
*[ADR-0062](0062-zone-state-uses-camara-inactive.md) - `zone.state` uses CAMARA's `active`/`inactive`/`unknown` (was `offline`), so OEG passes the zone status filter and value through unmapped; domain, capability and control-path-binding states keep `offline`