Skip to content

feat(routes): Domain-Registry-Bindung — Präfix + verifizierte Basis, Carve-out, Grandfathering, Nudge - #185

Merged
CallMeTechie merged 10 commits into
masterfrom
worktree-feature+routes-registry
Jun 25, 2026
Merged

CallMeTechie merged 10 commits into
masterfrom
worktree-feature+routes-registry

Conversation

@CallMeTechie

Copy link
Copy Markdown
Owner

Routen nutzen die Domain-Registry (Teilprojekt B)

Schließt die 3-teilige Domain-Initiative A → C → B ab. Routen beziehen ihre öffentliche Domain künftig aus der verifizierten Registry statt aus Freitext.

Was sich ändert

  • Präfix + verifizierte-Basis-Dropdown im Create-Wizard und Edit-Modal (alle 3 Themes). Effektiver Host = präfix.basis.
  • Carve-out für nicht-öffentliche TLDs (.internal/.lan/... via bestehendem isPublicDomain): bleiben Freitext, kein Verify (interner CA). Rein-interne Deployments können weiter Routen anlegen.
  • Öffentliche TLDs verlangen eine verifizierte Basis — sonst klarer Feld-Fehler (kein Anlegen).
  • Grandfathering: Bestehende Routen laufen unverändert weiter; Erzwingung nur bei Domain set/change (Create; Update mit geänderter Domain — auch reiner Präfix-Wechsel). Nicht-Domain-Edits an Alt-Routen unberührt.
  • Nudge-Badge (serverseitig berechnet) an öffentlichen Routen mit unverifizierter Basis, mit Link zur Registry. Nicht-öffentliche Routen bekommen nie ein Badge.
  • Kollisions-Guard: neue/geänderte Domain darf nicht den GateControl-Management-Host (config.app.baseUrl) oder den Portal-Host (effectivePortalHost, lazy) übernehmen.

Architektur / Risiko-Minimierung

  • Kein Schema-/Daten-Umbau: routes.domain bleibt der maßgebliche volle FQDN; Caddy/dns-Build-Pfad unverändert. Die Registry-Bindung ist eine Validierungsregel.
  • Erzwingung an EINER Stelle (Routes-API-Layer): Die Policy wird im nutzerseitigen POST/PUT /api/v1/routes-Handler durchgesetzt. Die ursprünglich geplante zusätzliche Service-Layer-Defense wurde nach dem finalen Review bewusst entferntservices/routes.js ist ein geteilter Chokepoint (Service-Bundles u. a.), eine Erzwingung dort hätte interne Aufrufer regressiert. Carve-out-Klassifizierung ist konsistent über Policy + List-API-Flags (domainIsPublic/baseUnverified) + Edit-Pfad-Erkennung (alle serverseitig, keine Client-Reimplementierung von isPublicDomain).

Tests

  • Neu: tests/route_domain_assemble, route_domain_policy, api_routes_registry, routes_registry_ui.
  • Betroffene Bestands-Suites (öffentliche *.example.com-Routen) seeden jetzt eine verifizierte Basis.
  • Lokal verifiziert grün: Feature + Routen-Regression (41/41) und API/External/Bundle-Suites (100/100). CI ist das Gate.

Bekannte Punkte (dokumentiert)

  • Kein jsdom → routes.js-DOM-Verhalten (Dropdown-Befüllung, Vorschau, Edit-Pfad-Erkennung, Submit-Assembly, Badge) ist nur smoke-/manuell geprüft; manueller Durchlauf ist Pflicht-Akzeptanzkriterium vor produktiver Nutzung.
  • A-Wechselwirkung: A's Boot-Seeding nimmt last-two-labels-Basen ALLER Route-Domains, auch nicht-öffentlicher (gc.internal) → diese bleiben dauerhaft pending (Rauschen, kein Funktionsfehler). Folge-Empfehlung: kleiner A-Fix, der !isPublicDomain-Basen überspringt.
  • Edit-Freitext-Pfad konvertiert interne→verifizierte Domain nicht (prefill-only, spec-konform).

🤖 Generated with Claude Code

https://claude.ai/code/session_01Nfanfu8v8xvSMCbuAmd8Sq

…ree-text)

Replace single edit-route-domain input with dropdown+prefix (public routes)
or freetext fallback (internal/stale). Preselects verified base or injects
unverified-legacy option with warning. Remaps all 6 edit-side JS call sites,
migrates data-dns to edit-route-domain-freetext, adds i18n+GC.t for
unverified_base_option and unverified_base_prefix_warning.
Add discreet amber badge to routes where baseUnverified is true — reads
GC.t['routes.unverified_base_badge'] (with tooltip pointing to Settings
→ General → Domains). Badge participates in existing extraTags +N collapse
logic. Both i18n keys added to en/de and all three layout GC.t allow-lists.
@CallMeTechie
CallMeTechie merged commit 4aa6b02 into master Jun 25, 2026
8 checks passed
CallMeTechie added a commit that referenced this pull request Jun 25, 2026
…ring pending rows (#186)

* fix(domains): skip non-public-TLD bases in boot seeding + prune lingering pending rows

Non-public bases (.internal/.lan/...) can never verify against public DNS,
so they lingered as permanent 'pending' noise on the Domains page once B made
them visible. Now they are never seeded, and existing auto-seeded pending
non-public rows are pruned on boot. Verified rows are never touched; routes
read routes.domain directly and nothing FKs to the domains table.

Follow-up to the A→C→B domain initiative (B = PR #185).

* test(domains): use Set.has to dodge CodeQL url-substring FP; prepare delete stmt once
@CallMeTechie
CallMeTechie deleted the worktree-feature+routes-registry branch June 25, 2026 20:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant