Loading…
How UAIU Holdings Corp (operator of ADAWCAG.org) protects authentication, tenant data, encryption keys, audit trails, and infrastructure for federal subcontracts and enterprise customers. Last updated May 13, 2026.
ADAWCAG.org is a multi-tenant SaaS platform delivering ADA / WCAG accessibility scanning, remediation, and audit deliverables for federal prime contractors, state and local agencies, and enterprise buyers. Our platform processes URLs belonging to customer organizations and stores accessibility findings keyed to each tenant. The controls below are the day-to-day baseline applied across the product.
This document is a public posture statement, not a third-party report. SOC 2 and ISO 27001 audits are tracked separately; contact justin@adawcag.org for current attestation status.
Sessions are issued as a signed JSON Web Token (HS256) using the jose library and stored in the app_session cookie. The cookie is HttpOnly, SameSite=Lax, and marked Secure in production. Tokens carry only the minimum claims required for routing (userId, tenantId) and are signed with JWT_SECRET, which is sourced from the platform secrets store and never committed.
maxAge=0.Passwords are hashed with bcryptjs at cost factor 12 before storage. Plaintext passwords are never logged, never written to disk, and never returned from any API. Password comparisons are performed in constant time via bcrypt.compare.
Authentication endpoints (login, signup) and other sensitive state-mutating routes require a matching CSRF token. A 32-byte random token is issued in the csrf_token cookie at first contact and must be echoed back in the x-csrf-token header on protected POST requests, where the server compares the header value against the cookie value (double-submit pattern).
Sensitive secrets (SSO client secrets, OAuth refresh tokens, outbound webhook signing keys) are wrapped with AES-256-GCM envelope encryption before being written to PostgreSQL. The implementation in lib/crypto.ts generates a fresh 96-bit IV per record, captures the 128-bit auth tag, and stores the ciphertext as enc:<iv>:<tag>:<data>. The 32-byte master key (MASTER_KEY_BASE64) is required in production — startup refuses to encrypt without it, and decrypt rejects malformed or wrong-length authentication tags.
All credentials (JWT_SECRET, MASTER_KEY_BASE64,ANTHROPIC_API_KEY, ZEPTOMAIL_TOKEN,GOOGLE_PLACES_API_KEY, SMTP credentials, and database URLs) are injected at runtime from the platform secrets store. They are not present in the repository, in build artifacts, or in client-side bundles.
Every tenant-owned record carries a tenantId column, and all Prisma queries that read or write tenant data are scoped by that column. Sessions resolve to a single tenantId on every request via requireSessionContext(), and downstream queries pass that ID intowhere clauses so a user can never read across tenant boundaries.
Government and agency partners receive scoped PortalTenant rows that bind a public-facing slug to both the operating agency tenant and the underlying client tenant. Host-based middleware (middleware.ts) maps custom domains to the correct portal, and only allowlisted hosts (adawcag.org, *.adawcag.org, Replit-hosted preview domains) bypass the per-domain lookup; unrecognized hosts are redirected to the canonical site.
Two append-only tables capture privileged activity:
AuditLog — per-tenant record of authentication events, configuration changes, and scheduled jobs (e.g. retention purges). Rows include actor email, action verb, target ID, source IP, user agent, and a JSONmeta blob.AuditorAction — captures human auditor activity (verifications, remediation sign-off) for evidence chains required by federal procurement.Each tenant has a configurable retention window stored on the Tenant row (default 365 days). The worker/retention.ts job runs on a schedule, deletes scans (and their dependent issues, pages, summaries, and assets) older than the cutoff, and writes a RETENTION_PURGE_COMPLETED entry into the audit log so the deletion itself is auditable.
Enterprise plans support OIDC and SAML 2.0 single sign-on. Identity provider client secrets and SAML signing certificates are stored using the same AES-256-GCM envelope encryption described above and decrypted only inside the request-handling process.
SCIM 2.0 user provisioning is available so customers can create users from their identity provider via the /api/scim/v2/Users endpoint, gated by a tenant-scoped bearer token (SCIM_BEARER_TOKEN). Update, deactivation, and just-in-time deprovisioning are on the enterprise roadmap; contact us for current status.
Outbound webhooks — every payload is signed with an HMAC over the request body using a per-tenant secret. Receivers verify the signature against the X-ADAWCAG-Signature header before trusting the payload. Secrets are rotatable from the dashboard; rotation re-encrypts and re-issues without downtime.
Inbound webhooks — the Calendly integration verifies the signing key on each event before any database write. Unsigned or signature-mismatched events are rejected with HTTP 401.
Please report suspected security issues to security@adawcag.org. We acknowledge reports within 1 U.S. business day and provide an initial triage assessment within 5 U.S. business days. Researchers acting in good faith and within scope will not face legal action from UAIU Holdings Corp.
Tenants whose data is implicated in a confirmed incident are notified by email to the workspace owner contact within 72 hours of confirmation, with a written post-incident summary inside 14 days.