Skip to content

ADR: Fleet Store & Control-Plane State Ownership - #18

Open
brettchien wants to merge 2 commits into
mainfrom
adr/fleet-store
Open

ADR: Fleet Store & Control-Plane State Ownership#18
brettchien wants to merge 2 commits into
mainfrom
adr/fleet-store

Conversation

@brettchien

Copy link
Copy Markdown
Contributor

Summary

Introduces the Fleet Store ADR — a backend-agnostic, durable source of truth for control-plane state that no runtime platform can hold (fleet membership, owner, TTL, lease, fencing epoch, the identity_verified latch), owned by a single long-running controller as sole writer, with file / S3 object as the reference backend and optimistic epoch-CAS for correctness.

Why

ADR-2 gave a stateless read/write model projected live from ECS. That leaves identity_verified only approximated from ECS lastStatus (→ false Unhealthy for chat-native agents), and owner / TTL / lease / fencing epoch with no home. This ADR gives them one.

Position in the stack

  • Builds on: ADR-1 (agent-lifecycle), ADR-2 (deployment-control-plane)
  • Enables: ADR-4 (reconcile loop), ADR-3 (per-caller authz), and a future ephemeral instances + reaper ADR

Status

Proposed (draft) — reviewers TBD (Mira / Jellyfish / Falcon). Deferred by design: reconcile algorithm & reaper triggers (ADR-4), per-caller authz (ADR-3).

Drafted by Orca (ecs-claude) from the design thread, for @brettchien.

brettchien pushed a commit that referenced this pull request Aug 13, 2026
…slice 2)

Declarative Fleet→managing-credential bindings, and the switch that makes a
bound cluster's calls run under its credential instead of the ambient [default].

- studio-cp: `FleetBinding` / `FleetBindings` (serde), `default_bindings_path`
  ($OAB_FLEETS_CONFIG, else ~/.config/oab-studio/fleets.toml), `load_bindings`
  (missing file => empty, opt-in), `resolve_binding_config` (profile-first +
  optional region, layered on the standard chain).
- oab-mcp: loads bindings at startup; `aws_for(cluster)` resolves the bound
  config once (memoized) and every deploy_* tool now switches through it,
  falling back to the default chain when no binding governs the cluster.
  `runtime_context` takes an optional cluster and reports the binding in effect.

Profile-first per the agreed slice-2 scope; assume-role and the IdentityMismatch
reconcile flag are later slices. Binding config is operator-side selection, kept
separate from the Fleet Store (#18) observed/lease state.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
brettchien added a commit that referenced this pull request Aug 13, 2026
…slice 2) (#21)

Declarative Fleet→managing-credential bindings, and the switch that makes a
bound cluster's calls run under its credential instead of the ambient [default].

- studio-cp: `FleetBinding` / `FleetBindings` (serde), `default_bindings_path`
  ($OAB_FLEETS_CONFIG, else ~/.config/oab-studio/fleets.toml), `load_bindings`
  (missing file => empty, opt-in), `resolve_binding_config` (profile-first +
  optional region, layered on the standard chain).
- oab-mcp: loads bindings at startup; `aws_for(cluster)` resolves the bound
  config once (memoized) and every deploy_* tool now switches through it,
  falling back to the default chain when no binding governs the cluster.
  `runtime_context` takes an optional cluster and reports the binding in effect.

Profile-first per the agreed slice-2 scope; assume-role and the IdentityMismatch
reconcile flag are later slices. Binding config is operator-side selection, kept
separate from the Fleet Store (#18) observed/lease state.

Co-authored-by: Orca (ecs-claude) <orca@ecs.local>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
brettchien added a commit that referenced this pull request Aug 14, 2026
…store) (#39)

Wire a Start/Stop action per deployment row to the sidecar's existing
`deploy_scale` MCP tool. Stop = scale→0, Start = scale→1 (ADR-2 §5 write
model): the Spec is kept by ECS at desiredCount 0, so it's reversible and
needs no durable state store (ADR-4 / Fleet Store #18 not required).

- render.ts: one contextual action button per row — Start when a deployment
  is off (desired 0), Stop when on. Carries name + namespace via data-* (the
  service is oab-{namespace}-{name}; the managing credential is per-cluster,
  so the row needs no cluster).
- source.ts: `scaleDeployment(name, size, namespace, cluster?)` on the Source
  contract; Tauri impl invokes `deploy_scale`, mock no-ops (browser preview).
- main.ts: delegated roster listener. Start executes on click; Stop is
  disruptive so it arms on the first click and executes on a confirming second
  click within 3s — webview-safe, no dialog plugin. On success tick() re-renders.
- src-tauri: `deploy_scale` bridge command (mirrors fleet_config_write), passes
  namespace explicitly so prod services resolve (handler defaults to "default").
- styles + tests.

Note: namespace MUST be sent — the MCP handler defaults it to "default", which
would target oab-default-{name} instead of the real oab-prod-{name}.

Verified: console typecheck + 34 vitest + vite build green. The Rust bridge is
compiled by CI's macOS `tauri build` (desktop.yml). Live click-test needs the
macOS app.

Co-authored-by: Orca (ecs-claude) <orca@ecs.local>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Align ADR "Fleet Store & Control-Plane State Ownership" with Brett's
2026-08-11 unified-fleet decision (one kind = Fleet; singleton = size-1
fleet; identity/credential at the instance layer):

- §3.4: collapse the schema to two tiers — fold ADR-2's separate Deployment
  desired-spec onto the Fleet; Instance is the unit. Call out identityPolicy
  (pinned vs ephemeral) as the real axis.
- §3.5: add "namespace is the implicit fleet" + policy cascade, and the
  reaper-safety hard rule (namespace-fleet defaults no-reap/pinned; reaper
  acts strictly per-instance identityPolicy, never namespace-wide — so it
  can't take down resident pinned agents like orca/mira).
- §3.6 (new): document the alignment + that this amends ADR-2's vocabulary.
- §3.2: port ops now speak Fleet/Instance, not Deployment.
- Fix a pre-existing dangling code fence at EOF.

Still Proposed (draft) — pending accept.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant