Files
tools-legacy/openspec/changes/archive/2026-10-06-cropper-token-auth/design.md
T

52 lines
2.1 KiB
Markdown
Raw Normal View History

# Design
## Context
See proposal.md. The a2loft `cropper-token-auth` change adds token mode to the
profile-picture endpoints: `Authorization: Bearer <pb token>`, identity from
the token's phone, authorized with OpenFGA `crop_image` on `domain:<code>` then
`domain:idid`. This change consumes it.
## Goals / Non-Goals
**Goals:** the cropper saves with the session token and no OTP; the save's
domain is a2loft's own record of the picture; the panel is truthful about the
profile's domain.
**Non-Goals:** the fingerprint wizard's OTP flow; the cropper's lookup (there
is none — pictures come from the queue); removing OTP support in a2loft.
## Decisions
1. **Token sent from the server**, never exposed to the browser beyond the
page's existing injected session: the proxy attaches
`Authorization: Bearer ${req.session.token}`.
2. **Domain from a2loft, not the client**: `dims/picture/{uploadId}` is the
record of the picture; its `domainCode` is the profile's identity domain and
its `domain` is the picture target (`core`). Sent as `domainCode`, displayed
as both. Falls back to the queue item's label when a2loft has no record
(custom ids), guarded by a path-safety pattern.
3. **The `core → uc` alias is deleted**: `core` is a2loft's own pseudo-domain
(special-cased in `getUserByPhoneAsync`/`updatePicture`), so rewriting it —
as the old bot did for its own calls — changed attribution and the
notification. Authorization no longer depends on the domain, so no alias is
needed.
4. **Queue loads are enriched** with `domainCode` for display (one extra
read-only a2loft call per picture).
## Risks / Trade-offs
- [a2loft record unavailable for an upload] → falls back to the queue label
under the path-safety check; the save still carries the token for authz.
- [Operators outside the domain's super-users] → irrelevant now: the OpenFGA
check with the `domain:idid` fallback authorizes them.
## Migration Plan
Deploy a2loft first (dual-mode, no client change), then this change; the
cropper saves without an OTP. Rollback = revert the proxy and re-add the field.
## Open Questions
None.