Skip to content

White-label firms (Phase 2.5)

What

A Firm record holds the audit firm's branding profile: display name, logo, primary/accent colors, methodology disclaimer, footer text, confidentiality notice, and per-firm engagement defaults (default archetype, default budget). Engagements reference a firm via firm_id; deliverable rendering looks up the firm at render time.

The result: cover page says "Prepared by Acme Audit Partners, LLP — Defense compliance · Pittsburgh", the logo embeds at the top of markdown / DOCX exports, the methodology page appends the firm's disclaimer, every page footer carries the firm's confidentiality notice. The end client sees a partner deliverable, not an AI report.

Why this matters

Without white-label, the deliverable cover says "Audit Findings — [Client Name]" with no firm identity — a partner can't put their reputation on it and can't sell it to their client. White-label is the gate to first paid engagement.

Data model

class Firm:
    id: str                        # firm-<hex>
    display_name: str              # "Acme Audit Partners, LLP"
    short_name: str                # "Acme" — for tight footers
    tagline: str                   # "Defense compliance · Pittsburgh"
    logo_url: str                  # public HTTPS URL; firm hosts on their CDN
    primary_color: str             # cover heading bars (hex)
    accent_color: str              # callouts / highlights (hex)
    methodology_disclaimer: str    # appended to methodology section
    footer_text: str               # cover + page footer
    confidentiality_notice: str    # rendered above exec summary
    default_archetype: str
    default_budget_cents: int

Persistence

S3-backed lazy-load with best-effort upload, mirrors EngagementStore pattern.

s3://{bucket}/auditforge/firms.json

In-memory cache, persisted on every mutation. Local cache at ${CACHE_DIR}/auditforge/firms.json for fast reads.

Default firm

When an engagement has firm_id=None or its referenced firm has been deleted, the deliverable renderer falls back to a hardcoded firm-default with neutral AuditForge branding ("Generated by AuditForge"). This means no engagement ever fails to render due to firm-lookup error.

Endpoints

Method Path Purpose
GET /auditforge/firm List all firms
POST /auditforge/firm Create a new firm
GET /auditforge/firm/{firm_id} Get one
PUT /auditforge/firm/{firm_id} Partial update — only sent fields apply
DELETE /auditforge/firm/{firm_id} Remove (engagements with that firm_id fall back to default branding)

All gated by x-admin-token. See api-reference.md for full request/response shapes.

Frontend

FirmManagement.tsx is a CRUD UI accessible via the "Firms" tab in the AuditForge SPA shell. Color pickers (HTML5 color input + hex text input), logo URL preview, methodology / footer / confidentiality textareas, archetype + default budget pre-fills.

NewEngagementForm.tsx reads from listFirms() and shows a dropdown when firms exist; selecting a firm applies its default_archetype and default_budget_cents to the form. Falls back to a free-text input pre-filled with firm-default when no firms are configured.

Render integration

app/auditforge/report.py calls get_firm_store().get_or_default(engagement.firm_id) at the top of each builder (build_markdown_deliverable, build_docx_deliverable, build_json_deliverable) and applies branding:

  • Markdown: logo image embed → "Prepared by [Firm] — [tagline]" → confidentiality notice as blockquote → at end of methodology, append disclaimer; end of doc, italic footer
  • DOCX: logo placeholder (image upload to be wired in Phase 2.6 polish), prepared-by paragraph with firm color accent, confidentiality notice italic, methodology disclaimer italic, footer paragraph italic
  • JSON: top-level firm block carrying id, display_name, tagline, logo_url, primary_color, footer_text — for downstream tooling that wants to apply its own rendering layer

Code

  • app/auditforge/firm.py — model + store
  • app/auditforge_endpoints.py — five CRUD endpoints
  • app/auditforge/report.py — branding integration in all three deliverable formats
  • frontend/src/components/FirmManagement.tsx — UI
  • frontend/src/api/auditforge.ts — typed API client

Open polish items

  • DOCX logo embedding (currently text-only "Prepared by"; image upload requires async fetch + python-docx image insert)
  • Custom font selection per firm
  • Cover page page-break separator (DOCX has implicit page-break-before-heading; markdown doesn't)
  • Firm-level user accounts (currently the admin token is shared across all firms)