Security

Your code never leaves GitHub.

Bundlle is built around a simple rule: read only what you need, store only what matters, and explain every decision out loud.

What Bundlle reads — and what it keeps

Bundlle reads the lightweight signal GitHub already produces for every push and pull request. It keeps only the outcome of the match. Source code, file contents, and line-level diffs are never read, persisted, or forwarded anywhere.

What we read

  • Branch names
  • Commit messages
  • Pull request titles
  • PR open / merge / close events
  • Author username

What we store

  • Matched task reference
  • Confidence score (0-100)
  • AI decision and clear reason
  • Event timestamp
  • Project and workspace IDs

File contents, line-level diffs, and full commit payloads are never read, stored, or sent to any third party — including the AI provider.

Access control

A layered model so that no single boundary failure exposes data.

Tenant isolation at the database level

Row Level Security is enforced at the Postgres engine on every table — workspaces, projects, tasks, members, and GitHub connections. Every authenticated request carries a Clerk JWT whose subject claim is the only identity the database trusts (auth.jwt()->>'sub'). Anonymous requests match no policy and are denied entirely. Application-level workspace filters run as a second check on top of RLS, so access is double-gated end-to-end.

GitHub webhook verification

Every incoming GitHub event is verified by HMAC-SHA256 (x-hub-signature-256) before any payload field is read or stored. Events that fail the signature check are rejected with no further processing. Per-project API tokens are derived on demand using HMAC-SHA256 keyed by a server secret and are never stored in the database — so there is no token table to exfiltrate.

GitHub OAuth and token storage

The GitHub OAuth flow sets a CSRF cookie to validate the state parameter before the authorisation code is exchanged. GitHub is a workspace-level integration that only an owner or admin can connect — one connection per workspace, stored in an RLS-protected table (github_connections). The access token is read only server-side with explicit per-workspace scope, so it's never exposed to members through the client.

AI confirmation tokens

When Bundlle's confidence is below the auto-move threshold (80%), it emails a yes/no confirmation link with a single-use token valid for 48 hours. Once a token is used the used_at timestamp is written and the token is rejected on any repeat click. Every AI decision — auto-moved, pending, or skipped — is recorded in ai_matches and visible to all workspace members in the AI Activity panel. Nothing the AI does is hidden.

Service-role isolation

The service-role Supabase client (which bypasses RLS) is used only for three specific cases: incoming GitHub webhooks that have no user session, the Clerk webhook handler that runs before any user exists, and invite acceptance flows that must act before a new member has been granted membership. It is never used for user-initiated data reads or writes.

Infrastructure

Bundlle runs on providers with independent security certifications and strong baseline postures.

Authentication

Clerk

Identity, session management, and JWT issuance. Clerk is SOC 2 Type II certified and GDPR-ready.

Database

Supabase

Managed PostgreSQL on AWS. RLS is enforced at the database engine layer, independent of application code.

Hosting

Vercel

Edge-deployed on Vercel's global CDN. Automatic TLS everywhere, DDoS mitigation at the network layer.

Found a vulnerability?

We take security reports seriously and aim to respond within one business day. Please reach out before public disclosure so we can address it first.