{{define "app_settings"}}{{template "top" .}} {{if .Flash}}
{{end}} {{if .FlashErr}}{{end}} {{template "appnav" .}}| App | Account |
|---|---|
{{.Detail.App}} | {{.Account.Name}} {{.Account.Sqid}} |
Release pipeline — the channels a release moves through, and what each one takes to promote onto.
{{if .IsOwner}} {{if .Settings.ControlPlane}}This app is marked as the control plane — it is this deployment’s own platform. Renaming, moving and deleting it are refused while the flag is set, and a service credential cannot promote it.
{{else if .Settings.CanRename}}This app has never shipped, so its name is still only a record here — after the first ship, the name is wired into addresses and bucket keys and stays.
{{else}}Renaming: {{.Settings.RenameBlocked}}
{{end}} {{end}} {{end}} {{if eq .SettingsSection "domains"}}| Domain | Type | Status | Certificate |
|---|---|---|---|
{{$d.Domain}} |
{{$d.Type}} | {{with $d.Status}}{{.}}{{else}}—{{end}} | {{if $d.TLS}}{{$d.TLS}}{{else}}—{{end}} |
| {{.}} | |||
No domains yet — the first shipped route brings one.
{{end}} {{if .IsOwner}}This app already answers at its platform domain; attaching adds addresses, it never removes one.
{{end}}Point the domain's DNS at this deployment — once it is attached, the row above says exactly what to create. The platform obtains the certificate itself and renews it, so nothing has to visit the domain first.
For an app with instances, attaching *.example.com
makes each instance also answer at <label>.example.com, where
the label is the first part of its own hostname. example.com must
already be attached to an app in this account, and a wildcard DNS record
(*) must point here.
One shared password in front of a hostname — for a static site or a prototype that should not be world-readable. Visitors see a plain page asking for it and stay signed in for a week. It is set per instance.
{{if .Settings.GatesUnavailable}}{{.Settings.GatesUnavailable}}
{{else if .Settings.Gates}}| Host | State | |
|---|---|---|
{{$g.Host}} |
{{if $g.Gated}}Password set{{else}}Open{{end}} | {{if $g.Gated}} {{end}} |
No instances yet. A password gate is set per instance.
{{end}} {{end}} {{if eq .SettingsSection "general"}} {{if and .Settings .Settings.MismatchTarget}}This app's hosts read releases from account
{{.Settings.MismatchTarget}}, but the console's record says
{{.Account.Name}} — so promotes from here reach nothing.
Move the record to where the platform already deploys from:
{{else}}{{if not .IsOwner}}Moving the record is the account owner's
to do{{else if not .Settings.TargetKnown}}The routes name an account this
console does not know{{else}}You are not a member of that account{{end}} —
the operator path is console migrate-app --app {{.Detail.App}} --to
{{.Settings.MismatchTarget}} on the console's box.
{{.MismatchCopy.NoInstances}} Instances
{{else}}{{if .IsOwner}}This app deploys from {{.Account.Name}}. Moving an app to a
different account moves its bucket objects and re-stamps its routes —
carlos accounts migrate, an operator act; once run, this page
offers the final console-record step.
A named environment is a config bundle that overlays this app's default one, per key. An instance bound to it reads the app's config with these values on top — which is how two instances of one app serve different origins, and how one of them gets a bucket of its own.
{{if .Settings.Envs}} {{range .Settings.Envs}}{{.Name}}| Sets | Read by | Object store |
|---|---|---|
{{if .Vars}}{{range $i, $v := .Vars}}{{if $i}}, {{end}}{{$v.Name}}{{if $v.Secret}} sealed{{end}}{{end}}{{else}}—{{end}} |
{{if .Hosts}}{{range $i, $h := .Hosts}}{{if $i}}, {{end}}{{$h}}{{end}}{{else}}no instances{{end}} | {{if .HasStore}}{{if .StoreBucket}}{{.StoreBucket}}{{else}}declared{{end}}{{else}}—{{end}} |
This environment has an object store but no instance reads it. The bucket still exists and still costs — destroying a store is always deliberate, so nothing has removed it. Its card is under Storage.
{{end}} {{end}}Values are not shown here. Read them with carlos env list
--app {{.Detail.App}} --environment <name>; secrets list by name only,
wherever you ask.
No named environments. Every instance of this app reads its
default config bundle. Add one with carlos env set --app {{.Detail.App}}
--environment <name> KEY=value, then bind an instance to it with
carlos instances set-environment --app {{.Detail.App}} --host <h>
--environment <name>.
| Env prefix | Backend | Bucket | Access key | Key age |
|---|---|---|---|---|
{{if .EnvPrefix}}{{.EnvPrefix}}_*{{else}}—{{end}} |
{{if .Backend}}{{.Backend}}{{else}}—{{end}} | {{if .Bucket}}{{.Bucket}}{{else}}—{{end}} |
{{if .KeyID}}{{.KeyID}}{{else}}—{{end}} |
{{if .KeyAge}}{{.KeyAge}}{{else}}—{{end}} |
Key age is the last credential change — a rotation and a repaired grant both move it, so it is not when the store was created.
{{end}} {{if and (not .Granted) (not .Provisioned)}}Declared and waiting:
an operator of this deployment creates the bucket and delivers the credentials.
Until then the {{if .EnvPrefix}}{{.EnvPrefix}}_*{{else}}store{{end}}
variables are not in this app's config.
A grant is half-done: the bucket was claimed but no credentials are recorded yet. Running the grant again repairs it — an operator of this deployment does that.
{{end}} {{if .PendingFinish}}A rotation is half-finished — two keys open this bucket until you retire the old one:
carlos store rotate --finish --app {{$.Detail.App}}{{end}}
{{if $.IsOwner}}
Destroying empties and deletes
{{if .Bucket}}{{.Bucket}}{{else}}the store{{end}}, deletes the
credentials that opened it, and removes the delivered variables from this app's
config. There is no trash for a store: the objects in it are gone, and nothing
here brings them back.
Confirms with your passkey.
{{else}}This console has no storage backend configured
(CARLOS_STORE_BACKEND), so it cannot delete this bucket or its
credentials — an operator of this deployment has to tear it down.
No object store. Ask for one with carlos store create --app
{{$.Detail.App}}; an operator of this deployment then creates the bucket
and delivers its credentials into this app's config.
Its own bucket and its own credential, delivered into the
{{.Environment}} config bundle — so only the instances bound to
that environment can reach it.
| Env prefix | Backend | Bucket | Access key | Key age |
|---|---|---|---|---|
{{if .EnvPrefix}}{{.EnvPrefix}}_*{{else}}—{{end}} |
{{if .Backend}}{{.Backend}}{{else}}—{{end}} | {{if .Bucket}}{{.Bucket}}{{else}}—{{end}} |
{{if .KeyID}}{{.KeyID}}{{else}}—{{end}} |
{{if .KeyAge}}{{.KeyAge}}{{else}}—{{end}} |
Declared and waiting: an operator of this deployment creates the bucket and delivers the credentials.
{{end}} {{if .PendingFinish}}A rotation is half-finished — two keys open this bucket until you retire the old one:
carlos store rotate --finish --app {{$.Detail.App}} --environment {{.Environment}}{{end}}
{{if $.IsOwner}}
Destroying empties and deletes
{{if .Bucket}}{{.Bucket}}{{else}}the store{{end}}, deletes the
credentials that opened it, and removes the delivered variables from the
{{.Environment}} bundle. The app's own store is not touched. There is
no trash for a store: the objects in it are gone.
Confirms with your passkey.
{{else}}This console has no storage backend configured
(CARLOS_STORE_BACKEND), so it cannot delete this bucket or its
credentials — an operator of this deployment has to tear it down.
This app’s Errors log level could not be read just now, so it is not shown and cannot be changed from here. Reload before concluding anything.
{{else if .IsOwner}} {{else}}Log lines at {{.ErrLevelSetting.LogLevel}} and above are counted as
errors for this app, from the {{.ErrLevelSetting.LogLevelFrom}}. Only the account owner can
change it.
The Errors tab always lets you widen one look to warn without changing this.
This app’s analytics setting could not be read just now. Reload before concluding anything.
{{else if .IsOwner}} {{else}}Analytics counting is {{.AnalyticsSetting.Count}} for this app, from
the {{.AnalyticsSetting.CountFrom}}. Only the account owner can change it.
When on, the edge counts HTML page views and daily visitors as it serves them: no JavaScript, no cookie, no stored IP. A visitor is a salted hash that changes every day and cannot be joined across days. Whether that needs consent where your visitors are is your call, which is why it is off until you turn it on.
{{.SwapCopy.Unread}}
{{else}}{{.SwapCopy.Intro}}
{{.SwapCopy.MigrationsNote}}
{{end}} {{end}} {{if eq .SettingsSection "features"}} {{if .Settings.NoBucket}}{{end}} {{if .Settings.FeaturesUnavailable}}{{end}} {{if .Settings}}{{with .Settings.Features}}| Key | Value |
|---|---|
{{.Key}} | {{.Value}} |
Last changed {{.SetAt}}{{if .SetBy}} by {{.SetBy}}{{end}}. The platform stores and serves these; what each one means is this app's own business. It reads them off the deployment block its instance token fetches, so a change lands on its next poll — no restart.
{{else}}No feature flags set.
{{end}}Set or clear one with
carlos features set --app {{$.Detail.App}} key=value
(key= clears); every change is audited under Activity.
| Env prefix | From address | Sending domains | Daily cap | SMTP username | Key age |
|---|---|---|---|---|---|
{{if .EnvPrefix}}{{.EnvPrefix}}_*{{else}}—{{end}} |
{{if .From}}{{.From}}{{else}}—{{end}} | {{if .Domains}}{{range $i, $d := .Domains}}{{if $i}}, {{end}}{{$d}}{{end}}{{else}}—{{end}} |
{{if .Granted}}{{.DailyCap}}{{else}}—{{end}} | {{if .KeyID}}{{.KeyID}}{{else}}—{{end}} |
{{if .KeyAge}}{{.KeyAge}}{{else}}—{{end}} |
Key age is the last credential change — a rotation moves it. The SMTP username above IS this credential's access key id; there is no separate password to show here.
{{end}} {{if .Paused}} {{end}} {{if .PendingFinish}}A rotation is half-finished — two keys open this credential until you retire the old one:
carlos email rotate --finish --app {{$.Detail.App}}{{end}}
{{if and .Declared (not .Granted) (not .Provisioned)}}Declared
and waiting on a verified sending domain — add one with
carlos email domains add --app {{$.Detail.App}} <domain>,
then carlos email enable --app {{$.Detail.App}}.
Authorised to send but
not provisioned yet — run
carlos email enable --app {{$.Detail.App}} to finish it.
| Name | SMTP username | Key age |
|---|---|---|
| {{.Name}} | {{.KeyID}} |
{{if .Age}}{{.Age}}{{else}}—{{end}} |
No password is shown here — standalone credentials have none on the record; it was handed over once, at creation.
{{end}} {{else}} {{if .Available}}No email for this app yet — get it with
carlos email enable --app {{$.Detail.App}}.
Email is not available on this deployment.
{{end}} {{end}} {{end}}{{end}} {{end}} {{if eq .SettingsSection "advanced"}} {{if and .Settings .IsOwner}}{{.Detail.App}} is marked as the control plane: it is what serves this deployment, so its release history is what the fleet is running. Clearing the flag removes that protection — trash, permanent deletion, rename and the account move all become available, and a service credential can promote it again.
Confirms with your passkey — clearing is the dangerous direction, so it is the one that asks. Marking an app again does not.
{{else}}{{.Detail.App}} is an ordinary app. Marking it as the control plane says it IS this deployment’s platform: trashing, permanent deletion, renaming and the account move are then refused, the account holding it cannot be retired, and a service credential can neither promote it nor shorten its release history. A person with ops membership still deploys it exactly as before.
No passkey: marking only adds refusals, and it is undone from this same card.
{{end}} {{end}} {{end}} {{if eq .SettingsSection "delete"}} {{if .IsOwner}}Deleting puts {{.Detail.App}} in the account's trash: hosts stop serving it on their next pass (custom domains included), and it is restorable for {{if .ExpiresAt.IsZero}}{{trashCooloffDays}}{{else}}{{temporaryCooloffDays}}{{end}} days before the platform destroys its releases for good.{{if not .ExpiresAt.IsZero}} It is a temporary app, so its window is shorter than usual.{{end}}{{if .Detail.Production.On}} It is marked as production right now, which blocks deletion — turn the safety delay off on the {{.DeploymentsCopy.History}} tab first.{{end}}
Confirms with your passkey.
{{end}} {{end}}