Skip to content

feat(deployment): display lease reclamation state & deadline#3277

Open
baktun14 wants to merge 5 commits into
mainfrom
feat/deployment-display-lease-reclamation-state
Open

feat(deployment): display lease reclamation state & deadline#3277
baktun14 wants to merge 5 commits into
mainfrom
feat/deployment-display-lease-reclamation-state

Conversation

@baktun14
Copy link
Copy Markdown
Contributor

@baktun14 baktun14 commented Jun 5, 2026

Why

After the v2.1.0 network upgrade (AEP-82 resource reclamation), a provider can reclaim a lease: it enters a new reclaiming state with a bounded deadline, and if the tenant doesn't act the lease closes and the group is paused. Today deploy-web has no concept of this — it treats every non-active lease as a generic closed lease, so a tenant can't see that a deployment is being reclaimed, can't see the deadline, and can't tell a provider reclamation apart from their own close.

Closes CON-289
Part of the v2.1.0 network upgrade; folds in CON-376 (honor paused groups, no auto-restart).

What

Scope: deploy-web only. No backend/indexer work — reclamation data comes straight off the chain lease query (/akash/market/v1beta5/leases/list, which already returns the v1 Lease). The reclamation field is optional, so pre-2.1 leases render exactly as today.

  • Data/DTO: optional reclamation + "reclaiming" state on RpcLease/LeaseDto; mapper copies reason/closedOn/reclamation.
  • reclamationUtils.ts (new, single source of truth): close-reason classification (tenant/provider/network/unknown) + human labels, deadline parsing, and isReclaiming/isLeaseLive/isProviderReclaimed. "Reclaimed" requires reclamation evidence (reclamation.startedAt > 0 or group.state === "paused"), not a provider-range close reason alone.
  • ReclamationBanner (new): top of DeploymentDetail while ≥1 lease is reclaiming — live countdown to the nearest deadline + redeploy CTA.
  • ReclamationCard (new): per-lease, terminal reclaimed case — Close (recover escrow) + Redeploy; no restart (reclamation is terminal).
  • List/detail wiring: amber reclaiming status pill, a "Reclaiming" chip + "closes in Xh" countdown and a close-reason badge in DeploymentListRow (revives the previously-unreachable "all leases closed" cell), workload tools stay live during the grace period, and the detail page no longer bounces an all-paused deployment to bid selection.

Tests

New unit specs for reclamationUtils, StatusPill, ReclamationBanner (fake-timer countdown incl. past-deadline and no-deadline), ReclamationCard (Close/Redeploy + new-SDL fallback), and the DeploymentListRow close-reason label. tsc, http-sdk validate:types, and lint all pass.

Not yet verifiable (mainnet upgrade ~Jun 11)

Exact REST casing of the reclamation fields and the deadline unit (assumed unix seconds), and whether the chain auto-closes an all-paused deployment.

Summary by CodeRabbit

  • New Features

    • New reclamation UI: banners and cards with live countdowns, “Redeploy” links, and a “Close (recover escrow)” flow.
    • Deployment rows and lease chips now show a distinct “Reclaiming” status/badge and improved closed-reason labels.
    • Live-lease detection updates affect displayed cost/GPU and tab availability.
  • Bug Fixes

    • Refined no-lease redirect: active deployments in paused/reclaimed group states no longer force “create leases” redirects.
  • Chores

    • Lease data now includes reclamation and close-reason details.
  • Tests

    • Added comprehensive tests for reclamation UI and utilities.

Surfaces AEP-82 provider reclamation in deploy-web: a top-of-detail
ReclamationBanner with a live countdown while a lease is reclaiming, a
per-lease ReclamationCard (Close + Redeploy) for the terminal reclaimed
case, an amber Reclaiming chip/status, and a close-reason badge on all
closed leases (reviving the previously-unreachable 'all leases closed'
cell). Reclamation data comes straight off the chain lease query; the
field is optional so pre-2.1 leases render unchanged.

Folds in CON-376 (honor paused groups, no auto-restart).

Closes CON-289
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 5, 2026

Need the big picture first? Review this PR in Change Stack to see what changed before going file by file.

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 67679858-6176-4c0a-9452-a393449674d4

📥 Commits

Reviewing files that changed from the base of the PR and between a1f4926 and 844d452.

📒 Files selected for processing (1)
  • apps/deploy-web/src/utils/reclamationUtils.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/deploy-web/src/utils/reclamationUtils.ts

📝 Walkthrough

Walkthrough

This PR integrates lease reclamation support into the deploy-web console. It adds reclamation data fields to contracts, implements utilities to classify close reasons and detect reclamation/live states, introduces two new reclamation UI components (banner and card), and wires live-lease and reclaiming logic throughout deployment and lease views.

Changes

Lease Reclamation Support in deploy-web

Layer / File(s) Summary
Reclamation contracts and DTO mapping
apps/deploy-web/src/types/deployment.ts, packages/http-sdk/src/lease/lease-http.service.ts, apps/deploy-web/src/utils/deploymentDetailUtils.ts, apps/deploy-web/src/utils/deploymentDetailUtils.spec.ts
LeaseDto gains optional reason, closedOn, and reclamation fields; RpcLease adds optional reclamation object with timing/reason; LeaseListParams.state filter extends to accept "reclaiming"; leaseToDto maps these new fields and includes tests for reclamation mapping.
Reclamation classification and predicates
apps/deploy-web/src/utils/reclamationUtils.ts, apps/deploy-web/src/utils/reclamationUtils.spec.ts
New utility module exports classifyLeaseCloseReason, getLeaseCloseReasonLabel, getReclamationDeadline, isReclaiming, isLeaseLive, and isProviderReclaimed with comprehensive test coverage for close-reason parsing, deadline conversion, and state detection across all combinations.
ReclamationBanner countdown surface
apps/deploy-web/src/components/deployments/ReclamationBanner/ReclamationBanner.tsx, apps/deploy-web/src/components/deployments/ReclamationBanner/ReclamationBanner.spec.tsx
New component renders warning alerts for reclaiming leases with live countdown to deadline, "closing now" fallback, and redeploy link; includes useCountdown hook and tests for timing, deadline-passed, and no-deadline states.
ReclamationCard close and redeploy actions
apps/deploy-web/src/components/deployments/ReclamationCard/ReclamationCard.tsx, apps/deploy-web/src/components/deployments/ReclamationCard/ReclamationCard.spec.tsx
New component with dependency injection renders provider-reclaimed alerts, confirmation-gated close transaction flow, and conditional redeploy/new-SDL actions; tests verify title rendering, action availability based on local manifest, and callback invocation.
Shared and detail-level live/reclaiming integration
apps/deploy-web/src/components/deployments/DeploymentDetail.tsx, apps/deploy-web/src/components/deployments/DeploymentSubHeader.tsx, apps/deploy-web/src/components/shared/StatusPill.tsx, apps/deploy-web/src/components/shared/StatusPill.spec.tsx, apps/deploy-web/src/queries/useLeaseQuery.ts
Deployment detail routes and tabs now use isLeaseLive instead of direct state checks; renders ReclamationBanner when leases are loaded; StatusPill and subheader derive active/GPU states from live-lease predicates; useLeaseStatus query checks live eligibility; status pill extends to display "reclaiming" state in amber.
Lease row and deployment list reclamation rendering
apps/deploy-web/src/components/deployments/DeploymentListRow.tsx, apps/deploy-web/src/components/deployments/DeploymentListRow.spec.tsx, apps/deploy-web/src/components/deployments/LeaseChip.tsx, apps/deploy-web/src/components/deployments/LeaseRow.tsx
Deployment list rows compute live leases and cost from live subset, display reclamation deadlines using strict time formatting, show closed-reason labels, and render new getClosedLeaseLabel helper with provider-reclaimed override; lease rows conditionally render ReclamationCard; lease chips add "Reclaiming" badge; list-row label tests verify reason classification across scenarios.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested labels

size: M

Suggested reviewers

  • ygrishajev
  • stalniy
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/deployment-display-lease-reclamation-state

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link
Copy Markdown

codecov Bot commented Jun 5, 2026

Codecov Report

❌ Patch coverage is 78.04878% with 27 lines in your changes missing coverage. Please review.
✅ Project coverage is 67.04%. Comparing base (a574181) to head (844d452).
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
...b/src/components/deployments/DeploymentListRow.tsx 14.28% 14 Missing and 4 partials ⚠️
...deploy-web/src/components/deployments/LeaseRow.tsx 0.00% 3 Missing ⚠️
...eb/src/components/deployments/DeploymentDetail.tsx 0.00% 0 Missing and 2 partials ⚠️
...src/components/deployments/DeploymentSubHeader.tsx 0.00% 0 Missing and 2 partials ⚠️
...eploy-web/src/components/deployments/LeaseChip.tsx 0.00% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3277      +/-   ##
==========================================
- Coverage   68.10%   67.04%   -1.06%     
==========================================
  Files        1074     1018      -56     
  Lines       26150    24526    -1624     
  Branches     6246     5933     -313     
==========================================
- Hits        17809    16444    -1365     
+ Misses       7306     7075     -231     
+ Partials     1035     1007      -28     
Flag Coverage Δ *Carryforward flag
api 84.77% <ø> (ø)
deploy-web 52.98% <78.04%> (+0.31%) ⬆️
log-collector ?
notifications 91.06% <ø> (ø)
provider-console 81.38% <ø> (ø) Carriedforward from a1f4926
provider-inventory ?
provider-proxy 86.37% <ø> (ø) Carriedforward from a1f4926
tx-signer 78.37% <ø> (ø)

*This pull request uses carry forward flags. Click here to find out more.

Files with missing lines Coverage Δ
...eployments/ReclamationBanner/ReclamationBanner.tsx 100.00% <100.00%> (ø)
...ts/deployments/ReclamationCard/ReclamationCard.tsx 100.00% <100.00%> (ø)
...ps/deploy-web/src/components/shared/StatusPill.tsx 100.00% <ø> (+33.33%) ⬆️
apps/deploy-web/src/queries/useLeaseQuery.ts 95.55% <100.00%> (ø)
apps/deploy-web/src/utils/deploymentDetailUtils.ts 79.54% <100.00%> (+1.49%) ⬆️
apps/deploy-web/src/utils/reclamationUtils.ts 100.00% <100.00%> (ø)
...eb/src/components/deployments/DeploymentDetail.tsx 0.00% <0.00%> (ø)
...src/components/deployments/DeploymentSubHeader.tsx 0.00% <0.00%> (ø)
...eploy-web/src/components/deployments/LeaseChip.tsx 14.28% <0.00%> (+14.28%) ⬆️
...deploy-web/src/components/deployments/LeaseRow.tsx 0.00% <0.00%> (ø)
... and 1 more

... and 61 files with indirect coverage changes

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/deploy-web/src/components/deployments/DeploymentListRow.tsx (1)

103-103: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Inconsistent lease-status query gating.

The enabled prop uses lease?.state === "active", but useLeaseStatus (in useLeaseQuery.ts line 87) now uses isLeaseLive(lease) in its queryFn. This means the query won't be enabled for reclaiming leases in the deployment list, creating an inconsistency with LeaseRow (line 73), which correctly enables the query for reclaiming leases via isLeaseActive.

For consistency, change the enabled check to use isLeaseLive(lease).

Suggested fix
-  const { data: leaseStatus } = useLeaseStatus({ provider, lease, enabled: !!(provider && lease?.state === "active" && providerCredentials.details.usable) });
+  const { data: leaseStatus } = useLeaseStatus({ provider, lease, enabled: !!(provider && lease && isLeaseLive(lease) && providerCredentials.details.usable) });
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/deploy-web/src/components/deployments/DeploymentListRow.tsx` at line
103, The enabled gating for the lease-status query in DeploymentListRow is
inconsistent: change the enabled prop passed to useLeaseStatus from the current
check using lease?.state === "active" to use isLeaseLive(lease) (keeping the
existing provider and providerCredentials.details.usable checks), so the call
becomes enabled: !!(provider && isLeaseLive(lease) &&
providerCredentials.details.usable); update the import/usage to reference
isLeaseLive and ensure useLeaseStatus continues to be called with provider and
lease.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/deploy-web/src/components/deployments/DeploymentListRow.tsx`:
- Line 307: getReclamationDeadline can still produce Dates from non-finite
numbers (Infinity/-Infinity) which leads to Invalid Date being passed to
formatDistanceToNowStrict; update the guard inside getReclamationDeadline (in
apps/deploy-web/src/utils/reclamationUtils.ts) to reject non-finite values by
using Number.isFinite on the numeric deadline before constructing a Date and
returning null for non-finite values so that the render line using
reclaimDeadline and formatDistanceToNowStrict is never called with an invalid
date.

In `@apps/deploy-web/src/types/deployment.ts`:
- Line 287: Change the Deployment type so its group property is optional to
match runtime behavior: update the declaration of "group: DeploymentGroup" to
"group?: DeploymentGroup" in the type defined in this file; verify related code
paths like the leaseToDto mapper (which can return undefined for group) and
usages such as isProviderReclaimed that already use optional chaining remain
type-safe after the change.

---

Outside diff comments:
In `@apps/deploy-web/src/components/deployments/DeploymentListRow.tsx`:
- Line 103: The enabled gating for the lease-status query in DeploymentListRow
is inconsistent: change the enabled prop passed to useLeaseStatus from the
current check using lease?.state === "active" to use isLeaseLive(lease) (keeping
the existing provider and providerCredentials.details.usable checks), so the
call becomes enabled: !!(provider && isLeaseLive(lease) &&
providerCredentials.details.usable); update the import/usage to reference
isLeaseLive and ensure useLeaseStatus continues to be called with provider and
lease.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: dab0fd2c-647a-400c-99a4-64f2357f01b7

📥 Commits

Reviewing files that changed from the base of the PR and between a574181 and 274747b.

📒 Files selected for processing (20)
  • apps/deploy-web/CONTEXT.md
  • apps/deploy-web/src/components/deployments/DeploymentDetail.tsx
  • apps/deploy-web/src/components/deployments/DeploymentListRow.spec.tsx
  • apps/deploy-web/src/components/deployments/DeploymentListRow.tsx
  • apps/deploy-web/src/components/deployments/DeploymentSubHeader.tsx
  • apps/deploy-web/src/components/deployments/LeaseChip.tsx
  • apps/deploy-web/src/components/deployments/LeaseRow.tsx
  • apps/deploy-web/src/components/deployments/ReclamationBanner/ReclamationBanner.spec.tsx
  • apps/deploy-web/src/components/deployments/ReclamationBanner/ReclamationBanner.tsx
  • apps/deploy-web/src/components/deployments/ReclamationCard/ReclamationCard.spec.tsx
  • apps/deploy-web/src/components/deployments/ReclamationCard/ReclamationCard.tsx
  • apps/deploy-web/src/components/shared/StatusPill.spec.tsx
  • apps/deploy-web/src/components/shared/StatusPill.tsx
  • apps/deploy-web/src/queries/useLeaseQuery.ts
  • apps/deploy-web/src/types/deployment.ts
  • apps/deploy-web/src/utils/deploymentDetailUtils.spec.ts
  • apps/deploy-web/src/utils/deploymentDetailUtils.ts
  • apps/deploy-web/src/utils/reclamationUtils.spec.ts
  • apps/deploy-web/src/utils/reclamationUtils.ts
  • packages/http-sdk/src/lease/lease-http.service.ts

Comment thread apps/deploy-web/src/components/deployments/DeploymentListRow.tsx
Comment thread apps/deploy-web/src/types/deployment.ts Outdated
baktun14 added 4 commits June 5, 2026 20:38
…lease group type

- getReclamationDeadline rejects non-finite deadlines (Infinity) to avoid Invalid Date
- LeaseDto.group is optional, matching leaseToDto (undefined when no group matches)
- ReclamationCard spec uses typed mock proxies (fixes tsc on loose vi.fn overrides)

Refs CON-289
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant