Before you continue...

CARLOS is an AI-enabled project, and all CARLOS software to date has been entirely produced using a combination of LLM-based coding products from Anthropic, OpenAI, and open-weight alternatives. Whilst CARLOS represents an approach to apply these products toward new standards of openness and release of corporate ownership of internet-based software and data, we realise that there are folks for whom use of these products is unacceptable. With that said, if folks will continue to use AI to produce software, our mission is to show that AI unlocks ways to produce better software for everyone.

One of the principles behind the project is full disclosure of AI use, and AI-written language, starting here.

Changelog

All the latest updates to CARLOS platform, auto-generated from its git history.

With the obvious assistance from the robots.

🤖 This page was written by an LLM, on the ideas, instruction, and editing of humans. AI-written text here is always marked, visibly, like this. That's factor X.

  • carlos logs now shows each run. It shows when each carlos run started, who asked for it and how it ended. The command's output is not kept there. run-lifecycle-logs-325 carlos logs carlos run
  • An app can ask for one uploaded object to be scanned. Where scanning is enabled for the deployment and an operator has granted the store, the app requests a scan with an app-scoped service credential and polls for the result, or receives a signed callback. See Receiving scan results. scan-demand-revival
  • The console's account switcher has a search box. It helps when you belong to many accounts. console-switcher-filter
For operators
  • Roll the boxes first, then the console. Coming from v0.28.4, read the v0.28.5 operator notes first. Coming from v0.28.5, upgrade the console with carlos system claims install-console --upgrade as the v0.28.6 notes describe. carlos system claims
  • An offline move can copy most of its data before the instance goes offline. Run carlos move offline stage --host <host> --to <region> while the instance keeps serving. It copies the instance's replica to the target region, and running it again copies only what is new. start then takes the instance offline as before, and the seal copies only what changed since the last stage. Until start, abort removes the staged copy and the instance is never offline. While a move is staged, the instance refuses carlos run and deletion, and no other instance can move offline. moves-offline-precopy carlos move carlos run
  • Every box in both regions must run this release before stage works. Each box now publishes offline-stage-1, and stage refuses while any box in either region lacks it. moves-offline-precopy
  • Moves and replica copies now run eight object copies at once. Before, they copied one object at a time, so a large replica took minutes to copy while the instance was offline. moves-offline-precopy
  • On-demand scanning needs CARLOS_SCAN_WEBHOOK_KEY only for callbacks. Polling works without it. To rotate it, keep the old key in CARLOS_SCAN_WEBHOOK_KEY_PREVIOUS and run carlos system antivirus rotate-webhook-key. Apps whose delivered secret changes restart. scan-demand-revival carlos system
  • Every dormant switch stays off. Leave CARLOS_MOVES_PHASE1, CARLOS_HOST_CLAIM, CARLOS_HOST_CLAIM_ORIGINS, CARLOS_HOST_CLAIM_RETIRED_LOCATIONS, CARLOS_CONSOLE_ID, CARLOS_REGION_HA, CONSOLE_APP_REGIONS, CARLOS_TEMPORARY_APPS, CARLOS_REQUIRE_POINTER_DIGEST and CARLOS_PLAN_CATALOG unset, don't put CARLOS_BOX_REFERENCE=group in any host.env, and don't run carlos channels digests on. Keep CARLOS_SWAP as it is: a box armed for zero-downtime deploys stays armed. carlos channels digests

Changes

7
  1. moves-offline-precopymoves-offline-precopy: carlos move offline stage (pre-copy while serving) and parallel mirror copies

    Paul Campbell with claude carlos move 771ca01b

  2. design-plans-and-capsspec: plans, caps and packs for the first paid launch (draft)

    Paul Campbell with claude #280 carlos accounts plan turning plans on the catalog assigning a plan sponsored accounts f550afa2

  3. test-suite-speedroot tests: the carlos binary is built once per test run, not once per test

    Paul Campbell with claude #291 aaa6a949

  4. test-suite-debtPrompts:

    Paul Campbell with claude #226 #258 #263 #266 #274 512baa59

  5. run-lifecycle-logs-325carlos run: a run's start and end reach carlos logs (#325)

    Paul Campbell with claude #325 carlos run f54aa2fc

  6. scan-demand-revivalMerge reviewed on-demand object scanning revival

    Paul Campbell with claude carlos store scan deployment wide object scanning asking for a scan the states callbacks take a path 3d444a1b

  7. console-switcher-filterconsole: searchable, scrolling account switcher

    Paul Campbell with claude #280 ce8c425a

  • Nothing changes for people deploying apps with the CLI.
For operators
  • Roll the boxes first, then the console.
  • Coming from v0.28.4, read the v0.28.5 operator notes first. They all still apply, including the one update by hand for a box whose guard is armed on v0.28.4.
  • A guard-armed box's protected console can now be replaced. Once the box's router is on this release, run carlos system claims install-console --upgrade --from <sha256> as root, where the sha256 is the console that is running now. It refuses unless that build is what the box holds, then installs the new console and keeps the old one as console.prev. No hand recovery is needed. A box upgraded this way can't be armed again with carlos system guard-arm until install-console has been run without --upgrade, because guard-arm expects both copies to be the same build. install-console-upgrade carlos system claims carlos system
  • A nested instance's config.env is written as soon as its directory appears. Before, a move could leave the instance without it for up to an hour. moves-offline-fixes
  • Each offline move step now sees a current box report. While a move is running, the source boxes and the sealing box report again every 15 seconds. A move takes under a minute of downtime when its steps run back to back. A step that meets a stale report now says the report is not current and to try again. Before, flip could answer that a process was still running. moves-offline-fixes
  • A source box's scheduler leaves a moved instance alone. After open, it no longer writes a stray token file into the instance it gave up. moves-offline-fixes
  • Every dormant switch stays off. Leave CARLOS_MOVES_PHASE1, CARLOS_HOST_CLAIM, CARLOS_HOST_CLAIM_ORIGINS, CARLOS_HOST_CLAIM_RETIRED_LOCATIONS, CARLOS_CONSOLE_ID, CARLOS_REGION_HA, CONSOLE_APP_REGIONS, CARLOS_TEMPORARY_APPS and CARLOS_REQUIRE_POINTER_DIGEST unset, don't put CARLOS_BOX_REFERENCE=group in any host.env, and don't run carlos channels digests on. Keep CARLOS_SWAP as it is: a box armed for zero-downtime deploys stays armed. carlos channels digests

Changes

2
  1. moves-offline-fixesmoves-offline-fixes: harness Run 9 defects. Config sync writes a nested row's config.env as soon as its instance directory appears, keeping it pending until delivered (6); each offline door step sees a current report: source boxes and the sealer refresh reports every 15 s while a move is active without renewing the tombstone, and a stale report answers MV-O178 (7); a source box's scheduler leaves a held or moved host alone, excluding it before the batch limit (8). Astra reviewed (two rounds); census-ruling-moves-offline-fixes (platform-1c); MV-O178 approved by Paul.

    Paul Campbell with claude e0986eab

  2. install-console-upgradeinstall-console --upgrade --from <sha256>: replace a guard-armed box's protected console

    Paul Campbell with claude carlos system claims 21850356

  • Nothing changes for people deploying apps with the CLI.
For operators
  • Roll the boxes first, then the console.
  • Coming from v0.28.3, read the v0.28.4 operator notes first. They all still apply.
  • carlos move offline moves one instance to another region, with planned downtime. It is for operators, works only while host claims and Phase 1 moves are off, and takes one step per command: start, seal, flip, open, then finish. The instance is offline from start until open. Until open, abort puts it back where it was with nothing lost. moves-offline carlos move
  • Roll every box in both regions before you start an offline move. seal waits until every box in the instance's current region has stopped it and said so, and a box on an earlier release never says so. moves-offline
  • A box whose guard is armed on v0.28.4 needs one update by hand. Its updater reads a candidate's progress messages as part of the answer, so carlos system update refuses every candidate on that box. Stop carlos-system-update.path, put the v0.28.5 binary in a root-only file after checking it against SHA256SUMS.txt, run it as root as system apply with the box's host.env, check the box, then start carlos-system-update.path again. Do one box at a time. From then on the box updates as usual. armed-box-updates carlos system
  • The guarded updater reads only what a candidate writes to standard output. Progress and warnings no longer break its checks, so this is the last update a guard-armed box needs by hand. armed-box-updates
  • carlos system guard-arm makes its directories readable whatever your umask is. Before, a root shell with a strict umask left them unreadable to the box's updater. claim-guard-umask carlos system
  • Routes with their own unit now restart on boxes whose agent doesn't run as root. The agent now hands those restarts to root. Before, the restart was refused, the agent read that as a broken build and rolled back. adopt-unit-root-pass-315
  • carlos system status warns when a new box would boot an older build. It compares bootstrap/carlos with stable's build and says which file to copy over it. bootstrap-carlos-follows-316 carlos system
  • Every dormant switch stays off. Leave CARLOS_MOVES_PHASE1, CARLOS_HOST_CLAIM, CARLOS_HOST_CLAIM_ORIGINS, CARLOS_HOST_CLAIM_RETIRED_LOCATIONS, CARLOS_CONSOLE_ID, CARLOS_REGION_HA, CONSOLE_APP_REGIONS, CARLOS_TEMPORARY_APPS and CARLOS_REQUIRE_POINTER_DIGEST unset, don't put CARLOS_BOX_REFERENCE=group in any host.env, and don't run carlos channels digests on. Keep CARLOS_SWAP as it is: a box armed for zero-downtime deploys stays armed. carlos channels digests

Changes

6
  1. armed-box-updatesarmed-box-updates: guard-armed boxes can take a release by the ruled re-arm. Cherry-picks 8376a468 (rootaws: an inherited disabled sentinel is not an override) and 8a313548 (hostfloor: a guarded run returns stdout only) from claim-empty-cohort-done, Astra-reviewed there; census-ruling-claim-rootaws-sentinel, confirmed for main by platform-1c. For v0.28.5.

    Paul Campbell with claude 54ae7fb9

  2. moves-offlinemoves-offline: operator-run offline region move (claims-off, planned downtime): holds and fences every source box, seals the source with a create-only tombstone after a final checkpoint, lands every dependency on the target proven against an immutable seal.json, opens, then retires the source by rename. Reviewed task by task and by Fable and Astra; census-ruling-moves-offline; copy approved by Paul 2026-10-20. Dormant until an operator runs carlos move offline.

    Paul Campbell with claude carlos move 7af88155

  3. changelog-v0.28.4changelog-v0.28.4: release step 10 for v0.28.1 to v0.28.4

    Paul Campbell with claude 57569bff

  4. bootstrap-carlos-follows-316system status: say when bootstrap/carlos is not stable's build (#316)

    Paul Campbell with claude #280 #316 cd2dd6e1

  5. adopt-unit-root-pass-315adopt: an agent that is not root hands named-unit routes to root's pass (#315)

    Paul Campbell with claude #280 #315 d7a5b8eb

  6. claim-guard-umaskclaim-guard-umask: guard-arm makes its guard, system and lock directories 0755 whatever the caller's umask (#317)

    Paul Campbell with claude #317 96db0efe

  • Console invites now arrive. Before this release, an invite to anyone but yourself never reached them. The console now delivers the link to the invitee's Keymail inbox, or by email where console email is on. If neither works, it shows you the link to pass on yourself. design-console-invite-delivery
  • An account can have 20 invites waiting at most, and send 20 an hour. An invite emailed to an address that isn't a Keymail address can't be accepted yet. design-console-invite-delivery
  • Nothing changes in the CLI.
For operators
  • Roll the boxes first, then the console.
  • Coming from v0.28.2, read the v0.28.3 operator notes first. They all still apply.
  • Console email can switch itself on. A console with CARLOS_MAIL_REGION set and a sending address (CARLOS_CONSOLE_MAIL_FROM, or one made from CARLOS_MAIL_PLATFORM_SUFFIX) creates an SES identity and DNS records for that address's domain the first time it starts. It sends nothing until SES has verified the domain. design-console-invite-delivery
  • Sending also needs a grant that is off by default. The region-host module's console_mail_from and console_mail_region add an ses:SendEmail grant to the host role. Leave them unset until that grant's security review is done. Without it, invites fall back to Keymail or the link. design-console-invite-delivery
  • With CARLOS_HOST_CLAIM on, the console sends no email. Invites then go by Keymail, or the owner passes the link on. design-console-invite-delivery
  • carlos system install-channel --policy now also takes --identity. The two go together. The published release identity stands in for the channel's release tag, which the channel only carries once a floor is published. claim-untagged-pointer carlos system
  • Every dormant switch stays off. Leave CARLOS_SWAP, CARLOS_MOVES_PHASE1, CARLOS_HOST_CLAIM, CARLOS_HOST_CLAIM_ORIGINS, CARLOS_HOST_CLAIM_RETIRED_LOCATIONS, CARLOS_CONSOLE_ID, CARLOS_REGION_HA, CONSOLE_APP_REGIONS, CARLOS_TEMPORARY_APPS and CARLOS_REQUIRE_POINTER_DIGEST unset, don't put CARLOS_BOX_REFERENCE=group in any host.env, and don't run carlos channels digests on. carlos channels digests

Changes

2
  1. claim-untagged-pointerclaim-untagged-pointer: install-channel --policy takes --identity (the published release identity) so an untagged channel pointer works; the activation witness has no hand-made input on the trial's path

    Paul Campbell with claude boxes a region s group launches f3bf1214

  2. design-console-invite-deliveryspec: console invite delivery by Keymail federation, then email

    Paul Campbell with claude #216 #250 91a651b3

  • Nothing changes for people using the CLI.
For operators
  • Roll the boxes first, then the console.
  • Coming from v0.28.1, read the v0.28.2 operator notes first. They all still apply.
  • carlos system install-channel --policy prepares a box that is already running for host claims. It puts the box's current release in both its copies, so the guard can be armed before a floor is published. That replaces the box's rollback copy, and the command says so. Nothing runs it on its own, and host claims stay off. claim-prev-rehearsal carlos system
  • Every dormant switch stays off. Leave CARLOS_SWAP, CARLOS_MOVES_PHASE1, CARLOS_HOST_CLAIM, CARLOS_HOST_CLAIM_ORIGINS, CARLOS_HOST_CLAIM_RETIRED_LOCATIONS, CARLOS_CONSOLE_ID, CARLOS_REGION_HA, CONSOLE_APP_REGIONS, CARLOS_TEMPORARY_APPS and CARLOS_REQUIRE_POINTER_DIGEST unset, don't put CARLOS_BOX_REFERENCE=group in any host.env, and don't run carlos channels digests on. carlos channels digests

Changes

1
  1. claim-prev-rehearsalclaim-prev-rehearsal: install-channel --policy arms an updater-installed box; the activation witness starts from a box the platform made and rehearses steps 6 and 7

    Paul Campbell with claude boxes a region s group launches 50f5b268

  • Nothing changes for people using the CLI.
For operators
  • Roll the boxes first, then the console.
  • Coming from v0.28.0, read the v0.28.1 operator notes first. They all still apply.
  • Three new carlos system claims commands prepare a box for host claims. run gains two phases, sign-policy and publish-identity, which make the files carlos system guard-arm needs, and install-console puts a protected copy of the console where the guard expects it. Nothing runs them on its own, and host claims stay off. claim-step6-artifacts carlos system claims carlos system
  • Every dormant switch stays off. Leave CARLOS_SWAP, CARLOS_MOVES_PHASE1, CARLOS_HOST_CLAIM, CARLOS_HOST_CLAIM_ORIGINS, CARLOS_HOST_CLAIM_RETIRED_LOCATIONS, CARLOS_CONSOLE_ID, CARLOS_REGION_HA, CONSOLE_APP_REGIONS, CARLOS_TEMPORARY_APPS and CARLOS_REQUIRE_POINTER_DIGEST unset, don't put CARLOS_BOX_REFERENCE=group in any host.env, and don't run carlos channels digests on. carlos channels digests

Changes

1
  1. claim-step6-artifactsclaim-step6-artifacts: claims run sign-policy and publish-identity, --out byte-exact files, claims install-console (dev cohort-1 trial step 6)

    Paul Campbell with claude carlos system claims 7c1beb2d

  • Nothing changes for people using the CLI.
For operators
  • Roll the boxes first, then the console.
  • Coming from v0.27.x, read the v0.28.0 operator notes first. They all still apply.
  • A box can publish its identity record by hand. systemd-run --wait --pipe -p EnvironmentFile=/etc/carlos/host.env -p User=carlos /opt/carlos/carlos system box publish-record writes the box's AWS-signed identity record to the deployment bucket once. It never replaces or deletes a record, and it refuses to run as root or on a fleet box. Nothing runs it on its own. box-publish-record
  • A box that has not reported for a day drops out of status. carlos status --live, the console's box list and the promote list leave out a box whose report has not been written for 24 hours. Before, it stayed in the list as stale. Fleet boxes are listed as before. region-ha-2b-build carlos status
  • Each box gets an idle join unit. carlos-system-join.path is installed and enabled at the roll. Nothing touches the file it watches until region HA is turned on, so it never starts its service. region-ha-2b-build
  • Every dormant switch stays off. Leave CARLOS_SWAP, CARLOS_MOVES_PHASE1, CARLOS_HOST_CLAIM, CARLOS_HOST_CLAIM_ORIGINS, CARLOS_HOST_CLAIM_RETIRED_LOCATIONS, CARLOS_CONSOLE_ID, CARLOS_REGION_HA, CONSOLE_APP_REGIONS, CARLOS_TEMPORARY_APPS and CARLOS_REQUIRE_POINTER_DIGEST unset, don't put CARLOS_BOX_REFERENCE=group in any host.env, and don't run carlos channels digests on. carlos channels digests

Changes

3
  1. box-publish-recordbox-publish-record

    Paul Campbell with claude a box s identity record 3b69c2bd

  2. region-ha-2b-buildregion HA 2b: the joining and enrolment plan and its copy record

    Paul Campbell with claude #275 boxes a region s group launches b1118925

  3. changelog-v0.28.0changelog-v0.28.0: release step 10 for v0.28.0, plus the darwin/windows vet fix for claimunit_inputs_test.go

    Paul Campbell with claude 04819f9b

  • carlos run runs one of your app's commands against one instance. carlos run --app shop --instance www.example.com -- <command> runs it as that instance, with its environment and database, and prints the output as it arrives. --file uploads files with the run, up to 64 MB in total. --timeout sets how long it may take, 30 minutes by default and up to 6 hours. --follow <id> reattaches to a run already started. It needs an instance on the nested layout. carlos-run carlos run
  • New instances can start from a copy of another instance's database. carlos instances create --from <host> copies the source's replica, so the source keeps serving. carlos instances import brings an instance the platform never ran onto it, from a snapshot of its database. Both refuse until your operator turns them on. seeded-instances carlos instances
  • The download is smaller again. The linux/arm64 binary is about 46 MB, down from about 78 MB. fix-binary-size-275
  • Nothing else changes for people using the CLI.
For operators
  • Roll the boxes first, then every console. A run is refused until the console that records it is on this release. carlos-run
  • Coming from v0.26.x, read the v0.27.0 to v0.27.3 operator notes first. They all still apply.
  • Instance control restarts with this update. carlos system update does that on its own. A box updated any other way needs systemctl restart carlos-instance-control afterwards. carlos system
  • Give the console room for run uploads. The console holds a run's uploaded files, up to 64 MB per run, in its temporary directory until the box takes them. carlos-run
  • Seeded instances stay off until you publish the seeds floor. carlos instances create --from and carlos instances import refuse until carlos system seeds-floor publish names a release every box runs. Publishing it is one way: from then on no box recovers to an older build. Leave it unpublished until you have decided to turn seeding on. seeded-instances carlos instances carlos system
  • The host claim is still off. This release carries the claim's protected host state and the carlos system claims activation commands, but nothing uses them while CARLOS_HOST_CLAIM is unset. Errors from a route that has no app are now filed so the claim's checks can read the bucket. feat/claim-root-trusted-state-p3 feat/claim-files-backfill carlos system claims
  • Every dormant switch stays off. Leave CARLOS_SWAP, CARLOS_MOVES_PHASE1, CARLOS_HOST_CLAIM, CARLOS_HOST_CLAIM_ORIGINS, CARLOS_HOST_CLAIM_RETIRED_LOCATIONS, CARLOS_CONSOLE_ID, CARLOS_REGION_HA, CONSOLE_APP_REGIONS, CARLOS_TEMPORARY_APPS and CARLOS_REQUIRE_POINTER_DIGEST unset, and don't run carlos channels digests on. carlos channels digests

Changes

15
  1. feat/claim-root-trusted-state-p3WIP claim Plan 14 foundations (not for merge): descriptor-backed root state, root-owned D3 health history, release lock, floor reconstruction and migration preflight helpers, constructor census, root-read census with the legacy freeze

    Paul Campbell with claude, codex carlos proof history carlos system claims 26065378

  2. region-ha-2a-buildregion HA spec 2 (two-box regions), rev 1 draft, and its Astra brief

    Paul Campbell with claude #299 box and group roles 6834659c

  3. fix-empty-app-keyfix-empty-app-key

    Paul Campbell with claude e8e961dd

  4. runbook-home2-sharunbook-home2-sha

    Paul Campbell with claude e963691d

  5. moves-home-part2-planmoves-home-part2-plan

    Paul Campbell with claude a89e35ca

  6. feat/claim-files-backfillPrompts:

    Paul Campbell with claude #250 ee35dee2

  7. moves-overcap-cutmoves-overcap-cut

    Paul Campbell with claude 70e57449

  8. docs-rehearsal-dev-uk-secrets-keydocs-rehearsal-dev-uk-secrets-key

    Paul Campbell with claude a5003aba

  9. docs-rehearsal-dev-uk-bootstrapdocs-rehearsal-dev-uk-bootstrap

    Paul Campbell with claude 9f17062a

  10. hostfiles-cap-live-entrieshostfiles: the path cap applies to live entries only (LiveEntriesWithinCap), so a manifest written before the cap that holds a tombstone or skipped entry past it stays readable, and a moves recovery that selects it is not stranded (#236, moves' review of a8cebad)

    Paul Campbell with claude #236 #250 5f4ace8b

  11. seeded-instancescopy gate: the seeded-instances deck, pinned (Plan 1 Task 1)

    Paul Campbell with claude #292 carlos instances the seeds floor legacy route assignments f97898f1

  12. carlos-runspecs: carlos run (#259) and instances seeded from a database (#260, #261)

    Paul Campbell with claude #259 #260 #261 #280 #294 carlos run what an instance is started with carlos instance exec carlos instance exit 37ab10c5

  13. zdd-owed-itemsactivator: write a cold wake's build-state record at its exec (#272)

    Paul Campbell with claude #250 #272 #292 1c5718f6

  14. fix-binary-size-275binary-size-275: store SDK method values, not clients, in interfaces; add a size ceiling

    Paul Campbell with claude 132cf996

  15. changelog-v0.27.3Prompts:

    Paul Campbell with claude 2683f16a

  • Restarting the edge no longer leaves an instance unreachable for 15 minutes. If the edge stopped while an instance was waking, the instance could stay locked until its lease expired, and every request to it was refused for up to 15 minutes. The stopping edge now cancels the wake, makes sure it has stopped, and lets the lease go. If it cannot confirm the stop, it keeps the lease, as before. fix-shutdown-lease-292
  • New accounts never get a reserved address. An account's address is part of every app's hostname. Account creation now skips any address that spells a name the platform uses itself, such as dev, edge or www. Existing accounts keep theirs. reserved-sqids-285
  • Nothing else changes for people using the CLI.
For operators
  • Roll the boxes first, then the console.
  • Coming from v0.26.x, read the v0.27.0, v0.27.1 and v0.27.2 operator notes first. They all still apply.
  • Instance control restarts with this update. This release changes carlos-instance-control, so it has to restart on each box. carlos system update does that on its own. A box updated any other way needs systemctl restart carlos-instance-control afterwards. fix-shutdown-lease-292 carlos system
  • Roll the console as well as the boxes. Only a console on this release skips reserved account addresses when it creates an account. reserved-sqids-285
  • Every dormant switch stays off. Leave CARLOS_SWAP, CARLOS_MOVES_PHASE1, CARLOS_HOST_CLAIM, CARLOS_HOST_CLAIM_ORIGINS, CARLOS_HOST_CLAIM_RETIRED_LOCATIONS, CARLOS_CONSOLE_ID, CARLOS_REGION_HA, CONSOLE_APP_REGIONS, CARLOS_TEMPORARY_APPS and CARLOS_REQUIRE_POINTER_DIGEST unset, and don't run carlos channels digests on. With CARLOS_HOST_CLAIM set, instance control now refuses to start until a later release. carlos channels digests

Changes

5
  1. fix-shutdown-lease-292activator: Shutdown aborts a waking entry and gives its lease back with swaps off (#292)

    Paul Campbell with claude #272 #292 e15ad6be

  2. reserved-sqids-285reserved-sqids-285

    Paul Campbell with claude fc70bc75

  3. changelog-v0.27changelog-v0.27.x: v0.27.0, v0.27.1 and v0.27.2 (README release step 10)

    Paul Campbell with claude 8b5c7561

  4. rehearsal-p0-two-boxrehearsal-p0-two-box

    Paul Campbell with claude a3bfa662

  5. readme-roll-orderreadme-roll-order

    Paul Campbell with claude 4e577fde

  • Two builds at once keeps each build's socket name. Where a deployment turns on two builds at once, each build's socket now has the same file name it has with the switch off, in a directory of its own. An app that works out its own address from its socket's name now starts the same way either way. Before, such an app saw a different name for the new build and refused to start. Nothing changes where the switch is off, which is every deployment by default. zdd-gen-socket-names
  • Nothing changes for people using the CLI.
For operators
  • Roll the boxes first, then the console.
  • Coming from v0.26.x, read the v0.27.0 and v0.27.1 operator notes first. They all still apply.
  • A long host name keeps stop-then-start updates. With two builds at once on, a host on a flat box whose name is longer than 59 bytes is updated the old way: stopped, then started on the new build. Its socket path would otherwise be too long. zdd-gen-socket-names
  • Every dormant switch stays off. Leave CARLOS_SWAP, CARLOS_MOVES_PHASE1, CARLOS_HOST_CLAIM, CARLOS_HOST_CLAIM_ORIGINS, CARLOS_HOST_CLAIM_RETIRED_LOCATIONS, CARLOS_CONSOLE_ID, CARLOS_REGION_HA, CONSOLE_APP_REGIONS, CARLOS_TEMPORARY_APPS and CARLOS_REQUIRE_POINTER_DIGEST unset, and don't run carlos channels digests on. With CARLOS_HOST_CLAIM set, instance control now refuses to start until a later release. carlos channels digests

Changes

3
  1. zdd-gen-socket-nameszdd rev 19 amendment: generation sockets keep the flag-off file name

    Paul Campbell with claude #272 ebddcfc6

  2. startup-largebox-test-281startup-largebox-test-281

    Paul Campbell with claude d2f58fd3

  3. fix-cross-test-compilehost: rootinventory_test.go is linux-only

    Paul Campbell with claude 21d91fd6

  • A box with many instances no longer fails its update while it starts. On a box with over a hundred instances, v0.27.0's update could take longer than the 20 seconds it allows, because the edge waited for the agent to check every instance first. The box then rolled back after about 45 seconds of failed requests. The edge now starts serving straight away. Requests for an instance wait up to 30 seconds for that check to finish, then get the usual answer that the instance is waking. hotfix-startup-sweep-281
  • Nothing changes for people using the CLI.
For operators
  • Roll the boxes first, then the console.
  • Coming from v0.26.x, read the v0.27.0 operator notes first. They all still apply.
  • After each box updates, check that it finished starting. The update's 20-second check now passes once the edge serves, before the agent has checked every instance. So also check the box's journal for agent: hibernation activator armed, and that one request to a sleeping instance succeeds.
  • Every dormant switch stays off. Leave CARLOS_SWAP, CARLOS_MOVES_PHASE1, CARLOS_HOST_CLAIM, CARLOS_HOST_CLAIM_ORIGINS, CARLOS_HOST_CLAIM_RETIRED_LOCATIONS, CARLOS_CONSOLE_ID, CARLOS_REGION_HA, CONSOLE_APP_REGIONS, CARLOS_TEMPORARY_APPS and CARLOS_REQUIRE_POINTER_DIGEST unset, and don't run carlos channels digests on. With CARLOS_HOST_CLAIM set, instance control now refuses to start until a later release. carlos channels digests

Changes

1
  1. hotfix-startup-sweep-281hotfix #281: the edge no longer waits on the startup sweep and recovery

    Paul Campbell #281 6dfbff10

  • Root keeps its own record of each box's releases. A box's root process now keeps the builds it has seen run healthy, and the build each service ran before its current one, in directories only root can write. Before, it read them from places the platform's own service could write. Restarts, rollbacks and recovering from a bad build work exactly as they did. feat/claim-root-trusted-state
  • Nothing changes for people using the CLI.
For operators
  • Roll the boxes first, then the console.
  • Coming from v0.25.x, read the v0.26.0 operator notes and the v0.26.1 notes first. They all still apply.
  • Before rolling, check two things on each box. /, /var and /var/lib must be owned by root and not writable by group or others, and /var/lib/carlos-claims must not exist. If either check fails, root can't update a service that has its own unit, such as the console, on that box, and logs repoint failed: permission denied on every pass.
  • Health history starts empty. Root no longer reads the health history the service kept before this release. Don't add a require or prove entry for a service to /etc/carlos/proof-policy.json until both its current build and the one before it have been seen healthy since the roll. Otherwise rolling back to the earlier build waits for a proof.
  • One earlier build per service is kept. /opt/carlos/previous/<host> points at the build each service ran before its current one, and the box keeps that build when it prunes old versions. Disk use can grow by up to one build per service.
  • carlos __cgexec can appear in ps. Each new instance process now starts through a short-lived helper that places it in its cgroup before it runs. For a few milliseconds ps can show carlos __cgexec as a child of the agent. Monitoring, or a pkill that matches "carlos" in a command line, can catch it. zdd-flag-readiness-3
  • After the roll, check placement on each box. journalctl -u carlos-edge --since '<roll time>' | grep 'placement before exec failed' should print nothing. A line there means a process was moved into its cgroup after it started instead. That affects resource accounting, not serving. zdd-flag-readiness-3
  • Every dormant switch stays off. Leave CARLOS_SWAP, CARLOS_MOVES_PHASE1, CARLOS_HOST_CLAIM, CARLOS_HOST_CLAIM_ORIGINS, CARLOS_HOST_CLAIM_RETIRED_LOCATIONS, CARLOS_CONSOLE_ID, CARLOS_REGION_HA, CONSOLE_APP_REGIONS, CARLOS_TEMPORARY_APPS and CARLOS_REQUIRE_POINTER_DIGEST unset, and don't run carlos channels digests on. With CARLOS_HOST_CLAIM set, instance control now refuses to start until a later release. carlos channels digests

Changes

7
  1. changelog-v0.26.1changelog: v0.26.1 (release step 10)

    Paul Campbell with claude f4cf27dd

  2. zdd-flag-readiness-3plan: zdd flag readiness round 3 (draft)

    Paul Campbell with claude #272 2e00b17e

  3. feat/claim-root-trusted-stateclaim Plan 14 Part 1 (#280): root-trusted state foundations, families B, C and D

    Paul Campbell with codex #280 645a7d05

  4. hotfix-instance-key-gatehotfix-instance-key-gate

    Paul Campbell with claude 34a4328f

  5. zdd-flag-readiness-2plan: zero-downtime flag readiness, round 2 (draft for Astra's review)

    Paul Campbell with claude ba52d5ef

  6. changelog-nested-bulletschangelog-nested-bullets

    Paul Campbell with claude 67698c9c

  7. changelog-v0.26.0changelog-v0.26.0

    Paul Campbell with claude 729e8508

  • A box with many instances no longer fails the update. v0.26.0 gave every instance on a box its key before the edge started, with one bucket read per instance. On a box with over a hundred instances that took longer than the 20 seconds the update allows, so the box rolled back after about half a minute of failed requests. The keys are now written in the background once the edge is serving, and the update no longer waits for them.
  • Nothing changes for people using the CLI.
For operators
  • Roll the boxes first, then the console.
  • Coming from v0.25.x, read the v0.26.0 operator notes first. They all still apply, and that includes any box that rolled back from v0.26.0. Restart carlos-instance-control.service on each box after it updates, run the instance key checks before any box rolls, and check what root's AWS settings rely on (#267).
  • Wait for the instance key line. agent: instance keys: now comes after hibernation activator armed, up to about a minute after the agent starts. Wait for it before you check for 0 failed. It also counts rows skipped because a move or a layout change held the host. Those get their key at their next start.
  • Every dormant switch stays off. Leave CARLOS_SWAP, CARLOS_MOVES_PHASE1, CARLOS_HOST_CLAIM, CARLOS_HOST_CLAIM_ORIGINS, CARLOS_HOST_CLAIM_RETIRED_LOCATIONS, CARLOS_CONSOLE_ID, CARLOS_REGION_HA, CONSOLE_APP_REGIONS, CARLOS_TEMPORARY_APPS and CARLOS_REQUIRE_POINTER_DIGEST unset, and don't run carlos channels digests on. The v0.26.0 notes say where each one is set. carlos channels digests

Changes

2
  1. console test: the layout guard's at-floor update asks for a version the vendor feed can never publish

    Paul Campbell with claude 9aaeace2

  2. agent: run the instance-key backfill after Start, off the edge's path (v0.26.1)

    Paul Campbell with claude b8ddad18

  • Two builds at once, off until your deployment turns it on. Where it is on, a new build starts beside the old one and takes over once it passes its health check, so no request waits. For a few seconds both builds share the instance's database and its scheduled work, and the new build's migrations run while the old one still serves. So add a column, table or index in one release and drop the old one in a later release. Keep the names of scheduled work (carlos schedule) the same across the two builds. A release that can't follow these rules ships with --swap hold on carlos deploy or carlos ship, which stops each instance before its new build starts. carlos apps set <app> --swap hold makes that the app's rule, and --swap-concurrency sets how many instances swap at once on one box. Every deployment ships with this off. zdd-1-generations zdd-2-containment zdd-3-swap zdd-4-release-side zdd-5-scheduler zdd-6-surfaces zdd-flag-readiness carlos schedule carlos deploy carlos ship carlos apps
  • carlos deploy follows the rollout box by box. Where a box reports its rollout, deploy counts an awake instance once the new build has passed its health check and taken over, and an asleep one once its box has installed the build. If the build fails on a box, that box stops rolling it out, and deploy names the failure and exits with an error. Boxes report only where two builds at once is on. Everywhere else deploy watches the app's URL, as before. If the console can't list the app's instances, deploy keeps asking until its deadline and then says the list could not be read. zdd-6-surfaces zdd-flag-readiness carlos deploy
  • carlos instances list shows two builds. INSTALLED is the build on the instance's box, and SERVING is the one answering its requests. They differ while a build rolls out, while an asleep instance waits for its next request, and after a build has failed on that box. REASON says which. A dash under SERVING means the box doesn't report it, which is every box until two builds at once is on. carlos instances retry <host> clears the failure hold on one instance, so the build that failed there is tried again as a canary. zdd-4-release-side zdd-6-surfaces carlos instances
  • Choose how each instance takes new builds. carlos instances set <host> --updates manual stops an instance taking new builds on its own. --channel, --major (stable only) and --pin <build> set the rest, and an empty value goes back to the app's default. carlos instances update <host> asks the box to install the newest build it considers ready, even with manual updates. --fast-track skips the safety delay, and only account owners can use it. On the app, carlos apps set --instance-control updates,pin names the settings an instance may change for itself once instances can act for themselves. --default-updates, --default-major and --default-channel set the app's defaults. The console accepts manual updates, a major hold or a pin only once every box can keep the builds they name, and says how many boxes it is waiting for. settings-3-console-settings settings-4-root-applies settings-5-surfaces carlos instances set carlos instances update carlos apps
  • Read a database as it was. carlos db pull --at <time> and carlos db query --at <time> read an instance's database as it was at an earlier time, given in RFC 3339 form such as 2026-10-07T14:00:00Z. The copy is never newer than that time, and the command says which transaction it stopped at. Ask for a time before the oldest history and it names the oldest time you can use. Instances that sleep now keep seven days of history, as awake ones do. That week fills in over the seven days after your deployment rolls this release. db-pull-at hibernate-retention carlos db
  • Channel digests. carlos channels digests shows whether channel pointers carry the sha256 of each build's manifest, and lists the channels that don't yet. Once a deployment turns digests on, boxes refuse pointers without them. So update the CLI on every machine and CI job that promotes, rolls back or fast-tracks before then. carlos channels resign <channel> re-signs a channel nobody has promoted to since digests went on. It shows every digest and signs only when you type yes. settings-1-pointer-digests carlos channels digests carlos channels resign
  • carlos releases authorize <app> <version>, for operators. It shows a build's manifest and file digests and, when you type yes, signs a promotion record for exactly those bytes. Every promotion now writes one. This is for a build promoted before records existed, so an instance can be pinned to it or recovered onto it. settings-2-promotion-records carlos releases
  • What an instance is started with. Every instance and seed now gets CARLOS_HOST, its hostname exactly as carlos instances list shows it. Read it, never the socket's file name. On an isolated box, an instance starts in its own data directory, the one its database is in, so a relative path such as ./data/blobs lands beside its database. Files and directories named after the host, such as <host>/ or <host>-blobs, now move with an instance when its box isolates it, and come back on a revert. fix-roll-incident-256 carlos instances
  • carlos move, off until your deployment turns moves on. It moves one instance to another region. The instance keeps serving while its data is copied, then goes offline for the cut. If the new region can't start it, the move takes it back on its own. Against a console without moves, carlos move sends nothing. moves-phase1 moves-phase1-2 moves-phase1-3 moves-phase1-3b moves-phase1-3c moves-phase1-4 moves-phase1-5 moves-phase1-5b moves-phase1-5c moves-phase1-5d moves-phase1-5e moves-phase1-5f moves-phase1-6 moves-phase1-7 moves-cut-guard carlos move
  • Smaller fixes. A build of about 100 MB no longer runs the box's staging out of memory, so its promote no longer waits for the hourly pass. carlos sidecars ls shows the build each sidecar's box last started, and "unknown" for one that hasn't started anywhere. carlos instances set-channel finds a host typed with capitals, and for a box route with no instance record it says how to move the route on its box. stage-stream-artifact zdd-6-surfaces setenv-box-route-error carlos sidecars carlos instances
For operators
  • If your boxes haven't run v0.25.1, read its operator notes and v0.25.0's first. They all apply to this release.
  • Roll the boxes first, then the console. Roll the boxes with carlos system update. carlos system
  • After each box updates, restart carlos-instance-control.service on it. The update runs the code the box already has, which installs this release without restarting that service. This release's agent refuses to wake isolated instances while the service runs an older build, and the reason in carlos logs ends with restart carlos-instance-control.service. carlos system status still reads current, so it won't tell you. From this release on, carlos system update restarts the service itself. fix-roll-incident-256 carlos logs carlos system
  • Before any box rolls, run the instance key checks. This release writes a CARLOS_INSTANCE_KEY into each instance's <host>.env the first time it starts, and starts a replica only with its home's key. instance-key-provision instance-key-build
    • On every box, find <data> -maxdepth 1 -name '*.env' -type l must print nothing. A <host>.env that is a symlink now fails that instance's start. Stop the instance, replace the link with the real file, and treat the token in it as leaked.
    • On every box with a replica (sqlite3 <data>/registry.db "select host from routes where replica=1"), compare each replica's key with its home's. A key is the last CARLOS_INSTANCE_KEY line of <host>.env, or of <host>.config.env when <host>.env has none, in the data directory for a flat instance or the instance's own directory for an isolated one. Where the two match, add <replica-host>=<sha256 of the key> to /etc/carlos/replica-home-keys on the replica's box before it rolls. Write the whole list to a temporary file in /etc/carlos, make it root:carlos 0640, and rename it into place. Where they differ, the replica is refused after the roll. Tell its owner first.
    • A replica with no key keeps starting where it has a control socket, but its legacy sidecar and any worker row of its own stop at the roll. List them on each box with a replica, and tell their owners.
    • Check the agent can read the list: sudo -u <agent user> test -r /etc/carlos/replica-home-keys && echo ok must print ok.
    • After the roll, journalctl -u carlos-edge --since '<roll time>' | grep 'agent: instance keys:' must show 0 failed.
  • Root ignores AWS profile, endpoint and trust-store settings. A box's root processes now ignore AWS_PROFILE, AWS_DEFAULT_PROFILE, AWS_CA_BUNDLE, the AWS_ENDPOINT_URL variables, SSL_CERT_FILE, SSL_CERT_DIR and shared AWS config files, and log an alert when one is set. Before rolling, check that no box's host.env depends on them. On a box outside AWS, /etc/carlos/credentials must hold only static keys under [default]. The agent rewrites it as root:carlos 0640 on every start. fix/267-credentials fix/267-adopt-writes docs/267-remote-host
  • Every dormant switch stays off. Leave each of these unset, and run none of the commands named, until its own rollout is approved. carlos system carlos system journal migrate carlos channels digests
    • CARLOS_SWAP on every box. Two builds at once still has open items, and only the exact word overlap arms it.
    • CARLOS_MOVES_PHASE1 on the console and every box. Don't publish a moves protocol floor (control/moves-protocol.json) either.
    • CARLOS_HOST_CLAIM, CARLOS_HOST_CLAIM_ORIGINS and CARLOS_HOST_CLAIM_RETIRED_LOCATIONS on the console and every box, and CARLOS_CONSOLE_ID on the console. Don't run carlos system guard-arm or carlos system journal-migrate.
    • CARLOS_REGION_HA on every box.
    • CONSOLE_APP_REGIONS and CARLOS_TEMPORARY_APPS on the console.
    • CARLOS_REQUIRE_POINTER_DIGEST on every box. Don't run carlos channels digests on yet.
  • Host claims: every roster reader first. Binaries older than this release reject a signed roster that names a home region. So before anyone publishes the home designation, every reader of control/host-actors.json must run this release: every console, every box's agent and root services, the update and rollback tools, and any offline or recovery binary. The designation is write-once, and this roll doesn't publish it. feat/hostclaim-home-region fix/home-region-followups
  • Digests: writers before readers. Once a box has verified a channel pointer with digests, it refuses pointers for that channel without them. So first upgrade every writer: every console, and every CLI or deploy script that promotes, rolls back or fast-tracks. Then run carlos channels digests on, and watch carlos channels digests until it lists nothing. Only then set CARLOS_REQUIRE_POINTER_DIGEST=on in every box's host.env. carlos channels digests off stops writers adding digests while one is fixed, but doesn't clear boxes that have already seen them. settings-1-pointer-digests carlos channels digests
  • Instance update settings wait for every box. The console refuses manual updates, a major hold or a pin until every box reports it can keep the builds they name. Before rolling any box back below this release, run carlos releases retention --off for each app that has a retention policy, because an older box prunes builds a pin or a held instance still needs. After such a rollback the console shows settings not enforced for instances on the older boxes. settings-4-root-applies settings-5-surfaces carlos releases
  • Remove the staging memory drop-ins after the roll. Staging now streams a build to disk instead of reading it into memory. A deployment that raised the memory of carlos-stage.service or carlos-adopt.service with a drop-in can remove it from every box, and from its box bootstrap, once every box runs this release. stage-stream-artifact
  • The deployment-buckets module now guards fence writes. Its new statement refuses every write under control/box-fences/ from a role not listed in box_fence_writer_role_arns. Nothing writes there while host claims are off, so applying it now is safe. feat/hostclaim-activation
  • Files left behind by earlier moves. An instance its box isolated before this release may have left files named after its host in the shared data directory. carlos status --layout and the agent log now name them on every pass. Move them into the instance's directory by hand. fix-roll-incident-256 carlos status

Changes

68
  1. moves-copy-approve-p5fmoves-copy-approve-p5f

    Paul Campbell with claude 09c5a4a5

  2. region-ha-1b-next-buildplan: region HA 1b-next, relocation released by stop evidence or a termination fence, reconcile row cases, create's once-only executor choice, and fences consumed in claim CASes

    Paul Campbell with claude #66 #236 #278 #279 a8cebade

  3. moves-plan15-proofmoves-plan15-proof

    Paul Campbell with claude 68b6ab5e

  4. region-ha-two-box-buildRegion HA two-box model: plan rev 11 and its Astra reviews (from region-ha-hostlife-two-box 8f95c4e0)

    Paul Campbell with claude 93ceb6cd

  5. settings-5-surfacessettings-5 task 1: draft plan 5's update settings copy for review

    Paul Campbell with claude carlos apps carlos instances set carlos instances update d850865b

  6. feat/claim-admitted-provenancefeat/claim-admitted-provenance

    Paul Campbell with codex 01edf901

  7. moves-phase1-5fmoves-phase1-5f

    Paul Campbell with claude d6122533

  8. moves-restoring-source-protectionmoves: restoring keeps the source region authoritative until a clean return or the commit (J2/F4, L18 finding 1)

    Paul Campbell with claude 650e6152

  9. settings-4-root-appliessettings-4 task 1: the build state, its registry copy, and root's consumed file

    Paul Campbell with claude 8916558d

  10. feat/claim-loss-pagesfeat/claim-loss-pages

    Paul Campbell with claude, codex 39986908

  11. zdd-flag-readinesszdd-readiness: implementation plan for the flag-readiness round (#272)

    Paul Campbell with claude #1 #2 #5 #6 #9 #10 #272 8ebd9d8c

  12. fix/home-region-followupsfix/home-region-followups

    Paul Campbell with claude, codex 2ad5412c

  13. feat/hostclaim-home-regionfeat/hostclaim-home-region

    Paul Campbell with codex a0806e4c

  14. moves-held-lockmoves-held-lock

    Paul Campbell with claude dde859f3

  15. moves-home-parksmoves-home-parks

    Paul Campbell with claude 359e8ac2

  16. moves-phase1-7moves-phase1-7

    Paul Campbell with claude 0715faca

  17. feat/hostclaim-moves-integrationfeat/hostclaim-moves-integration

    Paul Campbell with codex 1b5802fb

  18. moves-cut-guardmoves-cut-guard

    Paul Campbell with claude b04ff852

  19. moves-copy-approve-58moves-copy-approve-58

    Paul Campbell with claude bd9d6321

  20. moves-phase1-6moves-phase1-6

    Paul Campbell with claude carlos move bc25674a

  21. instance-key-buildInstance key provision (region HA L21): the platform mints CARLOS_INSTANCE_KEY create-only and durably into <host>.env on every launch path once configuration is delivered, gates every replica launch on its home's verified key, adds the writer-bound adoption verb (unmounted until O6/O7) and a legacy-box startup backfill, and carries the key byte for byte through re-render and moves. Rastrillo's carlos.InstanceKey consumes it. Effectively dormant until apps adopt the helper; rollout has pre-roll checks.

    Paul Campbell with claude #66 #162 #273 43da77c2

  22. zdd-6-surfaceszdd-6 task 2: rolloutwords, the one home for rollout phrases

    Paul Campbell with claude #1 #2 #3 #4 #5 #6 #7 #8 #9 carlos apps carlos deploy two builds at once carlos instances carlos sidecars 5da1cc9b

  23. settings-3-console-settingssettings-3 task 1: release.UpdateSettings

    Paul Campbell with claude 30866251

  24. moves-phase1-5emoves-phase1-5e

    Paul Campbell with claude 5157c1e7

  25. moves-phase1-5cmoves-phase1-5c

    Paul Campbell with claude e79d71b5

43 more
  1. moves-phase1-5dmoves-phase1-5d

    Paul Campbell with claude d562d7f2

  2. instance-key-provisionInstance key provision (region HA L21) implementation plan

    Paul Campbell with claude 0901e835

  3. fix-restore-wal-leftovershostbox: ColdRestore removes the temp database's -wal and -shm

    Paul Campbell with claude 0d338c14

  4. settings-2-promotion-recordssettings-2 task 1: internal/updatewords, the draft strings for the settings plans

    Paul Campbell with claude carlos releases 70f8119f

  5. feat/hostclaim-moves-recoveryfeat/hostclaim-moves-recovery

    Paul Campbell with codex 44c1b6d7

  6. docs/267-remote-hostdocs, lease: remote-host runbook for root:carlos 0640 credentials and the fresh-inode repair; the off-cloud session-token error (#267, copy approved by Paul 2026-10-10)

    Paul Campbell with claude #267 843b7180

  7. zdd-5-schedulerzdd-5 task 1: pin the plan 1-4 surface; CARLOS_SWAP flag

    Paul Campbell with claude d905a676

  8. fix/268-lease-marginlease: TestBlockedRenewalDeadlinePrecedesTakeover runs at a 3s TTL so its termination margin outlasts CI scheduling (#268)

    Paul Campbell with claude #268 d6f66ef3

  9. fix-moves-floor-gatemoves floor gate: compare the floor file in Go, not with cmp

    Paul Campbell with claude #267 00fdf541

  10. feat/hostclaim-region-hafeat/hostclaim-region-ha

    Paul Campbell with claude, codex 93ef4b50

  11. moves-phase1-5bmoves-phase1-5b

    Paul Campbell with claude ca591df7

  12. fix/267-credentialsfix/267-credentials

    Paul Campbell with codex 75618480

  13. moves-phase1-3cmoves-phase1-3c

    Paul Campbell with claude a34623bd

  14. fix/267-adopt-writesfix/267-adopt-writes

    Paul Campbell with claude, codex 2d3ff963

  15. fix/registry-chown-nofollowfix/registry-chown-nofollow

    Paul Campbell with claude, codex 29dab2d8

  16. stage-stream-artifactrelease: stream the artifact to disk while staging (#269)

    Paul Campbell with claude #269 cd987f6c

  17. zdd-3-swapzdd plan 3 task 1: swap types, the SwapBackend seam, flat staged spawn without health, each artifact's tier, canonical link at the switch

    Paul Campbell with claude #4 a3bf7d6c

  18. moves-phase1-5moves-phase1-5

    Paul Campbell with claude da76647b

  19. feat/hostclaim-activationclaim Plan 9: activation readiness (amadan #250), Paul's six rulings, ResolveMoveStart, moves C1 integration

    Paul Campbell with claude, codex #250 cancel an unpublished activation carlos system journal migrate abcc732d

  20. moves-copy-approve-2moves copy: Paul approved the 16 rows from Plans 3 and 4 (2026-10-09), no edits

    Paul Campbell with claude 17d5960b

  21. moves-copy-driftmoves copy: bring 24 approved rows to their code, 21 stay pending

    Paul Campbell with claude 94263187

  22. fix-fdholders-alias-teststopevidence test: wait until fd 3 holds the database by identity before scanning (flaky on arm64 CI)

    Paul Campbell with claude 316a0768

  23. moves-copy-approve-1moves copy: Paul approved the 205 reviewed rows (2026-10-09); 160 applied rows marked approved

    Paul Campbell with claude 33425265

  24. moves-phase1-4moves-phase1-4

    Paul Campbell with claude 412ca787

  25. settings-1-pointer-digestssettings-1 task 2: manifest digests and GetManifestRaw

    Paul Campbell with claude #1 #2 #3 #4 #5 #6 #7 #8 carlos channels resign carlos channels digests 8d33cef1

  26. hibernate-retentionhibernate-retention: sleeping instances keep 7 days of snapshots, like awake ones (#263)

    Paul Campbell with claude #263 f36718c5

  27. zdd-2-containmentzdd-2-containment

    Paul Campbell with claude 218b7454

  28. zdd-4-release-sidezdd-4 task 1: Manifest.Swap, the release's own demand (additive)

    Paul Campbell with claude db8c3f06

  29. zdd-1-generationszdd-1-generations

    Paul Campbell with claude 8e066e29

  30. db-pull-atdb-pull-at: carlos db pull/query --at reads a database as of a past time (#262)

    Paul Campbell with claude #262 carlos db 1621d271

  31. setenv-box-route-errorinstances set-environment/set-channel: say what a 404 really was (#264)

    Paul Campbell with claude #264 04aaa23b

  32. moves-phase1-3bmoves-phase1-3b

    Paul Campbell with claude 4a51a6da

  33. moves-phase1-3moves-phase1-3

    Paul Campbell with claude 81d0cc60

  34. fix-roll-incident-256Roll incident #256: system apply restarts instance-control; app entries move with the host; CARLOS_HOST; WorkingDirectory for instances

    Paul Campbell with claude #256 what an instance is started with the platform s own binary instance layout carlos instance control 56ebee16

  35. moves-phase1-2moves-phase1-2

    Paul Campbell with claude 4f26f15c

  36. feat/hostclaim-consolefeat/hostclaim-console

    Paul Campbell with claude, codex 76f728a9

  37. feat/hostclaim-box-assemblyhost, hostbox, registry, activator, provision, instancectl, cgroup, schedule, hostguard, console: claim Plan 6b, production assembly of the box wiring

    Paul Campbell with claude, codex a4cd3003

  38. fix/fdholders-lstatstopevidence: an fd entry that exists but cannot be followed is unreadable, not closed

    Paul Campbell with claude 9cf9f18f

  39. fix/fdholders-inodestopevidence: FDHolders matches the open file's device and inode, not only its path

    Paul Campbell with claude 8e9ac1b8

  40. fix/moves-copy-gate-scopemoves copy gate: inventory only moves code, and skip the diff checks where git cannot name the merge base

    Paul Campbell with claude e5adf329

  41. fix/c7-moves-intenthostclaim: the pre-flip conversion reads the move's own intent (C7 contract with moves)

    Paul Campbell with claude cfdb4e12

  42. moves-phase1moves-phase1

    Paul Campbell with claude 17362eaf

  43. changelog-v0.25.0changelog: v0.25.0 (release step 10)

    Paul Campbell with claude 76b1400f

  • Isolated instances now happen. v0.25.0 moved instances into their own box only on a box whose isolation probe passed, and no box could pass. Part of the probe checked the box's addresses using a kind of socket the probe's own unit is not allowed to open. The control service now makes that check itself, reading the addresses from /proc. Boxes whose other checks pass are now ready, and their instances move as v0.25.0 described.
  • Isolated instances stop cleanly. Inside its own box, an app ran as the first process, where the kernel ignores any signal the app has no handler for. A Go app with no SIGTERM handler could not be stopped: each stop waited 20 seconds, killed it, and left the unit failed. A small init now runs first. It passes stop signals on to the app, cleans up exited processes, and exits with the app's status. An app that dies by a signal now shows as exit 128+n in its instance event line, so a crash on SIGSEGV reads instance exited: exit 139. It used to read signal.
  • Temporary static sites, off until a deployment turns them on. carlos deploy --temporary ./dist creates an app named tmp- plus six letters and digits, or tmp-<name> with --app <name>. It lives 7 days, or what --ttl says (1h to 30d). When its time is up it moves to the Trash, and it is purged 3 days later instead of 30. carlos apps ttl moves the expiry and carlos apps keep makes it permanent. A temporary app is served only at its own platform address, so --host and --kind binary are refused, and an account holds at most 20. carlos deploy carlos apps
  • Names starting with tmp- are reserved for temporary sites. carlos apps create, carlos add --app, renames and console grant refuse them, whether or not temporary sites are on. carlos apps carlos add
  • carlos apps list shows every app in the account, the Trash included, and when each expires or is purged. carlos apps
  • carlos ship checks the program. For a Go binary, ship records its main package in the manifest. It refuses a release whose main package differs from the app's latest release. When the change is meant, ship with --program-change. carlos deploy has no such flag, so use carlos ship --program-change and then promote. Boxes check the bytes too, so a release shipped by an older client is refused at adoption and is not pointed live. A build the route has run before is always accepted, so going back across an intended change works. carlos ship carlos deploy
  • A console that will not start is rolled back. After a box adopts a new build for a route with a named unit, such as the console, it waits for the unit to stay up and accept connections. If it doesn't, the box rolls back, refuses that promotion and alerts. A plain re-promote stays refused. carlos promote --retry <version> <channel> tries again. carlos status --live shows refused hosts. carlos promote carlos status
  • GeoIP for apps. On a deployment that has published a GeoIP database, every request to an app carries the visitor's rough location in X-Carlos-Geo-Country, X-Carlos-Geo-Subdivision, X-Carlos-Geo-Lat, X-Carlos-Geo-Lon and X-Carlos-Geo-Source. Any of them can be missing; treat that as unknown. The edge removes any of these a visitor sends. Analytics count page views by country and credit the database. carlos geo <address> --app <a> gives the same answer for any address, and apps can call GET /api/cli/apps/<account>/<app>/geo?ip=<address>, at most 60 a minute. An app that shows visitors anything worked out from these headers must credit the database X-Carlos-Geo-Source names. carlos geo
For operators
  • If your boxes have not run v0.25.0, read its operator notes first. All of them apply to this release.
  • Instances move to the nested layout on their own, and this time they will. v0.25.0's note applies again. With no layout intent recorded, every box whose isolation probe passes starts moving its instances on the first change it sees after this release lands. Awake instances get an hour, then are stopped and moved. This includes boxes that already run v0.25.0 and recorded nothing. To keep control, record carlos system layout revert before you roll, then carlos system layout migrate --box <label> one box at a time, or put CARLOS_LAYOUT_DEFAULT=flat in a box's host.env to leave that box alone. carlos system
  • Before rolling, check one box: systemctl start carlos-instance-probe.service then read /run/carlos-control/probe.out. It must say ready: true. The control service no longer opens a resolver that is one of the box's own addresses. It reports that as a failing resolver-local line, and if it cannot read the box's addresses it opens no resolver at all. Landlock must be in the booted kernel's lsm= list, and /etc/resolv.conf (or resolved's upstream list) must name a resolver that isn't on loopback.
  • Roll the boxes before the console. The rollback, wrong-program and tmp- checks run on the box, and so does removing forged GeoIP headers.
  • Fix each console box's binding before you rely on the rollback. The rollback check runs only when the console unit's ExecStart names the live link of the route stamped with that unit. Where it doesn't, adopt logs binding: … restart not checked and restarts the unit as before, unchecked. On each console box, read systemctl show -p ExecStart console.service, stamp that host with carlos route --host <host> --unit console.service, and clear the stamp from any other host with --unit "". Until the binding is right, keep the final systemctl restart in your console roll. carlos route
  • The rollback check is on everywhere. After adopting a build for a route with a named unit, the box waits up to 30 seconds (CARLOS_UNIT_SETTLE, at least 5s) for the unit to stay up on the new build and accept connections. If it does not, the box rolls back, writes a refusal and alerts through SNS or CARLOS_ALERT_WEBHOOK. If your console takes longer than that to start listening, raise CARLOS_UNIT_SETTLE on its box before you fix the binding. With CONSOLE_GEOIP_DB set, the console now checks that file in a separate process before it listens.
  • The wrong-program check is on everywhere. A box refuses a staged binary whose Go main package differs from the live build's and from every program that route has run before, unless its manifest records --program-change. The refused build is not pointed live and nothing restarts. Each route starts its history from its live binary on its first pass. The console's ship door makes the same check once the console runs this release. The carlos binary is never a console artifact; build the console from ./cmd/console.
  • Dev proofs are off. They are off unless a box has /etc/carlos/proof-policy.json (root, mode 0644). On a proving console box, run carlos proof keygen as root, then write a policy file with a prove block: the apps, the prover's name, how long a build must run (after, such as 15m) and key_file. That box then mints a proof for each build that runs healthily for that long. On a requiring box, a require entry names the app, the prover and its public key. A new build of that app is then adopted only with a proof for those exact bytes, or if the box has already run that build healthily. Carry a proof with carlos proof get against the proving deployment and carlos proof put against the requiring one. carlos status --live shows a host that is waiting. A policy file that does not parse holds every named-unit route on its current build and says so in the journal. To switch the requirement off, delete the require entry (or the file) as root and run carlos adopt --stage-only. The box then logs once an hour that it is off. Write policy files on the box over SSM, not through tofu user_data. carlos proof carlos status carlos adopt
  • Temporary sites are off until you set CARLOS_TEMPORARY_APPS=1 on the console. The console adds four columns to its apps table when it starts. The change is additive. Its expiry pass runs every 5 minutes either way, and with no temporary apps it does nothing. Before you turn them on, roll every box, then check that no box's registry and neither the console's apps nor its owners table has a tmp- name. An expiry drops a temporary app's routes, so rename or remove any tmp- name you find first.
  • Platform GeoIP sends nothing until you publish a database. From this release every edge removes forged X-Carlos-Geo- headers and watches the bucket for a database. carlos system geoip publish <file.mmdb> sends one, and every edge picks it up within 12 minutes. Publish only after carlos system geoip status says ready, because a box on an older release passes a visitor's forged headers straight through. A retired box that still has control/edges/<label>.json keeps it from saying ready; delete that record. carlos system geoip off removes the database. On the console box, check that the console can read /data/carlos/geoip/current: with CONSOLE_GEOIP_DB unset, the console's region guess now uses that copy. carlos system
  • The GeoIP feed is off until you set CONSOLE_GEOIP_FEED. dbip-city-lite is free, needs nothing else, and requires the credit the platform already shows. For MaxMind, also set CONSOLE_GEOIP_MAXMIND_ACCOUNT and CONSOLE_GEOIP_MAXMIND_KEY. The console checks once a day. A GeoLite2 database is dropped 30 days after it was built. Before you publish GeoLite2, apply the deployment-buckets module version that expires old copies under control/geoip/ after a day. It is the module's first lifecycle configuration, and a bucket holds one, so check whether yours already has one before you apply.
  • A new geoip box alert sits beside disk, mem, cpu and lag. It fires after 30 minutes when the loaded database is over 45 days old, a GeoLite2 database is 21 days old, the database has expired, a box has not loaded the published database for over an hour, or the feed has failed 7 checks in a row. With no database and no feed it never fires.
  • Host claims stay dormant. Leave CARLOS_HOST_CLAIM unset, on the console and on every box. On a box, any value that is not blank stops the agent from starting. On the console, it starts claim recovery and backfill that have nothing to work from yet. Leave CARLOS_CONSOLE_ID unset on the console too. Do not run carlos system guard-arm. It replaces how the update, edge and console units start, and once armed it is enforced whatever CARLOS_HOST_CLAIM says. With all three left alone, nothing in this release writes or reads host claims. carlos system

Changes

9
  1. platform-changelogchangelog: carlosframework.com/platform/changelog, generated from git, release notes and Amadan

    Paul Campbell with claude 289043db

  2. feat/hostclaim-consolefeat/hostclaim-console

    Paul Campbell with claude, codex 3407d114

  3. feat/hostclaim-floorfeat/hostclaim-floor

    Paul Campbell with claude, codex #250 host lifecycle guard cbc0922e

  4. geoip-followupsGeoIP follow-up (#241): DirStore.Put CAS gate by Stat and streamed hash, so an oversized object at the key is never read into memory (Astra R2-1); restore the thirteen code-review reports lost with the build worktree; Astra round 14 merge-ready.

    Paul Campbell with claude #241 e0bec091

  5. geoip-for-appsPlatform GeoIP for apps (#241): bucket-mirrored database with hot swap on every edge; X-Carlos-Geo-* headers set by the ingress edge and carried across hops and tunnels; analytics countries with attribution; carlos system geoip publish/status/off; auto-update feed (DB-IP Lite default, GeoLite2 or paid MaxMind GeoIP2); geoip box alert; console follower, GET /api/cli/apps/{a}/{app}/geo and carlos geo; untrusted .mmdb verified only in a killable, memory-capped child. Spec rev 13 (Astra-accepted), 13 Astra code-review rounds.

    Paul Campbell with claude #241 #249 carlos analytics headers your app receives carlos geo platform geoip 6bdaba34

  6. fix-instance-initNested instances: a minimal init as PID 1 forwards stop signals and reaps, so apps stop cleanly (#126)

    Paul Campbell with claude #126 carlos instance exec 40b6f50c

  7. design-console-release-defencesConsole release defences: D1 settle and rollback, D2 wrong-program refusal, D3 opt-in dev proofs (after the 2026-10-06 console outage)

    Paul Campbell with claude #252 carlos proof 9e628024

  8. fix-probe-resolver-portsProbe: resolver checks no longer need netlink; the control service reads local addresses from /proc (#126)

    Paul Campbell with claude #126 3de0b0fc

  9. design-temporary-sitesTemporary static sites: self-expiring tmp- apps, trashed at expiry, purged 3 days later

    Paul Campbell with claude carlos apps carlos deploy 1da67e63

  • Each instance runs in its own box. Instances the platform starts on demand used to share one user and one data directory on a box, so one app could read another app's files. From this release, a box whose isolation checks pass moves every such instance into its own directory and its own mount and process namespace, where it sees its own files and nothing else. A sleeping instance moves at once; an awake one gets an hour to go to sleep, then is stopped briefly and moved. New instances on that box start out isolated. carlos status --layout shows where each box is. tenant-iso-default-nested tenant-iso-layout carlos status
  • carlos system layout lets an operator choose instead: migrate --box <label> moves one box at a time, and revert moves everything back. status prints what is recorded. tenant-iso-plan5 carlos system
  • Instances get CPU and IO limits beside their memory cap, see only their own app's build, and can't reach loopback or private addresses on the box except its DNS resolver. New starts are refused while the disk is nearly full. tenant-iso-hardening
  • Custom domains can require proof. On a deployment that sets CONSOLE_DOMAIN_PROOF=true, carlos domains attach reserves the name and prints a TXT record, and the name isn't served until carlos domains verify finds it. Names under another account's platform domain are refused everywhere. tenant-iso-domains carlos domains
  • Only a platform operator can add an upstream address to an instance. Upstreams an instance already has keep working, and can be kept, reordered or removed. tenant-iso-routes
  • Cookies stay within their account. On a platform hostname, a cookie whose Domain reaches beyond the app's own account is made host-only by the edge. tenant-iso-cookies
  • Instance catch-all domains. carlos domains attach --app <a> '*.<parent>' gives every instance of the app a public name, <slug>.<parent>, with no per-instance claim or DNS. instance-catchall carlos domains
  • carlos email test sends HTML too. The test message is now multipart, with a plain-text and an HTML part, so it shows that HTML mail gets through. Apps can send any MIME message over their credential. multipart-email-support carlos email
  • Smaller fixes. Re-attaching a static site's own hostname to flip --wildcard or --catchall no longer turns its route into an alias of itself. A box no longer places a certificate order every hour for a platform domain whose DNS zone its provider doesn't hold. first-route-wildcard wildcard-zone-check
For operators
  • Instances move to the nested layout on their own. This is the first release on which isolated instances run. With no layout intent recorded, every box whose isolation probe passes starts moving its instances on the first change it sees after this release lands. Awake instances get an hour, then are stopped and moved. A move refused for a reason a tenant could have caused (a planted hard link, a symlinked directory) keeps that instance stopped until an operator clears it; carlos status --layout names it. To keep control, record carlos system layout revert before you roll, then carlos system layout migrate --box <label> one box at a time, or put CARLOS_LAYOUT_DEFAULT=flat in a box's host.env to leave that box alone. tenant-iso-default-nested carlos status carlos system
  • Before rolling, check one box: systemctl start carlos-instance-probe.service then read /run/carlos-control/probe.out. It must say ready: true. Landlock must be in the booted kernel's lsm= list, and /etc/resolv.conf (or resolved's upstream list) must name a resolver that isn't on loopback. A box that fails any of these stays flat and says why. tenant-iso-layout tenant-iso-hardening
  • Roll the boxes before the console. The console now trusts a loopback X-Forwarded-For only when the edge has signed it, and switches to requiring the signature after it first sees one. Domain proof needs boxes that understand pending claims. tenant-iso-routes
  • Rolling back to a release before v0.25.0 is refused while any box has nested instances. Run carlos system layout revert, wait until carlos status --layout shows every instance flat, then roll back. tenant-iso-plan5 carlos system carlos status
  • Settings worth turning on for a deployment that hosts other people's apps: CONSOLE_DOMAIN_PROOF=true and CONSOLE_RESERVE_PLATFORM_DOMAINS=true on the console, after the boxes have rolled. CONSOLE_SECRETS_ENVELOPE_V2=true makes new secrets bound to their account and app; set it only once every box runs this release. tenant-iso-domains

Changes

17
  1. tenant-iso-default-nestedIsolated exec: nested is the default layout on a ready box; CARLOS_LAYOUT_DEFAULT=flat opts out (#126)

    Paul Campbell with claude #126 instance layout 2b2cc879

  2. region-ha-contractsRegion HA contracts for the claim (L13) and moves sessions, dormant

    Paul Campbell with claude 337b1062

  3. tenant-iso-cookiesEdge: tenant cookies can't reach beyond their own account; never cache a trailer Set-Cookie (#217)

    Paul Campbell with claude #217 carlos domains 383fae08

  4. tenant-iso-plan5Isolated exec, plan 5: the console door and carlos system layout; nested minting; downgrade guards with LayoutFloor v0.25.0 (#126)

    Paul Campbell with claude #126 #132 the platform s own binary instance layout f5ef8e36

  5. fix/hostbox-boxid-enrollhostbox: verify box identity with boxid.Verifier.Enroll (main build fix)

    Paul Campbell with claude 84c80eba

  6. feat/hostclaim-boxhostwrite: the inert selection interface for host-specific writers (claim Plan 6 Task 2)

    Paul Campbell with claude, codex d649d8d4

  7. design-region-ha-rev5Region HA spec 1 rev 5.4 and plan 1b: claim readers and evidence, dormant

    Paul Campbell with claude #236 3e12133f

  8. tenant-iso-routesRoutes: only operators add instance upstreams; the console trusts loopback X-Forwarded-For only with the edge's host-bound proof (#214 items 4-5, #50)

    Paul Campbell with claude #50 #170 #214 carlos instances 1c43c2ce

  9. tenant-iso-domainsDomains: opt-in proof of control; account namespaces are their own; fleet boxes see only their own claim bodies (#215)

    Paul Campbell with claude #209 #215 carlos domains 9bed97b5

  10. tenant-iso-hardeningNested instances: CPU/IO limits, a disk floor, own-build-only /opt/carlos, no loopback or private egress, private IPC and Landlock-scoped abstract sockets (#214 items 1-3, #178)

    Paul Campbell with claude #178 #214 09814f7f

  11. tenant-iso-layoutIsolated exec, plan 4: the nested layout and carlos layout migrate/revert (#126)

    Paul Campbell with claude #126 carlos status the platform s own binary 01f890ce

  12. multipart-email-supportemail test: send multipart/alternative, plain and HTML

    James Adam with claude carlos email 7143c7e0

  13. fix/hostclaim-r717hostclaim: a created incarnation's first admission declares nothing (moves 7.17 note 2)

    Paul Campbell with claude 67547f5a

  14. instance-catchallMerge instance-catchall: *.<parent> serves each instance at <label>.<parent> (#233)

    James Adam with claude #233 one name per instance parent 1d1a6f13

  15. first-route-wildcardMerge first-route-wildcard: a first-route claim stays first-route on a route-less re-attach (#238)

    James Adam with claude #238 e8d0328d

  16. wildcard-zone-checkMerge wildcard-zone-check: check the DNS-01 zone before placing a wildcard order (#237)

    James Adam with claude #237 58be3811

  17. fix/hostclaim-r16park, hostclaim: scopes stay in their own namespace; the legacy session-0 loss identity (joint round 16)

    Paul Campbell with claude, codex c7e595be

  • CI can deploy through the console. carlos services create --role deploy --app <a> --rungs canary,edge <name> mints a credential that can ship, and promote or roll back only the rungs you name: canary, edge and beta, never stable. In CI, set CARLOS_SERVICE_TOKEN and CARLOS_CONSOLE and run carlos deploy as usual. The first deploy of a new app still needs a person, because a deploy credential cannot create the app or set up its first host. It cannot hotfix, delete the app, or change retention or domains. carlos services list gains a RUNGS column. The CLI refuses to run with both CARLOS_SERVICE_TOKEN and CARLOS_DEPLOYMENT_BUCKET or CARLOS_DEPLOYMENT_DIR set. design-deploy-credential carlos services carlos deploy
  • A failed rollback says so. When the console cannot sign a rollback, it now answers "Nothing was rolled back." Before, it said "Nothing was promoted." fix-deploy-rollback-copy
  • carlos db no longer panics. If carlos db pull or query could not create its temporary file, the restore crashed. It now reports the error. feat/hostclaim-door carlos db
For operators
  • The boxes come back onto the release train. The flagship boxes have been running a hotfix build of v0.23.0 (f3f6cf73). It carried four fixes. Three are in v0.24.0, and their operator notes are there: a box runs its adopt work on its own loop, lists the bucket by app, and reads in parallel. The fourth is new in this release. When a box cannot stage a release itself, it asks a root pass to do it. That request used to be sent at most once a minute, and one made inside the minute was dropped, so a second release soon after the first waited for the next change to be noticed. On the flagship that was 98 extra seconds. The request is now limited to once every 15 seconds, and one made inside that window is sent at its end instead of dropped. Rolling this release moves those boxes off the hotfix with nothing lost. fix-stage-request-deferred
  • If your boxes are coming from v0.23.0 or a hotfix of it, read v0.24.0's operator notes first. Its changes now apply to the boxes: the keyless config guard, the box with no deployment store, and alerts to SNS. The check that matters most is this one. Every box that runs placed instances must hold the right CARLOS_SECRETS_KEY before you roll. A box without it, or with a key that does not open an instance's sealed config, will not wake that instance.
  • Leave CARLOS_HOST_CLAIM unset on the console. Any value that is not blank turns it on, including 0 and false. The console reads it once, when it starts. Nothing writes host claims yet, so with it on, carlos db pull and carlos db query fail for every host. feat/hostclaim-door carlos db
  • Do not set CARLOS_REGION_HA on a box yet. It is the switch for multi-box regions, which this release does not finish. Left unset, a box publishes no region-ha-1 capability and no headroom, and nothing changes. design-region-ha
  • Deploy credentials need the console's signing key. The console signs each deploy promote with a grant limited to the credential's rungs, so the console must hold its release key, as it already does for promotes. It adds a rungs column to its cli_tokens table when it starts. The change is additive. design-deploy-credential
  • Region HA foundations ship dormant. Every box's edges file gains box_id, which is the box's label. Box bootstrap also creates /run/carlos/hostguard and /data/hostguard, mode 2770, owned by carlos:carlos, when tmpfiles next runs. Nothing uses them yet. The host claim, generation selection and park libraries have no callers, so the boxes behave as before. design-region-ha feat/hostclaim-library feat/hostclaim-genselect feat/hostclaim-boxguard feat/hostclaim-park
  • Read the plan before applying the infrastructure modules. region-host gains a termination queue, an EventBridge rule and a box-role policy to read the queue, and its root volume is now deleted when the instance terminates. deployment-buckets gains a bucket policy that makes control/boxes/* create-only and undeletable. A bucket holds one policy, so check whether yours already has one before you apply. Nothing in this release needs them, so applying can wait. The own-bucket S3 version grants are split into separately named statements, with the same permissions. design-region-ha feat/hostclaim-door
  • The scanner host fix is in this release too. It is the freshclam change from v0.24.1. fix/scanner-freshclam-apparmor
  • Either roll order works. Nothing in this release needs the console and the boxes to roll in a particular order.

Changes

10
  1. feat/hostclaim-parkpark: the claim's park engine (claim Plan 4)

    Paul Campbell with claude, codex 7f403a77

  2. feat/hostclaim-doorconsole, dbdoor: the claim-bracketed pull door (claim Plan 7)

    Paul Campbell with claude, codex e1121997

  3. feat/hostclaim-boxguardhostguard, stopevidence, cgroup: the box-local host guard and stop evidence (claim Plan 3)

    Paul Campbell with claude, codex b37f73e1

  4. feat/hostclaim-genselectgenselect: the shared read-only generation selector (claim Plan 7b, F)

    Paul Campbell with claude, codex 4d13aec3

  5. feat/hostclaim-libraryhostclaim: the host lifecycle claim library (Plan 1, E)

    Paul Campbell with claude, codex 99084d7a

  6. fix-deploy-rollback-copyconsole: a failed deploy rollback says nothing was rolled back (#229)

    Paul Campbell with claude #229 55e3c1d9

  7. fix/scanner-freshclam-apparmorscanner-host: run the first freshclam with its packaged config (AppArmor denies any other)

    Paul Campbell with claude 592b667a

  8. fix-stage-request-deferredhost: a throttled stage request is deferred, not dropped; a blocked stage stays in the fast sweep

    Paul Campbell with claude #231 1a17848a

  9. design-deploy-credentialdeploy-credential: a rung-scoped deploy credential so CI promotes through the console (#229)

    Paul Campbell with claude #229 carlos services d1dab9a9

  10. design-region-haRegion HA plan 1a: the foundations for running instances on any box in a region

    Paul Campbell with claude #223 aadb8600

  • Nothing new for the CLI. The carlos binary is the same code as v0.24.0. This release only fixes a deployment module.
For operators
  • The scanner host boots. In v0.24.0, a new scanner-host box failed its first boot with SCANNER-HOST FAILED: first freshclam failed 3 times. Debian's AppArmor profile only lets freshclam read its own config under /etc/clamav, and the boot script gave it a copy elsewhere. It now uses the packaged config. A box from v0.24.0 never opened its port, so nothing was ever scanned through it. Pin scanner-host to v0.24.1 and replace the box with tofu apply -replace=module.<name>.aws_instance.scanner.

Changes

1
  1. scanner-host: run the first freshclam with its packaged config (AppArmor denies any other)

    Paul Campbell with claude f4478b15

  • Canaries have a one-label address, and can be created again. A canary's host is now <name>-<app>.<your account>.<apps domain>, so canary new-queue of app jam is new-queue-jam.bab.oncarlos.com. The old address put a dot between the name and the app. The console refused that, so carlos canary could not create a canary for an app that runs a process. The name and the app together can be at most 63 characters. You need this release's CLI. fix/canary-one-label carlos canary
  • Deploys reach running instances sooner on busy boxes. A box notices a promote sooner, and it restarts an awake instance onto the new release on its own two-second check instead of waiting for the rest of its work. On the flagship, noticing a promote had taken 16 to 43 seconds, and the restart then waited about 48 seconds more. fix-converge-own-loop fix-reconcile-listing fix-reconcile-parallel-reads
  • An instance never starts without its secrets. A box that cannot open an instance's sealed secrets no longer wakes it or takes it on. A box that can takes it instead. If none can, it does not start. Before, it could start with none of its config or secrets. fix/keyless-box-refuses
  • One address, one app. carlos instances create and carlos canary are refused when another app in your account already holds the host, including an app in the Trash, or when the host is a domain attached to another app. Before, both creates succeeded and one of them served nothing. fix/canary-one-label carlos instances carlos canary
  • Nothing new to type. The CLI has no new commands or flags in this release.
For operators
  • Check every box's secrets key before rolling the boxes. A box now takes an exec instance only if it can open that instance's sealed config. Without CARLOS_SECRETS_KEY, or with a key that does not open the config, it does not wake the instance or mint its record. It logs agent: config guard: refusing <host> and lists the host under metrics.config_refusals in its private snapshot, status/boxes/<box>.json. A box that cannot read the deployment store to check refuses too, and asks again after 30 seconds. Instances with no sealed config are not affected. fix/keyless-box-refuses
  • A box with no deployment store refuses exec instances. With CARLOS_HIBERNATE_BUCKET set and neither CARLOS_DEPLOYMENT_BUCKET nor CARLOS_DEPLOYMENT_DIR, a box cannot tell whether an instance's config is sealed, so it refuses. On a deployment with no sealed config at all, set CARLOS_NO_SEALED_CONFIG=1. Never set it on a box that serves tenants. The box then logs that the check is bypassed and says so in its snapshot. With a deployment store configured, the setting is ignored. fix/keyless-box-refuses
  • Roll the console to this release before pointing it at a scanner host. An older console records an archive that clamd could only partly scan as infected. This release records it as not scanned, and a scan time-out as failed, so the next sweep tries it again. A real signature match is still infected. worktree-scanner-host
  • Object-storage scanning has its own box. The new infra/modules/scanner-host module runs clamd on one box per deployment, reachable only from the console's security group. Set its outputs on the console: clamd_addr as CARLOS_CLAMD_ADDR and stream_max_bytes as CARLOS_CLAMD_MAX_BYTES. The console also needs CARLOS_SCAN_TAG_KEY, and refuses to boot with an address and no key. Set store_scanning = true on the console box's region-host so its role can read and tag store objects. It is off by default, and a deployment that leaves it off plans no change. Wiring the engine does not switch scanning on. carlos system antivirus enable does. A replaced scanner box gets a new private IP, so update CARLOS_CLAMD_ADDR after any -replace. Pin modules to v0.24.0: v0.23.0 does not contain scanner-host. worktree-scanner-host carlos system
  • The app regions rollback floor is v0.23.0. v0.23.0 is the first release that understands app regions. Once any app holds a region other than the home, do not roll the console below v0.23.0. docs-regions-floor-v0.23.0
  • Boxes can send alerts to SNS. Set CARLOS_ALERT_SNS_TOPIC_ARN to the box's own region's alerts topic, and anyone subscribed gets each fire and clear by email. The box's instance role needs sns:Publish on that topic. The modules in this repo do not grant it. A box with neither this nor CARLOS_ALERT_WEBHOOK logs NO SINK CONFIGURED when it starts. carlos status --live gains a last column: alerts=sns, alerts=webhook, alerts=webhook+sns, alerts=not-delivered, or alerts=sns-unavailable when a topic is set but the box could not build its SNS client. A dash means the box runs an older release. feat/alerts-sns carlos status
  • Boxes list the bucket by app. To find instance records, a box now lists each account's apps and each app's instances/ prefix, eight requests at a time, instead of every object under apps/. If one app's listing fails, the box logs a provision: listing line, converges everything it did see, and removes no route on that pass. The agent also logs an agent: fast converge: line when a step of its fast loop takes longer than five seconds. fix-reconcile-listing fix-reconcile-parallel-reads
  • Either roll order works. Nothing in this release needs the console and the boxes to roll in a particular order.

Changes

8
  1. fix-reconcile-parallel-readsprovision: read records eight at a time in the reconcile and record passes

    Paul Campbell with claude eef3e121

  2. fix-reconcile-listingprovision: find instance and sidecar records by walking app directories, not by listing all of apps/

    Paul Campbell with claude #231 91bb1a2e

  3. fix-converge-own-loophost: the converge leg runs on its own loop; slow fast-loop legs are logged

    Paul Campbell with claude #231 b2a76df9

  4. docs-regions-floor-v0.23.0README: v0.23.0 is the app-regions rollback floor

    Paul Campbell with claude e58a0d82

  5. worktree-scanner-hostspec: scanner host, getting object-storage scanning running on Carloku and Tito

    Paul Campbell with claude #235 carlos store scan 562f3dfc

  6. fix/canary-one-labelconsole: the instance create door refuses a host another app holds

    Paul Campbell with claude #207 #232 carlos canary carlos instances 04cd2d78

  7. fix/keyless-box-refusesappconfig: CanProvideConfig, can this box provide an instance's config (#213)

    Paul Campbell with claude #213 5cd92594

  8. feat/alerts-snsDeliver platform alerts to an SNS topic, and say when a box has no sink

    Paul Campbell with claude #192 carlos status 6956db67

  • A deploy reaches a running instance in seconds. When a box adopts a new release, an instance that is awake restarts onto it within a few seconds. Before, it kept serving the old build for about two minutes, longer than carlos deploy waits, so a deploy could report a timeout and a restart seemed to be needed. Instances on one box restart one at a time, two seconds apart. fix-adopted-exec-restart carlos deploy
  • Static sites show a deploy on the next page load. Browsers now check with the edge before reusing a page or file from a static site, and get a quick "not modified" answer while nothing has changed. Before, a browser could keep showing the old page for hours or days after a deploy. static-cache-control
  • Read a copy of an instance's database. carlos db pull --app <a> --out <file> saves a copy of a sleeping instance's database on your machine, and carlos db query --app <a> --sql "…" runs one query against a fresh copy. Both say how recent the copy is. The copy is read-only and never touches the live database. Name an instance with --instance when the app has more than one. feat/carlos-db-read carlos db
  • Region flags. carlos apps create, carlos deploy and carlos canary take --region. A console that is not assigning app regions yet says so and starts the app in its home region. carlos deploy --region on an existing app stops before shipping if the region differs from the app's own. The line carlos instances create prints now names the place the instance runs. design-nearest-region carlos apps carlos deploy carlos canary carlos instances
  • Invite links ask before you join. Opening an invite link shows who invited you and a Join button. Nothing happens until you press it. tenant-iso-leftovers
  • Sending domains you did not set up. If a domain already has a sending identity that your account did not create, carlos email domains add asks you to prove you control it: publish a TXT record at _carlos-mail.<domain> with the value carlos-mail-account=<account>, then add the domain again. A domain another account holds now reads "sending domain unavailable". A claim that is not verified within 7 days can be taken by another account. tenant-iso-mail carlos email
  • Stores no longer share a bucket by accident. App and environment names are joined with "-", so app shop with environment eu and app shop-eu used to map to the same bucket. The second one is now refused with a 409, and nothing is created. tenant-iso-objstore
  • Platform domains. An operator can attach one of the deployment's own domains to an app with carlos domains attach --platform. Members cannot attach, change or detach those names. platform-domain-claims-209 carlos domains
For operators
  • Roll the boxes, then the console. With the new switches left off, either order is safe. The two switches below need every box on v0.23.0 first.
  • Leave CONSOLE_SECRETS_ENVELOPE_V2 off until every box runs v0.23.0. When it is on, the console seals new secrets so they open only for their own account and app. A box on an older release cannot open them, and the app's whole config stops updating on that box. Rolling a box back below v0.23.0 after turning it on does the same. A value that is not true or false stops the console from starting. tenant-iso-binding
  • v0.23.0 is the first release that understands app regions. That makes it the rollback floor the README describes: once any app holds a region other than the home, do not roll the console below v0.23.0. CONSOLE_APP_REGIONS is off by default. Turn it on only by the README's steps. Boxes now publish serves_shared_pool, accepts_inbound and, where they hold the secrets key, secrets_key_fp in their edges file. design-nearest-region
  • Boxes restart awake instances when they adopt a release. The agent checks every two seconds and restarts at most one instance per check. Workers still converge on the old 90-second timer. A restart drains the old process as before: new requests wait for the new one. fix-adopted-exec-restart
  • Static responses change their headers. They now carry Cache-Control: no-cache and a weak ETag worked out from each file's bytes and type, and no Last-Modified. The first request for a file after a deploy reads it once to work out the tag. The edge's own cache still does not store static responses. static-cache-control
  • Pin infrastructure modules to v0.23.0. The box role gains permission to list, read and delete object versions in its own data bucket. Nothing uses it yet, so applying it can wait. Check also that nothing in your policies denies s3:DeleteObject on the deployment bucket: purges, store teardown and mail claim release delete objects, and fail without it. feat/hostclaim-storage
  • Run carlos accounts migrate with a v0.23.0 CLI. Pointers are now signed for their account, and migrating re-signs them, which needs the root CARLOS_RELEASE_KEY. An older CLI copies them unchanged, and the moved app stops adopting releases. tenant-iso-binding carlos accounts
  • Existing data is left in place. Purging an app now also deletes its tokens, door keys and ledgers, but apps purged before this release keep theirs. Removing a sending domain that was added before this release leaves its SES identity in SES. Moving an app revokes its door keys, so moved apps need new ones. tenant-iso-leftovers tenant-iso-mail

Changes

14
  1. feat/hostclaim-storagelease: versioned storage primitives for the host lifecycle claim (Plan 2)

    Paul Campbell with claude, codex 3ca43d33

  2. static-cache-controledge: static responses revalidate, on a version ETag

    Paul Campbell with claude #195 b58e1275

  3. fix-adopted-exec-restarthost, activator: the agent finishes an adoption the root pass performed

    Paul Campbell with claude #231 3a86f348

  4. fix/console-capturelogconsole tests: untangle #208 and nearest-region on main

    Paul Campbell with claude #208 8d8e4bae

  5. tenant-iso-mailMail: members can't adopt another party's SES identity; unverified sending-domain claims lapse (#216)

    Paul Campbell with claude #216 carlos email be3338d4

  6. tenant-iso-leftoversPurge and membership leftovers: credentials, door keys and ledgers end with their app; invite accept by POST (#219)

    Paul Campbell with claude #219 f36ad36a

  7. tenant-iso-bindingBind release pointers and secret envelopes to their account; close relay deny-list gaps (#220)

    Paul Campbell with claude #220 b94ad230

  8. tenant-iso-objstoreobjstore: bucket and IAM user names can't collide across stores (#218, #191)

    Paul Campbell with claude #191 #218 2129e26e

  9. platform-domain-claims-209domains: the operator's door for platform hostnames (#209)

    Paul Campbell with claude #209 a6e4cd41

  10. design-nearest-regiondocs: nearest-region default design spec

    Paul Campbell with claude #169 carlos apps carlos deploy carlos canary carlos instances carlos services 3f4a9bfd

  11. fix-console-registry-208console: protect shared registry lifetime (#208)

    Paul Campbell with codex #208 #210 78fc8d40

  12. fix/199-create-refuses-leftoversconsole: create refuses a host that still holds a deleted instance's replica (#199 stopgap)

    Paul Campbell with claude #199 fe2088e3

  13. system-operators-176console: system operators can roll signed platform releases (#176)

    Paul Campbell with claude #176 #201 the platform s own binary a7a2aaa2

  14. feat/carlos-db-readcarlos db pull and query: read an instance's database from its replica (spec 2026-09-02, unit 1)

    Paul Campbell with claude · Tony Wood carlos db da866a92

  • Database size on the app Overview. A new tile shows how much disk your app's databases use, including copies that are asleep. feature/instance-db-stats-card
  • Busy and large instances can finish a move. An instance that is awake and writing, or that keeps large database files, can now finish moving to another region. Before, such a move could wait in preparing and never become ready. The cut still copies everything that is left, exactly, before the instance serves from its new region. move-ready-delta-threshold
  • Nothing new to type. The CLI has no new commands or flags in this release.
For operators
  • v0.22.1 was tagged but never published. v0.22.2 supersedes it, so roll v0.22.2 and pin modules to v0.22.2.
  • A move becomes ready when little is left to copy. By default, a preparing round now promotes when it copied 16 MiB or less. To change that bar, set CARLOS_MOVE_READY_DELTA_BYTES in /etc/carlos/host.env; the agent reads it when it starts. 0 restores the old rule that a round must copy nothing. A value that is not a whole number of bytes is ignored with a log line, and the default stays. The ready log line now shows the bytes copied, the number of changes and the bar. move-ready-delta-threshold
  • Copy receipts in the source box's data bucket. A box moving an instance away keeps receipts at move-receipts/<host>.json in its own data bucket, so large objects that have not changed are not copied again. The cut and an abort delete them. A deployment whose data-bucket policy denies DeleteObject keeps stale receipts, which are harmless. The box policy in this repo already allows the prefix. move-ready-delta-threshold
  • The cut is still exact. It copies everything that is left before it flips the record. If an object changes during that final copy, the cut waits for the next pass instead of landing an incomplete copy. move-ready-delta-threshold
  • The Database tile is console only. It reads the database sizes boxes have reported since v0.21.0, so it needs no box roll and no env or IAM change. A slow read shows a dash and never holds up the page. feature/instance-db-stats-card

Changes

2
  1. move-ready-delta-thresholdlease: MirrorPrefix reports the bytes a round copied

    Paul Campbell with claude #175 7edd4b33

  2. feature/instance-db-stats-cardconsole: a Database tile on the app Overview (size on disk, including sleeping copies)

    Paul Campbell with claude · Tony Wood with claude #197 abe897e0

v0.22.1

· Tagged but not published

Changes

1
  1. feature/instance-db-stats-cardconsole: a Database tile on the app Overview (size on disk, including sleeping copies)

    Paul Campbell with claude · Tony Wood with claude #197 abe897e0

  • Availability, apart from errors. carlos availability lists the requests an app's instances could not answer, every 502, 503 and 504 the edge saw, grouped by cause instead of by page. One outage is one row, however many pages it hit. --fp <id> expands a cause to each request and the path it asked for. The same view is the new Availability tab beside Errors. availability-tab carlos availability
  • Errors is shorter. carlos errors and the Errors tab keep the app's own 500s and the error lines in its logs. Edge 502s, 503s and 504s, failed wakes and exits have moved to Availability. availability-tab carlos errors
  • Replica instances. carlos instances create --role replica --region <r> makes a second instance of an app, holding a one-way copy of the live instance's data, in a region near its buyers. The live instance names the regions it allows replicas in with --replicas ie,uk when it is created. Until a batch of orders drains home, a replica holds order data in its own region, so the regions are always a decision on the live instance, never a default. edge-replica-placements carlos instances
  • Door keys. carlos instances door-key create, list and revoke manage keys for the edge-local door. That is one socket on a box that a process running beside an app's instances can dial to reach any of them, whether it is asleep, moved to another box or awake. A key is shown once, when it is created. The door is off until the box's operator turns it on. instance-moves-p7 carlos instances
  • Faster log reads. Log chunks are now fetched 16 at a time instead of one by one, which speeds up carlos logs, Errors and Availability. parallel-chunk-read carlos logs
  • A restored app keeps its pipeline. When the console registers an app whose files are already in the bucket, it keeps that app's release pipeline instead of resetting it to the default. fix/preserve-adopted-app-pipeline
For operators
  • Roll the console first, then the boxes, close together. The boxes record why the edge had no answer and the console shows it. A console on its own groups stored 502s under "cause not recorded", and new ones too until the boxes roll. Boxes on their own, under an old console, list each cause as its own row on Errors. Rolling the console back is safe: nothing in the bucket is rewritten. availability-tab
  • A new CLI against an old console. carlos availability fails with not found: check --account and --app, and that your token's address is a member. Until the console rolls, that message means the console predates the command, not that the app or your membership is missing. An old console silently ignores carlos instances create --role replica and creates an ordinary instance in that region instead. availability-tab edge-replica-placements carlos availability carlos instances
  • No replicas until every box has rolled. Only this release keeps replicas out of DNS latency routing. Each box adds two columns to its registry when it starts (routes.replicas and routes.replica). There is nothing to migrate, and a box rolled back ignores them. edge-replica-placements
  • Long polls show up in Availability. A visitor who gives up after waiting five seconds or more, before the instance has sent response headers, is filed as an outage. On a sleeping route the five seconds include the wake. An endpoint that holds its headers longer by design, like a long poll, shows a standing row, and that row is expected. A visitor who leaves sooner is no longer filed at all, so expect fewer one-off 502s on static files. availability-tab
  • Tunnelled failures are filed once. On a route a box reaches over a tunnel or a fleet, the front box files only its own hop failures, and the box serving the app files the rest. availability-tab
  • Instance moves. A box cutting a move now fences the instance so a scheduled wake cannot start it again mid-move. A move past ready can no longer be aborted, and a replica cannot be moved: delete it and create one in the new region. A later release's boxes rely on this console's abort rule, which is one more reason to roll the console first. instance-moves-p0
  • The edge-local door is off by default. It stays off until a box sets CARLOS_EDGE_DOOR=/run/carlos/edge-local.sock and its agent restarts. The calling process's user must also be enrolled with carlos bootstrap --socket-consumer <user>. The console re-signs door keys every 12 hours, and a key whose record has not been re-signed for 72 hours stops working, so a console down that long closes every door. instance-moves-p7 carlos bootstrap
  • Each instance gets its own /dev/shm. Instance units no longer see the host's /dev/shm, so an instance cannot reach another's shared memory. They also no longer set RestrictSUIDSGID=, which broke openat2 on systemd 257 and kept the isolated exec probe from reporting ready. carlos system update installs the new units, and a running instance picks them up when it next restarts. isolated-exec-probe-fixes carlos system

Changes

13
  1. fix-worker-store-boundsBound worker assignment storage versions and reject enabled no-op writes

    Paul Campbell #146 91fc2c43

  2. docs-carloku-infra-splitAGENTS.md: the flagship root lives in carloku-infrastructure, pinned to release tags

    Paul Campbell with claude e8406ce6

  3. instance-moves-p7instance moves P7 (#175): the edge-local door, dormant until CARLOS_EDGE_DOOR

    Paul Campbell with claude #175 storage of its own for every instance 88abfae2

  4. isolated-exec-probe-fixesisolated exec: the probe goes ready, and each instance gets its own /dev/shm (#126)

    Paul Campbell with claude #126 #178 52f71143

  5. instance-moves-p0instance moves P0 (#175): fence the cut against tick wakes, refuse abort past ready, refuse moving a replica

    Paul Campbell with claude #175 408db5ef

  6. fix/preserve-adopted-app-pipelinePreserve existing release pipelines when restoring app registration

    Paul Campbell with codex 4d5eab8a

  7. amadan-agent-skill.claude: install amadan's agent skill; ignore local Claude settings

    Bill Horsman with claude 8c54ec7a

  8. release-notes-v0.22.0README: operator note for v0.22.0 (Availability, replica placements)

    Bill Horsman with claude 2158949f

  9. refs-designspec: request references — one ID a customer can read out, and we can find

    Bill Horsman with claude 1786da9c

  10. agents-amadan-source-of-truthAGENTS.md: amadan is the source of truth; squash before landing

    Bill Horsman with claude f50e3425

  11. availability-tabAvailability: edge 502/503/504 grouped by cause, on their own tab

    Bill Horsman with claude carlos errors carlos availability 38639c1e

  12. parallel-chunk-readapplog: fetch chunks 16 at a time, assemble in serial order

    Bill Horsman with claude 249bbe5e

  13. edge-replica-placementsprovision, edge: replica placements — the routing half of edge checkout (#162)

    Paul Campbell with claude #162 carlos instances b5b0a53a

  • A new address is never a dead end. An edge that hasn't heard of a host under the deployment's own domains yet answers 503 with Retry-After and a page that tries again on its own for 90 seconds, instead of "unknown host". Edges also learn which box serves a new host within about 30 seconds, down from as much as six minutes. edge-unknown-host-174
  • The release recipe is in the README. "Releasing the platform" now walks through tagging, building, signing, publishing, Homebrew and apt. docs-release-recipe
Before you roll
  • On an edge started with -fallback, a mistyped or retired subdomain under a platform domain now reaches the fallback URL only after the 90-second retry page, and only in a browser. curl, crawlers and monitors see the 503.

Changes

2
  1. docs-release-recipedocs-release-recipe

    Paul Campbell with claude 8138d942

  2. edge-unknown-host-174edge-unknown-host-174

    Paul Campbell with claude 055ed3b6

  • Named deploy destinations. carlos config destinations keeps the places an app deploys to in .carlos/config, and carlos deploy -d <name> picks one. config-destinations-cli carlos-deploy-targets carlos config carlos deploy
  • Sidecars. carlos sidecars runs a process beside each enrolled member of an app, such as a document converter. it takes enable, create, ls, wake, rm and logs. sidecar-members sidecar-engine-capability carlos sidecars
  • Email you can follow. carlos email events shows what happened to each message an app sent (delivered, bounced, complained about or delayed) for 30 days. carlos email events push posts those events to the app itself, signed. carlos email domains rm stops an app sending from a domain and frees the domain for another account once no app uses it. mail-events-log mail-events-push carlos email
  • A store per environment. carlos store create --environment <e> gives one named environment its own bucket and credential, delivered into that environment's config. an app can now have each instance get its own environment and store. per-instance-store 412-storage-isolation-config carlos store
  • Purge every host of an account at once. Carlos-Purge-Host now takes a list of up to 32 hosts, each checked against the same app and account. a host the box doesn't serve is skipped. The control socket's POST /purge takes {"path":"*"} to clear the whole host. edge-purge-hosts-173
  • Faster edge start on distant boxes. certificates now load in parallel at boot, so a box far from its bucket no longer fails its update check. fix-edge-boot-refresh
Before you roll a console to this release
  • The control-plane role needs ses:CreateTenantResourceAssociation and ses:DeleteTenantResourceAssociation. email sender records have moved to email/senders/app.json, and a console rolled back after the first write loses any pause or rotation made since.
  • Every config pass now lists each app's instances-config/ prefix. an IAM policy that narrows s3:ListBucket by prefix will freeze that app's config until the listing succeeds, so check a hand-edited policy first. look for instance config unresolved in the box log.

Changes

23
  1. edge-purge-hosts-173edge-purge-hosts-173

    Paul Campbell with claude 0d2fdd44

  2. email-domains-rmemail: release a sending-domain claim without deleting the app

    James Adam with claude carlos email 413256dd

  3. 412-storage-isolation-configApp policy: every instance gets its own environment and store (#412)

    James Adam with claude storage of its own for every instance carlos services 1c4ee673

  4. per-instance-storePer-environment object storage: a store an instance can own

    James Adam with claude #140 #159 #172 a store for one environment 1447716c

  5. worktree-instance-configappconfig: the instance config layer's key, host rule and etag-returning reader (plan 4, task 1)

    Paul Campbell with claude eb9ba0fe

  6. worktree-tenant-email-sendersDesign: tenant email senders (#147, #148)

    Paul Campbell with claude #147 #148 #155 ce24be04

  7. sidecar-engine-capabilitycaps: doc-engine capability for document-conversion sidecars (Gotenberg, OCR)

    Paul Campbell #168 91cf6888

  8. fix-edge-boot-refreshedge: fetch the cert mirror's boot refresh concurrently

    Paul Campbell with claude 1b48ed5e

  9. fix/timer-rearm-completionPreserve timer replacements across in-flight delivery completion

    Paul Campbell with claude, codex · James Adam with claude #120 carlos instances carlos routes carlos store carlos relay 203f67a9

  10. config-destinations-clicli: carlos config destinations — manage deploy destinations

    James Adam with claude #157 carlos auth carlos config deploying one checkout to several places 1643418d

  11. fix-system-apply-dirshost: create the relay's state dir on every apply, and arm what the target build asks for

    Paul Campbell with claude #118 5a409bdd

  12. reserve-platform-domains-opt-indomains: reserving platform domains is opt-in (CONSOLE_RESERVE_PLATFORM_DOMAINS)

    James Adam with claude #156 carlos domains e6773f53

  13. carlos-deploy-targetscli: named deploy destinations in .carlos/config

    James Adam with claude deploying one checkout to several places 1bcc593c

  14. fix/tito-platform-domainsAllow trusted accounts to attach short platform app aliases

    Paul Campbell 5abc9ecf

  15. docs/infrastructure-approvalRequire scoped approval for production infrastructure experiments

    Paul Campbell db79997d

  16. sidecar-membersspec: sidecar members — a serving class that nothing can dial

    Paul Campbell with claude carlos sidecars 671d3d11

  17. worktree-eleven-migrationspec: refresh the Eleven→Carloku design against a week of main

    Paul Campbell with claude b7fa9a69

  18. instances-trashed-apexAn app's platform apex is its own, whichever arrives first (discussion 153)

    Bill Horsman with claude #153 carlos apps carlos instances 520fcc04

  19. mail-events-pushemail events push: tell the app itself, signed, at a path on its own host

    Bill Horsman with claude #153 carlos email a430d4d6

  20. mail-events-logemail events: keep what happened to each message, and `carlos email events` to read it

    Bill Horsman with claude #151 #152 carlos email b9b4238d

  21. minio-contract-github-sourceci: fetch the pinned MinIO and mc from GitHub — dl.min.io serves nothing now

    Bill Horsman with claude #152 d9f67f2f

  22. worktree-isolated-exec-specAdd isolated-exec design spec and codex review brief (#126)

    Paul Campbell with claude #17 #126 carlos instance control carlos instance exec carlos instance exit carlos instance probe c1d40eeb

  23. feat-maintenance-worker-identitySpecify scoped maintenance worker enrollment and publication

    Paul Campbell #132 7fdcb6d1

  • Self-serve object storage. carlos store create is the whole path once an account is approved; accounts apply and operators decide through the console. worktree-store-self-serve carlos store
  • Console instance pages. Instance status, activity and live logs are wired up in the console.
  • Edge reads s-maxage, so an origin can address the edge cache and the browser cache separately. edge-s-maxage
  • Maintenance worker. Pinned maintenance subprocesses are supervised; a launch context codec is shared with standalone consumers. feat-maintenance-worker feat-launchctx-module

Changes

4
  1. feat-launchctx-moduleShare maintenance launch decoding with standalone consumers

    Paul Campbell #131 a0a60b58

  2. feat-maintenance-workerValidate private maintenance launch contexts and checkpoint bindings

    Paul Campbell #130 bf4c83ab

  3. edge-s-maxageedge: read s-maxage, so an origin can tell the two caches apart

    Bill Horsman with claude 006e7825

  4. worktree-store-self-servespec: self-serve object storage via account apply/approve (#381)

    Paul Campbell with claude carlos store 2e26c5f2

Changes

50
  1. console-ux-12-final-wiringConnect console instance status, activity and live logs

    Paul Campbell 16593de5

  2. console-ux-11-status-checkstatus: distinguish numeric leaks from timestamp text

    Paul Campbell f773b13f

  3. console-ux-01-statusconsole: derive deployment status from observed instances

    Paul Campbell 64972fd9

  4. console-ux-08-cliAdd optional descriptions to CLI mutations

    Paul Campbell describing changes 08f27891

  5. console-ux-10-actionsAdd app and instance restart controls

    Paul Campbell 0bc32c46

  6. console-ux-05-deploymentsMake deployments show channel targets and release history

    Paul Campbell d73bd1b3

  7. console-ux-02-settingsconsole: split app settings into independently saved sections

    Paul Campbell f33f3404

  8. console-ux-07-activityRecord structured activity descriptions

    Paul Campbell with codex cff5c82b

  9. console-ux-04-diagnosticsconsole: summarize account mismatches and scope account review

    Paul Campbell f4207d3b

  10. console-ux-06-logsconsole: filter and follow logs by instance

    Paul Campbell 92361249

  11. console-ux-03-instancesconsole: add instance details and channel grouping

    Paul Campbell 9251082a

  12. design-checker-launchSpecify checker-only closed-checkpoint launch context

    Paul Campbell d492f628

  13. fix-maintenance-admission-orderingBound maintenance admission and isolate scheduled token ordering

    Paul Campbell 12e9c809

  14. sweep-staged-versionsSweep the staged versions nothing on the box still names (#111)

    Paul Campbell with claude #111 caf60d12

  15. hosting-capability-wireregions: each box answers for its own hosting, and three doors stop sharing one bar

    Paul Campbell with claude #110 851a531d

  16. design-runtime-signing-r2Specify verified runtime contract execution and writer edge cases

    Paul Campbell 2ace60d2

  17. design-always-awake-r2Revise always-awake lifecycle ownership and recovery contract

    Paul Campbell d2cbfba6

  18. design-maintenance-protocol-r2Revise maintenance protocol after independent review

    Paul Campbell 4f0e078e

  19. design-maintenance-launch-r3Specify private descriptor context for maintenance consumers

    Paul Campbell 9969a8fe

  20. feat-maintenance-writer-integrationAdd durable host maintenance guards and app lifecycle claims

    Paul Campbell 11a30399

  21. feat-maintenance-payloadBound encrypted maintenance input without rewriting signed JSON

    Paul Campbell 9bf83ba6

  22. feat-release-conditional-deleteAdd optional revision-conditional store deletion

    Paul Campbell 8746297d

  23. feat-maintenance-envelopeAdd recipient-bound private maintenance envelopes

    Paul Campbell d43d971b

  24. fix-relay-meter-waitWait for relay accounting after packet delivery

    Paul Campbell b39d1efa

  25. design-maintenance-execDraft exec instance maintenance boundary and review prerequisites

    Paul Campbell 05c877f9

25 more
  1. relay-syncexec-test-fixappconfig: the multi-upstream SyncExec test passes the ack parameter

    Paul Campbell with claude dcf0cad3

  2. relay-stun-turn-implplan: stage 4a relay implementation plan

    Paul Campbell with claude carlos relay 4316089d

  3. worktree-password-gatespec: password gate — a shared password in front of an instance

    Paul Campbell with claude carlos instances carlos gate df7d1d25

  4. analytics-step2plan: analytics step 2, counting at the edge

    Paul Campbell with claude carlos analytics 40c6ab73

  5. appconfig: deliver to multi-upstream exec routes (#391)

    Paul Campbell 8e16153d

  6. Sync GitHub mirror to amadan main 1a99060

    Paul Campbell with claude #113 carlos errors a8f0d04f

  7. Sync GitHub mirror to amadan main d1cfc65

    Paul Campbell with claude carlos store scan carlos system the platform s own binary deployment wide object scanning 1a44a30d

  8. Sync GitHub mirror to amadan main d2216ee

    Paul Campbell with claude #6 #17 #19 carlos store scan carlos system f42bf583

  9. Sync GitHub mirror to amadan main d1cfc65

    Paul Campbell with claude #6 #7 #8 #9 #10 #11 #13 #16 #17 #110 carlos apps carlos deploy carlos restart restarting less than the whole app carlos env 52b398ab

  10. console: the architecture page is one picture per region, stacked (#390)

    Paul Campbell with claude d72ac7f8

  11. purge-path-routed-hostsLet a path-routed app purge its own cache

    Paul Campbell with claude eb721282

  12. console: the architecture page reads as two estates, not one (#387)

    Paul Campbell with claude 505addb6

  13. path-based-routingPath-based routing: one hostname, many upstreams

    Paul Campbell with claude 6a594976

  14. instances: let a route name its own config bundle, so a canary can accept a POST (#385)

    Paul Campbell with claude carlos canary carlos env carlos instances f7ac3aaf

  15. canary: fill the reserved verb with the sugar over what already works (#384)

    Paul Campbell with claude carlos canary everything else 537c4a1e

  16. host: mark a served catch-all as an alias, so it stops refusing itself (#382)

    Paul Campbell with claude ceecb3a9

  17. static sites: name the shape mismatch instead of denying the promote (#380)

    Paul Campbell with claude carlos promote f975b47c

  18. AGENTS.md: pushing main to amadan is the last step of landing a change (#377)

    Paul Campbell with claude 97eb53fb

  19. docs: the instance service role provisions instances, it does not just read them (#373)

    Paul Campbell with claude #4 carlos services 7f7f9417

  20. instances: a first instance follows the app's pipeline entry, not stable (#372)

    Paul Campbell with claude #5 29046890

  21. Scheduled ticks must not hold an instance awake (#371)

    Paul Campbell with claude f10d8e1d

  22. carlos-skills-cmdcli: carlos skills — list and fetch the published agent skills

    Paul Campbell with claude carlos skills 32e8662d

  23. cert-sweepdomains: the Settings page's state, the claim-fold cache, and the cert sweep (#299 §3f, #173, #243)

    Paul Campbell with claude 5ef69c6b

  24. cert-warm-outcomeswarm outcomes: the platform can say a certificate FAILED (#299 §3e)

    Paul Campbell with claude c5e33287

  25. trash-route-removalA trashed app's routes are retired on every box, and static platform hosts are steered by default

    Paul Campbell with claude carlos steering c3f021d3

Release notes

Region residence: instances know where they live, and can move

This release is about placement. Three pieces land together (platform #329, #331, #346):

  • Armed-placement validation on instance create (#329). Creating an instance names a region, and the console now refuses a code that is not armed on the deployment instead of provisioning into nowhere. Each box's edges file publishes its own placement code, and every exec child inherits it as CARLOS_REGION, so an app can tell where it is running without asking anyone.
  • Two-phase, data-following instance moves (#331). POST .../instances/{host}/move requests a move to another armed region; the host prepares in rounds, mirroring the instance's replica prefix into the destination's staging bucket until the copy is current; POST .../move/cut then cuts over, with a re-checkpoint at the cut so nothing written in the gap is lost. DELETE .../move aborts cleanly at either phase. Staging wins over a stale local copy, a failed fallback is a hard fail rather than a silent downgrade, and a serial nudge on every box-side write means the cut chain converges in seconds rather than five-minute hops.
  • The armed-regions endpoint (#346). GET /api/cli/apps/{account}/{app}/regions returns the deployment's regions with their armed state, the home region's name, and the default, so pickers in the console, the CLI, and consumer apps draw from one list.

Also in this release

  • served_by on instances (#337): an instance row now carries where it is observed to be served (the edges that actually join it), beside where it was placed.
  • Control and edges files carry placement + data-bucket coordinates, so a box and its peers can locate each other's replica prefixes without a console round trip.
  • sibling_staging_arns on the region-remote-host and region-host Terraform modules: the push-only moves/* grant that lets a host stage into a sibling region's bucket and nothing else.
  • carlos-app@ units can no longer reach IMDS (#351/#352); a host_role drop-in re-opens it for the apps that need instance credentials.

The operator CLI verbs are unchanged from v0.16.0; the new surface is on the console API and in the host, edge, and activator halves of the same binary.

Changes

6
  1. regions-endpointinstances API: armed-regions endpoint + flat move views + the home region's name (#346)

    Paul Campbell with claude e6c3bf9a

  2. move-serial-nudgemoves: serial nudges — cut chain in seconds (#331 rehearsal measurement)

    Paul Campbell with claude 223fc566

  3. mirror-skips-the-leasemirror: skip the lease's lock.json (#331 rehearsal catch)

    Paul Campbell with claude ae64ea53

  4. instance-movesInstance moves: two-phase, data-following residence moves (#331)

    Paul Campbell with claude fa5ba8e4

  5. idms-gatecarlos-app@ units can no longer reach IMDS; host_role drop-ins re-open it

    Paul Campbell with claude 08d4a489

  6. region-at-the-doorregion at the door: armed-placement validation on instance create + CARLOS_REGION to exec children (#329)

    Paul Campbell with claude d56ac003

Release notes

carlos features — app feature flags on the deployment object

The headline: carlos features set and carlos features list (platform #347, PR #350). An app's own feature flags — switches the app defines, the platform stores, serves and audits, but never interprets:

carlos features set --app titogo sandbox=on
carlos features list --app titogo

key= with nothing after the equals clears a key. The app reads the map off the deployment block its instance token already fetches (beside managed_domains), so a change lands on the app's next poll — no restart, no env edit, no root-owned file on an edge box. Setting is an admin-role write; the app's own credential can read its flags but never set them.

Also in this release

  • Custom domains grew a lifecycle (#299, #325, #328): carlos domains list rows now carry one derived state (checking, pending-dns, misdirected, issuing-cert, live, unknown) with a reason, structured records[] telling you exactly which DNS records to create, and a checked_at freshness stamp; the answer's self-describing deployment block says what the deployment manages. A per-host read (GET .../domains/{host} under the hood) makes single-hostname refreshes cheap.
  • carlos deploy is stricter about what it claims: it refuses a git-derived version from a dirty tree, and watches the app's own build report rather than an edge header.
  • carlos apps create gained -control-plane and -build-probe.

Changes

19
  1. feature-flagsApp feature flags on the deployment object — `carlos features` (#347)

    Paul Campbell with claude carlos features 9a056e54

  2. reliability-followupsReliability follow-ups: #344 account tie-break + config-delete guard, spawn-seam tier pin, OOM polish

    Paul Campbell cf772129

  3. cp-instance-doorsGuard the provision-record lifecycle: creating, mutating or removing a record for a control-plane app transfers or destroys reconciler authority over its route. Removal refused outright; creation and mutation refuse a service principal only. Found mid-rollout — the console cannot become instance-backed until this exists.

    Paul Campbell with claude d27e2f01

  4. reliabilitymemwatch: publish to the box's placement region

    Paul Campbell 0ac8c98a

  5. reliabilitycgroup: bound memory.swap.max with memory.max (zram made the cap escapable)

    Paul Campbell d86a5c16

  6. rails-poc-hostname-postscriptspec: Rails PoC postscript — hostname configuration closed, edge hostnames live

    Paul Campbell with claude 6e189a5c

  7. instances-served-byinstances API: served_by — observed per-instance placement from control/edges (#337)

    Paul Campbell with claude 9ee32f64

  8. reliabilityMemory pressure containment: edge wall, per-app caps, memwatch, module alarm

    Paul Campbell c2054152

  9. rails-behind-edge-poc-specdocs: Rails-behind-the-edge PoC — design record + implementation plan

    Paul Campbell with claude 2ca7d60f

  10. box-machine-joinThe box tells us which machine it is

    Paul Campbell with claude eb69ae64

  11. runbook-r1-three-deliveriesR1 is three deliveries, not one — the root binary carries the adoption fix and roll-console.sh never touches it.

    Paul Campbell with claude b0da3d86

  12. domains-per-host-doorconsole: a per-host domains read, so a refresh is not a deployment-wide scan (#299)

    Paul Campbell with claude c135cccc

  13. console-as-an-appThe console is an app: carlos deploy -app console, and a rollback that leaves the box running.

    Paul Campbell with claude carlos apps fd4b8f4a

  14. ses-event-pathCount deliveries, and say when a topic is refused. Closes the first two of #270.

    Paul Campbell with claude 0489037c

  15. custom-domains-manageddomains: managed custom-domain connections — one state, structured records, capability discovery, and platform-provisioned certs (#299)

    Paul Campbell with claude 039c0645

  16. mail-configset-reconcileVerify reconciles the configuration set in both directions, closing #272.

    Paul Campbell with claude 72ed99ec

  17. mail-refresh-policiesGrant before bind: domains add must not 554 the app it repairs.

    Paul Campbell with claude 0d3cf9de

  18. pipelines-v2-residualspipelines v2 follow-ups: ratchet-backed bake verdicts, one-channel canary visibility, execution re-checks

    Paul Campbell with claude 1fb7fecb

  19. arch-legibilityarch page: alarms ride the node they watch, text fits its box, BYO boxes carry no price

    Paul Campbell with claude 35666a40

Release notes

CLI flag conventions

The documented face of every carlos command now says --app. Both spellings have always parsed identically — Go's flag package treats -app and --app the same — so this release changes what the tool teaches, not what it accepts: usage pages, docs, and error messages all show the double-dash form, and the four flags you type all day gain short aliases:

--app, -a        --channel, -c
--environment, -e  --version, -v

The old single-dash spellings (-app, -channel, …) keep working forever; nothing you have scripted breaks. Every command's -h page is now generated from the live flag set through one usage printer, so a usage page can no longer drift from what the parser actually accepts. (#321)

Licence

The platform source is now MPL-2.0, following the redaction pass ahead of the repository going public. (#317)

For operators

The same binary is the edge, the host agent, and the console, so this tag also carries fleet-side work:

  • Non-issuer certificate backfill (#320, #318): certsync backfills certificates into control/certs/ on every contending box, not just the issuance winner, with identity settle stamps — a box that never wins issuance still converges the certificates it serves.
  • Delegated customer wildcards on every edge (#311, #305): the edges file publishes delegated wildcards and every edge loads them, closing the last name-scope gap for serving custom names through region edges.
  • Fleet architecture page (#237): the console renders /fleet/architecture, an architecture diagram drawn from a provider-neutral inventory of the fleet.

Nothing in this tag changes what existing scripts parse — -app and friends behave exactly as before.

Changes

5
  1. cli-flagsCLI flag conventions: --app canonical, four short aliases, one usage printer

    Paul Campbell with claude carlos auth carlos apps carlos ship carlos promote carlos deploy 4235e9fd

  2. nonissuer-cert-backfillcertsync: backfill on every contending box; identity settle stamps (#318)

    Paul Campbell with claude 9f3cf41e

  3. fleet-diagramFleet architecture diagram: /fleet/architecture over a provider-neutral inventory

    Paul Campbell with claude 65c6956e

  4. open-source: MPL-2.0 licence and redaction pass ahead of going public (#317)

    Paul Campbell with claude 2adc71f3

  5. delegated-wildcards-deploymentedges file: delegated customer wildcards are published and loaded on every edge (#305)

    Paul Campbell with claude 2aaf747b

Release notes

carlos economics backhaul

What serving through region edges costs the platform. When a request lands on a region edge and is carried on to the account's home box, the inter-region leg is a cost the platform absorbs — it sits inside the account's egress total, never on top of it, and appears in nobody's bill. This verb is the operator's view of that leg:

carlos economics backhaul [-period mtd|last|7d]

Per account: bytes backhauled, the share of that account's egress it represents, and what the leg comes to at the rate card's inter-region $/GB. The header shows the period's coverage (days of meters present) so a partial month reads as one. Backhaul meters are a subset of the egress meters and are never counted as usage. Operator only — a non-operator's token gets the same bare 404 an unknown route gets. (#288, #284)

carlos economics with no sub-verb now lists both bill and backhaul.

Multi-region ingress, hardened

The same binary is the edge and the host agent, so this tag also carries the steering work that has been rolling out across the fleet:

  • Custom domains through any edge (#287): the edges file publishes attached custom domains under their own names, aliases are marked on the wire, routes win collisions, and the config layer denies entry for names that must not be published.
  • Wildcard parents (#300, #290): derived from the deployment's hosts — provisioned routes as well as console-minted ones — with the class mark on the wire, a serialized refresh, and an async wake that is blind to catch-alls.
  • Per-box domain health stamps (#303, #304): run on every box again, once per tick, never on a fleet box, inert without an apps domain; a resolver failure never overwrites a DNS verdict.
  • Certificate backfill (#291, #297): the issuer backfills pre-existing certificates into control/certs/, with the settled stamp pinned on the bucket side.
  • Domains reconcile is a housekeeper duty (#289): one writer per deployment.
  • Snapshot fingerprint ignores the box's own scheduling stamps (#207), ending a churn where every tick looked like a change.

Docs

Two docs sites (carlosframework.com/docs, carloku.com/docs) now build from a corpus in this repo, with a gate that holds the CLI reference to main.go's dispatch switch — every command must have a page, every fence a language, every link a target.


carlos economics backhaul needs a console running this build or later; everything else in this tag is fleet-side and already rolled.

Changes

9
  1. hop-readereconomics: what backhaul costs us — meters, pages, API and CLI (#288)

    Paul Campbell with claude carlos economics 845a850c

  2. aliases-in-edges-fileedges file: publish attached custom domains under their own names (#287)

    Paul Campbell with claude 5e9b918c

  3. domains-health-per-boxdomains: the per-box health stamps run on every box again (#303)

    Paul Campbell with claude 6340c9e1

  4. docsdocs: carlosframework.com/docs — the corpus, six gates, and the CLI reference

    Paul Campbell with claude your apps carlos auth carlos apps carlos ship carlos promote e9628b7d

  5. wildcard-parents-deploymentedge: wildcard parents are derived from the deployment's hosts, not the box's (#300)

    Paul Campbell with claude da9a7eeb

  6. snapshot-fingerprint-churnregistry: SnapshotFingerprint ignores the box's own scheduling stamps (#207)

    Paul Campbell with claude cbb65607

  7. cert-backfillcertsync: the issuer backfills pre-existing certs into control/certs/ (#291)

    Paul Campbell with claude 3e8a6759

  8. wildcard-parents-provisionededge: wildcard parents from provisioned routes too (region edges served no wildcards)

    Paul Campbell with claude d6cd0e90

  9. domains-loop-housekeeper-dutyhost: the domains reconcile is a housekeeper duty (one writer per deployment)

    Paul Campbell with claude d7eba3e5

Release notes

A static site gets a URL from the CLI alone

carlos deploy -kind static with no -host now mints the app's own platform hostname — <app>.<sqid>.<apps-domain> — and the static route record that serves it. Publishing a site no longer requires owning a domain or pointing DNS at anything:

carlos apps create -app mysite
carlos deploy -kind static ./dist

Everything it needs was already there: DNS under the apps domain resolves to the edge at any depth, and the edge derives its own per-account wildcard certificate from the live route table. The missing piece was a record, and now the CLI writes one.

-host still does exactly what it did — it now means "serve on this hostname instead of the app's own", and remains the answer for a domain you control.

carlos instances set-channel

The only door onto which release channel a route follows. A route's channel lives in its instance record, which the box converges from every pass, so carlos route -channel on a box is reverted within seconds — and until now nothing else could change it. A route that landed on the wrong channel had a URL that served nothing and no way back.

carlos instances set-channel -app <a> -host <h> -channel <c>

A move must clear the rules of both channels it touches, each at its strictest, because a move can achieve a promotion: with production requiring approvals and edge requiring none, moving the production route onto edge would otherwise serve unreviewed code from a guarded URL with nobody's approval. Gated moves are proposed and confirmed in the console, exactly like a promote.

carlos instances create -kind

instance (default) | service | static — exposing the route class the record shape has always carried.

carlos schedule

Recurring and one-shot work per app, owned by the platform rather than by a box's crontab: carlos schedule ls | set | rm | run. Landed in #285 and included in this tag; boxes and consoles are already rolled for it.


Requires a console running this build or later for set-channel; the static mint works against any console with a platform apps domain configured.

Changes

7
  1. static-cliA static site gets a URL from the CLI, and a route's channel can change

    Paul Campbell with claude ee76d394

  2. cronScheduled work: recurring schedules and one-shot timers as a platform concern

    Paul Campbell with claude 2fb300b1

  3. egress-and-minting-rulingsmulti-region: backhaul egress ruling (cap + hop metering) and the #277 cert-gate fix

    Paul Campbell with claude 6a861ce1

  4. retire-github-ciRetire the GitHub workflow: amadan CI is the gate now

    Paul Campbell with claude 1010be20

  5. amadan-ci-minioamadan CI: port the minio-contract job, without a container runtime

    Paul Campbell with claude cd47f38f

  6. amadan-ci-one-definitionamadan CI: one definition of the gate, so gofmt is actually checked

    Paul Campbell with claude ae6a1824

  7. amadan-ci-cross5amadan CI: cross-compile all five targets, not three

    Paul Campbell with claude a0e1b911

Release notes

Tenant email — carlos email

An app on CARLOS can now send mail without running an MTA or holding a cloud key. The platform mints a sending identity, publishes DKIM, SPF and DMARC where it owns the zone, and delivers working SMTP credentials as config.

carlos email enable -app <app>

That is the whole walk: declare, provision the domain, wait for verification, deliver. The identity defaults to the app's own host, so the signing domain matches the domain of the links inside the mail. Credentials arrive as CARLOS_SMTP_HOST, _PORT, _USER, _PASS, _FROM (rename the set with -env-prefix). Transport is submission on 587 with STARTTLS.

For a customer's own domain, -domain mail.example.com prints the record set for the zone's owner to publish and polls until SES confirms it.

The rest of the surface:

Verb What it does
carlos email status What is declared, which domains verified, what was delivered
carlos email test -to <addr> Sends a real message through a throwaway credential, then revokes it
carlos email domains add Add a second sending domain
carlos email credentials create|list|revoke Standalone credentials for something not on CARLOS; the password is shown once
carlos email rotate [-finish] Two-phase key rotation
carlos email pause|resume A deployment operator's abuse brake
Three things worth knowing
  • A freshly minted credential does not work for the first minute or two. SES's SMTP endpoint does not see a new IAM access key immediately, and the symptom is 535 Authentication Credentials Invalid — which reads exactly like a wrong password and is not one. carlos email test now waits this out; an app's own first sends after enable will still meet it.
  • DMARC passes on the DKIM rail alone. Records are published with adkim=s; aspf=s, and that strictness is what stops one tenant's signature authenticating another tenant's From address on a shared domain. SPF authenticates but does not align, because the envelope sender is a region-qualified subdomain. So never turn off DKIM signing on a sending identity, and treat p=reject as safe but unforgiving.
  • The MAIL FROM subdomain carries its region forever, fixed at first verification. On a custom domain it lives in the customer's zone — the one record CARLOS cannot republish for them.

Also in this release

  • Multi-region steering is member-settable and pool-railed.
  • carlos email status names a verified domain that emits no SES events, rather than showing counts that can only ever be zero.

Changes

9
  1. fix-configset-policyGrants the configuration set the credential sends through, closing #271.

    Paul Campbell with claude 04dece9d

  2. multi-region-steeringconsole: repair the #259 merge (compile fix)

    Paul Campbell with claude a87affbd

  3. multi-region-steeringMulti-region steering: latency DNS, health checks, the probe (#238 Part 4)

    Paul Campbell with claude ddc2fcc4

  4. ses-ingest-fixemail status names a verified domain that emits no SES events, and fixes a latent nil-deref on a nil RegionState.

    Paul Campbell with claude ab58c524

  5. console-mail-cardConsole Email card on the app Settings tab, mirroring StoreCard.

    Paul Campbell with claude c25cd5f6

  6. email-followupsFixes carlos email test, which could not succeed at all, and corrects two spec statements the first live send disproved.

    Paul Campbell with claude d64deac0

  7. emailTenant email sending for CARLOS: SMTP credentials issued by the platform, backed by SES multi-tenancy.

    Paul Campbell with claude fe1a31ab

  8. docs: AGENTS.md is the canonical agent-instructions file (#260)

    Paul Campbell with claude 8fb52b27

  9. console: ship budget is 2 a minute, and a refusal says how long (#262)

    Paul Campbell with claude deccd44f

Release notes

Release pipelines: apps start with one edge channel; carlos pipeline (show / init-from-template / add / set / remove) opts into multi-channel pipelines with per-channel bake windows, passkey and N-member approval rules. carlos promote/rollback propose gated actions and print where to finish them; -hotfix now works over the API (order bypass only — rules always apply); carlos deploy resolves a pipelined app's entry channel and treats a pending proposal as success, not failure.

Built from platform tag v0.11.0 (main a347034). SHA256SUMS.txt is signed (SHA256SUMS.txt.sig) for carlos update. Windows remains client-only (zip; no self-update).

Changes

7
  1. edge-beta-stableRelease pipelines v2 — one channel by default, pipelines opt-in

    Paul Campbell with claude a347034f

  2. multi-region-steering-planplan: multi-region steering (plan 3 of 3, spec Part 4)

    Paul Campbell with claude d662f1b6

  3. multi-region-backhaulMulti-region backhaul: home maps, mesh key, one-hop dialing, serving classes (#238 Part 3)

    Paul Campbell with claude 920d5994

  4. multi-region-backhaul-planplan: multi-region backhaul (plan 2 of 3, spec Part 3)

    Paul Campbell with claude eab8c788

  5. multi-region-ingress-specMulti-region stage 1-2: carry #245 to main

    Paul Campbell with claude 66dbc05f

  6. multi-region-ingress-specspec: multi-region ingress — TLS at every edge (#238)

    Paul Campbell with claude 67fb71d5

  7. ci: run the gate on amadan too, with the cross-compiles one per shard (#233)

    Paul Campbell d9a643fd

Release notes

Windows

carlos now runs on Windows as a client: carlos login, ship, deploy, logs — everything that talks to a console or a bucket — from a Windows workstation against a Linux fleet. Download carlos-windows-amd64.zip (or -arm64), unpack carlos.exe onto your PATH, and check it against SHA256SUMS.txt.

Two things to know:

  • carlos update does not self-replace on Windows. Windows cannot rename a new binary over a running .exe, so carlos update tells you when you're behind and hands you the zip URL instead of swapping itself.
  • Your credentials file is not permission-protected on Windows. On Linux and macOS ~/.carlos/credentials is written 0600; the equivalent mode means nothing on %USERPROFILE%\.carlos\credentials. Don't carlos login on a shared machine.

Windows cannot BE a box — carlos agent and the root-side passes need unix sockets, flock and systemd, and refuse there rather than pretending.

Also in this release

105 commits since v0.9.0, including:

  • Service principals (#227) — non-human members that deploy.
  • Edge response compression (#224, #230) — gzip on the shared edge.
  • Logs terminal pane (#209) in the console.
  • SQLite corruption defence (#200) and replica/hibernate freshness work (#211, #214, #213).
  • Wake single-flight (#199), fleet claims (#215), economics account names (#203).

Verifying

Every artifact's checksum is in SHA256SUMS.txt, signed with the CLI-update key as SHA256SUMS.txt.sig — the same signature carlos update checks against the public key embedded in the binary.

sha256sum -c SHA256SUMS.txt --ignore-missing

Changes

20
  1. windows-releasewindows: a client-only carlos, behind per-OS boundaries

    Paul Campbell with claude 4167d5b4

  2. service-rolesService principals: a console API caller that is not a person

    Paul Campbell with claude e934cb51

  3. specs: app trust classes + private instances, ahead of their code (#231)

    Paul Campbell with claude 59d2d435

  4. fix-gzip-verify-commanddocs: gzip verify command needs a GET, not curl -I

    Paul Campbell with claude 377d533f

  5. gzip-assetsEdge response compression (gzip)

    Paul Campbell with claude 09e6b5e5

  6. logs-terminal-paneconsole: the Logs tab is a terminal, not a table

    Paul Campbell with claude 89b6bbc2

  7. worktree-184-wake-singleflightactivator: failed wakes are singleflight — the initiator waits on its own entry (#184)

    Paul Campbell with claude d7077d17

  8. corruption-doc-updatedocs: record the currency question and the cutover blocker

    Paul Campbell with claude f5c5d07a

  9. fleet-claims-onlylitestream: the glob proposes, the registry disposes

    Paul Campbell with claude d63a566c

  10. hibernate-freshnesshibernate-verify: the same currency question as the box-wide drill

    Paul Campbell with claude c2466bf6

  11. unit-tenant-db-treeslitestream: unit-tenant DB trees, and refuse to shrink the replication set

    Paul Campbell with claude dd04065e

  12. titogo-bugsRoute-scoped config delivery: exec_delivery per environment, fast rebinding convergence, carlos routes

    Paul Campbell with claude 5bef643f

  13. replica-freshnessrestore-verify: prove the replica is CURRENT, not merely restorable

    Paul Campbell with claude 0ed1ed12

  14. claudemd-merge-ruleCLAUDE.md: agents may merge a PR; the rule is about how work reaches main

    Paul Campbell with claude b77856a8

  15. verify-tmp-rationaleverify drills: correct the tmpfs rationale with what the box measured

    Paul Campbell with claude c80b67ef

  16. verify-tmp-on-diskverify drills: restore to disk, because tmpfs files are memory

    Paul Campbell with claude 72a0c10f

  17. sqlite-corruption-defencedurability: drill the replicas nobody drilled, check what we restore

    Paul Campbell with claude 104e261a

  18. econ-account-namesconsole: economics pages show account names, sqids muted

    Paul Campbell with claude 3f28e9f9

  19. business-modelCarloku business model: the ladder, the pool, fleet pricing

    Paul Campbell with claude c4fb7309

  20. gofmt: blank line before the stamped-units banner in agent_test.go (#188)

    James Adam 8371cf89

Release notes

The project-defaults release: carlos deploy, alone, is the whole flow (platform#185).

  • Zero-arg carlos deploy: resolves your account and app (offering to create one — named after your directory — in a fresh project), asks for the artifact once, and offers to save it all to .carlos/config. Every deploy after that is one word.
  • Omitted -app resolves everywhere: every app-scoped command uses your project's saved app, your account's only app, or asks — same rules -account gained in v0.7.0. Scripts keep exact errors; explicit flags always win.
  • Channel ambiguity in deploy is now a numbered choice at a terminal instead of "pass -channel".
  • Hardening: project-config artifacts are confined to the project tree (a committed config can never ship files from outside your checkout), and save prompts only ever cover what you actually chose.

Built from platform tag v0.9.0. SHA256SUMS.txt is signed (SHA256SUMS.txt.sig); carlos update from v0.8.0 verifies and installs this release.

Changes

11
  1. worktree-project-defaultsProject defaults: zero-arg carlos deploy, resolved -app, saved state in .carlos

    Paul Campbell with claude f906a303

  2. worktree-domain-attachDomain attach: self-serve custom domains from Settings, CLI and deploy (#82)

    Paul Campbell with claude c42ec0c3

  3. ha-posture-specdocs: HA posture ladder + multi-upstream addr routes — design record

    Paul Campbell with claude 729cffb0

  4. ha-snapshothost: registry snapshot to bucket + auto-recovery alarm (HA rung 0/1)

    Paul Campbell with claude 58e65c63

  5. multi-upstream-routesedge: multi-upstream health-checked addr routes (#152)

    Paul Campbell with claude a49a7cf6

  6. worktree-route-recordsroute records: a route's desired state lives in the bucket (#123, #130)

    Paul Campbell with claude d754d04e

  7. claim-derived-wildcardsClaim-derived wildcard state: delegated parents, catch-all aliases, capability door (Plan C)

    Paul Campbell with claude c16f5574

  8. unit-economicsUnit economics: metering, cost/profit dashboards, scenarios, CE bill reconcile

    Paul Campbell with claude 82832041

  9. worktree-route-hostnamesroute hostnames: attach/detach an extra public hostname on an existing route (#151)

    Paul Campbell with claude 8f363775

  10. worktree-woodstar-carlokuWoodstar → Carloku migration: spec + Plans A/B (docs)

    Paul Campbell with claude e03d95b1

  11. edge-delegated-wildcardsedge: delegated-challenge wildcard certs (customer domains, zero customer DNS knowledge)

    Paul Campbell b56213fd

Release notes

The proactive release: when carlos can see both the problem and the fix, it offers the fix (platform#160, #161, #162).

  • Moved consoles are explained, not numbered: a permanently-redirected console produces this console has moved: old -> new, an offer to log in to the new home, and an offer to repoint your .carlos/config — never again "unexpected response (status 308)". Redirects are never silently followed (a cross-host follow used to drop your credentials into a mystery 401).
  • Missing logins are offered: run any command while logged out and, at a terminal, the CLI runs the login right there and then continues your command. Scripts keep the exact errors they've always matched.
  • carlos update: a once-a-day muted hint when a newer release exists, and a verb that updates a plain-binary install after verifying the release's signed checksum list (ed25519 key embedded in the binary) — brew and apt installs are handed to their package manager. update_check: "off" in .carlos/config or CARLOS_NO_UPDATE_CHECK opts out.

This release introduces SHA256SUMS.txt.sig: the checksum list is signed with the CARLOS CLI-update key from here on.

Built from platform tag v0.8.0. Static binaries, no dependencies.

Changes

1
  1. worktree-proactive-cliProactive CLI: moved consoles explained, logins offered, self-update (#160 #161 #162)

    Paul Campbell with claude e52d8ecc

Release notes

The account-discovery release: carlos now finds your account instead of making you guess it (platform#157).

  • Omitted -account resolves itself (signed-in mode): your one account is used automatically; with several you get an interactive chooser — which can save the pick as the project default in .carlos/config — or, in scripts, an error that lists your accounts.
  • carlos accounts list now works signed-in from any machine: your accounts as NAME / SQID / ROLE, no box access needed.
  • carlos auth whoami prints your memberships alongside your identity.
  • .carlos/config gains an account key (a console+account pair, honored only for that console); config rewrites now preserve keys written by newer versions.

Built from platform tag v0.7.0. Static binaries, no dependencies; debs install with apt install ./carlos_0.7.0_<arch>.deb or from the apt repo.

Changes

3
  1. worktree-account-defaultCLI: default -account to your own account; membership discovery (#157)

    Paul Campbell with claude 9d1084ec

  2. worktree-fleet-apiFleet API surface: the deployment bucket behind the edge (#73)

    Paul Campbell with claude a73539fe

  3. dashboard-truth-and-scaleDashboard truth + scale: honest health, route-granular mismatch banner, instance list controls

    Paul Campbell with claude fb590565

Release notes

Built from carlosframework/platform @ v0.6.0 (79f6fc2). Verify with SHA256SUMS.txt. See the repo README for install instructions.

Highlights: carlos logs — an app's merged log timeline (its own output + platform events: wakes, restarts, and why a wake failed) with time/stream/instance/level/grep/field filters and -f live follow; carlos deploy timeout reports now include the wake reason. Debian packages included.

Changes

18
  1. deploy-hint-wake-reasondeploy: timeout report carries the wake reason and names carlos logs (#131)

    Paul Campbell with claude 79f6fc27

  2. worktree-customer-fleetsCustomer fleets: account-attached compute (v1)

    Paul Campbell with claude 00c33444

  3. worktree-releases-retentionreleases retention: ambient prune for shipped releases (#136)

    Paul Campbell with claude e816eba6

  4. object-storage-primitiveobjstore: object-storage primitive (#55)

    Paul Campbell with claude b7b7a16d

  5. carlos-logscarlos logs: an app's merged log timeline with no box access (#131, #78)

    Paul Campbell with claude db76025d

  6. console-critique-and-ignorekeep the console clarity critique; ignore the root binary and worktrees

    Paul Campbell with claude ca7c86b3

  7. console-running-and-flowconsole: retire "Machines", and draw the release path as a path

    Paul Campbell with claude bdadb3f5

  8. worktree-versions-sort-then-fetchconsole/CLI releases: rank versions by manifest stamp before reading manifests

    Paul Campbell with claude 8f64abd6

  9. console-clarity-batchconsole: clarity batch — health verdict, safety delay, progressive reveal (P0s+P1s)

    Paul Campbell with claude a86de88c

  10. worktree-deploy-url-outputcarlos deploy: name the destination URL on every path

    Paul Campbell with claude 11670ef5

  11. worktree-metrics-instances-fixesconsole + agent: instances page gets real readings for exec-backed apps, stops flapping, stops paying the sweep

    Paul Campbell with claude 9668d302

  12. worktree-issues-69-70-db-pathregistry+cli: db_path rewrites reach running edges; relative -db refused on exec routes

    Paul Campbell with claude 934414c8

  13. worktree-exec-instance-metricsagent: exec-backed instances get per-instance metrics (#118)

    Paul Campbell with claude 5695e88d

  14. claude-md-small-thingsCLAUDE.md: deploy reality after the small-things batch

    Paul Campbell with claude 332aecaf

  15. static-headerStatic routes carry X-Carlos-Version; carlos deploy watches static apps (#112)

    Paul Campbell with claude 916cd6b3

  16. restart-verbcarlos restart: cycle an app's processes with no box access (#113)

    Paul Campbell with claude de23f6ae

  17. route-unitRoutes learn the systemd unit that owns their process; adoption cycles it (#110)

    Paul Campbell with claude c8b2eed2

  18. small-residualsSmall residuals: #58 sibling back-fill, syncable anti-drift, trash serial bumps, concurrent deploy watch

    Paul Campbell with claude 40469637

Release notes

carlos deploy — seconds to live

One command from working tree to serving URL: carlos deploy -app <a> <binary-or-site-dir> ships, promotes to the channel your instances follow, and waits until the URL provably serves the new build (the edge's new X-Carlos-Version header, required over 2xx — exit 0 means live). -version defaults to your git short HEAD. On a bake-held production channel it ships, promotes, prints the hold, and exits without waiting — never a bake bypass.

Platform-side (live on CARLOS deployments running ≥ 1fba18f): promotes converge in seconds on every non-baking channel, warm instances restart onto the new build automatically, and brand-new instances stage at first request instead of 503ing.

Also in this release (from #107): carlos releases, version targets (carlos version target), -label/-notes on ship, and semver tags cut when a release reaches stable.

New: Debian packages — carlos_0.5.0_{amd64,arm64}.deb; install with sudo apt install ./carlos_0.5.0_arm64.deb. Homebrew: brew install carlosframework/tap/carlos.

Changes

29
  1. carlos-deploy-docsdocs: deploy reality — seconds-to-live convergence, console restart caveat

    Paul Campbell with claude 7a3d8c15

  2. worktree-carlos-deploycarlos deploy: seconds-to-live for every non-baking channel

    Paul Campbell with claude · James Adam with claude 1fba18ff

  3. worktree-release-versioning-specRelease versioning: targets, labeled iterations, tags with changelogs

    Paul Campbell with claude 1c9381d2

  4. worktree-instance-socket-consumersInstance-socket consumers: blessed cross-user story for /run/carlos (issue #103)

    Paul Campbell with claude 32dec0b9

  5. worktree-console-carloku-hostconsole: CONSOLE_REDIRECT_HOSTS — retired hosts 301/308 to the canonical origin

    Paul Campbell with claude edbfbc43

  6. worktree-console-app-pagesConsole app pages v2: dashboard overview, human ladder, confirm cards, fast instances table, real settings

    Paul Campbell with claude dc6a6c34

  7. console: send the reader at the API-backed verb, not box-local carlos add (#99)

    James Adam with claude 82dbca9d

  8. s3compat: one home for S3-compatible quirks; fix CAS on Ceph RGW (#92)

    James Adam with claude 6a52ae09

  9. lease: honour CARLOS_S3_ENDPOINT, so hibernation (and instance provisioning) works off AWS (#88)

    James Adam with claude f3001017

  10. CLI: colour the output, but only ever on a terminal (#93)

    James Adam with claude 084b86ff

  11. echoapp: accept --db, so the reference tenant can boot exec-backed

    James Adam with claude 535038f4

  12. clearer-command-displaycarlos: group the top-level command list by role

    James Adam with claude 9553b7bf

  13. ci-build-gateci: run the build gate on every PR, including a darwin compile

    James Adam with claude 38b49990

  14. worktree-tito-console-rerollhost: fix darwin build — Statfs Bsize is uint32 there

    Paul Campbell with claude 40937553

  15. worktree-console-redesignconsole: carloku reskin + Heroku-style IA — sections, tabs, and a settings page of one's own

    Paul Campbell with claude b918b56f

  16. issue-66-api-go-liveConsole API + CLI: bring an app live on its platform domain with a login alone (#66)

    Paul Campbell with claude dd87bf67

  17. worktree-api-cli-ruleCLAUDE.md: day-to-day admin via API/CLI, direct AWS only for platform work

    Paul Campbell with claude 91d03117

  18. merge: carlos apps create — app creation over the console API, rate limited (#52)

    Paul Campbell with claude 1c32d739

  19. merge: per-account wildcard DNS-01 certs — instant TLS for new app hostnames (#60)

    Paul Campbell with claude 7302bad8

  20. merge: raspberry pi instance host — region pi on the dev platform (#59)

    Paul Campbell with claude 7ea697f6

  21. merge: app deletion — the trash, the 30-day cooloff, and the ceremonial purge (#56)

    Paul Campbell with claude f11e8c5b

  22. merge: instance provisioning — placing an instance is a data write, never host surgery (#54)

    Paul Campbell with claude 749fc22c

  23. merge: app capabilities — a closed vocabulary the platform materializes (#40)

    Paul Campbell with claude 09b084d5

  24. merge: only a hibernating instance may render as asleep (#30)

    Paul Campbell with claude 36ff0206

  25. worktree-remote-host-agentRemote host-agent: tunnel route backing, heartbeat metrics, off-cloud bootstrap (#53)

    Paul Campbell with claude d6e7d08b

4 more
  1. worktree-config-console-apiconfig: env/secrets through the console API, and fast convergence — both halves (issues #43, #44)

    Paul Campbell with claude 28874d56

  2. worktree-console-default-configcarlos: settable default consoles (~/.carlos/config + per-project .carlos/config)

    Paul Campbell with claude 761d3d01

  3. merge: console bake controls — the production flag and fast-track (#47)

    Paul Campbell with claude 088358d7

  4. merge: account names as addresses — /a/amadan resolves, ambiguity is loud, -account-id never guesses (#46)

    Paul Campbell with claude 6d5f71ab

Release notes

carlos v0.4.0 — the CARLOS platform binary (edge, host agent, operator CLI). Built from carlosframework/platform @ v0.4.0. Verify with SHA256SUMS.txt. See the README for install instructions.

Supersedes v0.3.0, which was built from a commit predating the console-API CLI merge.

The headline: deploys need no bucket access and no keys in the terminal.

carlos auth login -console https://<your-deployment-console>
carlos ship    -account <acct> -app <app> -version <sha> ./<binary>
carlos promote -account <acct> -app <app> <sha> canary/<name>

A logged-in terminal ships and promotes through the console API; the console signs server-side and your account membership is the authorization. channels and rollback work the same way. The direct bucket mode (CARLOS_DEPLOYMENT_BUCKET + signing key, root or scoped) remains for operators and CI, and promote -hotfix is deliberately operator-only.

Also since v0.3.0: host & process monitoring, external-socket advisory, open-ledgers primitive, follow-up hardening.

Changes

8
  1. ledger-primitiveOpen-ledgers primitive: hash-chained ledger streams, console API writes, fail-closed edge serving

    Paul Campbell with claude 3b8e3238

  2. infra/region-host: never let a floating AMI replace a live host (#38)

    Paul Campbell with claude 0cd91622

  3. spec + plan: open ledgers — status.carlosframework.com's full ledger set on a platform primitive (#31)

    Paul Campbell with claude 114255c8

  4. merge: follow-up fixes — the bake clock leaves /opt, 1xx stops killing the cache, purges ride a host index, unit tenants learn the channel (#33)

    Paul Campbell with claude cc933026

  5. merge: external-socket advisory — a stray process serving an exec route's socket is now loud (#28)

    Paul Campbell with claude b8e930b5

  6. merge: host & process monitoring — agent sampler, alerts, operator + owner dashboards (#23)

    Paul Campbell with claude 98348152

  7. merge: CLI through the console API — carlos ship/promote without seeing the infrastructure (#25)

    Paul Campbell with claude 7eb397eb

  8. framework design doc: record §4 package-per-directory resolution (#21)

    Paul Campbell with claude a8b4ad47

Release notes

Superseded by v0.4.0 — this build was cut from a commit predating the console-API CLI merge, so it lacks ship/promote through the console (bucket-free deploys). Use v0.4.0.

carlos v0.3.0 — the CARLOS platform binary (edge, host agent, operator CLI). Built from carlosframework/platform @ v0.3.0. Verify with SHA256SUMS.txt.

Highlights since v0.1.0:

  • carlos auth login -console <url> — log a terminal in to a deployment's console. whoami / logout round it out.
  • ship / promote / channels / rollback take -account <sqid|name> — deploys are account-scoped; promote climbs the ladder canary → edge → beta → stable.
  • accounts, env, secrets verbs; scoped release signing keys (release-keygen -scope).

Changes

44
  1. merge: scoped signing keys — a key that can reach edge cannot touch stable

    Paul Campbell with claude b60b18af

  2. spec: scoped signing keys — a key that can reach edge cannot touch stable

    Paul Campbell with claude f1cc9146

  3. merge: opt-in exec config delivery — the app-supervised shape (issue #18, platform half)

    Paul Campbell with claude eced477d

  4. edge: Carlos-Purge-Host — same-app+account cross-host purge override (#24)

    Paul Campbell with claude 5f3b8929

  5. rastrillo-ui-addendumspec: rastrillo UI addendum — app shape, reactivity, icons, WCAG 2.2 AA

    Paul Campbell with claude dc80c657

  6. accounts: a legacy-source migration never moves a qualified pointer backwards

    Paul Campbell with claude b1bb191f

  7. spec: unit-tenant purge channel — Carlos-Purge response header design (#19)

    Paul Campbell with claude be5a9993

  8. edge: Carlos-Purge response-header purge channel (#22)

    Paul Campbell with claude 8bc97547

  9. merge: retire the legacy read-fallback — the runtime reads qualified keys only

    Paul Campbell with claude 0ca02f6c

  10. edge: per-entry Vary storage — mixed Vary schemes coexist per URL (#20)

    Paul Campbell with claude 6846d9af

  11. merge: canary TTL — expiry is visibility, never a gate (spec §5)

    Paul Campbell with claude 3c7c7bc3

  12. carlos env/secrets: exec-backend delivery — the instance-fleet shape (#16)

    Paul Campbell 079b0857

  13. merge: environments — named config bundles, bound per route (pipelines slice 2)

    Paul Campbell with claude 6c8d5fdb

  14. merge: edge cache follow-ups — the header class swept, a real Close race, and an honest deferral (#12)

    Paul Campbell c8038ae6

  15. spec+plan: environments layer on app-config — pipelines slice 2

    Paul Campbell with claude c0823de3

  16. merge: edge cache-before-wake — bots shouldn't wake hibernated instances (#10)

    Paul Campbell with claude 41d99f4e

  17. route: a verb to move a route's channel subscription, safely

    Paul Campbell with claude de07dac9

  18. carlos env/secrets: bucket-backed app config, encrypted at rest (#9)

    Paul Campbell 68d06629

  19. docs: CLAUDE.md — delegation policy and the rules this repo has paid for

    Paul Campbell with claude 98377f22

  20. plan: pipelines slice 1 — the ladder, enforced and visible

    Paul Campbell with claude a106a581

  21. spec: pipelines — channels are maturity, environments are glue

    Paul Campbell with claude 6258137e

  22. release: pin that canary never jumps to stable

    Paul Campbell with claude 97f0561e

  23. pipelines slice 1: the ladder, enforced and visible (#11)

    Paul Campbell with claude 701bbd40

  24. console: passkey step-up for sensitive actions, and account deletion that sticks (#7)

    Paul Campbell with claude 13f7ece4

  25. accounts: name the legacy key space, so ops apps can leave it (#8)

    Paul Campbell with claude 84b40e36

19 more
  1. merge: vendor Lucide for the console's chrome

    Paul Campbell with claude 771c2f0a

  2. merge: carlos auth login — the terminal gets an identity

    Paul Campbell with claude cecc01a7

  3. spec: passkey step-up via fresh Keymail auth — a stolen session should not be enough

    Paul Campbell with claude abd6bcb0

  4. merge: the account switcher becomes a dropdown; New account gets its own screen

    Paul Campbell with claude 67cccf2a

  5. merge: backfill no longer undoes migrations; accounts create requires an owner

    Paul Campbell with claude a30a45da

  6. merge: membership tooling + sequential account ids

    claude fc94c671

  7. spec: account ids are sequential — 40-bit random gave 9-char sqids

    Paul Campbell with claude 4875560d

  8. merge fix: the fast-adopt test learns the account argument

    Paul Campbell with claude 5b4e8ffe

  9. feat: fast-adopt canary channels every few seconds, not hourly

    Paul Campbell with claude 6dce4e88

  10. merge: multi-account — accounts as projects, memberships, account-scoped app identity

    Paul Campbell with claude 68d6a91c

  11. plan: multi-account — eight tasks, read-fallback, migration as a verb

    Paul Campbell with claude 0b8caeaa

  12. spec: multi-account — accounts as projects, console-minted durable ids, account-scoped app identity

    Paul Campbell with claude 81662fb9

  13. merge: domains — platform domains, DNS/TLS health, console Domains section

    Paul Campbell with claude 5bbf4eed

  14. spec: canary minting is static-only; durable account ids gate the rollout

    Paul Campbell with claude 02da0129

  15. spec: record path routing as future work — the /blog case forces it eventually

    Paul Campbell with claude 80d6811b

  16. plan: woodstar → flagship (recon complete, execution deferred behind multi-account)

    Paul Campbell with claude 3481167c

  17. plan: domains — six tasks, frozen sqids, reconciler seams

    Paul Campbell with claude 1e1f0481

  18. plan: design a platform-dev environment in the repurposed kass AWS account

    Paul Campbell with claude 54b487ec

  19. spec: domains — account-sqid platform domains, custom-domain health, bucket-manifest accounts

    Paul Campbell with claude 81c53beb

v0.2.0

· Tagged but not published

Changes

50
  1. spec + plan: open ledgers — status.carlosframework.com's full ledger set on a platform primitive (#31)

    Paul Campbell with claude 114255c8

  2. merge: follow-up fixes — the bake clock leaves /opt, 1xx stops killing the cache, purges ride a host index, unit tenants learn the channel (#33)

    Paul Campbell with claude cc933026

  3. merge: external-socket advisory — a stray process serving an exec route's socket is now loud (#28)

    Paul Campbell with claude b8e930b5

  4. merge: host & process monitoring — agent sampler, alerts, operator + owner dashboards (#23)

    Paul Campbell with claude 98348152

  5. merge: CLI through the console API — carlos ship/promote without seeing the infrastructure (#25)

    Paul Campbell with claude 7eb397eb

  6. framework design doc: record §4 package-per-directory resolution (#21)

    Paul Campbell with claude a8b4ad47

  7. merge: scoped signing keys — a key that can reach edge cannot touch stable

    Paul Campbell with claude b60b18af

  8. spec: scoped signing keys — a key that can reach edge cannot touch stable

    Paul Campbell with claude f1cc9146

  9. merge: opt-in exec config delivery — the app-supervised shape (issue #18, platform half)

    Paul Campbell with claude eced477d

  10. edge: Carlos-Purge-Host — same-app+account cross-host purge override (#24)

    Paul Campbell with claude 5f3b8929

  11. rastrillo-ui-addendumspec: rastrillo UI addendum — app shape, reactivity, icons, WCAG 2.2 AA

    Paul Campbell with claude dc80c657

  12. accounts: a legacy-source migration never moves a qualified pointer backwards

    Paul Campbell with claude b1bb191f

  13. spec: unit-tenant purge channel — Carlos-Purge response header design (#19)

    Paul Campbell with claude be5a9993

  14. edge: Carlos-Purge response-header purge channel (#22)

    Paul Campbell with claude 8bc97547

  15. merge: retire the legacy read-fallback — the runtime reads qualified keys only

    Paul Campbell with claude 0ca02f6c

  16. edge: per-entry Vary storage — mixed Vary schemes coexist per URL (#20)

    Paul Campbell with claude 6846d9af

  17. merge: canary TTL — expiry is visibility, never a gate (spec §5)

    Paul Campbell with claude 3c7c7bc3

  18. carlos env/secrets: exec-backend delivery — the instance-fleet shape (#16)

    Paul Campbell 079b0857

  19. merge: environments — named config bundles, bound per route (pipelines slice 2)

    Paul Campbell with claude 6c8d5fdb

  20. merge: edge cache follow-ups — the header class swept, a real Close race, and an honest deferral (#12)

    Paul Campbell c8038ae6

  21. spec+plan: environments layer on app-config — pipelines slice 2

    Paul Campbell with claude c0823de3

  22. merge: edge cache-before-wake — bots shouldn't wake hibernated instances (#10)

    Paul Campbell with claude 41d99f4e

  23. route: a verb to move a route's channel subscription, safely

    Paul Campbell with claude de07dac9

  24. carlos env/secrets: bucket-backed app config, encrypted at rest (#9)

    Paul Campbell 68d06629

  25. docs: CLAUDE.md — delegation policy and the rules this repo has paid for

    Paul Campbell with claude 98377f22

25 more
  1. plan: pipelines slice 1 — the ladder, enforced and visible

    Paul Campbell with claude a106a581

  2. spec: pipelines — channels are maturity, environments are glue

    Paul Campbell with claude 6258137e

  3. release: pin that canary never jumps to stable

    Paul Campbell with claude 97f0561e

  4. pipelines slice 1: the ladder, enforced and visible (#11)

    Paul Campbell with claude 701bbd40

  5. console: passkey step-up for sensitive actions, and account deletion that sticks (#7)

    Paul Campbell with claude 13f7ece4

  6. accounts: name the legacy key space, so ops apps can leave it (#8)

    Paul Campbell with claude 84b40e36

  7. merge: vendor Lucide for the console's chrome

    Paul Campbell with claude 771c2f0a

  8. merge: carlos auth login — the terminal gets an identity

    Paul Campbell with claude cecc01a7

  9. spec: passkey step-up via fresh Keymail auth — a stolen session should not be enough

    Paul Campbell with claude abd6bcb0

  10. merge: the account switcher becomes a dropdown; New account gets its own screen

    Paul Campbell with claude 67cccf2a

  11. merge: backfill no longer undoes migrations; accounts create requires an owner

    Paul Campbell with claude a30a45da

  12. merge: membership tooling + sequential account ids

    claude fc94c671

  13. spec: account ids are sequential — 40-bit random gave 9-char sqids

    Paul Campbell with claude 4875560d

  14. merge fix: the fast-adopt test learns the account argument

    Paul Campbell with claude 5b4e8ffe

  15. feat: fast-adopt canary channels every few seconds, not hourly

    Paul Campbell with claude 6dce4e88

  16. merge: multi-account — accounts as projects, memberships, account-scoped app identity

    Paul Campbell with claude 68d6a91c

  17. plan: multi-account — eight tasks, read-fallback, migration as a verb

    Paul Campbell with claude 0b8caeaa

  18. spec: multi-account — accounts as projects, console-minted durable ids, account-scoped app identity

    Paul Campbell with claude 81662fb9

  19. merge: domains — platform domains, DNS/TLS health, console Domains section

    Paul Campbell with claude 5bbf4eed

  20. spec: canary minting is static-only; durable account ids gate the rollout

    Paul Campbell with claude 02da0129

  21. spec: record path routing as future work — the /blog case forces it eventually

    Paul Campbell with claude 80d6811b

  22. plan: woodstar → flagship (recon complete, execution deferred behind multi-account)

    Paul Campbell with claude 3481167c

  23. plan: domains — six tasks, frozen sqids, reconciler seams

    Paul Campbell with claude 1e1f0481

  24. plan: design a platform-dev environment in the repurposed kass AWS account

    Paul Campbell with claude 54b487ec

  25. spec: domains — account-sqid platform domains, custom-domain health, bucket-manifest accounts

    Paul Campbell with claude 81c53beb

Release notes

First tagged release of carlos — the CARLOS platform binary (edge, host agent, operator CLI). Built from carlosframework/platform @ v0.1.0. Verify with SHA256SUMS.txt. See the README for install instructions.

Changes

40
  1. plan: implementation plan for the platform-dev environment

    Paul Campbell with claude 1d67c651

  2. plan: design a platform-dev environment in the repurposed kass AWS account

    Paul Campbell with claude df6ded21

  3. depth-console-statusTenant hibernation + unix-socket upstreams, console slice 3, fleet status spec

    Paul Campbell with claude 6736599f

  4. plan: keymail overnight prep folded in — K0 PR open, K1 committed, K3 rehearsal verified; two cutover blockers named

    Paul Campbell with claude b11e511f

  5. plan: CARLOS framework design — event-driven writes, crypto core, manifest UI (#2)

    Paul Campbell with claude 4d15d766

  6. infra/region-host: optional extra_ingress rules (keymail MX needs tcp/25)

    claude 324617bf

  7. plan: keymail → flagship migration — recon, CARLOS fit, rehearsal + cutover

    Paul Campbell with claude 17bcc6a0

  8. console: app-internal instance visibility — the /.carlos/instances contract

    Paul Campbell with claude 3e9ae1c9

  9. console: audit table — the store remembers what owners did

    Paul Campbell with claude e22284c0

  10. feat: carlos-app@ tenant template — DynamicUser + full sandbox by default

    Paul Campbell with claude 8c15d9f3

  11. feat: console slice 2 — claim apps, promote, rollback from the browser

    Paul Campbell with claude 8d8c6178

  12. console: one-button Sign in with Keymail — no address entry

    Paul Campbell with claude 3a715183

  13. feat: platform console slice 1 — sign up/in with Keymail, read-only apps dashboard

    Paul Campbell with claude 492ebf66

  14. infra: deployment roots move to carlosframework/platform-infrastructure

    Paul Campbell with claude a91a7ae4

  15. Platform marketing site live; infra refactored into reusable modules

    Paul Campbell with claude 63a8a16c

  16. infra: note platform.carlosframework.com managed in personal DNSimple account

    Paul Campbell with claude 1c11de8a

  17. Kass cut over to the flagship; oncarlos.com registered and wildcarded

    Paul Campbell with claude 71df9f8c

  18. fix: rehearsal lessons — route-before-adopt, per-host live link, /data 711, ship keys binaries by target

    Paul Campbell with claude f4523b66

  19. infra: rehearsal + promote scripts; state and operator queues updated

    Paul Campbell with claude 30180792

  20. infra: bootstrap-box + provision-keys operator scripts (both boxes live)

    Paul Campbell with claude d8ee5570

  21. feat: ship -kind static packs the site dir deterministically

    Paul Campbell with claude 2024e502

  22. feat: static serving class, carlos vet, end-to-end smoke; flagship mail applied

    Paul Campbell with claude ede3ba44

  23. feat: host verbs — bootstrap, agent, adopt; tito svc-pdf ASCII fix

    Paul Campbell with claude bf2f8b69

  24. infra: tito operator queue + cutover checklist

    Paul Campbell with claude 2ed6993c

  25. infra: stage Kass secrets-copy script in the operator queue

    Paul Campbell with claude 6d5f1176

15 more
  1. feat: wire add/remove/instances, ship/promote/channels/rollback, ops verbs

    Paul Campbell with claude 67c944fa

  2. feat: activator, releases/channels, fleet ops (ported from Eleven + titogo)

    Paul Campbell with claude 845ffd40

  3. infra: flagship SES multi-tenant mail (Kass first) + operator queue

    Paul Campbell with claude 9be1c805

  4. infra: tito host-init script (was missing from the module)

    Paul Campbell with claude 4c610fbe

  5. feat: edge — host router with unix and TCP upstreams, ACME, live reload

    Paul Campbell with claude 6f8bb910

  6. feat: lease — single-writer S3 lease + litestream replication (from Eleven)

    Paul Campbell with claude f374052b

  7. deps: pin litestream, aws-sdk-go-v2, x/crypto at Eleven's proven versions

    Paul Campbell with claude 7bb6929c

  8. feat: registry — routes table with activator and placement columns

    Paul Campbell with claude 9f98be56

  9. feat: carlos binary scaffold with subcommand dispatch

    Paul Campbell with claude d2d3ed5b

  10. Add implementation roadmap and Plans A/B/C

    Paul Campbell with claude 4e0e131a

  11. Add static serving class: platform-hosted static sites

    Paul Campbell with claude e8d056df

  12. Confirm flagship account: Keymail's 271376211898, root email to move

    Paul Campbell with claude eb55b1ad

  13. Regions become a per-deployment registry, not platform constants

    Paul Campbell with claude 34a6c1e0

  14. Assimilate Tito production infra spec; add deployment topology

    Paul Campbell with claude 1d76bdb8

  15. Add CARLOS platform design spec

    Paul Campbell with claude 57b20bf7