https://github.com/portwood-global-solutions/docgen
Free, native document generation for Salesforce. PDF, DOCX, XLSX, PPTX — merge tags, images, barcodes, QR codes, bulk generation, Flow actions. 100% Apex + LWC, zero external dependencies.
https://github.com/portwood-global-solutions/docgen
apex barcode bulk-generation document-generation docx flow-actions lwc merge-tags open-source pdf qr-code salesforce salesforce-accelerator salesforce-package
Last synced: 1 day ago
JSON representation
Free, native document generation for Salesforce. PDF, DOCX, XLSX, PPTX — merge tags, images, barcodes, QR codes, bulk generation, Flow actions. 100% Apex + LWC, zero external dependencies.
- Host: GitHub
- URL: https://github.com/portwood-global-solutions/docgen
- Owner: Portwood-Global-Solutions
- License: apache-2.0
- Created: 2026-03-27T19:13:37.000Z (3 months ago)
- Default Branch: main
- Last Pushed: 2026-06-08T15:58:18.000Z (7 days ago)
- Last Synced: 2026-06-08T17:31:54.321Z (7 days ago)
- Topics: apex, barcode, bulk-generation, document-generation, docx, flow-actions, lwc, merge-tags, open-source, pdf, qr-code, salesforce, salesforce-accelerator, salesforce-package
- Language: Apex
- Homepage: https://portwood.dev
- Size: 15.1 MB
- Stars: 78
- Watchers: 2
- Forks: 20
- Open Issues: 4
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- Funding: .github/FUNDING.yml
- License: LICENSE
- Code of conduct: CODE_OF_CONDUCT.md
- Security: SECURITY.md
- Roadmap: ROADMAP.md
Awesome Lists containing this project
README
# Portwood DocGen — Free Document Generation for Salesforce
Generate PDFs and Word docs from any Salesforce record. Merge PDFs, add barcodes and QR codes, compute totals — 100% native: no external services, no callouts, your data never leaves Salesforce. 100% free forever. All features, all users, no paid tiers. PowerPoint and Excel coming soon.
[Join the Community Channel](https://portwood.dev/community) | [Website](https://portwood.dev) | [Roadmap](https://portwood.dev/roadmap)
[](#install)
[](LICENSE)
[](https://www.salesforce.com)
[](#install)
[](#code-quality)
[](#code-quality)
[](#security)
[](https://portwood.dev)
---
## Install
```bash
sf package install --package 04tVx000000nPGbIAM --wait 10 --target-org
```
[Install in Production](https://login.salesforce.com/packaging/installPackage.apexp?p0=04tVx000000nPGbIAM) | [Install in Sandbox](https://test.salesforce.com/packaging/installPackage.apexp?p0=04tVx000000nPGbIAM)
**Then:** Assign **DocGen Admin** permission set | Enable **Blob.toPdf() Release Update** | Open the **DocGen** app
---
## Quick Start
1. **Create a template** — pick Word, Excel, PowerPoint, or HTML. Choose your Salesforce object.
2. **Select your fields** — use the visual query builder, or paste a full SOQL statement for complex nested relationships.
3. **Add tags and upload** — type `{Name}` where you want data. Upload the file (or a Google Docs "Download → Web Page" zip for HTML templates).
4. **Generate** — from any record page, in bulk, or from a Flow.
Download example templates from [portwood.dev](https://portwood.dev).
---
## What You Can Do
### Template Formats
| Format | Template | Output Options | Best For |
| ----------------- | ----------------------- | -------------- | ---------------------------------------------------------- |
| **Word** | `.docx` | PDF or DOCX | Contracts, proposals, invoices, letters |
| **HTML** (v1.61+) | `.html`, `.htm`, `.zip` | PDF | Google Docs, Notion, ChatGPT, Apple Pages, any HTML source |
| **PDF** (v3.03+) | `.pdf` | PDF | Fillable PDF forms / AcroForm mapping (testing) |
| **Excel** | `.xlsx` | XLSX | Data exports, reports, financial summaries |
| **PowerPoint** | `.pptx` | PPTX | Presentations, slide decks |
Word and HTML both support images, rich text, headers/footers, and PDF output. Word adds barcodes and QR codes. Excel and PowerPoint render in their native formats only.
**HTML templates** accept Google Docs "Download → Web Page" zips directly — the admin UI unzips client-side, extracts each image into a ContentVersion, and rewrites the HTML to reference them. Inline `data:image/...` URIs from Notion / ChatGPT / rich-text paste are handled the same way. Optional `Header HTML` / `Footer HTML` fields with a WYSIWYG editor (and a **Show HTML** toggle for raw-source edits) support merge tags including `{PageNumber}` and `{TotalPages}`.
### Merge Tags
| Tag | What It Does | Example |
| ------------------------------- | ------------------------------------ | ------------------------------------------------------------ |
| `{FieldName}` | Insert a field value | `{Name}`, `{Email}`, `{Phone}` |
| `{Parent.Field}` | Pull from a related record | `{Account.Name}`, `{Owner.Email}` |
| `{#ChildList}...{/ChildList}` | Repeat for each child record | `{#Contacts}{FirstName}{/Contacts}` |
| `{#BoolField}...{/BoolField}` | Show/hide based on checkbox | `{#IsActive}Active member{/IsActive}` |
| `{#Field}...{:else}...{/Field}` | Show/hide with fallback | `{#Industry}Sector: {Industry}{:else}No industry{/Industry}` |
| `{^Field}...{/Field}` | Show when field is false/blank | `{^HasDiscount}No discount applied{/HasDiscount}` |
| `{#IF Field op Value}...{/IF}` | Compare field against value | `{#IF Amount > 50000}Premium{:else}Standard{/IF}` |
| `{RichTextField}` | Rich text with formatting and images | `{Description}` renders bold, italic, lists |
### Formatting
| Tag | Output |
| ------------------------ | -------------------------- |
| `{CloseDate:MM/dd/yyyy}` | 03/18/2026 |
| `{Amount:currency}` | $500,000.00 |
| `{Rate:percent}` | 15.5% |
| `{Quantity:number}` | 1,234 |
| `{IsActive:checkbox}` | [X] or [ ] |
| `{StageName:label}` | User-facing picklist label |
### Aggregates
Place these **outside** the loop to compute totals from child records:
| Tag | Example |
| --------------------------------------- | -------------------------------------- |
| `{SUM:List.Field}` | `{SUM:QuoteLineItems.TotalPrice}` |
| `{COUNT:List}` | `{COUNT:Contacts}` |
| `{AVG:List.Field}` | `{AVG:OpportunityLineItems.UnitPrice}` |
| `{MIN:List.Field}` / `{MAX:List.Field}` | `{MIN:QuoteLineItems.Quantity}` |
### Images
Store a ContentVersion ID (starts with `068`) in a text field, then use `{%FieldName}` in your template:
| Tag | What It Does |
| ----------------------- | ---------------------------------------------- |
| `{%Logo__c}` | Insert image at original size |
| `{%Logo__c:200x60}` | Fixed size: 200px wide, 60px tall |
| `{%Logo__c:100%x}` | Full page width, keep aspect ratio |
| `{%Logo__c:m100%xm50%}` | Shrink to fit within page width and 50% height |
Images work in both **PDF** and **DOCX** output. You can also embed images directly in your Word template — they render in PDFs automatically.
### Rich Text Fields
Rich text fields render with full formatting (bold, italic, lists, images) in PDF output. Images inside rich text fields work in PDFs. For DOCX output, use `{%FieldName}` image tags instead of rich text images.
### Barcodes & QR Codes
PDF output only. No external services required.
| Tag | What You Get |
| ------------------------------- | -------------------------------- |
| `{*ProductCode}` | Code 128 barcode |
| `{*ProductCode:code128:300x80}` | Barcode at 300px wide, 80px tall |
| `{*Website:qr}` | QR code (150px default) |
| `{*TrackingUrl:qr:200}` | QR code at 200px square |
QR codes are generated natively in Salesforce with Level Q error correction and support values up to 600 characters. For printed or mailed documents, short URLs or tokens under 120 characters scan most reliably at 1 inch square.
### Charts (v1.99+)
Nine chart styles, one tag, every output format. Pure-Apex PNG rasterization — no ``, no external services, no JavaScript libraries. Works in HTML→PDF (Flying Saucer), Word DOCX, Word→PDF, PowerPoint PPTX, and server-side Flow / batch / Queueable contexts.
```
{Chart:Survey_Responses__r:Selected_Answer__c} ← bar (default)
{Chart:Survey_Responses__r:Department__c:pie:title=Department Share}
{Chart:Survey_Responses__r:Selected_Answer__c:stacked:groupBy=Department__c&colSort=Eng,Sales,Marketing}
{Chart:Survey_Responses__r:Selected_Answer__c:line:groupBy=Department__c&colSort=Eng,Sales,Marketing}
```
| Style | Visual | Best for |
| ----------- | ---------------------------------------------------- | --------------------------------------------- |
| `bar` | Horizontal bars, label + count + percent | One dimension, long labels |
| `column` | Vertical bars | One dimension, short labels |
| `pie` | Pie + right-side legend | Share of total, ≤8 slices |
| `donut` | Pie with center hole | Pie, lighter visual |
| `pivot` | Cross-tab table with Total column | Numeric matrix readout |
| `stacked` | Horizontal stacked bar segmented by `groupBy` | "How does each row split across dimension 2?" |
| `clustered` | Vertical clustered bars, mini-bar per col | Side-by-side comparison |
| `line` | Polyline through (bucket index, count), multi-series | Trend / ordering matters |
| `area` | Line + semi-transparent fill below each series | Trend + accumulated volume |
Composable modifiers: `title=`, `width=`, `height=`, `where=` (SOQL fragment), `groupBy=`, `colSort=`, `colors=` (hex palette), `split=` (multi-select delimiter), `scale=`, `htmlRender=svg`. Aggregates via SOQL `GROUP BY` — constant cost regardless of row count (verified end-to-end at 30,000 child rows). Full reference + LLM authoring prompt in `UserGuide.md` §7.6; reference templates ship in `docs/ChartEngineShowcase.{html,docx}`.
### Repeating Tables
To repeat rows inside a table (not the whole table), put the loop tags in the data row:
| Name | Title | Email |
| ----------------------------------- | --------- | -------------------- |
| `{#Contacts}{FirstName} {LastName}` | `{Title}` | `{Email}{/Contacts}` |
The `{#Contacts}` goes in the first cell and `{/Contacts}` goes in the last cell of the same row. The header row stays fixed, and the data row repeats for each record.
### Cover Pages & Section Breaks
- **Title pages** — If your Word template has "Different First Page" enabled, the PDF will suppress headers and footers on page 1. Your cover page stays clean.
- **Section breaks** — Section breaks in your Word template create proper page breaks in the PDF.
### Page Breaks in Loops
Put a page break inside a loop to give each child record its own page:
```
{#Opportunities}
Customer: {Account.Name}
Amount: {Amount:currency}
← page break here (Insert → Page Break in Word)
{/Opportunities}
```
### PDF Merger
Five ways to combine PDFs:
| Mode | What It Does |
| --------------------- | -------------------------------------------------------------------------- |
| **Generate & Merge** | Generate a doc, then append existing PDFs from the record |
| **Document Packets** | Generate from multiple templates, merge into one PDF |
| **Merge Only** | Combine existing PDFs on the record with drag-and-drop ordering |
| **Child Record PDFs** | Pull PDFs from child records (e.g., all Opportunity PDFs under an Account) |
| **Bulk Merge** | After bulk generation, merge all generated PDFs into one download |
### Giant Query Engine
Records with **2,000 to 50,000+ child records** are detected automatically. Same template, same button — the engine handles pagination and async processing behind the scenes.
### E-Signatures
Collect legally valid electronic signatures directly from DocGen — no third-party tools required. Built-in Simple Electronic Signature (SES) support that's valid under the US ESIGN Act and UETA. Guided field-to-field signing **on the actual PDF** — **draw or type** signatures and initials — date stamps, document packets, parallel / sequential / single multi-signer flows, decline flow, sender **and signer** completion notifications, and a **Certificate of Completion** (signed timestamps, IP, consent, document hash) — all 100% native. Send from the **Signature Sender** UI or trigger from a **Flow / platform event** — both take the same guided experience. Signed documents follow your template's **Document Title Format** naming, and each signature lands as a clean, professional signature stamp card.
**Signature tag syntax:** `{@Signature_Role:Order:Type}`
| Type | What It Does | Example |
| ---------- | ---------------------------------- | ------------------------------- |
| `Full` | Signer types their full legal name | `{@Signature_Buyer:1:Full}` |
| `Initials` | Signer types their initials | `{@Signature_Buyer:2:Initials}` |
| `Date` | Auto-filled server timestamp | `{@Signature_Buyer:3:Date}` |
| `DatePick` | Signer selects a date | `{@Signature_Buyer:4:DatePick}` |
Backward compatible: `{@Signature_Buyer}` still works (treated as `:1:Full`).
**How it works:**
1. Add signature tags to your Word template — DocGen auto-detects roles and placement types
2. Select template(s) from the Send For Signature tab — preview the merged document before sending
3. Each signer receives a branded email with a secure link
4. Signers verify their email with a 6-digit PIN, then walk through each placement step by step — an arrow points to where they need to sign, initial, or add a date
5. The document updates live as each placement is confirmed — signers can leave and resume later
6. After all signers complete, DocGen generates a signed PDF with an Electronic Signature Certificate
**Key features:**
- **Guided signing** — step-by-step walk-through with live document updates and arrow indicators
- **Document packets** — send multiple templates as one signing session (e.g., NDA + Contract + Addendum)
- **Sequential signing** — signers go one at a time in order (next signer notified after previous completes)
- **Decline flow** — signers can decline with a reason; sender is notified immediately
- **Sender notifications** — email alerts when each signer completes, when all are done, or when someone declines
- **Sender preview** — see the fully merged document with highlighted signature placements before sending
- **Resume support** — per-placement persistence; signers pick up exactly where they left off
- **Automated reminders** — configurable reminder emails for signers who haven't responded
- **Setup validation** — automated checklist verifies site, permissions, OWA, and email deliverability
**What's captured for every signature:**
| Data Point | How |
| ------------------ | ---------------------------------------------------------------------- |
| Signer identity | Email PIN verification (SHA-256 hashed, 10-min expiry, 3 attempts max) |
| Consent | Explicit checkbox — timestamp recorded |
| IP address | Server-side capture via request headers, shown on PDF certificate |
| User agent | Browser fingerprint |
| Document integrity | SHA-256 hash of the final PDF |
| Tamper evidence | Field history tracking on all audit fields |
**Verification:** Every signed PDF includes a certificate page with signer details (name, role, email, IP address, timestamps) and a verification URL. The verify page lets anyone upload a PDF to check its hash against the audit record — the file never leaves the browser.
**Admin setup:** Configure a Salesforce Site, assign the Guest Signature permission set, set an Org-Wide Email Address, and customize email branding — all from the Signatures tab in the Command Hub. An automated setup checklist shows green/red status for each requirement. See the Learning Center for step-by-step instructions.
### Query Builder
The query builder accepts full SOQL statements with unlimited nesting depth. Paste a query like:
```sql
SELECT Name, Industry,
(SELECT FirstName, LastName, Account.Name FROM Contacts),
(SELECT Name, Amount,
(SELECT Quantity, Product2.Name FROM OpportunityLineItems)
FROM Opportunities WHERE StageName = 'Closed Won')
FROM Account
```
The builder parses the query, displays the field tree with parent lookups highlighted, and generates copy-paste merge tags for your template. Outer `SELECT` / `FROM` clauses are stripped automatically — DocGen always runs against a specific record.
**Tips:**
- Test your query in Developer Console or tools like [Salesforce Inspector](https://chromewebstore.google.com/detail/salesforce-inspector-reloaded/hpijlohoihegkfehhibggnkbjhoemldh) before pasting.
- Use AI to help build complex queries — Agentforce, ChatGPT, Gemini, and Claude can all generate valid SOQL with nested relationships.
- Subqueries support WHERE, ORDER BY, and LIMIT clauses.
- Parent lookups (e.g., `Account.Name`, `Product2.Family`) work at every nesting level.
### Automation
| Action | Inputs | Use In |
| ---------------------- | -------------------------- | ------------------------------------ |
| `DocGenFlowAction` | templateId, recordId | Record-Triggered Flows, Screen Flows |
| `DocGenBulkFlowAction` | templateId, queryCondition | Scheduled Flows, Bulk Processing |
### Bulk Generation
Generate documents for hundreds of records at once. Enter a filter condition, click Submit. Real-time progress tracking in the app.
---
## What Works in PDF vs DOCX
| Feature | PDF | DOCX |
| ---------------------------------------------- | ---------------------------- | ------------------------------ |
| All merge tags and formatting | Yes | Yes |
| Bold, italic, underline, colors, font sizes | Yes | Yes |
| Tables with borders, shading, column widths | Yes | Yes |
| Template-embedded images | Yes | Yes |
| Dynamic images from record fields (`{%Field}`) | Yes | Yes |
| Rich text field formatting | Yes | Yes |
| Rich text images | Yes | No — use `{%Field}` image tags |
| Barcodes and QR codes | Yes | No |
| Page numbers in headers/footers | Yes | N/A (Word handles natively) |
| Cover page (no header on page 1) | Yes | N/A (Word handles natively) |
| Custom fonts (Calibri, branded, etc.) | No — falls back to Helvetica | Yes — preserves original fonts |
| Clickable hyperlinks | No — rendered as styled text | Yes |
---
## PDF Font Support
Salesforce's PDF engine supports these fonts:
| Font | CSS Name | When It's Used |
| -------------------- | ------------ | ----------------------------------------------- |
| **Helvetica** | `sans-serif` | Default for all text |
| **Times** | `serif` | If explicitly set in template |
| **Courier** | `monospace` | Fixed-width text |
| **Arial Unicode MS** | (automatic) | Chinese, Japanese, Korean, Thai, Arabic, Hebrew |
Custom fonts from your Word template (Calibri, Cambria, branded typefaces) **fall back to Helvetica** in PDF output. If custom fonts matter, generate as DOCX — Word preserves the original fonts.
Starting with Spring '26, the renderer supports expanded multibyte character rendering for international scripts.
---
## What PDF Can't Do
These are Salesforce platform limitations, not DocGen bugs:
| Not Supported | Why | Workaround |
| ------------------------ | ---------------------------------------------------------------------------------------------------- | --------------------------------------------- |
| Custom fonts | `Blob.toPdf()` only has 4 built-in fonts | Generate as DOCX |
| `@font-face` CSS | Not supported by the PDF renderer | Generate as DOCX |
| Text boxes and shapes | Word drawing objects aren't converted to HTML | Use tables for layout |
| SmartArt and charts | Not rendered in the HTML conversion | Insert as images in your template |
| Clickable hyperlinks | PDF renderer outputs styled text, not links | Links work in DOCX |
| CSS Grid / Flexbox | The PDF renderer supports CSS 2.1 only | Use tables |
| JavaScript | Ignored by the renderer | N/A |
| Even/odd page headers | Not currently supported | Same header on all pages |
| Multiple section headers | One header/footer set per document | Use page breaks, not section-specific headers |
| Multi-column layouts | CSS columns not supported by the PDF engine | Use tables for column layouts |
| E-signatures (QES) | SES signatures are built-in; Qualified Electronic Signatures (EU eIDAS) require a certified provider | Use built-in SES for most use cases |
---
## Governor Limits
| Limit | Details | How DocGen Handles It |
| ------------------------- | -------------------------- | ----------------------------------------------------------------- |
| **6 MB heap (sync)** | Single document generation | DOCX uses client-side assembly; PDF uses zero-heap image pipeline |
| **12 MB heap (async)** | Bulk batch generation | Batch size 1 = fresh heap per record |
| **~3 MB PDF save** | Saving PDF to a record | Download has no size limit |
| **4 MB Aura payload** | Saving DOCX to a record | Download works for any size |
| **100 SOQL queries** | Per transaction | Multi-level queries use 1 SOQL per relationship depth |
| **50,000+ child records** | Giant datasets | Auto-detected, processed async with cursor pagination |
---
## Architecture
```
Template (.docx/.xlsx/.pptx)
↓
Decompress → Merge XML tags → Recompress
↓ ↓
DOCX/XLSX/PPTX PDF path:
(client-side ZIP) DocGenHtmlRenderer → Blob.toPdf()
```
| Class | Role |
| ----------------------------- | -------------------------------------------------------------------- |
| `DocGenService` | Core merge engine — tags, loops, images, aggregates, barcodes |
| `DocGenHtmlRenderer` | DOCX XML → HTML for PDF rendering |
| `DocGenDataRetriever` | Multi-level SOQL with query tree stitching |
| `BarcodeGenerator` | Code 128 + QR code generation (pure Apex) |
| `DocGenController` | LWC controller — template CRUD, generation endpoints |
| `DocGenBatch` | Batch Apex for bulk document generation |
| `DocGenSignatureController` | Signing page — token validation, PIN verification, signature capture |
| `DocGenSignatureService` | Typed-name stamping, PDF generation, verification certificate |
| `DocGenSignatureEmailService` | Branded signature request and PIN emails with OWA support |
| `docGenPdfMerger.js` | Client-side PDF merge engine (pure JS) |
| `docGenZipWriter.js` | Client-side DOCX/XLSX assembly (pure JS) |
---
## Releases
DocGen ships on a **biweekly release cycle**. Latest release: **v3.11.0 — Shared Template Image Rendering**.
See [CHANGELOG.md](CHANGELOG.md) for full version history.
---
## Community
DocGen is 100% free, open source, and community-driven. Published through [Portwood Global Solutions](https://portwood.dev).
| Channel | What It's For |
| --------------------------------------------------------------------------- | -------------------------------------------------- |
| [Community Channel](https://portwood.dev/community) | Real-time help, feature requests, template sharing |
| [GitHub Issues](https://github.com/Portwood-Global-Solutions/DocGen/issues) | Bug reports and tracked feature requests |
| [Roadmap](https://portwood.dev/changelog) | What's shipped and what's coming next |
| [Website](https://portwood.dev) | Install links, feature overview |
Need dedicated support? Contact us at [hello@portwood.dev](mailto:hello@portwood.dev).
## Contributing
We welcome contributions — see [CONTRIBUTING.md](CONTRIBUTING.md) for setup instructions.
## Security
### Code Analyzer Results
We run the [Salesforce Code Analyzer](https://developer.salesforce.com/docs/platform/salesforce-code-analyzer/guide/engine-sfge.html) with **Security + AppExchange** rule selectors on every release.
| Severity | Count | Status |
| ------------ | ----- | ------------------------------ |
| **Critical** | 0 | Clean |
| **High** | 0 | Clean |
| **Moderate** | 41 | All documented false positives |
| **Low** | 0 | Not flagged |
The 41 moderate findings are all PMD false positives that cannot be suppressed inline:
- **29** `ProtectSensitiveData` — PMD flags field names containing "Token", "Signature", "Email", "Hash", "PIN" in XML metadata. These are signature system fields plus the v1.9x signature-email branding settings (Signature_Email_Subject/Message/Footer/Logo/Brand_Color, Signature_OWA_Id, reminder fields). All intentionally sensitive, protected by permission sets, sharing model, and field history tracking.
- **12** `AvoidLwcBubblesComposedTrue` — Required for recursive tree node event propagation in the visual query builder, plus the v1.9x runner LWC's cross-boundary events (chart-resolution status, signature-placement events, giant-query progress). Events must cross shadow DOM boundaries in nested components.
See [`code-analyzer.yml`](code-analyzer.yml) for full documentation of each accepted finding.
### How Access Is Enforced
| Layer | Mechanism |
| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| **Object CRUD** | `DocGen_Admin` and `DocGen_User` permission sets (platform-enforced) |
| **Field-level security** | Same permission sets (platform-enforced) |
| **Record sharing** | Admin-context classes use `with sharing`; signature classes use `without sharing` with access gated by cryptographic token validation |
| **Standard objects** | `USER_MODE` + `Security.stripInaccessible()` (code-enforced) |
| **Signature guest access** | `SYSTEM_MODE` with 64-char SHA-256 token + email PIN verification |
No user can access DocGen data without an explicitly assigned permission set. Signature guest users can only access records matching their validated cryptographic token.
### E-Signature Security
| Control | Implementation |
| ------------------ | ------------------------------------------------------------------------------------ |
| Token generation | `Crypto.generateAesKey(256)` + SHA-256 hash (64-char hex) |
| Token expiry | 48 hours from creation |
| PIN verification | 6-digit code, SHA-256 hashed (plaintext never stored), 10-min expiry, 3 attempts max |
| Consent | Explicit checkbox with audit trail entry |
| Document integrity | SHA-256 hash of final PDF stored on audit record |
| Tamper evidence | Field history tracking on all audit fields |
| IP capture | Server-side via `X-Forwarded-For` / `True-Client-IP` headers |
Found a vulnerability? See [SECURITY.md](SECURITY.md).
## Version History
| Version | Channel | Package ID |
| ------- | --------------------------------------- | -------------------- |
| v3.11.0 | **Latest (Released)** | `04tVx000000nPGbIAM` |
| v3.10.0 | Previous | `04tVx000000nOh7IAE` |
| v3.09.0 | Previous | `04tVx000000nOdtIAE` |
| v3.08.0 | Previous | `04tVx000000nOFhIAM` |
| v3.07.0 | Previous | `04tVx000000nLOHIA2` |
| v3.06.0 | Previous | `04tVx000000nIv4IAE` |
| v3.05.0 | Previous | `04tVx000000nI5RIAU` |
| v3.04.0 | Previous | `04tVx000000nGZtIAM` |
| v3.03.0 | Previous | `04tVx000000nEHxIAM` |
| v3.02.0 | Previous | `04tVx000000muJFIAY` |
| v3.01.0 | Previous | `04tVx000000hWJBIA2` |
| v3.0.0 | Previous | `04tVx000000a8blIAA` |
| v2.9.0 | Previous | `04tVx000000a7fhIAA` |
| v2.8.0 | Previous | `04tVx000000a7e5IAA` |
| v2.7.0 | Previous | `04tVx000000a1IXIAY` |
| v2.6.0 | Previous | `04tVx000000a037IAA` |
| v2.5.0 | Previous | `04tVx000000ZyyzIAC` |
| v2.4.0 | Previous | `04tVx000000ZyanIAC` |
| v2.3.0 | Previous | `04tVx000000ZxDJIA0` |
| v2.2.0 | Previous | `04tVx000000ZxBhIAK` |
| v2.1.0 | Previous | `04tVx000000Zw5xIAC` |
| v2.0.0 | Previous | `04tVx000000ZqBpIAK` |
| v1.99.0 | Previous | `04tVx000000ZVFRIA4` |
| v1.98.0 | Previous | `04tVx000000Si9NIAS` |
| v1.97.0 | Previous | `04tVx000000SFovIAG` |
| v1.96.0 | Previous | `04tVx000000SFH3IAO` |
| v1.95.0 | Previous | `04tVx000000SFDpIAO` |
| v1.94.0 | Previous | `04tVx000000SExhIAG` |
| v1.93.0 | Previous | `04tVx000000SDOvIAO` |
| v1.92.0 | Previous | `04tVx000000S9I5IAK` |
| v1.91.0 | Previous | `04tVx000000RvbhIAC` |
| v1.90.0 | Previous | `04tVx000000R8cbIAC` |
| v1.89.0 | Previous | `04tVx000000Qu1lIAC` |
| v1.88.0 | Previous | `04tVx000000Qu09IAC` |
| v1.87.0 | Previous | `04tVx000000QtqTIAS` |
| v1.86.0 | Previous | `04tVx000000QtorIAC` |
| v1.85.0 | Previous | `04tVx000000QlePIAS` |
| v1.84.0 | Previous | `04tVx000000QL2PIAW` |
| v1.83.0 | Previous | `04tVx000000QKRJIA4` |
| v1.82.0 | Previous | `04tal000006rKBdAAM` |
| v1.81.0 | Previous | `04tal000006rKA1AAM` |
| v1.80.0 | Previous | `04tal000006rJkDAAU` |
| v1.79.0 | Previous | `04tal000006rD8XAAU` |
| v1.77.0 | Previous | `04tal000006rCxFAAU` |
| v1.76.0 | Previous | `04tal000006rCu1AAE` |
| v1.75.0 | Previous | `04tal000006rCZ3AAM` |
| v1.74.0 | Previous | `04tal000006rBTJAA2` |
| v1.73.0 | Previous | `04tal000006rAYrAAM` |
| v1.72.0 | Previous | `04tal000006r0xiAAA` |
| v1.71.0 | Previous | `04tal000006r0jBAAQ` |
| v1.70.0 | Previous | `04tal000006qyhNAAQ` |
| v1.69.0 | Previous | `04tal000006qyB7AAI` |
| v1.68.0 | Previous | `04tal000006qt1lAAA` |
| v1.67.0 | Previous | `04tal000006qqOrAAI` |
| v1.66.0 | Previous | `04tal000006qiUXAAY` |
| v1.65.0 | Previous | `04tal000006qiG1AAI` |
| v1.64.0 | Previous | `04tal000006qhYTAAY` |
| v1.63.0 | Previous | `04tal000006qZmEAAU` |
| v1.62.0 | Previous | `04tal000006q929AAA` |
| v1.61.0 | Previous | `04tal000006pzu1AAA` |
| v1.60.0 | Previous | `04tal000006lrGjAAI` |
| v1.59.0 | Previous | `04tal000006lrDVAAY` |
| v1.58.0 | Previous | `04tal000006lpoPAAQ` |
| v1.57.0 | Superseded (install validator rejected) | `04tal000006lplBAAQ` |
| v1.56.0 | Previous | `04tal000006i1rNAAQ` |
| v1.55.0 | Previous | `04tal000006i0thAAA` |
| v1.54.0 | Previous | `04tal000006i0qTAAQ` |
| v1.53.0 | Previous | `04tal000006hyYXAAY` |
| v1.52.0 | Previous | `04tal000006hyVJAAY` |
| v1.51.0 | Previous | `04tal000006hyThAAI` |
| v1.50.0 | Previous | `04tal000006hyNFAAY` |
| v1.49.0 | Previous | `04tal000006hlZhAAI` |
| v1.48.0 | Previous | `04tal000006hhhNAAQ` |
| v1.47.0 | Previous | `04tal000006hQwfAAE` |
| v1.46.0 | Previous | `04tal000006hQ73AAE` |
| v1.45.0 | Previous (tester rollout) | `04tal000006hOZtAAM` |
| v1.43.0 | Previous | `04tal000006hLTxAAM` |
| v1.42.0 | Previous | `04tal000006UkpxAAC` |
| v1.41.0 | Previous | `04tal000006UiubAAC` |
See [CHANGELOG.md](CHANGELOG.md) for full release notes.
## License
Apache License, Version 2.0. See [LICENSE](LICENSE).
---
Built by [Portwood Global Solutions](https://portwood.dev)