carlos / platform Public

Merge origin/main into console-as-an-app

249 commits of main taken in — the branch was cut from a stale base and had
to carry release pipelines v2 (#254), static-cli (#261), tenant email,
multi-region ingress, scheduled work, the domains housekeeper duty (#289)
and the amadan CI move before it could be reviewed.

Six files conflicted; every one keeps BOTH sides:

- cmd/console/main.go — main's http.Server (ReadHeaderTimeout/ReadTimeout,
  now load-bearing because sesevents.go is an unauthenticated body-reading
  route) built over OUR explicit net.Listen, so NotifyReady still fires
  strictly after the listener is open and Type=notify still catches a build
  that dies before serving. Addr dropped: Serve(ln) never reads it.
- app_settings.html — main's Email card and our Control plane card, in that
  order so the two danger-head sections stay adjacent.
- adopt_test.go / deploy_test.go — not semantic conflicts: both sides append
  tests and git interleaved them at shared fixture boilerplate. Main's file
  taken verbatim, our append blocks re-applied verbatim. deploy_test's
  deployFakeConsole carries both shipProbe (ours) and promoteProposed
  (main's).
- internal/console/apicli.go — in handleAPIPromote and handleAPIRollback,
  our refuseServiceControlPlane runs BEFORE main's pipeline channel gate. A
  service credential barred from the verb must not be able to author a
  proposal for it, which is also what keeps main's new pending/quorum
  machinery from becoming a way around the flag. Consequence, deliberate:
  a service credential aimed at the control plane's stable now reads the
  control-plane refusal rather than "stable needs a passkey" — both 403,
  membership already proved by apiAccountApp's 404 above.
- internal/host/agent.go — our two-phase fastDeps construction is kept (it
  is structurally required: observeRestart wraps the dispatch and needs d to
  exist first), with main's schedule converge seed in its own position and
  scheduleLeg added as the last field assignment. Task 7's WithStartUnit
  wiring and restart-hold backoff intact; #289 touches domainsLoop, not this
  loop, and auto-merged.

a90e22e (the ship budget) never presented: it is content-identical to main's
squashed deccd44, so git took it once. cliShipWindow/cliShipBurst/
svcShipBurst/resetIn each appear exactly once.

Gate: go build, go vet, GOOS=darwin go build all clean; go test ./...
-count=1 = 33 ok, 0 FAIL (29 before — main added packages); gofmt clean on
every file touched.

Full conflict-by-conflict account in
.superpowers/sdd/2026-08-23-console-as-an-app/merge-report.md
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Paul Campbell pushed by paul@keymail.dev daff6d5a091648f8de8d4d2346bfc6bc8fbd021b parent ede1e1cparent d6cd0e9
217 files changed, +67745 −1051
  • .amadan/README.md +78 −0
  • .amadan/ci.d/10-gate +51 −0
  • .amadan/ci.d/20-cross@5 +55 −0
  • .amadan/ci.d/30-minio-contract +323 −0
  • .github/workflows/ci.yml +0 −186
  • .gitignore +5 −0
  • AGENTS.md +205 −0
  • CLAUDE.md +4 −185
  • Makefile +8 −2
  • apimode.go +500 −21
  • apimode_test.go +239 −8
  • auth_e2e_test.go +1 −1
  • cli.go +33 −13
  • cli_test.go +15 −0
  • cmd/console/mailbackends_test.go +128 −0
  • cmd/console/main.go +217 −1
  • color.go +12 −0
  • deploy.go +186 −41
  • deploy_e2e_test.go +167 −0
  • deploy_test.go +324 −15
  • deploy_wizard_test.go +4 −4
  • docs/superpowers/plans/2026-08-16-woodstar-cutover-runbook.md +37 −6
  • docs/superpowers/plans/2026-08-19-tenant-email.md +5505 −0
  • docs/superpowers/plans/2026-08-20-multi-region-writer-map-and-certs.md +777 −0
  • docs/superpowers/plans/2026-08-20-release-pipelines-v2.md +974 −0
  • docs/superpowers/plans/2026-08-22-multi-region-backhaul.md +843 −0
  • docs/superpowers/plans/2026-08-23-multi-region-steering.md +763 −0
  • docs/superpowers/plans/2026-08-23-record-channel-change.md +601 −0
  • docs/superpowers/plans/2026-08-23-scheduled-work.md +3164 −0
  • docs/superpowers/plans/2026-08-23-static-platform-host.md +558 −0
  • docs/superpowers/specs/2026-08-19-tenant-email-design.md +773 −0
  • docs/superpowers/specs/2026-08-20-bucket-writer-audit.md +399 −0
  • docs/superpowers/specs/2026-08-20-multi-region-ingress-design.md +675 −0
  • docs/superpowers/specs/2026-08-20-release-pipelines-v2-design.md +238 −0
  • docs/superpowers/specs/2026-08-23-record-channel-change-design.md +179 −0
  • docs/superpowers/specs/2026-08-23-scheduled-work-design.md +652 −0
  • docs/superpowers/specs/2026-08-23-static-platform-host-design.md +201 −0
  • domains_cli_test.go +2 −2
  • fleets_cli_test.go +1 −1
  • go.mod +9 −8
  • go.sum +18 −16
  • infra/modules/README.md +3 −0
  • infra/modules/region-host/main.tf +91 −0
  • infra/modules/region-host/variables.tf +20 −0
  • instances_cli.go +175 −3
  • instances_e2e_test.go +75 −0
  • internal/activator/activator_test.go +335 −18
  • internal/activator/admintoken.go +214 −0
  • internal/activator/admintoken_test.go +266 −0
  • internal/activator/backend_exec.go +131 −53
  • internal/activator/logsink.go +6 −3
  • internal/appconfig/syncexec.go +2 −2
  • internal/appconfig/syncexec_test.go +1 −1
  • internal/applog/record.go +1 −1
  • internal/applog/record_test.go +1 −1
  • internal/console/apicli.go +211 −23
  • internal/console/apicli_test.go +144 −11
  • internal/console/apidomains.go +1 −1
  • internal/console/apiinstances.go +89 −19
  • internal/console/apiinstances_test.go +334 −0
  • internal/console/apimail.go +1148 −0
  • internal/console/apimail_test.go +1085 −0
  • internal/console/apipipeline.go +340 −0
  • internal/console/apipipeline_test.go +399 −0
  • internal/console/apischedule.go +322 −0
  • internal/console/apischedule_test.go +468 −0
  • internal/console/apiservices.go +1 −1
  • internal/console/apiservices_test.go +1 −1
  • internal/console/apistore.go +1 −1
  • internal/console/appsettings.go +131 −1
  • internal/console/appsettings_test.go +364 −0
  • internal/console/authcli.go +37 −0
  • internal/console/channelmove.go +229 −0
  • internal/console/channelmove_test.go +343 −0
  • internal/console/confirm.go +19 −4
  • internal/console/confirm_test.go +45 −1
  • internal/console/deletion_test.go +104 −0
  • internal/console/economicspage_test.go +1 −1
  • internal/console/flow.go +61 −15
  • internal/console/ladder.go +113 −2
  • internal/console/ladder_test.go +2 −2
  • internal/console/mailcounts.go +275 −0
  • internal/console/mailcounts_test.go +458 −0
  • internal/console/ownership.go +62 −0
  • internal/console/pending.go +335 −0
  • internal/console/pending_test.go +185 −0
  • internal/console/pendingflow_test.go +943 −0
  • internal/console/pendinghandlers.go +655 −0
  • internal/console/pipelinepage.go +331 −0
  • internal/console/pipelinepage_test.go +446 −0
  • internal/console/server.go +415 −55
  • internal/console/server_test.go +159 −7
  • internal/console/sesevents.go +694 −0
  • internal/console/sesevents_test.go +677 −0
  • internal/console/store.go +22 −1
  • internal/console/svcroutes_test.go +44 −4
  • internal/console/templates/app_overview.html +8 −0
  • internal/console/templates/app_releases.html +10 −3
  • internal/console/templates/app_settings.html +66 −0
  • internal/console/templates/ladder.html +8 −1
  • internal/console/templates/pending.html +22 −0
  • internal/console/templates/pipeline.html +60 −0
  • internal/console/view.go +127 −25
  • internal/console/view_test.go +9 −9
  • internal/dnsrec/dnsrec.go +90 −0
  • internal/dnsrec/dnsrec_test.go +75 −0
  • internal/dnsrec/route53.go +165 −0
  • internal/dnsrec/route53_test.go +35 −0
  • internal/edge/backhaul_e2e_test.go +920 −0
  • internal/edge/certcache.go +8 −0
  • internal/edge/certsync.go +1407 −0
  • internal/edge/certsync_e2e_test.go +1298 −0
  • internal/edge/certsync_test.go +1853 −0
  • internal/edge/edge.go +646 −29
  • internal/edge/homemap.go +707 −0
  • internal/edge/homemap_test.go +1551 −0
  • internal/edge/mesh.go +303 −0
  • internal/edge/mesh_test.go +389 −0
  • internal/edge/purge.go +83 −25
  • internal/edge/purge_listen_windows.go +5 −3
  • internal/edge/steeringprobe.go +120 −0
  • internal/edge/steeringprobe_test.go +231 −0
  • internal/edge/storedoor_test.go +101 −0
  • internal/edge/usagemeter.go +12 −2
  • internal/edge/usagemeter_test.go +30 −4
  • internal/edge/wildcard.go +185 −38
  • internal/edge/wildcard_test.go +33 −12
  • internal/host/agent.go +232 −29
  • internal/host/domains_duty_test.go +54 −0
  • internal/host/edgesfile.go +251 −0
  • internal/host/edgesfile_test.go +568 −0
  • internal/host/housekeeper.go +472 −0
  • internal/host/housekeeper_test.go +562 −0
  • internal/host/schedule_wake_test.go +532 −0
  • internal/host/schedule_wiring.go +436 −0
  • internal/host/schedule_wiring_test.go +160 −0
  • internal/host/snapshot_loop.go +51 −36
  • internal/host/snapshot_loop_test.go +112 −27
  • internal/host/statfs_unix.go +1 −1
  • internal/host/steering_loop.go +246 −0
  • internal/host/steering_loop_test.go +525 −0
  • internal/mail/aws.go +470 −0
  • internal/mail/aws_test.go +351 −0
  • internal/mail/dnsrecords.go +93 −0
  • internal/mail/dnsrecords_test.go +107 −0
  • internal/mail/domain.go +203 −0
  • internal/mail/domain_test.go +107 −0
  • internal/mail/domainclaim.go +209 −0
  • internal/mail/events.go +128 −0
  • internal/mail/events_test.go +163 −0
  • internal/mail/mail.go +162 −0
  • internal/mail/mail_test.go +105 −0
  • internal/mail/memprovisioner.go +300 −0
  • internal/mail/memprovisioner_test.go +133 −0
  • internal/mail/policy.go +181 −0
  • internal/mail/policy_test.go +320 −0
  • internal/mail/provisioner.go +77 −0
  • internal/mail/smtppass.go +43 −0
  • internal/mail/smtppass_test.go +55 −0
  • internal/mail/walk.go +1169 −0
  • internal/mail/walk_domain_test.go +372 −0
  • internal/mail/walk_domainclaim_test.go +624 −0
  • internal/mail/walk_enable_test.go +482 −0
  • internal/mail/walk_grant_test.go +86 −0
  • internal/mail/walk_lifecycle_test.go +539 −0
  • internal/mail/walk_verify_test.go +129 −0
  • internal/objstore/contract_test.go +6 −5
  • internal/provision/provision.go +37 −0
  • internal/provision/provision_test.go +57 −1
  • internal/provision/reconcile.go +290 −13
  • internal/provision/reconcile_test.go +375 −0
  • internal/registry/registry.go +108 −6
  • internal/registry/registry_test.go +92 −0
  • internal/registry/timers.go +216 −0
  • internal/registry/timers_test.go +251 −0
  • internal/release/adopt.go +222 −32
  • internal/release/adopt_test.go +476 −0
  • internal/release/bake.go +266 −0
  • internal/release/bake_test.go +333 −0
  • internal/release/pipeline.go +356 −0
  • internal/release/pipeline_test.go +234 −0
  • internal/release/release.go +24 −2
  • internal/schedule/control.go +171 −0
  • internal/schedule/control_test.go +195 −0
  • internal/schedule/converge.go +334 −0
  • internal/schedule/converge_test.go +543 −0
  • internal/schedule/cron.go +169 −0
  • internal/schedule/cron_test.go +85 −0
  • internal/schedule/declaration.go +303 −0
  • internal/schedule/declaration_test.go +181 −0
  • internal/schedule/envfile.go +32 −0
  • internal/schedule/runner.go +469 −0
  • internal/schedule/runner_test.go +674 −0
  • internal/schedule/spec.go +134 −0
  • internal/schedule/spec_test.go +86 −0
  • internal/schedule/status.go +116 −0
  • internal/schedule/status_test.go +37 −0
  • internal/status/status_test.go +1 −1
  • internal/steering/deployment.go +73 −0
  • internal/steering/deployment_test.go +151 −0
  • internal/steering/route53.go +965 −0
  • internal/steering/route53_test.go +1241 −0
  • internal/steering/steering.go +364 −0
  • internal/steering/steering_test.go +424 −0
  • internal/usage/edge.go +16 −0
  • internal/usage/edge_test.go +76 −0
  • internal/usage/usage.go +7 −0
  • mail_cli.go +1331 −0
  • mail_cli_test.go +1110 −0
  • main.go +16 −1
  • pipeline.go +470 −0
  • pipeline_test.go +549 −0
  • schedule.go +367 −0
  • schedule_test.go +402 −0
  • services_cli_test.go +2 −2
  • store.go +1 −1
  • store_test.go +1 −1
.amadan/README.md

Loading diff…

.amadan/ci.d/10-gate

Loading diff…

.amadan/ci.d/20-cross@5

Loading diff…

.amadan/ci.d/30-minio-contract

Loading diff…

.github/workflows/ci.yml

Loading diff…

.gitignore

Loading diff…

AGENTS.md

Loading diff…

CLAUDE.md

Loading diff…

Makefile

Loading diff…

apimode.go

Loading diff…

apimode_test.go

Loading diff…

auth_e2e_test.go

Loading diff…

cli.go

Loading diff…

cli_test.go

Loading diff…

cmd/console/mailbackends_test.go

Loading diff…

cmd/console/main.go

Loading diff…

color.go

Loading diff…

deploy.go

Loading diff…

deploy_e2e_test.go

Loading diff…

deploy_test.go

Loading diff…

deploy_wizard_test.go

Loading diff…

docs/superpowers/plans/2026-08-16-woodstar-cutover-runbook.md

Loading diff…

docs/superpowers/plans/2026-08-19-tenant-email.md

Loading diff…

docs/superpowers/plans/2026-08-20-multi-region-writer-map-and-certs.md

Loading diff…

docs/superpowers/plans/2026-08-20-release-pipelines-v2.md

Loading diff…

docs/superpowers/plans/2026-08-22-multi-region-backhaul.md

Loading diff…

docs/superpowers/plans/2026-08-23-multi-region-steering.md

Loading diff…

docs/superpowers/plans/2026-08-23-record-channel-change.md

Loading diff…

docs/superpowers/plans/2026-08-23-scheduled-work.md

Loading diff…

docs/superpowers/plans/2026-08-23-static-platform-host.md

Loading diff…

docs/superpowers/specs/2026-08-19-tenant-email-design.md

Loading diff…

docs/superpowers/specs/2026-08-20-bucket-writer-audit.md

Loading diff…

docs/superpowers/specs/2026-08-20-multi-region-ingress-design.md

Loading diff…

docs/superpowers/specs/2026-08-20-release-pipelines-v2-design.md

Loading diff…

docs/superpowers/specs/2026-08-23-record-channel-change-design.md

Loading diff…

docs/superpowers/specs/2026-08-23-scheduled-work-design.md

Loading diff…

docs/superpowers/specs/2026-08-23-static-platform-host-design.md

Loading diff…

domains_cli_test.go

Loading diff…

fleets_cli_test.go

Loading diff…

go.mod

Loading diff…

go.sum

Loading diff…

infra/modules/README.md

Loading diff…

infra/modules/region-host/main.tf

Loading diff…

infra/modules/region-host/variables.tf

Loading diff…

instances_cli.go

Loading diff…

instances_e2e_test.go

Loading diff…

internal/activator/activator_test.go

Loading diff…

internal/activator/admintoken.go

Loading diff…

internal/activator/admintoken_test.go

Loading diff…

internal/activator/backend_exec.go

Loading diff…

internal/activator/logsink.go

Loading diff…

internal/appconfig/syncexec.go

Loading diff…

internal/appconfig/syncexec_test.go

Loading diff…

internal/applog/record.go

Loading diff…

internal/applog/record_test.go

Loading diff…

internal/console/apicli.go

Loading diff…

internal/console/apicli_test.go

Loading diff…

internal/console/apidomains.go

Loading diff…

internal/console/apiinstances.go

Loading diff…

internal/console/apiinstances_test.go

Loading diff…

internal/console/apimail.go

Loading diff…

internal/console/apimail_test.go

Loading diff…

internal/console/apipipeline.go

Loading diff…

internal/console/apipipeline_test.go

Loading diff…

internal/console/apischedule.go

Loading diff…

internal/console/apischedule_test.go

Loading diff…

internal/console/apiservices.go

Loading diff…

internal/console/apiservices_test.go

Loading diff…

internal/console/apistore.go

Loading diff…

internal/console/appsettings.go

Loading diff…

internal/console/appsettings_test.go

Loading diff…

internal/console/authcli.go

Loading diff…

internal/console/channelmove.go

Loading diff…

internal/console/channelmove_test.go

Loading diff…

internal/console/confirm.go

Loading diff…

internal/console/confirm_test.go

Loading diff…

internal/console/deletion_test.go

Loading diff…

internal/console/economicspage_test.go

Loading diff…

internal/console/flow.go

Loading diff…

internal/console/ladder.go

Loading diff…

internal/console/ladder_test.go

Loading diff…

internal/console/mailcounts.go

Loading diff…

internal/console/mailcounts_test.go

Loading diff…

internal/console/ownership.go

Loading diff…

internal/console/pending.go

Loading diff…

internal/console/pending_test.go

Loading diff…

internal/console/pendingflow_test.go

Loading diff…

internal/console/pendinghandlers.go

Loading diff…

internal/console/pipelinepage.go

Loading diff…

internal/console/pipelinepage_test.go

Loading diff…

internal/console/server.go

Loading diff…

internal/console/server_test.go

Loading diff…

internal/console/sesevents.go

Loading diff…

internal/console/sesevents_test.go

Loading diff…

internal/console/store.go

Loading diff…

internal/console/svcroutes_test.go

Loading diff…

internal/console/templates/app_overview.html

Loading diff…

internal/console/templates/app_releases.html

Loading diff…

internal/console/templates/app_settings.html

Loading diff…

internal/console/templates/ladder.html

Loading diff…

internal/console/templates/pending.html

Loading diff…

internal/console/templates/pipeline.html

Loading diff…

internal/console/view.go

Loading diff…

internal/console/view_test.go

Loading diff…

internal/dnsrec/dnsrec.go

Loading diff…

internal/dnsrec/dnsrec_test.go

Loading diff…

internal/dnsrec/route53.go

Loading diff…

internal/dnsrec/route53_test.go

Loading diff…

internal/edge/backhaul_e2e_test.go

Loading diff…

internal/edge/certcache.go

Loading diff…

internal/edge/certsync.go

Loading diff…

internal/edge/certsync_e2e_test.go

Loading diff…

internal/edge/certsync_test.go

Loading diff…

internal/edge/edge.go

Loading diff…

internal/edge/homemap.go

Loading diff…

internal/edge/homemap_test.go

Loading diff…

internal/edge/mesh.go

Loading diff…

internal/edge/mesh_test.go

Loading diff…

internal/edge/purge.go

Loading diff…

internal/edge/purge_listen_windows.go

Loading diff…

internal/edge/steeringprobe.go

Loading diff…

internal/edge/steeringprobe_test.go

Loading diff…

internal/edge/storedoor_test.go

Loading diff…

internal/edge/usagemeter.go

Loading diff…

internal/edge/usagemeter_test.go

Loading diff…

internal/edge/wildcard.go

Loading diff…

internal/edge/wildcard_test.go

Loading diff…

internal/host/agent.go

Loading diff…

internal/host/domains_duty_test.go

Loading diff…

internal/host/edgesfile.go

Loading diff…

internal/host/edgesfile_test.go

Loading diff…

internal/host/housekeeper.go

Loading diff…

internal/host/housekeeper_test.go

Loading diff…

internal/host/schedule_wake_test.go

Loading diff…

internal/host/schedule_wiring.go

Loading diff…

internal/host/schedule_wiring_test.go

Loading diff…

internal/host/snapshot_loop.go

Loading diff…

internal/host/snapshot_loop_test.go

Loading diff…

internal/host/statfs_unix.go

Loading diff…

internal/host/steering_loop.go

Loading diff…

internal/host/steering_loop_test.go

Loading diff…

internal/mail/aws.go

Loading diff…

internal/mail/aws_test.go

Loading diff…

internal/mail/dnsrecords.go

Loading diff…

internal/mail/dnsrecords_test.go

Loading diff…

internal/mail/domain.go

Loading diff…

internal/mail/domain_test.go

Loading diff…

internal/mail/domainclaim.go

Loading diff…

internal/mail/events.go

Loading diff…

internal/mail/events_test.go

Loading diff…

internal/mail/mail.go

Loading diff…

internal/mail/mail_test.go

Loading diff…

internal/mail/memprovisioner.go

Loading diff…

internal/mail/memprovisioner_test.go

Loading diff…

internal/mail/policy.go

Loading diff…

internal/mail/policy_test.go

Loading diff…

internal/mail/provisioner.go

Loading diff…

internal/mail/smtppass.go

Loading diff…

internal/mail/smtppass_test.go

Loading diff…

internal/mail/walk.go

Loading diff…

internal/mail/walk_domain_test.go

Loading diff…

internal/mail/walk_domainclaim_test.go

Loading diff…

internal/mail/walk_enable_test.go

Loading diff…

internal/mail/walk_grant_test.go

Loading diff…

internal/mail/walk_lifecycle_test.go

Loading diff…

internal/mail/walk_verify_test.go

Loading diff…

internal/objstore/contract_test.go

Loading diff…

internal/provision/provision.go

Loading diff…

internal/provision/provision_test.go

Loading diff…

internal/provision/reconcile.go

Loading diff…

internal/provision/reconcile_test.go

Loading diff…

internal/registry/registry.go

Loading diff…

internal/registry/registry_test.go

Loading diff…

internal/registry/timers.go

Loading diff…

internal/registry/timers_test.go

Loading diff…

internal/release/adopt.go

Loading diff…

internal/release/adopt_test.go

Loading diff…

internal/release/bake.go

Loading diff…

internal/release/bake_test.go

Loading diff…

internal/release/pipeline.go

Loading diff…

internal/release/pipeline_test.go

Loading diff…

internal/release/release.go

Loading diff…

internal/schedule/control.go

Loading diff…

internal/schedule/control_test.go

Loading diff…

internal/schedule/converge.go

Loading diff…

internal/schedule/converge_test.go

Loading diff…

internal/schedule/cron.go

Loading diff…

internal/schedule/cron_test.go

Loading diff…

internal/schedule/declaration.go

Loading diff…

internal/schedule/declaration_test.go

Loading diff…

internal/schedule/envfile.go

Loading diff…

internal/schedule/runner.go

Loading diff…

internal/schedule/runner_test.go

Loading diff…

internal/schedule/spec.go

Loading diff…

internal/schedule/spec_test.go

Loading diff…

internal/schedule/status.go

Loading diff…

internal/schedule/status_test.go

Loading diff…

internal/status/status_test.go

Loading diff…

internal/steering/deployment.go

Loading diff…

internal/steering/deployment_test.go

Loading diff…

internal/steering/route53.go

Loading diff…

internal/steering/route53_test.go

Loading diff…

internal/steering/steering.go

Loading diff…

internal/steering/steering_test.go

Loading diff…

internal/usage/edge.go

Loading diff…

internal/usage/edge_test.go

Loading diff…

internal/usage/usage.go

Loading diff…

mail_cli.go

Loading diff…

mail_cli_test.go

Loading diff…

main.go

Loading diff…

pipeline.go

Loading diff…

pipeline_test.go

Loading diff…

schedule.go

Loading diff…

schedule_test.go

Loading diff…

services_cli_test.go

Loading diff…

store.go

Loading diff…

store_test.go

Loading diff…