Files
harmony/docs/adr/drafts/fleet-cd-pass-lessons.md

42 lines
3.2 KiB
Markdown

# Lessons: Operate / Provision / Release pass
Internal. Not the product spec — that is [fleet-products.md](../../guides/fleet-products.md).
## Mistakes
1. **Coded before the product existed.** Harbor 401, two bots, then kubectl scripts, then a CLI, then the three doors. Each layer papered the last. Reviewers saw a cut, not a 1.0 surface.
2. **Wrong tenant for the work.** Device upgrade was implemented as a DX shell script, then as a Harmony bin that still thought like kubectl. Customers must not reimplement in-cluster ops.
3. **Mixed identities in one process.** `release.sh` built images, pushed Harbor, deployed a tenant crate, and patched Devices. `build-push-operator-and-agent.sh` invoked that from the tenant repo. DX bot pushed `harmony/*`.
4. **Guessed OpenBao paths and JWT roles.** `harmony/harmony-fleet` and default `nationtech-cloud-tenants` were invented in code. Coordinates are product data, not filler.
5. **`--context` as a homonym.** Operate: OpenBao namespace. Provision: compiled `Context` name. Same flag, two types.
6. **Agent pin as three strings.** Release prints `artifactUrl`, `maxBytes`, `sha256`; Operate parses them independently. A mismatched triple is representable. Digests were scraped from `RUST_LOG` stdout with awk.
7. **Operate is kubectl folklore.** `Api<Device>` + JSON merge-patch, not a Score. ADR-023 exception was assumed, not decided.
8. **Junk-drawer crate.** `harmony-fleet-deploy` holds Scores, Release (`harmony-fleet-release`), Operate (`harmony-fleet`), and provision helpers. The Operate bin does not use the lib.
9. **No tests** on the path that replaces a privileged agent binary: `validate_upgrade`, merge-patch shape, `release.sh` rejecting tenant flags, `provision.sh` args.
10. **Cross-compile honesty.** aarch64 artifacts are not `--version`-checked on an x86 host. x86 check is an unanchored glob (`0.6.8` matches `0.6.80`).
11. **Docs lagged SETUP.md** and leftover `harmony-fleet-publish` / `--tag --push` clap.
12. **Shipped the door shape and asked reviewers to bless 1.0.** They correctly said no.
13. **Committed and pushed when the user was asking a question.** Supervisor failed the loop.
## Corrections imposed (this pass)
These are the ones that actually changed the crate. Do not reverse them.
1. **Three jobs, three identities.** Operate / Provision / Release. One process, one key. `--tenant` is an OpenBao path, not provision `--context`.
2. **Domain in the library, clap is a switchboard.** Flags in, `println` out. No tag grammar, digest triples, or patch JSON in `main.rs`.
3. **Types map the problem, they are not SOLID costumes.** `Pin` is the Harbor object. Catalog mints it from `--version`/`--arch`. No `ArtifactCatalog` trait with one impl. No twin `PublishedOperator`/`PublishedCallout`. `ResolvedVersions` is the chosen images, not a pairing invariant.
4. **Simple engineering that maps the space.** Getters, row-beans, and fake ports are fuss. Public fields + constructors + `FromStr`. Run the reviewers; do not infer MERGE. Do not commit when the user is asking.
5. **Operate UX is the product.** This bin defaults to `warn` and keeps `cli_logger`. Junk Harbor tags are silent. Upgrade stdout includes the pin. List tables have headers (`UPGRADE` is the agent-upgrade phase, not reachability).