Files
vantage-shared/CLAUDE.md
T

5.1 KiB

vantage-shared

The private Go module every Vantage service imports. Extracted from the vantage monorepo with its history.

vantage-shared/
├── grpc/pb/                    # the agent↔control-plane wire types, hand-written
├── grpc/codec/                 # the JSON codec they travel over
├── proto/vantage/v1/           # vantage.proto — documentation for the above
├── mail/                       # the one email system: transport + templates
├── license/                    # payload, sign, verify, trusted keys, plans
├── models/                     # Instance, User, Settings
├── provision/                  # slug rules, reserved names, instance/user creation
├── backup/                     # dump, restore, verify, manifest, fingerprint
├── cryptobox/                  # the single AES-256-GCM implementation
├── indexes/                    # users.email and instances.slug
└── cmd/lkctl/                  # issue and inspect licences by hand

Module path is gitea.hostxtra.co.uk/vantage/vantage-sharedlowercase vantage, though the Gitea org is canonically Vantage. Gitea serves both spellings; Go module paths are case-sensitive strings, and two spellings would cache as two modules. Keep the lowercase one.

Who depends on this, and when they find out

Repository Modules A change here reaches them
vantage server, agent, vantagectl server at the next push to main after a pin bump; agent and vantagectl only at their next release tag
vantage-admin server at the next push to main after a pin bump
vantage-site server at the next push to main after a pin bump

Nothing bumps a pin automatically. A fix here is live nowhere until each consumer's go.mod moves, and nothing in any of those repositories will remind you. That is the trade this split made: a service can no longer be shipped against a version of this module it was never built against, and in exchange the staleness is now silent rather than impossible.

Tag a release when you change anything: git tag v0.2.0 && git push origin v0.2.0. Consumers pin exact versions.

proto/ is documentation, not a generator input

grpc/pb is hand-written JSON-tagged structs over the codec in grpc/codec. Nothing generates them, and vantage.proto is not compiled by any build. It is the readable statement of the wire contract, and it lives in the same repository as the Go types precisely so that a message added to one can be added to the other in the same commit — that co-location is the only thing enforcing the match, so do not split them again.

There used to be two copies of pb, in the agent and the server, and they had already drifted: the agent's UnimplementedVantageServer was three methods stale and carried no ReportWorkloads at all. One package now serves both sides. The agent links the server half as dead code, which the linker drops.

A wire change lands in three steps, in this order: release this module, bump the pin in vantage/server (live at the next push to main), bump the pin in vantage/agent (live only at the next agent/v* tag). The control plane will be ahead of the fleet in between, which was true before too — it is just written down in two go.mod files now instead of implied by a shared directory.

Things that mirror something outside this repository

These cannot be enforced by the compiler and must be changed by hand, in step with a file in another repository:

  • backup.ciphertextFields names each collection's *_enc fields and mirrors server/internal/models in the vantage repository, which this module cannot import. Wrong field names fail silently: verify's live probe finds no ciphertext and reports "this database stores no ciphertext yet", so the one gate that catches what a key fingerprint cannot becomes a no-op. settings is deliberately in neither that map nor CiphertextCollections() — its ESO read token is a SHA-256 hash, not ciphertext.
  • mail/templates/layout.html.tmpl carries the control plane's dark theme values as literal hex. Email clients support neither var() nor a reliable prefers-color-scheme, so the token indirection the four front ends use is not available here. Every colour in the email system is in that one file. The tokens it mirrors live in vantage-site.
  • provision is the single implementation of the slug rules that both the control plane and Vantage HQ depend on. It is the one place those two repositories must agree on behaviour, which is why it is here rather than copied — but it now also means a change to it is a release and two pin bumps.

mail/render_test.go renders every template and fails if one exists that no case covers. The templates are parsed in init(), so without that test a mistyped field is a boot-time panic in three services.