Docs

Security and data

What agentappbuilder stores, including captures of your app, how keys and isolation work, how prototypes render, where data lives and what we do not protect.

The organising idea

Built so that a compromised platform holds nothing that can act on your systems.

Your agent runs on your machine, with your credentials. The platform holds prototypes and their metadata, the screenshots your agent captures of your app, and two kinds of secret, both stored only as SHA-256 hashes: project keys, which only open a project on the platform itself, and the claim tokens of pending projects. It stores no credential for your repository, your database or your hosting, so there is nothing on the platform that could push a commit or change your data.

What is stored

Data Details
Your account Your email address, for sign-in by code.
Sign-in requests For 30 days, the network address (IP) and the email address of each code request, to limit abuse. The last code sent to an address, for 10 minutes, so that asking again sends the same code.
Organizations Name and members with their role (owner, admin, member).
Projects Name, status, and for a pending project the SHA-256 hash of its claim token and its expiry date.
Project keys The SHA-256 hash of each key, its first 12 characters, its name, kind, expiry, last use (updated at most once a minute) and revocation date.
Apps and screens Names, kinds, device presets, descriptions, routes, source file paths, folder paths and canvas positions, as your agent or you set them.
Frames and versions State labels and, for each version, the prototype HTML (or, for a capture version, the path of its image), its description, change note, optional contract, its variant label and round when your agent proposed it as a variant, and your user identifier when you made it (a copy made with Duplicate, or your edits in the canvas, with the version you edited and the list of your edits: element, property, values before and after).
Captures Screenshots of your running app, one per captured state, as JPEG, PNG or WebP files in a private storage bucket. With each: the address captured, the window size and the date.
Flow links and notices The links between frames with their triggers, and the questions relayed to your agent with your decisions.
Journal One entry per write of your agent (for example “version added”) and per project, key, claim, import, variant choice, duplicate or edit action in the app, with a short payload: names, version numbers, counts, identifiers, and the optional note your agent adds when it reports an implementation.

Prototype HTML is stored in the database, in the same place as the rest of the project. Capture images are files in Supabase Storage, in the same Supabase project; the database keeps their paths.

What is never stored

  • Your source code. Your agent writes prototypes as separate HTML; what they contain (texts, sample data) is up to you and your agent.
  • The credentials of your app. When your app needs a sign-in to be captured, your agent uses the demo account that your repository documents, or asks you for demo credentials, and passes them to its script as environment variables, on your machine. The script sends only images.
  • Git, GitHub, database or hosting credentials. The platform has no connection to your repository or your database today. A read-only GitHub connection is coming next.
  • Your Claude subscription or any model token: the platform runs no model for you.
  • Project keys in clear, and claim tokens in clear.

Project keys

  • A key is aab_ followed by 64 hexadecimal characters: 32 random bytes from the database’s cryptographic generator.
  • Only its SHA-256 hash is stored. The key is shown once, when it is created, and cannot be shown again.
  • A key opens one project. Every tool call is checked against the key’s project.
  • When your agent creates a project, it saves the key in a file outside your repository that only you can read, reads it from there in each command and never prints it. It does not add the MCP server itself: you run that command if you want it, and Claude Code then keeps the key in its own configuration.
  • Temporary keys come with a pending project and expire with its claim link (7 days). Your agent can renew the link, and the key with it, only before it expires. Claiming the project makes the key permanent.
  • Revocation: once the project is claimed, an owner or admin revokes a key in Settings, Keys. It stops working at once. The key of a pending project cannot be revoked from the app.

Captures of your app

A capture is a picture of whatever your app displayed at that moment. The rules tell your agent to capture with demo data only, never real customer data. The platform does not read, blur or filter the images: what the app showed is what is stored.

The screenshots leave your machine, so your agent captures right away only when your message names both the Playwright install and app.agentappbuilder.com. Otherwise it first asks you, in one message: the screens it will capture, where they go, that your app must show demo data only, and the account it will sign in with. It captures once you send back the sentence it gives you, “Install Playwright in /tmp/aab-capture and send the screenshots to app.agentappbuilder.com.” It uses only the script of the guide, which posts the screenshots itself: it never copies the HTML of your app, never starts a local server to collect pages and never sends source code.

  • Where: a private bucket named captures in Supabase Storage, region eu-west-1. It accepts only JPEG, PNG and WebP images of up to 2 MB. The server also checks the first bytes of each image against its declared type.
  • Who writes: only the agent server, when your agent’s script sends a capture with the project key. No account and no browser can write to the bucket.
  • Who reads: members of the project’s organization, once the project is claimed. The app asks for signed links valid one hour and renews them while the canvas is open. Your agent gets a signed link, and over MCP the image itself, from get_frame. Anonymous visitors, including someone with the claim link, see no capture.
  • Through the model: sending a capture does not go through the model; the script posts the image directly. Reading it back with get_frame over MCP attaches the image to the result, so your agent can see the screen it recreates. Over HTTP, your agent downloads the signed link to a temporary file outside your repository and opens it, with the same effect.
  • In the app: capture images are shown as plain images. The app’s content security policy allows images only from its own origin, data: and blob: URLs, and the Supabase project that serves the signed links.

Quotas

A pending project can be created by anyone, so its captures are capped: 10 MB per project, and 200 MB for all pending projects of the platform together. Past these, captures are refused, even a new capture of a state that already has one: the image it would replace still counts until it is removed. Claiming the project lifts both limits. Within the 10 MB of a project, deleting live frames also frees room, unless an imported capture version still shows their image. Claimed projects have no capture quota of their own today.

When captures are deleted

  • A new capture of the same state replaces the previous one, whose image is deleted unless an imported capture version still shows it.
  • delete_live_frame deletes the image of a live frame, unless an imported capture version still shows it.
  • delete_proto_frame deletes the images of the frame’s capture versions, unless the live frame or another version still shows them.
  • When a pending project was never claimed and its claim link has expired, its images are removed from storage in batches of up to 100, after a later capture of a pending project succeeds. There is no scheduled cleanup: until then, the images stay in storage.

Isolation

Row level security is enabled on every table. There are three ways in:

  • You, in the app: you read your organizations, their members and their active projects, plus the preview of a pending project whose claim link you have. You can change only a few columns: the active version of a frame, the position of a screen on the canvas, and, as an owner or admin, the project and organization names. Creating projects, keys and claims goes through database functions that check your role. Importing captures into the prototype goes through a database function that checks you are a member of the project’s organization. Choosing a variant and duplicating a state or a screen go through database functions that check you are a member of the project, and that it is claimed. Saving your edits in the canvas goes through the agent server: the app sends your session token and a list of typed changes (an element, a property from a fixed list, a value checked against its grammar), never HTML. The server verifies the token with the sign-in service, rewrites only the style attribute of the elements you changed, and writes the version under your identity (the authenticated role with your claims), through a database function outside the public API that checks you are a member of the claimed project.
  • Your agent: the agent server checks the key, then runs each tool call in one transaction under a dedicated database role, aab_agent, with the key’s project set for that transaction only. The row level security policies of that role only match rows of that project. Its write privileges (insert and update) are granted column by column; it reads and deletes only through those project-scoped policies.
  • The agent server itself: it connects to the database with a privileged role, which row level security does not restrict. By design (in its code, not enforced by the database), it uses that connection only to call three functions of a private schema that the public API does not expose (authenticate a key, create a pending project, renew a claim link), and to read the sizes and paths of stored captures for the quotas and the removal of expired pending projects. It then switches to aab_agent for each tool call and each capture, and to authenticated, with the claims of your verified session token, to save your edits in the canvas. It also holds the storage service key, which it uses only on the captures bucket: to store, sign, read and delete capture images.

Anonymous visitors can read the name, screen and frame counts and expiry date of a pending project from its claim link, and create a pending project through the agent server. They cannot read any capture.

This isolation is tested with pgTAP tests on a real local database: between organizations, between projects, and for the agent role.

How prototypes are rendered

Prototype HTML is written by an agent, so the app never trusts it:

  • It renders in an iframe with an empty sandbox attribute: no script, no form, no navigation, an opaque origin.
  • While you edit a frame on the canvas, that frame only renders with sandbox="allow-same-origin" and still without scripts, so that the app can read and restyle its elements: no script or inline event handler of the HTML runs, and the content security policy below still blocks the network. The app reads that document only through its own DOM functions and its own copy of the HTML tree, so a name in the HTML (a field called parentElement, an image called elementFromPoint) cannot mislead or freeze the editor. Copying a frame as PNG uses the same setting.
  • Before rendering, the app puts a content security policy at the top of the HTML: default-src 'none'; style-src 'unsafe-inline'; img-src data:; font-src data:. The frame cannot load anything from the network.
  • The app itself is served with a content security policy that only allows scripts from its own origin.

Prototypes are shown inside the app, from the database, not from a separate origin.

Where your data lives

The database, the capture storage, the sign-in service and the agent server run on Supabase in the region eu-west-1, in Ireland. The web app is served by Netlify, which also relays /mcp and /api to the agent server in the same region. Sign-in emails are sent by Resend.

Deleting data

Every row of a project (apps, screens, frames, versions, links, notices, journal, keys) references the project and is deleted with it. Capture images are files in storage, not rows: deleting the rows does not remove them by itself. There is no delete button in the app yet: write to hello@logics-studio.com to delete a project or your account, and ask for its captures to be deleted with it.

Your agent can delete a single frame when you ask: delete_proto_frame for a prototype frame with its versions and links, delete_live_frame for a live frame with its capture. See when captures are deleted.

What we do not claim to protect

  • A compromised developer machine. Your agent has your credentials and your project key. Someone who controls your machine controls both.
  • What you put in prototypes. Texts and sample data in prototype HTML are stored as your agent writes them. Ask your agent to use sample data rather than real customer data.
  • What your app shows in captures. A capture stores whatever was on screen, including personal data if the app displayed any. The platform does not check the images. Capture with a demo account and demo data.
  • A leaked key. Whoever has the key can read and write the prototypes of that project, send captures and read the existing ones, until you revoke it. It gives no access to anything else. While a project is pending, its key cannot be revoked from the app, and its holder can renew the claim link (the previous link stops working) and claim the project. Claim it first, then revoke the key.