# Contract Renewal & Amendment

**Date:** 2026-05-31  
**Status:** Draft  
**Spec:** 89  
**Tier:** All tiers  
**Depends on:** `contracts-esignature`, `foundation-auth-rbac`, `audit-compliance`  
**Referenced by:** `contracts-esignature`

---

## Overview

Spec 48 (`contracts-esignature`) covers the initial contract lifecycle: DRAFT→SENT→VIEWED→SIGNED→VOIDED. This spec adds two workflows that follow a SIGNED contract: **renewal** (creating a new contract from an expiring one) and **amendment** (creating a contract revision from an active signed contract).

---

## Data Model

```sql
-- Schema delta on contracts:
ALTER TABLE contracts ADD COLUMN renewed_from_id UUID REFERENCES contracts(id);
ALTER TABLE contracts ADD COLUMN amended_from_id UUID REFERENCES contracts(id);
ALTER TABLE contracts ADD COLUMN effective_date DATE;
ALTER TABLE contracts ADD COLUMN expiry_date    DATE;
```

- `renewed_from_id`: set on a renewal contract, points to the original
- `amended_from_id`: set on an amendment, points to the contract being amended
- `effective_date` / `expiry_date`: optional date range for the contract term (tenant fills in)

No new status values. Renewals and amendments are new `contracts` rows in `DRAFT` status.

---

## Renewal Flow

Triggered from a SIGNED contract detail page when `expiry_date` is set and within 60 days of expiry, OR manually at any time:

### Contract Detail: Renewal Banner

```
┌──────────────────────────────────────────────────────────────┐
│  Service Agreement — Acme Corp                SIGNED         │
│                                                              │
│  ⚠ Expires in 23 days (2026-06-30)                          │
│  [Renew contract]                                            │
└──────────────────────────────────────────────────────────────┘
```

### Renewal Form

```
┌──────────────────────────────────────────────────────────────┐
│  Renew contract                                              │
│  Renewing: Service Agreement — Acme Corp                     │
│                                                              │
│  New contract title  [Service Agreement — Acme Corp 2026___] │
│  New effective date  [2026-07-01]                            │
│  New expiry date     [2027-06-30]                            │
│                                                              │
│  ● Copy content from original                               │
│  ○ Use blank template                                        │
│                                                              │
│  [Cancel]                       [Create renewal draft]      │
└──────────────────────────────────────────────────────────────┘
```

Creates new `contracts` row:
- `content` = copied from original (Tiptap JSONB) with dates updated
- `renewed_from_id` = original contract id
- `status = 'DRAFT'`
- Same customer and signatories as original (copied into new `contract_signatories` rows)

---

## Amendment Flow

Triggered from SIGNED contract detail:

```
┌──────────────────────────────────────────────────────────────┐
│  Service Agreement — Acme Corp                SIGNED         │
│                                                              │
│  [⋯ More actions]                                            │
│  ├ Download PDF                                              │
│  ├ Create invoice                                            │
│  ├ Renew contract                                            │
│  └ Create amendment                                          │
└──────────────────────────────────────────────────────────────┘
```

Amendment form prompts for:
- Amendment title (e.g., "Amendment #1 — Rate Change")
- Content (pre-filled with original, fully editable)
- Effective date

Creates new `contracts` row:
- `title` = amendment title
- `amended_from_id` = original contract id
- `status = 'DRAFT'`
- Same signatories copied

---

## Contract List: Lineage Display

Contract list and detail views show linkage:

```
┌──────────────────────────────────────────────────────────────┐
│  Service Agreement 2026           SIGNED   2026-01-01 → now  │
│    └ Amendment #1 — Rate Change   SIGNED   2026-03-15 →       │
│    └ Renewal 2027                 DRAFT    (pending signature) │
└──────────────────────────────────────────────────────────────┘
```

Grouping: contracts with same customer sorted by `effective_date`; renewals and amendments indented under parent.

---

## Expiry Notifications

Cron: `contract-expiry-reminder` — daily 08:00 UTC. Checks:

```sql
SELECT id, title, customer_id, expiry_date
FROM contracts
WHERE status = 'SIGNED'
  AND expiry_date IS NOT NULL
  AND expiry_date BETWEEN now() AND now() + interval '60 days'
  AND id NOT IN (
    SELECT renewed_from_id FROM contracts
    WHERE renewed_from_id IS NOT NULL
  )
```

Notifies OWNER/ADMIN: in-app notification + optional email (user_preferences notification toggle).

---

## API

```
POST /api/contracts/:id/renew
     → create renewal contract in DRAFT
       body: { title, effectiveDate, expiryDate, copyContent: boolean }
       Requires: contracts:write

POST /api/contracts/:id/amend
     → create amendment contract in DRAFT
       body: { title, effectiveDate, content? }
       Requires: contracts:write

GET /api/contracts/:id/lineage
     → original + all amendments + renewals in chain
       Requires: contracts:read
```

---

## Architecture Decisions

| Decision | Choice | Reason |
|----------|--------|--------|
| Renewals/amendments = new contracts | Not in-place edit | SIGNED contracts are immutable (PDF stored, IL law requires record integrity); new rows preserve the audit trail |
| No new status values | Not 'RENEWED'/'AMENDED' | The original contract stays SIGNED; its relationship to successors is expressed via FK links, not status |
| 60-day expiry window | Not 30-day | IL service contracts typically 30–90 days negotiation; 60 days gives buffer for re-negotiation |
| `expiry_date` added | Not inferred from content | Contract body text is free-form; structured date enables cron queries and UI banners without parsing |
