# Renewals and contracts

Build the renewal calendar before scoring anything. A correct verdict that arrives after the notice boundary is worthless for another term.

## One record per contract or order

Not per vendor. One vendor can hold several orders with different term ends. Record:

- Legal entity and product.
- Term end and the first day of the next term. A one-day mistake matters at a boundary.
- Payment schedule. Monthly instalments can still pay for an annual commitment.
- Notice days, notice mechanism (account toggle or written notice) and the required recipient as the order describes it. Do not copy notice addresses into shared files; point to the order.
- Pricing basis, reduction rule, discount end, quantities.
- Decision owner and the link to the executed order.

CON01 fails any tool in the top 80% of tool spend whose register lacks term_end, notice_days, notice_mechanism, auto_renew, pricing_basis or reduction_rule. A notice of 0 days counts as present. Monthly tools are exempt; a blank or unknown `billing_period` still needs all six fields. Register dates are YYYY-MM-DD unless `--date-format` says otherwise.

## Date arithmetic

stack_inventory.py uses calendar days only:

- Notice boundary = term end - notice days.
- Decision target = notice boundary - 14 days (`--decision-buffer`).
- Change lead:
  - 30 days for keep, enable or no disposition yet, and for renegotiate or right-size on other tools.
  - 75 days for consolidate, replace, retire or investigate.
  - 75 days for renegotiate or right-size when the tool is in the top 80% of tool spend or CON05 fires (its discount ends within 120 days). A negotiation needs a credible, tested alternative, and that alternative needs as long as a migration estimate. At 30 days the vendor holds the leverage.
  - 120 days instead of 75 when a tool being consolidated, replaced, retired or investigated holds identity, consent or customer-facing automation: `system_of_record_for` is set, or a capability is crm, cdp_event_collection, lifecycle_messaging, marketing_automation_email, consent_management, identity_resolution or warehouse.
  - `change_lead_days` on the register row overrides all of these.
- Migration start = term end - change lead.
- Review-by = the earlier of the decision target and the migration start.
- Buckets from the as-of date: overdue, 0-30, 31-60, 61-90, later.
- CON04 (FAIL): review-by has passed while the notice boundary is still ahead. Decide now.
- CON06 (WARN): the term end is already past, so the register is stale.
- Act now: every CON04 FAIL and every review-by date within 14 days of the as-of date is listed at the top of the output. Tell the user the same day; these cannot wait for the report.
- CON03, CON04 and CON06 print NOT CHECKED when no annual row records both term_end and notice_days, and CON05 when no row records discount_end or pricing_basis. A PASS names how many tools had terms; the rest sit under "Unknown terms" in the calendar.

Fictional check: a CRM term ends 2027-01-15 with a zero-day account toggle and a discount that ends the same day. As a right-size on a top-spend tool its lead is 75 days, so on an as-of date of 2026-11-01 its review-by is 2026-11-01, not the 2026-12-16 a 30-day lead would give. The decision target stays 2027-01-01.

The contract owner confirms inclusive counting, time of day, time zone, business-day rules and what counts as valid notice. The script's dates are planning dates, not legal deadlines.

## Locked renewals

- CON03: the boundary passed and the term is still running. The renewal is effectively locked.
- Plan for the next term: recertify access, ownership and need 120 days before the next term end. The script assumes a one-year renewal; check the order.
- Keep the decision record, even when the decision was "too late this time".
- When auto-renew is off, a passed boundary means the term ends on its date unless someone renews it. Confirm the renewal or exit plan instead.

## Zero-day notice

An account-toggle rule with no notice period still needs an internal decision target, someone with authorised access to the billing page, and a retained confirmation. Put the action in an owned calendar with a backup person. A reminder that goes to a former employee is not a control.

## Public default terms (examples only; the executed order always wins)

Read from the vendors' public terms in October 2026. Re-check at run time and quote the order, not these lines.

- HubSpot: renewal fees can rise to the then-current list price with at least 30 days' notice of the increase. Under the default terms, non-renewal is done by turning off auto-renew in Account & Billing before the term ends, unless the order says otherwise. Using fewer seats, contacts or credits does not downgrade the subscription by itself.
- Salesforce Main Services Agreement: fees follow purchased subscriptions, not use; quantities generally cannot be reduced during the term; the default renewal is another year unless written notice (email counts) arrives at least 30 days before term end; promotional pricing can reset to list, and a smaller renewal can be repriced. The agreement PDF could not be re-read on 2026-11-06, so verify this line against the current agreement before relying on it.
- AppsFlyer: 45-day written non-renewal notice by default; renewal unit fees may rise by up to 7%; a free period does not carry into the renewal. The total can still rise by more than 7% when volume or scope changes.
- Zendesk Customer Agreement: no mid-term plan or pricing-metric reductions; a future reduction needs 30 days' written notice plus removal of the affected agents before the next term.
- Self-serve plans such as Amplitude Plus renew at the then-current fees and are cancelled in the billing page before the term ends. Record who bought it; the original purchaser or an organisation admin may be the only person who can cancel.

## Explaining a renewal increase

Build a bridge from the current payable amount to the proposed amount, changing one driver at a time: discount, unit price, quantity, package, one-time work. State the order of the steps; the final difference does not change.

Fictional example: 50 seats at 100 a seat a month with a 20% introductory discount, renewing as 40 seats at 140 with no discount.

```text
Current: 50 x 100 x 12 x 0.8           = 48,000
Remove the 20% discount                = +12,000 -> 60,000
Unit price 100 -> 140 at 50 seats      = +24,000 -> 84,000
Quantity 50 -> 40 at 140               = -16,800 -> 67,200
Result: the bill rises 40% while seats fall 20%
```

Check the base of any price cap. A 5% cap on the expiring net rate of 80 gives 84; on the old list rate of 100 it gives 105. At 40 seats for a year that is 40,320 against 50,400.

CON05 warns when a discount ends within 120 days, so the decomposition happens before the decision target, not after the invoice.

## Notice drafts

- The agent drafts the notice or the account-toggle instruction. The contract owner sends it, keeps the acknowledgement and checks the next invoice.
- Disabling a workflow is not cancelling a subscription. An unanswered cancellation email, a removed card or an unused account does not end a commitment.
- If a deadline has passed, establish the current obligation before choosing the next step, and route any dispute through the contract process.
