carlos / platform Public

Console chrome and welcome name the deployment from CARLOS_CONSOLE_NAME (Carloku on carloku.com); defaults unchanged. Census overlay proposed on #280.

Squashed from console-brand-name into main.
claude agent, operated by paul@keymail.dev 5f341f337ab71fde37f685aece3d21eef9f9d050 parent 0235046
8 files changed, +81 −5
  • internal/console/authcli.go +1 −0
  • internal/console/server.go +21 −0
  • internal/console/server_test.go +31 −0
  • internal/console/templates/apps.html +1 −1
  • internal/console/templates/home.html +1 −1
  • internal/console/templates/layout.html +2 −2
  • internal/provision/plan14_root_reads_test.go +14 −1
  • internal/provision/testdata/plan14-root-reads-console-brand-name.tsv +10 −0

CI passed — run details

CI log
=== gate ===
.amadan/test-gate.sh
=== launchctx (1 s)
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]
=== vet (18 s)
=== gofmt (1 s)
gofmt -l .: clean
=== rest (168 s)
?   	github.com/carlosframework/platform/cmd/changelog	[no test files]
ok  	github.com/carlosframework/platform/cmd/console	3.555s
ok  	github.com/carlosframework/platform/cmd/moveprobe	11.863s
ok  	github.com/carlosframework/platform/cmd/zddprobe	0.746s
ok  	github.com/carlosframework/platform/internal/activator	61.572s
ok  	github.com/carlosframework/platform/internal/agentsock	0.065s
ok  	github.com/carlosframework/platform/internal/alerting	0.011s
ok  	github.com/carlosframework/platform/internal/analytics	0.057s
ok  	github.com/carlosframework/platform/internal/appconfig	2.827s
ok  	github.com/carlosframework/platform/internal/apperr	0.184s
ok  	github.com/carlosframework/platform/internal/applog	0.258s
ok  	github.com/carlosframework/platform/internal/awsinv	0.010s
ok  	github.com/carlosframework/platform/internal/boxchoice	0.013s
ok  	github.com/carlosframework/platform/internal/boxid	0.741s
?   	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.020s
ok  	github.com/carlosframework/platform/internal/caps	0.043s
ok  	github.com/carlosframework/platform/internal/certwarm	0.005s
ok  	github.com/carlosframework/platform/internal/cgroup	0.800s
ok  	github.com/carlosframework/platform/internal/changelog	0.528s
ok  	github.com/carlosframework/platform/internal/claimactivation	1.190s
ok  	github.com/carlosframework/platform/internal/clamd	0.072s
?   	github.com/carlosframework/platform/internal/cliflag	[no test files]
?   	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	6.467s
ok  	github.com/carlosframework/platform/internal/dbdoor/dbdoortest	0.039s
ok  	github.com/carlosframework/platform/internal/dbverify	0.013s
ok  	github.com/carlosframework/platform/internal/dnsrec	0.015s
ok  	github.com/carlosframework/platform/internal/docsite	0.029s
ok  	github.com/carlosframework/platform/internal/domains	2.688s
ok  	github.com/carlosframework/platform/internal/doorkey	0.022s
ok  	github.com/carlosframework/platform/internal/economics	0.015s
ok  	github.com/carlosframework/platform/internal/edge	45.639s
?   	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.146s
ok  	github.com/carlosframework/platform/internal/gate	1.662s
ok  	github.com/carlosframework/platform/internal/genselect	0.019s
ok  	github.com/carlosframework/platform/internal/geo	0.027s
ok  	github.com/carlosframework/platform/internal/geoip	0.064s
ok  	github.com/carlosframework/platform/internal/historyreadback	0.197s
ok  	github.com/carlosframework/platform/internal/host	138.226s
ok  	github.com/carlosframework/platform/internal/hostactors	5.745s
ok  	github.com/carlosframework/platform/internal/hostactors/awsmembership	0.008s
ok  	github.com/carlosframework/platform/internal/hostbox	2.982s
ok  	github.com/carlosframework/platform/internal/hostclaim	0.812s
ok  	github.com/carlosframework/platform/internal/hostenv	0.012s
ok  	github.com/carlosframework/platform/internal/hostevidence	0.007s
ok  	github.com/carlosframework/platform/internal/hostexec	5.271s
ok  	github.com/carlosframework/platform/internal/hostfence	0.062s
ok  	github.com/carlosframework/platform/internal/hostfiles	10.348s
ok  	github.com/carlosframework/platform/internal/hostfloor	0.022s
ok  	github.com/carlosframework/platform/internal/hostguard	1.113s
ok  	github.com/carlosframework/platform/internal/hostops	1.976s
?   	github.com/carlosframework/platform/internal/hostops/fencerelease	[no test files]
ok  	github.com/carlosframework/platform/internal/hostops/internal/fencerelease	0.011s
ok  	github.com/carlosframework/platform/internal/hostquarantine	0.002s
ok  	github.com/carlosframework/platform/internal/hostrelocate	0.610s
ok  	github.com/carlosframework/platform/internal/hostresolve	0.170s
ok  	github.com/carlosframework/platform/internal/hostwrite	0.012s
ok  	github.com/carlosframework/platform/internal/infraview	0.011s
ok  	github.com/carlosframework/platform/internal/instancectl	5.227s
ok  	github.com/carlosframework/platform/internal/instanceexec	2.839s
ok  	github.com/carlosframework/platform/internal/instancefs	0.011s
ok  	github.com/carlosframework/platform/internal/instancekey	0.011s
ok  	github.com/carlosframework/platform/internal/instanceupdates	0.012s
ok  	github.com/carlosframework/platform/internal/layout	1.704s
ok  	github.com/carlosframework/platform/internal/lbhealth	0.016s
ok  	github.com/carlosframework/platform/internal/lease	10.251s
ok  	github.com/carlosframework/platform/internal/lease/leasetest	0.573s
ok  	github.com/carlosframework/platform/internal/ledger	0.023s
ok  	github.com/carlosframework/platform/internal/mail	0.230s
ok  	github.com/carlosframework/platform/internal/maintenance	0.113s
ok  	github.com/carlosframework/platform/internal/maintenanceexec	5.583s
ok  	github.com/carlosframework/platform/internal/maintenanceguard	0.153s
ok  	github.com/carlosframework/platform/internal/metrics	0.005s
ok  	github.com/carlosframework/platform/internal/moves	22.692s
ok  	github.com/carlosframework/platform/internal/moves/archive	1.071s
ok  	github.com/carlosframework/platform/internal/objstore	0.322s
ok  	github.com/carlosframework/platform/internal/ops	0.242s
ok  	github.com/carlosframework/platform/internal/park	0.277s
ok  	github.com/carlosframework/platform/internal/plans	0.014s
ok  	github.com/carlosframework/platform/internal/privatefile	0.006s
ok  	github.com/carlosframework/platform/internal/provision	22.836s
ok  	github.com/carlosframework/platform/internal/publicrelease	0.016s
?   	github.com/carlosframework/platform/internal/regionname	[no test files]
ok  	github.com/carlosframework/platform/internal/registry	5.634s
ok  	github.com/carlosframework/platform/internal/relay	7.228s
ok  	github.com/carlosframework/platform/internal/release	26.302s
ok  	github.com/carlosframework/platform/internal/rollout	3.796s
ok  	github.com/carlosframework/platform/internal/rolloutwords	0.005s
ok  	github.com/carlosframework/platform/internal/rootaws	0.009s
ok  	github.com/carlosframework/platform/internal/rootparticipation	0.064s
ok  	github.com/carlosframework/platform/internal/rootstate	0.030s
ok  	github.com/carlosframework/platform/internal/runs	0.594s
ok  	github.com/carlosframework/platform/internal/s3compat	0.007s
ok  	github.com/carlosframework/platform/internal/safefile	0.005s
ok  	github.com/carlosframework/platform/internal/schedule	2.779s
ok  	github.com/carlosframework/platform/internal/seeds	0.011s
ok  	github.com/carlosframework/platform/internal/sim/engines	2.599s
ok  	github.com/carlosframework/platform/internal/sim/hostlife	11.771s
ok  	github.com/carlosframework/platform/internal/sim/litestreamfacts	4.145s
ok  	github.com/carlosframework/platform/internal/status	0.098s
ok  	github.com/carlosframework/platform/internal/steering	0.009s
ok  	github.com/carlosframework/platform/internal/stopevidence	0.299s
ok  	github.com/carlosframework/platform/internal/svcrole	0.003s
ok  	github.com/carlosframework/platform/internal/telemetry	0.005s
ok  	github.com/carlosframework/platform/internal/termfence	0.004s
ok  	github.com/carlosframework/platform/internal/tunnelclient	0.006s
ok  	github.com/carlosframework/platform/internal/unixdial	0.005s
ok  	github.com/carlosframework/platform/internal/updatewords	0.011s
ok  	github.com/carlosframework/platform/internal/usage	0.005s
ok  	github.com/carlosframework/platform/internal/version	0.002s
ok  	github.com/carlosframework/platform/internal/vet	1.754s
=== internal_console@0 (82 s)
ok  	github.com/carlosframework/platform/internal/console	79.954s
=== internal_console@1 (36 s)
ok  	github.com/carlosframework/platform/internal/console	33.810s
=== internal_console@2 (42 s)
ok  	github.com/carlosframework/platform/internal/console	40.373s
=== internal_console@3 (37 s)
ok  	github.com/carlosframework/platform/internal/console	35.372s
=== internal_console@4 (39 s)
ok  	github.com/carlosframework/platform/internal/console	37.300s
=== internal_console@5 (40 s)
ok  	github.com/carlosframework/platform/internal/console	38.448s
=== internal_console@6 (43 s)
ok  	github.com/carlosframework/platform/internal/console	40.728s
=== internal_console@7 (43 s)
ok  	github.com/carlosframework/platform/internal/console	41.180s
=== root@0 (34 s)
ok  	github.com/carlosframework/platform	32.396s
=== root@1 (45 s)
ok  	github.com/carlosframework/platform	42.860s
=== root@2 (42 s)
ok  	github.com/carlosframework/platform	40.105s
=== 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: 50069666 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: downloading https://github.com/minio/minio/releases/download/RELEASE.2025-09-07T16-13-09Z/minio.linux-arm64.RELEASE.2025-09-07T16-13-09Z
  minio: downloaded, digest verified
  mc: downloading https://github.com/minio/mc/releases/download/RELEASE.2025-08-13T08-35-41Z/mc.linux-arm64.RELEASE.2025-08-13T08-35-41Z
  mc: downloaded, 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.024s
=== RUN   TestT4StorageProbeMinio
2026/10/22 10:10:35 moves: T4: STORE: list: operation error S3: ListObjectsV2, https response error StatusCode: 403, RequestID: 18E0D2429CEB0490, 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/internal/console/authcli.go b/internal/console/authcli.go
index b18c7763f..90c76a5b6 100644
--- a/internal/console/authcli.go
+++ b/internal/console/authcli.go
@@ -1386,6 +1386,7 @@ type cliPage struct {
}
func (s *Server) renderCLI(w http.ResponseWriter, status int, name string, p cliPage) {
+ s.chrome(&p.page)
w.Header().Set("Content-Type", "text/html; charset=utf-8")
w.WriteHeader(status)
if err := templates.ExecuteTemplate(w, name, p); err != nil {
diff --git a/internal/console/server.go b/internal/console/server.go
index 728c16991..e8f8d7e5f 100644
--- a/internal/console/server.go
+++ b/internal/console/server.go
@@ -1190,6 +1190,22 @@ func (s *Server) consoleName() string {
return "the CARLOS platform"
}
+// brandName is the console's own name in its page chrome (the header, the
+// tab title, the front page): CARLOS_CONSOLE_NAME when the deployment sets
+// one, so carloku.com reads "Carloku" throughout, else "CARLOS console".
+func (s *Server) brandName() string {
+ if n := strings.TrimSpace(s.consoleNameCfg); n != "" {
+ return n
+ }
+ return "CARLOS console"
+}
+
+// chrome fills the deployment's names on any page before it renders.
+func (s *Server) chrome(p *page) {
+ p.Brand = s.brandName()
+ p.ConsoleName = s.consoleName()
+}
+
// dnsTargets is what every custom-domain guidance string in this console is
// built from (view.go's domainGuidance): the deployment's edge addresses and
// its steering hostname, read from ONE place so the app page, the Settings
@@ -1799,6 +1815,10 @@ type page struct {
NoMail bool
CheckSent, CodeError string
SigninCopy signinView
+ // Brand and ConsoleName are the deployment's names (render fills them):
+ // Brand in the page chrome, ConsoleName in prose ("Welcome to ...").
+ Brand string
+ ConsoleName string
// The emailed link's confirm page: the token and the login-CSRF nonce
// its form POSTs; StepUpLink when the link re-confirms a session
// rather than signing in.
@@ -2132,6 +2152,7 @@ func (s *Server) render(w http.ResponseWriter, status int, name string, p page)
p.BrowserRestartCopy = approvedBrowserRestartCopy
p.MismatchCopy = approvedMismatchCopy
p.SigninCopy = approvedSigninView
+ s.chrome(&p)
w.Header().Set("Content-Type", "text/html; charset=utf-8")
w.WriteHeader(status)
if err := templates.ExecuteTemplate(w, name, p); err != nil {
diff --git a/internal/console/server_test.go b/internal/console/server_test.go
index b5be130b6..1d43c7dc5 100644
--- a/internal/console/server_test.go
+++ b/internal/console/server_test.go
@@ -2634,3 +2634,34 @@ func TestNormalizeHost(t *testing.T) {
}
}
}
+
+// A deployment that sets CARLOS_CONSOLE_NAME reads as itself everywhere a
+// person looks: the front page, the tab title, the header and the new
+// account's welcome. Unset, the CARLOS names stay (TestEmptyStateWelcomesNewUser).
+func TestConsoleNameBrandsThePages(t *testing.T) {
+ fx := newConsoleFixture(t)
+ fx.srv.consoleNameCfg = "Carloku"
+ _, _, front := get(t, newBrowser(t), fx.ts.URL+"/")
+ for _, want := range []string{"🤖 Carloku", "· Carloku</title>", `<a href="/">Carloku</a>`} {
+ if !strings.Contains(front, want) {
+ t.Fatalf("front page missing %q", want)
+ }
+ }
+ if strings.Contains(front, "CARLOS console") {
+ t.Fatal("front page still says CARLOS console")
+ }
+ fx.setUser("bob@keymail.dev")
+ c := newBrowser(t)
+ signUp(t, fx, c, "code-b")
+ _, home, _ := get(t, c, fx.ts.URL+"/")
+ _, _, body := get(t, c, fx.ts.URL+home)
+ // Inside an account the header is the account switcher, not the brand.
+ for _, want := range []string{"Welcome to Carloku", "· Carloku</title>"} {
+ if !strings.Contains(body, want) {
+ t.Fatalf("account home missing %q", want)
+ }
+ }
+ if strings.Contains(body, "CARLOS platform") || strings.Contains(body, "CARLOS console") {
+ t.Fatal("account home still names CARLOS")
+ }
+}
diff --git a/internal/console/templates/apps.html b/internal/console/templates/apps.html
index 0b035b1e2..adc59fe07 100644
--- a/internal/console/templates/apps.html
+++ b/internal/console/templates/apps.html
@@ -18,7 +18,7 @@
</table>
</div>
{{else}}
-<h1>Welcome to the CARLOS platform</h1>
+<h1>Welcome to {{.ConsoleName}}</h1>
<p>The account <strong>{{.Account.Name}}</strong> is ready. No apps live here yet — claim a name below and it's yours.</p>
{{end}}
{{if .TrashN}}<p class="small"><a href="{{.Nav}}/trash">Trash ({{.TrashN}})</a>: deleted apps you can still
diff --git a/internal/console/templates/home.html b/internal/console/templates/home.html
index 7099f68e9..cd9944420 100644
--- a/internal/console/templates/home.html
+++ b/internal/console/templates/home.html
@@ -1,6 +1,6 @@
{{define "home"}}{{template "top" .}}
<div class="pagehead">
- <p class="eyebrow">🤖 CARLOS console</p>
+ <p class="eyebrow">🤖 {{.Brand}}</p>
<h1>Ship it. Promote it. Sleep<span style="color: var(--accent)">.</span></h1>
<p class="lede">Your apps, their live routes, and their release channels —
signed releases in, immutable bytes out.</p>
diff --git a/internal/console/templates/layout.html b/internal/console/templates/layout.html
index 172755dd3..3f4e63949 100644
--- a/internal/console/templates/layout.html
+++ b/internal/console/templates/layout.html
@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
-<title>{{.Title}} · CARLOS console</title>
+<title>{{.Title}} · {{.Brand}}</title>
<style>
:root {
--bg: #ffffff; --ink: #201d29; --muted: #6f6480;
@@ -574,7 +574,7 @@
</div>
</details>
{{else}}
- <div class="brand"><a href="/">CARLOS console</a></div>
+ <div class="brand"><a href="/">{{.Brand}}</a></div>
{{end}}
{{if .Address}}<nav>
{{if .Account}}
diff --git a/internal/provision/plan14_root_reads_test.go b/internal/provision/plan14_root_reads_test.go
index 770724ec2..715d31d63 100644
--- a/internal/provision/plan14_root_reads_test.go
+++ b/internal/provision/plan14_root_reads_test.go
@@ -1299,7 +1299,7 @@ func TestPlan14RootReadCensus(t *testing.T) {
seal = "b25dfda5a68d2183af759b42398f79bb471749d46e68d267545647d1a2e6046b"
// Census overlay plans-2-box-limits (boxes read account limits behind the
// console's plans marker; the activator's idle hook), loaded last, after
- // email-signin. PROPOSED-plans-2-box-limits, asked of the census owner on
+ // plans-2-box-limits. PROPOSED-plans-2-box-limits, asked of the census owner on
// #280. The new agent units read routes and two bucket objects and only
// narrow idle windows. Frozen declarations are added, so the seal moves;
// email-signin's is checked first.
@@ -1310,6 +1310,19 @@ func TestPlan14RootReadCensus(t *testing.T) {
t.Fatal(err)
}
seal = "d044224434b0b375599a076e573c7c4164e3777ae6295abf95d9d9b9ed69e482"
+ if errs := checkRootReadLegacy(inv, seal); len(errs) != 0 {
+ t.Fatal(errs)
+ }
+ // Census overlay console-brand-name (the console's chrome and welcome name
+ // the deployment from CARLOS_CONSOLE_NAME), loaded last, after
+ // plans-2-box-limits. Proposed; ruling asked of the census owner on #280. Three
+ // templates change text only; envelopes re-pinned; no read is added. The
+ // seal moves because the three templates' legacy declarations are
+ // re-pinned.
+ if err = loadRootReadInventory(filepath.Join(root, "internal/provision/testdata/plan14-root-reads-console-brand-name.tsv"), &inv, true); err != nil {
+ t.Fatal(err)
+ }
+ seal = "78e18e222a8178bbe16b638c5e3811b8f64c4c2664ffd6649eb4273e72fae24e"
errs := append(compareRootReads(got, inv), checkRootReadLegacy(inv, seal)...)
errs = append(errs, checkRootReadDeclarations(got, inv)...)
if len(errs) > 0 {
diff --git a/internal/provision/testdata/plan14-root-reads-console-brand-name.tsv b/internal/provision/testdata/plan14-root-reads-console-brand-name.tsv
new file mode 100644
index 000000000..f857c81fc
--- /dev/null
+++ b/internal/provision/testdata/plan14-root-reads-console-brand-name.tsv
@@ -0,0 +1,10 @@
+# Census overlay console-brand-name (the console names the deployment in its chrome and welcome from CARLOS_CONSOLE_NAME: "Carloku" on carloku.com, the CARLOS names otherwise), loaded last, after email-signin. Proposed; rows carry rev3=PROPOSED-console-brand-name and the ruling is asked of the census owner on #280.
+# Three embedded templates change their text only (apps.html, home.html, layout.html); no read, file or record write is added. They run in the console (cmd/console serve under console.service, user carlos-console). The internal/console and internal/console/templates envelopes are re-pinned (server.go and authcli.go gain brandName/chrome, render paths fill two page fields).
+@legacy d156d262b04550e8dcf774d6291dfd1b4f08cf5d2bb13ae615fb1f142bfa1b86 internal/console/templates/apps.html external legacy accepted-legacy accepted-legacy;rev3=J4;basis=root-input;rev3=PROPOSED-console-brand-name;identity=the console (cmd/console serve under console.service, user carlos-console);basis=the empty account's welcome names the deployment ({{.ConsoleName}}, CARLOS_CONSOLE_NAME) instead of the CARLOS platform; no new input. file:external@0 c048758eb446bbd78fc65e08103348d5f3e160b4e983ad180bf55039b75ec3ee
+@legacy 9a8bb2eb92f4e88e3b65dc6fcfb7fb658403e95da7e11007e8edfce03d415cd0 internal/console/templates/home.html external legacy accepted-legacy accepted-legacy;rev3=J4;basis=root-input;rev3=PROPOSED-email-signin;identity=the console (cmd/console serve under console.service, user carlos-console);basis=the front page's one address form posting to /auth/continue, with the approved copy, a banner and a no-mail note; whole embedded template remains frozen as legacy UI input;rev3=PROPOSED-console-brand-name;identity=the console (cmd/console serve under console.service, user carlos-console);basis=the front page eyebrow names the deployment ({{.Brand}}, CARLOS_CONSOLE_NAME); no new input. file:external@0 86cbfc29e2098cbe5c0224e8256f96bfe640c62db467c4c55e035f2c821c745b
+@legacy 35be103f7a6c54220be3d3da5c8fd9078a364c36b93ca3850c8df5190ba9d094 internal/console/templates/layout.html external legacy accepted-legacy accepted-legacy;rev3=PROPOSED-console-switcher-filter;basis=Account switcher adds a client-side filter box and a scrolling list; whole embedded template remains frozen as legacy UI input.;rev3=PROPOSED-email-signin;identity=the console (cmd/console serve under console.service, user carlos-console);basis=CSS only: email inputs styled as text inputs and sign-in form labels; whole embedded template remains frozen as legacy UI input;rev3=PROPOSED-console-brand-name;identity=the console (cmd/console serve under console.service, user carlos-console);basis=the tab title and header brand name the deployment ({{.Brand}}, CARLOS_CONSOLE_NAME); no new input. file:external@0 c9a651201ef7b3e7af39bc90793b8e1c10cd4450f51ceb634afaff6a1cd74020
+internal/console/templates/apps.html external legacy accepted-legacy accepted-legacy;rev3=J4;basis=root-input;rev3=PROPOSED-console-brand-name;identity=the console (cmd/console serve under console.service, user carlos-console);basis=the empty account's welcome names the deployment ({{.ConsoleName}}, CARLOS_CONSOLE_NAME) instead of the CARLOS platform; no new input. file:external@0 c048758eb446bbd78fc65e08103348d5f3e160b4e983ad180bf55039b75ec3ee
+internal/console/templates/home.html external legacy accepted-legacy accepted-legacy;rev3=J4;basis=root-input;rev3=PROPOSED-email-signin;identity=the console (cmd/console serve under console.service, user carlos-console);basis=the front page's one address form posting to /auth/continue, with the approved copy, a banner and a no-mail note; whole embedded template remains frozen as legacy UI input;rev3=PROPOSED-console-brand-name;identity=the console (cmd/console serve under console.service, user carlos-console);basis=the front page eyebrow names the deployment ({{.Brand}}, CARLOS_CONSOLE_NAME); no new input. file:external@0 86cbfc29e2098cbe5c0224e8256f96bfe640c62db467c4c55e035f2c821c745b
+internal/console/templates/layout.html external legacy accepted-legacy accepted-legacy;rev3=PROPOSED-console-switcher-filter;basis=Account switcher adds a client-side filter box and a scrolling list; whole embedded template remains frozen as legacy UI input.;rev3=PROPOSED-email-signin;identity=the console (cmd/console serve under console.service, user carlos-console);basis=CSS only: email inputs styled as text inputs and sign-in form labels; whole embedded template remains frozen as legacy UI input;rev3=PROPOSED-console-brand-name;identity=the console (cmd/console serve under console.service, user carlos-console);basis=the tab title and header brand name the deployment ({{.Brand}}, CARLOS_CONSOLE_NAME); no new input. file:external@0 c9a651201ef7b3e7af39bc90793b8e1c10cd4450f51ceb634afaff6a1cd74020
+@coverage internal/console 8ca2a88f9fa21649085cc31d49ad7f319b7c8cac811cf38942533fdf7805a7db
+@coverage internal/console/templates 8fe5a2476674ae5ab64a9e6dad7c8e3b5ce301fa81a39da3a5d7c0583a25c585