carlos / platform Public

changelog-v0.28.4

Squashed from changelog-v0.28.4 into main.
claude agent, operated by paul@keymail.dev 57569bfffa089b9e0ac9c61b9d6f1a03ccf4fc97 parent cd2dd6e
3 files changed, +423 −0
  • docs/site/changelog-links.json +41 −0
  • docs/site/changelog.json +381 −0
  • docs/site/people.json +1 −0

CI passed — run details

CI log
=== gate ===
cd launchctx && go vet ./... && go test ./... -count=1
ok  	amadan.net/carlos/platform.git/launchctx	0.012s
?   	amadan.net/carlos/platform.git/launchctx/controlname	[no test files]
?   	amadan.net/carlos/platform.git/launchctx/wireid	[no test files]
go vet ./...
gofmt -l .: clean
go test ./... -count=1 -timeout 30m
ok  	github.com/carlosframework/platform	340.586s
?   	github.com/carlosframework/platform/cmd/changelog	[no test files]
ok  	github.com/carlosframework/platform/cmd/console	2.818s
ok  	github.com/carlosframework/platform/cmd/moveprobe	92.277s
ok  	github.com/carlosframework/platform/cmd/zddprobe	0.710s
ok  	github.com/carlosframework/platform/internal/activator	250.478s
ok  	github.com/carlosframework/platform/internal/agentsock	0.020s
ok  	github.com/carlosframework/platform/internal/alerting	0.005s
ok  	github.com/carlosframework/platform/internal/analytics	0.021s
ok  	github.com/carlosframework/platform/internal/appconfig	2.498s
ok  	github.com/carlosframework/platform/internal/apperr	0.075s
ok  	github.com/carlosframework/platform/internal/applog	0.142s
ok  	github.com/carlosframework/platform/internal/awsinv	0.004s
ok  	github.com/carlosframework/platform/internal/boxchoice	0.005s
ok  	github.com/carlosframework/platform/internal/boxid	0.802s
?   	github.com/carlosframework/platform/internal/boxid/boxidtest	[no test files]
?   	github.com/carlosframework/platform/internal/boxid/internal/signtest	[no test files]
ok  	github.com/carlosframework/platform/internal/boxvolumes	0.014s
ok  	github.com/carlosframework/platform/internal/caps	0.015s
ok  	github.com/carlosframework/platform/internal/certwarm	0.002s
ok  	github.com/carlosframework/platform/internal/cgroup	0.723s
ok  	github.com/carlosframework/platform/internal/changelog	0.337s
ok  	github.com/carlosframework/platform/internal/claimactivation	0.816s
ok  	github.com/carlosframework/platform/internal/clamd	0.054s
?   	github.com/carlosframework/platform/internal/cliflag	[no test files]
ok  	github.com/carlosframework/platform/internal/console	414.020s
?   	github.com/carlosframework/platform/internal/controlname	[no test files]
?   	github.com/carlosframework/platform/internal/controlsock	[no test files]
ok  	github.com/carlosframework/platform/internal/dbdoor	5.884s
ok  	github.com/carlosframework/platform/internal/dbdoor/dbdoortest	0.009s
ok  	github.com/carlosframework/platform/internal/dbverify	0.004s
ok  	github.com/carlosframework/platform/internal/dnsrec	0.004s
ok  	github.com/carlosframework/platform/internal/docsite	0.005s
ok  	github.com/carlosframework/platform/internal/domains	2.407s
ok  	github.com/carlosframework/platform/internal/doorkey	0.006s
ok  	github.com/carlosframework/platform/internal/economics	0.004s
ok  	github.com/carlosframework/platform/internal/edge	45.063s
?   	github.com/carlosframework/platform/internal/edgeproof	[no test files]
ok  	github.com/carlosframework/platform/internal/edgesfile	0.008s
ok  	github.com/carlosframework/platform/internal/fleetapi	0.133s
ok  	github.com/carlosframework/platform/internal/gate	1.657s
ok  	github.com/carlosframework/platform/internal/genselect	0.015s
ok  	github.com/carlosframework/platform/internal/geo	0.014s
ok  	github.com/carlosframework/platform/internal/geoip	0.029s
ok  	github.com/carlosframework/platform/internal/historyreadback	0.193s
ok  	github.com/carlosframework/platform/internal/host	187.421s
ok  	github.com/carlosframework/platform/internal/hostactors	5.534s
ok  	github.com/carlosframework/platform/internal/hostactors/awsmembership	0.005s
ok  	github.com/carlosframework/platform/internal/hostbox	2.722s
ok  	github.com/carlosframework/platform/internal/hostclaim	0.623s
ok  	github.com/carlosframework/platform/internal/hostenv	0.005s
ok  	github.com/carlosframework/platform/internal/hostevidence	0.005s
ok  	github.com/carlosframework/platform/internal/hostexec	5.051s
ok  	github.com/carlosframework/platform/internal/hostfence	0.044s
ok  	github.com/carlosframework/platform/internal/hostfiles	10.542s
ok  	github.com/carlosframework/platform/internal/hostfloor	0.016s
ok  	github.com/carlosframework/platform/internal/hostguard	1.003s
ok  	github.com/carlosframework/platform/internal/hostops	1.661s
?   	github.com/carlosframework/platform/internal/hostops/fencerelease	[no test files]
ok  	github.com/carlosframework/platform/internal/hostops/internal/fencerelease	0.002s
ok  	github.com/carlosframework/platform/internal/hostquarantine	0.002s
ok  	github.com/carlosframework/platform/internal/hostrelocate	0.476s
ok  	github.com/carlosframework/platform/internal/hostresolve	0.159s
ok  	github.com/carlosframework/platform/internal/hostwrite	0.002s
ok  	github.com/carlosframework/platform/internal/infraview	0.002s
ok  	github.com/carlosframework/platform/internal/instancectl	5.231s
ok  	github.com/carlosframework/platform/internal/instanceexec	2.738s
ok  	github.com/carlosframework/platform/internal/instancefs	0.008s
ok  	github.com/carlosframework/platform/internal/instancekey	0.002s
ok  	github.com/carlosframework/platform/internal/instanceupdates	0.009s
ok  	github.com/carlosframework/platform/internal/layout	1.599s
ok  	github.com/carlosframework/platform/internal/lbhealth	0.004s
ok  	github.com/carlosframework/platform/internal/lease	9.839s
ok  	github.com/carlosframework/platform/internal/lease/leasetest	0.005s
ok  	github.com/carlosframework/platform/internal/ledger	0.013s
ok  	github.com/carlosframework/platform/internal/mail	0.216s
ok  	github.com/carlosframework/platform/internal/maintenance	0.088s
ok  	github.com/carlosframework/platform/internal/maintenanceexec	5.521s
ok  	github.com/carlosframework/platform/internal/maintenanceguard	0.083s
ok  	github.com/carlosframework/platform/internal/metrics	0.006s
ok  	github.com/carlosframework/platform/internal/moves	21.337s
ok  	github.com/carlosframework/platform/internal/moves/archive	0.804s
ok  	github.com/carlosframework/platform/internal/objstore	0.202s
ok  	github.com/carlosframework/platform/internal/ops	0.182s
ok  	github.com/carlosframework/platform/internal/park	0.222s
ok  	github.com/carlosframework/platform/internal/privatefile	0.006s
ok  	github.com/carlosframework/platform/internal/provision	39.039s
ok  	github.com/carlosframework/platform/internal/publicrelease	0.008s
?   	github.com/carlosframework/platform/internal/regionname	[no test files]
ok  	github.com/carlosframework/platform/internal/registry	5.582s
ok  	github.com/carlosframework/platform/internal/relay	7.239s
ok  	github.com/carlosframework/platform/internal/release	24.788s
ok  	github.com/carlosframework/platform/internal/rollout	3.779s
ok  	github.com/carlosframework/platform/internal/rolloutwords	0.003s
ok  	github.com/carlosframework/platform/internal/rootaws	0.007s
ok  	github.com/carlosframework/platform/internal/rootparticipation	0.058s
ok  	github.com/carlosframework/platform/internal/rootstate	0.027s
ok  	github.com/carlosframework/platform/internal/runs	0.571s
ok  	github.com/carlosframework/platform/internal/s3compat	0.006s
ok  	github.com/carlosframework/platform/internal/safefile	0.004s
ok  	github.com/carlosframework/platform/internal/schedule	2.545s
ok  	github.com/carlosframework/platform/internal/seeds	0.013s
ok  	github.com/carlosframework/platform/internal/sim/hostlife	10.301s
ok  	github.com/carlosframework/platform/internal/sim/litestreamfacts	4.454s
ok  	github.com/carlosframework/platform/internal/status	0.060s
ok  	github.com/carlosframework/platform/internal/steering	0.006s
ok  	github.com/carlosframework/platform/internal/stopevidence	0.291s
ok  	github.com/carlosframework/platform/internal/svcrole	0.002s
ok  	github.com/carlosframework/platform/internal/telemetry	0.004s
ok  	github.com/carlosframework/platform/internal/termfence	0.007s
ok  	github.com/carlosframework/platform/internal/tunnelclient	0.004s
ok  	github.com/carlosframework/platform/internal/unixdial	0.003s
ok  	github.com/carlosframework/platform/internal/updatewords	0.004s
ok  	github.com/carlosframework/platform/internal/usage	0.004s
ok  	github.com/carlosframework/platform/internal/version	0.002s
ok  	github.com/carlosframework/platform/internal/vet	1.592s
=== cross ===
--- shard 0 of 5 ---
cross-compiling darwin/arm64
--- shard 1 of 5 ---
cross-compiling darwin/amd64
--- shard 2 of 5 ---
cross-compiling linux/arm64
linux/arm64 carlos binary: 49414306 bytes (ceiling 52000000)
--- shard 3 of 5 ---
cross-compiling windows/amd64
--- shard 4 of 5 ---
cross-compiling windows/arm64
=== minio-contract ===
minio contract: arm64, minio RELEASE.2025-09-07T16-13-09Z, mc RELEASE.2025-08-13T08-35-41Z
  minio: cached, digest verified
  mc: cached, digest verified
  minio healthy on 127.0.0.1:20999
Added `local` successfully.
Bucket created successfully `local/contract-bucket`.
Bucket created successfully `local/denied-bucket`.
Created policy `contract-only` successfully.
Added user `scopeduser` successfully.
Attached Policies: [contract-only]
To User: scopeduser
  buckets and scoped user ready
=== RUN   TestDeliveredContractMinio
=== RUN   TestDeliveredContractMinio/put
=== RUN   TestDeliveredContractMinio/get_round-trips_the_body
=== RUN   TestDeliveredContractMinio/list_shows_the_key
=== RUN   TestDeliveredContractMinio/head_and_list_agree_on_the_version
=== RUN   TestDeliveredContractMinio/the_app_cannot_tag_its_own_object
=== RUN   TestDeliveredContractMinio/the_app_cannot_tag_its_own_object/not_by_PutObjectTagging
=== RUN   TestDeliveredContractMinio/the_app_cannot_tag_its_own_object/and_not_by_x-amz-tagging_on_upload
=== RUN   TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route
=== RUN   TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/not_by_CreateMultipartUpload
=== RUN   TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/not_by_CopyObject_with_a_REPLACE_tagging_directive
=== RUN   TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/but_multipart_itself_is_allowed
=== RUN   TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/and_copy_itself_is_allowed
=== RUN   TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/a_POST-policy_forged_tag_with_a_matching_version_is_still_not_a_verdict
=== RUN   TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/and_an_ordinary_tagged-with-something-else_upload_is_allowed
=== RUN   TestDeliveredContractMinio/delete_removes_it
=== RUN   TestDeliveredContractMinio/cross-bucket_denial
--- PASS: TestDeliveredContractMinio (0.02s)
    --- PASS: TestDeliveredContractMinio/put (0.00s)
    --- PASS: TestDeliveredContractMinio/get_round-trips_the_body (0.00s)
    --- PASS: TestDeliveredContractMinio/list_shows_the_key (0.00s)
    --- PASS: TestDeliveredContractMinio/head_and_list_agree_on_the_version (0.00s)
    --- PASS: TestDeliveredContractMinio/the_app_cannot_tag_its_own_object (0.00s)
        --- PASS: TestDeliveredContractMinio/the_app_cannot_tag_its_own_object/not_by_PutObjectTagging (0.00s)
        --- PASS: TestDeliveredContractMinio/the_app_cannot_tag_its_own_object/and_not_by_x-amz-tagging_on_upload (0.00s)
    --- PASS: TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route (0.01s)
        --- PASS: TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/not_by_CreateMultipartUpload (0.00s)
        --- PASS: TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/not_by_CopyObject_with_a_REPLACE_tagging_directive (0.00s)
        --- PASS: TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/but_multipart_itself_is_allowed (0.00s)
        --- PASS: TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/and_copy_itself_is_allowed (0.00s)
        --- PASS: TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/a_POST-policy_forged_tag_with_a_matching_version_is_still_not_a_verdict (0.00s)
        --- PASS: TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/and_an_ordinary_tagged-with-something-else_upload_is_allowed (0.00s)
    --- PASS: TestDeliveredContractMinio/delete_removes_it (0.00s)
    --- PASS: TestDeliveredContractMinio/cross-bucket_denial (0.00s)
PASS
ok  	github.com/carlosframework/platform/internal/objstore	0.025s
=== RUN   TestT4StorageProbeMinio
2026/10/20 14:43:12 moves: T4: STORE: list: operation error S3: ListObjectsV2, https response error StatusCode: 403, RequestID: 18E043FA10A75E25, HostID: 7c420053e0fbcd7f41653fdd92ffa2802c903d05303b1aa15adc2e8bb65d183f, api error SignatureDoesNotMatch: The request signature we calculated does not match the signature you provided. Check your key and signing method.
--- PASS: TestT4StorageProbeMinio (0.01s)
PASS
ok  	github.com/carlosframework/platform/internal/host	0.022s
minio contract: PASS
diff --git a/docs/site/changelog-links.json b/docs/site/changelog-links.json
index 6aad62c18..3082e8c6a 100644
--- a/docs/site/changelog-links.json
+++ b/docs/site/changelog-links.json
@@ -1,5 +1,46 @@
{
"//": "For the changelog: each release-note bullet's bold lead, mapped to the branches behind it. Kept by hand, one release at a time, as step 10 of the release recipe in the README. go run ./cmd/changelog fails on a lead no bullet has, or a branch that did not land in that release.",
+ "v0.28.4": {
+ "Console invites now arrive.": [
+ "design-console-invite-delivery"
+ ],
+ "An account can have 20 invites waiting at most, and send 20 an hour.": [
+ "design-console-invite-delivery"
+ ],
+ "Console email can switch itself on.": [
+ "design-console-invite-delivery"
+ ],
+ "Sending also needs a grant that is off by default.": [
+ "design-console-invite-delivery"
+ ],
+ "With `CARLOS_HOST_CLAIM` on, the console sends no email.": [
+ "design-console-invite-delivery"
+ ],
+ "`carlos system install-channel --policy` now also takes `--identity`.": [
+ "claim-untagged-pointer"
+ ]
+ },
+ "v0.28.3": {
+ "`carlos system install-channel --policy` prepares a box that is already running for host claims.": [
+ "claim-prev-rehearsal"
+ ]
+ },
+ "v0.28.2": {
+ "Three new `carlos system claims` commands prepare a box for host claims.": [
+ "claim-step6-artifacts"
+ ]
+ },
+ "v0.28.1": {
+ "A box can publish its identity record by hand.": [
+ "box-publish-record"
+ ],
+ "A box that has not reported for a day drops out of status.": [
+ "region-ha-2b-build"
+ ],
+ "Each box gets an idle join unit.": [
+ "region-ha-2b-build"
+ ]
+ },
"v0.28.0": {
"`carlos run` runs one of your app's commands against one instance.": [
"carlos-run"
diff --git a/docs/site/changelog.json b/docs/site/changelog.json
index d2b0bf5bd..a15fa98c9 100644
--- a/docs/site/changelog.json
+++ b/docs/site/changelog.json
@@ -2,6 +2,387 @@
"//": "Generated by go run ./cmd/changelog from git, the published release notes and Amadan. Do not edit; regenerate.",
"repo": "https://amadan.net/carlos/platform",
"releases": [
+ {
+ "tag": "v0.28.4",
+ "date": "2026-10-18",
+ "sha": "f3bf1214ab92a47ecb626400e7bd1b35cd7a112c",
+ "published": true,
+ "notes_url": "https://github.com/carlosframework/releases/releases/tag/v0.28.4",
+ "notes": {
+ "form": "bullets",
+ "sections": [
+ {
+ "title": "",
+ "bullets": [
+ {
+ "md": "**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.",
+ "branches": [
+ "design-console-invite-delivery"
+ ]
+ },
+ {
+ "md": "**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.",
+ "branches": [
+ "design-console-invite-delivery"
+ ]
+ },
+ {
+ "md": "**Nothing changes in the CLI.**"
+ }
+ ]
+ },
+ {
+ "title": "For operators",
+ "bullets": [
+ {
+ "md": "**Roll the boxes first, then the console.**"
+ },
+ {
+ "md": "**Coming from v0.28.2, read the [v0.28.3 operator notes](https://github.com/carlosframework/releases/releases/tag/v0.28.3) first.** They all still apply."
+ },
+ {
+ "md": "**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.",
+ "branches": [
+ "design-console-invite-delivery"
+ ]
+ },
+ {
+ "md": "**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.",
+ "branches": [
+ "design-console-invite-delivery"
+ ]
+ },
+ {
+ "md": "**With `CARLOS_HOST_CLAIM` on, the console sends no email.** Invites then go by Keymail, or the owner passes the link on.",
+ "branches": [
+ "design-console-invite-delivery"
+ ]
+ },
+ {
+ "md": "**`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.",
+ "branches": [
+ "claim-untagged-pointer"
+ ],
+ "docs": [
+ "/docs/cli#carlos-system"
+ ]
+ },
+ {
+ "md": "**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`.",
+ "docs": [
+ "/docs/cli#carlos-channels-digests"
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "changes": [
+ {
+ "sha": "f3bf1214ab92a47ecb626400e7bd1b35cd7a112c",
+ "date": "2026-10-18",
+ "subject": "claim-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",
+ "branch": "claim-untagged-pointer",
+ "branch_url": "https://amadan.net/carlos/platform/-/branch/claim-untagged-pointer",
+ "commits": 6,
+ "docs": [
+ "/docs/cli#boxes-a-region-s-group-launches"
+ ],
+ "credit": [
+ {
+ "person": "Paul Campbell",
+ "agents": [
+ "claude"
+ ]
+ }
+ ]
+ },
+ {
+ "sha": "91a651b3c5a0837445c1a5bc738aafe340928510",
+ "date": "2026-10-18",
+ "subject": "spec: console invite delivery by Keymail federation, then email",
+ "branch": "design-console-invite-delivery",
+ "branch_url": "https://amadan.net/carlos/platform/-/branch/design-console-invite-delivery",
+ "commits": 20,
+ "discussions": [
+ {
+ "id": 216,
+ "title": "Mail: a member can adopt another party's verified SES domain; sending-domain claims never expire",
+ "state": "open"
+ },
+ {
+ "id": 250,
+ "title": "Host floor guard: fix these before anyone runs guard-arm (Opus review of Plans 8/8b)",
+ "state": "open"
+ }
+ ],
+ "credit": [
+ {
+ "person": "Paul Campbell",
+ "agents": [
+ "claude"
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "tag": "v0.28.3",
+ "date": "2026-10-18",
+ "sha": "50f5b26845fb0a23109078654ec5d59b3723d9c4",
+ "published": true,
+ "notes_url": "https://github.com/carlosframework/releases/releases/tag/v0.28.3",
+ "notes": {
+ "form": "bullets",
+ "sections": [
+ {
+ "title": "",
+ "bullets": [
+ {
+ "md": "**Nothing changes for people using the CLI.**"
+ }
+ ]
+ },
+ {
+ "title": "For operators",
+ "bullets": [
+ {
+ "md": "**Roll the boxes first, then the console.**"
+ },
+ {
+ "md": "**Coming from v0.28.1, read the [v0.28.2 operator notes](https://github.com/carlosframework/releases/releases/tag/v0.28.2) first.** They all still apply."
+ },
+ {
+ "md": "**`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.",
+ "branches": [
+ "claim-prev-rehearsal"
+ ],
+ "docs": [
+ "/docs/cli#carlos-system"
+ ]
+ },
+ {
+ "md": "**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`.",
+ "docs": [
+ "/docs/cli#carlos-channels-digests"
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "changes": [
+ {
+ "sha": "50f5b26845fb0a23109078654ec5d59b3723d9c4",
+ "date": "2026-10-18",
+ "subject": "claim-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",
+ "branch": "claim-prev-rehearsal",
+ "branch_url": "https://amadan.net/carlos/platform/-/branch/claim-prev-rehearsal",
+ "commits": 7,
+ "docs": [
+ "/docs/cli#boxes-a-region-s-group-launches"
+ ],
+ "credit": [
+ {
+ "person": "Paul Campbell",
+ "agents": [
+ "claude"
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "tag": "v0.28.2",
+ "date": "2026-10-18",
+ "sha": "7c1beb2da18da1a659e57a4514aee8abe2146d2d",
+ "published": true,
+ "notes_url": "https://github.com/carlosframework/releases/releases/tag/v0.28.2",
+ "notes": {
+ "form": "bullets",
+ "sections": [
+ {
+ "title": "",
+ "bullets": [
+ {
+ "md": "**Nothing changes for people using the CLI.**"
+ }
+ ]
+ },
+ {
+ "title": "For operators",
+ "bullets": [
+ {
+ "md": "**Roll the boxes first, then the console.**"
+ },
+ {
+ "md": "**Coming from v0.28.0, read the [v0.28.1 operator notes](https://github.com/carlosframework/releases/releases/tag/v0.28.1) first.** They all still apply."
+ },
+ {
+ "md": "**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.",
+ "branches": [
+ "claim-step6-artifacts"
+ ],
+ "docs": [
+ "/docs/cli#carlos-system-claims",
+ "/docs/cli#carlos-system"
+ ]
+ },
+ {
+ "md": "**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`.",
+ "docs": [
+ "/docs/cli#carlos-channels-digests"
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "changes": [
+ {
+ "sha": "7c1beb2da18da1a659e57a4514aee8abe2146d2d",
+ "date": "2026-10-18",
+ "subject": "claim-step6-artifacts: claims run sign-policy and publish-identity, --out byte-exact files, claims install-console (dev cohort-1 trial step 6)",
+ "branch": "claim-step6-artifacts",
+ "branch_url": "https://amadan.net/carlos/platform/-/branch/claim-step6-artifacts",
+ "commits": 9,
+ "docs": [
+ "/docs/cli#carlos-system-claims"
+ ],
+ "credit": [
+ {
+ "person": "Paul Campbell",
+ "agents": [
+ "claude"
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "tag": "v0.28.1",
+ "date": "2026-10-18",
+ "sha": "3b69c2bd60edaecb04771d4cd85792e326010cc0",
+ "published": true,
+ "notes_url": "https://github.com/carlosframework/releases/releases/tag/v0.28.1",
+ "notes": {
+ "form": "bullets",
+ "sections": [
+ {
+ "title": "",
+ "bullets": [
+ {
+ "md": "**Nothing changes for people using the CLI.**"
+ }
+ ]
+ },
+ {
+ "title": "For operators",
+ "bullets": [
+ {
+ "md": "**Roll the boxes first, then the console.**"
+ },
+ {
+ "md": "**Coming from v0.27.x, read the [v0.28.0 operator notes](https://github.com/carlosframework/releases/releases/tag/v0.28.0) first.** They all still apply."
+ },
+ {
+ "md": "**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.",
+ "branches": [
+ "box-publish-record"
+ ]
+ },
+ {
+ "md": "**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.",
+ "branches": [
+ "region-ha-2b-build"
+ ],
+ "docs": [
+ "/docs/cli#carlos-status"
+ ]
+ },
+ {
+ "md": "**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.",
+ "branches": [
+ "region-ha-2b-build"
+ ]
+ },
+ {
+ "md": "**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`.",
+ "docs": [
+ "/docs/cli#carlos-channels-digests"
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "changes": [
+ {
+ "sha": "3b69c2bd60edaecb04771d4cd85792e326010cc0",
+ "date": "2026-10-18",
+ "subject": "box-publish-record",
+ "branch": "box-publish-record",
+ "branch_url": "https://amadan.net/carlos/platform/-/branch/box-publish-record",
+ "commits": 1,
+ "docs": [
+ "/docs/cli#a-box-s-identity-record"
+ ],
+ "credit": [
+ {
+ "person": "Paul Campbell",
+ "agents": [
+ "claude"
+ ]
+ }
+ ]
+ },
+ {
+ "sha": "b11189254fcf542ba99a428e63742c0aa81f069e",
+ "date": "2026-10-18",
+ "subject": "region HA 2b: the joining and enrolment plan and its copy record",
+ "branch": "region-ha-2b-build",
+ "branch_url": "https://amadan.net/carlos/platform/-/branch/region-ha-2b-build",
+ "commits": 32,
+ "discussions": [
+ {
+ "id": 275,
+ "title": "carlos binary doubled to 74.5 MB: the EC2 SDK client via internal/awsinv",
+ "state": "closed"
+ }
+ ],
+ "docs": [
+ "/docs/cli#boxes-a-region-s-group-launches"
+ ],
+ "credit": [
+ {
+ "person": "Paul Campbell",
+ "agents": [
+ "claude"
+ ]
+ }
+ ]
+ },
+ {
+ "sha": "04819f9b42ed6767d816bdfecd53490407ee20bb",
+ "date": "2026-10-17",
+ "subject": "changelog-v0.28.0: release step 10 for v0.28.0, plus the darwin/windows vet fix for claimunit_inputs_test.go",
+ "branch": "changelog-v0.28.0",
+ "branch_url": "https://amadan.net/carlos/platform/-/branch/changelog-v0.28.0",
+ "commits": 2,
+ "credit": [
+ {
+ "person": "Paul Campbell",
+ "agents": [
+ "claude"
+ ]
+ }
+ ]
+ }
+ ]
+ },
{
"tag": "v0.28.0",
"date": "2026-10-17",
diff --git a/docs/site/people.json b/docs/site/people.json
index 918907637..ded9bed1e 100644
--- a/docs/site/people.json
+++ b/docs/site/people.json
@@ -3,6 +3,7 @@
"paul@tito.io": "Paul Campbell",
"paul@rslw.com": "Paul Campbell",
"paul@keymail.dev": "Paul Campbell",
+ "paulmartinbernardcampbell@gmail.com": "Paul Campbell",
"bill@tito.io": "Bill Horsman",
"bill@logicalcobwebs.com": "Bill Horsman",
"bill@keymail.dev": "Bill Horsman",