feat(portal): VPN Landing Portal (Roadmap #6) — Phase 1 - #175
Merged
Merged
Conversation
… + deterministic test
…P-safe state CSS, API config gating
… domain test assertions
…me host, prune dead i18n key, strengthen tests, cleanups
…+ plain includes)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
VPN Landing Portal (Roadmap #6) — Phase 1
Personalisierte, zero-login VPN-Startseite unter dem internen
home.<vpn-domain>(Captive-Portal-Stil). Ein verbundener Peer sieht nur seine eigenen Daten: Gerätestatus, Traffic-Verlauf und die Dienste, die er erreichen darf. Eigenes Design-System (Dark / Light „Papier"), self-hosted Fonts.Umgesetzt strikt im Phase-1-Scope (TDD, subagent-getrieben, zweistufiges Review pro Task + finales Whole-Branch-Review).
Scope-Entscheidungen (vom Owner während der Umsetzung getroffen)
Widgets (3)
Pro Widget: Loading-Skeleton / unidentified-Fallback / Error+Retry-Zustände.
Security-Modell (make-or-break)
Identität wird ausschließlich etabliert, wenn der Request über das interne
home.<domain>-Caddy-Site kommt:remote_ip), strippt jede vom Client gesetzteX-GC-Portal-Peer-IPund setzt sie aus der echten TCP-Quelle ({http.request.remote.host}).portalIdentityverlangt zusätzlich eine Loopback-Verbindung UNDreq.hostname === home.<domain>.req.ip/X-Forwarded-Forwerden nie für Identität vertraut./api/v1/client/*bleiben unverändert; die Identitäts-Brücke gilt nur auf/api/v1/portal/*.Weitere Bausteine
portal.enabled+ Per-Widget-Toggles (alle 3 Themes), server-seitig gegated (deaktiviert → 404).home.<domain>→ Gateway-IP.home.<domain>nutzt für interne TLDs den internen Caddy-CA-Issuer.Finales Whole-Branch-Review (behoben in diesem PR)
portalIdentity+ Header-Strip auf dem Management-vhost; Regressionstests).home.<domain>jetzt in der TLS-Automation; portal.js-injiziertes<style>(CSP-blockiert) inportal.cssverschoben; Portal-API durchportalConfiggegated.Bekannte Follow-up-Minors (nicht blockierend)
GC_DNS_DOMAINeine öffentliche TLD ist, würdehome.<domain>öffentliches ACME versuchen, ist aber internal-only → ggf. internen Issuer für den home-Host erzwingen (Defaultgc.internalist unkritisch).fallbackGateway;/devicenutztgetAll({limit})-Sentinel.Tests
Doku
3-teiliges Batch unter
/root/Dokumentation/gatecontrol/vpn-landing-portal/(FAQ + Dokumentation + Knowledge-Base), local-only.🤖 Generated with Claude Code