Skip to content

ADR-018: Each product ships its own Compose; the suite retires

Source of truth: docs/adr/018-product-owned-compose.md (synced at build time — edit the original, not this copy). Status: Accepted (2026-10-17). The build is tracked in #1670.

Decision owner: Danny

Amends:

  • ADR-014 Decision 3, its third consequence, Rejected alternative 5 and its 2026-10-15 focused milestone rules. Product repositories ship a supported Compose install again, for VectorFlow and CHAD (to be renamed Sigmatic).
  • ADR-013’s 2026-09-26 amendment, which removed the standalone deployment path from product repositories.

ADR-014 made veltro install the only install path and deleted every product’s own login. A VectorFlow-only or CHAD-only install is Veltro core plus that product, installed through the CLI. That shipped (#1063).

Three things have changed since:

  • The only live installation is one homelab. Nobody else runs the suite.
  • The people VectorFlow and CHAD are for already run OpenSearch and move logs with Vector or something like it. They want one docker-compose.yml per product that they can read and run. The veltro CLI is one more tool between them and that.
  • The suite release train couples every product fix to a suite cut. A product fix becomes installable after merge, a product release, a manual release-suite.yml dispatch and a veltro install --suite-version on the user’s side. No product workflow starts a suite release.

Plain docker compose up can’t work today. start_stack() starts identity alone, projects its public signing ring into .env, then starts the products (cli/veltro_cli/lib/install.py:444-469). _validate_identity() creates the TOTP keyring bind file (cli/veltro_cli/lib/install.py:474-512). Seven identity one-shots run before identity serves (compose/veltro.yml:55-284). The product repositories’ Compose files leave identity out and say they aren’t an install (../vectorflow/docker/server/docker-compose.yml:1-4, ../chad/docker-compose.yml:1-3, ../warden/docker-compose.yml:1-4).

  1. VectorFlow and CHAD each ship a supported docker-compose.yml in their own repository: the product, Veltro identity, the nginx gateway and the product’s datastores. The product pins an identity image version the same way it pins its base images. Users don’t run the veltro CLI to install one product.
  2. One identity authority per stack. Identity keeps sign-in, SSO, SCIM, MFA, PATs, MCP OAuth, grants and audit as they are, and the identity↔product peer contract for status and audit stays (the console Audit page reads a one-product stack over /api/peer/v1/audit). Each product keeps exactly one authentication path, the gateway’s request assertion.
  3. Two products are two independent stacks, each with its own identity. They integrate over a URL and a token: VectorFlow’s http sink to a CHAD push data source, or VectorFlow’s OpenSearch sink to an index a CHAD pull data source reads. The first-class CHAD sink only works inside one stack, because it finds data sources and ingest tokens through that stack’s workload exchange (../vectorflow/src/lib/vector/chad-sink.ts:1-17, ../vectorflow/src/server/services/suite/chad-client.ts:49-98), so it goes when the suite retires.
  4. Identity bootstraps itself on boot: migrations, signing key, authority fence, workload credentials for the installed products, and the TOTP keyring in a volume. That replaces the seven one-shots and the CLI’s .env projection. Products fetch the JWKS from identity over the network. The plan for this settles where products get their workload credentials in plain Compose, how the signing key is stored and rotated, and JWKS fetch retry and issuer pinning, and gets a security review before merge.
  5. Identity gets its own release workflow, tags and image, licensed AGPL-3.0 like the products. Each product pins it, Renovate bumps the pin, and each product’s compose-boot CI gate, on the self-hosted runners, proves the bump. The SDK is Apache-2.0; the two verifier libs are Apache-2.0 following their owner-approved relicensing on 2026-10-18. SDK publishing to PyPI and npm moves to identity’s release workflow when that workflow is created. npm publishing still needs a GitHub-hosted runner, because npm trusted publishing refuses self-hosted OIDC, so it runs when hosted minutes are available.
  6. The suite retires once the homelab runs standalone VectorFlow and CHAD stacks. Until then the suite Compose, the umbrella chart, the veltro CLI, the suite manifest, qualification and the suite release workflow keep working as today. Homelab auto-promotion stays on until the Sigmatic rename starts and is turned off as its first step; after that, suite releases are cut only for fixes and promoted by hand, and the homelab CHAD only gets builds from before the rename. Once the homelab is on standalone stacks, the suite is deleted, and the last commit is tagged suite-final so it can be recovered from git. The CLI retires with it.
  7. The two-products-in-one-stack code is deleted with the suite, after an inventory lists every caller: the first-class CHAD sink with its discovery and ingest-token workload exchange, delivery-time team scoping, cross-product discovery auth, and the bundle side of the manifest and qualification. The peer contract, MCP, grants, SSO, SCIM, MFA and PATs aren’t part of this.
  8. CHAD is renamed Sigmatic everywhere before it goes public: repository, images, chart, docs path, UI strings, the product id in identity and VELTRO_PRODUCTS, the CHAD_* environment variables, the Python package, the index prefixes including chad-percolator-*, the chad_* MCP tool prefix and the gateway path. There’s no migration; the one live CHAD install is rebuilt from scratch.
  9. Hosting isn’t built now. If it happens, it’s isolated per-customer stacks of the same published images (ADR-014 Decision 7), with a thin provisioning layer and entitlement flags the products read at boot. A customer with both products gets one stack with both, rebuilt from suite-final history if there’s demand. The suite was that architecture, built before there was anything to sell.

The fixed path /vectorflow/ stays and the CHAD path becomes /sigmatic/, so ADR-014 Decision 5 still holds: one installed product brands sign-in and the shell, and the plain VectorFlow image stays retired.

  • Someone running VectorFlow and CHAD signs in twice, once per stack, enrols MFA twice, configures two SSO clients and manages users in two places.
  • Cross-stack integration is whatever a URL and a token can carry. Discovery of CHAD data sources from VectorFlow, delivery-time ingest-token lookup and shared team scoping go away.
  • Product CI has to boot the product against a published identity image. Today none does.
  • Helm product charts don’t change until the Compose shape has shipped. The umbrella chart still requires identity and the gateway (charts/veltro/templates/validate-profile.yaml:5-10) until it’s deleted with the suite.
  • veltro-cli stops publishing. ADR-013’s single-CLI operator entry point ends with the suite.
  • Warden is out of scope here. It stays at 0.25.0 and leaves with the suite.

ADR-014 Decision 3 (docs/adr/014-suite-composition-and-packaging.md:50) is reversed for VectorFlow and CHAD:

The Veltro repository is the only install path: veltro install with a product selection for Compose, or the umbrella chart with per-product enabled values for Kubernetes, both through the ADR-013 CLI. Product repositories publish images and their Helm subcharts. Their Compose files serve product CI and development and are not a supported install.

The same goes for its third consequence (docs/adr/014-suite-composition-and-packaging.md:120):

Product repositories stop supporting a deployment without Veltro. Running a product’s own Compose file outside CI is unsupported.

for Rejected alternative 5 (docs/adr/014-suite-composition-and-packaging.md:131), which this ADR takes up for two products instead of four:

Install paths in every product repository. Four install paths drift. The product Compose defaults already lag the suite pins (see Context).

and for the first focused milestone rule (docs/adr/014-suite-composition-and-packaging.md:60-62):

VectorFlow-only and CHAD-only installs require core (identity and gateway) and their own infrastructure, with no sibling-product or Warden requirement. Product selection doesn’t make a release independent of core or its manifest.

Identity still runs in every install. It now ships inside the product’s Compose and releases on its own line.

ADR-014’s one sign-in path per product stands (docs/adr/014-suite-composition-and-packaging.md:118):

One product, two products, or all three install the same way, with one sign-in path per product and no fixed profile matrix.

Only the first half changes: one product now installs from its own repository.

ADR-008 Amendment 10 stands (docs/adr/008-suite-identity-roles-and-principals.md:390-392):

ADR-014 supersedes Amendment 3’s support for product-only Veltro profiles and local product sign-in. A one-product installation includes Veltro identity and its single-origin gateway.

No product gets its local login back. A product’s own Compose includes identity and the gateway, so it meets this amendment as written.

ADR-013’s 2026-09-26 amendment (docs/adr/013-deployment-targets-and-operator-entry-point.md:9-10) is reversed for Compose:

Product repositories keep native development commands but no standalone deployment path.

VectorFlow and CHAD repositories have a supported Compose deployment again, as ADR-013 originally allowed (docs/adr/013-deployment-targets-and-operator-entry-point.md:33):

A product repository can keep native development and standalone deployment commands.

ADR-013’s single-CLI contract and Compose/Helm parity apply to the suite until it retires. They don’t apply to a product’s own Compose.