project-map.ts54 lines · main
1/**
2 * Briven projectId → briven-engine app/tenant map (Path A).
3 *
4 * Phase 1: pure mapping rules (no Multitenancy recipe yet).
5 * Later: Multitenancy creates tenants in briven-engine; this stays the source of truth
6 * for which Briven project owns which engine tenant.
7 *
8 * Isolation rule: one Briven project = one tenantId under app "public"
9 * (default app until Phase 6 enterprise apps).
10 */
11
12const ST_APP_ID = 'public';
13
14/**
15 * Normalize project id into a briven-engine-safe tenant id.
16 * Core allows only letters, numbers, hyphens (no underscores).
17 */
18export function projectIdToTenantId(projectId: string): string {
19 const cleaned = projectId
20 .trim()
21 .toLowerCase()
22 .replace(/_/g, '-')
23 .replace(/[^a-z0-9-]/g, '-')
24 .replace(/-+/g, '-')
25 .replace(/^-|-$/g, '');
26 if (!cleaned) {
27 throw new Error('projectId is empty');
28 }
29 return `proj-${cleaned}`.slice(0, 64);
30}
31
32export function tenantIdToProjectId(tenantId: string): string | null {
33 if (!tenantId.startsWith('proj-')) return null;
34 // Reverse hyphenation is lossy for original underscores; store projectId separately in product.
35 return tenantId.slice('proj-'.length);
36}
37
38export type AuthCoreProjectMap = {
39 projectId: string;
40 appId: typeof ST_APP_ID;
41 tenantId: string;
42 phase: 1;
43};
44
45export function mapProjectToAuthCore(projectId: string): AuthCoreProjectMap {
46 return {
47 projectId,
48 appId: ST_APP_ID,
49 tenantId: projectIdToTenantId(projectId),
50 phase: 1,
51 };
52}
53
54export const AUTH_CORE_DEFAULT_APP_ID = ST_APP_ID;