labbel
llms.txt
security · what we can say, and what we cannot

Security, as far as we can say

Publication snapshot: web-eef8292b2fbc2ddd

Revision 6 · Production review pending.

Your agent needs to know what it would send to labbel, what we keep, and what prevents another organisation from accessing it. This page describes those boundaries, the security reviews we commissioned, the corrections that followed and the limitations we have accepted.

The reviews described here were performed by AI agents with access to source code and local test environments. They were not independent third-party security audits. Using an OpenAI model for a review does not constitute an audit or endorsement by OpenAI. The findings below are dated observations and reported corrections; they do not certify the security of the running service.

Release status, 16 September 2026. The September 7 corrections have a recorded deployment, and the S+ security changes described below were deployed on 16 September 2026: database migrations 049 to 053 and the MCP server. Post-deployment checks were run and are described where they bear on a claim. The website is published separately. This account describes the server deployment and checks recorded on that date; it is not a full security assessment of production.

The 7 September review

On 7 September 2026, David Eberlen commissioned a separate review by ChatGPT 6, working as Astra. It examined source commit 7179101, following authentication, organisation boundaries, database permissions, the human review bench and changes since the previous production baseline.

The reviewer ran the unit tests and source and test type checks, applied migrations 001–047 to a separate PostgreSQL database, and used synthetic data to investigate suspected failures. The Supabase integration suite was skipped because its test environment was unavailable. The separate database probes did not replace that suite.

The review did not test production, real OAuth sign-ins, platform log collection or concurrent trial-transfer requests under load. It was a source review with targeted local experiments, not a penetration test of the deployed service.

In the cases tried, all six organisation-checked write functions refused a foreign organisation's record. Three further probes checked that returning an existing stamp did not bypass that boundary: nine probes passed in total. A database policy probe also prevented a user in one organisation from reading another's domain. These results describe the cases tested, not every possible request.

What the review found, and what changed

The review found four issues. Two could lose saved work through ordinary use, and the reviewer recommended withholding deployment until those two were corrected.

FindingCorrection
S1: transferring trial work into an organisation could delete authored domains and their bench records.The transfer now moves those records within the transaction, checks domain-name collisions and refuses deletion if dependent work remains.
S2: cleanup of old unused trials did not count authored domains as saved work.Domain editions and bench cases now protect a trial from that cleanup.
S3: an administrator demoted to member could retain administrative powers in an open MCP session.Each tool call now uses the account's current role for permission checks and the handler.
S4: suspending an account did not stop organisation-level reads through the database's authenticated-user policies.The shared policy helpers now require an active account. Personal-record exceptions are described below.

S1, S2 and S4 were corrected in migration 048. S3 was corrected in the MCP server. Our engineering record reports a passing strict gate, including the Supabase integration suite, after the corrections. Our deployment record dated 8 September 2026 reports that the corrected server and database migrations were deployed. These are the project's verification and deployment records; the original reviewer did not independently retest production.

The 15 September review and the S+ corrections

After the work on organisation-authored domains, David commissioned a further review using OpenAI's Daybreak Blue model. Astra prepared the source context; Daybreak conducted the security assessment. It examined authentication and session boundaries, database relationships and permissions, error logging and a reachable dependency. The work combined source review, local request tests and database probes with synthetic data. It was not a penetration test of production.

Daybreak reported five findings, two of which blocked its deployment recommendation. We addressed all five in the S+ security stage. The corrections are summarised here at the level relevant to a customer; reproduction scripts and detailed attack sequences remain internal.

Sessions and authorisation. The implementation deployed on 16 September separates trial and organisation session handling and checks organisation authorisation on each request. Local regression tests cover revoked or expired access, use of another principal's session and session termination. The post-deployment check confirmed that the organisation endpoint rejects an unauthenticated request with 401. That check did not exercise an authenticated session or verify session isolation in production.

Input handling. A dependency update and a regression test address excessive processing from a crafted document. The dependency audit reported no known production-dependency vulnerabilities at the 16 September closing check. That result describes the audit's database and dependency versions at that time, not the absence of undiscovered vulnerabilities.

Database integrity and permissions. New database constraints keep a run's step and recipe connected correctly. Permission changes remove unnecessary table privileges from anonymous and authenticated roles on the affected tables. Integration tests check both invalid relationships and the resulting privilege sets. These changes do not remove the service's responsibility for organisation-scoped reads.

Error logging. The MCP error path now uses a fixed failure classification, an operation from a closed vocabulary and an error code. Local tests check that submitted values do not enter that log line. This correction applies to the MCP repository-error log line, not every logging surface. The platform settings and remaining bench limitation are described below.

Astra reviewed the S+ implementation and subsequent corrections, including additional findings about session termination and the vocabulary used in logs. The engineering record for 16 September reports that the source and test type checks and the full test gate, including the local Supabase integration suite, passed at closure. These tests verified the corrected code and local behaviour. The deployment record separately confirms the database and MCP server release and limited checks against the running service. Those checks did not repeat the full regression suite in production.

How we handle findings

The work above followed a repeatable sequence: examine the change, reproduce suspected failures with synthetic data, record findings, implement corrections, add regression coverage and review the result. Findings that affect deployment are kept visible until corrected or explicitly accepted. An accepted limitation remains a limitation.

Daybreak is a review tool in this process. The record describes a dedicated assessment after a major development stage, not continuous Daybreak scanning or a standing external audit. Local tests, reviewer judgement and production checks provide different evidence; we keep their scope and dates separate. Public summaries describe material risks and the state of corrections without publishing exploit instructions for unresolved issues.

How organisation boundaries are enforced

The MCP service uses a privileged database role that bypasses row-level security (RLS). On this path, saying that the database has RLS policies would not explain what protects your organisation's records. The controls have separate responsibilities.

Identity and reads. The service resolves the organisation from the authenticated connection. Application queries must restrict reads to that organisation. The repository has a shared suite of negative isolation cases for methods that accept an organisation ID, run against both the in-memory implementation and PostgreSQL through the same privileged role used by the service. A coverage test checks the repository interface so that a new organisation-scoped method without a case fails the suite. The database portion requires the integration environment; a run with those tests skipped is not equivalent.

These tests check application isolation. They do not add an RLS boundary to MCP reads. A defective read query remains a risk on this path.

Writes. Migration 047 added database-side organisation checks to six ID-based write functions. Each compares the supplied organisation with the record's organisation before writing or returning an existing stamp. This gives those operations a second check beneath the application. It still relies on the service supplying the authenticated organisation correctly; the database does not independently authenticate the end user behind the service role.

Evidence records. Database grants restrict direct changes to protected records such as signals and traces. The service role has no general table-level update or delete permission on the append-only set. This is a restriction on specified roles and operations, not a claim that database owners, privileged functions or cascading operations cannot affect records. The trial-transfer findings above illustrate why those other paths also need review.

The bench. The bench server also uses the privileged service role for its repository access. The public application key is used in the sign-in flow; it does not put the bench's subsequent repository queries under user-token RLS. The bench verifies a signed session cookie, reloads the current account, checks organisation and role, and checks the origin of write requests. Its boundary therefore also depends on server-side authorisation and scoped repository operations.

Direct authenticated database access. This is a separate path, governed by RLS. Organisation-level policies built on the shared helpers require an active account. Suspension deliberately leaves policies for a person's own account row, enrollments, progress and personal signals available; it does not mean every possible database read is blocked.

What data is kept

labbel stores method documents, including recipes, course steps and organisation-authored domain editions, together with account information, permitted progress records, run records and reported signals. Those documents are content you submit for the service to retain.

The code-review path receives and processes the submitted review but does not retain its body as a document or in its trace. It keeps structural checks, versions, selected declarations and derived counts. For work submitted under an organisation-authored domain, the trace does not copy the work's text or extract declarations from it. Your organisation needs to keep the original material if it wants to examine it later.

The service does not collect your agent's conversation history. It receives the arguments sent to its tools. Pasting conversation content into a stored document would still send that content to us: the retention rules depend on the tool and field, not on where the text originated. See the guide for the distinction between material sent, processed and stored.

Signal reflections have a 2,000-character limit per field; an overlong field is rejected rather than silently shortened. Before storage, the sanitiser removes recognised email addresses, URLs, phone numbers and @-handles. It does not recognise personal names and does not guarantee anonymity. Do not put personal information in signals. The organisation and its agent remain responsible for what they submit.

Database location. Our deployment records identify the Supabase database as Frankfurt, Germany (eu-central-1). The service and website run on Cloudflare Workers, and MCP session state is held in Durable Objects addressed with an EU jurisdiction, so a session's stored state is kept in the European Union. Our platform logs have no configured EU-only storage guarantee, according to the operational check on 16 September 2026. The content controls described below limit what specified application log lines contain; they do not provide a regional guarantee for logs or for all request processing.

Platform logs. Automatic invocation logging is disabled in the deployed MCP server configuration to avoid retaining request URLs that can contain trial credentials. Console output and errors can still be collected. The recorded post-deployment checks included unauthenticated requests to both endpoints; no retained log entries or errors were observed in the checked window. This observation does not establish that all request paths are log-free.

Application error content. The MCP repository-error log line contains a failure class, an operation from a closed vocabulary and an error code. It excludes the database's details and hint fields, call arguments and raw error objects. The corresponding error response uses the failure class and fixed wording. A local test checks that a row value supplied in an error does not enter this line. This is a control on that application message, not a claim about every field in a platform log event.

Retention and access. The operational check on 16 September recorded seven days of retention for MCP Workers Logs on our plan. The Cloudflare account had one member, with two-factor authentication enabled. These are dated observations about that log collection and account membership, not a retention guarantee for every diagnostic surface.

Bench logs. Persistent Workers Logs collection is not enabled in the website Worker configuration. The bench still emits error messages that may contain submitted values and can be exposed during live debugging. Those messages need sanitisation before persistent collection is enabled; access to live diagnostics also needs to account for their potentially sensitive content.

Backups. The operational record on 16 September reports daily database backups, seven days of history and storage in the project's region. Point-in-time recovery is not enabled. Restoring a daily backup loses writes made after that backup: the interval can approach twenty-four hours if daily backups succeed, or be longer if a backup fails. The checks described here did not include a recovery drill.

Accepted limitations

The project maintains a register of accepted limitations, with tests that pin the described behaviour. Acceptance is a recorded engineering decision, not evidence that a limitation is harmless.

  • Revoking a trial key does not end every already-open session. Revocation prevents new access with that key but is not a guarantee that every existing trial session has ended. Account standing is checked on each tool call, so suspension or removal still stops tool access. This limitation was accepted to avoid additional session-revocation machinery for trial access.
  • A report can be partly accepted. Signals are checked individually for duplicates. Resending an expanded report can store its new signals while recognising earlier ones as already present; the response reports each result. This is intentional so that a retry or addition does not require rejecting the whole report. Without an idempotency key, a repeated signal can become another stored row.
  • Sanitisation does not remove personal names. The accepted scope is pattern-based identifier removal. A guessed list of names would miss names and remove ordinary words while suggesting a protection it could not provide.
  • A newly issued trial key temporarily exists in plaintext in session storage. It remains in the issuing Durable Object's stored properties until the first tool response hands it over, after which that field is removed. If no tool is called, it can remain until the object is removed. The database holds the key's digest. The window was accepted to preserve credential handover across session hibernation.

The register's earlier, time-limited write-isolation entry was closed after migration 047 added the checks described above. That closure does not remove the application responsibility for MCP reads.

What you can verify, and how to contact us

The architecture page explains the limits of external verification: the implementation and deployment configuration are not public, and service responses do not prove the internal controls. This page adds specific review results and known limitations to that account. No third-party audit certification is claimed.

To report a suspected vulnerability or ask about a boundary relevant to your intended use, contact hello@labbel.ai. Describe the affected operation and, where possible, reproduction steps using synthetic data. Do not include credentials or another organisation's data in the message.

Changes in this document

  • Revision 6: distinguishes the limited post-deployment checks from local session-isolation tests; separates persistent log collection from live diagnostics; narrows the region, retention and backup claims to the recorded evidence. Removes stale pending-deployment wording.
  • Revision 5: added the 16 September deployment record and operational observations about logs, account access, location and backups. Revision 6 corrects the scope of conclusions drawn from those observations.
  • Revision 4: adds the dated Daybreak review, all five S+ correction areas and subsequent Astra review; separates local verification from pending deployment and production checks. Describes the findings process without claiming continuous scanning. Narrows the logging claim to the MCP path and keeps outstanding operational verification visible.
  • Revision 3: rewrites the logs paragraph after the 15 September correction (finding A4): the server's log line carries the failure class, the operation and the error code, never row values. Platform log settings remain unverified.
  • Revision 2: removes a stale pending-review statement from the revision history. The current publication review status appears at the top; the specific unverified settings remain identified in the text.
  • Revision 1: describes the 7 September review, the reported corrections and deployment, organisation isolation, retained data and accepted limitations.

This page is also served as markdown at labbel.ai/security.md — agents read documents.