Skip to content

Shuttle Annotation Conventions

Annotations are metadata, not selectable. They carry provenance, trigger rollout semantics, and integrate with external platforms (DigitalOcean CCM, Prometheus ecosystem). Every annotation Shuttle applies is cataloged here so engineers have a single source of truth.

§24B.1 Provenance Annotations (On All Service Resources)

Annotation Value Purpose
starform.io/deployment-id Deployment UUID Which deployment created this resource version
starform.io/build-id Build UUID Which build produced the image
starform.io/git-sha Full commit SHA Source commit reference
starform.io/git-ref e.g. refs/heads/main Source ref at build time
starform.io/git-repo e.g. github.com/acme/api Source repository
starform.io/image-ref Full image ref with digest Exact image running (digest, not tag)
starform.io/deployed-at ISO-8601 timestamp When Shuttle applied this version
starform.io/deployed-by User UUID Who triggered the deployment
kubernetes.io/change-cause Deployment <dep_id> by <user_email> Shown in kubectl rollout history

§24B.2 Rollout Trigger Annotations (On Pod Template)

Changing these annotations forces a new ReplicaSet and triggers a rolling restart without requiring an image change. Used when non-image configuration changes (e.g., Var Group rotation).

Annotation Value When It Changes
starform.io/var-group-checksum sha256:<hex> of sorted JSON of all attached Var Group values When any attached Var Group entry value changes
starform.io/config-checksum sha256:<hex> of service config (ports, probes, resource limits) When service config changes
starform.io/restart-nonce Random UUID When user explicitly clicks "Restart" in dashboard

Checksum computation (Var Group): Shuttle sorts attached Var Groups by attach_order, serializes each group's entries (sorted by key) to canonical JSON, concatenates, and hashes with SHA-256. Any change to any attached value produces a new checksum, which bumps the pod template hash, which triggers a zero-downtime rolling restart. See §38.7.

§24B.3 Customer-Facing Metadata Annotations

Annotation Value Purpose
starform.io/service-url e.g. api-ws_abc.starform.app Auto-generated public URL
starform.io/custom-domains Comma-separated domain list Customer-configured domains
starform.io/environment-label e.g. Production, Staging Human-readable env name (distinct from the label value used for selectors)

§24B.4 DigitalOcean Cloud Controller Manager Annotations

Applied to the Envoy Gateway Service (the LoadBalancer-type Service that fronts the cluster):

Annotation Typical Value Purpose
service.beta.kubernetes.io/do-loadbalancer-size-unit 1200 LB size (scales with cluster load; Starbase manages)
service.beta.kubernetes.io/do-loadbalancer-protocol tcp Transport; TLS terminates at Envoy
service.beta.kubernetes.io/do-loadbalancer-enable-proxy-protocol true Preserves client IP for Envoy
service.beta.kubernetes.io/do-loadbalancer-healthcheck-port 10256 Health check endpoint
service.beta.kubernetes.io/do-loadbalancer-healthcheck-protocol tcp Health check protocol

The full DO LB annotation set is maintained in a Go constant in Starbase's DO adapter package; this table lists the subset managed via desired state.

§24B.5 Prometheus Scrape Annotations

Applied to pods that expose a /metrics endpoint:

Annotation Value Purpose
prometheus.io/scrape true Opt-in to metric scraping
prometheus.io/port e.g. 9090 Metrics port
prometheus.io/path Default /metrics Metrics endpoint path
prometheus.io/scheme http or https Scheme

Reserved for optional customer app-/metrics scraping — a future OTel Collector scrape job, not wired at MVP (the collector scrapes only cAdvisor, v2 Collect; custom metrics are a §18 non-goal). Identity on scraped rows would come from the same k8sattributes label stamping as every pod-origin signal.

§24B.6 Var Group Secret Annotations

Applied to K8s Secrets created from Var Groups (§38):

Annotation Value
starform.io/var-group-id Var Group UUID
starform.io/var-group-name Var Group display name
starform.io/var-group-version Monotonic version, bumped on value change
starform.io/environment Environment this Secret is scoped to
starform.io/project-id Owning project
starform.io/encrypted-at-rest true — the value's Postgres source-of-truth is AES-256-GCM encrypted; the K8s Secret itself is protected at rest by Talos disk encryption (not by this annotation)

§24B.7 Namespace Annotations

Annotation Value
starform.io/project-created-at ISO-8601
starform.io/project-owner-email For debugging; customer-visible
starform.io/cluster-assignment-reason e.g., "default-region=fra1" — why the project's entities on this cluster landed here (placement is per service-per-environment, FR-077; the namespace exists per cluster)
starform.io/soft-delete-at Set on project deletion; namespace GC removes after retention window

§24B.8 HTTPRoute Annotations

Annotation Value
starform.io/custom-domain-validated-at When domain ownership was validated (Cloudflare custom-hostname DCV)
starform.io/custom-hostname-id Cloudflare for SaaS custom-hostname ID — cert issuance/renewal is Cloudflare's (post-MVP, §39.3 #27; no cert-manager)

§24B.9 Consumer Contracts

Each annotation has a defined consumer. Changes to annotation names or semantics require updating all consumers:

Annotation prefix Consumer
starform.io/* Shuttle (filtering, rollout triggers), OTel Collector (k8sattributes identity stamping), Stardeck (dashboard display), billing cron (aggregation)
service.beta.kubernetes.io/do-* DigitalOcean Cloud Controller Manager
prometheus.io/* OTel Collector scrape config (future app-metrics scrape)
kubernetes.io/change-cause kubectl rollout history
app.kubernetes.io/* Third-party K8s tools (Lens, k9s, Headlamp)

Cross-references

The selectable label set (annotations' counterpart) → §24 · the Var Group checksum / rotation flow → §38.7 · the telemetry collection that consumes identity → v2 Collect · DO LB sizing via desired state → §25.1.