carlos / platform Public

Merge worktree-route-hostnames (#151) — one claim writer, one wire contract

#151's internal/domains claim surface (AttachClaim/DetachClaim/ListClaims,
NormalizeAliasHost, HostDenied, ErrHostUnavailable) supersedes the interim
internal/domainclaim stub, and its /api/cli domains door + carlos domains
CLI pin the wire: POST /domains with a JSON body (200 {host,route,created}),
DELETE /domains/{host} (always-200 {host,removed}), GET rows carrying
status/dns_status/cert_expires_at. Resolved in their favour throughout:

- apimode.go: their apiDomainRecord/domainAttach/domainDetach/domainList
  land; my apiDomain client is folded in — domainAttach grows optional
  kind/channel body fields (deploy's first-route extras), domainList keeps
  the domainListError status wrapper deploy's degrade paths read, and the
  record shape gains the additive guidance field.
- internal/domainclaim is DELETED; the attach/detach core, Settings list
  and every test now speak internal/domains. Same-owner re-attach is now
  idempotent (their titogo contract) instead of a 409; the neutral refusal
  is "hostname unavailable" everywhere; audit + serial gate on an actual
  write (their changed rule).
- domainpolicy.go is DELETED: shape is NormalizeAliasHost, platform space
  is HostDenied over deniedDomains() (origin + apps domain + redirect
  hosts + CONSOLE_DENY_DOMAINS) — one validation spot, both doors.
- their POST handler gains the kind=static first-route branch: an app with
  no ready route short-circuits route resolution into the shared
  attachDomain core (claim + declared static provision record); route and
  kind together are a 400. GET rows compute guidance exactly as the
  Settings page does (domainGuidance, EdgeIPs).
- deploy.go / deploy_test.go adapt to the pinned wire (dns_status,
  POST-body attach, 200-not-201, 'carlos domains list -app' wording).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Paul Campbell e79d0d6d8b9ac650303669cba6643eb566912371 parent be3f9c4parent 3950833
37 files changed, +4366 −506
  • apimode.go +86 −49
  • cmd/console/main.go +20 −0
  • deploy.go +17 −17
  • deploy_test.go +45 −38
  • docs/superpowers/plans/2026-08-12-route-extra-hostnames.md +548 −0
  • docs/superpowers/specs/2026-08-12-route-extra-hostnames-design.md +288 −0
  • domains_cli.go +150 −0
  • domains_cli_test.go +393 −0
  • internal/console/apidomains.go +388 −0
  • internal/console/apidomains_test.go +480 −0
  • internal/console/appdomains_test.go +6 −6
  • internal/console/appsettings.go +5 −2
  • internal/console/authcli.go +9 −2
  • internal/console/domainattach.go +101 −56
  • internal/console/domainattach_test.go +70 −46
  • internal/console/domainpolicy.go +0 −30
  • internal/console/domainpolicy_test.go +0 −27
  • internal/console/server.go +9 −0
  • internal/console/view.go +1 −1
  • internal/domainclaim/domainclaim.go +0 −96
  • internal/domainclaim/domainclaim_test.go +0 −106
  • internal/domains/aliases.go +74 −0
  • internal/domains/aliases_test.go +245 −0
  • internal/domains/claims.go +251 −0
  • internal/domains/claims_test.go +256 −0
  • internal/domains/reconcile.go +43 −10
  • internal/domains/reconcile_test.go +77 −0
  • internal/edge/alias_test.go +277 −0
  • internal/edge/edge.go +35 −1
  • internal/edge/storedoor.go +43 −7
  • internal/edge/storedoor_test.go +20 −0
  • internal/host/agent.go +21 −3
  • internal/registry/registry.go +121 −3
  • internal/registry/registry_test.go +186 −0
  • internal/status/snapshot.go +59 −6
  • internal/status/status_test.go +38 −0
  • main.go +4 −0
apimode.go

Loading diff…

cmd/console/main.go

Loading diff…

deploy.go

Loading diff…

deploy_test.go

Loading diff…

docs/superpowers/plans/2026-08-12-route-extra-hostnames.md

Loading diff…

docs/superpowers/specs/2026-08-12-route-extra-hostnames-design.md

Loading diff…

domains_cli.go

Loading diff…

domains_cli_test.go

Loading diff…

internal/console/apidomains.go

Loading diff…

internal/console/apidomains_test.go

Loading diff…

internal/console/appdomains_test.go

Loading diff…

internal/console/appsettings.go

Loading diff…

internal/console/authcli.go

Loading diff…

internal/console/domainattach.go

Loading diff…

internal/console/domainattach_test.go

Loading diff…

internal/console/domainpolicy.go

Loading diff…

internal/console/domainpolicy_test.go

Loading diff…

internal/console/server.go

Loading diff…

internal/console/view.go

Loading diff…

internal/domainclaim/domainclaim.go

Loading diff…

internal/domainclaim/domainclaim_test.go

Loading diff…

internal/domains/aliases.go

Loading diff…

internal/domains/aliases_test.go

Loading diff…

internal/domains/claims.go

Loading diff…

internal/domains/claims_test.go

Loading diff…

internal/domains/reconcile.go

Loading diff…

internal/domains/reconcile_test.go

Loading diff…

internal/edge/alias_test.go

Loading diff…

internal/edge/edge.go

Loading diff…

internal/edge/storedoor.go

Loading diff…

internal/edge/storedoor_test.go

Loading diff…

internal/host/agent.go

Loading diff…

internal/registry/registry.go

Loading diff…

internal/registry/registry_test.go

Loading diff…

internal/status/snapshot.go

Loading diff…

internal/status/status_test.go

Loading diff…

main.go

Loading diff…