Security posture

Enterprise-grade security for every platform we build.

We handle real money and real customer data. This page documents exactly what we do, what we don't do, and what we're still working toward. No vague claims about “enterprise-grade security.”

OWASP ASVS L2

Application standard

PCI DSS SAQ A

Payment compliance

AES-256

Encryption at rest

TLS 1.3

Encryption in transit

Application security

OWASP ASVS Level 2

Application Security Verification Standard

We build to ASVS Level 2, which covers 14 chapters and approximately 200 verification requirements spanning authentication, session management, access control, input validation, cryptography, error handling, data protection, communications security, malicious code protection, business logic, file handling, API security, and configuration. Level 2 is the standard for applications handling sensitive financial data.

OWASP Top 10 (2021)

Audited against all 10 categories

Every release is audited against all OWASP Top 10 categories: broken access control, cryptographic failures, injection, insecure design, security misconfiguration, vulnerable and outdated components, identification and authentication failures, software and data integrity failures, security logging and monitoring failures, and server-side request forgery.

Annual penetration testing

Third-party, CREST-accredited

We commission external penetration testing annually from a CREST-accredited firm. CREST is the internationally recognized accreditation body for penetration testing organizations. Testers are credentialed, methodology is auditable, and results are defensible. Tests include both automated scanning and manual adversarial testing with full codebase access.

Quarterly vulnerability scans

Dependabot + SAST + DAST

Between annual pen tests, we run automated vulnerability scanning quarterly. Dependabot monitors dependency CVEs continuously. Static Application Security Testing (SAST) analyzes source code for vulnerabilities. Dynamic Application Security Testing (DAST) scans running applications. Pull requests cannot merge with open critical or high-severity dependency alerts.

Secure development lifecycle

Security built into every stage

Security is integrated into our development process, not appended at the end. Threat modeling during architecture. Peer code review with security checklist. Automated security linting in CI. Dependency audit on every build. No code reaches production without passing security gates.

Input validation and sanitization

Zod schemas + parameterized queries

All user input is validated server-side using Zod schemas before processing. All database queries use parameterized statements via Drizzle ORM — no string concatenation, no eval(), no dynamic SQL. HTML output is automatically escaped by React's rendering engine. File uploads are validated for type, size, and content.

Payment security

PCI DSS SAQ A compliance

Self-Assessment Questionnaire A

We maintain PCI DSS SAQ A compliance, which applies to merchants that fully outsource all cardholder data functions to PCI-compliant third parties. Card data is tokenized in the customer's browser via Authorize.net's Accept.js hosted fields before it ever reaches our servers. We receive a CIM token, never a card number. SAQ A is the narrowest PCI compliance scope — appropriate because we genuinely never handle raw card data.

Authorize.net CIM vault

Customer Information Manager

Saved payment methods are stored in Authorize.net's PCI-compliant CIM vault — not in our database. We store only the CIM customer profile ID and payment profile ID. These tokens are useless without Authorize.net's API credentials. A breach of our database does not expose card numbers, CVVs, or expiration dates.

Client-side tokenization

Accept.js hosted fields

Card data entry uses Authorize.net's Accept.js hosted payment fields. These fields are rendered in iframes controlled by Authorize.net — our JavaScript cannot read the card number. The card is tokenized directly between the customer's browser and Authorize.net's servers. The token is then sent to our backend for processing. At no point does raw card data touch our infrastructure.

Transaction security

Charge, void, and refund controls

All payment operations (charge, void, refund) are routed through a dedicated API route handler with explicit error handling and audit logging. Payment amounts are validated server-side against invoice totals. Duplicate payment prevention is enforced. Every transaction is logged with actor identity, timestamp, and result.

Access control

Microsoft Entra ID SSO

Tenant-locked OIDC authentication

Internal staff authenticate via Microsoft Entra ID (formerly Azure AD) using OpenID Connect. The tenant is locked — only accounts within the specific organization's tenant can authenticate. External Microsoft accounts, Google accounts, personal accounts, and any credentials outside the tenant are rejected at the OIDC layer before any application code executes.

Role-based access control (RBAC)

Per-route and per-action enforcement

Every route and every server action is protected by RBAC. Roles are defined in code and the permission matrix is auditable in the repository. A customer service rep cannot access financial reports. A sales rep cannot access admin functions. Access denials are logged to the audit trail with the denied actor, attempted action, and timestamp.

Session security

HttpOnly + Secure + SameSite

Session cookies are set with HttpOnly (not readable by client-side JavaScript), Secure (transmitted only over HTTPS), and SameSite=Lax (prevents cross-site request forgery). Session tokens are rotated on privilege changes and login events. Sessions expire after configurable inactivity periods. Concurrent session limits can be enforced per role.

API authentication

JWT validation on every request

All API routes validate JWT tokens on every request. Tokens are short-lived and contain role claims injected during the Entra ID authentication callback. Expired tokens are rejected. Token claims are verified against the server-side role configuration. No API endpoint is accessible without valid authentication.

Data protection

Append-only audit trail

JSONB before/after snapshots

Every mutation — invoice update, payment, ticket reply, user role change, customer edit — generates an immutable audit record. Each record contains the before and after state as JSONB, the actor's identity, timestamp, IP address, and user agent. There are no UPDATE or DELETE code paths for audit records. They can only be appended, never modified or removed.

Encryption in transit

TLS 1.3 enforced

All data in transit is encrypted with TLS 1.3. TLS 1.0 and 1.1 are disabled. HTTP Strict Transport Security (HSTS) headers are set with a minimum max-age of one year. Certificate transparency logs are monitored. All internal service-to-service communication is encrypted.

Encryption at rest

AES-256 at the database layer

All data at rest is encrypted with AES-256 at the managed database layer (Neon PostgreSQL). Database backups are encrypted with the same standard. File storage (Cloudflare R2) uses server-side encryption. Encryption keys are managed by the cloud provider and rotated automatically.

Backup and recovery

Daily automated backups with point-in-time recovery

Databases are backed up daily with automated point-in-time recovery capability. Backups are stored in a separate geographic region from the primary database. Recovery procedures are tested quarterly. Backup retention is 30 days minimum. Recovery time objective (RTO) is under 4 hours for full database restoration.

Data isolation

Single-tenant architecture

Each Baseframe deployment is a single-tenant application with its own database, application instance, and credentials. Your data is never co-mingled with another client's data. There is no shared database, no shared application server, and no shared credentials between deployments.

Logging and monitoring

Structured logging with anomaly detection

All application events are logged in structured JSON format using Pino. Logs include request metadata, actor identity, and response codes. Authentication failures, access denials, and payment errors trigger real-time alerts. Logs are retained for 90 days minimum and are exportable for compliance review.

Infrastructure

Hosting infrastructure

DigitalOcean + Neon + Cloudflare

Applications are hosted on DigitalOcean with managed PostgreSQL on Neon. Static assets and file storage use Cloudflare R2. All providers maintain SOC 2 Type II compliance. Infrastructure is provisioned via code (infrastructure as code), not manual configuration.

Network security

Firewalls + WAF + DDoS protection

Application servers are behind a web application firewall (WAF) with DDoS mitigation. Database connections are restricted to application server IP addresses only — no public database access. SSH access to servers requires key-based authentication. All management ports are firewalled.

Dependency management

Automated CVE monitoring

All third-party dependencies are monitored continuously for known vulnerabilities via Dependabot and npm audit. Critical and high-severity CVEs are patched within 48 hours. Dependency updates are tested in a staging environment before production deployment. The dependency tree is audited on every build.

Environment isolation

Production, staging, and development

Production, staging, and development environments are fully isolated with separate databases, credentials, and configurations. Production secrets are never available in development. Environment variables are managed through platform-native secret management — never committed to version control.

What we're working toward

We don't claim things we haven't done. Here's what's on our security roadmap.

SOC 2 Type II

In progress. SOC 2 Type II requires a 6-12 month observation period with a licensed auditor. We follow SOC 2 controls and are working toward formal certification as our client base grows. Our infrastructure providers (DigitalOcean, Neon, Cloudflare) all maintain SOC 2 Type II compliance.

Bug bounty program

Not yet established. We accept responsible disclosure (see below) and are designing a formal bug bounty program with defined scope and reward structure.

ISO 27001

Not in scope for our current size. ISO 27001 is an information security management system standard more appropriate for larger organizations. We follow its principles without the formal certification overhead.

HIPAA

Not applicable to our current client base. If a client requires HIPAA compliance, we can scope a BAA and implement the necessary controls as part of the build engagement.

What we never do

  • We never store raw card data. Tokenization is enforced at the architecture level, not just policy.
  • We never use session cookies without Secure, HttpOnly, and SameSite flags.
  • We never log sensitive fields — card numbers, CVVs, passwords, and SSNs are excluded from all application logs.
  • We never write to Shopify. Our Shopify integration is strictly read-only.
  • We never expose internal stack traces or error details in production responses.
  • We never use eval(), dynamic SQL string concatenation, or innerHTML with unsanitized data.
  • We never store passwords in plaintext or with reversible encryption.
  • We never transmit credentials or tokens in URL query parameters.
  • We never disable HTTPS or allow mixed-content requests in production.
  • We never commit secrets, API keys, or credentials to version control.

Responsible disclosure

If you find a security issue, email [email protected]. We acknowledge within 48 hours. We take disclosures seriously and will communicate what we're doing about it. We won't threaten researchers who report in good faith.

Please don't run automated scanners against production systems, access customer data beyond what's necessary to demonstrate the issue, or disclose publicly before we've had a chance to respond.