fly-deployment — Obraz kontejneru je projekcí modelu repozitáře a jeho smoke test je jeho důkazem
Jeden kanonický objekt nasazení pod .ai/repo/deployments/ popisuje image; typovaný model v Rustu ho parsuje a ověřuje; Dockerfile, jeho ignore soubor, image na GHCR, který sestavují docker-image.yml a release.yml, jeho smoke odvozený z registru tras, kontroly doctoru, dokumentace a pohled v Cockpitu jsou projekce tohoto objektu a registru schopností, každá kontrolovaná na drift. Publikovaný image běží jako non-root uživatel, nenese žádné tajemství ani vývojářskou cestu, ve svém smoke odpovídá jako live a ready a má změřené základní hodnoty velikosti, cold-startu a paměti. Přeorientováno 2026-10-14 z nasazení na Fly.io, které vlastník odpojil 2026-10-12.
AKTIVNÍ 4 of 26 issues done
- připraveno
- 8
- blokováno
- 14
- aktivní
- 0
- verify
- 0
- hotovo
- 4
- zrušeno
- 9
Problém
Majordomus nemá vůbec žádné nasazení: žádný kontejner, žádného hostingového poskytovatele, žádný způsob, jak by někdo, kdo nestojí před tímto checkoutem, viděl vrstvu, kterou servíruje. Zřejmá náprava je ta špatná. Ručně psaný Dockerfile a fly.toml by byly druhým popisem faktů, které repozitář už drží — port, na kterém server naslouchá, trasy, které registruje, assety, které produkuje build webu, binárka, kterou pojmenovává workspace — a každý z těchto párů by se rozešel při první změně jedné poloviny. Repozitář už takový tvar jinde odmítá: schopnosti se deklarují jednou a promítají do CLI, HTTP, MCP, OpenAPI, dokumentace a webu a generate --check selže, když je projekce zastaralá. Nasazení musí přijít stejnou cestou, nebo vůbec.
Výsledek
Jeden kanonický objekt nasazení pod .ai/repo/deployments/ popisuje image; typovaný model v Rustu ho parsuje a ověřuje; Dockerfile, jeho ignore soubor, image na GHCR, který sestavují docker-image.yml a release.yml, jeho smoke odvozený z registru tras, kontroly doctoru, dokumentace a pohled v Cockpitu jsou projekce tohoto objektu a registru schopností, každá kontrolovaná na drift. Publikovaný image běží jako non-root uživatel, nenese žádné tajemství ani vývojářskou cestu, ve svém smoke odpovídá jako live a ready a má změřené základní hodnoty velikosti, cold-startu a paměti. Přeorientováno 2026-10-14 z nasazení na Fly.io, které vlastník odpojil 2026-10-12.
Aktuální stav
Measured 2026-10-14 on master e28daccd9b: .ai/repo/deployments/majordomus.yaml is the canonical object; deploy/Dockerfile and its ignore file are generated from it (Alpine, uid 10001, exec-form entrypoint); docker-image.yml builds and smoke-tests the image on pull requests and on master, and release.yml publishes it to GHCR; .github/actions/image-smoke checks the image runs as non-root and answers /api/v1/live and /api/v1/ready; deploy.list, deploy.get, deploy.check and deploy.observed are capabilities. Missing: a smoke derived from the route registry, a secret and developer-path scan of the image, an SBOM, size, cold-start and memory baselines, a documentation page. The object still carries region, machines and resources, which nothing reads since Fly.io was disconnected on 2026-10-12.
Cílový stav
Image v GHCR je projekcí kanonického objektu jako každý jiný artefakt: generovaný, kontrolovaný na drift, smoke-testovaný z registru tras, skenovaný na tajnosti a vývojářské cesty, měřený proti zaznamenaným rozpočtům, zdokumentovaný a zobrazený v cockpitu. Zda region, stroje a zdroje opustí schéma deployment/v1, je rozhodnuto a zaznamenáno.
Rozsah
- .ai/repo/deployments
- .ai/repo/adrs
- .ai/repo/rules/project
- .ai/repo/policy.yaml
- apps/majordomus-cli/src/deploy
- apps/majordomus-cli/src/capability/builtin
- apps/majordomus-cli/src/http
- deploy
- share/kinds.yaml
- share/allow
- share/schemas
- dokumentace
- web
- test/cases
- .github/workflows
Mimo rozsah
- Jakákoli závislost v kódu, skriptu, dokumentaci, CI nebo výchozí hodnotě na ~/dev/prismatic-platform
- Abstrakce providera pokrývající i jiné hosty než ten, na který tento repozitář nasazuje
- Kubernetes, Nomad, buildpacks, Nixpacks nebo druhá implementace kontejnerů
- Perzistentní svazek, databáze nebo jakákoli stavová služba, pokud ji nevynutí změřený požadavek
- Mutující operace nasazení vystavené neověřenému HTTP nebo prohlížeči
- Optimalizace řízená profilem
Kritéria přijetí
- Jeden kanonický objekt nasazení je jediné místo, kde se uvádí port, region, zdroje, počet Machine, routy health, vstupy buildu a rozpočty
- Každý artefakt image — Dockerfile a jeho ignore soubor — je generovaný, označený jako generovaný se svým zdrojem a příkazem regenerace a selže na generate --check, když se upraví ručně
- Čtení nasazení jsou deklarována jednou v registru schopností a objevují se v CLI, HTTP API, MCP, OpenAPI a vygenerované dokumentaci bez druhé registrace
- Sada smoke testů se odvozuje z registru rout; nikde neexistuje druhý seznam endpointů
- Produkční image běží jako uživatel bez roota, neobsahuje žádný build toolchain, žádnou historii repozitáře, žádné tajemství a žádnou absolutní cestu vývojáře
- Publikovaný image odpovídá live a ready ve svém smoke, spuštěném zvenčí kontejneru na volném portu hostitele
- Velikost image, velikost binárky, velikost build kontextu, studený start, rezidentní paměť a latence endpointu se měří, zaznamenávají jako základní hodnoty a hlídají proti nevysvětlené regresi
- Žádný přihlašovací údaj se nezapisuje do repozitáře, do vrstvy Dockeru, do generovaného souboru, na web ani do logu a image se publikuje vlastním tokenem workflow
- Každé pravidlo, které tento milník uvádí, vynucuje kontrola, kterou CI spouští
Validace
- bash test/run.sh
- bin/majordomus doctor
- cargo test --workspace --all-features
- cargo clippy --workspace --all-targets --all-features -- -D warnings
- majordomus generate --check
Požadované důkazy
- canonical_object
- typed_model
- generated_projections
- registry_derived_smoke
- container_minimal
- image_smoke
- budgets_measured
- secrets_isolated
- rules_enforced
Rizika
- Generování může skrýt Dockerfile před lidmi, kteří jej musí číst. Vygenerovaný soubor musí zůstat idiomatický a reviewovatelný; zdroj popisuje záměr, výstup popisuje mechaniku a přispěvateli, který upraví výstup, se řekne, který soubor má místo toho změnit.
- Topologie tras a servírované povrchy se přepisují na jiných větvích podle ADR 0013. Smoke sada přišpendlená k dnešním cestám by byla při příchodu zastaralá, takže musí číst registr tras, ne seznam cest.
- 256 MB je hypotéza. Drží se jen tak dlouho, dokud projde změřený běh pod tímto limitem; konečné číslo rozhodují důkazy, ne preference.
- Nasazení se dotýká peněz. První nasazení nesmí zanechat běžet dva Machine a inventář Machine se ověřuje, ne předpokládá.
- Zaváděcí přihlašovací údaje pocházejí zvenčí tohoto repozitáře. Smějí se použít k získání autentizované relace a nikde jinde; cokoli jiného by učinilo Majordomus závislým na Prismatic Platform, což je zakázáno.
Úkoly
Každý z nich je prováděcí kontrakt s vlastními kritérii přijetí, validačním příkazem a požadovanými důkazy. Sloupec wave je vrstva grafu závislostí, v níž úkol leží.
| issue | status | vlna | závisí na | název |
|---|---|---|---|---|
| I0901 | HOTOVO | 0 | — | Popis nasazení je druh vrstvy, ne soubor providera |
| I0902 | HOTOVO | 1 | I0901 | Objekt nasazení se stane typovaným Rustem, který odmítá nesmysly |
| I0903 | HOTOVO | 2 | I0902 | Čtení nasazení se deklarují jednou a promítají všude |
| I0904 | HOTOVO | 2 | I0902 | Adresa pro naslouchání je jeden fakt se dvěma projekcemi |
| I0905 | PŘIPRAVENO | 2 | I0902 | Liveness a readiness jsou registrované schopnosti, ne hacky routeru |
| I0906 | PŘIPRAVENO | 3 | I0904 | Ukončení je řádné a dokázané proti skutečnému kontejneru |
| I0907 | PŘIPRAVENO | 2 | I0902 | Běžící proces říká, co je, ze seznamu povolených |
| I0908 | PŘIPRAVENO | 2 | I0902 | Hostovaný proces nemá repozitář a řekne to místo selhání |
| I0909 | BLOKOVÁNO | 3 | I0902, I0904, I0905 | Produkční image je generovaná projekce specifikace buildu |
| I0910 | BLOKOVÁNO | 4 | I0909 | Profil release se volí měřením, ne lidovou moudrostí |
| I0911 | BLOKOVÁNO | 4 | I0909 | Změna zdroje nepřebuduje celý svět a kontext zůstane malý |
| I0912 | BLOKOVÁNO | 4 | I0909 | Image servíruje web, který vytvořila kanonická pipeline |
| I0913 | ZRUŠENO | 3 | I0902, I0903 | Konfigurace providerů je generovaná a levný profil je deklarován |
| I0914 | ZRUŠENO | 4 | I0903, I0909, I0913 | Jedno jádro nasazení, jeden příkaz a dry run, který nic nezmění |
| I0915 | ZRUŠENO | 5 | I0914 | Nasazení se přidá k diagnostice, která už existuje |
| I0916 | BLOKOVÁNO | 5 | I0905, I0914 | Smoke sada se odvozuje z registru tras a nikdy se nepíše dvakrát |
| I0917 | ZRUŠENO | 5 | I0914 | Špatné nasazení lze deterministicky vrátit |
| I0918 | ZRUŠENO | 2 | I0902 | Bootstrap credential se použije jednou a nepatří nikomu |
| I0919 | BLOKOVÁNO | 4 | I0909 | V image neodchází nic tajného a nic lokálního |
| I0920 | BLOKOVÁNO | 4 | I0909 | Závislosti image jsou známé a jeho advisories jsou politika |
| I0921 | BLOKOVÁNO | 5 | I0910, I0911 | Velikost se nejdřív měří a až poté rozpočtuje |
| I0922 | ZRUŠENO | 6 | I0930 | Hypotéza o paměti je testována, ne tvrzena |
| I0923 | BLOKOVÁNO | 6 | I0930 | Studený start a cena endpointu jsou cíle měření jako všechno ostatní |
| I0924 | ZRUŠENO | 1 | I0901 | Rozhodnutí je zaznamenáno tam, kde se zaznamenávají architektonická rozhodnutí |
| I0925 | BLOKOVÁNO | 6 | I0915 | Každé pravidlo nasazení je kontrola, která běží |
| I0926 | BLOKOVÁNO | 4 | I0903, I0913, I0924 | Dokumentace nasazení je vygenerovaná a dostupná |
| I0927 | PŘIPRAVENO | 3 | I0903 | Cockpit ukazuje nasazení ze stejných dat |
| I0928 | BLOKOVÁNO | 6 | I0919, I0921, I0930 | Pull request nemůže zmergovat nasazení, které by nefungovalo |
| I0929 | ZRUŠENO | 8 | I0918, I0931 | Produkce se nasazuje z CI tokenem omezeným na jednu aplikaci |
| I0930 | BLOKOVÁNO | 5 | I0906, I0909, I0912 | Skutečný image běží za skutečných limitů dřív, než se cokoli nasadí |
| I0931 | ZRUŠENO | 7 | I0913, I0914, I0916, I0917, I0918, I0922, I0930 | Aplikace existuje, jeden stroj ji spouští a URL odpovídá |
| I0932 | BLOKOVÁNO | 9 | I0920, I0923, I0925, I0926, I0927, I0928, I0929, I0931 | Milník se přijímá na základě svých důkazů |
| I3244 | PŘIPRAVENO | 0 | — | The generated Dockerfile copies every path crate cargo metadata names, so a new workspace crate needs no edit of the image |
| I3245 | PŘIPRAVENO | 0 | — | The image build's cold and warm durations and its context size are read from docker-image runs, and the deployment records say what is built today |
| I3315 | PŘIPRAVENO | 0 | — | The image smoke completes an MCP initialize on /mcp and a WebSocket upgrade on /events, not only a ready probe |
Graf
flowchart LR
I0901["I0901<br/>The deployment description is a kind of the layer, not a provider file"]:::done
I0902["I0902<br/>The deployment object becomes typed Rust that refuses nonsense"]:::done
I0903["I0903<br/>Deployment reads are declared once and projected everywhere"]:::done
I0904["I0904<br/>The listen address is one fact with two projections"]:::done
I0905["I0905<br/>Liveness and readiness are registered capabilities, not router hacks"]:::ready
I0906["I0906<br/>Termination is graceful and proved against the real container"]:::ready
I0907["I0907<br/>The running process says what it is, from an allowlist"]:::ready
I0908["I0908<br/>A hosted process has no repository, and says so instead of failing"]:::ready
I0909["I0909<br/>The production image is a generated projection of the build specification"]:::blocked
I0910["I0910<br/>The release profile is chosen by measurement, not by folklore"]:::blocked
I0911["I0911<br/>A source change does not rebuild the world, and the context stays small"]:::blocked
I0912["I0912<br/>The image serves the site the canonical pipeline produced"]:::blocked
I0913["I0913<br/>The provider configuration is generated, and the cheap profile is declared"]:::cancelled
I0914["I0914<br/>One deployment core, one command, and a dry run that mutates nothing"]:::cancelled
I0915["I0915<br/>Deployment joins the diagnostics that already exist"]:::cancelled
I0916["I0916<br/>The smoke suite is derived from the route registry, never written twice"]:::blocked
I0917["I0917<br/>A bad deployment can be undone deterministically"]:::cancelled
I0918["I0918<br/>The bootstrap credential is used once and belongs to nothing"]:::cancelled
I0919["I0919<br/>Nothing secret and nothing local leaves in the image"]:::blocked
I0920["I0920<br/>The image's dependencies are known and its advisories are policy"]:::blocked
I0921["I0921<br/>Size is measured first and budgeted second"]:::blocked
I0922["I0922<br/>The memory hypothesis is tested, not asserted"]:::cancelled
I0923["I0923<br/>Cold start and endpoint cost are benchmark targets like everything else"]:::blocked
I0924["I0924<br/>The decision is recorded where architecture decisions are recorded"]:::cancelled
I0925["I0925<br/>Every deployment rule is a check that runs"]:::blocked
I0926["I0926<br/>The deployment documentation is generated and reachable"]:::blocked
I0927["I0927<br/>The cockpit shows the deployment from the same data"]:::ready
I0928["I0928<br/>A pull request cannot merge a deployment that would not work"]:::blocked
I0929["I0929<br/>Production deploys from CI with a token scoped to one application"]:::cancelled
I0930["I0930<br/>The real image runs under the real limits before anything is deployed"]:::blocked
I0931["I0931<br/>The application exists, one machine runs it, and the URL answers"]:::cancelled
I0932["I0932<br/>The milestone is accepted on its evidence"]:::blocked
I3244["I3244<br/>The generated Dockerfile copies every path crate cargo metadata names, so a new workspace crate needs no edit of the image"]:::ready
I3245["I3245<br/>The image build's cold and warm durations and its context size are read from docker-image runs, and the deployment records say what is built today"]:::ready
I3315["I3315<br/>The image smoke completes an MCP initialize on /mcp and a WebSocket upgrade on /events, not only a ready probe"]:::ready
I0901 --> I0902
I0901 --> I0924
I0902 --> I0903
I0902 --> I0904
I0902 --> I0905
I0902 --> I0907
I0902 --> I0908
I0902 --> I0909
I0902 --> I0913
I0902 --> I0918
I0903 --> I0913
I0903 --> I0914
I0903 --> I0926
I0903 --> I0927
I0904 --> I0906
I0904 --> I0909
I0905 --> I0909
I0905 --> I0916
I0906 --> I0930
I0909 --> I0910
I0909 --> I0911
I0909 --> I0912
I0909 --> I0914
I0909 --> I0919
I0909 --> I0920
I0909 --> I0930
I0910 --> I0921
I0911 --> I0921
I0912 --> I0930
I0913 --> I0914
I0913 --> I0926
I0913 --> I0931
I0914 --> I0915
I0914 --> I0916
I0914 --> I0917
I0914 --> I0931
I0915 --> I0925
I0916 --> I0931
I0917 --> I0931
I0918 --> I0929
I0918 --> I0931
I0919 --> I0928
I0920 --> I0932
I0921 --> I0928
I0922 --> I0931
I0923 --> I0932
I0924 --> I0926
I0925 --> I0932
I0926 --> I0932
I0927 --> I0932
I0928 --> I0932
I0929 --> I0932
I0930 --> I0922
I0930 --> I0923
I0930 --> I0928
I0930 --> I0931
I0931 --> I0929
I0931 --> I0932
classDef done stroke:#16a34a,fill:#dcfce7,color:#14532d,stroke-width:2px
classDef active stroke:#2563eb,fill:#eff6ff,color:#1e3a8a,stroke-width:2px
classDef verify stroke:#7c3aed,fill:#f5f3ff,color:#4c1d95,stroke-width:2px
classDef ready stroke:#0891b2,fill:#ecfeff,color:#164e63,stroke-width:2px
classDef planned stroke:#0891b2,fill:#ecfeff,color:#164e63,stroke-width:2px
classDef blocked stroke:#b45309,fill:#fffbeb,color:#78350f,stroke-width:2px
classDef cancelled stroke:#6b7280,fill:#f9fafb,color:#374151,stroke-width:2px
classDef superseded stroke:#6b7280,fill:#f9fafb,color:#374151,stroke-width:2pxLinked from this diagram (35)
- I0901 Popis nasazení je druh vrstvy, ne soubor providera
- I0902 Objekt nasazení se stává typovaným Rustem, který odmítá nesmysly
- I0903 Čtení nasazení se deklarují jednou a promítají všude
- I0904 Adresa naslouchání je jeden fakt se dvěma projekcemi
- I0905 Živost a připravenost jsou registrované schopnosti, ne hacky routeru
- I0906 Ukončení je řádné a doložené proti skutečnému kontejneru
- I0907 Běžící proces říká, co je, ze seznamu povolených
- I0908 Hostovaný proces nemá repozitář a řekne to, místo aby selhal
- I0909 Produkční image je generovaná projekce specifikace buildu
- I0910 Profil release se volí měřením, ne lidovou moudrostí
- I0911 Změna zdroje nepřestavuje svět a kontext zůstává malý
- I0912 Image servíruje web, který vyrobila kanonická pipeline
- I0913 Konfigurace providera je generovaná a levný profil je deklarovaný
- I0914 Jedno jádro nasazení, jeden příkaz a nanečisto, které nic nemění
- I0915 Nasazení se připojí k diagnostice, která už existuje
- I0916 Smoke sada se odvozuje z registru tras, nikdy se nepíše dvakrát
- I0917 Chybné nasazení lze vrátit deterministicky
- I0918 Bootstrap credential se použije jednou a nepatří nikomu
- I0919 Nic tajného a nic lokálního neopouští image
- I0920 Závislosti image jsou známé a jeho advisories jsou politika
- I0921 Velikost se nejdřív měří a teprve potom rozpočtuje
- I0922 Hypotéza paměti je testována, ne tvrzena
- I0923 Studený start a cena endpointu jsou cíle měření výkonu jako všechno ostatní
- I0924 Rozhodnutí se zaznamenává tam, kde se zaznamenávají architektonická rozhodnutí
- I0925 Každé pravidlo nasazení je kontrola, která běží
- I0926 Dokumentace nasazení je generovaná a dosažitelná
- I0927 Cockpit ukazuje nasazení ze stejných dat
- I0928 Pull request nemůže zmergovat nasazení, které by nefungovalo
- I0929 Produkce se nasazuje z CI s tokenem omezeným na jednu aplikaci
- I0930 Skutečný image běží pod skutečnými limity, než se cokoli nasadí
- I0931 Aplikace existuje, jeden stroj ji provozuje a URL odpovídá
- I0932 Milník se přijímá na základě svých důkazů
- I3244 The generated Dockerfile copies every path crate cargo metadata names, so a new workspace crate needs no edit of the image
- I3245 The image build's cold and warm durations and its context size are read from docker-image runs, and the deployment records say what is built today
- I3315 The image smoke completes an MCP initialize on /mcp and a WebSocket upgrade on /events, not only a ready probe
Kanonický záznam: .ai/repo/project/milestones/fly-deployment.yaml. Přečtěte jej zpět pomocí majordomus plan show fly-deployment.