Security and tenant isolation

The boundary is in the database, not in the screens in front of it.

A register of what an organization decided, spent and shipped — and now of what its agents did, which models saw the work, and what they were allowed to touch. Every record is separated at the database, encrypted in transit and at rest, and written to a trail nobody can edit afterwards.

/app/…/engineering/modelsIllustrative workspace
The model register: five standing approvals, each with the hosting posture it runs under, the address it runs at, whether it may process regulated content, and the basis its approver stated.
The screen is the product as it stands. The workspace in it is illustrative: every organization, project, person and model address was substituted out of the database before the capture, and the capture is refused if one of them survives in the rendered page.

Tenant isolation

One workspace cannot see another

Every record LockedIn Labs FDE stores carries the organization that owns it, and the database refuses any read or write that crosses that line.

The boundary is attached to the data rather than to the screens in front of it. Ordinary tenant requests use the caller’s database policies; privileged application functions enforce explicit session, organization and role checks.

Row Level Security is enabled on every table in the application schema, and on every one of them it is forced. Ordinary Row Level Security protects ordinary roles; FORCE also subjects table owners to policies unless they are superusers or hold BYPASSRLS. Those privileged operator paths can bypass row security, so FORCE alone does not establish their tenant isolation. A schema trigger applies the setting to new application tables.

The application checks the signed-in person’s organization and role as well. That check is the first line; the database boundary is the one that still holds if a query is ever written incorrectly. Relationships carry the organization too — a link from one customer’s work to another’s is declared on the pair of organization and record, so it does not satisfy the constraint and cannot be stored. A cross-tenant reference is a constraint violation, not a bug that behaves like a working join.

A signed-in personor an agent holding a workspace credential
The database policyforced on every table in the schema
Records in their organizationread or written when permitted
Records in another onenot returned, not writable
Ordinary tenant reads and writes are evaluated against the caller's database policies and granted permissions. Privileged operator paths can bypass RLS; application security-definer functions instead enforce explicit session and scope checks.
  • scripts/prove-tenancy.mjs
  • scripts/measure-posture.mjs
  • src/app/app/[org]/settings/security/page.tsx

Verification

Recorded isolation evidence

Before a release ships, a real signed-in identity from one organization attempts to read and write the records of organizations it does not belong to, through the same interface a browser uses. Every attempt has to be refused.

The run enumerates what to try from the live schema rather than from a checklist, so anything added to the product is covered by the next release rather than by somebody remembering it. A table added with no organization on it is reported by name instead of being skipped quietly.

The same run attempts the deletions the trail is supposed to refuse, so the append-only boundary is proved by trying to cross it rather than asserted. Workspace security settings show current session and schema reads separately from the historical proof, with its recorded deployment and date.

Historical isolation proof · LockedIn Labs FDE External hosted service. Recorded 26 August 2026, 13 days ago: the run recorded no readable foreign row or accepted foreign write. This is the record of a run at a moment, not a live check. It does not verify LockedIn Labs FDE production or this installation.

  • scripts/prove-tenancy.mjs
  • scripts/gate.mjs

Agent authority

What an agent may reach is decided before it runs

The catalog of tools an agent can call is derived from the server that publishes them, and anything that writes is denied until a named person grants it.

A control a workspace deliberately made advisory is not a control it is protected by, so a refusal records whether the call was actually stopped or only watched.

/app/…/engineering/policiesIllustrative workspace
The operating-policy register: nine policies in the workspace, nine adopted, seven of them adopted at blocking enforcement, with the standing counted against its own denominator.
The rules a workspace holds its agent runs to, each adopted by a named person at a stated enforcement. Illustrative workspace, real screen: the counts are the product's own arithmetic.
  • The catalog is derived, not typedWhat an agent can call comes from the server that publishes the tools, so the register cannot describe a door that does not exist or miss one that does.
  • Writes are denied by defaultA tool that only reads is available. Anything that writes is refused until somebody with authority grants it, and the basis they gave is recorded beside the grant — a register whose default is “allowed” is a list rather than a control.
  • The check precedes the doorThe permission is asked at the workspace endpoint before the tool executes, never alongside it — a check that runs in parallel with the work it authorizes has authorized nothing. The answer comes from the same function the workspace console reads, so the screen cannot describe a posture the door does not apply.
  • A refusal is a recordIt names the tool, the reason, and whether the call was stopped or only watched. It never names the payload, and the stated reason is screened at write against the patterns that identify a person, so a refusal cannot itself become the leak.
  • Nine operating policiesA run may not widen its own permissions, may not pipe fetched bytes straight into an interpreter, may not carry regulated content past its approved boundary, and may not accept its own output. Each is adopted by a named person at a stated enforcement level, and which are blocking is recorded rather than assumed.
  • Silence is never a passA policy with no verdict on a run reads as not evaluated — never as passed. Verdicts are append-only, and a waiver that names nobody is refused by the database. Correcting a verdict means recording a new run, which is the honest shape.
  • supabase/migrations/20260820190000_tool_permission.sql
  • src/app/api/mcp/route.ts
  • src/lib/tool-permission/gate.ts
  • supabase/migrations/20260820020000_agentic_harness.sql

The AI control plane

Which models saw the work, and where they run

Models are approved one at a time and recorded with where they run, and each approval states in writing whether that model may process regulated content.

No credential is stored on a register a member can read. The pointer to the key and the key’s fingerprint are withheld from every workspace role, and the runtime reaches the secret through a privileged function that hands it to nobody.

Work leaving for a modelregulated, or de-identified
The approval's posturewhere that model runs, stated in writing
A model that may see itwith the address it runs at
De-identified work onlynever shown regulated content
Where its key livesa pointer the register will not hand out
Each approval states where that model runs and whether it may process regulated content, and the posture is the permission: work that carries regulated content is not sent to a model approved for de-identified work only, and the decision was made by a named person in advance rather than by whoever configured the run. A workspace holds several credentials at once, each with its own boundary and its own ceiling; a retired one stays listed with the date and the person, because the runs that happened under it did happen.
  • On premisesRuns on hardware this organization controls. Prompts do not leave the network.
  • Private cloudA tenant-isolated deployment under contract. Handling is governed by that agreement rather than public terms.
  • Vendor hostedA public API. Work sent here leaves the organization's boundary.
  • supabase/migrations/20260820100000_provider_credentials.sql
  • supabase/migrations/20260820200000_ai_credential_repair.sql
  • src/lib/harness/model.ts

Encryption

Encrypted in transit and at rest

Both are provided by the managed platforms this deployment runs on, and both are stated here as fact rather than as a contractual undertaking.

  • In transitEvery connection — browser to application, application to database — is TLS 1.2 or above. There is no unencrypted listener to reach.
  • At restThe database and its backups are stored encrypted with AES-256 on managed infrastructure.
  • Where it sitsCustomer data is held in the United States and nowhere else. Pages that carry no customer data are cached on a global network, which is why the site loads quickly from anywhere without any register content leaving the country.

Regions, key management and the limits of what we will put in a contract are set out in control detail.

Access and roles

Only the people you put in the workspace

A new account reaches nothing until an administrator places it in one workspace at one role. To somebody outside a workspace, the database answers exactly as it would to a stranger.

There is no cross-organization role and no global search. Least privilege here is the default state rather than a setting somebody has to remember to switch on.

  • Two kinds of authority, kept apartAdministering a workspace and holding authority over delivery evidence are deliberately different grades, so managing membership does not carry the power to publish evidence, change billing or transfer ownership.
  • Two-step verificationAny member can enroll a time-based code from an authenticator app. Once enrolled it cannot be skipped, and enrollment issues single-use recovery codes that are shown once and never emailed. No support process here can remove somebody’s second factor on request.
  • Passwords are never ours to loseCredentials are exchanged with the identity service; this application never receives, stores or logs a password or a verification code. Passwords must be at least twelve characters and are checked against a public breach corpus and refused if they appear in it.
  • Sessions expire, and privileged acts re-askA session ends after eight hours idle or twelve hours in total, and ending it revokes it at the identity service rather than only clearing the browser. Changing how people sign in to a workspace requires proving your identity again within the last fifteen minutes, and removing your own second factor requires that factor or an unspent recovery code.
  • An act is somebody's actCustody triggers take the actor from the authenticated session rather than from anything the client sends, and a session with no identity behind it cannot approve a model, adopt a policy or grant a tool at all — the database refuses the write and says why.
  • Single sign-onSAML 2.0 for Microsoft Entra ID and other standards-based providers is built into the product and enabled per deployment during onboarding. Its current activation status is stated in control detail.

The record

A trail that cannot be rewritten

Every act that changes what the register claims is appended to a trail: who did it, what changed and when.

The actor comes from the authenticated session rather than from anything the client sends. Deletion is blocked for workspace users, for owners and for privileged platform roles, and each release proves that boundary by attempting the deletion and being refused.

The trail is kept for the life of the tenancy. It does not roll off on a schedule and it is not something a plan can buy more of.

Evidence that leaves the building

Deck and trail exports carry an Ed25519 receipt over canonical bytes, and the public key travels inside the receipt.

The receipt holds the counts with their denominators, the acceptances, and the commit the export was pinned to. Anyone holding it can check it in their own browser at /verify — no account, and no call back to us — or with their own code, because the format and the canonicalization are published.

A claim whose count exceeds its own denominator is not rounded: the receipt is not issued. There is no partial receipt.

  • src/lib/evidence/receipt.ts
  • src/lib/evidence/canonical.ts
  • src/app/verify/page.tsx

Disclosure

Reporting a vulnerability

There is a monitored security mailbox and a published disclosure policy.

The mailbox was verified end to end with a real message before this page named it, because an address that bounces silently turns a researcher trying to help into one who concludes nobody is listening.

Security contact: security@lockedinlabs.ai — also published machine-readably at security.txt (RFC 9116) with the scope notes. Tenant isolation is in scope and is the finding we most want.

Availability

Availability and recovery

What this deployment does today, and where the commitments about it actually live.

  • BackupsDaily encrypted backups with point-in-time recovery, managed at the database platform layer.
  • Dependency postureDependency advisories are triaged for reachability, and the tests that establish an advisory is unreachable are kept so the classification can be re-checked rather than believed.

Recovery objectives and support commitments are commercial terms, settled in the agreement for the estate in question. What this deployment does and does not commit to today is stated in control detail.

Subprocessors

Who else handles a workspace’s data

The services that handle customer data on our behalf, and what each one receives. Notice and objection rights are established in commercial terms.

SubprocessorWhat it receives
SupabaseThe database, authentication identities and file storage.
NetlifyRequest metadata, and the rendered HTML of every page.
ResendThe email address of anyone invited to a workspace.
StripeBilling contact and payment details for a paid plan. Card numbers are entered on Stripe’s own page and never reach this application.
Google Gemini (optional voice assistant)Only when the assistant is enabled: a workspace brief scoped to what the signed-in person may already read — the workspace name, selected project keys, titles and states, and aggregate register counts — plus the live conversation’s audio and transcriptions. It receives nothing from this application when the assistant is not enabled.

A model a workspace approves under the control plane is not on this list: those are the customer’s own arrangements, made under the customer’s own contracts, and the register records where each one runs so that the answer belongs to them rather than to us.

Assurance

Compliance and assurance

Under data-protection law your organization is the controller of its register content and LockedIn Labs FDE is its processor.

A data processing agreement, standard contractual clauses, a business associate agreement (BAA) where one is needed, incident-notification terms and deletion undertakings are settled in the enterprise agreement.

LockedIn Labs FDE holds no third-party attestation today. SOC 2 Type II, HITRUST and FedRAMP authorization are not held, and neither is ISO/IEC 27001. The product is not PCI DSS assessed and stores no card data — card details are entered on Stripe’s own page and never reach this application. We publish that here rather than in a footnote, because a trust badge that turns out to be a roadmap is the thing a reviewer never forgives.

What we offer instead is the mechanism and the dated evidence: the controls above, the release verification, the files under each one that a reviewer can open, and a control-detail page that answers a questionnaire without waiting for a call. Nothing the platform produces is described as certified.

The privacy notice covers what is collected and the rights a person can exercise. The terms carry the contractual counterparts of the limits stated here, and control detail carries the rest of what is not implemented.

Security review

Everything above can be checked, not just read

Control detail is written for the questionnaire: mechanisms stated precisely, the boundary of each one, and what is not implemented. Send anything it does not answer to the security team and you will get a direct answer rather than a deflection.