opbox

Security in Opbox is not a feature you switch on, it is the path every action takes. Every request to read or change anything passes through one front door and a stack of independent checks, each of which can only ever narrow what you are allowed to do, never widen it. The result is a system where a leak is structurally hard: a single bug or a single stolen credential is not enough, because several of the locks are enforced by different systems (the database, the application, the cryptography) and all of them have to fail at once. This page describes the controls a partner, a compliance lead, or a founder can manage and inspect.

What it does

Workspace isolation enforced by the database. One client lives in one workspace, and the wall between workspaces is built into Postgres itself using row-level security, not only into application code. When a request comes in, the database is told it is acting for one workspace and physically refuses to return a row from any other. It fails closed: a request that arrives without a workspace stamped on it matches no rows at all, so the accident is no data, never all data. Above the workspace sits the organisation, a separate membership where an OVERSEER role can read the audit trail across workspaces without dissolving the walls.

Tiers decide who you are. Every person and agent holds one of four tiers on a ladder: EXTERNAL (a client on the portal, the narrowest view), MEMBER (everyday staff work), ADMIN (the money and oversight work), and OWNER (the whole estate, including the most destructive and structural acts). Every action carries a required tier, and your tier must be at least that high or the action is refused. Moving a person’s tier is itself a governed, Owner-only act that blocks demoting the last remaining OWNER, so the workspace can never be left without one.

Money and destruction need a second factor. The actions that move money or tear things down require a senior tier and a fresh multi-factor step-up: even an already-signed-in senior user must re-prove themselves within a short, fixed window before the system will let the action through. A stale session is not enough, and if an owner uses an emergency override that override is written into the audit log so it can never be quiet.

Autonomy meters what the AI may do on its own. An agent’s power is set by an autonomy dial from 0 (read only) to 3 (owner-equivalent), bounded by both the agent’s own standing level and the ceiling carried on the credential it is using. The effective level is the lower of the two: hand an agent a key capped at level 1 and even a level-3 agent does only level-1 work while holding it. Power can shrink as it passes down the chain, never grow.

Tokens are keys cut for one door. A bearer token is not an all-areas pass. It can be limited to a named list of actions and bound to one specific resource, so a client’s portal link opens that client’s portal and nothing else. That resource binding is the anti-enumeration fence: swapping the identifier in a link does not work, because the key does not fit the other door. A token’s secret is shown once when it is minted and is never recoverable thereafter; listing and reading a token return only its hash, scope, status, and expiry, never the secret. A single scope-fan kill can revoke a whole family of tokens at once by bumping a scope-version counter, so a stale token used afterwards is rejected.

Credentials and secrets, protected and rotatable. Bring-your-own-key AI credentials are stored encrypted at rest and shown back only masked (****<last4>); the raw secret is never returned by any read. Each credential can carry its own spend cap, distinct from the org budget, and can be verified with a dry run that does not move money. When a key needs to change you rotate it in place or revoke it terminally, and box-local secrets (the database role, the LLM key, signing keys) rotate through the same governed path. Personal data and file bytes are encrypted with AES-256-GCM and each blob is bound to its own row and workspace, so a stolen blob pasted into a different record simply fails to decrypt.

File sensitivity grades gate the bytes themselves. Each file carries a grade (NORMAL, SENSITIVE, CONFIDENTIAL, RESTRICTED), and the higher the grade the higher the tier required to read the actual bytes. Knowing a file exists and being allowed to open it are gated separately, so the most sensitive material does not reveal its contents to staff below its grade. A firm can author its own grade-to-tier policy on top of the defaults.

Policies and egress control decide what is allowed. A workspace’s policies define the rules that decide what is allowed, evaluated before an action runs. The egress chokepoint runs on the same path: a per-rail egress policy sets the maximum data classification that may leave on a given route, regulated data is denied by default, and the policy can only ever be tightened above the substrate floor, never loosened below it.

A tamper-evident audit log. Every action that changes the system writes exactly one record to an append-only log: who, what, when, in which workspace. The records are hash-chained, each fingerprint computed from the one before, so altering or removing a past row underneath the application breaks the chain at that point. A built-in verification action re-walks the chain and reports whether it is intact, so you can demonstrate rather than assert that the history has not been quietly rewritten.

Fail closed everywhere. The thread through every lock is the same: when the system is unsure, it denies. An unrecognised action is refused rather than guessed at, a request with no clear identity is refused rather than run as a default user, and a decryption that does not perfectly check out returns an error rather than a best-effort plaintext. The default answer to any ambiguity is no, and a human has to take a positive step to turn it into a yes.

How you use it

Grant and revoke fine-grained access. Open a thing and grant a specific person reach to it, list who has been granted what, and revoke a grant when it is no longer needed. These are the everyday, member-level access adjustments that sit underneath the coarser tier model.

Manage people and their tiers. As an admin or owner, invite a person onto the roster at a starting tier, move someone between MEMBER, ADMIN, and OWNER, deactivate a leaver (which bumps their session version so existing sessions stop working), and reactivate them later if they return. The last-owner guard means you cannot accidentally lock the workspace out of ownership.

Hold and rotate credentials and tokens. Store a bring-your-own AI key, set a spend cap on it, and verify it with a dry run before relying on it. Inventory your credentials (always masked), rotate one whose secret has changed, or revoke one terminally. Mint a scoped bearer token, list the outstanding tokens for a scope, and revoke one token or fan-kill a whole scope at once.

Set the policies and the egress floor. Author and publish the policies that decide what is allowed, and set the per-rail egress classification ceiling so that regulated material cannot leave on a route that is not cleared for it. Reads of policy go through the same policy.get path as everything else.

Inspect and prove the record. Query the audit log or follow its live feed to see exactly who did what and when, and run the chain verification to confirm the history has not been tampered with. This is the evidence you bring into a compliance sign-off.

Run the recovery and host controls. As an operator, set the disaster-recovery policy (the RPO/RTO targets and the restore-drill cadence) and read the current DR status, take a machine-readable host snapshot of services, tenants, storage, and preflight checks, and rotate box-local secrets when the situation calls for it. Re-HMAC the global identifiers to a new key version when the identity secret rotates.

The kernel verbs behind it

Each goes through the one front door - permission-checked, autonomy-checked, scope-checked, and audited before it runs (see Security and permissions). These are the verbs most specific to this feature.

Access and people:

  • acl.grant - grant a person fine-grained reach to a specific thing.
  • acl.list - see who has been granted access to what.
  • acl.revoke - take a grant back.
  • actor.invite - invite a human onto the roster at a starting tier.
  • actor.setRole - move a person between MEMBER, ADMIN, and OWNER; the last-owner-demote is blocked.
  • actor.deactivate - offboard a human and bump their session version so live sessions stop.
  • actor.reactivate - re-enable a deactivated roster user (re-login required).

Tokens:

  • token.mint - mint a scoped bearer token; the secret is shown once.
  • token.list - list outstanding tokens by scope and status (secret never returned).
  • token.get - read one token’s metadata: hash, scope, status, and expiry only.
  • token.revoke - revoke a single token.
  • token.revoke-scope - fan-kill a whole scope by bumping its version counter.

Credentials and secrets:

Policy, egress, and the record:

Recovery and host:

  • dr.policy.set - set the DR RPO/RTO and restore-drill-cadence policy.
  • dr.status - read the current disaster-recovery status.
  • host.doctor - a machine-readable host snapshot of services, tenants, storage, and preflight.

Many more related verbs live across actor, audit, config, connection, policy, token, and tenant. See the full set in the Verb reference.