---
name: saas_subscription_audit
description: "Audit software subscriptions end to end: build the full inventory from billing, contracts, and login records, find unused seats and duplicate tools, track the real decision deadline for every renewal, and produce a cut list ranked by saving against pain. Use when someone asks what they are paying for, wants to cut SaaS spend, suspects unused seats or duplicate tools, got surprised by a renewal, or needs a subscription inventory before budgeting."
---

# SaaS Subscription Audit

## Purpose

Software spend leaks in predictable places: seats bought for people who left, tools replaced but never cancelled, trials that converted, and contracts that renewed because nobody tracked the notice date. Industry research puts average license use near half of what organizations provision, but that number is context only. An audit earns its keep from the inventory in front of it, not from benchmarks.

This skill runs the audit as a method, not a one-off spreadsheet cleanup: reconcile four sources into one inventory, check usage against seats, group tools by the job they do so duplicates surface, compute a decision deadline for every contract, and rank every cut by annual saving divided by the pain of making it. The output is a decision list a person can act on, ordered so the biggest, easiest savings come first and anything risky is flagged instead of cut blind.

## Workflow

1. **Build the inventory from records, not memory.** Pull four sources and reconcile them into one CSV: finance and card statements for every recurring charge, contracts or order forms for terms, single sign-on or identity provider logs for who can access what, and each app's admin console for seat and activity data. A charge with no contract and no sign-on record is a shadow purchase: log it, name an owner, and treat it as a finding, not an error. Use the column format in `references/sample-inventory.csv`: tool, function, owner, billing, amount, seats_paid, seats_active, last_used_days_ago, renewal_date, notice_days, criticality, pain_to_cut, background.

2. **Normalize every cost to annual.** Monthly times 12, annual as-is, quarterly times 4. Seat counts, renewal dates, and notice periods come from the contract or admin console. If a field cannot be verified, leave it blank and mark the row partial. Never fill a gap with a plausible number.

3. **Check usage against seats.** Follow the evidence order in `references/usage-check-workflow.md`: admin console export, sign-on logs, HR roster cross-check, owner attestation last. For each tool, compare paid seats with people active in the last 90 days. The usual gaps are former employees still holding licenses, contractors whose work ended, seats bought for hires that never happened, and premium tiers assigned to people who never use the premium features. Record unused seats and their annual cost per tool. Do not call a seat future capacity unless someone names who needs it and when.

4. **Apply the 90-day test, with one exception.** A tool with no active seats, or no use in 90 days, is a cut candidate. The exception is background software: automation, sync, backup, and integration tools may show no direct logins while doing real work every day. Mark those rows background in the inventory. They get checked for what they connect to and what data they hold, never cut on login data alone.

5. **Group by function to find duplicates.** Sort tools by the job they do, in plain words: project management, team chat, design, CRM. Two tools in one group means one migration decision, not two keep decisions. The tool with more active seats is the default keeper. Record why the other one exists before recommending a cut, because sometimes the second tool serves a different team with a real need.

6. **Compute the decision deadline for every contract.** The renewal date is not the deadline. The deadline is renewal date minus notice days, pulled from the contract text. Many contracts need written notice 30, 60, or 90 days before term end, so a contract that renews in November may have been decided in September. Set review lead time by size: largest contracts 120 to 180 days before the deadline, material contracts at least 90 days, small card-paid tools 30 days.

7. **Run the calculator.** Run `python3 scripts/audit.py inventory.csv --as-of YYYY-MM-DD`. It prints total annual spend, identified saving, the cut list ranked by saving per point of pain, decisions due within 90 days, and flagged rows. Use `--format json` when the result feeds a report, calendar, or tracker. Check the flagged section by hand before anything else: those are the cuts that could break work.

8. **Score pain honestly.** pain_to_cut is 1 to 5: 1 means nobody notices, 3 means a team migrates data or changes a habit, 5 means contracts, compliance, or live customer work depends on it. Pain is scored by the tool's owner, not by the person running the audit. A high-saving, low-pain cut goes first. A high-saving, high-pain cut goes on the plan with a migration date, not on this week's list.

9. **Add the labor cost before comparing tools.** Invoice price is not total cost. For tools that survive the cut, note monthly admin, integration upkeep, and duplicate-data handling hours, priced at one internal hourly rate used across the whole audit. A cheap tool that eats eight hours a month can cost more than the expensive one it was meant to replace. Show the arithmetic when this flips a decision.

10. **Recommend, do not execute.** The audit produces decisions for a person to approve. Cancellations, downgrades, and vendor messages are drafted and wait for approval. Re-run the audit quarterly, and re-check seats before every decision deadline, because a clean inventory goes stale within one hiring round.

## Output Contract

Every audit produces:

- The inventory table: one row per tool with annual cost, paid and active seats, unused seat cost, last use, renewal date, decision deadline, owner, and verdict.
- A totals line: total annual spend and total identified saving, with saving split into full cuts, consolidations, and seat downgrades.
- The cut list ranked by saving per point of pain, each entry with verdict, annual saving, pain score, and the one-line reason.
- A decisions-due list: every contract whose decision deadline falls within 90 days, plus any deadline already passed, marked overdue with its next step.
- A flagged list: critical tools that look idle and background tools with no direct use, each with what must be verified before any decision.
- A shadow purchase list: every charge found in billing with no contract or sign-on record, with owner and next step.

## Operating Rules

- Savings figures come only from the inventory's own numbers, computed by the tool or shown as arithmetic the reader can check. Industry waste percentages are context for why audits matter, never a savings claim for this stack.
- The contract text is the source of truth for notice periods, renewal terms, and seat entitlements. Vendor summaries and invoices do not override it. Unverified fields stay blank and get named as gaps in the report.
- Never recommend cutting a tool that holds the only copy of data, runs live automations, or is another team's working system without flagging the dependency first. Flagged means a person verifies it before it joins the cut list.
- Active use is measured in the window that fits the tool: 90 days for daily and weekly tools, a full cycle for monthly reporting or annual compliance tools. State the window used for any tool judged on a longer cycle.
- Keep credentials, card numbers, and contract documents out of the inventory. The inventory is an operational list with tool names, owners, costs, and dates, nothing more.
- If usage data cannot be obtained for a tool, say so and base the verdict on owner attestation, labeled as attested rather than measured. Do not present an attested verdict with the same confidence as a measured one.
