image-cropper capability added; tools-app landing + config requirements updated (internal /cropper link, credentials-via-env carve-out).
4.2 KiB
Spec Delta: image-cropper
Purpose
The Image Cropper at /cropper: operators review, crop, clean and save
identity photos submitted for YOUreka ID domain profiles, with every proxied
action authorized by the crop_image relation.
ADDED Requirements
Requirement: Crop permission gate
Access to the cropper SHALL require the crop_image relation on domain:idid
(subsystem idid) for the signed-in operator's phone, verified against the
portal OpenFGA endpoint and failing closed on denial or error. Read paths
(page load, picture loading, background cleanup, dequeue) MAY serve a cached
result for up to 5 minutes; saving SHALL always verify live.
Scenario: Permitted operator opens the cropper
- WHEN an operator with the crop_image relation requests
/cropper - THEN the editor page loads
Scenario: Non-permitted operator is kept out
- WHEN an operator without the crop_image relation requests the cropper page
- THEN the page renders a not-permitted explanation with no editor UI
Scenario: Cached gate on reads
- WHEN a read action occurs within 5 minutes of the operator's last permission check
- THEN the cached result is used without calling the portal
Requirement: Picture loading is gated and namespaced
The cropper SHALL load review pictures only through its namespaced routes
(/cropper/picture/next, /cropper/picture/load/:id,
/cropper/picture/:file_name) behind the session and crop gates. A denied
route SHALL return 403 without contacting the queue, storage, or review
services.
Scenario: Next queued picture
- WHEN the operator requests the next picture
- THEN the route proxies the Azure queue and returns the queue message
Scenario: Denied picture load does not reach services
- WHEN a request without the crop_image relation loads a picture route
- THEN the route answers 403 and makes no upstream calls
Requirement: Background cleanup is gated
The background-cleanup proxy (/cropper/api/removebg) SHALL require the
session and crop gate, forwarding the cropped image to the cleanup service
only for permitted operators.
Scenario: Denied cleanup does not reach the cleanup service
- WHEN a request without the crop_image relation calls the cleanup proxy
- THEN it answers 403 without contacting the cleanup service
Scenario: Cleanup proxies the cleaned image
- WHEN a permitted operator submits a cropped image for cleanup
- THEN the route forwards it to the cleanup service and returns the cleaned image
Requirement: Saving requires a live gate and an OTP
Saving a cropped picture (/cropper/profile/picture) SHALL verify the crop
permission live (bypassing the cache) and SHALL require an OTP from the
operator, forwarding the session phone as the validating identity together
with the OTP and the picture's domain to a2loft. A denied or OTP-less save
SHALL not reach a2loft.
Scenario: Successful save
- WHEN a permitted operator saves with an OTP
- THEN the route verifies the live gate and forwards the picture to a2loft with the session phone, OTP, and picture domain
Scenario: Denied save does not reach a2loft
- WHEN the live crop check denies, or the OTP is missing
- THEN the route answers 403/400 and makes no a2loft call
Requirement: Unified login — no separate artist login
The cropper SHALL NOT implement its own login. The operator's identity comes from the YOUreka session (phone prefilled), the picture's metadata carries the domain, and the only credential the operator supplies is the save-time OTP.
Scenario: Phone prefilled from the session
- WHEN a signed-in operator opens the cropper
- THEN their phone is already known to the page without any login form
Requirement: Cropper credentials come from the environment
The cropper's service credentials (Minio keys, Azure storage connection string, nodered credentials, cleanup-service key) SHALL be read from environment variables. When they are absent, the cropper routes SHALL answer 503 without attempting upstream calls; the application itself SHALL still boot.
Scenario: Unconfigured deployment degrades gracefully
- WHEN the app starts without the cropper credentials
- THEN the other tools work and cropper routes answer 503