Identity.

BackPro does not own the firm's identity layer. Authentication lives with the firm's IdP. Every meaningful action is attributed to a real person, or to a named service account with a real human owner, and signed into an audit log that the firm can verify without us.

The shape

One identity provider. One audit log. Both signed.

The firm's IdP is the single source of truth for who. The audit log is the single source of truth for what. Neither is owned by BackPro; the audit log is signed with a key held in the firm's key vault and can be verified offline.

              ┌──────────────────────────┐
              │   Firm IdP               │
              │   (Entra · Okta · Google)│
              └─────────────┬────────────┘
                            │ SAML / OIDC
                            ▼
              ┌──────────────────────────┐
              │   BackPro session        │
              │   (short-lived, JWT)     │
              └──────┬───────────────────┘
                     │
       ┌─────────────┼─────────────┐
       ▼             ▼             ▼
  Reads:        Writes:       Every action:
  RAG over      Drafts +      Appended to
  read-only     named         signed audit
  connectors    approver      log (HMAC + key
                workflow      held in firm KV)
                     │
                     ▼
              ┌──────────────────────────┐
              │   Audit log              │
              │   Append-only · Signed   │
              │   Exportable, verifiable │
              └──────────────────────────┘
I
Single sign-on

The firm's IdP authenticates. BackPro doesn't.

BackPro supports SAML 2.0 (preferred for enterprise IdPs: Entra ID, Okta) and OIDC (preferred for Google Workspace and modern providers). The firm publishes its metadata; BackPro consumes it; no shared secrets are exchanged outside the metadata document.

Group claims from the IdP map to BackPro roles via a firm-defined mapping table, the firm can re-map without re-deploying BackPro and without involving us.

SAML metadata snippet (BackPro as SP)
<?xml version="1.0" encoding="UTF-8"?>
<EntityDescriptor
  xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
  entityID="https://{firm-tenant}.backpro.ai/saml/metadata">

  <SPSSODescriptor
    AuthnRequestsSigned="true"
    WantAssertionsSigned="true"
    protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">

    <KeyDescriptor use="signing">
      <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
        <X509Data><X509Certificate>{firm-sp-cert}</X509Certificate></X509Data>
      </KeyInfo>
    </KeyDescriptor>

    <NameIDFormat>
      urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress
    </NameIDFormat>

    <AssertionConsumerService
      Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
      Location="https://{firm-tenant}.backpro.ai/saml/acs"
      index="0" isDefault="true"/>

    <SingleLogoutService
      Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
      Location="https://{firm-tenant}.backpro.ai/saml/slo"/>

  </SPSSODescriptor>

  <ContactPerson contactType="technical">
    <EmailAddress>contact@backpro.ai</EmailAddress>
  </ContactPerson>
</EntityDescriptor>
II
Role model

A small role surface, deliberately.

Five roles cover every firm we've worked with. Smaller surfaces are easier to audit than infinitely flexible ABAC graphs that nobody reads. Customers who need finer slicing get it via the IdP's group claim, which can be mapped onto data-scope filters without inventing a sixth role.

RoleWhat it doesReadsWrites
AdviserAuthors and approves client-facing documents.Their own client book.SoAs, fee consents, ROAs. Signs as named approver.
ParaplannerDrafts artefacts for adviser review.Assigned client folders.Drafts only, never signs the final record.
Compliance OfficerReviews artefacts against the firm's control library.Whole firm. Audit log. Approvals queue.Issues findings; cannot edit client-facing documents.
Principal / Practice ManagerOperational oversight + commercial reporting.Whole firm.Workflow configuration. No artefact authorship.
Auditor (external)Time-boxed read-only access for external review.Scoped to a date range + matter list.Nothing. Cannot export bulk PII.
III
Service accounts

Service accounts have a human owner. Always.

Where a platform doesn't support OAuth-on-behalf-of, the firm provisions a named service account. The connector authenticates as that account. The account's human owner is a named employee of the firm, recorded in the evidence pack and reviewed every 90 days. Service accounts cannot be owned by "IT" or a shared mailbox.

Rotation policy: credentials are rotated on a 90-day schedule or immediately on owner change. BackPro emits a webhook 14 days before expiry; the firm rotates without our involvement.

IV
Audit log

Append-only. Signed. Verifiable without us.

Every action is a log entry. Each entry is hash-chained to its predecessor and HMAC-signed with a key the firm holds in its own key vault. The auditor can verify the chain offline; a tampered or removed entry breaks the chain at a known offset.

Log entries are retained for the contractual period (typically seven years for financial advice) and exported on request as a single signed bundle. No log entry leaves the tenancy unless the firm explicitly exports it.

Audit log entry, JSON schema (excerpt)
{
  "$schema": "/schemas/audit-log/v1.json",
  "type": "object",
  "required": ["id", "ts", "actor", "action", "resource", "prev_hash", "signature"],
  "properties": {
    "id":        { "type": "string", "format": "uuid" },
    "ts":        { "type": "string", "format": "date-time" },
    "tenant":    { "type": "string" },
    "actor": {
      "type": "object",
      "required": ["principal_id", "principal_type", "ip", "session_id"],
      "properties": {
        "principal_id":   { "type": "string" },
        "principal_type": { "enum": ["user", "service_account"] },
        "owner_id":       { "type": "string", "description": "Required iff service_account" },
        "ip":             { "type": "string" },
        "session_id":     { "type": "string" }
      }
    },
    "action":    {
      "enum": [
        "AUTH.LOGIN", "AUTH.LOGOUT",
        "READ.DOCUMENT", "READ.CRM_RECORD",
        "DRAFT.CREATE", "DRAFT.SUBMIT",
        "APPROVE.SIGN", "APPROVE.REJECT",
        "WRITE.DELIVER",
        "CONFIG.CHANGE", "EXPORT.AUDIT"
      ]
    },
    "resource":  {
      "type": "object",
      "required": ["type", "id"],
      "properties": {
        "type":   { "enum": ["document", "client", "draft", "config", "audit_export"] },
        "id":     { "type": "string" },
        "scope":  { "type": "string" }
      }
    },
    "metadata":  { "type": "object", "description": "Action-specific payload" },
    "prev_hash": { "type": "string", "pattern": "^[0-9a-f]{64}$" },
    "signature": { "type": "string", "description": "HMAC-SHA256(prev_hash || entry_body, audit_key)" }
  },
  "additionalProperties": false
}
V
Session + token policy

Short-lived everything.

Sessions are 8 hours by default, tunable to the firm's policy. Access tokens expire in 15 minutes. Refresh tokens are rotated on every use and revoked on logout. Tokens are never written to disk; they live in memory and in the firm's session store (typically Redis on the firm's infrastructure).

Step-up authentication is required for any write that crosses the firm's defined threshold (default: any action with monetary or regulatory impact). The step-up challenge is delegated to the IdP, BackPro does not implement MFA in-house.

Session config (default)
# Session and token defaults — overridable per firm at deploy time
sessions:
  session_max_hours:       8        # hard cap; user re-authenticates after
  idle_timeout_minutes:    30       # forces re-auth on returning user
  step_up_required_for:
    - APPROVE.SIGN
    - WRITE.DELIVER
    - CONFIG.CHANGE
    - EXPORT.AUDIT

tokens:
  access_token_ttl_seconds:    900     # 15 min
  refresh_token_ttl_hours:     8       # cannot exceed session_max_hours
  refresh_rotation:            on_use  # rotate on every refresh
  revoke_on_logout:            true
  bind_to_session_id:          true    # tokens scoped to the session

storage:
  token_storage:               memory     # never persisted on BackPro disk
  session_store:               firm_redis # firm-owned, in-tenancy
VI
PII outside production

PII never leaves production.

Staging, QA, and developer environments are seeded with synthetic data. Production data is never copied into a non-prod environment, even temporarily. Where production issues require a debugging copy, the firm exports a redacted slice: names, emails, phone numbers, dates of birth, account numbers, addresses, and free-text fields are replaced before the data ever leaves prod.

The redaction contract is open-source within the firm's tenancy: it's the same code that runs the redaction, and the firm can audit it before any export.

Redaction policy (excerpt)
# Applied before any prod → non-prod data movement.
# Fail-closed: any column without an explicit rule is dropped.
fields:
  # Direct identifiers, replaced with deterministic synthetic values
  - { match: "client.full_name",        rule: "fake_name",       seed: "tenant_id" }
  - { match: "client.email",            rule: "fake_email",      seed: "tenant_id" }
  - { match: "client.phone",            rule: "fake_phone",      seed: "tenant_id" }
  - { match: "client.dob",              rule: "shift_date",      range_days: 180 }
  - { match: "client.address.*",        rule: "fake_address",    seed: "tenant_id" }

  # Account + reference numbers — masked but length-preserving
  - { match: "*.account_number",        rule: "mask_keep_last4" }
  - { match: "*.tfn",                   rule: "drop" }
  - { match: "*.medicare_number",       rule: "drop" }

  # Free text — replaced with synthetic prose of the same length class
  - { match: "soa.body",                rule: "synthetic_prose" }
  - { match: "note.body",               rule: "synthetic_prose" }

policy:
  default:                              "drop"   # fail closed
  reversible:                           false    # one-way; not joinable to prod
Under NDA

Full identity runbook, threat model, and the live audit-log verification CLI, releases under NDA on request. contact@backpro.ai.