Compartable/ Security

What happens to your app, exactly

You are being asked to trust a hosting product with your code, your credentials, and your colleagues' attention. You should not have to take that on faith. This page describes what Compartable actually does, in the same terms we would want before hosting our own work anywhere.

The short version

Your code never runs on our server
Every hosted app is built on the provider's remote builders and runs in its own Firecracker microVM on Fly.io. Compartable's own server never executes user code, at build time or at runtime.
We cannot read your secrets
Env var values write through to the host's encrypted secret store and are injected only into your app's VM. Our database keeps the names so the UI can list them; it has no value column at all.
Private by default, enforced in the database
Visibility is Row Level Security, deny by default. A project you are not allowed to see returns the same 404 as one that does not exist. Feedback goes only to the project owner.

Where your secrets go

When you set an environment variable on a hosted app, the value makes one trip:

••••••
YouType KEY=value once, over HTTPS
Host's encrypted vaultFly.io secret store. Write-only from here
Your app's own VMInjected at boot, in memory only
Compartable's databaseKEYThe name arrives. The value structurally can't: the table has no value column, and a test asserts that stays true.

We do not store the value, and we do not hash it either. Hashing would imply we kept something; we keep nothing. The value goes over HTTPS to our server, which forwards it in the same request to Fly.io's encrypted secret store and then forgets it. The database table for env vars structurally has no value column, and an automated test fails the build if anyone adds one. Build and runtime logs are scrubbed against your app's known secret names before they are stored or shown. API errors from the pipeline deliberately omit request bodies and headers.

The practical consequence: nobody can leak what was never kept. If Compartable's database were stolen tomorrow, the thief would learn that your app has a variable named SNOWFLAKE_PASSWORD. They would not learn the password.

Where your app runs

Full-stack apps hosted through Compartable are built from your GitHub repo on the provider's remote builders and deployed as isolated Firecracker microVMs, one per app, under Fly.io. Isolation is the hypervisor's, not a shared Node process with good intentions. Apps scale to zero when idle and wake on the next visit, which is why the first request after a quiet spell takes a few seconds. Each app gets a pinned machine size and a per-owner app cap as cost guardrails.

Compartable never sets domain-wide cookies. Its auth cookies are host-only, so a hosted app on a sibling subdomain can never read your Compartable session.

When a project page shows the running app, it is embedded in a sandboxed frame, and how tightly depends on where that app lives. An app on its own origin, which is every app we host and every external link, is given back its own origin inside the frame so its stylesheets, fonts, and scripts actually load, while staying as separated from this page as any other website would be. Files hosted inside Compartable itself sit on our own origin, and those are held to the stricter setting: they run with no origin of their own, so a page someone uploaded can never reach into the page framing it, read your session, or act as you. The stricter rule is the default, and anything we cannot confidently classify gets it.

That containment has a cost we pay deliberately rather than weaken. A page with no origin of its own cannot present your session when it asks for its own stylesheets and scripts, so a multi-file site would load its HTML and then fail to fetch anything else. Rather than hand the frame our origin back, the project page issues it a signed token that is bound to that one project, expires in thirty minutes, and is readable only by the browser, never by the page's own code. It is minted only after you have already been allowed to see the project, and it permits exactly one thing: reading that project's files. It cannot open a different project, it cannot be reused for any other purpose, and a tampered or expired one is refused outright.

What we store, and what we never store

Stored
  • Your project files and metadata, RLS-scoped
  • Env var names and when they were last set
  • Your GitHub App installation id (an integer)
  • Build logs, after secret-name scrubbing
Never stored
  • Env var values, in any form
  • GitHub repo tokens. Each API call mints a short-lived, single-repo, read-only token, uses it in memory, and discards it
  • Your Google or GitHub password. Sign-in is OAuth through Supabase; we never see credentials

GitHub access, scoped to the point of paranoia

Connecting a repo goes through a dedicated GitHub App, not the sign-in flow, so logging in never asks for repo scope. The App requests read-only Contents and Metadata, and GitHub lets you pick exactly which repos it can see. Tokens are minted per request, live one hour, are scoped to the single repo being read, and are never returned to the browser or written to a log.

What a shared link gives away

When you paste a project link into Slack, email, or a message, the app on the other end fetches a preview as an anonymous visitor. What it gets depends on the project's visibility, and the rule is deliberate. Public and org-visible projects return their title, description, and cover image: a link to your team's dashboard should look like that dashboard, including for the colleague deciding whether to click. Private projects return nothing at all, the same blank card as a link to a project that does not exist.

The distinction to hold on to: this is the label on the door, never the room. A preview carries a title and a cover thumbnail. It does not carry the project, its files, its feedback, or its data, and the sign-in screen follows exactly the same rule when it tells an arriving visitor what they are about to open. Anyone who reaches the project itself still passes Row Level Security, every time. If a title alone is too much to reveal, that project should be private, and then a link to it says nothing whatsoever.

One related convenience worth naming, because it grants real access: if you follow a link to a project owned by an organization and sign in with an email address on that organization's own domain, you are added to it and shown the project, rather than being made to request permission for your own team's work. The domain match is re-checked inside the database when the join happens, so the page cannot grant anything the rules would not. Every other case still asks the project's owner.

The Claude connector, on your terms

Compartable can be added to Claude as a connector, so a page built in a chat can be published by asking for it. The direction of that pipe matters: Claude pushes to Compartable, never the reverse. Compartable holds no Claude credentials, cannot read your chats, and learns nothing about a conversation except the single page you explicitly told Claude to publish. On our side, the connection is a per-user grant you approve while signed in, scoped to three actions: publish a site to your own account, update a site you own, list your sites. Sites it publishes are private by default, like every other publish path. The tokens behind the connection are stored only as hashes, access tokens expire daily, and removing the connector in Claude ends the grant. Setup steps live at /claude.

Honest states over pretend features

Compartable runs with the minimum secrets it needs. Features whose credentials are not configured say so plainly in the UI instead of pretending to work. If something looks switched off, it is switched off, and turning it on is a deliberate act by the operator, not a default.

Prefer not to host it at all? Run it on your machine

Some tools should not live on a server: apps that hit big internal datasets, need per-person credentials, or are simply faster against local memory. For those, a project can be shared as run-it-locally instead of hosted. The project page shows your colleagues the clone, setup, and run steps, plus a .env template listing the variable names they need. Everyone fills in their own credentials, everything runs on their own machine with their own access, and nothing sensitive is uploaded to Compartable at all. The gallery is then just the map, not the territory.

Questions

If any claim on this page looks wrong, or you want detail this page does not give, ask the person who runs your Compartable workspace. Skepticism about where your credentials go is the correct instinct; this page exists because of it.