Skip to content

Add building, rack, and group targets to curtailment #909

Description

@negarn

🤖 Updated by Negar's AI agent.

Summary

Add Buildings, Racks, and Groups to the shared Apply to targeting used by:

  • Energy → New curtailment
  • Settings → Create/Edit response profile

Each curtailment or response profile has exactly one terminal miner scope. The
backend resolves that logical selector against current topology; the browser
does not expand topology selections into miner snapshots.

Source of truth

The curtailment building, rack, and group targets plan
defines the detailed behavior, security boundaries, rollout, and verification.
PR #926 updates the plan and
contract foundation to the single-terminal-scope model. The plan is
authoritative if this tracker and the plan differ.

Exact target-builder interactions and presentation will follow the pending
design without changing these semantics. This issue tracks the implementation
PRs; merging the plan or contract foundation does not complete the feature.

Required behavior

  • Represent exactly one terminal miner-scope type: Whole organization, Sites,
    Buildings, Racks, Groups, or explicit Miners.
  • Allow multiple IDs within the selected type, with deterministic
    deduplication. Reject mixed scope types and Whole organization combined with
    a narrower selector.
  • Reuse Schedules picker and filtering behavior for both curtailment modal
    variants. Navigation ancestors constrain child catalogs but are not submitted
    as additional targets. Changing the terminal type replaces the prior miner
    scope.
  • Keep Schedules' existing multi-type union semantics; only picker behavior is
    shared with curtailment.
  • Keep Infrastructure as an independent facility-fan selection that never
    contributes miners.
  • Use the same canonical terminal scope for validation, confirmation copy,
    Preview, Start, profile save/reload/edit/test, automation, active events, and
    history. Unsupported or missing typed scopes must never fall back to Whole
    organization.
  • Preserve logical topology selectors in response profiles so later manual and
    automated executions resolve current topology.
  • Apply Target all paired miners to FULL_FLEET with any terminal scope type.
    Unpaired miners may belong to site/building/rack/group selectors and can be
    admitted when they become paired.
  • Preserve the execution semantics from the plan:
    • Non-FULL_FLEET events resolve once and freeze concrete targets.
    • Unflagged FULL_FLEET events follow topology selectors; explicit miner IDs
      remain Start-time snapshots.
    • Flagged FULL_FLEET events follow their persisted terminal selector,
      including explicit miner identifiers.
  • Never directly release a miner that may have received a Curtail command.
    Retain it as an owned restore obligation until safe restoration is confirmed.
  • Persist executable selectors separately from authorization envelopes.
    Validate selected resources, members, facility fans, current principal
    permissions, and admin-only controls where required.
  • Revalidate current topology and authorization immediately before every
    physical Curtail send so a post-claim move cannot broaden execution.
  • Bound selector input, expanded targets, and active watchers as specified by
    the plan; fail closed before over-limit work is persisted or dispatched.
  • Remove the unused generic ScopeDeviceSets message and fields and reserve
    their protobuf names/tags. There is no legacy client or stored-record
    compatibility path.

Staged rollout

  • Contract, validation, persistence, and backend resolution may land before the
    final drill-down UI.
  • Until the UI can rehydrate topology terminal scopes, topology-scoped profiles
    remain visible but read-only in Settings and are excluded from the New
    curtailment profile selector.
  • No intermediate adapter may convert an unsupported topology profile to Whole
    organization. Editing, testing, or execution that cannot preserve its typed
    scope must fail closed.

Implementation areas

  • Canonical frontend terminal-scope model, request/hydration adapters,
    confirmations, summaries, and shared drill-down UI.
  • Typed protobuf/domain/JSON scope contracts and generated code.
  • Backend validation, single-type resolution, cooldowns, authorization,
    persistence, event rendering, and lifecycle handling.
  • Response-profile revisions, authorization envelopes, automation bindings,
    and stale-resource recovery behavior.
  • Closed-loop reconciliation, reservations, pairing/topology transitions, fan
    sequencing, dispatch-time checks, quotas, and safe restoration.
  • Fail-closed deployment gate and the frontend, backend, integration, and E2E
    coverage defined in the plan.

Acceptance criteria

  • Buildings, Racks, and Groups work in both Apply-to flows as a single terminal
    scope; multiple IDs of that type are supported, and parent selections remain
    navigation-only.
  • Schedules retains its existing union behavior while sharing reusable picker
    and filtering components.
  • Preview, Start, profile save/reload/edit/test, and automation preserve and
    resolve the same canonical terminal scope.
  • Confirmation and summary copy describe only the submitted terminal scope.
  • Normal and FULL_FLEET membership behavior matches the plan, including
    pair/unpair and topology transitions.
  • Empty, unknown, deleted, wrong-type, cross-org, unauthorized,
    infrastructure-only, stale, mixed-type, and over-limit scope cannot widen to
    Whole organization or dispatch commands.
  • During staged rollout, unsupported topology profiles remain read-only and
    excluded from execution selectors rather than being reinterpreted.
  • Authorization envelopes cannot be interpreted as executable selectors, and
    topology or permission races fail closed before dispatch.
  • Dispatched miners remain owned through confirmed fan-aware restoration when
    they leave scope or authorization.
  • Required contract, persistence, reconciliation, authorization, regression,
    and E2E tests pass.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions