~/About~/Foundry~/Blueprint~/Journal~/Projects
Book a Call
Foundry

Contract Lifecycle Engine

·9 min read·Kingsley Onoh·View on GitHub

From Signed Contract to Tracked Obligation, Automatically

The Situation

A mid-market company carries somewhere between 200 and 500 active vendor and customer contracts at any time. Master services agreements, SaaS subscriptions, distribution contracts, NDAs, lease agreements. Each one buries payment schedules, renewal notice windows, reporting obligations, SLA commitments, and indemnity deadlines in dense legal prose. Most of these commitments have dates attached. A quarterly compliance report due 30 days before quarter-end. A renewal notice that must be delivered 90 business days before the contract anniversary. A payment obligation that triggers an SLA penalty if it lands more than 5 business days late.

Legal operations teams track these the same way they have for fifteen years: spreadsheets, shared calendars, and someone in the office who "knows the contracts." That person is the single point of failure for every deadline in the organization. When they go on vacation, the renewal notice slips. When they leave the company, six months of institutional knowledge walks out with them.

The industry benchmark for missed contract obligations at this scale is sobering. Mid-market companies typically absorb 5 to 15 percent cost overruns from silently auto-renewed contracts that nobody flagged in time. Renewal notice windows lapse. Price-escalation clauses trigger because the protest window closed without a protest.

The Cost of Doing Nothing

Manual contract tracking consumes 15 to 25 hours per week of a legal-ops specialist's time at a mid-market company: calendar reviews, spreadsheet updates, chasing internal stakeholders for status, reformatting dates into compliance reports. At a loaded cost of €40 to €60 per hour across Western Europe, that is roughly €40,000 to €80,000 per year in direct labor, spent on work the machine should be doing.

That is the visible bill. The invisible bill is where the real money sits. A single missed renewal notice on a €120,000-per-year SaaS contract that auto-renews because nobody filed the non-renewal in time locks the company into another twelve-month term. One missed SLA penalty clause on a vendor agreement can cost a quarter's supplier discount. The 5 to 15 percent cost overrun from silent auto-renewals translates, on a typical mid-market contract portfolio with €2 to €5 million in annual contract spend, to €100,000 to €750,000 per year in committed cost that was never actively chosen.

A third cost is audit exposure. When a regulator or internal auditor asks "show me every obligation we waived in the last six months and who authorized it," a spreadsheet cannot answer. Email threads and shared-drive documents cannot answer. The labor to reconstruct that answer from source records is a multi-week forensics project.

What I Built

A headless, tenant-scoped contract and obligation tracking API, built in C# on .NET 8, PostgreSQL, and Quartz.NET. Contracts come in by API upload or via inbound webhooks from DocuSign and PandaDoc (signed via HMAC-SHA256). The AI extraction pipeline, using a separate RAG Platform, pulls every payment obligation, renewal window, compliance duty, and performance commitment out of the document with its clause reference and suggested deadline. Each extracted obligation lands in a Pending state. A human operator reviews and either confirms or dismisses.

Once confirmed, the hourly deadline scanner takes over. It walks every non-terminal obligation, computes business days remaining against the obligation's own holiday calendar (US, Germany, UK, Netherlands, or a tenant-custom calendar), and transitions the obligation through the lifecycle: Active, Upcoming, Due, Overdue, Escalated. Alerts fire at configurable windows before the deadline (default: 90, 30, 14, 7, 1 business days out). Three other scheduled jobs run alongside the scanner: a five-minute extraction processor that picks up queued AI jobs, a daily auto-renewal monitor that catches contracts approaching their end date, and a weekly sweep that catches obligations the scanner missed.

The design decision that shaped every other part of the system was this: every AI-extracted obligation lands in Pending, never Active, and a human clicks confirm before the scanner treats it as real. That single choice, fully explained in the Journal companion piece on extract-then-confirm, ripples through every downstream behavior: the event log structure, the four distinct terminal states (Dismissed, Fulfilled, Waived, Expired), the 422 response on invalid status transitions, and the archive cascade that cleanly expires obligations when their parent contract closes.

System Flow

Data Model

Architecture Layers

The Decision Log

Decision Alternative Rejected Why
AI extractions always land in Pending status, never Active Auto-activate high-confidence extractions A phantom obligation auto-activated by the AI creates a fiction in the compliance record that is worse than missing the real one. False positives are the more expensive failure mode in legal contexts.
Four distinct terminal states (Dismissed, Fulfilled, Waived, Expired) Single Closed status with a reason column An auditor asking "how many obligations did we waive this quarter?" should get a number from a filtered query, not a regex over free-text reasons. Each terminal state answers a different compliance question.
Business-day precision with per-tenant holiday calendars Calendar-day approximation A deadline that fires an alert on a bank holiday is worse than no alert. The system seeds US, German, UK, and Dutch holidays and accepts per-tenant custom calendars. Grace periods are in business days, not calendar days.
Feature-flagged ecosystem integrations with no-op stubs Required external service wiring The core contract and obligation engine runs without the RAG Platform, without the Notification Hub, without the Compliance Ledger. Six integrations default to disabled. The stub layer means service code has no null checks and no feature-flag branching at call sites.
Event-sourced obligation history with INSERT-only events Mutable status with updated_at A missed obligation becomes a legal liability. The repository interface exposes no Update or Delete on the event table, and a reflection test enforces it. Reconstructing who changed what, when, and why is a single indexed query.
Webhook receiver returns 404 when the feature flag is off 403 Forbidden 404 gives port scanners no hint the endpoint exists. Applies to both signed-contract webhooks and public tenant self-registration. Operators can disable surfaces without advertising them.
Fire-and-forget ecosystem dispatch after the database commit Synchronous dispatch inside the transaction A missed notification or audit event must never roll back an obligation transition. Every ecosystem emission is wrapped in a try/catch that logs the failure and moves on. The compliance ledger is a trailing audit stream, not an atomic dependency.

Ecosystem Integration

This system does not run alone in production. Inbound signed-contract webhooks from DocuSign and PandaDoc arrive through a webhook ingestion engine with HMAC-SHA256 verification. Obligation extraction runs on a multi-agent RAG platform across four prompt types: payment, renewal, compliance, performance. Deadline alerts route through a notification hub for email and Telegram delivery. Obligation breaches and contract lifecycle events publish to a compliance ledger over NATS JetStream. Confirmed payment obligations push purchase orders to an invoice reconciliation engine. Contract amendments can trigger approval flows in a workflow automation engine (client wired, call-site wiring deferred). All six integrations are feature-flagged. The engine boots clean with every _ENABLED flag set to false and runs standalone with no ecosystem dependencies.

Results

The test suite shipped with 714 passing tests across the Core, API, and Integration projects, plus 12 end-to-end test classes that spawn a real Kestrel subprocess on dedicated ports to verify the full HTTP surface. A live end-to-end walkthrough on 2026-04-17 confirmed 19 API calls against a running server behaved exactly as specified, including the tenant isolation boundary, the state-machine rejections (422 with valid next states in the error envelope), the feature-flag 404 on the disabled webhook receiver, and the recurring-obligation spawn that auto-creates the next instance when a monthly payment obligation is fulfilled.

For the operating business this replaces, the shift is measurable on two axes. The 15 to 25 weekly hours of manual contract tracking collapses to a focused review session where an operator confirms or dismisses AI-extracted obligations. The reading still happens, the typing does not. On the labor side, the €40,000 to €80,000 annual tracking cost recovers as time redirected to higher-value legal work. On the renewal exposure, the hourly deadline scanner plus the daily auto-renewal monitor close the window that silent auto-renewals used to exploit. A €120,000 SaaS contract that would have auto-renewed unnoticed now generates an alert 90 business days out, another at 30 days out, another at 7 days out, each idempotent on (obligation_id, alert_type, days_remaining) so re-scanning the same window does not duplicate the notifications.

The design choice that separates this engine from the off-the-shelf contract management products is the one in the Journal: AI is a proposal engine, not an activation engine. Every legally-binding commitment in the database was put there by a human with an identity and a timestamp. The audit log is the data, not a shadow of the data. That is the difference between a contract tracker and a defensible compliance system.

The system is production-capable via containerized deployment, and runs green with all six ecosystem integrations feature-flagged off, which is exactly the posture a legal-ops team should adopt on day one, before deciding which downstream services to onboard.

#csharp#dotnet#postgresql#quartz#legal-tech#obligation-tracking

The full system record for Contract Lifecycle Engine

Get Notified

New system breakdown? You'll know first.