Conformiti
ProductEditionsPricing ConsultingSelf-hostDocs Security GitHub Book a demo

Documentation

How it is organised,
and how to use it.

This page is the orientation. The authoritative documents live in the repository and are versioned with the code. Every link below goes to the file on main. Check out your own tag if you are running an older release.

Concepts

Eight ideas, and you have the model.

Framework → category → control

SOC 2, ISO/IEC 27001:2022 and PCI DSS v4.0.1 ship pre-loaded: 217 controls. Each has a status (not started, in progress, implemented, not applicable), an owner and a count of linked evidence. Readiness is implemented ÷ applicable.

Folders and documents

Evidence lives in a tree generated from the control libraries, plus any subfolders you add. Access is granted per folder, by role or by user, at view, edit or manage, and inherited down the tree. Documents carry a review cadence and a next-review date, which drive reminders.

Evidence links

A many-to-many mapping between controls and documents. One Access Control Policy can satisfy CC6.1, A.5.15 and 7.1; one control can cite many documents. Editable from either side, and unlinking anywhere unlinks everywhere.

Risks

Register entries scored on a 5×5 likelihood × impact matrix (low / moderate / high / critical), with status, treatment, owner, an optional control and Jira key, a due date and a note trail. Import from CSV or XLSX; export to CSV.

Access reviews

Point-in-time snapshots of every account, on which an administrator records keep, modify or revoke: the periodic user-access review SOC 2 and ISO expect. The grid exports as evidence, and a completed review is read-only from that moment.

Audit trail

Every successful mutating request the API serves (apart from the notification tray and the health check, which are excluded) plus every sign-in, failed sign-in (with the reason) and sign-out, with actor, record, the field names touched (never the values) and the IP. The REST API exposes no create, update or delete method on the trail. It is written only by server-side middleware. The Django admin is the exception: an operator account with the delete permission can still remove rows there, which is one more reason to keep /admin/ off the network.

Readiness history

A snapshot is recorded every day, and on the first dashboard visit of a day. The dashboard trend and the month-over-month delta come from those snapshots rather than from a figure recomputed on each page view.

Workspaces

The tenant. Every organisation-owned row belongs to one, and every query is scoped to the active workspace at the ORM level. A single-organisation install has one, called Default, and never notices it exists.

Roles

Who can do what.

Capabilities are enforced by the API. The interface shows a write control only where the API would accept the write, not the other way round.

Role capabilities
RoleCan
AdministratorEverything, including users, roles, access reviews and integrations. Cannot lock themselves out, and the API will never leave a workspace with no active administrator.
Compliance ManagerFrameworks and control statuses, all folders and documents, risks, meetings, calendar, vendors, packages. Sees the whole tree.
Control OwnerEdit documents in folders granted to them, update risks they own, add meeting minutes, answer PBC lines assigned to them, including on packages they cannot otherwise see.
AuditorRead-only: the audit log, access reviews, and folders granted to them: capped at view regardless of what grant is applied. Folder grants gate folders and documents only, so an Auditor account also reads the control register, risks, vendors, the RACI matrix, the calendar and analytics, as any signed-in account does. An external auditor is given an Auditor account plus a per-person package grant, and it is that grant which reaches the evidence pinned into the package and the request list attached to it.
ViewerNo capability flags at all: folders granted to them, plus the read-only registers any signed-in account can see. No write anywhere.
Custom rolesDefined from the same capability flags: manage users, manage frameworks, manage documents, manage folders, view all, auditor.

How effective folder access is resolved

Folder.effective_access(user) returns the highest of:

  1. manage  if superuser, or role.can_manage_folders
  2. view    if role.can_view_all
  3. manage  if the user owns the folder
  4. the strongest FolderPermission for the user or their role
     on this folder or any ancestor   (inheritance)

then: an Auditor role is capped at view.

Documents inherit their folder's access. A document owner may always
edit their own document; deleting it requires manage on the folder.
Re-parenting requires manage on the folder and edit on the
destination. Generated framework folders are immutable through the API.

Screen by screen

The day-to-day reference.

What each screen does and who can use it
ScreenWhat you do thereWho
DashboardOverall readiness with trend and status bar; framework, document and overdue-review cards; evidence coverage; risk posture; the compliance calendar; and “Reviews coming up” with Mark reviewed inline.Everyone
AnalyticsFramework readiness bars, control and document status donuts, review load for the next six months, ownership coverage across controls, documents and risks, and the most overdue documents.Everyone
ControlsFilter by framework and status, search by reference or title, expand for the objective and evidence, set status and owner, attach or unlink evidence, Export CSV.Read: everyone
Write: managers
DocumentsThe folder tree (arrow keys to move and expand, Enter to select) beside the document list. Upload, rename, mark reviewed, version, map controls, add subfolders. With manage: grant access and delete folders you created.By folder grant
RisksFilter live / closed / all, download the CSV template, import CSV or XLSX, create and edit entries, export. Notes can be added by anyone with access.Write: managers or the risk's owner
VendorsRegister, tier, data handled, assurance on file with expiry, the shared responsibility matrix (typed, prompted or imported), and the questionnaire, including Send to the vendor.Read: everyone
Write: managers
ResponsibilityThe RACI matrix per control across people and vendors, with implied assignments shown and the gaps counted.Read: everyone
Write: managers
Audit packagesAssemble, seal, issue, withdraw. Sampling and populations. The PBC request list, with lines assigned to you listed even if you cannot see the package. That is for control owners; an external auditor reaches the list only through their package grant, so revoking the grant ends the access.Assemble: managers
Conclude: the auditors the package is issued to
UsersCreate accounts with a temporary password of 12+ characters, assign roles, set passwords, deactivate, delete, reset a person's second factor.Administrators
User auditStart new review to snapshot every account, record a decision and note per row, export CSV, then Complete review: refused while any row is pending.Administrators
Auditors: read-only
Audit logFilter by action, record type, user and time window; search detail, record or IP; page through history.Administrators, auditors, view-all managers
MeetingsSeries with a required cadence per year, and the minutes recorded against them with an optional attachment. The badge compares minutes held with what the calendar demands so far.Add series: managers
Minutes: owners
GroupsChampion groups with an accountable owner and members tagged by the department they represent.Administrators
JiraConnect one Atlassian site per workspace (base URL, account email, API token: stored server-side, encrypted at rest, never sent to the browser) and track boards by id. Read-only: Conformiti never creates or transitions an issue.Connect: administrators
Read: everyone
SettingsProfile · Appearance (four theme packs, four accent packs, a custom accent) · Security (password, TOTP, backup codes, passkeys) · Notifications · Role & access · About.Everyone, for themselves

Full narrative version: USER_GUIDE.md in the repository.

API

The interface is a client of it.

Django REST Framework, with the SPA as its first consumer. Anything the interface can do, a script can do: under the same permission checks, and writing the same audit-trail entries.

Authentication

  • POST /api/auth/token/ → access (60 min) + refresh (7 days)
  • Accounts with a second factor receive { mfa_required, factors, passkey? } until an otp (authenticator or backup code) or a passkey assertion is supplied
  • POST /api/auth/token/refresh/ rotates the refresh token and blacklists the old one
  • POST /api/auth/logout/ blacklists the current token
  • HttpOnly cookie transport is the default since 0.6.1, with __Host-/__Secure- prefixes derived from the deployment
  • Login, failed login (with the reason) and logout are audit events

Conventions

  • Every list of organisation-owned rows is scoped to the caller's workspace on the queryset, and the filter is carried through every chain, so a view that forgets to filter still cannot reach another workspace's rows. Folder grants gate folders and documents specifically. The other registers are readable by any account in the workspace
  • A superuser may target another workspace with X-Workspace: <slug>
  • Per-client login and refresh throttling, with the counters in Redis in the Docker stack so the limit is shared across workers (a bare install falls back to per-process memory). Set NUM_PROXIES to your proxy hop count if you front it differently. This is rate limiting, not account lockout. There is no per-account failure counter
  • Mutations are recorded with the field names touched; password, token and code keys are dropped before the entry is written
  • GET /api/health/ is unauthenticated and unthrottled on purpose, and reports six things: status, version, database, whether the seeded demo accounts are still present, scanner state and signing state
Principal API endpoints
EndpointPurpose
/api/frameworks/ · /api/controls/The control libraries, statuses, owners and the crosswalk. CSV export of the register.
/api/folders/ · /api/documents/The evidence tree, uploads, versions, review marking, and per-folder permission grants.
/api/documents/{id}/preview/Grant-gated, audited render of a document for the in-browser viewer. Magic-byte checked; Office formats returned as structure, not markup.
/api/risks/ · /api/risk-notes/The register, the note trail, and the CSV/XLSX importer.
/api/access-reviews/Snapshot creation, per-row decisions, CSV export and completion.
/api/vendors/Register, assessments and assurance. /{id}/matrix/ GET, PUT (bulk, validated before write), matrix/parse and matrix/export.
/api/questionnaire/<token>/Public, token-scoped, separately throttled. What a vendor answers, with no account.
/api/evidence-packages/ · /api/package-samples/Assembly, sealing, issuing, withdrawal, the manifest, the bundle, and per-sample verdicts.
/api/pbc-requests/ · /api/pbc-items/The auditor's request list: provide, accept, return, withdraw, export.
/api/signing-keys/The installation's Ed25519 public keys and fingerprints, published unauthenticated so an auditor can check a bundle against them. One key signs every workspace's packages, so the fingerprint identifies the installation, not the organisation. The organisation is named inside the signed manifest instead.
/api/workspaces/List, retrieve, create, patch and current. Create and patch: superusers. List, retrieve and current: any signed-in account, which sees only its own workspace. There is no DELETE. A workspace is archived, never deleted, and neither the workspace you are in nor Default can be archived.
/api/audit-log/ · /api/notifications/ · /api/analytics/summary/The read-only trail, the derived per-person feed with receipts, and the dashboard summary with readiness history.

In DEBUG, the browsable API is available at the same paths with session authentication: useful for exploring, never for production. Separately, the Django admin is mounted at /admin/ in every mode, and the shipped nginx proxies it. It is an operator tool that sits outside the role model: it does not ask for a second factor, it is not covered by the login throttle, and its session authenticates the whole of /api/. Put it behind a VPN or an allow-list.

Data model

The essentials, in one block.

Eleven Django apps: accounts, compliance, documents, governance, vendors, attestations, notifications, audit, analytics, calendar_app and integrations, plus config.

Every organisation-owned model inherits a tenancy base that adds a workspace foreign key and a manager whose querysets carry the workspace filter whenever one is active. The filter is re-applied on every chain. It stops short in three cases the code names: a queryset that has already been sliced, one carrying a combinator, and one evaluated with no workspace active. The last is why a view that runs outside a request scopes itself explicitly. Not tenant-scoped, on purpose: the workspace list itself, per-person authentication state, the signing-key registry, the scanner status row, notification receipts and webhook deliveries.

Full architecture notes
essentials
Framework 1─* ControlCategory 1─* Control *─* ControlMapping
                                   │ 1─* ControlEvidence *─1 Document

User(Role) ─owns→ Control / Folder / Document / Risk

Folder (self-parent tree, cycle-guarded)
   │ 1─* Document 1─* DocumentVersion
   │        └─ owner, review_cadence, next_review_date,
   │           reminders_sent, scan verdict / quarantine
   └─ FolderPermission (role|user → view/edit/manage, inherited)

Risk 1─* RiskNote        AccessReview 1─* AccessReviewItem
MeetingSeries 1─* MeetingMinute   ChampionGroup 1─* GroupMember

Vendor 1─* VendorAssessment
   ├─ 1─* SharedResponsibility   (the matrix)
   ├─ 1─* Responsibility          (RACI rows, keyed on Control)
   └─ 1─* QuestionnaireInvite     (token hash only)

EvidencePackage 1─* PackageControl 1─┬─* PackageEvidence
                                    └─* PackageSample
   ├─ 1─* PackageGrant   (the audited folder-permission bypass)
   ├─ 1─* PbcRequest 1─* PbcItem
   └─ prior_package →  roll-forward chain

AuditLog · ReadinessSnapshot · CalendarEvent · NotificationReceipt
MfaDevice · WebAuthnCredential · SigningKey    User 1─* MfaBackupCode
every organisation-owned row above → workspace_id

Operations

The command
reference.

Prefix with docker compose exec backend python on the Docker path, or ../.venv/bin/python from backend/ locally.

Full operations guide

Scheduled: one run covers every workspace

manage.py send_review_reminders [--dry-run]
manage.py record_readiness
manage.py scan_evidence
manage.py send_digests
manage.py flushexpiredtokens

Administration

manage.py createsuperuser
manage.py seed_frameworks --with-folders
manage.py seed_frameworks --roles-only
manage.py remove_demo_data [--delete]
      [--workspace slug]
manage.py rotate_signing_key
manage.py link_oidc_identity
manage.py test_mailbox --to you@example.com

Something missing here?

Documentation gaps are bugs. Open an issue and it gets fixed in the repository, where it belongs.