Files
tessera-ctl/.planning/quick/261008-j9f-nextcloud-status-logo-per-http-adresse-h/261008-j9f-SUMMARY.md
T
2026-10-08 14:14:38 +02:00

6.4 KiB

phase, plan, subsystem, tags, requires, provides, affects, tech-stack, key-files, decisions, metrics, status, commits, plan_head_before, plan_head_after, actuals
phase plan subsystem tags requires provides affects tech-stack key-files decisions metrics status commits plan_head_before plan_head_after actuals
quick-261008-j9f 01 nextcloud-status
ssrf
logo
validation
i18n
nextcloud-status
http logo address fetched once by Tessera and stored like an upload
shared SSRF guard (apps/api/src/common/public-url-guard.ts)
code-based form errors (API + web) for the cloud form
favorites (re-export only)
nextcloud-status
added patterns
{ code, message } errors mapped to de/en texts in the web (as in Domains)
created modified
apps/api/src/common/public-url-guard.ts
apps/api/src/nextcloud-status/nextcloud-form-errors.ts
apps/api/src/nextcloud-status/nextcloud-logo-fetch.ts
apps/api/src/nextcloud-status/nextcloud-logo-fetch.spec.ts
apps/api/src/nextcloud-status/dto/nextcloud-instance.dto.spec.ts
apps/web/src/components/nextcloud-status/cloud-form-errors.ts
apps/web/src/components/nextcloud-status/cloud-form-errors.test.ts
apps/api/src/favorites/icon-discovery.service.ts
apps/api/src/nextcloud-status/dto/nextcloud-instance.dto.ts
apps/api/src/nextcloud-status/nextcloud-status.service.ts
apps/api/src/nextcloud-status/nextcloud-status.service.spec.ts
apps/web/src/lib/nextcloud-status-api.ts
apps/web/src/app/(portal)/modules/nextcloud-status/components/CloudForm.tsx
apps/web/src/app/(portal)/modules/nextcloud-status/components/CloudForm.test.tsx
apps/web/src/messages/de.json
apps/web/src/messages/en.json
apps/web/src/messages/umlaut-dictionary.ts
CHANGELOG.md
docs/anleitung-anwender.md
docs/anleitung-administration.md
Only http addresses are downloaded; https stays a browser-loaded logoUrl (D-04)
DTO keeps only type guards whose messages are error codes; length and URL rules live in validateInstanceInput / classifyLogoUrl so they arrive as { code, message }
Web never renders server text; unknown errors fall back to the generic German save/delete text
tasks completed
3 2026-10-08
complete 3 4ff43c2252 166a6fc9d1
tokens tasks commits
60000 3 3

Phase quick-261008-j9f Plan 01: Nextcloud-Status http logo address Summary

An http:// logo address in the Nextcloud cloud form is now downloaded once by Tessera (SSRF-guarded per hop, 8 s total deadline, 1 MiB streaming cap, magic-byte check) and stored in logoData/logoMime like an upload; every error of the form now appears in German (English with the English UI) via stable error codes.

Commits

Task Commit Description
1 (tracer, API) 4432561 shared SSRF guard, fetchLogoImage, error catalogue, DTO codes, service wiring + specs
2 (web) c30a82e client pre-check, code -> de/en mapping, label "Bildadresse" + new hint, umlaut allowlist
3 (docs) 166a6fc CHANGELOG (Geändert + Behoben), both manuals

Measurements

  • Task 1 gate: nextcloud-status + favorites + rls-coverage/inventory: 18 files, 365 tests green; api tsc clean; favorites spec/service/controller byte-identical to 4ff43c2; tenantPrisma call sites still 14.
  • New specs: nextcloud-logo-fetch.spec.ts 16 tests, dto spec 3 tests, service spec 32 tests, web cloud-form-errors.test.ts + extended CloudForm.test.tsx.
  • Full suites: api 137 files / 2525 tests green; web 133 files / 1472 tests green; both tsc --noEmit clean.
  • Biome: clean on all new/changed files (pre-existing findings in untouched favorites files left alone).
  • de/en parity, 12 error keys, label/hint, old keys removed, no Mandant/Lizenz words: "web form ok".
  • Umlaut allowlist addition: Adressen (correct German, in the new hint).

Live probe (rebuilt local stack, admin)

POST instances logoUrl http://127.0.0.1/logo.png -> 400 {"code":"logoFetchInternal", ...German text}
POST instances logoUrl ftp://x                  -> 400 {"code":"logoUrlInvalid", ...}
POST instances customerName ""                  -> 400 {"code":"customerNameRequired", ...}
POST instances customerName 5                   -> 400 {"message":["customerNameRequired"]}  (DTO message = code)
POST instances logoUrl http://example.com/      -> 400 {"code":"logoFetchNotImage", ...}
POST instances logoUrl http://upload.wikimedia.org/...png (follows http->https redirect)
                                                -> 201, hasUploadedLogo true, logoUrl null
GET  instances/:id/logo                         -> 200 image/png

The 201 probe row was deleted again; no "Probe j9f" row remains.

Deviations from Plan

None - plan executed as written. Notes:

  • The user-visible old/new Cloud nicht gefunden message changed to the code-based notFound text on all cloud routes as the plan specified (not a deviation).
  • A rejected file type in the upload picker clears the pending file and shows the error; a subsequent submit clears the error and saves without logo (same behaviour as the existing too-large case).

Known Stubs

None.

Threat Flags

None - the new outbound request surface (logo download) is exactly the one covered by T-j9f-01..05 in the plan's threat model.

Browser steps for the orchestrator (dark mode)

  1. Nextcloud-Status -> edit a cloud -> radio "Bildadresse" shows the new hint (https loaded by browser, http fetched once, internal via "Bild hochladen").
  2. Enter a public http:// image address of a real website, save -> tile shows the logo; reopening the form shows "Bild hochladen" selected (stored like an upload). A working example: http://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png
  3. http://192.168.x.x/logo.png -> German hint pointing to "Bild hochladen", nothing saved.
  4. http address of an HTML page (e.g. http://example.com/) -> "Unter dieser Adresse liegt kein Bild ...".
  5. Empty name, address without http(s) and an ftp:// logo address -> German texts without any request.
  6. https logo address still works as before (browser loads it, logoUrl kept).
  7. Switch the UI to English once and repeat (5) -> English texts.
  8. Favorites: an existing favorite still shows its icon.

Self-Check: PASSED

  • Created files exist (public-url-guard.ts, nextcloud-form-errors.ts, nextcloud-logo-fetch.ts + spec, dto spec, cloud-form-errors.ts + test).
  • Commits 4432561, c30a82e, 166a6fc exist on main (3 commits measured from plan_head_before).