§ 3
Technical Approach
3.1 Recommended stack
| Layer | Choice | Why |
| Frontend | Next.js 15 (App Router, TypeScript) | Server components reduce data over the wire (RFP §4.1); strong accessibility primitives; first-class Vercel deployment. |
| UI library | Tailwind CSS + shadcn/ui (Radix primitives) | Radix ships accessible primitives (keyboard nav, focus, ARIA) out of the box — less WCAG remediation in Phase 2. |
| Backend / API | Next.js Route Handlers + tRPC | One TypeScript type system across client and server reduces integration bugs and shortens QA cycles. |
| Database | PostgreSQL via Supabase | Relational model fits assessments, weights, candidates, scores, audit logs. Row Level Security enforces tenant isolation in the database. |
| Auth | Supabase Auth | Standards-based. OAuth-ready for Phase 2 Google/Apple sign-in. Integrates with RLS for portal-level access. |
| Storage | Supabase Storage (S3-compatible) | Candidate document uploads, company logos, generated reports — signed-URL access with audit trail. |
| Payments | Stripe (Checkout, Customer Portal, Webhooks) | RFP-specified. PCI scope minimized via hosted Checkout. Webhook-driven credit ledger. |
| Email | Resend with React Email | Templates are version-controlled and previewable in CI. Strong deliverability for candidate invitations. |
| PDF generation | React-PDF + Puppeteer fallback | Deterministic layout for candidate and client report variants. |
| Hosting | Vercel + Supabase + AWS S3 (cold backups) | Region-aware edge delivery for the geographic spread in SRS §2.5. |
| Observability | Sentry · PostHog (PII-masked) · Better Stack | Covers RFP §8.2 error tracking, session replay, user behavior — GDPR-compatible defaults. |
| Infrastructure | Terraform + GitHub Actions | IaC required for SOC 2 readiness (RFP §4.3). |
| Background jobs | Inngest or Supabase Edge Functions | Email scheduling, reminders, scheduled deletions. |
3.2 Database selection rationale
The SRS asks for written justification of the database choice. We recommend PostgreSQL via Supabase over document or key-value alternatives for three concrete reasons:
- The data model is relational. Companies own jobs; jobs reference assessments and batteries with per-assessment weights; assessments contain ordered questions; candidates produce scored responses joined back to questions. These joins are first-class in Postgres and awkward in document stores.
- Row Level Security is the cleanest tenant isolation model. Supabase exposes Postgres RLS policies that map directly onto the four client roles (Super-Admin, Admin, Editor, Reviewer), the internal SciRec staff role, and the Phase 2 Organizations sub-unit model. RLS is enforced in the database, not in the application — which materially reduces the risk of access-control bugs.
- Audit logging is straightforward. Postgres trigger functions write to an append-only audit table on every significant action, serving the SOC 2 readiness requirement in RFP §4.3 directly.
3.3 High-level architecture
The platform is a single Next.js application serving three logical portals (Candidate, Client, Internal), differentiated by authenticated role. Server components fetch data through a thin tRPC layer that calls Supabase via the service role for trusted operations and via the user role (with RLS) for everything else. Stripe webhooks drive the credit ledger. Resend handles transactional email through background functions. PDF generation runs server-side and is stored in Supabase Storage with signed-URL access.
Key architectural choices, mapped to RFP non-negotiables:
- Candidate-safe deployments (RFP §4.1). Vercel's atomic deployments combined with a session-aware "assessment in progress" flag. New deployments do not interrupt active assessment sessions because client-side state and server APIs are versioned for the duration of the session. A feature flag (replacing the Bubble Variables toggles) lets SciRec block new assessment starts during scheduled releases.
- Performance over varied connections (RFP §4.1). Server components reduce JavaScript shipped to the client. Static assets are CDN-delivered. Assessment payloads are paginated by question. The candidate runtime targets sub-100KB of JavaScript on first load.
- High availability (RFP §4.1). Vercel's edge network and Supabase's multi-AZ Postgres provide redundancy. Point-in-time recovery is included. Encrypted nightly snapshots replicate to a separate AWS region.
- Architected for Phase 2 (RFP §4.5). Strings are externalized from day one to support future i18n (including RTL and non-Roman scripts). The scoring engine is implemented as a pure-function library that statistical extensions (tertiles, quartiles, Z-scores) plug into without schema changes. The assessment process model supports multiple stages even though only one stage is exposed in the MVP.
3.4 GDPR compliance
- Data subject access: clients and candidates request and download a machine-readable export of their personal data through a self-service flow.
- Right to erasure: a candidate-initiated deletion flow purges PII while retaining hashed, anonymized response data for psychometric integrity. SciRec staff can also action erasure requests from the internal portal.
- Lawful basis and consent: candidate consent is captured at the start of every assessment with versioned consent records linked to the candidate ID.
- Data residency: primary database hosted in the EU region (Supabase EU-West) by default; jurisdictional preference confirmed in discovery.
- DPA: a Data Processing Agreement is provided and signed before any production data is handled.
- Session replay and analytics tooling run with PII masking on by default (see §3.8).
3.5 Security
- TLS 1.3 in transit (TLS 1.2+ minimum per RFP); AES-256 at rest via Supabase and Vercel.
- Sessions secured with HttpOnly, Secure, SameSite=Lax cookies.
- Password policy: 12-character minimum, breached-password check against HaveIBeenPwned, rate-limited login, lockout on repeated failures.
- OWASP Top 10 protections: parameterized queries, output encoding, CSRF tokens, content security policy, security headers via Vercel edge middleware.
- Dependency scanning via Dependabot and weekly
npm audit; secrets in GitHub Actions environments, never in code.
- Third-party penetration test included in the fixed price (see §9.2).
3.6 Accessibility
The MVP foundations in RFP §4.2 and SRS §3.4 are table stakes:
- Component library (shadcn/ui on Radix primitives) ships keyboard nav, focus management, and ARIA semantics by default.
- Heading hierarchy, landmark regions, and form-field labelling enforced through linting (
eslint-plugin-jsx-a11y) and code review.
- Color palette selected at design time using a contrast checker; tokens validated in CI.
- Assessment-taking interface tested with NVDA and VoiceOver during QA on every sprint that touches it.
Full WCAG 2.2 AA compliance — including third-party audit and remediation — is quoted separately in §9.3.
3.7 SOC 2 readiness
We will build the MVP so that SOC 2 Type II certification in Phase 2 is a documentation and observation exercise, not a re-architecture:
- Audit logging. An append-only
audit_log table records every authentication event, permission change, data export, credit transaction, and significant data modification — with timestamp, actor, and resource.
- Infrastructure as code. All infrastructure (Vercel projects, Supabase configuration, Resend domains, Stripe webhook endpoints) captured in Terraform and version-controlled.
- Separation of duties. Production secrets live only in Vercel's production environment. Developers have no direct production database access. Releases require pull-request approval from a second reviewer.
- Data retention. Configurable per-resource retention policies, scheduled deletion jobs, verification logs.
- Documentation. A security and operations runbook is delivered at handover, formatted to align with the SOC 2 trust services criteria.
When Phase 2 begins, we will recommend an experienced SOC 2 auditor partner. Building to the criteria from day one is the work that matters; the audit itself is structured once the foundation is in place.
3.8 Monitoring, error tracking, and session replay
RFP §8.2 asks specifically about production monitoring, session replay, user-behavior understanding, and GDPR implications. Our recommendation:
- Sentry — error tracking and performance. Source-mapped stack traces, release tagging, performance traces for slow API routes. PII scrubbed via
beforeSend hook.
- PostHog — product analytics and session replay. Replay enabled only for client-portal and internal-portal users; disabled on the candidate-facing assessment runtime by default. PII masking on all text inputs; replays purged after 30 days.
- Better Stack — uptime and structured logs. External heartbeat checks against all three portals.
Candidate consent for analytics is captured at session start; the candidate runtime can be configured to disable replay entirely if you prefer a more conservative posture. The final posture is agreed in discovery.