auth-compliance.ts123 lines · main
1/**
2 * Compliance metadata for briven auth tenants (Phase 6.6).
3 *
4 * Tracks SOC 2 Type II controls, HIPAA BAA, and GDPR DPA status.
5 * One row per tenant — created lazily on first read/write.
6 */
7
8import { runInProjectDatabase } from '../db/data-plane.js';
9
10export interface ComplianceSettings {
11 soc2ControlsUrl: string | null;
12 hipaaBaaSignedAt: string | null;
13 hipaaBaaSignedBy: string | null;
14 gdprDpaSignedAt: string | null;
15 gdprDpaSignedBy: string | null;
16 encryptionAtRestEnabled: boolean;
17}
18
19export async function getComplianceSettings(
20 projectId: string,
21): Promise<ComplianceSettings> {
22 const rows = await runInProjectDatabase<
23 Array<{
24 soc2_controls_url: string | null;
25 hipaa_baa_signed_at: Date | null;
26 hipaa_baa_signed_by: string | null;
27 gdpr_dpa_signed_at: Date | null;
28 gdpr_dpa_signed_by: string | null;
29 encryption_at_rest_enabled: boolean;
30 }>
31 >(projectId, async (tx) => {
32 return (await tx.unsafe(
33 `SELECT soc2_controls_url, hipaa_baa_signed_at, hipaa_baa_signed_by,
34 gdpr_dpa_signed_at, gdpr_dpa_signed_by, encryption_at_rest_enabled
35 FROM "_briven_auth_compliance"
36 LIMIT 1`,
37 )) as never[];
38 });
39
40 const row = rows[0];
41 if (!row) {
42 return {
43 soc2ControlsUrl: null,
44 hipaaBaaSignedAt: null,
45 hipaaBaaSignedBy: null,
46 gdprDpaSignedAt: null,
47 gdprDpaSignedBy: null,
48 encryptionAtRestEnabled: true,
49 };
50 }
51
52 return {
53 soc2ControlsUrl: row.soc2_controls_url,
54 hipaaBaaSignedAt: row.hipaa_baa_signed_at?.toISOString() ?? null,
55 hipaaBaaSignedBy: row.hipaa_baa_signed_by,
56 gdprDpaSignedAt: row.gdpr_dpa_signed_at?.toISOString() ?? null,
57 gdprDpaSignedBy: row.gdpr_dpa_signed_by,
58 encryptionAtRestEnabled: row.encryption_at_rest_enabled,
59 };
60}
61
62export async function setComplianceSettings(
63 projectId: string,
64 patch: Partial<ComplianceSettings>,
65): Promise<ComplianceSettings> {
66 const existing = await getComplianceSettings(projectId);
67 const next: ComplianceSettings = {
68 soc2ControlsUrl: patch.soc2ControlsUrl ?? existing.soc2ControlsUrl,
69 hipaaBaaSignedAt: patch.hipaaBaaSignedAt ?? existing.hipaaBaaSignedAt,
70 hipaaBaaSignedBy: patch.hipaaBaaSignedBy ?? existing.hipaaBaaSignedBy,
71 gdprDpaSignedAt: patch.gdprDpaSignedAt ?? existing.gdprDpaSignedAt,
72 gdprDpaSignedBy: patch.gdprDpaSignedBy ?? existing.gdprDpaSignedBy,
73 encryptionAtRestEnabled:
74 patch.encryptionAtRestEnabled ?? existing.encryptionAtRestEnabled,
75 };
76
77 await runInProjectDatabase(projectId, async (tx) => {
78 const rows = await tx.unsafe(
79 `SELECT id FROM "_briven_auth_compliance" LIMIT 1`,
80 ) as Array<{ id: string }>;
81
82 if (rows[0]) {
83 await tx.unsafe(
84 `UPDATE "_briven_auth_compliance"
85 SET soc2_controls_url = $1,
86 hipaa_baa_signed_at = $2,
87 hipaa_baa_signed_by = $3,
88 gdpr_dpa_signed_at = $4,
89 gdpr_dpa_signed_by = $5,
90 encryption_at_rest_enabled = $6,
91 updated_at = now()
92 WHERE id = $7`,
93 [
94 next.soc2ControlsUrl,
95 next.hipaaBaaSignedAt ? new Date(next.hipaaBaaSignedAt) : null,
96 next.hipaaBaaSignedBy,
97 next.gdprDpaSignedAt ? new Date(next.gdprDpaSignedAt) : null,
98 next.gdprDpaSignedBy,
99 next.encryptionAtRestEnabled,
100 rows[0].id,
101 ] as never[],
102 );
103 } else {
104 await tx.unsafe(
105 `INSERT INTO "_briven_auth_compliance"
106 (id, soc2_controls_url, hipaa_baa_signed_at, hipaa_baa_signed_by,
107 gdpr_dpa_signed_at, gdpr_dpa_signed_by, encryption_at_rest_enabled, created_at, updated_at)
108 VALUES ($1, $2, $3, $4, $5, $6, $7, now(), now())`,
109 [
110 `comp_${Date.now()}`,
111 next.soc2ControlsUrl,
112 next.hipaaBaaSignedAt ? new Date(next.hipaaBaaSignedAt) : null,
113 next.hipaaBaaSignedBy,
114 next.gdprDpaSignedAt ? new Date(next.gdprDpaSignedAt) : null,
115 next.gdprDpaSignedBy,
116 next.encryptionAtRestEnabled,
117 ] as never[],
118 );
119 }
120 });
121
122 return next;
123}