Technical Architecture
How TrueConfig works under the hood: system design, data flow, and core components.
System Overview
TrueConfig is a continuous governance platform that monitors Microsoft 365 tenants for security misconfigurations and unauthorized changes. It operates by periodically scanning your Microsoft environment, comparing the current state against security baselines (DSC - Desired State Configuration), and detecting drift from the desired state.
┌─────────────────────────────────────────────────────────────┐
│ Microsoft 365 │
│ (Users, Admins, Security Policies, Applications) │
└─────────────────────────┬───────────────────────────────────┘
│
│ Graph API (OAuth 2.0)
↓
┌─────────────────────────────────────────────────────────────┐
│ TrueConfig Edge Function │
│ sync-tenant (Deno runtime, 8-phase scan) │
│ ├─ Phase 1-4: Fetch & Store Raw Data │
│ ├─ Phase 5: Create Security Snapshot │
│ ├─ Phase 6: Detect Configuration Drift │
│ ├─ Phase 7: Run DSC Control Evaluations │
│ └─ Phase 8: Finalize & Notify │
└─────────────────────────┬───────────────────────────────────┘
│
↓
┌─────────────────────────────────────────────────────────────┐
│ Supabase PostgreSQL │
│ ├─ tenant_* tables (scan data) │
│ ├─ dsc_evaluations (control results) │
│ ├─ drift_events (change detection) │
│ ├─ snapshots (state backups) │
│ └─ audit_log (immutable event log) │
└─────────────────────────┬───────────────────────────────────┘
│
│ RLS-protected queries
↓
┌─────────────────────────────────────────────────────────────┐
│ Next.js App │
│ ├─ Server Components (data fetch via getContext) │
│ ├─ Server Actions (mutations) │
│ └─ Client Components (UI interactivity) │
└─────────────────────────────────────────────────────────────┘Core Components
Edge Functions (Deno)
Stateless serverless functions that run the scanning logic. Primary function issync-tenantwhich orchestrates the 8-phase scan process.
supabase/functions/sync-tenant/PostgreSQL Database
Supabase-hosted Postgres with Row-Level Security (RLS) policies enforcing multi-tenant data isolation. All queries automatically filtered by organization_id.
supabase/migrations/DSC Evaluation Engine
Control evaluation system that compares scan data against baseline security controls. Each control has an evaluator function that returns pass/fail/warning status.
src/lib/dsc/engine.tsMicrosoft Graph Integration
OAuth 2.0 authenticated API calls to Microsoft Graph v1.0. Refresh tokens stored encrypted at-rest, rotated every 90 days per Microsoft best practices.
tenant_connections tableData Flow: Scan to Dashboard
1. Scan Trigger
Scans can be triggered manually (user clicks "Scan Now"), on a schedule (cron-based), or via API. The scan creates a new scan_id UUID and updates the tenant status to "scanning".
2. Data Collection (Phases 1-4)
Edge function makes parallel API calls to Microsoft Graph endpoints to fetch:
- Users (GET /users with $select for specific fields)
- Directory roles and role assignments
- Groups and group memberships
- Service principals and app registrations
- Conditional Access policies
- MFA registration status (if available)
Data is normalized and stored in tenant_* tables tagged with the current scan_id. Old scan data is retained per plan limits (30 days / 1 year / unlimited).
3. Snapshot Creation (Phase 5)
A complete snapshot of security-critical configuration (Conditional Access policies, role assignments, security defaults) is serialized to JSONB and stored in the snapshots table. This enables point-in-time comparison for drift detection.
4. Drift Detection (Phase 6)
Current snapshot is compared against the previous snapshot using PostgreSQL JSONB operators:
-- Simplified drift detection query
SELECT
jsonb_path_query(
current_snapshot - previous_snapshot,
'$.conditionalAccessPolicies[*] ? (@.state != "disabled")'
) AS changed_policies
FROM snapshots
WHERE scan_id = current_scan_id;Detected changes are recorded as drift_events with actor attribution from Microsoft audit logs when available.
5. Control Evaluation (Phase 7)
For each enabled control in the tenant's baseline:
- Load control definition and evaluator function
- Query scan data (e.g.,
SELECT * FROM tenant_users WHERE is_mfa_enabled = false) - Execute evaluator logic (compare expected vs actual state)
- Generate result object with status, severity, evidence, resource counts
- Upsert to
dsc_evaluationstable (composite key: tenant_id, scan_id, control_id) - Record audit event via
record_dsc_event()RPC function
6. Dashboard Display
Web app queries aggregated statistics on page load:
-- Deviation summary calculation
SELECT
COUNT(*) FILTER (WHERE status = 'pass') as passed,
COUNT(*) FILTER (WHERE status = 'fail' AND severity = 'critical') as critical,
COUNT(*) FILTER (WHERE status = 'fail' AND severity = 'high') as high,
COUNT(*) FILTER (WHERE status = 'fail' AND severity = 'medium') as medium,
COUNT(*) FILTER (WHERE status = 'fail' AND severity = 'low') as low
FROM dsc_evaluations
WHERE tenant_id = $1
AND scan_id = (SELECT MAX(scan_id) FROM tenant_scans WHERE tenant_id = $1);Results are computed on-the-fly (no pre-aggregated statistics stored) and cached at the Next.js request level using React cache().
Multi-Tenancy & Data Isolation
TrueConfig uses a strict hierarchical multi-tenancy model: User → Organization → Tenants. Data isolation is enforced at multiple layers:
Database Level (RLS)
Every table has Row-Level Security policies that automatically filter queries by organization_id:
-- Example RLS policy on tenant_users table
CREATE POLICY "Users can only access their org's tenant data"
ON tenant_users
FOR ALL
USING (
organization_id = (
SELECT organization_id FROM user_memberships
WHERE user_id = auth.uid()
)
);Application Level (Context)
All server components and actions use getContext() which loads and caches the user's organization context, permissions, and plan limits. Failed context checks return 403 errors.
// Every protected route starts with:
const context = await requireContext();
// context contains: user, organization, membership, plan, permissions
// All queries automatically scoped:
const { data } = await supabase
.from('tenants')
.select('*')
.eq('organization_id', context.organization.id); // RLS enforces thisAPI Level (Token Scoping)
Microsoft Graph API tokens are scoped per-tenant. Refresh tokens stored encrypted intenant_connections with unique tenant_ms_id foreign key. Cross-tenant access is architecturally impossible.
Plan Tiers & Feature Gating
TrueConfig offers three plan tiers (Essential, Pro, Scale) with different control sets and capabilities. Plan gating is enforced during control evaluation:
// In Phase 7 (DSC Evaluation)
const { data: planData } = await supabase
.from('plan_subscriptions')
.select('plan_tier')
.eq('organization_id', organizationId)
.maybeSingle();
const planTier: PlanTier = planData?.plan_tier || 'essential';
// Filter controls by plan tier
const planOrder = { essential: 1, pro: 2, scale: 3 };
const controlsToRun = enabledControls.filter(c => {
const controlPlan = c.minimum_plan_tier || 'essential';
return planOrder[controlPlan] <= planOrder[planTier];
});
// Essential: 15 controls, Pro: 33 controls, Scale: 33 controlsEssential (15 controls)
Foundational identity and privileged access controls. Manual remediation only. 3 scans/day limit. 30-day data retention.
Pro (33 controls)
Full control set including Conditional Access and application governance. One-click remediation. Unlimited scans. 1-year data retention.
Scale (33 controls)
Same controls as Pro with automated remediation, SIEM export, dedicated support, and unlimited data retention.