Public read access and server-rendered page HTML #56
Labels
No Label
area:auth
area:docs
area:export
area:ops
area:storage
area:supply-chain
auth
backend
blocked
collab
deployment
docs
effort:L
effort:M
effort:S
frontend
plugins
qa
vs-nfd
vs-nfd:blocker
No Milestone
No project
No Assignees
2 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: stwaidele/dorfteich#56
Loading…
Reference in New Issue
Block a user
No description provided.
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Context
Non-authenticated visitors read what public grants allow (vision); crawlers and the PDF exporter need server-rendered HTML (ADR 0005/0009).
Scope
Anonymous request path: the auth guard resolves 'public' subject grants; SPA renders public ponds/pages read-only (no editor bundle loading for anonymous). Server endpoint
GET /public/:pondSlug/:pageSlugrendering full HTML (shareddocToHtml, pond fonts, minimal chrome, canonical link) used for crawlers (proxy rule documented) and reused by PDF export in M6. Sidebar/search for anonymous users show only public content.Acceptance criteria
Technical notes
Dependencies
Depends on #52.
Size: ~1.5 days
Conventions: English code/comments, clear human-readable code, no hard-coded UI strings (ADR 0012, add
deanden), permission checks only via the shared guard (docs/architecture/permissions.md). Read the referenced ADRs before starting.Umgesetzt in
fc41c91(Claude Opus 4.8), Pipeline komplett grün (CI + CD: Deploy Test, Smoke, Int-Promotion — auf dem inzwischen wieder gesunden Runner). Live auf Int verifiziert.Was #56 liefert
public/:GET /public/:pondSlug/:pageSlugliefert ein vollständiges, in sich geschlossenes HTML-Dokument (Content-Cache + minimale Chrome + Canonical-Link, kein session-abhängiger Inhalt) für Crawler/PDF-Export;…/contentliefert JSON für die SPA. Beide@Public(), Auflösung despublic-Subjekts über den geteilten Resolver — verweigert/fehlend → 404 (nicht-öffentliche Seiten verraten ihre Existenz nie). Bild-Nodes (data-file-id) werden zu/api/v1/media/:fileIdaufgelöst.GET /media/:fileIdist ebenfalls@Public(), sodass eingebettete Bilder öffentlicher Seiten für Anonyme streamen; der Attachment-Guard gated weiter auf denpublic-Grant (nicht-öffentlich → 404).PublicPageViewunter/public/:pondSlug/:pageSlug(außerhalb des Auth-Guards) rendert das Server-HTML — bewusst ohne den kollaborativen Editor zu importieren, sodass Anonyme kein Editor-Bundle laden. Neuerpublic-i18n-Namespace (de+en).Acceptance criteria
Live-Checks (Int): anon HTML ohne Grant → 404; mit Public-Grant → 200
text/html(voll gerendert); content JSON → 200; nach Entzug → 404.Tests:
public.e2e.db.test.ts(HTML+JSON, non-public 404, Grant-Entzug 404); Browser-public-Pack (anon liest Public-Seite + Bild via SPA; non-public → not found) mit eigenem CI-Step.Hinweis: Anonyme Sidebar/Suche über public-Content ist nicht Teil dieses Commits — der Zugriffspfad läuft über direkte
/public/…-Deep-Links; kann bei Bedarf als Folge-Issue ergänzt werden.