Authentication fails closed
A passkey whose signature counter regresses looks cloned. Conformiti disables that credential and refuses the sign-in: it does not quietly drop the account back to password-only, which is the failure mode most implementations choose because it generates fewer support tickets. Backup codes belong to the account, not to the TOTP device, so a passkey-only person still has a recovery path.
Tokens rotate and can be revoked
Refreshing rotates the refresh token and blacklists the old one; signing out blacklists the current one. Login, failed login with the reason, and logout are explicit audit events. In the Docker stack the per-client login throttle counters live in Redis, so the limit is shared across workers rather than reset by whichever process answers; a bare install without CACHE_URL falls back to a per-process cache. Set NUM_PROXIES to your proxy hop count if you front it differently. It is rate limiting, not account lockout. There is no per-account failure counter.
SSO cannot be configured from a form
OIDC and SAML settings come from the environment only. Verified-email linking will never attach an external identity to a superuser, a staff account or anyone who can manage users; auto-provisioning refuses user-managing roles; the issuer is compared with trailing slashes stripped; JWKS verification is asymmetric only. If your provider asserts no second factor, SSO_STEP_UP asks for a local one. It defaults to if_enrolled. A code is demanded only from people who have a local authenticator; set it to required to refuse the sign-in from anyone who has neither.
Authorisation is resolved server-side
Folder access resolves through superuser, view-all, ownership and the strongest grant on the folder or any ancestor, then caps Auditor roles at view. Those rules gate every folder, document, tree, feed and evidence count. They do not narrow the registers: anyone signed in to a workspace can read its control programme, risks, vendors, RACI and analytics, so the shipped Auditor role reaches further than "granted folders" implies. Narrowing it is on the list. Write controls are gated on the same capability flags the API re-checks on every request, so the interface does not offer an action the API will refuse. The Django admin is an operator tool that sits outside those rules entirely: it bypasses MFA and the login throttle, so restrict who can reach it, as SECURITY.md says.
Tenancy is enforced at the ORM
Workspace scoping lives on the queryset and is re-applied on every chain, so a view that forgets to filter still reads only the active workspace. It is not an absolute: a queryset that has already been sliced or combined skips the filter, and installation-level tables (the signing key, the webhook delivery log, per-person authentication state) sit outside the mechanism by design. Pinning never widens. No active workspace means no filter: correct for migrations and for jobs that walk every tenant, but an API request with nowhere to go is refused with 403 rather than served unscoped.
Evidence is rendered, never executed
Inline delivery happens only after a magic-byte check on the actual bytes. PDFs are drawn by pdf.js onto canvases rather than handed to a plugin. Word and Excel are parsed server-side into structured JSON and rendered as structure: the file's own markup never reaches the page. Media is served as sandboxed attachments; the viewer fetches through the API and renders from a blob.
The audit trail records names, not values
Middleware reads the top-level field names of a mutating request before the view runs: password, token and code keys are dropped outright, and writes the entry only after a successful response. Auth events are written explicitly. The API exposes no create, update or delete method on the trail. The Django admin is the exception, as it is for every other rule here: restrict who can reach it.
Outbound calls are hardened
The Jira client accepts https only, refuses redirects, and pins to public hosts. A stored integration URL is a classic SSRF vector. Slack and Teams webhooks are https-only and settable by an operator and nowhere else. Secrets like the TOTP seed and the Jira token are encrypted at the field level.