Skip to content

Graceful provider wind-down: drain existing contracts, block renewals, notify & migrate users #281

Description

@rosarp

Motivation

When a provider operator wants to stop offering storage, they should be able to wind down gracefully rather than abruptly: stop taking new customers, stop renewing existing contracts, and give existing users a clear path off the provider — a heads-up in the UI plus help moving to a comparable provider.

The pieces for "stop new / stop renew" mostly exist on-chain, but there's no single wind-down flow, no user-facing notification, and no migration path.

Scope note: this is the economic/business wind-down. Process-level clean shutdown (SIGTERM, drain, flush) is #258; data-transfer mechanics are #65 §4. This issue coordinates them from the operator/user perspective.

Desired behavior

  1. No new users — a draining provider accepts no new primary/replica agreements.
  2. No renewals — existing agreements run to term, then lapse; no extensions.
  3. Notify users — drive-ui / s3-ui show existing owners their provider is winding down, with the effective end date.
  4. Migrate users — users are offered and helped to move their drive/bucket to a similar available provider.

Current state

  • (1) No new users — done. accepting_primary (pallet/src/lib.rs:536, enforced impls/agreements.rs:199); ensure_provider_active (impls/providers.rs:12); discovery skips de-registering providers (impls/marketplace.rs:19-23); provider-node rejects with ProviderDeregistering (api.rs:942); provider UI toggle (provider/src/pages/Registration.tsx:953-980).
  • (2) No renewals — primitive exists, not wired. Global accepting_extensions (lib.rs:540/1877) + per-bucket set_extensions_blocked. But per-bucket block is not in the provider UI, and there's no single action.
  • (3) Notify users — missing. UIs read accepting flags only for the create-time picker; no banner on an existing drive/bucket, despite provider-node exposing de-registering (api.rs:209).
  • (4) Migrate users — missing. No "move drive/bucket to another provider" flow; client/src/storage_user.rs:117-141 (upload_replicated) is a logging stub.

Key gap / design question

De-registration requires committed_bytes == 0 before it can be announced (lib.rs:1164-1167) — there is no "draining" state where existing agreements stay live and lapse naturally. Parts (2)–(4) need this. Evaluate (overlaps #107): add a distinct draining state, or relax deregister_provider with live agreements (new commitments + extensions stay blocked).

Proposed work (slices)

  • Chain: drain-down state so a provider stops new + renewals while existing ag.
  • Provider UI: single "Begin graceful shutdown" action; expose per-bucket block_extensions and cancel_deregister.
  • User UIs: banner on drives/buckets whose provider is draining, with effectivr_at + deregistering).
  • Migration: turn the upload_replicated stub + replica-sync into a real "migrate to a similar provider" flow using query_find_matching_providers. Depends on Robust Syncing Protocol for Dynamic Primary and Replica Node Topologies #65 §4.

Related

#107 (deregistration design) · #258 (process-level shutdown) · #65 §4 (provider migration) · #80 (2-step deregister foundation) · #191 (closed; deregister button)

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions