Skip to main content

ADR-211: Validation Interview Tracking System

Status: Accepted Date: 2026-02-18 Deciders: Hal Casteel, CODITECT Engineering Track: N (GTM Launch)


Context

CODITECT's venture projects (starting with C-of-C-CANADA) require structured validation interviews as part of the customer discovery process. The V.1.2 Tracking Sheet (markdown-based) provides a static template, but a proper system is needed to:

  1. Track interviews across multiple projects — C-of-C-CANADA, future ventures, and CODITECT's own product validation
  2. Capture structured data — interview responses, scores, hypotheses validation, follow-up actions
  3. Support multiple users/teams — different interviewers tracking their own conversations
  4. Enable analytics — aggregate validation metrics, go/no-go thresholds, hypothesis confirmation rates
  5. Scale to a product feature — eventually offered as part of CODITECT's GTM strategy suite for customers

The system must support a phased approach: rapid local development first, then cloud deployment for multi-tenant usage.


Decision

Build a Validation Interview Tracking System as a reusable component in coditect-gtm-strategy with two phases:

Phase 1: Local SQLite + TypeScript UI

  • Database: SQLite with strict schema, local file-based storage
  • Language: TypeScript strict mode (no any, no implicit types)
  • UI: React/Vite local development server
  • Scope: Single-user, multi-project tracking
  • Data Model: Projects, Contacts, Interviews, Responses, Hypotheses, Scores, Actions
  • CLI: Optional command-line interface for quick data entry

Phase 2: Cloud Multi-Tenant (Future)

  • Database: PostgreSQL with row-level security (RLS) for tenant isolation
  • Auth: CODITECT SSO (OAuth2/JWT) — reuse existing auth infrastructure
  • Multi-tenant: Organization → Team → User hierarchy with project-scoped data
  • API: RESTful API (Django or FastAPI) behind CODITECT API gateway
  • Real-time: WebSocket updates for team collaboration
  • Analytics: Aggregate dashboards per project, per venture, cross-venture

Data Model

Core Entities

┌─────────────┐     ┌──────────────┐     ┌──────────────┐
│ Project │────<│ Contact │────<│ Interview │
│ │ │ │ │ │
│ id (PK) │ │ id (PK) │ │ id (PK) │
│ name │ │ project_id │ │ contact_id │
│ description │ │ org_name │ │ interviewer │
│ venture_id │ │ org_type │ │ scheduled_at │
│ status │ │ contact_name │ │ completed_at │
│ created_at │ │ title │ │ status │
│ updated_at │ │ email │ │ duration_min │
└─────────────┘ │ phone │ │ notes │
│ city │ │ recording_url│
│ state_prov │ │ overall_score│
│ country │ └──────────────┘
│ member_count │ │
│ staff_count │ │
│ annual_budget│ ┌──────┴───────┐
│ ams_platform │ │ │
│ status │ ▼ ▼
│ source │ ┌──────────┐ ┌──────────────┐
│ referral_from│ │ Response │ │ HypothesisVal│
└──────────────┘ │ │ │ │
│ id (PK) │ │ id (PK) │
│ interview│ │ interview_id │
│ question │ │ hypothesis_id│
│ section │ │ confirmed │
│ answer │ │ evidence │
│ score │ │ confidence │
│ notes │ │ notes │
└──────────┘ └──────────────┘

┌─────┴──────┐
│ │
▼ ▼
┌──────────┐ ┌───────────┐
│ Action │ │ Dimension │
│ │ │ Score │
│ id (PK) │ │ │
│ interview│ │ id (PK) │
│ type │ │ interview │
│ desc │ │ dimension │
│ assignee │ │ score │
│ due_date │ │ notes │
│ status │ └───────────┘
│ completed│
└──────────┘

Supporting Entities

EntityPurpose
HypothesisReusable hypothesis definitions per project (e.g., "80%+ pain confirmation")
InterviewTemplateSection/question definitions (reusable across projects)
OutreachPre-interview outreach tracking (emails sent, responses, scheduling)
ReferralReferral chain tracking (who referred whom)

Schema Design Principles

  1. Project-scoped everything — All data belongs to a project; no orphaned records
  2. Audit trailcreated_at, updated_at, created_by on all tables
  3. Soft deletedeleted_at column instead of physical deletion
  4. Enum as text — Status fields stored as text for SQLite compatibility, validated at app layer
  5. JSON columns for flexibilitymetadata JSONB for extensible attributes without schema changes
  6. Score normalization — All scores on 1-5 scale with decimal precision

TypeScript Type System

// Strict mode: no any, no implicit types
// All types exported from types/index.ts

interface Project {
id: string; // UUID
name: string;
description: string;
ventureId: string; // Links to CODITECT venture
status: ProjectStatus;
hypotheses: Hypothesis[];
template: InterviewTemplate;
createdAt: Date;
updatedAt: Date;
}

type ProjectStatus = 'planning' | 'active' | 'paused' | 'completed' | 'archived';
type ContactStatus = 'prospect' | 'contacted' | 'responded' | 'scheduled' | 'completed' | 'declined' | 'referred' | 'follow_up';
type InterviewStatus = 'scheduled' | 'in_progress' | 'completed' | 'cancelled' | 'no_show';
type ActionStatus = 'pending' | 'in_progress' | 'completed' | 'cancelled';
type ActionType = 'follow_up' | 'demo' | 'proposal' | 'referral' | 'internal' | 'escalation';

Phase 1 Technology Stack

ComponentTechnologyRationale
DatabaseSQLite (better-sqlite3)Zero-config, file-based, portable
ORMDrizzle ORMTypeScript-first, SQLite support, strict types
UI FrameworkReact 18 + ViteFast development, CODITECT standard
StylingTailwind CSSCODITECT design system compatible
StateZustandLightweight, TypeScript-first
FormsReact Hook Form + ZodType-safe validation
ChartsRechartsLightweight, React-native
Exportxlsx + jsPDFOffline report generation

Phase 2 Migration Path

Phase 1 (Local)Phase 2 (Cloud)Migration
SQLitePostgreSQL + RLSDrizzle handles dialect switch
File-based authCODITECT SSO (JWT)Add auth middleware
Single userMulti-user/team/tenantAdd tenant_id, user_id columns
Local storageGCS/S3 for recordingsAdd storage service abstraction
No APIREST API (Django/FastAPI)Extract service layer
Local reportsCloud dashboardsAdd Grafana/custom dashboards

Multi-Tenant Schema Extension (Phase 2)

-- Added columns for multi-tenancy
ALTER TABLE projects ADD COLUMN tenant_id UUID REFERENCES tenants(id);
ALTER TABLE projects ADD COLUMN team_id UUID REFERENCES teams(id);
ALTER TABLE interviews ADD COLUMN interviewer_id UUID REFERENCES users(id);

-- Row-level security policies
CREATE POLICY tenant_isolation ON projects
USING (tenant_id = current_setting('app.tenant_id')::UUID);

Directory Structure

coditect-gtm-strategy/
├── 09-validation-tracking/ # New directory
│ ├── README.md # System documentation
│ ├── package.json # Dependencies
│ ├── tsconfig.json # Strict TypeScript config
│ ├── drizzle.config.ts # Database config
│ ├── src/
│ │ ├── db/
│ │ │ ├── schema.ts # Drizzle schema definition
│ │ │ ├── migrations/ # Auto-generated migrations
│ │ │ └── seed.ts # Sample data seeder
│ │ ├── types/
│ │ │ ├── index.ts # All TypeScript types
│ │ │ ├── project.ts # Project types
│ │ │ ├── contact.ts # Contact types
│ │ │ ├── interview.ts # Interview types
│ │ │ └── analytics.ts # Analytics types
│ │ ├── services/
│ │ │ ├── project.service.ts # Project CRUD
│ │ │ ├── contact.service.ts # Contact CRUD
│ │ │ ├── interview.service.ts # Interview CRUD
│ │ │ └── analytics.service.ts # Aggregation queries
│ │ ├── ui/
│ │ │ ├── App.tsx # Main app shell
│ │ │ ├── pages/ # Route pages
│ │ │ ├── components/ # Shared components
│ │ │ └── hooks/ # Custom hooks
│ │ └── cli/
│ │ └── index.ts # Optional CLI interface
│ └── data/
│ └── validation.db # SQLite database file

Relationship to Existing Systems

SystemRelationship
C-of-C-CANADA V.1.2 Tracking SheetStatic predecessor; this system replaces it with dynamic tracking
C-of-C-CANADA V.1.1 Interview GuideQuestion templates imported as InterviewTemplate records
CODITECT Feedback System (N.2.5)Complementary; feedback is post-launch, validation is pre-launch
CODITECT GTM StrategyParent product; this is a module within the GTM toolkit
CODITECT Product SuitePhase 2 — offered as a feature for CODITECT customers doing their own validation

Consequences

Positive

  • Reusable — any CODITECT venture can use the same system
  • Data-driven go/no-go — aggregate scores and hypothesis validation rates drive decisions
  • Product potential — becomes a revenue feature for CODITECT customers
  • TypeScript strict — catches data model issues at compile time
  • SQLite portable — works offline, no server dependencies for Phase 1

Negative

  • Phase 1 single-user — no concurrent access in SQLite mode
  • Migration effort — Phase 1 → Phase 2 requires schema migration tooling
  • Additional maintenance — new codebase in gtm-strategy submodule

Risks

  • SQLite → PostgreSQL drift — mitigated by Drizzle ORM's dialect abstraction
  • Over-engineering Phase 1 — mitigated by strict Phase 1 scope (local only)
  • Template rigidity — mitigated by JSON metadata fields for extensibility

ADRRelationship
ADR-004Beachhead Market — defines ICP criteria used in contact scoring
ADR-005Pricing Strategy — informs budget/pricing interview questions
ADR-055Container Sessions — Phase 2 may use container-based analytics
ADR-118Database Architecture — Phase 2 follows CODITECT DB patterns
ADR-155Project-Scoped Session Logs — same project-scoping pattern

Document Control:

  • Created: 2026-02-18
  • Author: CODITECT Engineering Team
  • Review: Before Phase 1 implementation