Files
harmony/docs/reference/fleet-score-references.md
2026-07-15 17:55:48 -04:00

109 lines
4.1 KiB
Markdown

# Fleet Score references
Fleet is the first application of [ADR-028](../adr/028-typed-score-references.md).
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:
```bash
./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:
```rust
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
[![PostgreSQLScore passes PostgreSQLRootAccountRef to ZitadelScore, composing identity functionality.](../diagrams/fleet-identity-composition.svg)](../diagrams/fleet-identity-composition.svg)
### Messaging functionality
[![NatsScore and NatsAuthCalloutScore exchange typed Refs, composing authenticated messaging.](../diagrams/fleet-messaging-composition.svg)](../diagrams/fleet-messaging-composition.svg)
The bidirectional messaging relationship is still declarative: constructing
either Ref does not require its target to exist.
## Complete reference
[![Fleet functionality, exported Ref types, and consuming Score types.](../diagrams/fleet-score-references.svg)](../diagrams/fleet-score-references.svg)
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:
1. A configured deployment runs as
`./harmony-fleet-deploy ship --context prod`.
2. 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.
3. `harmony-fleet-deploy` contains only context loading, configuration,
component declarations, Ref wiring, and interpretation.
4. Each migrated Ref removes the string or cache contract it replaces.
5. Constructing and passing Refs performs no I/O and implies no execution order.
6. Production and E2E compose the same Score and Ref APIs.
7. No generic graph, scheduler, or convergence mechanism is added as part of
ADR-028.