# Contract Settings

**Date:** 2026-06-01
**Status:** Draft
**Spec:** 153
**Tier:** All tiers (template defaults); Business+ (e-signature features)
**Depends on:** `contracts-esignature`, `contract-renewal-amendment`, `foundation-auth-rbac`
**Referenced by:** `contracts-esignature`, `contract-renewal-amendment`

---

## Overview

Spec 48 (`contracts-esignature`) defines contract CRUD, templates, and the full signature lifecycle. Spec 89 (`contract-renewal-amendment`) defines renewal reminders. Neither defines a `/settings/contracts` page for configuring tenant-level defaults: default template, signature workflow defaults, renewal reminder timing, and expiry behavior. This spec fills that gap.

---

## Route

`/settings/contracts` — requires `users:manage`.

---

## Page Layout

```
┌──────────────────────────────────────────────────────────────┐
│  Settings > Contracts                                        │
│                                                              │
│  ┌── Contract Defaults ──────────────────────────────────┐  │
│  │                                                        │  │
│  │  Default contract template                             │  │
│  │  [None (blank) ▾]  <list of tenant templates>         │  │
│  │                                                        │  │
│  │  Default expiry (days from creation)                   │  │
│  │  [365___] days  (0 = no expiry)                        │  │
│  │                                                        │  │
│  └───────────────────────────────────────────────────────┘  │
│                                                              │
│  ┌── E-Signature Workflow  [Business+] ──────────────────┐  │
│  │                                                        │  │
│  │  Default signing order                                 │  │
│  │  ● All signatories at once (parallel)                  │  │
│  │  ○ Ordered — route to next only after previous signs   │  │
│  │                                                        │  │
│  │  Require signatory email verification                  │  │
│  │  ● Yes (signatory must click email link first)         │  │
│  │  ○ No (sign immediately on page load)                  │  │
│  │                                                        │  │
│  │  Signature reminder cadence (after send)               │  │
│  │  First reminder: [3____] days                          │  │
│  │  Follow-up:      [7____] days                          │  │
│  │  Stop after:     [3____] reminders                     │  │
│  │                                                        │  │
│  └───────────────────────────────────────────────────────┘  │
│                                                              │
│  ┌── Renewal Reminders ──────────────────────────────────┐  │
│  │                                                        │  │
│  │  Notify before contract expires                        │  │
│  │  ☑ [30___] days before expiry                          │  │
│  │  ☑ [7____] days before expiry                          │  │
│  │  ☐ [1____] days before expiry                          │  │
│  │                                                        │  │
│  │  Notify channel                                        │  │
│  │  ☑ In-app notification to OWNER + ADMIN                │  │
│  │  ☑ Email to OWNER                                      │  │
│  │                                                        │  │
│  └───────────────────────────────────────────────────────┘  │
│                                                              │
│  [Save changes]                                             │
└──────────────────────────────────────────────────────────────┘
```

---

## Schema Delta

```sql
-- Add expires_at + signing_order to contracts (not present in spec 48 schema)
-- signing_order controls whether all signatories are invited simultaneously or sequentially
ALTER TABLE contracts
  ADD COLUMN IF NOT EXISTS expires_at TIMESTAMPTZ,
  ADD COLUMN IF NOT EXISTS signing_order TEXT NOT NULL DEFAULT 'parallel'
    CHECK (signing_order IN ('parallel', 'ordered'));

ALTER TABLE tenant_settings
  ADD COLUMN IF NOT EXISTS contract_default_template_id UUID REFERENCES contract_templates(id) ON DELETE SET NULL,
  ADD COLUMN IF NOT EXISTS contract_default_expiry_days INTEGER NOT NULL DEFAULT 365
    CHECK (contract_default_expiry_days >= 0),
  ADD COLUMN IF NOT EXISTS contract_default_signing_order TEXT NOT NULL DEFAULT 'parallel'
    CHECK (contract_default_signing_order IN ('parallel', 'ordered')),
  ADD COLUMN IF NOT EXISTS contract_require_email_verification BOOLEAN NOT NULL DEFAULT true,
  ADD COLUMN IF NOT EXISTS contract_reminder_first_days INTEGER NOT NULL DEFAULT 3,
  ADD COLUMN IF NOT EXISTS contract_reminder_followup_days INTEGER NOT NULL DEFAULT 7,
  ADD COLUMN IF NOT EXISTS contract_reminder_max_count INTEGER NOT NULL DEFAULT 3,
  ADD COLUMN IF NOT EXISTS contract_renewal_remind_30d BOOLEAN NOT NULL DEFAULT true,
  ADD COLUMN IF NOT EXISTS contract_renewal_remind_7d BOOLEAN NOT NULL DEFAULT true,
  ADD COLUMN IF NOT EXISTS contract_renewal_remind_1d BOOLEAN NOT NULL DEFAULT false,
  ADD COLUMN IF NOT EXISTS contract_renewal_notify_email BOOLEAN NOT NULL DEFAULT true,
  ADD COLUMN IF NOT EXISTS contract_renewal_notify_in_app BOOLEAN NOT NULL DEFAULT true;
```

---

## Pre-fill Behavior

When opening `/contracts/new`:
- Default template selection from `contract_default_template_id` (if set)
- `contracts.expires_at` pre-filled as `now() + contract_default_expiry_days` (if > 0)
- `contracts.signing_order` pre-filled from `contract_default_signing_order`; controls whether invitation emails go to all signatories at once (`parallel`) or sequentially (`ordered`)

These are pre-fills only — user can override all values per contract.

---

## Renewal Reminder Integration

The renewal reminder cron (spec 89) reads `contract_renewal_remind_30d`, `contract_renewal_remind_7d`, `contract_renewal_remind_1d` to determine which intervals to fire. Channel flags (`contract_renewal_notify_email`, `contract_renewal_notify_in_app`) control delivery.

---

## Non-Business+ Note

E-signature settings section is visible to all tiers but shows an upsell for non-Business+:

```
E-Signature — Business+ feature
Set signing order, require email verification, and configure reminder cadence.
[Upgrade to Business+]
```

Renewal reminders are available to all tiers.

---

## API

```
GET  /api/settings/contracts
     → get contract settings
       Returns: { contract_default_template_id, contract_default_expiry_days,
                  contract_default_signing_order, contract_require_email_verification,
                  contract_reminder_first_days, contract_reminder_followup_days,
                  contract_reminder_max_count,
                  contract_renewal_remind_30d, contract_renewal_remind_7d,
                  contract_renewal_remind_1d,
                  contract_renewal_notify_email, contract_renewal_notify_in_app }
       Requires: users:manage

PATCH /api/settings/contracts
      → update contract settings
        body: { ...any settable fields above }
        Requires: users:manage
```

---

## Architecture Decisions

| Decision | Choice | Reason |
|----------|--------|--------|
| Extend `tenant_settings` | Not new `contract_settings` table | Same scalar-config pattern as other settings specs (125, 148, 151, 152) |
| `contract_default_template_id` FK | `ON DELETE SET NULL` | Deleting a template should not prevent settings from loading; NULL means "no default" |
| Renewal reminder as boolean per interval | Not a single `days_before INTEGER[]` | Three common intervals (30/7/1 days) cover >95% of use cases; boolean flags are simpler to render and query than an array |
| E-sig features gated Business+ | Not all tiers | Consistent with spec 48 which gates e-signature workflow to Business+ |
