image-cropper capability added; tools-app landing + config requirements updated (internal /cropper link, credentials-via-env carve-out).
80 lines
3.9 KiB
Markdown
80 lines
3.9 KiB
Markdown
# Design
|
|
|
|
## Context
|
|
|
|
`id-image-bot` is three things: a Telegram intake bot (handlers disabled in
|
|
code), a picture-review pipeline (Azure queue `id-images`, Minio `files`
|
|
bucket, nodered review/process endpoints), and the operator web tool ("Smart
|
|
Photo Editor": Vue 2 + vue-croppa, phone/OTP login against a2loft). Only the
|
|
web tool moves; the bot and its deployment stay. The a2loft save route
|
|
(`POST /:domainCode/profile/picture`) accepts only `?phone=&otp=` — no key
|
|
variant — so the operator OTP survives, but only at save time. See proposal.md
|
|
for motivation.
|
|
|
|
## Goals / Non-Goals
|
|
|
|
**Goals:**
|
|
- One login story: YOUreka session everywhere; the cropper adds only a
|
|
save-time OTP (a2loft's requirement).
|
|
- Uniform `crop_image` authorization over every proxied cropper endpoint,
|
|
cheap for the portal (read cache, live at save).
|
|
- Faithful behavior: same queue/review/nodered flows and review-reason list.
|
|
|
|
**Non-Goals:**
|
|
- Moving the Telegram bot; decommissioning `spxa.yrka.app`.
|
|
- Changing the review/reject workflow or the review-reason catalog.
|
|
- Replacing toastr/swal UX patterns wholesale.
|
|
|
|
## Decisions
|
|
|
|
1. **Namespaced router, `tools/cropper.js` with DI.** `createCropperRouter({
|
|
minio, queue, fetch, requireApi, cropGate, a2loftBase, ... })` — the same
|
|
injectable pattern as the app factory, so tests fake minio/queue/upstreams.
|
|
Mounted at `/cropper` in server.js; the UI uses relative request paths.
|
|
2. **Unified login.** The bot app's phone+OTP middleware validated every
|
|
request; here the YOUreka session replaces it, and the one a2loft call that
|
|
needs an OTP (picture save) takes an operator-entered OTP forwarded with the
|
|
session phone and the picture's domain. Phone prefill from `/auth/session`.
|
|
3. **`crop_image` gate with read cache.** `permit.js` grows `cropPermission(
|
|
phone, {force})` beside the domain checker: same verifyOnce plumbing,
|
|
`relation: 'crop_image'`, object `domain:idid`, no fallback; results cached
|
|
per phone for 5 minutes, save forces live. Router-level middleware covers
|
|
every cropper route uniformly.
|
|
4. **Credentials via env, URLs hardcoded.** `MINIO_ACCESS_KEY`,
|
|
`MINIO_SECRET_KEY`, `AZURE_STORAGE_CONNECTION_STRING`,
|
|
`NODERED_HTTP_USERNAME`, `NODERED_HTTP_PASSWORD`, `CARVEKIT_API_KEY` — same
|
|
names the bot app used, so an existing `.env` is drop-in. Clients are built
|
|
only when the env is present; without it the router answers 503 and the
|
|
rest of the app is unaffected.
|
|
5. **Restyle to the tools design language.** Same stylesheet and panel
|
|
structure as `/fingerprint` (navbar, step chips, badges, buttons); toastr
|
|
stays for toasts. No behavior change beyond namespacing and auth.
|
|
6. **Native `FormData`** (Node 22) replaces the `form-data` dependency for the
|
|
cleanup proxy.
|
|
|
|
## Risks / Trade-offs
|
|
|
|
- [a2loft `validateOtp` may not recognize the YOUreka session phone format] →
|
|
the fingerprint walkthrough already saw a2loft accept the session phone on
|
|
lookups; the field pass confirms on the save path before cutover.
|
|
- [Cached crop gate lets a revoked operator act for ≤5 minutes] → reads only;
|
|
the save verifies live, and a2loft's OTP check remains the hard gate.
|
|
- [Review/process endpoints depend on nodered availability] → unchanged from
|
|
the bot app; failures surface as route errors, not crashes.
|
|
- [Two auth domains (mnet/ucth) disappear from the login] → the save validates
|
|
against the picture's domain; the field pass exercises a real item.
|
|
|
|
## Migration Plan
|
|
|
|
1. Land the cropper in `tools/` while `id-image-bot` keeps running unchanged.
|
|
2. Field pass: login → gate → load a real queued item (or by ID) → crop →
|
|
clean → save with OTP; confirm the picture lands in a2loft.
|
|
3. Repoint the landing card (done in the same change); leave `spxa.yrka.app`
|
|
running until the team confirms the new home.
|
|
4. Rollback: the old deployment still serves the tool.
|
|
|
|
## Open Questions
|
|
|
|
None — auth unification, secret handling and scope were confirmed with the
|
|
operator.
|