## What this is
The enterprise procurement flow, built into the customer portal as a
**vertical slice** — one linked account can go the whole way from trial
to a paid, committed subscription, using real Stripe under the hood.
Procurement no longer lives as a nav tab. It sits on **Home** as a
deal-status hero and expands into a full-screen takeover, matching the
marketing prototype.
## The journey (what a customer does)
- **Start a trial** in one click — the deadline and next steps show on
the Home hero (no card, mock licence).
- **Build a quote** — a short form (volume → commitment & service →
details); pricing is computed server-side.
- **Generate the quote** — this creates a real **Stripe Quote** with a
proper **PDF** you can download and share, and it becomes a milestone
you can come back to.
- **Review & sign the agreement** — one combined agreement (MSA + Order
Form + EULA + DPA) with an itemised order form and an "I agree" (no
e-signature yet).
- **Accept** — Stripe creates the committed annual **subscription** and
its **first invoice**, which you can **pay or download right in the
app** (no waiting on email).
- Edit a quote any time — it remembers your inputs and company name; the
old Stripe quote is cancelled so it can't still be accepted.
- The hero also has quick actions: **key documents**, **invite
teammates**, **schedule a call**, and a **trial countdown** you can
extend.
## Architecture — Supabase vs Java
Pricing, deal/quote state, and the commercial journey live in **Java
(`:saas`)**. Everything that touches **Stripe** (writes + PDFs) lives in
**Supabase edge functions** — Java has no Stripe SDK and only reads
Stripe via the sync mirror. The portal calls both.
```mermaid
flowchart LR
Portal["Portal (React · editor/src/portal)"]
subgraph JAVA["Java :saas backend (trusted cloud)"]
Pricing["Pricing engine (volume bands, SLA, term, add-ons)"]
Deal["Deal + quote state, journey, snapshot"]
Trial["Trial (mock Keygen licence seam)"]
Authz["Auth: team resolve + leader gating"]
Mirror["Reads Stripe via sync mirror (stripe.* tables)"]
end
subgraph SUPA["Supabase edge functions (own Stripe)"]
Issue["issue-procurement-quote → create + finalize Stripe Quote"]
Accept["accept-procurement-quote → subscription + finalize invoice"]
Pdf["get-procurement-quote-pdf → proxy the quote PDF"]
RPC["SECURITY DEFINER RPCs (read/write stirling_pdf, enforce team/leader)"]
end
Stripe["Stripe (Quotes · Subscription · Invoice)"]
Portal -->|"price / build / trial / agreement / snapshot"| JAVA
Portal -->|"issue / accept / download PDF"| SUPA
SUPA --> Stripe
SUPA --- RPC
Mirror -. reads .-> Stripe
```
| Top-level feature | Handled in |
|---|---|
| Quote pricing (bands, SLA, term, add-ons) | **Java** |
| Deal + quote state, journey, snapshot | **Java** |
| Trial start / extend (mock licence) | **Java** |
| AuthN/Z (team resolve, leader gating) | **Java** |
| Issue quote → Stripe Quote + PDF | **Supabase edge fn** |
| Accept → subscription + invoice | **Supabase edge fn** |
| Quote PDF download | **Supabase edge fn** |
| Reading Stripe state | **Java** (sync mirror) |
| `stirling_pdf` writes from edge | **SECURITY DEFINER RPCs**
(service-role only) |
## Screenshots
<!-- Drag each PNG into the box below it before publishing. -->
**Home deal-status hero (trial)**
<img width="1920" height="1009" alt="hero-check"
src="https://github.com/user-attachments/assets/7ae21831-9578-4f4d-b91a-d3ab2cb171dc"
/>
**Issued quote milestone (with breakdown)**
<img width="1920" height="1009" alt="milestone-breakdown"
src="https://github.com/user-attachments/assets/3a463c67-3c6e-4f93-a1cc-59b250d54cc9"
/>
**Agreement step (itemised order form)**
<img width="1920" height="1009" alt="agreement-itemised"
src="https://github.com/user-attachments/assets/1a4efa16-d0a3-41d0-849c-a125b1492a34"
/>
**Key documents**
<img width="1920" height="1009" alt="keydocs-modal"
src="https://github.com/user-attachments/assets/5672d1d2-99d9-499e-9edf-d485df378e7f"
/>
**Subscription created (pay / download invoice)**
<img width="1920" height="1009" alt="accepted-check"
src="https://github.com/user-attachments/assets/3a8cbe9f-e72c-4389-b365-0c1749108b6f"
/>
## Mocked for now (scaffolding, not wired to real backends)
- **Key documents** ledger — static demo list.
- **Schedule a call** — static solutions-engineer + time slots.
- **Invite teammates** — routes to the existing Users view.
- **Simulate payment received** / **Reset procurement** — demo controls,
**off by default** in prod (flag-gated), 404 unless enabled.
## Deferred (separate follow-up PRs)
- **Real `invoice.paid` webhook** → go-live (today a demo button stands
in).
- **Keygen licence controller** — real licensing (currently a mock
seam).
- **Document sharing**.
- **Stirling admin / Deal Desk** view.
- **Minimum ACV floor** — pending a number from marketing (server-side
enforcement is a one-liner once decided).
## How to test
- **Frontend, no backend:** runs against MSW mocks (Storybook + mocks-on
dev) — the whole journey is clickable.
- **Real end-to-end:** apply the migrations (Flyway `V27–V29` / Supabase
`20260701–20260707`), deploy the three edge functions, ensure
**Invoicing Plus** is enabled on Stripe, and set
`STIRLING_PROCUREMENT_DEMO_CONTROLS_ENABLED=true` if you want the demo
controls.
- Paired SaaS PR: **Stirling-Tools/Stirling-PDF-SaaS#318**.
## Notes for reviewers
- Pricing is server-authoritative (client sends config, never amounts).
- Security review done: edge functions validate the JWT and enforce
**team membership** (and **leader** for issue/accept) via the RPC; demo
endpoints are flag-gated off. Only open item is the ACV floor (policy).
Stirling PDF - The Open-Source PDF Platform
Stirling PDF is a powerful, open-source PDF editing platform. Run it as a personal desktop app, in the browser, or deploy it on your own servers with a private API. Edit, sign, redact, convert, and automate PDFs without sending documents to external services.
Key Capabilities
- Everywhere you work - Desktop client, browser UI, and self-hosted server with a private API.
- 50+ PDF tools - Edit, merge, split, sign, redact, convert, OCR, compress, and more.
- Automation & workflows - No-code pipelines direct in UI with APIs to process millions of PDFs.
- Enterprise‑grade - SSO, auditing, and flexible on‑prem deployments.
- Developer platform - REST APIs available for nearly all tools to integrate into your existing systems.
- Global UI - Interface available in 40+ languages.
For a full feature list, see the docs: https://docs.stirlingpdf.com
Quick Start
docker run -p 8080:8080 docker.stirlingpdf.com/stirlingtools/stirling-pdf
Then open: http://localhost:8080
For full installation options (including desktop and Kubernetes), see our Documentation Guide.
Resources
Support
- Community: Discord
- Bug Reports: GitHub Issues
Contributing
We welcome contributions! Please see CONTRIBUTING.md for guidelines.
This project uses Task as a unified command runner for all build, dev, and test commands. Run task dev to get started running the editor, run task to see the most common commands, or see the Developer Guide for full details.
For adding translations, see the Translation Guide.
License
Stirling PDF is open-core. See LICENSE for details.

