The security model
Plugboard scopes application access by institution and permissions. Production
Compose adds database row-level security through its restricted app_user
connection. Demo and native deployments use an owner connection, so they do not
have that independent database restriction. Connector secrets are encrypted;
passwords and API keys are stored as hashes.
Authentication
Section titled “Authentication”Local accounts use a modern memory-hard password hash.
Sessions use short-lived access tokens with revocable refresh tokens. Refresh tokens are revoked in the same transaction that deactivates an account, whether you do it by hand or through SCIM.
Each refresh retires the token it used and issues a replacement. A retired token presented again outside the grace window is treated as a possible replay: the account’s live sessions are ended at first detection. Two requests from the same browser can legitimately race, for example when a page reloads mid-refresh, so a request inside a short grace window is handed the same replacement instead. Before 0.16.0 that replacement could be lost, and staff were occasionally signed out of every device without warning; that no longer happens. A reuse outside the window is recorded in the audit log as Refresh token reuse detected, naming the person and how many sessions were ended. From 0.22.1, presenting that same retired token again does not create another alert or revoke later sessions. The token itself is never recorded.
Two-factor authentication is TOTP, set up by each user under their account. Turning it off requires a current code.
Single sign-on is generic OIDC or SAML 2.0. The OIDC flow uses PKCE and a nonce. See SSO.
Authorisation
Section titled “Authorisation”Role-based, with fine-grained permissions. A role
holding * is a superuser within its own institution, and no permission crosses
into another.
The same checks run on the web console, the REST API, the MCP server and the assistant.
Separate permissions allow administrators to distinguish these operations:
ticket.internalseparates the desk’s own notes from working the queue, so you can give somebody the queue without the notes.charge.raiseandcharge.approveseparate proposing a charge from making it real. Waiving sits with approval.
Isolation between institutions
Section titled “Isolation between institutions”Tenant-owned records are accessed through the scoped database wrapper. Some deployment-wide identity lookups deliberately resolve the tenant before a scoped query. See tenant isolation for the deployment differences.
Secrets
Section titled “Secrets”Connector credentials are encrypted before they reach the database and decrypted in memory only for the duration of a call. See secrets and keys.
The outbound fetch guard
Section titled “The outbound fetch guard”Outbound requests to private, loopback and link-local addresses are blocked by default, so a URL typed into a service monitor or a webhook cannot reach an internal host.
A self-hosted install that monitors LAN addresses opts out:
ALLOW_PRIVATE_EGRESS=1The setting allows private destinations deployment-wide; it does not permit cloud metadata addresses. Leave it off if the deployment serves more than one institution. A managed deployment uses a connector agent instead, which reaches internal systems without Plugboard requesting a private address.
Guarded requests pin approved addresses and validate redirects. The Ollama
connector requires an agent, the operator’s
private-egress setting or the exact configured LOCAL_AI_URL origin for private
access. See Ollama.
Transport
Section titled “Transport”TLS 1.2 is the floor. HSTS is sent, HTTP redirects to HTTPS, and a strict content security policy is applied.
HSTS comes from the application itself rather than from a reverse proxy in
front of it, so a deployment that terminates TLS somewhere we did not write the
config for still sends it. The default is one year including subdomains, and
HSTS_MAX_AGE changes or removes it.
The API honours X-Forwarded-Proto and X-Forwarded-For from a reverse proxy.
See HTTPS and certificates.
Rate limiting
Section titled “Rate limiting”Applied to authentication endpoints, and to the public API per key.
Audit entries cannot be edited or deleted through the application. Coverage is
not complete across all mutations; for example, API-key lifecycle operations
currently lack entries. Production app_user also cannot update or delete audit
rows; an operator’s database-owner access has broader powers. See
the audit log and API-key coverage.
Vendor support operations use a separate deployment credential, with an optional operator identity recorded on audited operations. The product’s support-access switch controls that API; it does not revoke infrastructure administrator access.
Supply chain
Section titled “Supply chain”Release container images are signed and include an SPDX software inventory. The image scan fails on fixable high or critical vulnerabilities. Source scans and dependency checks provide additional coverage, not a guarantee that no vulnerabilities remain.
Every download has a checksum published beside it, and the automatic updater refuses an archive that does not match. Verification instructions are in updating.
What is your responsibility
Section titled “What is your responsibility”SECRETS_MASTER_KEY, kept somewhere other than the server.
The certificate, and its renewal.
Who holds which role. The product enforces permissions; it cannot tell you
that four people should not hold device.manage.
Deciding when to update. Nothing updates itself except the on-premises bundle, and you can turn that off.
Restoring a backup once, to confirm your regime works.
Reporting a vulnerability
Section titled “Reporting a vulnerability”Email [email protected] with reproduction details. The repository security policy targets acknowledgement within two business days and initial assessment within five business days. Avoid posting unpatched vulnerability details publicly.