Skip to content

Security architecture

Security architecture review note

A buyer-level map of access, application, data, integration, logging, and deployment controls to review before production.

Last reviewed: 2026-09-24. Final contractual commitments must be reviewed before signature.

Review status: Operational security draft. Confirm final controls, legal wording, and customer-specific commitments before contract signature.

Access and identity

TwentyCore uses authenticated browser access, JWT sessions, tenant-aware user context, role permissions, and optional 2FA/TOTP for user hardening.

  • Confirm admin, finance, operations, warehouse, and quality roles during onboarding.
  • Review 2FA policy and backup-code process before adding production users.
  • Limit privileged account count and review inactive users monthly.

Application and API boundary

The web app talks to API routes under `/api/v1`; backend handlers should enforce tenant context and role requirements before returning business records.

  • Verify API health, router health, migration health, and auth/session checks after deploy.
  • Keep frontend public environment variables separate from backend secrets.
  • Use request IDs and structured logs for production support.

Data and tenant isolation

Tenant isolation is enforced twice: every query is scoped to the signed-in user's tenant, and PostgreSQL row-level security is enabled and forced on every tenant-scoped table, with the tenant set on each request. The API refuses to start on a database role that bypasses RLS.

  • A PostgreSQL check in CI fails when any table with a tenant_id column lacks an enforced RLS policy.
  • Run tenant-isolation regression tests before production release.
  • Prefer PostgreSQL integration testing for finance, inventory, sales, procurement, and WMS flows.
  • Capture restore-drill evidence for production backup confidence.

Buyer checks

Questions this document should help answer.

Can the team show tenant A cannot read tenant B data?

Are production secrets kept out of Vercel/frontend builds?

Are request IDs visible in support logs?

Is there a rollback and restore path that has been rehearsed?