For BPO compliance officers, IT directors & CISOs

FrontLine for Compliance & IT — the procurement questionnaire arsenal.

Immutable audit log. Row-level multi-tenant isolation. PII access log. DSAR workflow. SOC 2 Type II evidence package. Enterprise SSO. Everything an enterprise client's security review asks about — answered in the data model, not in slides.

app.frontlinehq.io/compliance/overview

Compliance dashboard

Acme BPO · 247 agents · 4 clients · SOC 2 Type II — period: Q2 2026

Audit events · 30d

2.1M

PII reveals · 24h

14

Open DSAR requests

2

Active legal holds

3

Compliance surfaces

Audit log · 2,147,892 events · 7y retention

PII access log · Compliance officer only · alerts on

Failed access log · Brute-force + cross-tenant probes

Retention policies · 8 categories · PIPEDA floor enforced

DSAR queue · 2 open · next deadline 7d

Legal holds · 3 active · scope evaluator live

SOC 2 evidence · Q2 package generated · 24h URL

Recent activity

HIGH

SOC 2 Q2 evidence package generated · CC6/CC7/CC9/A1 · 14,217 events · 24h signed URL

12m

MEDIUM

DSAR request submitted (PIPEDA) · Subject employee · deadline 2026-06-18 · stage: in_progress

1h

HIGH

Cross-tenant probe flagged · Actor: api token #4128 · classified HIGH · audit row #au-8921

2h

MEDIUM

Retention policy edit — recruiting_applications_rejected · Window: 730d → 365d · retroactive confirm required (409)

3h

Audit log · last hour

Live

Aisha D.

employee.update

08:42

Hannah C.

pii.read

08:14

Sweep

retention.run

03:00

System

audit.export

Yesterday
Compliance Officers · IT Directors · CISOs

What's hard about compliance at a multi-client BPO

Generic HRMS + scheduling tools answer compliance questionnaires with slides and intent. Enterprise clients sign NDAs that say "your operational data cannot touch ours." The data layer is the only place that answer holds up.

Risk: NDA breach

Every enterprise client signs a different NDA

Each NDA has its own isolation clause: "our agent activity cannot touch other clients' infrastructure." Honoring that across 7+ clients with app-layer scope checks means every new query is one place a cross-client row can leak.

Risk: forensic Excel

The audit log lives in 6 systems

HR, payroll, scheduling, QA — four tools. When legal asks "who changed this record on this date," it's a forensic Excel pull across exports. The answer arrives a week late, never confidently complete.

Window: 30 / 45 days

DSAR requests trigger a 30-day fire drill

"Give me everything you have on me." PIPEDA gives you 30 days, CCPA gives you 45. You start hunting across 6 systems hoping nothing leaks across tenants. Every DSAR is a credibility test you can fail silently.

Cost: 3-week audit

SOC 2 evidence is hand-built each quarter

Cobble logs from across systems, write CSVs, tag by control, draft narrative. The Type II audit takes three weeks every year — if nothing's missing. The compliance officer assembles the same package instead of working the next risk.

Risk: PII leak

PII access is a Slack message away from a leak

Without a separate PII access log + role-based scoping, every employee with HR access can see national IDs whether they need to or not. When a privacy incident lands, you can't prove the scope of exposure.

Procurement: SSO matrix

SSO works for 4 clients, not 7

Entra ID, Okta, Google Workspace, native fallback for the small ones. Most platforms support 2 well and 1 badly. Enterprise procurement asks about all four — plus MFA, device trust, and an audited break-glass path.

What FrontLine does

What FrontLine gives compliance & IT

Seven controls procurement questionnaires actually ask about — wired into the data model, not bolted onto a dashboard. Every claim below is testable from the codebase or the Atlas.

Feature 01

Immutable audit log + unified viewer

Every change to every record across HR, scheduling, QA, training, billing — one audit_events table. Write-only by architecture: no DELETE, no UPDATE endpoint. Filter the live log by actor, action, resource, date range, IP, free-text. CSV/JSON export hard-capped at 50K rows; every export emits its own audit event so chain-of-custody is intact.

  • Immutable by architecture. No DELETE or UPDATE endpoint on the audit-log routes. The table is write-only. There is no "admin override" path.
  • Unified across modules. HR, scheduling, QA, training, billing, recruiting, onboarding, change requests, policy acks, retention, DSAR — all emit to the same audit_events table.
  • Queryable in seconds. Filter by actor_id, action prefix, resource_type, resource_id, date range, client_account_id, client_lob_id, IP, free-text search across action + metadata.
  • Export with chain-of-custody. CSV / JSON export hard cap 50K rows; truncation flag in response. Every export emits its own audit event (the auditor sees you exported it).
  • Cursor-paginated. 50-200 rows per page. Spec 36 §4 prevents accidental full-table scans by privileged users.
app.frontlinehq.io/compliance/audit-log

Unified audit log — every change to every record

Filters

Actorany
Actioncompliance.*
Resourceany
Date rangeLast 30 days
Resultany
Session IDany

Events · 2,147,892 total · cursor-paginated

09:42:18Z

j.tremblay@belov.com

compliance.soc2.package_generated

soc2:Q2-2026

OK
09:38:02Z

p.singh@belov.com

employees.private_profile.national_id.reveal

employee:emp-1284

OK
09:35:11Z

api-token-4128

auth.session.cross_tenant_probe

tenant:other-tenant

DENIED
09:32:47Z

j.tremblay@belov.com

compliance.retention_policy.update

policy:recruiting_apps

409
09:28:33Z

system-worker

compliance.retention_run.purge

category:dsar_records

OK
09:24:01Z

m.brown@belov.com

compliance.legal_hold.create

hold:case-2024-08

OK

Export CSV / JSON · 50K row cap · every export emits its own audit event.

Feature 02

PII access log + failed-access detection

Two separate filtered surfaces over the audit log. PII reveals (national IDs, addresses, private notes) and authentication failures land in their own viewers, scoped to the compliance_officer role. Cross-tenant probes (JWT tenant_id ≠ resource tenant_id) auto-classify HIGH severity; brute-force aggregation per actor + IP surfaces a credential-stuffing wave before it drowns in single-row noise.

  • PII access is its own log. 8 baseline PII actions tracked (national_id.read, home_address.read, private_note.read, etc.). Filtered projection over audit_events; compliance_officer-only view.
  • Per-employee report. /compliance/pii-access-log/report rolls up access events per employee. When an employee asks 'who looked at my record,' the answer is one screen.
  • Failed/denied access surface. Auth failures, permission denials, cross-tenant probes — one log. Brute-force aggregation (≥5 failures from same IP in 10 min) surfaces patterns; cross-tenant probes auto-flagged HIGH severity.
  • On the roadmap — purpose annotation + volume alerts. A purpose-annotation gate (HR admin declares why before a reveal returns) and tenant-configurable volume alerts (e.g., ">5 national_id reveals by same actor in 1 hour") are on the Atlas roadmap. Today the PII access log is investigative-grade: every reveal is captured with actor + timestamp + scope, and the compliance officer can query it. The alert worker that fires on volume thresholds is a deferred phase of spec 36 — track it on the Atlas.
app.frontlinehq.io/compliance/pii-access-log

PII access log — compliance officer view

PII reveals · 8 baseline actions tracked

Filtered projection over audit_events · compliance_officer only · HR admin denied

09:38:02Z

p.singh@belov.com

national_id.reveal

AGT-1284

Onboarding verify

09:24:11Z

m.brown@belov.com

private_note.read

AGT-1612

HR case investigation

08:51:47Z

h.davis@belov.com

home_address.read

AGT-2298

Records change

08:42:09Z

p.singh@belov.com

national_id.reveal

AGT-1284

Onboarding verify

08:14:33Z

p.singh@belov.com

national_id.reveal

AGT-2417

Onboarding verify

07:58:21Z

p.singh@belov.com

national_id.reveal

AGT-1284

Onboarding verify

ALERT: p.singh@belov.com — 5 national_id.reveal in 1h45 · threshold (≥5/1h) tripped · notification fired to compliance officers.

Feature 03

DSAR (PIPEDA + CCPA) workflow with right-to-erasure

Request intake → deadline tracking → cross-module data collection → ZIP package + signed-URL download → erasure with legal-hold precheck. PIPEDA's 30-day clock or CCPA's 45-day clock starts on submit; deadline alerts at 7d / 3d / day-of. Erasure is field-level anonymization with deterministic tokens — relational integrity survives, original values don't. Audit logs are never erased.

  • Per-jurisdiction deadlines. PIPEDA = submitted_at + 30 days; CCPA = submitted_at + 45 days. State machine survives: SUBMITTED → IN_PROGRESS → DATA_GATHERED → REVIEWED → FULFILLED, with PENDING_HOLD_RELEASE + REJECTED_WITH_REASON branches.
  • Cross-module collection. 6 module-specific DSAR collectors live today — employees, private info, recruiting + assessment, onboarding, workforce, notifications, service desk. ZIP package with manifest.json + one JSON per module.
  • Field-level anonymization. Not hard deletion. Deterministic per-tenant tokens preserve foreign keys; original values gone. Per-field retention reasons captured (regulatory floors honored).
  • Audit logs never erased. Architectural constraint. PIPEDA's 7-year minimum retention applies. The erasure surface explicitly excludes audit_events; auditors trust this.
  • Legal-hold precheck. Before erasure runs, the legal-hold scope evaluator checks the subject. If held, the request transitions to PENDING_HOLD_RELEASE; the clock pauses and resumes on hold release.
app.frontlinehq.io/compliance/dsar/req-4221

DSAR request #req-4221 — PIPEDA

Subject: former employee · request type: ACCESS + ERASURE

Submitted 2026-05-19 · deadline 2026-06-18 (30 days · PIPEDA)

PIPEDA30 days

Submitted

2026-05-19 09:14 · intake form · subject identity verified

In progress

Collectors running: employees, private_info, recruiting, audit_events

Data gathered

ZIP package ready · manifest.json + 6 module JSONs

Reviewed

Compliance officer signed off · legal hold precheck: clear

Fulfilled

Signed-URL download issued · erasure runs · audit row captured

Every state transition audit-logged. Erasure runs through legal-hold precheck. Audit log itself never erased.

Feature 04

Retention policies + legal holds

Per-category retention windows (employee records, payroll, audit, PII access, DSAR, chat, QA, recruiting) with PIPEDA's 7-year floor as a hard minimum. Dry-run preview default; retroactive stricter changes require explicit confirmation. Legal holds override retention — held records skip purge automatically. Both creation and release are MFA-gated and idempotent.

  • 8 retention categories. Configurable per tenant, with regulatory floors as hard minimums (7-year for employee records, payroll, audit, PII access events).
  • Dry-run preview. Every policy change ships in dry-run mode by default. Preview which rows would be purged or archived before commit. Live runs require an explicit confirmation step.
  • Retroactive-application gate. Stricter retention changes (tighter window) return 409 RETROACTIVE_CONFIRMATION_REQUIRED until acknowledged. A tighter rule cannot silently delete years of history.
  • Legal holds override retention. Hold scope is JSONB: employee_ids, candidate_ids, date_range, data_categories, client_account_ids. The retention executor consults recordMatchesAnyHold() before every purge.
  • Both MFA-gated. Policy changes + hold create/release require X-MFA-Verified + Idempotency-Key. Audit-trail captured for every change.

Retention policies + legal holds

Retention policies · 8 categories

Employee records

7 yearsARCHIVE

Audit log

7 yearsARCHIVE

Payroll & T&A

7 yearsARCHIVE

PII access events

7 yearsARCHIVE

DSAR records

3 yearsARCHIVE

Chat transcripts

1 yearPURGE

QA evaluations

3 yearsARCHIVE

Recruiting (rejected)

1 yearPURGE

Active legal holds · 3

case-2024-08

12 employees · audit + private_info

Active
case-2025-02

Recruiting records · 2025-Q1

Active
case-2025-12

Single candidate · 30-day window

Released

Holds override retention — held records skip purge automatically. Create + release MFA-gated.

Feature 05

SOC 2 Type II evidence package — one query, not a quarter

Pre-built ZIP export of audit events organized by SOC 2 trust services criteria — CC6 (Logical Access), CC7 (System Operations), CC9 (Change Management), A1 (Availability). Period-bounded; one CSV per criterion. The Type II evidence collection that used to take 3 weeks is one signed-URL download. Generation itself emits a CC9 audit event so the auditor sees you generated it.

  • 4 trust services criteria. CC6 (Logical Access), CC7 (System Operations), CC9 (Change Management), A1 (Availability). Each maps to specific audit-event action prefixes per spec 36 §11.
  • Period-bounded. Specify period_start + period_end on generation. Out-of-period events excluded. Audit-window-friendly.
  • Cover sheet + CSVs. cover_sheet.json lists categories with record_count + scope_note; one CSV per requested category. Auditors load it into their workpapers as-is.
  • Self-referential audit. Generation event (`compliance.soc2.package_generated`, severity HIGH) shows up in the next CC9 export. The auditor literally sees the timestamp of when you collected the evidence.
  • 24h signed-URL TTL. Download links expire. No long-lived URL leaking the auditor-facing evidence package on a shared drive.
app.frontlinehq.io/compliance/soc2

SOC 2 Type II evidence package

Period

Apr 1 → Jun 30, 2026 (Q2)

CC6

Logical Access

4,128 events

.csv
CC7

System Operations

6,892 events

.csv
CC9

Change Management

2,447 events

.csv
A1

Availability

750 events

.csv

Package contents

cover_sheet.json + 4 CSV files (one per criterion) · ZIP · 24h signed URL

Generation emits compliance.soc2.package_generated (severity HIGH) — appears in next CC9 export.

Feature 06

Tenant + account row-level isolation (RLS)

tenant_id and client_account_id scoped at the PostgreSQL row level via RLS policies. Cross-account queries return zero rows at the database — not in app code. The same data infrastructure handles a 50-agent fintech client and a 2,000-agent retail client without either being able to query the other. Survives the security review's "try to fetch another tenant's data" probe.

  • Enforced in the database. RLS policies on tenant_id (every table) + client_account_id (every operational table). The database refuses cross-tenant queries — there is no application-layer filter to forget.
  • JWT carries the context. current_setting('app.current_tenant_id', true) sourced from JWT claims; immutable within a request lifecycle (per ADR-001). No request handler can switch tenants mid-request.
  • Cross-tenant probes flagged. When a request's JWT tenant_id doesn't match a referenced resource's tenant_id, the audit event is auto-classified `auth.session.cross_tenant_probe` at HIGH severity. The security team sees the probe before it's a leak.
  • 50+ tables under RLS. Every table holding tenant data — including compliance tables themselves. Integration-tested per spec 12.
  • Sole exception: audit_events read. compliance_officer reads can span the tenant's full audit history without RLS narrowing — but never across tenants. The architecture lets you investigate within your own tenant scope.

Row-level isolation — try to query another tenant

SET app.current_tenant_id = 'belov-tenant';

SELECT * FROM employees WHERE tenant_id = 'other-tenant';

RLS policies

employees

tenant_isolation · client_account_scope

audit_events

tenant_isolation

compliance_dsar_requests

tenant_isolation

client_user_account_bindings

tenant + account scope

Result

(0 rows)

The database refused the query — RLS policy filtered it before app code saw any data. No filter to forget.

Same query without tenant context → audit row `auth.session.cross_tenant_probe` severity HIGH.

Feature 07

Enterprise SSO + RBAC

OIDC and SAML 2.0 with Entra ID, Okta, Google Workspace, or any standards-compliant IdP. Native email/password fallback for break-glass and small clients. MFA via TOTP or email OTP; device trust cookie (30-day TTL) for trusted-device MFA bypass. Permissions follow `<module>.<resource>.<action>` keys with role defaults per tenant — about 80 permissions registered today across all modules.

  • OIDC + PKCE. Authorization Code + PKCE + state + nonce validation. Discovery URL configurable per IdP. Entra ID, Okta, Google Workspace tested against real IdPs.
  • SAML 2.0. Signed assertions, replay-attack prevention, 5-minute clock skew tolerance. Metadata XML upload or paste-in.
  • Native fallback. Email/password with HaveIBeenPwned breach check on registration. Tenant policy (enforce_sso vs allow_native_break_glass) controls availability.
  • MFA + device trust. TOTP or email OTP. Optional by default; tenant policy mfa_required_for_all forces. Device trust cookie 30-day TTL for trusted-device bypass; revocable per session.
  • RBAC permission keys. <module>.<resource>.<action> — e.g., `compliance.audit_log.export`, `recruiting.requisition.create`. ~80 permissions across all modules. Role defaults per tenant; client role locked to client-portal endpoints only.
app.frontlinehq.io/admin/sso

Enterprise SSO + RBAC

Identity providers

Microsoft Entra ID

OIDC + PKCE

Active

Okta

SAML 2.0

Active

Google Workspace

OIDC

Active

Native (fallback)

Email + password

Break-glass

Tenant policy

enforce_sso = true · native allowed for break-glass only

mfa_required_for_all = true · TOTP or email OTP

device_trust_ttl = 30 days · revocable per session

RBAC permission example

compliance_officer → compliance.* (wildcard) · hr_admin → compliance.dashboard.read + compliance.audit_log.read (no export)

For the decision maker

Business outcomes for the people running the BPO

What this looks like for the COO, CISO, or compliance lead.

Procurement

Enterprise security reviews close in days, not weeks

The procurement questionnaire that used to chew up two weeks of compliance + IT time across multiple disciplines closes in days. Every checkbox has an architectural answer — not a slide-deck intent. Win the deal you'd have stalled on.

Audit

SOC 2 Type II evidence becomes one signed-URL download

The 3-week annual scramble becomes a single ZIP per period. CC6 / CC7 / CC9 / A1 categories pre-bundled. The auditor opens it and starts working — no "can you also send the change log for Q2?" follow-ups.

Risk

Cross-tenant data exposure is structurally impossible

Row-level isolation in the database means the worst-case query — "give me agents from another tenant" — returns zero rows. Not handled in app code, not gated by middleware, not depending on a developer remembering. The platform itself refuses.

Liability

DSAR fire drills become 30-day workflows

PIPEDA's 30 days and CCPA's 45 days are workflow milestones, not panic triggers. Deadline alerts at 7d / 3d / day-of. Erasure runs through a legal-hold precheck. The case file at fulfillment is its own audit trail.

What compliance & IT actually gets back

Directional outcomes — real magnitude depends on your prior audit workflow and starting baseline. The architectural properties (RLS, immutable audit, DSAR state machine) are not estimates — they ship as the platform.

SOC 2 evidence

Weeks → days

Pre-built CSVs per trust criterion replace the quarterly cobble-from-CSVs exercise. Magnitude depends on your prior cycle length.

Audit log

One immutable table, every event

Every change, every read of PII, every cross-tenant probe — one append-only audit table. No spread across module-specific logs to reconcile.

Cross-tenant isolation

Zero cross-tenant query paths

Row-level isolation in the database. No application-layer filter to forget — the data physically can't be queried across tenant boundaries.

DSAR turnaround

Statutory deadlines tracked in-app

PIPEDA + CCPA deadlines tracked in-app with alerts at 7d / 3d / day-of. No spreadsheet for compliance to chase.

Regulatory & framework posture

PIPEDA (Canada)CCPA / CPRA (California)Law 25 (Quebec)SOC 2 Type II — evidence-package generator (audit Q3 2026)HIPAA-aware (workforce-side handling)PCI-DSS aware (recordings live in your CCaaS)GDPR-aligned subject rightsAODA · WCAG 2.1 AAAudit log (7-year floor)Tenant + account RLS

FrontLine for Compliance & IT vs. a generic HRMS

Six things compliance + IT teams notice in their first procurement questionnaire after a generic HRMS.

FrontLine for Compliance & ITGeneric HRMS

Row-level multi-tenant isolation enforced in the database

Generic HRMS shares schemas across all tenants; isolation is in application code — easy to bypass with a new query.

Immutable audit log with no UPDATE / DELETE endpoints

Generic HRMS audit logs typically allow admin override or soft delete. FrontLine's table is write-only by architecture.

DSAR workflow (PIPEDA + CCPA) with deadline tracking

Generic HRMS has no DSAR concept. You build the workflow yourself with email + Excel.

SOC 2 Type II evidence package generator

Generic HRMS gives you the data; assembling Type II evidence is your problem (and your auditor's headache).

OIDC + SAML SSO with native fallback + MFA + device trust

Generic HRMS supports one IdP family well, others poorly. Native fallback is often missing or required-by-default.

RBAC with `<module>.<resource>.<action>` permission keys

Generic HRMS RBAC is role-name-coupled — not permission-keyed. Custom roles require vendor support tickets.

In production today

Compliance and Audit Dashboard (Module 36) shipped 2026-05-17 — full coverage: audit log + PII access log + DSAR workflow + retention + legal holds + SOC 2 evidence + right-to-erasure. Authentication (11) and RBAC (11A) shipped earlier alongside the core platform. See feature-level status on the Atlas.

FAQ

Questions compliance & IT actually ask before signing

Pulled from real fit calls. Short, direct answers.

What stops one of our tenants from querying another's data?+
PostgreSQL row-level security policies on tenant_id (every table) and client_account_id (every operational table). JWT carries the tenant context; current_setting('app.current_tenant_id', true) is set per-request from claims and immutable within the request lifecycle (per ADR-001). The database refuses cross-tenant queries — there is no application-layer filter to forget. Cross-tenant probes are also auto-classified at HIGH severity in the audit log.
Is the audit log actually immutable, or just soft-deleted?+
The audit_events table has no DELETE or UPDATE endpoint. The routes don't exist. There is no admin override path. It is architecturally write-only — the only way to remove a row is a manual database operation that itself triggers an alert. The 7-year retention floor (PIPEDA) is enforced as a hard minimum on the retention policy engine.
What's the DSAR turnaround? And how do you handle erasure under legal hold?+
PIPEDA = 30 days from submitted_at; CCPA = 45 days. State machine with deadline alerts at 7d / 3d / day-of. For erasure: the legal-hold scope evaluator runs as a precheck. If the subject matches an active hold, the request transitions to PENDING_HOLD_RELEASE and the deadline clock pauses; both resume on hold release. Erasure itself is field-level anonymization with deterministic tokens — relational integrity survives, the original PII does not. Audit logs are never erased (architectural).
What does the SOC 2 Type II evidence package actually contain?+
A ZIP per period (you specify start + end) with a cover_sheet.json + one CSV per requested SOC 2 trust services criterion. We cover CC6 (Logical Access), CC7 (System Operations), CC9 (Change Management), and A1 (Availability). Each CSV is the filtered audit events for that criterion's action prefixes per spec 36 §11. The generation event itself emits a CC9 audit event — so the next period's package shows the auditor when you collected the evidence.
Which IdPs do you support? And do you require SSO?+
OIDC (Authorization Code + PKCE + state + nonce validation) tested against Microsoft Entra ID, Okta, Google Workspace, and any discovery-URL-compliant OIDC IdP. SAML 2.0 with signed assertions, replay-attack prevention, and 5-minute clock skew tolerance via metadata XML upload. Native email/password is available as fallback with HaveIBeenPwned breach check on registration; tenant policy (enforce_sso vs allow_native_break_glass) controls whether native is allowed.
Can we get a custom role with very specific permissions?+
Yes. Permissions follow `<module>.<resource>.<action>` keys — e.g., `compliance.audit_log.export`, `recruiting.requisition.create`. There are about 80 permissions registered across modules today. Tenant admins compose roles from those keys; we can also pre-build custom roles for procurement-specific requirements during onboarding. The client role is restricted to client-portal endpoints by architecture — no escape hatch.
What about MFA? Device trust? Break-glass?+
MFA via TOTP or email OTP. Optional by default; tenant policy mfa_required_for_all forces it. Device trust cookie (30-day TTL) lets a trusted device skip MFA on subsequent logins — revocable per session, and break-glass attempts (account-locked, native fallback) emit their own HIGH-severity audit events for review.

Ready for the procurement review?

Two ways to take the next step.

FrontLine for Compliance & IT | FrontLine