AdministronAdministron
← Back home

Security & Data Protection

Your data is the product.We treat it that way.

Administron stores HR, payroll, and finance data — the kind of stuff you don't want leaking. Here's an honest, technical writeup of how we keep it safe and what we don't yet have.

Encryption — at rest and in transit

All data is stored on managed Postgres (Supabase). Encryption at rest uses AES-256 transparent disk encryption — the default on every Supabase database.

Every connection from your browser to Administron and from Administron to the database goes over TLS 1.2 or higher. There is no plaintext path.

  • AES-256 encryption at rest (managed Postgres default)
  • TLS 1.2+ required on all browser → server and server → DB hops
  • Secrets and tokens never logged

Role-based access control

Authentication is handled by BetterAuth — a well-maintained, open-source auth library. Sessions use secure, HttpOnly cookies that don't survive a logout, with sensible expiry and a database-backed rate limiter on the sign-in endpoints.

Inside the app, every server action and every API route checks the caller's role against an allow-list before doing anything. The same gate applies to actions performed by the AI agent.

  • Session cookies: HttpOnly, Secure, SameSite=Lax
  • Rate-limited sign-in (database-backed, shared across serverless instances)
  • Per-route role check via requireActiveOrganization(ORG_ADMIN_ROLES)
  • Server-side approval gate for destructive actions — the LLM cannot bypass it

Audit logs on everything that matters

Every create, update, and delete across employees, leave, claims, contracts, invoices, plans, positions, and payroll writes a row to activity_log. Each entry records who did what to which entity and when. Agent-driven actions get a 'via AI Agent' suffix so you can tell them apart from manual ones.

The log can't be edited from the app — it's append-only. Auditors can export it per organisation, per entity, or per period.

  • Append-only activity_log
  • Every mutation: creator, timestamp, entity type, entity id
  • Filter by entity type (employee / claim / leave / contract / payroll …)
  • Available to org admins; export-ready

Document storage

Receipts, contracts, and other uploads go to Vercel Blob with a per-organisation, per-employee path that includes a hard-to-guess nonce. Files are scoped so an admin can only see uploads from their own organisation.

Allowed types and sizes are enforced server-side: PDF, JPG, PNG, WEBP, up to 5 MB by default. Server actions validate the upload before it reaches storage.

  • Per-org, per-employee storage paths with random nonce
  • Server-side type and size enforcement
  • Org-scoped access — the upload action verifies employee ownership before writing

Org isolation

Every query in the application is scoped by organization_id. There is no API surface that returns data from a foreign organisation, and the AI agent's tools all run with the caller's organisation in context.

Membership is checked via the member table on every authenticated request — being signed in is not enough; you also have to be a member of the org you're trying to read or modify.

  • All Drizzle queries filtered by organization_id
  • Cross-org reads are not exposed by any route
  • Active-org gate via session.activeOrganizationId

Backups & disaster recovery

Database backups are managed by Supabase: daily automated snapshots and point-in-time recovery (depending on the plan tier). We don't store the only copy of your data — Vercel and Supabase each handle redundancy at the platform level.

Migrations run automatically on every deploy and are versioned in git. If a release ships a bad schema change we can roll forward with a fix in minutes — and the audit log preserves the data history.

  • Daily automated DB backups (Supabase)
  • Point-in-time recovery (plan-dependent)
  • Version-controlled, idempotent migrations

Employee data protection

Sensitive employee fields (NRIC, bank details, salary) are stored alongside non-sensitive fields in the same table — with the same access controls. Only admins of the same organisation can read them.

Employees are not exposed to other organisations' admins. There is no global employee directory across customers.

  • Per-org employee table — never shared across customers
  • Sensitive fields gated by ORG_ADMIN role
  • Activity log records every access to mutating endpoints

What we don't have yet

Boilerplate security pages tend to be aspirational. Here's the honest version of where the gaps are today:

  • We don't have SOC 2 or ISO 27001 certification yet. We can talk through our controls in writing if your procurement process needs it.
  • Two-factor authentication is supported by BetterAuth but isn't enforced by default — it's on the short-term roadmap.
  • Today the deployment is single-region (ap-southeast-1). Multi-region failover is planned but not yet shipped.
  • Data Processing Addendum (DPA) and Master Service Agreement (MSA) templates are available on request.

Need a security review or a DPA?

We answer security questionnaires in plain language and have a template DPA ready to share.