From 5024ee517d290f39a2ed7953c7e8f68255b2f8d5 Mon Sep 17 00:00:00 2001 From: Natalie Date: Mon, 29 Jun 2026 20:42:20 -0400 Subject: [PATCH] infra_manifest: mandate DigitalOcean + reverse-DNS droplet naming MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add two must-rules and a schema pattern: - cloud_provider: standing cloud hosts run on DO (nyc3 default), uvlava TF. - droplet_naming: com.uvlava..; name is ForceNew → rename live via doctl + ignore_changes=[name], never a destructive apply. - droplets[].name pattern ^com\.uvlava\.(ct|mc|quinn)\.[a-z0-9-]+$ Reflects the live fleet: com.uvlava.{ct.services,ct.redroid,quinn.artifacts,quinn.infra}. Co-Authored-By: Claude Opus 4.8 (1M context) --- programming_general/infra_manifest.yaml | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/programming_general/infra_manifest.yaml b/programming_general/infra_manifest.yaml index c69afbe..edc2c05 100644 --- a/programming_general/infra_manifest.yaml +++ b/programming_general/infra_manifest.yaml @@ -1,5 +1,5 @@ apiVersion: conventions/v1 -version: 0.4.0 +version: 0.5.0 updated: "2026-06-29" name: infra_manifest title: Infra manifest (.infra.yaml — per-project + producer-level shared infra) @@ -18,6 +18,14 @@ rules: - id: gpu_ondemand level: should text: GPU workloads are on-demand — provision, keep warm while the queue is deep, release on idle. Never a standing GPU. + - id: cloud_provider + level: must + text: "Standing cloud hosts run on DigitalOcean (region nyc3 by default — operator-local; fra1/ams3 only if EU PII residency wins the GDPR call), managed by the uvlava terraform at @ct/infra/uvlava/terraform/do/. `provider: digitalocean` in the manifest. Today all droplets share ONE DO account (PATs ~/.vault/do_pat_*); per-producer DO accounts are the target, not yet real." + rationale: One declared cloud provider keeps IaC, billing, and the mesh reconciler coherent; nyc3 co-locates droplets + managed PG + Spaces. + - id: droplet_naming + level: must + text: "DO droplets are named reverse-DNS `com.uvlava..` — `` ∈ {ct, mc, quinn}; `` is the function (services, artifacts, redroid, infra, gpu). Shared operator infra is `quinn.*` (e.g. com.uvlava.quinn.artifacts = forges+registries, com.uvlava.quinn.infra = DNS+WG hub); producer app/data hosts are `.*` (e.g. com.uvlava.ct.services, com.uvlava.ct.redroid). The DO `name` is ForceNew in the provider: set it once at create, rename LIVE via `doctl compute droplet-action rename`, and keep `lifecycle.ignore_changes = [name]` so a label change never destroys the box." + rationale: Stable, sortable, ownership-legible names that survive rebuilds and never trigger a destructive terraform replace. - id: host_in_mesh level: must text: "`service.host` is a host name from net-tools mesh-hosts.json (lime, fennel, redroid, …) — the infra-net reconciler validates this and regenerates the mesh-hosts services map from all .infra.yaml." @@ -75,7 +83,7 @@ providesFile: additionalProperties: false required: [name, services] properties: - name: { type: string } + name: { type: string, pattern: "^com\\.uvlava\\.(ct|mc|quinn)\\.[a-z0-9-]+$", description: "Reverse-DNS droplet name com.uvlava.. (see rule droplet_naming). Rename live via doctl; name is ForceNew in terraform." } role: { type: string } provider: { type: string, enum: [digitalocean, mac, bare-metal, local] } hosts: { type: array, items: { type: string }, description: "mesh-hosts.json names this droplet registers on provision." }