feat(cli): validate prerequisites and seal installation plans
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
# Installation preflight and release manifest
|
||||
|
||||
The native operator protocol is version 1. `installation preflight` is the independent
|
||||
step-3 host check. `installation plan` repeats document validation, performs step-5
|
||||
live checks and writes an owner-only JSON plan plus a separate owner-only `.key` file.
|
||||
Neither command creates containers, imports bindings, modifies a database or invokes
|
||||
model generation. Exit codes are 0 (checks passed), 1 (blocking error), and 2 (usage).
|
||||
JSON stdout contains only the report. Checks carry stable `id`, `outcome`, `field`
|
||||
and `action`; outcomes are `passed`, `error`, `warning`, `deferred-to-runtime`.
|
||||
|
||||
## Release manifest schema 1
|
||||
|
||||
The manifest is a local JSON file shipped with the verified operator/release bundle.
|
||||
Required keys:
|
||||
|
||||
| Key | Contract |
|
||||
| --- | --- |
|
||||
| `schema_version` | `1` |
|
||||
| `version` | Semantic release version, optionally prerelease |
|
||||
| `revision` | 40 lowercase hexadecimal Git commit characters |
|
||||
| `validator_protocol` | `1`; incompatible consumers refuse the manifest |
|
||||
| `requirements` | `cpus`, `memory_bytes`, `disk_bytes`; at least 2 CPUs, 4 GiB Docker memory and 10 GiB installation filesystem space |
|
||||
| `components` | Includes `pi`, `catalog-migrations`, `workspace-maintenance` |
|
||||
| `images` | Exactly `core`, `frontend`, `catalog`, `qdrant`, `embedding`; each maps `linux/amd64` and/or `linux/arm64` to a `docker.io/...@sha256:...` **single-platform image digest** |
|
||||
| `files` | Relative packaged resource paths to SHA-256; no traversal, links or absolute paths; maximum 256 files, 32 MiB per resource |
|
||||
| `compose` | Ordered relative Compose file paths present in `files` for this release configuration |
|
||||
|
||||
Include the selected `deploy/compose.git-https.yaml` or `deploy/compose.git-ssh.yaml`
|
||||
transport overlay in `files`. Standard transport overlays are resolved from the
|
||||
release while absent in the installation directory; existing authored overrides
|
||||
remain input files. Compose must resolve all eight services: core, frontend,
|
||||
catalog-db, catalog-migrate, workspace-maintenance, qdrant, embedding and
|
||||
embedding-model-init. The two maintenance services share the core digest; embedding
|
||||
initialization shares the embedding digest. Source builds and undeclared services
|
||||
are rejected in this prebuilt path. The explicit source path is a separate ticket.
|
||||
|
||||
`docker manifest inspect --verbose` checks each selected immutable image and its
|
||||
platform without pulling layers. `docker compose config --format json` checks the
|
||||
effective service configuration. Compose receives only Docker connection/trust,
|
||||
proxy and executable-discovery host variables; application parameters come from
|
||||
the prepared environment file. Raw Docker output is never copied into reports.
|
||||
Each Docker command has a 15-second bound. No release is currently certified merely
|
||||
because controlled manifest tests pass: publication and real pull acceptance belong
|
||||
to the publication/execution tickets.
|
||||
|
||||
## External checks and bounds
|
||||
|
||||
- Git HTTPS: authenticated `GET /info/refs?service=git-upload-pack`, configured CA,
|
||||
no redirects, selected branch advertised, 1 MiB response and 5-second bound.
|
||||
Git SSH uses its prepared key/known-hosts and `git-upload-pack --advertise-refs`
|
||||
with the same response/time bounds; no checkout or push occurs.
|
||||
- PostgreSQL: the existing Catalog diagnostic adapter authenticates and reads
|
||||
`current_database()` plus schema `USAGE`; no user tables are modified.
|
||||
- REST database transport: existing Catalog diagnostic `GET` with the configured
|
||||
bearer/API-key header and status validation. SSH database bindings cannot pass
|
||||
this NL-to-SQL installation plan because runtime sessions do not support them.
|
||||
- Evidence: local paths were already validated. HTTP performs bounded GET requests
|
||||
and cancels response bodies; signed URL identities must match authored provenance.
|
||||
S3 performs one `ListObjectsV2` request with `MaxKeys: 1`, no retries, explicit
|
||||
file credentials and the canonical Evidence egress policy. These metadata requests
|
||||
can incur normal remote-service request charges; they do not run LLM generation.
|
||||
Each external request has a 5-second bound; the native database/Evidence helper
|
||||
has a 60-second aggregate bound. Correct unavailable services before repeating.
|
||||
- Explicit model endpoints: DNS/TCP/TLS origin reachability, without generating
|
||||
tokens. Built-in endpoint resolution, provider authentication and model smoke
|
||||
operations use the bundled Pi SDK at runtime; the report never claims those
|
||||
operations have already passed.
|
||||
|
||||
No unreachable configured external dependency is converted to a deferred success.
|
||||
Runtime obligations have explicit identities: `container-network`,
|
||||
`catalog-initialization`, `pi-operation`, `local-embedding`,
|
||||
`workspace-preprocessing`, `workspace-readiness`. These must be discharged by the
|
||||
execution/readiness tickets before final success. Host disk inspection cannot prove
|
||||
Docker Desktop VM free storage; its separate storage warning remains explicit.
|
||||
|
||||
## Input identity and freshness
|
||||
|
||||
The plan records normalized installation configuration, release digests, validator
|
||||
build identity, verified input paths, local workspace content and its Git HEAD when
|
||||
available (otherwise a content snapshot). Files are bounded to 32 MiB each and
|
||||
256 MiB total; workspace/auth trees to 10,000 entries, without links or special files.
|
||||
Credential contents are never serialized. An HMAC covers the private inputs and
|
||||
plan using a separate random 32-byte owner-only key; no public unkeyed secret hash
|
||||
is generated. Credential rotation invalidates the plan. Added/deleted/changed
|
||||
workspace files invalidate it as well. Changes during the checks abort publication.
|
||||
Plan output never overwrites an existing plan or key.
|
||||
|
||||
Execution and resumption must call `VerifyPlanInputs` **and repeat live checks and
|
||||
credential reads before mutations**. A valid seal alone does not certify current
|
||||
network availability, Docker state or runtime readiness. Keep both plan files
|
||||
private and outside the workspace repository; they are installation-local artifacts.
|
||||
@@ -152,6 +152,46 @@ must already exist. Release assets, external connectivity, Catalog import and ru
|
||||
readiness remain explicit deferred checks. Success prepares the next preflight;
|
||||
it neither skips those checks nor establishes a completed installation.
|
||||
|
||||
## Check prerequisites and produce the plan
|
||||
|
||||
At step 3, before completing all application parameters, check the machine and
|
||||
the private installation directory already prepared:
|
||||
|
||||
```bash
|
||||
tht installation preflight --directory /path/installation --json
|
||||
```
|
||||
|
||||
This requires a reachable Linux Docker daemon, Compose 2.24 or newer, at least
|
||||
2 CPUs, 4 GiB allocated to Docker and 10 GiB free on the installation filesystem.
|
||||
A release may require more resources. On Windows run the Linux executable in
|
||||
Ubuntu WSL2 with Docker Desktop integration; Pi is bundled in the core image.
|
||||
|
||||
At step 5, after `installation validate`, select the published release manifest
|
||||
with its downloaded bundle resources and produce a new plan:
|
||||
|
||||
```bash
|
||||
tht --installation /path/installation/thothii-installation.yaml installation plan \
|
||||
--workspaces /path/workspaces \
|
||||
--release /path/release/release-manifest.json \
|
||||
--output /path/installation/installation-plan.json --json
|
||||
```
|
||||
|
||||
This repeats document checks, verifies image digests and Compose, Git, available
|
||||
external databases and Evidence, then saves the plan and its separate private
|
||||
`.key` file. It does not execute setup. Missing images and unavailable existing
|
||||
dependencies block the plan. Actual Docker Hub publication remains the next ticket;
|
||||
an invented manifest cannot bypass publication.
|
||||
|
||||
Correct `error` outcomes and read `warning` outcomes. `deferred-to-runtime` entries
|
||||
are mandatory checks after startup, not readiness already achieved. After changing
|
||||
documents or rotating credentials, produce a new plan; existing files are never
|
||||
overwritten. Keep both plan files outside workspace Git. External probes perform
|
||||
bounded database authentication/schema reads, Git/HTTP/S3 reads and explicit model
|
||||
endpoint reachability checks. They invoke no LLM generation; HTTP/S3 requests may
|
||||
incur ordinary service request charges. See the
|
||||
[preflight reference](installation-preflight.md) for limits, the manifest
|
||||
format and runtime obligations.
|
||||
|
||||
## Before you start: the two repositories
|
||||
|
||||
There are two separate repositories:
|
||||
|
||||
@@ -158,6 +158,47 @@ differiti: asset del rilascio, connettività esterna, import Catalog e readiness
|
||||
Un esito positivo prepara il successivo preflight: non autorizza a saltare tali
|
||||
controlli e non equivale a un'installazione completata.
|
||||
|
||||
## Verificare le precondizioni e produrre il piano
|
||||
|
||||
Al passo 3, prima di completare tutti i parametri applicativi, controllare la
|
||||
macchina e la directory privata già preparata:
|
||||
|
||||
```bash
|
||||
tht installation preflight --directory /percorso/installazione --json
|
||||
```
|
||||
|
||||
Servono Docker Linux raggiungibile, Compose 2.24 o successivo, almeno 2 CPU,
|
||||
4 GiB assegnati a Docker e 10 GiB liberi nella directory di installazione. Il
|
||||
rilascio può richiedere risorse maggiori. Su Windows eseguire il binario Linux
|
||||
in Ubuntu WSL2 con integrazione Docker Desktop; Pi è incluso nell'immagine core.
|
||||
|
||||
Al passo 5, dopo `installation validate`, selezionare il manifest del rilascio
|
||||
pubblicato, con le risorse del bundle già scaricate, e produrre un piano nuovo:
|
||||
|
||||
```bash
|
||||
tht --installation /percorso/installazione/thothii-installation.yaml installation plan \
|
||||
--workspaces /percorso/workspaces \
|
||||
--release /percorso/rilascio/release-manifest.json \
|
||||
--output /percorso/installazione/installation-plan.json --json
|
||||
```
|
||||
|
||||
Il comando ripete i controlli dei documenti, verifica immagini/digest e Compose,
|
||||
Git, database ed Evidence esterne disponibili, poi salva il piano e il suo file
|
||||
privato `.key`. Non esegue il setup. Le immagini assenti e le dipendenze esterne
|
||||
irraggiungibili bloccano il piano. Al momento la pubblicazione reale Docker Hub
|
||||
è ancora il ticket successivo: un manifest inventato non permette di aggirarla.
|
||||
|
||||
Correggere gli esiti `error`; leggere gli `warning`. Gli esiti
|
||||
`deferred-to-runtime` identificano controlli obbligatori dopo l'avvio, non una
|
||||
readiness già ottenuta. Un piano valido non sostituisce questi gate. Dopo una
|
||||
correzione o rotazione di credenziali produrre un nuovo piano; i file esistenti
|
||||
non vengono sovrascritti. Conservare piano e chiave fuori dal Git dei workspace.
|
||||
Le prove esterne sono letture limitate: autenticazione/schema del database,
|
||||
letture Git e HTTP/S3, raggiungibilità degli endpoint modello espliciti. Nessuna
|
||||
generazione LLM viene invocata; le richieste HTTP/S3 possono avere i normali costi
|
||||
del servizio. Limiti, manifest e obblighi sono nel
|
||||
[riferimento di preflight](installation-preflight.md).
|
||||
|
||||
## Prima di iniziare: i due repository
|
||||
|
||||
Servono due repository distinti:
|
||||
|
||||
Reference in New Issue
Block a user