ADR 0004 β JWT-only identity on CAP (no SCI profile enrichment) β
Status: Accepted Β Β·Β Date: 2026-04-28 Β Β·Β Deciders: (project team)
Context β
The Java IMS predecessor resolved user identity by taking the XSUAA JWT's subject, then making a synchronous HTTP call to SAP Cloud Identity (SCI) /cps/* endpoints to enrich the profile with display name, email verification state, and role attributes. This gave rich per-request user data at the cost of one out-of-band SCI hop on every authenticated request β plus a hard runtime dependency on SCI availability, and rate limits when the platform's request volume grew.
The CAP rewrite had a fork in the road: keep the SCI enrichment (behaviour parity) or move identity resolution entirely to what's already on the JWT.
Decision β
User identity on the CAP srv comes exclusively from the XSUAA JWT β specifically xs.user.attributes and the standard claim set. No synchronous SCI lookup happens on the request path. Profile enrichment (display name, avatar, verified state) uses whatever the IDP put on the token; where richer data is needed (e.g. bulk backfill), we do it asynchronously outside the request cycle.
Consequences β
- Positive. No SCI latency in the request path. No cascade failure when SCI is rate-limiting or degraded. The srv can be reasoned about as a pure JWT consumer: given a valid token, identity is fully determined without another network hop.
- Positive. Simpler local dev β a hybrid session with
cds binddoesn't need SCI credentials, only an XSUAA binding. - Negative. The token has to carry everything we need. When we discovered author-nudge emails were unbound after migration ([memory: project_ims_author_nudge_emails_unbound]), the fix couldn't be "just call SCI"; it needed a proper async backfill path and a lazy self-heal on next login. We accept that cost.
- Neutral. Any feature that reads a user attribute not on the JWT is a design pause: either the IDP mapping needs to include the attribute, or the feature has to work with what's there. This forces a healthy conservatism about profile scope.
- Neutral. SCI rate limits observed at ~10 concurrent lookups (see memory
feedback_sci_cps_endpoint_rate_limits_aggressively) confirmed the wisdom of keeping SCI off the request path even for async paths.
Alternatives Considered β
- Keep SCI enrichment (parity with Java IMS). Rejected because the reliability and latency cost was material and the CAP rewrite was the moment to reset it.
- Cache SCI lookups per-user in HANA with TTL. Considered as a hybrid. Rejected as an unnecessary layer once we accepted that everything we actually need is already on the token β the cache would exist to defend a hop we no longer take.
- Full profile snapshot on first login, updated by a webhook. Cleaner than caching but requires SCI to reliably deliver webhooks and requires ongoing sync logic. Deferred β may return as an option if attribute needs grow.
References β
- Originating spec: docs/superpowers/specs/2026-04-28-ims-cap-rewrite-design.md
- Architecture: docs/developers/architecture/authentication.md
- Related decision aggregate: docs/developers/reference/design-decisions.md Β§Data + identity