4.1 KiB
Fleet Score references
Fleet is the first application of ADR-028. Its deployment should read like a declaration of what Fleet needs and how those components connect.
Target experience
Deploying a configured Fleet should require one command:
./harmony-fleet-deploy ship --context prod
The context selects the desired configuration. The command composes the Scores, passes their Refs, and interprets the result. It does not expose the deployment sequence to the operator.
The corresponding Rust should stay close to the same statement:
let postgres = PostgreSQLScore::new(config.postgres);
let zitadel = ZitadelScore::new(config.zitadel)
.database(postgres.root_account_ref());
let nats = NatsScore::new(config.nats);
let callout = NatsAuthCalloutScore::new(config.callout)
.nats(nats.account_ref());
let operator = FleetOperatorScore::new(config.operator)
.identity(zitadel.application_ref())
.messaging(nats.client_ref());
The API names are illustrative. The required shape is a short component declaration followed by typed connections to other components.
How composition works
Identity functionality
Messaging functionality
The bidirectional messaging relationship is still declarative: constructing either Ref does not require its target to exist.
Complete reference
The final map lists each functionality, the Ref types it exports, and the Score types that consume them. The names identify intended contracts. They become public APIs only as implementation replaces the corresponding string wiring; the map does not prescribe a generic Ref hierarchy or registry.
Composition boundary
harmony-fleet-deploy is composition only. It may:
- load the selected context;
- declare component configuration;
- construct Scores;
- connect Scores through typed Refs;
- interpret the composed deployment.
It must not:
- call provider APIs or commands directly;
- build Kubernetes or Helm resources;
- generate credentials or reconstruct provider outputs;
- implement deployment ordering, retries, or readiness checks;
- copy provider URLs, IDs, credential locations, or naming conventions.
All deployment behavior belongs to the Score that owns the component. If a required operation has no Score, the missing work is to add or extend that Score, not to implement the operation in Fleet composition.
Ref behavior
Refs are available from desired state before their resources exist. Passing a
Ref is therefore not a readiness check. Each consuming Score handles an absent
or unavailable target through its own Interpret/Topology path, often by
emitting a native Kubernetes reference.
ADR-028 does not require a particular non-success outcome, retry policy, or continuous convergence mechanism.
Acceptance criteria
Fleet validates this design when:
- A configured deployment runs as
./harmony-fleet-deploy ship --context prod. - Declarations and Ref wiring average at most five non-blank lines per logical component in the canonical Fleet composition. PostgreSQL, Zitadel, each Zitadel application or account, NATS, the auth callout, OpenBao, the Fleet operator, and device enrollment each count as logical components.
harmony-fleet-deploycontains only context loading, configuration, component declarations, Ref wiring, and interpretation.- Each migrated Ref removes the string or cache contract it replaces.
- Constructing and passing Refs performs no I/O and implies no execution order.
- Production and E2E compose the same Score and Ref APIs.
- No generic graph, scheduler, or convergence mechanism is added as part of ADR-028.