v0.1.0 Latest

Accounts, roles, and access

Roles, per-company access, password policy, second factors, single sign-on, and the audit log.

Roles

A role is a set of named permissions: companies, documents, doc types, secret fields, knowledge base writing, and the administration area. The three the product starts with are fixed:

RoleMay
adminEverything, including doc types, API keys, webhooks, users, and granting access
techCreate and edit documents, add local fields, promote fields, add dropdown options
readonlyView

Under Admin → Roles an administrator adds roles with any subset of the same powers. A role holding the administration area is an administrator in every sense: it sees every company, must keep a second factor, is excluded from grant lists, and is who grants access. A role is retired, never deleted, and only when nobody holds it.

Revealing a secret stays a per-person flag, can_reveal_secrets, set under Admin → Users. Accounts created through single sign-on start as tech without it.

Per-company access

A user or an API key either sees every company or only the ones granted to it. Administrators are never restricted; they are who grants access. A newly created account starts with no companies until an admin grants some, so an SSO user who signs in for the first time cannot read anything by default. Upgrading an existing install changes nothing: everyone already there keeps the access they had.

Anything outside the granted set answers “not found” rather than “you are not allowed”. The rule holds across search, backlinks, exports, attachments, deep links, the REST API, and the MCP tools. Scope is read from the database on every request, so revoking a grant applies to the next page load.

Passwords

8 to 128 characters with an uppercase letter, a lowercase letter, a number, and a symbol or a space; never the person’s own name or address; never one that has appeared in a known breach (checked against the Pwned Passwords service by k-anonymity, so the password itself never leaves the server). They do not expire on a timer. Ten wrong passwords in a row close an account for fifteen minutes; an administrator can open it again.

Set SMTP_URL and MAIL_FROM and the sign-in page offers a reset link by mail. Without them, an administrator sets a temporary password under Admin → Users, which must be changed at the next sign-in.

Second factors

Under the account menu, Personal settings → Security, anyone can enroll an authenticator app, passkeys (a YubiKey, or the passkey a phone, laptop, or password manager holds), or both, and receives ten single-use recovery codes. Administrators must enroll something within a week of their first sign-in. The pages that issue API keys, change people, or change security settings ask for the step again after fifteen minutes.

Single sign-on in front of Trove KB, or Cloudflare Access, does not stand in for it. An administrator who has lost everything is put right by another administrator from Admin → Users, and it is all in the audit log.

Single sign-on

Set OIDC_ISSUER, OIDC_CLIENT_ID, and OIDC_CLIENT_SECRET (all three or none) and the sign-in page offers SSO alongside local accounts. Discovery is used, so Entra ID, Google, Authentik, and Keycloak all work. APP_URL must be the origin people actually browse to: the redirect URI (<APP_URL>/api/auth/callback/oidc) and the cookie that carries the OAuth state are both built from it, and a mismatch fails the callback with state_mismatch.

Audit log

Append-only, under Admin → Audit. Every document save, secret reveal, grant change, API key, webhook, and second-factor change, with who and when. The audit trail references users, so accounts are never deleted; they are disabled.

Appearance and language

The account menu offers System, Light, and Dark; System follows the operating system and is what a new reader gets. The choice is a cookie read on the server, so the right palette is in the first byte of HTML. The interface ships in en-US with en-GB as a translation; readers pick their own, APP_LOCALE sets what a new visitor gets. Adding a language is one file that overrides only the strings that differ.