carlos / platform Public

domains attach: no supported way to put the platform's own apex (carloku.com) on a console app Issue closed

Claimed by claude~paul@keymail.dev 3 weeks ago

What I was doing

Moving carloku.com, the Carloku marketing site, off the direct-bucket app bab/carloku and onto a normal console app, bes/website (account carloku). The app deployed cleanly with carlos deploy --account bes --app website --kind static. It serves at https://website.bes.oncarlos.com as a71ce06, byte-identical to the live site.

The last step fails:

$ carlos domains attach --account bes --app website carloku.com
domains attach: that hostname is platform-managed

Why

attachDomain (internal/console/domainattach.go:93) refuses any host that domains.HostDenied matches. Matching is host == entry || HasSuffix(host, "."+entry). On the flagship, the deny list (CONSOLE_DENY_DOMAINS, plus the derived console origin and apps domain) evidently covers carloku.com. That protects console.carloku.com and the rest of the zone, but it also blocks the apex, which is just a marketing site. I couldn't read the box's env, so I'm inferring this from the code. The refusal message is the evidence.

The only route carloku.com has had so far is the direct-bucket ship through the pinfra scripts. That route can't be seen from the console, carlos channels, or carlos domains list.

What I'm asking for

A supported way for the platform operator to attach a hostname inside a platform-managed zone to a specific console app, so the platform's own site can run as an ordinary app. Two possible shapes:

  • the deny list can name an exact host as an exception (allow carloku.com, keep denying *.carloku.com), or
  • an operator-only attach (ops account, or --control-plane style gating) that may claim platform-managed hosts.

I haven't worked around this: no registry or bucket writes, and nothing changed in the deny list. carloku.com is still served by bab/carloku until this lands. DNS for carloku.com is on DNSimple. Once the claim exists, the plan is an apex ALIAS to website.bes.oncarlos.com. Both resolve to 99.81.104.219 today, so the claim is the only missing piece.

The operator confirmed this is needed and widened it. It's a general capability, not a one-off fix for carloku.com: the operator of any CARLOS deployment should be able to claim hostnames in their own platform-managed zones for apps on that deployment.

The flagship (carloku.com, under a deny entry) is just the first case. Tito's deployment has the same shape, with go.tito.io and platform.tito.io on its deny list. So the design should:

  • keep the deny list as the guard that stops members from claiming platform hostnames, which is what it does today;
  • give the operator (whoever holds the deployment's ops/control-plane role) an explicit door through that guard for a named host, with the usual claim, cert, and domains list visibility;
  • never let a member's claim through, including via an operator-created claim that later changes hands.

carloku.com → bes/website is waiting on this and will be the first real use.

Built on branch platform-domain-claims-209 (tip dfeeb389). Full gate green locally; Astra reviewed it over two rounds: one P1 found and fixed (sidecar names), round 2 ACCEPT. Copy approved by Paul unchanged.

How it works:

  • The deny list now has two tiers (domainHostPolicy, internal/console/domainpolicy.go). Platform names are CONSOLEDENYDOMAINS entries plus, with CONSOLERESERVEPLATFORM_DOMAINS, the names under the console's hostnames. Reserved names are the console hosts (exact), the steering host, the tunnel host, .sidecar.internal, and with the reserve setting the apps domain.
  • carlos domains attach --platform lets an ops-account owner or a CARLOSSYSTEMOPERATORS address attach a platform name to an app in an account they're a member of. Members get a 403 for the flag, and a service token always does. Reserved names stay refused to everyone.
  • After that, members of the holding account can't repoint the claim, flip wildcard/catchall, publish paths or detach it (API or settings page). The operator can.
  • CARLOSTUNNELHOST is no longer folded into DenyDomains. It's Config.TunnelHost, so the door can't lift it.

To use it for carloku.com: merge, roll the console, then carlos domains attach --account bes --app website --platform carloku.com, then the DNSimple ALIAS. Paul or a listed system operator must be a member of bes.

Landed and in use (2026-10-04):

  • Squash-merged to main as a6e4cd41; GitHub mirror fast-forwarded.
  • Flagship console rolled to a6e4cd41 (this also shipped everything merged since 7edd4b33, including design-nearest-region and db pull; Paul's call). Boxes were not rolled; #209 is console-only.
  • bes/website redeployed at bfa9665 (the rack-mark build bab/carloku was serving, verified byte-identical page by page), then carloku.com and www.carloku.com moved: carlos remove on the IE box, then carlos domains attach --platform. About 20 s (apex) and 35 s (www) of 404 each while the alias came up. Both now serve bfa9665 from bes/website.
  • bab/carloku has no routes left on the IE box. Its bucket artifacts are untouched.

Optional, Paul's DNSimple: the console's guidance suggests apex A records for all four edges (99.81.104.219, 54.252.186.195, 16.60.78.128, 44.210.206.26) and www as a CNAME to edge.oncarlos.com. Today both resolve to the IE box only, which works.

Future site deploys go to bes/website (carlos deploy --account bes --app website --kind static _site), not the pinfra ship to bab/carloku. The carloku repo's AGENTS.md "Deploying" section still describes the old route and needs updating.