@factoredui/core 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/{init.cjs → factoredui.cjs} +118 -5
- package/dist/index.cjs +110 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +39 -10
- package/dist/index.d.ts +39 -10
- package/dist/index.js +110 -17
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/supabase/migrations/20250101000026_rls_ui_specs.sql +9 -0
- package/supabase/migrations/20250101000027_devices.sql +44 -0
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/capture/session.ts","../src/capture/writer.ts","../src/capture/path.ts","../src/capture/behavioral.ts","../src/capture/web-adapter.ts","../src/capture/index.ts","../src/factors/query.ts","../src/factors/snapshots.ts","../src/factors/data-sources.ts","../src/sdui/spec-types.ts","../src/factors/dashboard-spec.ts","../src/factors/clustering.ts","../src/experiment/targeting.ts","../src/experiment/flags.ts","../src/experiment/lifecycle.ts","../src/experiment/results.ts","../src/experiment/governance.ts","../src/experiment/governance-check.ts","../src/experiment/dashboard.ts","../src/experiment/governance-log.ts","../src/sdui/spec-validator.ts","../src/sdui/data-source.ts","../src/sdui/binding.ts","../src/sdui/action-dispatch.ts","../src/sdui/spec-loader.ts","../src/sdui/default-storage.ts","../src/sdui/ed25519.ts"],"sourcesContent":["import type { SupabaseClient } from \"@supabase/supabase-js\";\nimport type { Session, Platform } from \"../types.js\";\nimport type { CaptureAdapter } from \"./adapter.js\";\n\nconst DEFAULT_TIMEOUT_MS = 30 * 60 * 1000; // 30 minutes\n\nexport interface SessionManager {\n ensureSession: (userId: string) => Promise<string>;\n endSession: () => Promise<void>;\n getSessionId: () => string | null;\n}\n\nexport function createSessionManager(\n supabase: SupabaseClient,\n adapter: CaptureAdapter,\n platform: Platform,\n timeoutMs: number = DEFAULT_TIMEOUT_MS,\n): SessionManager {\n let currentSessionId: string | null = adapter.loadSessionId();\n let lastActivityAt = Date.now();\n\n function isSessionExpired(): boolean {\n return Date.now() - lastActivityAt > timeoutMs;\n }\n\n async function createSession(userId: string): Promise<string> {\n const metadata = {\n ...adapter.collectSessionMetadata(),\n platform,\n };\n\n const { data, error } = await supabase\n .from(\"sessions\")\n .insert({ user_id: userId, metadata })\n .select(\"id\")\n .single();\n\n if (error) throw new Error(`Failed to create session: ${error.message}`);\n return (data as Session).id;\n }\n\n async function ensureSession(userId: string): Promise<string> {\n lastActivityAt = Date.now();\n\n if (currentSessionId && !isSessionExpired()) {\n return currentSessionId;\n }\n\n currentSessionId = await createSession(userId);\n adapter.storeSessionId(currentSessionId);\n return currentSessionId;\n }\n\n async function endSession(): Promise<void> {\n if (!currentSessionId) return;\n\n await supabase\n .from(\"sessions\")\n .update({ ended_at: new Date().toISOString() })\n .eq(\"id\", currentSessionId);\n\n currentSessionId = null;\n adapter.clearSessionId();\n }\n\n function getSessionId(): string | null {\n return currentSessionId;\n }\n\n return { ensureSession, endSession, getSessionId };\n}\n","import type { SupabaseClient } from \"@supabase/supabase-js\";\nimport type { CaptureEvent } from \"../types.js\";\n\nconst DEFAULT_FLUSH_INTERVAL_MS = 2000;\nconst DEFAULT_FLUSH_BATCH_SIZE = 50;\n\nexport interface EventWriter {\n enqueue: (sessionId: string, userId: string, event: CaptureEvent) => void;\n flush: () => Promise<void>;\n startAutoFlush: () => void;\n stopAutoFlush: () => void;\n}\n\ninterface QueuedEvent {\n user_id: string;\n session_id: string;\n event_type: string;\n component_path: string;\n payload: Record<string, unknown>;\n}\n\nexport function createEventWriter(\n supabase: SupabaseClient,\n flushIntervalMs: number = DEFAULT_FLUSH_INTERVAL_MS,\n flushBatchSize: number = DEFAULT_FLUSH_BATCH_SIZE,\n): EventWriter {\n let queue: QueuedEvent[] = [];\n let flushTimer: ReturnType<typeof setInterval> | null = null;\n let isFlushing = false;\n\n function enqueue(\n sessionId: string,\n userId: string,\n event: CaptureEvent,\n ): void {\n queue.push({\n user_id: userId,\n session_id: sessionId,\n event_type: event.event_type,\n component_path: event.component_path,\n payload: event.payload,\n });\n\n if (queue.length >= flushBatchSize) {\n flush();\n }\n }\n\n async function flush(): Promise<void> {\n if (isFlushing || queue.length === 0) return;\n\n isFlushing = true;\n const batch = queue.splice(0, flushBatchSize);\n\n try {\n const { error } = await supabase.from(\"events\").insert(batch);\n if (error) {\n // Re-enqueue on failure — front of queue to preserve order\n queue.unshift(...batch);\n console.error(\"factoredui: flush failed:\", error.message);\n }\n } catch (err) {\n queue.unshift(...batch);\n console.error(\"factoredui: flush error:\", err);\n } finally {\n isFlushing = false;\n }\n }\n\n function startAutoFlush(): void {\n if (flushTimer) return;\n flushTimer = setInterval(flush, flushIntervalMs);\n }\n\n function stopAutoFlush(): void {\n if (flushTimer) {\n clearInterval(flushTimer);\n flushTimer = null;\n }\n }\n\n return { enqueue, flush, startAutoFlush, stopAutoFlush };\n}\n","/**\n * Resolves a DOM element to its component path.\n * Traverses upward looking for data-factored attributes:\n * data-factored-flow, data-factored-page, data-factored-component, data-factored-element\n *\n * Returns a path like \"onboarding/review/photo-grid/upload-button\"\n */\n\nconst PATH_TIERS = [\n \"data-factored-flow\",\n \"data-factored-page\",\n \"data-factored-component\",\n \"data-factored-element\",\n] as const;\n\nexport function resolveComponentPath(target: Element): string {\n const segments = collectPathSegments(target);\n return segments.join(\"/\") || \"unknown\";\n}\n\nfunction collectPathSegments(target: Element): string[] {\n const found: Map<string, string> = new Map();\n let current: Element | null = target;\n\n while (current) {\n for (const attr of PATH_TIERS) {\n if (!found.has(attr) && current.hasAttribute(attr)) {\n found.set(attr, current.getAttribute(attr)!);\n }\n }\n current = current.parentElement;\n }\n\n return PATH_TIERS.map((attr) => found.get(attr)).filter(\n (segment): segment is string => segment != null,\n );\n}\n","/**\n * Behavioral detection: pure logic for rage clicks and scroll reversals.\n * Platform-specific DOM bindings are in web-adapter.ts.\n * Dead click detection (MutationObserver) is web-only, lives in web-adapter.ts.\n */\n\nconst RAGE_CLICK_THRESHOLD = 3;\nconst RAGE_CLICK_WINDOW_MS = 500;\nconst SCROLL_REVERSAL_WINDOW_MS = 300;\n\n// --- Rage click detection (pure logic) ---\n\nexport interface RageClickState {\n targetPath: string | null;\n timestamps: number[];\n count: number;\n}\n\nexport function createRageClickState(): RageClickState {\n return { targetPath: null, timestamps: [], count: 0 };\n}\n\nexport function recordClickAndDetectRage(\n state: RageClickState,\n componentPath: string,\n now: number,\n): boolean {\n if (state.targetPath !== componentPath) {\n state.targetPath = componentPath;\n state.timestamps = [now];\n state.count = 1;\n return false;\n }\n\n state.timestamps.push(now);\n state.timestamps = state.timestamps.filter(\n (ts) => now - ts < RAGE_CLICK_WINDOW_MS,\n );\n state.count = state.timestamps.length;\n\n return state.count >= RAGE_CLICK_THRESHOLD;\n}\n\n// --- Scroll reversal detection (pure logic) ---\n\nexport interface ScrollState {\n lastScrollY: number;\n lastDirection: \"up\" | \"down\" | null;\n lastDirectionChangeAt: number;\n}\n\nexport function createScrollState(): ScrollState {\n return { lastScrollY: 0, lastDirection: null, lastDirectionChangeAt: 0 };\n}\n\nexport function detectScrollReversal(\n state: ScrollState,\n scrollY: number,\n now: number,\n): \"up\" | \"down\" | null {\n const direction: \"up\" | \"down\" = scrollY > state.lastScrollY ? \"down\" : \"up\";\n const previousDirection = state.lastDirection;\n\n state.lastScrollY = scrollY;\n\n if (previousDirection === null) {\n state.lastDirection = direction;\n return null;\n }\n\n if (direction !== previousDirection) {\n const timeSinceLastChange = now - state.lastDirectionChangeAt;\n state.lastDirection = direction;\n state.lastDirectionChangeAt = now;\n\n if (timeSinceLastChange < SCROLL_REVERSAL_WINDOW_MS) {\n return direction;\n }\n }\n\n return null;\n}\n","import type { CaptureEvent } from \"../types.js\";\nimport type { CaptureAdapter } from \"./adapter.js\";\nimport { resolveComponentPath } from \"./path.js\";\nimport {\n recordClickAndDetectRage,\n createRageClickState,\n detectScrollReversal,\n createScrollState,\n type RageClickState,\n type ScrollState,\n} from \"./behavioral.js\";\n\nconst THROTTLE_INTERVAL_MS = 100;\nconst DEAD_CLICK_WAIT_MS = 1000;\nconst SESSION_STORAGE_KEY = \"factoredui:session_id\";\n\n/**\n * Web (DOM) implementation of CaptureAdapter.\n * Attaches document/window listeners for clicks, scroll, input, errors, etc.\n * Uses sessionStorage for session persistence and navigator/window for metadata.\n */\nexport function createWebAdapter(): CaptureAdapter {\n const handlers = new Map<string, EventListener>();\n const rageClickState = createRageClickState();\n const scrollState = createScrollState();\n let emitEvent: ((event: CaptureEvent) => void) | null = null;\n\n function emit(event: CaptureEvent): void {\n emitEvent?.(event);\n }\n\n function addHandler(\n key: string,\n target: EventTarget,\n mapFn: (event: Event) => CaptureEvent | null,\n options?: AddEventListenerOptions,\n ): void {\n const eventName = key.split(\":\")[0];\n const handler = (event: Event) => {\n const mapped = mapFn(event);\n if (mapped) emit(mapped);\n };\n handlers.set(key, handler);\n target.addEventListener(eventName, handler, options);\n }\n\n function addThrottledHandler(\n key: string,\n target: EventTarget,\n mapFn: (event: Event) => CaptureEvent | null,\n options?: AddEventListenerOptions,\n ): void {\n const eventName = key.split(\":\")[0];\n let lastFiredAt = 0;\n const handler = (event: Event) => {\n const now = Date.now();\n if (now - lastFiredAt < THROTTLE_INTERVAL_MS) return;\n lastFiredAt = now;\n const mapped = mapFn(event);\n if (mapped) emit(mapped);\n };\n handlers.set(key, handler);\n target.addEventListener(eventName, handler, options);\n }\n\n function dropHandler(\n key: string,\n target: EventTarget,\n options?: EventListenerOptions,\n ): void {\n const eventName = key.split(\":\")[0];\n const handler = handlers.get(key);\n if (handler) {\n target.removeEventListener(eventName, handler, options);\n handlers.delete(key);\n }\n }\n\n function startListening(onEvent: (event: CaptureEvent) => void): void {\n emitEvent = onEvent;\n\n addHandler(\"click\", document, mapClickEvent, { capture: true });\n addHandler(\"click:rage\", document, (e) => mapRageClick(e, rageClickState), { capture: true });\n addHandler(\"click:dead\", document, (e) => { detectDeadClick(e, emit); return null; }, { capture: true });\n addThrottledHandler(\"scroll\", window, mapScrollEvent);\n addHandler(\"scroll:reversal\", window, () => mapScrollReversal(scrollState));\n addThrottledHandler(\"input\", document, (e) => mapTargetEvent(e, \"input\"), { capture: true });\n addHandler(\"focus\", document, (e) => mapTargetEvent(e, \"focus\"), { capture: true });\n addHandler(\"blur\", document, (e) => mapTargetEvent(e, \"blur\"), { capture: true });\n addHandler(\"submit\", document, mapSubmitEvent, { capture: true });\n addThrottledHandler(\"resize\", window, mapResizeEvent);\n addHandler(\"error\", window, mapErrorEvent);\n addHandler(\"visibilitychange\", document, mapVisibilityEvent);\n }\n\n function stopListening(): void {\n dropHandler(\"click\", document, { capture: true });\n dropHandler(\"click:rage\", document, { capture: true });\n dropHandler(\"click:dead\", document, { capture: true });\n dropHandler(\"scroll\", window);\n dropHandler(\"scroll:reversal\", window);\n dropHandler(\"input\", document, { capture: true });\n dropHandler(\"focus\", document, { capture: true });\n dropHandler(\"blur\", document, { capture: true });\n dropHandler(\"submit\", document, { capture: true });\n dropHandler(\"resize\", window);\n dropHandler(\"error\", window);\n dropHandler(\"visibilitychange\", document);\n emitEvent = null;\n }\n\n function registerUnloadHandler(onUnload: () => void): void {\n if (typeof window === \"undefined\") return;\n window.addEventListener(\"visibilitychange\", () => {\n if (document.visibilityState === \"hidden\") onUnload();\n });\n }\n\n return {\n startListening,\n stopListening,\n collectSessionMetadata,\n storeSessionId,\n loadSessionId,\n clearSessionId,\n registerUnloadHandler,\n };\n}\n\n// --- Session storage (leaf functions, no closure state needed) ---\n\nfunction collectSessionMetadata(): Record<string, unknown> {\n if (typeof window === \"undefined\") return {};\n return {\n user_agent: navigator.userAgent,\n screen_width: screen.width,\n screen_height: screen.height,\n viewport_width: window.innerWidth,\n viewport_height: window.innerHeight,\n language: navigator.language,\n referrer: document.referrer || null,\n url: window.location.href,\n };\n}\n\nfunction storeSessionId(id: string): void {\n try {\n sessionStorage.setItem(SESSION_STORAGE_KEY, id);\n } catch {\n // SSR or restricted storage -- session lives in memory only\n }\n}\n\nfunction loadSessionId(): string | null {\n try {\n return sessionStorage.getItem(SESSION_STORAGE_KEY);\n } catch {\n return null;\n }\n}\n\nfunction clearSessionId(): void {\n try {\n sessionStorage.removeItem(SESSION_STORAGE_KEY);\n } catch {\n // Ignore storage errors\n }\n}\n\n// --- Event mappers (pure leaf functions) ---\n\nfunction mapClickEvent(event: Event): CaptureEvent | null {\n const target = event.target as Element | null;\n if (!target) return null;\n return {\n event_type: \"click\",\n component_path: resolveComponentPath(target),\n payload: {\n x: (event as MouseEvent).clientX,\n y: (event as MouseEvent).clientY,\n target_tag: target.tagName.toLowerCase(),\n },\n };\n}\n\nfunction mapScrollEvent(): CaptureEvent {\n return {\n event_type: \"scroll\",\n component_path: resolveComponentPath(document.documentElement),\n payload: { scroll_x: window.scrollX, scroll_y: window.scrollY },\n };\n}\n\nfunction mapTargetEvent(event: Event, eventType: \"input\" | \"focus\" | \"blur\"): CaptureEvent | null {\n const target = event.target as Element | null;\n if (!target) return null;\n return {\n event_type: eventType,\n component_path: resolveComponentPath(target),\n payload: { target_tag: target.tagName.toLowerCase() },\n };\n}\n\nfunction mapSubmitEvent(event: Event): CaptureEvent | null {\n const target = event.target as Element | null;\n if (!target) return null;\n return {\n event_type: \"submit\",\n component_path: resolveComponentPath(target),\n payload: { form_id: (target as HTMLFormElement).id || null },\n };\n}\n\nfunction mapResizeEvent(): CaptureEvent {\n return {\n event_type: \"resize\",\n component_path: resolveComponentPath(document.documentElement),\n payload: { width: window.innerWidth, height: window.innerHeight },\n };\n}\n\nfunction mapErrorEvent(event: Event): CaptureEvent {\n const errorEvent = event as ErrorEvent;\n return {\n event_type: \"error\",\n component_path: resolveComponentPath(document.documentElement),\n payload: {\n message: errorEvent.message,\n filename: errorEvent.filename,\n lineno: errorEvent.lineno,\n colno: errorEvent.colno,\n },\n };\n}\n\nfunction mapVisibilityEvent(): CaptureEvent {\n return {\n event_type: \"visibility\",\n component_path: resolveComponentPath(document.documentElement),\n payload: { visibility_state: document.visibilityState },\n };\n}\n\n// --- Behavioral mappers (delegate to pure logic in behavioral.ts) ---\n\nfunction mapRageClick(event: Event, state: RageClickState): CaptureEvent | null {\n const target = event.target as Element | null;\n if (!target) return null;\n\n const componentPath = resolveComponentPath(target);\n const isRage = recordClickAndDetectRage(state, componentPath, Date.now());\n\n if (isRage) {\n return {\n event_type: \"rage_click\",\n component_path: componentPath,\n payload: {\n click_count: state.count,\n x: (event as MouseEvent).clientX,\n y: (event as MouseEvent).clientY,\n },\n };\n }\n return null;\n}\n\nfunction detectDeadClick(\n event: Event,\n emit: (e: CaptureEvent) => void,\n): void {\n const target = event.target as Element | null;\n if (!target) return;\n\n const componentPath = resolveComponentPath(target);\n let hasMutation = false;\n const observer = new MutationObserver(() => {\n hasMutation = true;\n observer.disconnect();\n });\n\n observer.observe(document.body, {\n childList: true,\n subtree: true,\n attributes: true,\n characterData: true,\n });\n\n setTimeout(() => {\n observer.disconnect();\n if (!hasMutation) {\n emit({\n event_type: \"dead_click\",\n component_path: componentPath,\n payload: { target_tag: target.tagName.toLowerCase() },\n });\n }\n }, DEAD_CLICK_WAIT_MS);\n}\n\nfunction mapScrollReversal(state: ScrollState): CaptureEvent | null {\n const scrollY = window.scrollY;\n const reversal = detectScrollReversal(state, scrollY, Date.now());\n\n if (reversal) {\n return {\n event_type: \"scroll_reversal\",\n component_path: resolveComponentPath(document.documentElement),\n payload: { scroll_y: scrollY, direction: reversal },\n };\n }\n return null;\n}\n","import type { SupabaseClient } from \"@supabase/supabase-js\";\nimport type { CaptureHandle, Config, CaptureEvent } from \"../types.js\";\nimport { createSessionManager } from \"./session.js\";\nimport { createEventWriter } from \"./writer.js\";\nimport { createWebAdapter } from \"./web-adapter.js\";\n\n/**\n * Orchestrator: initializes capture pipeline.\n * Coordinates adapter, session manager, and batched writer.\n * Defaults to web adapter when no adapter provided.\n */\nexport function initCapture(config: Config): CaptureHandle {\n const adapter = config.adapter ?? createWebAdapter();\n const platform = config.platform ?? \"web\";\n\n const sessionManager = createSessionManager(\n config.supabase,\n adapter,\n platform,\n config.sessionTimeoutMs,\n );\n const writer = createEventWriter(\n config.supabase,\n config.flushIntervalMs,\n config.flushBatchSize,\n );\n\n const enqueueEvent = createEventEnqueuer(\n config.supabase,\n sessionManager,\n writer,\n );\n\n adapter.startListening(enqueueEvent);\n writer.startAutoFlush();\n\n adapter.registerUnloadHandler(() => {\n writer.flush();\n sessionManager.endSession();\n });\n\n return {\n stopCapture: () => {\n adapter.stopListening();\n writer.stopAutoFlush();\n },\n flushEvents: () => writer.flush(),\n getSessionId: () => sessionManager.getSessionId(),\n trackNavigation: (componentPath, action) =>\n enqueueEvent({\n event_type: \"navigation\",\n component_path: componentPath,\n payload: { action },\n }),\n trackImpression: (componentPath) =>\n enqueueEvent({\n event_type: \"impression\",\n component_path: componentPath,\n payload: {},\n }),\n };\n}\n\nfunction createEventEnqueuer(\n supabase: SupabaseClient,\n sessionManager: ReturnType<typeof createSessionManager>,\n writer: ReturnType<typeof createEventWriter>,\n): (event: CaptureEvent) => void {\n let cachedUserId: string | null = null;\n\n return (event: CaptureEvent) => {\n resolveUserId(supabase, cachedUserId).then((userId) => {\n cachedUserId = userId;\n return sessionManager.ensureSession(userId).then((sessionId) => {\n writer.enqueue(sessionId, userId, event);\n });\n }).catch((err) => {\n console.error(\"factoredui: failed to enqueue event:\", err);\n });\n };\n}\n\nasync function resolveUserId(\n supabase: SupabaseClient,\n cachedUserId: string | null,\n): Promise<string> {\n if (cachedUserId) return cachedUserId;\n const { data: { user } } = await supabase.auth.getUser();\n if (!user) throw new Error(\"factoredui: user not authenticated\");\n return user.id;\n}\n","import type { SupabaseClient } from \"@supabase/supabase-js\";\nimport type { Factor, FactorTier } from \"../types.js\";\n\nexport interface ComponentFactorAggregate {\n component_path: string;\n factor_name: string;\n factor_tier: FactorTier;\n user_count: number;\n avg_value: number;\n median_value: number;\n p95_value: number;\n min_value: number;\n max_value: number;\n stddev_value: number | null;\n}\n\nexport async function queryFactors(\n client: SupabaseClient,\n userId: string,\n componentPath: string,\n): Promise<Factor[]> {\n const { data, error } = await client\n .from(\"v_factors_current\")\n .select(\"user_id, component_path, factor_name, factor_tier, value, computed_at\")\n .eq(\"user_id\", userId)\n .eq(\"component_path\", componentPath);\n\n if (error) throw new Error(`queryFactors failed: ${error.message}`);\n return data as Factor[];\n}\n\nexport async function queryComponentFactors(\n client: SupabaseClient,\n componentPath: string,\n): Promise<ComponentFactorAggregate[]> {\n const { data, error } = await client\n .from(\"v_component_factors_agg\")\n .select(\n \"component_path, factor_name, factor_tier, user_count, avg_value, median_value, p95_value, min_value, max_value, stddev_value\",\n )\n .eq(\"component_path\", componentPath);\n\n if (error) throw new Error(`queryComponentFactors failed: ${error.message}`);\n return data as ComponentFactorAggregate[];\n}\n","import type { SupabaseClient } from \"@supabase/supabase-js\";\n\nexport interface FactorSnapshot {\n factor_name: string;\n factor_tier: string;\n value: number;\n snapshot_at: string;\n}\n\nexport interface FactorDelta {\n factor_name: string;\n before: number;\n after: number;\n delta: number;\n}\n\nexport async function queryFactorHistory(\n client: SupabaseClient,\n userId: string,\n componentPath: string,\n factorName: string,\n since: Date,\n): Promise<FactorSnapshot[]> {\n const { data, error } = await client\n .from(\"factor_snapshots\")\n .select(\"factor_name, factor_tier, value, snapshot_at\")\n .eq(\"user_id\", userId)\n .eq(\"component_path\", componentPath)\n .eq(\"factor_name\", factorName)\n .gte(\"snapshot_at\", since.toISOString())\n .order(\"snapshot_at\", { ascending: true });\n\n if (error) throw new Error(`queryFactorHistory failed: ${error.message}`);\n return data as FactorSnapshot[];\n}\n\nexport async function queryFactorDelta(\n client: SupabaseClient,\n userId: string,\n componentPath: string,\n factorName: string,\n before: Date,\n after: Date,\n): Promise<FactorDelta | null> {\n const beforeSnapshot = await findClosestSnapshot(\n client, userId, componentPath, factorName, before,\n );\n const afterSnapshot = await findClosestSnapshot(\n client, userId, componentPath, factorName, after,\n );\n\n if (!beforeSnapshot || !afterSnapshot) return null;\n\n return {\n factor_name: factorName,\n before: beforeSnapshot.value,\n after: afterSnapshot.value,\n delta: afterSnapshot.value - beforeSnapshot.value,\n };\n}\n\nasync function findClosestSnapshot(\n client: SupabaseClient,\n userId: string,\n componentPath: string,\n factorName: string,\n targetDate: Date,\n): Promise<FactorSnapshot | null> {\n const { data, error } = await client\n .from(\"factor_snapshots\")\n .select(\"factor_name, factor_tier, value, snapshot_at\")\n .eq(\"user_id\", userId)\n .eq(\"component_path\", componentPath)\n .eq(\"factor_name\", factorName)\n .lte(\"snapshot_at\", targetDate.toISOString())\n .order(\"snapshot_at\", { ascending: false })\n .limit(1)\n .maybeSingle();\n\n if (error) throw new Error(`findClosestSnapshot failed: ${error.message}`);\n return data as FactorSnapshot | null;\n}\n","import type { SupabaseClient } from \"@supabase/supabase-js\";\nimport type { DataSourceConfig } from \"../sdui/spec-types.js\";\nimport { queryFactors, queryComponentFactors } from \"./query.js\";\nimport { queryFactorHistory } from \"./snapshots.js\";\n\n/**\n * SDUI data source configs for factor views.\n * Each returns a DataSourceConfig that specs reference by name in their registry.\n */\n\nexport function factorSource(\n supabase: SupabaseClient,\n userId: string,\n componentPath: string,\n): DataSourceConfig {\n return {\n fetch: () => queryFactors(supabase, userId, componentPath),\n cache: \"local\",\n };\n}\n\nexport function componentFactorSource(\n supabase: SupabaseClient,\n componentPath: string,\n): DataSourceConfig {\n return {\n fetch: () => queryComponentFactors(supabase, componentPath),\n cache: \"local\",\n };\n}\n\nexport function factorHistorySource(\n supabase: SupabaseClient,\n userId: string,\n componentPath: string,\n factorName: string,\n since: Date,\n): DataSourceConfig {\n return {\n fetch: () => queryFactorHistory(supabase, userId, componentPath, factorName, since),\n cache: \"local\",\n };\n}\n","/**\n * SDUI Spec Types\n *\n * Declarative UI spec format. Pure data, no expressions.\n * Inspired by A2UI's flat structure, constrained for LLM generation.\n *\n * Rules:\n * - No expression language. Values are literals or single-level path refs \"{path.to.value}\".\n * - No state management in the spec. Host provides context.\n * - No data fetching. Spec declares source refs, host resolves them.\n * - No complex conditionals. Single boolean visibility via \"{flag}\" refs.\n * - Actions are named references, never inline code.\n */\n\n// --- Spec envelope ---\n\nexport interface Spec {\n spec_version: number;\n renderer_min: number;\n root: SpecNode;\n}\n\n// --- Node types ---\n\nexport type SpecNodeType =\n | \"column\"\n | \"row\"\n | \"stack\"\n | \"scrollview\"\n | \"grid\"\n | \"text\"\n | \"image\"\n | \"icon\"\n | \"divider\"\n | \"spacer\"\n | \"textinput\"\n | \"button\"\n | \"toggle\"\n | \"select\"\n | \"slider\"\n | \"card\"\n | \"list\"\n | \"tabs\"\n | \"modal\"\n | \"chip\";\n\nexport interface SpecNode {\n id: string;\n type: SpecNodeType;\n props?: Record<string, SpecValue>;\n children?: SpecNode[];\n visible?: string;\n action?: ActionRef;\n}\n\n// --- Values ---\n\n/**\n * A spec value is either a literal, a binding reference, or a nested SpecNode.\n * Binding refs are strings starting with \"{\" and ending with \"}\".\n * Single-level path only: \"{sources.pipeline.name}\" — no expressions, no chaining.\n *\n * SpecNode is included to support props like ListProps.itemTemplate\n * where a prop value is itself a component subtree.\n */\nexport type SpecValue = string | number | boolean | null | SpecNode | SpecValueArray | SpecValueObject;\ninterface SpecValueArray extends Array<SpecValue> {}\ninterface SpecValueObject { [key: string]: SpecValue; }\n\n// --- Actions ---\n\nexport interface ActionRef {\n action: string;\n params?: Record<string, SpecValue>;\n}\n\n// --- List-specific props ---\n\nexport interface ListProps {\n data: string;\n itemTemplate: SpecNode;\n emptyText?: string;\n maxItems?: number;\n}\n\n// --- Layout props ---\n\nexport interface LayoutProps {\n direction?: \"column\" | \"row\";\n gap?: number;\n padding?: number | [number, number, number, number];\n align?: \"start\" | \"center\" | \"end\" | \"stretch\";\n justify?: \"start\" | \"center\" | \"end\" | \"between\" | \"around\";\n flex?: number;\n}\n\n// --- Text props ---\n\nexport interface TextProps {\n value: string;\n variant?: \"heading\" | \"subheading\" | \"body\" | \"caption\" | \"label\";\n align?: \"left\" | \"center\" | \"right\";\n color?: string;\n bold?: boolean;\n numberOfLines?: number;\n}\n\n// --- Button props ---\n\nexport interface ButtonProps {\n label: string;\n variant?: \"primary\" | \"secondary\" | \"outline\" | \"ghost\" | \"destructive\";\n size?: \"sm\" | \"md\" | \"lg\";\n icon?: string;\n disabled?: string;\n}\n\n// --- TextInput props ---\n\nexport interface TextInputProps {\n placeholder?: string;\n multiline?: boolean;\n maxLength?: number;\n submitAction?: ActionRef;\n}\n\n// --- Image props ---\n\nexport interface ImageProps {\n source: string;\n alt: string;\n fit?: \"cover\" | \"contain\" | \"fill\";\n aspectRatio?: number;\n}\n\n// --- Icon props ---\n\nexport interface IconProps {\n name: string;\n size?: number;\n color?: string;\n}\n\n// --- Card props ---\n\nexport interface CardProps {\n variant?: \"elevated\" | \"outlined\" | \"filled\";\n}\n\n// --- Tabs props ---\n\nexport interface TabsProps {\n items: string[];\n selectedIndex?: number;\n}\n\n// --- Grid props ---\n\nexport interface GridProps {\n columns: number;\n gap?: number;\n}\n\n// --- Select props ---\n\nexport interface SelectProps {\n options: Array<{ label: string; value: string }>;\n placeholder?: string;\n selectedValue?: string;\n}\n\n// --- Chip props ---\n\nexport interface ChipProps {\n label: string;\n selected?: boolean;\n variant?: \"filled\" | \"outlined\";\n}\n\n// --- Modal props ---\n\nexport interface ModalProps {\n title?: string;\n dismissible?: boolean;\n}\n\n// --- ScrollView props ---\n\nexport interface ScrollViewProps {\n horizontal?: boolean;\n}\n\n// --- Toggle props ---\n\nexport interface ToggleProps {\n label?: string;\n value?: string;\n}\n\n// --- Slider props ---\n\nexport interface SliderProps {\n min?: number;\n max?: number;\n step?: number;\n value?: string;\n}\n\n// --- Divider props ---\n\nexport interface DividerProps {\n orientation?: \"horizontal\" | \"vertical\";\n}\n\n// --- Spacer props ---\n\nexport interface SpacerProps {\n size?: number;\n flex?: number;\n}\n\n// --- Data source contract (implemented by the host app) ---\n\nexport interface DataSourceConfig {\n fetch: () => Promise<unknown>;\n cache?: \"none\" | \"local\";\n realtime?: boolean;\n maxItems?: number;\n}\n\nexport type DataSourceRegistry = Record<string, DataSourceConfig>;\n\n// --- Action handler contract (implemented by the host app) ---\n\nexport type ActionHandler = (params: Record<string, unknown>) => void | Promise<void>;\nexport type ActionRegistry = Record<string, ActionHandler>;\n\n// --- Component contract (implemented by the host app) ---\n\nexport type ComponentRenderer = (props: Record<string, unknown>, children?: React.ReactNode) => React.ReactNode;\nexport type ComponentRegistry = Record<SpecNodeType, ComponentRenderer>;\n\n// --- Signing ---\n\nexport interface SignedSpec {\n spec: Spec;\n signature: string;\n signed_at: string;\n spec_hash: string;\n}\n\n// --- Renderer version ---\n\nexport const RENDERER_VERSION = 1;\n","import type { Spec, SpecNode, ListProps } from \"../sdui/spec-types.js\";\nimport { RENDERER_VERSION } from \"../sdui/spec-types.js\";\n\n/**\n * Generates an SDUI spec for a factor dashboard.\n * The spec expects a data source named \"factors\" bound to componentFactorSource output.\n * Each factor renders as a card with tier badge, name, and aggregate stats.\n */\n\nexport function buildFactorDashboardSpec(componentPath: string): Spec {\n return {\n spec_version: 1,\n renderer_min: RENDERER_VERSION,\n root: buildRoot(componentPath),\n };\n}\n\nfunction buildRoot(componentPath: string): SpecNode {\n return {\n id: \"root\",\n type: \"column\",\n props: { gap: 16, padding: 16 },\n children: [\n buildHeader(componentPath),\n buildFactorList(),\n ],\n };\n}\n\nfunction buildHeader(componentPath: string): SpecNode {\n return {\n id: \"header\",\n type: \"column\",\n props: { gap: 4 },\n children: [\n {\n id: \"title\",\n type: \"text\",\n props: { value: \"Factor Dashboard\", variant: \"heading\" },\n },\n {\n id: \"subtitle\",\n type: \"text\",\n props: { value: componentPath, variant: \"caption\", color: \"#666\" },\n },\n ],\n };\n}\n\nfunction buildFactorList(): SpecNode {\n const listProps: ListProps = {\n data: \"{sources.factors}\",\n emptyText: \"No factors computed yet\",\n itemTemplate: buildFactorCard(),\n };\n\n return {\n id: \"factor-list\",\n type: \"list\",\n props: { ...listProps },\n };\n}\n\nfunction buildFactorCard(): SpecNode {\n return {\n id: \"factor-card\",\n type: \"card\",\n props: { variant: \"outlined\" },\n children: [\n {\n id: \"card-content\",\n type: \"column\",\n props: { gap: 8, padding: 12 },\n children: [\n buildCardHeader(),\n buildCardStats(),\n ],\n },\n ],\n };\n}\n\nfunction buildCardHeader(): SpecNode {\n return {\n id: \"card-header\",\n type: \"row\",\n props: { justify: \"between\", align: \"center\" },\n children: [\n {\n id: \"factor-name\",\n type: \"text\",\n props: { value: \"{item.factor_name}\", variant: \"subheading\", bold: true },\n },\n {\n id: \"tier-badge\",\n type: \"chip\",\n props: { label: \"{item.factor_tier}\", variant: \"filled\" },\n },\n ],\n };\n}\n\nfunction buildCardStats(): SpecNode {\n return {\n id: \"card-stats\",\n type: \"row\",\n props: { gap: 16 },\n children: [\n buildStatColumn(\"stat-avg\", \"Avg\", \"{item.avg_value}\"),\n buildStatColumn(\"stat-p95\", \"P95\", \"{item.p95_value}\"),\n buildStatColumn(\"stat-users\", \"Users\", \"{item.user_count}\"),\n ],\n };\n}\n\nfunction buildStatColumn(id: string, label: string, valueRef: string): SpecNode {\n return {\n id,\n type: \"column\",\n props: { align: \"center\", gap: 2 },\n children: [\n {\n id: `${id}-label`,\n type: \"text\",\n props: { value: label, variant: \"caption\", color: \"#888\" },\n },\n {\n id: `${id}-value`,\n type: \"text\",\n props: { value: valueRef, variant: \"body\", bold: true },\n },\n ],\n };\n}\n","import type { SupabaseClient } from \"@supabase/supabase-js\";\n\nexport interface UserCluster {\n user_id: string;\n cluster_id: number;\n assigned_at: string;\n}\n\n/**\n * Queries the cluster assignment for a specific user.\n */\nexport async function queryUserCluster(\n client: SupabaseClient,\n userId: string,\n): Promise<UserCluster | null> {\n const { data, error } = await client\n .from(\"user_clusters\")\n .select(\"user_id, cluster_id, assigned_at\")\n .eq(\"user_id\", userId)\n .maybeSingle();\n\n if (error) throw new Error(`queryUserCluster failed: ${error.message}`);\n return data as UserCluster | null;\n}\n\n/**\n * Queries all users in a specific cluster.\n */\nexport async function queryClusterMembers(\n client: SupabaseClient,\n clusterId: number,\n): Promise<UserCluster[]> {\n const { data, error } = await client\n .from(\"user_clusters\")\n .select(\"user_id, cluster_id, assigned_at\")\n .eq(\"cluster_id\", clusterId);\n\n if (error) throw new Error(`queryClusterMembers failed: ${error.message}`);\n return (data ?? []) as UserCluster[];\n}\n\n// --- Pure k-means algorithm (shared with edge function) ---\n\nconst MAX_ITERATIONS = 50;\nconst CONVERGENCE_THRESHOLD = 1e-6;\n\nexport interface KMeansResult {\n labels: number[];\n centroids: number[][];\n iterations: number;\n}\n\n/**\n * K-means clustering with k-means++ initialization.\n * Pure function — no I/O, deterministic given a seed.\n */\nexport function kMeans(\n points: number[][],\n k: number,\n seed?: number,\n): KMeansResult {\n const rng = createSeededRng(seed ?? Date.now());\n const centroids = initializeCentroids(points, k, rng);\n const labels = new Array<number>(points.length).fill(0);\n\n let iteration = 0;\n for (; iteration < MAX_ITERATIONS; iteration++) {\n assignPointsToCentroids(points, centroids, labels);\n const maxShift = updateCentroids(points, centroids, labels, k);\n\n if (maxShift < CONVERGENCE_THRESHOLD) {\n iteration++;\n break;\n }\n }\n\n return { labels, centroids, iterations: iteration };\n}\n\nfunction initializeCentroids(\n points: number[][],\n k: number,\n rng: () => number,\n): number[][] {\n const centroids: number[][] = [];\n const firstIndex = Math.floor(rng() * points.length);\n centroids.push([...points[firstIndex]]);\n\n for (let c = 1; c < k; c++) {\n const distances = points.map(p => nearestCentroidDistance(p, centroids));\n const totalDistance = distances.reduce((sum, d) => sum + d, 0);\n const threshold = rng() * totalDistance;\n\n let cumulative = 0;\n for (let i = 0; i < points.length; i++) {\n cumulative += distances[i];\n if (cumulative >= threshold) {\n centroids.push([...points[i]]);\n break;\n }\n }\n }\n\n return centroids;\n}\n\nfunction nearestCentroidDistance(point: number[], centroids: number[][]): number {\n let minDist = Infinity;\n for (const centroid of centroids) {\n const dist = squaredEuclidean(point, centroid);\n if (dist < minDist) minDist = dist;\n }\n return minDist;\n}\n\nfunction assignPointsToCentroids(\n points: number[][],\n centroids: number[][],\n labels: number[],\n): void {\n for (let i = 0; i < points.length; i++) {\n let minDist = Infinity;\n let bestCluster = 0;\n\n for (let c = 0; c < centroids.length; c++) {\n const dist = squaredEuclidean(points[i], centroids[c]);\n if (dist < minDist) {\n minDist = dist;\n bestCluster = c;\n }\n }\n\n labels[i] = bestCluster;\n }\n}\n\nfunction updateCentroids(\n points: number[][],\n centroids: number[][],\n labels: number[],\n k: number,\n): number {\n const dimensions = points[0].length;\n let maxShift = 0;\n\n for (let c = 0; c < k; c++) {\n const newCentroid = new Array<number>(dimensions).fill(0);\n let count = 0;\n\n for (let i = 0; i < points.length; i++) {\n if (labels[i] !== c) continue;\n count++;\n for (let d = 0; d < dimensions; d++) {\n newCentroid[d] += points[i][d];\n }\n }\n\n if (count === 0) continue;\n\n for (let d = 0; d < dimensions; d++) {\n newCentroid[d] /= count;\n }\n\n const shift = squaredEuclidean(centroids[c], newCentroid);\n if (shift > maxShift) maxShift = shift;\n\n centroids[c] = newCentroid;\n }\n\n return maxShift;\n}\n\nfunction squaredEuclidean(a: number[], b: number[]): number {\n let sum = 0;\n for (let d = 0; d < a.length; d++) {\n const diff = a[d] - b[d];\n sum += diff * diff;\n }\n return sum;\n}\n\n// Mulberry32 PRNG — deterministic for reproducible tests\nfunction createSeededRng(seed: number): () => number {\n let state = seed | 0;\n return () => {\n state = (state + 0x6d2b79f5) | 0;\n let t = Math.imul(state ^ (state >>> 15), 1 | state);\n t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296;\n };\n}\n","import type { Factor } from \"../types.js\";\n\nexport type TargetingOperator = \"gt\" | \"gte\" | \"lt\" | \"lte\" | \"eq\";\n\nexport interface TargetingRule {\n factor: string;\n operator: TargetingOperator;\n threshold: number;\n}\n\nexport function evaluateTargeting(\n factors: Factor[],\n rules: TargetingRule[],\n): boolean {\n if (rules.length === 0) return true;\n\n const factorsByName = indexFactorsByName(factors);\n return rules.every((rule) => evaluateRule(factorsByName, rule));\n}\n\nfunction indexFactorsByName(factors: Factor[]): Map<string, number> {\n const indexed = new Map<string, number>();\n for (const factor of factors) {\n indexed.set(factor.factor_name, factor.value);\n }\n return indexed;\n}\n\nfunction evaluateRule(\n factorsByName: Map<string, number>,\n rule: TargetingRule,\n): boolean {\n const value = factorsByName.get(rule.factor);\n if (value === undefined) return false;\n\n return compareValue(value, rule.operator, rule.threshold);\n}\n\nfunction compareValue(\n value: number,\n operator: TargetingOperator,\n threshold: number,\n): boolean {\n switch (operator) {\n case \"gt\": return value > threshold;\n case \"gte\": return value >= threshold;\n case \"lt\": return value < threshold;\n case \"lte\": return value <= threshold;\n case \"eq\": return value === threshold;\n }\n}\n","import type { SupabaseClient } from \"@supabase/supabase-js\";\nimport type { ExperimentAssignment, Platform } from \"../types.js\";\nimport { queryFactors } from \"../factors/query.js\";\nimport { evaluateTargeting } from \"./targeting.js\";\nimport type { TargetingRule } from \"./targeting.js\";\n\n/**\n * Flag evaluation: reads experiment assignments for the current user.\n * If not yet assigned to a running experiment, assigns deterministically via hash bucketing.\n * Optional platform parameter filters experiments to those targeting the current platform.\n */\n\nexport async function evaluateFlag(\n supabase: SupabaseClient,\n experimentName: string,\n platform?: Platform,\n): Promise<ExperimentAssignment | null> {\n const userId = await resolveUserId(supabase);\n if (!userId) return null;\n\n const existingAssignment = await fetchAssignment(supabase, userId, experimentName);\n if (existingAssignment) {\n await recordExposure(supabase, userId, existingAssignment);\n return existingAssignment;\n }\n\n const newAssignment = await assignToExperiment(supabase, userId, experimentName, platform);\n if (newAssignment) {\n await recordExposure(supabase, userId, newAssignment);\n }\n return newAssignment;\n}\n\nasync function resolveUserId(supabase: SupabaseClient): Promise<string | null> {\n const { data: { user } } = await supabase.auth.getUser();\n return user?.id ?? null;\n}\n\ninterface AssignmentJoinRow {\n experiment_id: string;\n variant_key: string;\n experiment_variants: { config: Record<string, unknown> } | null;\n}\n\nasync function fetchAssignment(\n supabase: SupabaseClient,\n userId: string,\n experimentName: string,\n): Promise<ExperimentAssignment | null> {\n const { data, error } = await supabase\n .from(\"experiment_assignments\")\n .select(`\n experiment_id,\n variant_key,\n experiments!inner ( name, status ),\n experiment_variants!inner ( config )\n `)\n .eq(\"user_id\", userId)\n .eq(\"experiments.name\", experimentName)\n .eq(\"experiments.status\", \"running\")\n .maybeSingle();\n\n if (error || !data) return null;\n\n const row = data as unknown as AssignmentJoinRow;\n return {\n experiment_id: row.experiment_id,\n variant_key: row.variant_key,\n config: row.experiment_variants?.config ?? {},\n };\n}\n\nasync function assignToExperiment(\n supabase: SupabaseClient,\n userId: string,\n experimentName: string,\n platform?: Platform,\n): Promise<ExperimentAssignment | null> {\n const experiment = await fetchRunningExperiment(supabase, experimentName, platform);\n if (!experiment) return null;\n\n const isTargeted = await checkTargeting(supabase, userId, experiment);\n if (!isTargeted) return null;\n\n const variants = await fetchExperimentVariants(supabase, experiment.id);\n if (variants.length === 0) return null;\n\n const selectedVariant = selectVariantByHash(userId, experiment.id, variants);\n if (!selectedVariant) return null;\n\n const { error } = await supabase\n .from(\"experiment_assignments\")\n .insert({\n user_id: userId,\n experiment_id: experiment.id,\n variant_key: selectedVariant.variant_key,\n });\n\n if (error) return null;\n\n return {\n experiment_id: experiment.id,\n variant_key: selectedVariant.variant_key,\n config: selectedVariant.config,\n };\n}\n\ninterface RunningExperiment {\n id: string;\n name: string;\n component_path: string;\n targeting_rules: TargetingRule[];\n platforms: string[];\n}\n\nasync function fetchRunningExperiment(\n supabase: SupabaseClient,\n experimentName: string,\n platform?: Platform,\n): Promise<RunningExperiment | null> {\n const { data, error } = await supabase\n .from(\"experiments\")\n .select(\"id, name, component_path, targeting_rules, platforms\")\n .eq(\"name\", experimentName)\n .eq(\"status\", \"running\")\n .maybeSingle();\n\n if (error || !data) return null;\n\n const experiment = data as RunningExperiment;\n\n if (platform && experiment.platforms.length > 0 && !experiment.platforms.includes(platform)) {\n return null;\n }\n\n return experiment;\n}\n\nasync function checkTargeting(\n supabase: SupabaseClient,\n userId: string,\n experiment: RunningExperiment,\n): Promise<boolean> {\n if (!experiment.targeting_rules || experiment.targeting_rules.length === 0) return true;\n\n const factors = await queryFactors(supabase, userId, experiment.component_path);\n return evaluateTargeting(factors, experiment.targeting_rules);\n}\n\ninterface VariantWithTraffic {\n variant_key: string;\n config: Record<string, unknown>;\n traffic_percentage: number;\n}\n\nasync function fetchExperimentVariants(\n supabase: SupabaseClient,\n experimentId: string,\n): Promise<VariantWithTraffic[]> {\n const { data, error } = await supabase\n .from(\"experiment_variants\")\n .select(\"variant_key, config, traffic_percentage\")\n .eq(\"experiment_id\", experimentId)\n .order(\"variant_key\");\n\n if (error || !data) return [];\n return data as VariantWithTraffic[];\n}\n\nfunction selectVariantByHash(\n userId: string,\n experimentId: string,\n variants: VariantWithTraffic[],\n): VariantWithTraffic | null {\n const hashValue = simpleHash(`${userId}:${experimentId}`);\n const bucket = hashValue % 100;\n\n let cumulativeTraffic = 0;\n for (const variant of variants) {\n cumulativeTraffic += variant.traffic_percentage;\n if (bucket < cumulativeTraffic) {\n return variant;\n }\n }\n\n return null;\n}\n\n// DJB2 hash — deterministic, fast, sufficient for traffic bucketing\nfunction simpleHash(input: string): number {\n let hash = 5381;\n for (let i = 0; i < input.length; i++) {\n hash = ((hash << 5) + hash + input.charCodeAt(i)) >>> 0;\n }\n return hash;\n}\n\nasync function recordExposure(\n supabase: SupabaseClient,\n userId: string,\n assignment: ExperimentAssignment,\n): Promise<void> {\n await supabase.from(\"experiment_exposures\").insert({\n user_id: userId,\n experiment_id: assignment.experiment_id,\n variant_key: assignment.variant_key,\n });\n}\n","import type { SupabaseClient } from \"@supabase/supabase-js\";\nimport type { Platform } from \"../types.js\";\nimport type { TargetingRule } from \"./targeting.js\";\n\nexport interface VariantDefinition {\n variant_key: string;\n config: Record<string, unknown>;\n traffic_percentage: number;\n}\n\nexport interface ExperimentDefinition {\n name: string;\n description?: string;\n component_path: string;\n variants: VariantDefinition[];\n targeting_rules?: TargetingRule[];\n platforms?: Platform[];\n}\n\nexport interface CreatedExperiment {\n id: string;\n name: string;\n status: string;\n component_path: string;\n}\n\n/**\n * Creates a new experiment in draft status with its variants.\n * Validates traffic percentages sum to 100 and requires a control variant.\n */\nexport async function createExperiment(\n client: SupabaseClient,\n definition: ExperimentDefinition,\n): Promise<CreatedExperiment> {\n validateDefinition(definition);\n\n const experiment = await insertExperiment(client, definition);\n await insertVariants(client, experiment.id, definition.variants);\n\n return experiment;\n}\n\n/**\n * Transitions an experiment from draft to running.\n * Fails if the experiment is not in draft status.\n */\nexport async function startExperiment(\n client: SupabaseClient,\n experimentId: string,\n): Promise<void> {\n const { error } = await client\n .from(\"experiments\")\n .update({ status: \"running\" })\n .eq(\"id\", experimentId)\n .eq(\"status\", \"draft\");\n\n if (error) throw new Error(`startExperiment failed: ${error.message}`);\n}\n\nfunction validateDefinition(definition: ExperimentDefinition): void {\n if (definition.variants.length < 2) {\n throw new Error(\"Experiment requires at least 2 variants\");\n }\n\n const hasControl = definition.variants.some(v => v.variant_key === \"control\");\n if (!hasControl) {\n throw new Error(\"Experiment requires a 'control' variant\");\n }\n\n const totalTraffic = definition.variants.reduce((sum, v) => sum + v.traffic_percentage, 0);\n if (totalTraffic !== 100) {\n throw new Error(`Traffic percentages must sum to 100, got ${totalTraffic}`);\n }\n}\n\nasync function insertExperiment(\n client: SupabaseClient,\n definition: ExperimentDefinition,\n): Promise<CreatedExperiment> {\n const { data, error } = await client\n .from(\"experiments\")\n .insert({\n name: definition.name,\n description: definition.description ?? null,\n component_path: definition.component_path,\n targeting_rules: definition.targeting_rules ?? [],\n platforms: definition.platforms ?? [],\n })\n .select(\"id, name, status, component_path\")\n .single();\n\n if (error) throw new Error(`insertExperiment failed: ${error.message}`);\n return data as CreatedExperiment;\n}\n\nasync function insertVariants(\n client: SupabaseClient,\n experimentId: string,\n variants: VariantDefinition[],\n): Promise<void> {\n const rows = variants.map(v => ({\n experiment_id: experimentId,\n variant_key: v.variant_key,\n config: v.config,\n traffic_percentage: v.traffic_percentage,\n }));\n\n const { error } = await client\n .from(\"experiment_variants\")\n .insert(rows);\n\n if (error) throw new Error(`insertVariants failed: ${error.message}`);\n}\n","import type { SupabaseClient } from \"@supabase/supabase-js\";\nimport type { FactorDelta } from \"../factors/snapshots.js\";\n\nexport interface VariantResult {\n variant_key: string;\n user_count: number;\n factor_deltas: FactorDelta[];\n}\n\nexport async function queryExperimentResults(\n client: SupabaseClient,\n experimentId: string,\n factorNames: string[],\n): Promise<VariantResult[]> {\n const experiment = await fetchExperiment(client, experimentId);\n if (!experiment) return [];\n\n const variantGroups = await fetchAssignmentsByVariant(client, experimentId);\n\n const results: VariantResult[] = [];\n for (const [variantKey, userIds] of variantGroups) {\n const factorDeltas = await computeVariantDeltas(\n client, userIds, experiment.component_path, factorNames, experiment.created_at,\n );\n results.push({\n variant_key: variantKey,\n user_count: userIds.length,\n factor_deltas: factorDeltas,\n });\n }\n\n return results;\n}\n\nasync function fetchExperiment(\n client: SupabaseClient,\n experimentId: string,\n): Promise<{ component_path: string; created_at: string } | null> {\n const { data, error } = await client\n .from(\"experiments\")\n .select(\"component_path, created_at\")\n .eq(\"id\", experimentId)\n .maybeSingle();\n\n if (error || !data) return null;\n return data as { component_path: string; created_at: string };\n}\n\nasync function fetchAssignmentsByVariant(\n client: SupabaseClient,\n experimentId: string,\n): Promise<Map<string, string[]>> {\n const { data, error } = await client\n .from(\"experiment_assignments\")\n .select(\"variant_key, user_id\")\n .eq(\"experiment_id\", experimentId);\n\n if (error || !data) return new Map();\n\n const groups = new Map<string, string[]>();\n for (const row of data) {\n const existing = groups.get(row.variant_key) ?? [];\n existing.push(row.user_id);\n groups.set(row.variant_key, existing);\n }\n return groups;\n}\n\nasync function computeVariantDeltas(\n client: SupabaseClient,\n userIds: string[],\n componentPath: string,\n factorNames: string[],\n experimentCreatedAt: string,\n): Promise<FactorDelta[]> {\n const beforeDate = new Date(experimentCreatedAt);\n const afterDate = new Date();\n\n const { data, error } = await client.rpc(\"bulk_factor_deltas\", {\n p_user_ids: userIds,\n p_component: componentPath,\n p_factor_names: factorNames,\n p_before: beforeDate.toISOString(),\n p_after: afterDate.toISOString(),\n });\n\n if (error) throw new Error(`bulk_factor_deltas failed: ${error.message}`);\n if (!data) return [];\n\n return (data as BulkDeltaRow[]).map(row => ({\n factor_name: row.factor_name,\n before: row.avg_before,\n after: row.avg_after,\n delta: row.avg_delta,\n }));\n}\n\ninterface BulkDeltaRow {\n factor_name: string;\n avg_before: number;\n avg_after: number;\n avg_delta: number;\n}\n","import type { SupabaseClient } from \"@supabase/supabase-js\";\nimport { queryExperimentResults } from \"./results.js\";\nimport type { VariantResult } from \"./results.js\";\nimport type { FactorDelta } from \"../factors/snapshots.js\";\n\nexport type ThresholdOperator = \"gt\" | \"lt\" | \"gte\" | \"lte\" | \"eq\";\n\nexport interface Threshold {\n id: string;\n factor_name: string;\n component_path: string | null;\n operator: ThresholdOperator;\n value: number;\n action: \"alert\" | \"experiment\";\n}\n\nexport interface FactorVerdict {\n factor_name: string;\n best_variant: string;\n best_delta: number;\n control_delta: number;\n is_significant: boolean;\n}\n\nexport type GovernanceAction = \"conclude\" | \"flag_review\" | \"continue\";\n\nexport interface GovernanceVerdict {\n action: GovernanceAction;\n winning_variant: string | null;\n factor_verdicts: FactorVerdict[];\n}\n\n/**\n * Orchestrator: evaluates whether an experiment should be concluded\n * based on factor deltas exceeding governance thresholds.\n */\nexport async function evaluateExperimentThresholds(\n client: SupabaseClient,\n experimentId: string,\n factorNames: string[],\n): Promise<GovernanceVerdict> {\n const componentPath = await fetchExperimentComponentPath(client, experimentId);\n if (!componentPath) return buildEmptyVerdict();\n\n const results = await queryExperimentResults(client, experimentId, factorNames);\n const thresholds = await fetchThresholds(client, factorNames, componentPath);\n\n return computeGovernanceVerdict(results, thresholds);\n}\n\n/**\n * Concludes an experiment: sets status to 'concluded' and records the winner.\n */\nexport async function concludeExperiment(\n client: SupabaseClient,\n experimentId: string,\n winningVariant: string,\n): Promise<void> {\n const { error } = await client\n .from(\"experiments\")\n .update({\n status: \"concluded\",\n concluded_at: new Date().toISOString(),\n winning_variant: winningVariant,\n })\n .eq(\"id\", experimentId)\n .eq(\"status\", \"running\");\n\n if (error) throw new Error(`concludeExperiment failed: ${error.message}`);\n}\n\nasync function fetchExperimentComponentPath(\n client: SupabaseClient,\n experimentId: string,\n): Promise<string | null> {\n const { data, error } = await client\n .from(\"experiments\")\n .select(\"component_path\")\n .eq(\"id\", experimentId)\n .maybeSingle();\n\n if (error || !data) return null;\n return data.component_path as string;\n}\n\nasync function fetchThresholds(\n client: SupabaseClient,\n factorNames: string[],\n componentPath: string,\n): Promise<Threshold[]> {\n const { data, error } = await client\n .from(\"thresholds\")\n .select(\"id, factor_name, component_path, operator, value, action\")\n .in(\"factor_name\", factorNames)\n .or(`component_path.eq.${componentPath},component_path.is.null`);\n\n if (error) throw new Error(`fetchThresholds failed: ${error.message}`);\n return (data ?? []) as Threshold[];\n}\n\n/**\n * Pure logic: compares variant deltas against thresholds to produce a verdict.\n * SQL mirror: factoredui.evaluate_governance() in migration 021 duplicates these rules.\n *\n * Conservative rules:\n * - At least one factor must have a significant delta to conclude\n * - All significant factors must agree on the same winning variant\n * - If any treatment delta is worse than control, flag for review\n * - Otherwise, continue running\n */\nexport function computeGovernanceVerdict(\n results: VariantResult[],\n thresholds: Threshold[],\n): GovernanceVerdict {\n if (results.length < 2 || thresholds.length === 0) return buildEmptyVerdict();\n\n const controlResult = results.find(r => r.variant_key === \"control\");\n if (!controlResult) return buildEmptyVerdict();\n\n const treatmentResults = results.filter(r => r.variant_key !== \"control\");\n const factorVerdicts = buildFactorVerdicts(controlResult, treatmentResults, thresholds);\n\n return deriveVerdict(factorVerdicts);\n}\n\nfunction buildFactorVerdicts(\n controlResult: VariantResult,\n treatmentResults: VariantResult[],\n thresholds: Threshold[],\n): FactorVerdict[] {\n const verdicts: FactorVerdict[] = [];\n\n for (const threshold of thresholds) {\n const controlDelta = findFactorDelta(controlResult.factor_deltas, threshold.factor_name);\n const bestTreatment = findBestTreatment(treatmentResults, threshold);\n\n if (!bestTreatment || controlDelta === null) continue;\n\n const improvement = Math.abs(bestTreatment.delta) - Math.abs(controlDelta);\n const isSignificant = isThresholdExceeded(improvement, threshold.operator, threshold.value);\n\n verdicts.push({\n factor_name: threshold.factor_name,\n best_variant: bestTreatment.variantKey,\n best_delta: bestTreatment.delta,\n control_delta: controlDelta,\n is_significant: isSignificant,\n });\n }\n\n return verdicts;\n}\n\ninterface TreatmentCandidate {\n variantKey: string;\n delta: number;\n}\n\nfunction findBestTreatment(\n treatmentResults: VariantResult[],\n threshold: Threshold,\n): TreatmentCandidate | null {\n let best: TreatmentCandidate | null = null;\n\n for (const result of treatmentResults) {\n const delta = findFactorDelta(result.factor_deltas, threshold.factor_name);\n if (delta === null) continue;\n\n if (!best || Math.abs(delta) > Math.abs(best.delta)) {\n best = { variantKey: result.variant_key, delta };\n }\n }\n\n return best;\n}\n\nfunction findFactorDelta(deltas: FactorDelta[], factorName: string): number | null {\n const match = deltas.find(d => d.factor_name === factorName);\n return match?.delta ?? null;\n}\n\nexport function isThresholdExceeded(\n value: number,\n operator: ThresholdOperator,\n threshold: number,\n): boolean {\n switch (operator) {\n case \"gt\": return value > threshold;\n case \"lt\": return value < threshold;\n case \"gte\": return value >= threshold;\n case \"lte\": return value <= threshold;\n case \"eq\": return value === threshold;\n }\n}\n\nfunction deriveVerdict(factorVerdicts: FactorVerdict[]): GovernanceVerdict {\n if (factorVerdicts.length === 0) return buildEmptyVerdict();\n\n const hasWorseningTreatment = factorVerdicts.some(\n v => Math.abs(v.best_delta) < Math.abs(v.control_delta),\n );\n if (hasWorseningTreatment) {\n return { action: \"flag_review\", winning_variant: null, factor_verdicts: factorVerdicts };\n }\n\n const significantVerdicts = factorVerdicts.filter(v => v.is_significant);\n if (significantVerdicts.length === 0) {\n return { action: \"continue\", winning_variant: null, factor_verdicts: factorVerdicts };\n }\n\n const winningVariants = new Set(significantVerdicts.map(v => v.best_variant));\n if (winningVariants.size !== 1) {\n return { action: \"flag_review\", winning_variant: null, factor_verdicts: factorVerdicts };\n }\n\n const winningVariant = [...winningVariants][0];\n return { action: \"conclude\", winning_variant: winningVariant, factor_verdicts: factorVerdicts };\n}\n\nfunction buildEmptyVerdict(): GovernanceVerdict {\n return { action: \"continue\", winning_variant: null, factor_verdicts: [] };\n}\n","import type { SupabaseClient } from \"@supabase/supabase-js\";\nimport { evaluateExperimentThresholds, concludeExperiment } from \"./governance.js\";\nimport type { GovernanceVerdict } from \"./governance.js\";\n\n/**\n * Logs a governance verdict to the append-only audit log.\n */\nexport async function logGovernanceVerdict(\n client: SupabaseClient,\n experimentId: string,\n verdict: GovernanceVerdict,\n): Promise<void> {\n const { error } = await client\n .from(\"governance_log\")\n .insert({\n experiment_id: experimentId,\n verdict: verdict.action,\n winning_variant: verdict.winning_variant,\n factor_verdicts: verdict.factor_verdicts,\n });\n\n if (error) throw new Error(`logGovernanceVerdict failed: ${error.message}`);\n}\n\n/**\n * Orchestrator: evaluates governance thresholds, logs the verdict,\n * and auto-concludes if there's a clear winner.\n * Mirrors SQL cron evaluate_governance() but callable from TypeScript.\n */\nexport async function runGovernanceCheck(\n client: SupabaseClient,\n experimentId: string,\n factorNames: string[],\n): Promise<GovernanceVerdict> {\n const verdict = await evaluateExperimentThresholds(client, experimentId, factorNames);\n await logGovernanceVerdict(client, experimentId, verdict);\n await concludeIfWinner(client, experimentId, verdict);\n\n return verdict;\n}\n\nasync function concludeIfWinner(\n client: SupabaseClient,\n experimentId: string,\n verdict: GovernanceVerdict,\n): Promise<void> {\n if (verdict.action === \"conclude\" && verdict.winning_variant) {\n await concludeExperiment(client, experimentId, verdict.winning_variant);\n }\n}\n","import type { SupabaseClient } from \"@supabase/supabase-js\";\n\nexport interface ExperimentSummaryRow {\n experiment_id: string;\n name: string;\n component_path: string;\n status: string;\n winning_variant: string | null;\n created_at: string;\n concluded_at: string | null;\n variant_key: string;\n traffic_percentage: number;\n assigned_users: number;\n exposed_users: number;\n}\n\nexport interface ExperimentSummaryFilters {\n status?: string;\n component_path?: string;\n created_after?: string;\n created_before?: string;\n}\n\n/**\n * Queries all experiment summaries from the governor dashboard view.\n * Each row is one variant of one experiment with assignment/exposure counts.\n */\nexport async function queryExperimentSummaries(\n client: SupabaseClient,\n filters?: ExperimentSummaryFilters,\n): Promise<ExperimentSummaryRow[]> {\n let query = client\n .from(\"v_experiment_summary\")\n .select(\"*\");\n\n query = applyFilters(query, filters);\n\n const { data, error } = await query;\n if (error) throw new Error(`queryExperimentSummaries failed: ${error.message}`);\n return (data ?? []) as ExperimentSummaryRow[];\n}\n\n/**\n * Queries a single experiment's summary rows (one per variant).\n */\nexport async function queryExperimentSummary(\n client: SupabaseClient,\n experimentId: string,\n): Promise<ExperimentSummaryRow[]> {\n const { data, error } = await client\n .from(\"v_experiment_summary\")\n .select(\"*\")\n .eq(\"experiment_id\", experimentId);\n\n if (error) throw new Error(`queryExperimentSummary failed: ${error.message}`);\n return (data ?? []) as ExperimentSummaryRow[];\n}\n\ntype SupabaseQuery = ReturnType<ReturnType<SupabaseClient[\"from\"]>[\"select\"]>;\n\nfunction applyFilters(\n query: SupabaseQuery,\n filters?: ExperimentSummaryFilters,\n): SupabaseQuery {\n if (!filters) return query;\n\n if (filters.status) {\n query = query.eq(\"status\", filters.status);\n }\n if (filters.component_path) {\n query = query.eq(\"component_path\", filters.component_path);\n }\n if (filters.created_after) {\n query = query.gte(\"created_at\", filters.created_after);\n }\n if (filters.created_before) {\n query = query.lte(\"created_at\", filters.created_before);\n }\n\n return query;\n}\n","import type { SupabaseClient } from \"@supabase/supabase-js\";\nimport type { GovernanceAction, FactorVerdict } from \"./governance.js\";\n\nexport interface GovernanceLogRow {\n id: string;\n experiment_id: string;\n verdict: GovernanceAction;\n winning_variant: string | null;\n factor_verdicts: FactorVerdict[];\n evaluated_at: string;\n}\n\nconst GOVERNANCE_LOG_COLUMNS =\n \"id, experiment_id, verdict, winning_variant, factor_verdicts, evaluated_at\";\n\n/**\n * Queries all governance evaluations for a single experiment,\n * ordered by most recent first.\n */\nexport async function queryGovernanceLog(\n client: SupabaseClient,\n experimentId: string,\n): Promise<GovernanceLogRow[]> {\n const { data, error } = await client\n .from(\"governance_log\")\n .select(GOVERNANCE_LOG_COLUMNS)\n .eq(\"experiment_id\", experimentId)\n .order(\"evaluated_at\", { ascending: false });\n\n if (error) throw new Error(`queryGovernanceLog failed: ${error.message}`);\n return (data ?? []) as GovernanceLogRow[];\n}\n\n/**\n * Queries the most recent governance evaluations across all experiments.\n * Defaults to 50 rows.\n */\nexport async function queryRecentGovernanceLog(\n client: SupabaseClient,\n limit = 50,\n): Promise<GovernanceLogRow[]> {\n const { data, error } = await client\n .from(\"governance_log\")\n .select(GOVERNANCE_LOG_COLUMNS)\n .order(\"evaluated_at\", { ascending: false })\n .limit(limit);\n\n if (error) throw new Error(`queryRecentGovernanceLog failed: ${error.message}`);\n return (data ?? []) as GovernanceLogRow[];\n}\n\n/**\n * Queries governance evaluations filtered by verdict type\n * (conclude, flag_review, continue).\n */\nexport async function queryGovernanceLogByVerdict(\n client: SupabaseClient,\n verdict: GovernanceAction,\n): Promise<GovernanceLogRow[]> {\n const { data, error } = await client\n .from(\"governance_log\")\n .select(GOVERNANCE_LOG_COLUMNS)\n .eq(\"verdict\", verdict)\n .order(\"evaluated_at\", { ascending: false });\n\n if (error) throw new Error(`queryGovernanceLogByVerdict failed: ${error.message}`);\n return (data ?? []) as GovernanceLogRow[];\n}\n","import type { Spec, SpecNode, SpecNodeType } from \"./spec-types.js\";\nimport { RENDERER_VERSION } from \"./spec-types.js\";\n\n/**\n * Validates an Spec for structural correctness and renderer compatibility.\n * Returns a list of errors. Empty list = valid spec.\n */\n\nconst VALID_TYPES: ReadonlySet<SpecNodeType> = new Set([\n \"column\", \"row\", \"stack\", \"scrollview\", \"grid\",\n \"text\", \"image\", \"icon\", \"divider\", \"spacer\",\n \"textinput\", \"button\", \"toggle\", \"select\", \"slider\",\n \"card\", \"list\", \"tabs\", \"modal\", \"chip\",\n]);\n\nconst MAX_TREE_DEPTH = 20;\n\nexport function validateSpec(spec: Spec): string[] {\n const errors: string[] = [];\n\n validateEnvelope(spec, errors);\n validateNodeTree(spec.root, errors, 0);\n validateUniqueIds(spec.root, errors);\n\n return errors;\n}\n\nfunction validateEnvelope(spec: Spec, errors: string[]): void {\n if (typeof spec.spec_version !== \"number\" || spec.spec_version < 1) {\n errors.push(\"spec_version must be a positive integer\");\n }\n if (typeof spec.renderer_min !== \"number\" || spec.renderer_min < 1) {\n errors.push(\"renderer_min must be a positive integer\");\n }\n if (spec.renderer_min > RENDERER_VERSION) {\n errors.push(\n `spec requires renderer_min ${spec.renderer_min} but installed renderer is ${RENDERER_VERSION}`,\n );\n }\n if (!spec.root) {\n errors.push(\"spec must have a root node\");\n }\n}\n\nfunction validateNodeTree(node: SpecNode, errors: string[], depth: number): void {\n if (depth > MAX_TREE_DEPTH) {\n errors.push(`node \"${node.id}\" exceeds max tree depth of ${MAX_TREE_DEPTH}`);\n return;\n }\n\n validateNodeStructure(node, errors);\n validateBindingRefs(node, errors, depth);\n\n if (node.children) {\n for (const child of node.children) {\n validateNodeTree(child, errors, depth + 1);\n }\n }\n}\n\nfunction validateNodeStructure(node: SpecNode, errors: string[]): void {\n if (!node.id || typeof node.id !== \"string\") {\n errors.push(\"every node must have a string id\");\n }\n if (!VALID_TYPES.has(node.type)) {\n errors.push(`node \"${node.id}\" has unknown type \"${node.type}\"`);\n }\n if (node.action && typeof node.action.action !== \"string\") {\n errors.push(`node \"${node.id}\" has action without a name`);\n }\n}\n\nfunction validateBindingRefs(node: SpecNode, errors: string[], depth: number): void {\n if (node.visible && !isValidBindingRef(node.visible)) {\n errors.push(`node \"${node.id}\" visible must be a binding ref like \"{flag.name}\"`);\n }\n\n if (node.props) {\n for (const [key, value] of Object.entries(node.props)) {\n if (isSpecNode(value)) {\n validateNodeTree(value, errors, depth + 1);\n } else {\n validatePropValue(node.id, key, value, errors);\n }\n }\n }\n}\n\nfunction isSpecNode(value: unknown): value is SpecNode {\n return typeof value === \"object\" && value !== null && \"id\" in value && \"type\" in value;\n}\n\nfunction validatePropValue(\n nodeId: string,\n key: string,\n value: unknown,\n errors: string[],\n): void {\n if (typeof value === \"string\" && value.includes(\"{\") && !isValidBindingRef(value)) {\n errors.push(`node \"${nodeId}\" prop \"${key}\" has malformed binding ref \"${value}\"`);\n }\n}\n\nfunction isValidBindingRef(value: string): boolean {\n if (!value.startsWith(\"{\") || !value.endsWith(\"}\")) return false;\n const path = value.slice(1, -1);\n return /^[a-zA-Z_][a-zA-Z0-9_.]*$/.test(path);\n}\n\nfunction validateUniqueIds(root: SpecNode, errors: string[]): void {\n const ids = new Set<string>();\n collectDuplicateIds(root, ids, errors);\n}\n\nfunction collectDuplicateIds(\n node: SpecNode,\n seen: Set<string>,\n errors: string[],\n): void {\n if (seen.has(node.id)) {\n errors.push(`duplicate node id \"${node.id}\"`);\n }\n seen.add(node.id);\n\n if (node.children) {\n for (const child of node.children) {\n collectDuplicateIds(child, seen, errors);\n }\n }\n\n if (node.props) {\n for (const value of Object.values(node.props)) {\n if (isSpecNode(value)) {\n collectDuplicateIds(value, seen, errors);\n }\n }\n }\n}\n","import type { DataSourceRegistry, DataSourceConfig } from \"./spec-types.js\";\n\n/**\n * Resolves data sources for spec rendering.\n * Each source has a fetch function, optional cache policy, and optional realtime flag.\n * Offline: serves cached data if available, empty object if not.\n */\n\nexport interface ResolvedSources {\n sources: Record<string, unknown>;\n errors: Record<string, string>;\n}\n\nexport interface DataSourceCache {\n load(key: string): Promise<unknown | null>;\n save(key: string, data: unknown): Promise<void>;\n}\n\nexport async function resolveAllSources(\n registry: DataSourceRegistry,\n cache: DataSourceCache,\n): Promise<ResolvedSources> {\n const sourceEntries = Object.entries(registry);\n const results = await Promise.allSettled(\n sourceEntries.map(([name, config]) => resolveSource(name, config, cache)),\n );\n\n return assembleResults(sourceEntries, results);\n}\n\nasync function resolveSource(\n name: string,\n config: DataSourceConfig,\n cache: DataSourceCache,\n): Promise<{ name: string; data: unknown }> {\n const cached = config.cache === \"local\" ? await cache.load(name) : null;\n\n try {\n const fresh = await config.fetch();\n const data = applyMaxItems(fresh, config.maxItems);\n\n if (config.cache === \"local\") {\n await cache.save(name, data);\n }\n\n return { name, data };\n } catch {\n if (cached != null) {\n return { name, data: cached };\n }\n throw new Error(`source \"${name}\" fetch failed and no cache available`);\n }\n}\n\nfunction applyMaxItems(data: unknown, maxItems?: number): unknown {\n if (!maxItems || !Array.isArray(data)) return data;\n return data.slice(0, maxItems);\n}\n\nfunction assembleResults(\n entries: [string, DataSourceConfig][],\n results: PromiseSettledResult<{ name: string; data: unknown }>[],\n): ResolvedSources {\n const sources: Record<string, unknown> = {};\n const errors: Record<string, string> = {};\n\n for (let i = 0; i < entries.length; i++) {\n const [name] = entries[i];\n const result = results[i];\n\n if (result.status === \"fulfilled\") {\n sources[name] = result.value.data;\n } else {\n errors[name] = result.reason?.message ?? \"unknown error\";\n sources[name] = null;\n }\n }\n\n return { sources, errors };\n}\n","/**\n * Binding resolution: resolves \"{path.to.value}\" references against a data context.\n * Pure functions. No side effects. No expressions — single-level path lookup only.\n */\n\nconst BINDING_PATTERN = /^\\{([a-zA-Z_][a-zA-Z0-9_.]*)\\}$/;\nconst INLINE_BINDING_PATTERN = /\\{([a-zA-Z_][a-zA-Z0-9_.]*)\\}/g;\n\nexport function isBindingRef(value: string): boolean {\n return BINDING_PATTERN.test(value);\n}\n\nexport function resolveBinding(ref: string, context: Record<string, unknown>): unknown {\n const match = ref.match(BINDING_PATTERN);\n if (!match) return ref;\n return resolvePath(match[1], context);\n}\n\nexport function resolveTextWithBindings(\n text: string,\n context: Record<string, unknown>,\n): string {\n return text.replace(INLINE_BINDING_PATTERN, (_, path: string) => {\n const value = resolvePath(path, context);\n return value != null ? String(value) : \"\";\n });\n}\n\nexport function resolveProps(\n props: Record<string, unknown>,\n context: Record<string, unknown>,\n): Record<string, unknown> {\n const resolved: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(props)) {\n resolved[key] = resolveValue(value, context);\n }\n return resolved;\n}\n\nfunction resolveValue(value: unknown, context: Record<string, unknown>): unknown {\n if (typeof value === \"string\" && value.includes(\"{\")) {\n if (isBindingRef(value)) return resolveBinding(value, context);\n return resolveTextWithBindings(value, context);\n }\n if (Array.isArray(value)) return value.map((v) => resolveValue(v, context));\n if (typeof value === \"object\" && value !== null) {\n return resolveProps(value as Record<string, unknown>, context);\n }\n return value;\n}\n\nfunction resolvePath(path: string, context: Record<string, unknown>): unknown {\n const segments = path.split(\".\");\n let current: unknown = context;\n\n for (const segment of segments) {\n if (current == null || typeof current !== \"object\") return undefined;\n current = (current as Record<string, unknown>)[segment];\n }\n\n return current;\n}\n","import type { ActionRef, ActionRegistry } from \"./spec-types.js\";\nimport { resolveProps } from \"./binding.js\";\n\n/**\n * Dispatches named actions from spec nodes.\n * Actions are defined by the host app, not the spec.\n * The spec references actions by name; this module resolves and invokes them.\n */\n\nexport function dispatchAction(\n actionRef: ActionRef,\n registry: ActionRegistry,\n context: Record<string, unknown>,\n): void {\n const handler = registry[actionRef.action];\n if (!handler) {\n console.warn(`factoredui: unknown action \"${actionRef.action}\"`);\n return;\n }\n\n const resolvedParams = actionRef.params\n ? resolveProps(actionRef.params as Record<string, unknown>, context)\n : {};\n\n Promise.resolve(handler(resolvedParams)).catch((err) => {\n console.error(`factoredui: action \"${actionRef.action}\" failed:`, err);\n });\n}\n","import type { SupabaseClient } from \"@supabase/supabase-js\";\nimport type { Spec, SignedSpec } from \"./spec-types.js\";\nimport { RENDERER_VERSION } from \"./spec-types.js\";\nimport { validateSpec } from \"./spec-validator.js\";\n\n/**\n * Spec loading: baseline (bundled) → active (local storage) → remote (Supabase).\n * Signature verification is required. Fail closed on invalid signatures.\n *\n * The host app provides:\n * - baselineSpec: bundled in the APK/IPA at build time\n * - loadActive/saveActive: local storage for the current active spec\n * - verifySignature: Ed25519 verification against embedded public key\n */\n\nexport interface SpecStorage {\n loadActive(): Promise<SignedSpec | null>;\n saveActive(signed: SignedSpec): Promise<void>;\n}\n\nexport interface SignatureVerifier {\n verify(specHash: string, signature: string): Promise<boolean>;\n computeHash(spec: Spec): Promise<string>;\n}\n\nexport interface LoadedSpec {\n spec: Spec;\n source: \"remote\" | \"active\" | \"baseline\";\n}\n\nexport async function loadSpec(\n supabase: SupabaseClient,\n platform: string,\n baseline: Spec,\n storage: SpecStorage,\n verifier: SignatureVerifier,\n): Promise<LoadedSpec> {\n const remote = await fetchRemoteSpec(supabase, platform);\n if (remote) {\n const validated = await validateSignedSpec(remote, verifier);\n if (validated) {\n await storage.saveActive(remote);\n return { spec: remote.spec, source: \"remote\" };\n }\n }\n\n const active = await loadActiveSpec(storage);\n if (active) {\n const validated = await validateSignedSpec(active, verifier);\n if (validated) {\n return { spec: active.spec, source: \"active\" };\n }\n }\n\n return { spec: baseline, source: \"baseline\" };\n}\n\nasync function validateSignedSpec(\n signed: SignedSpec,\n verifier: SignatureVerifier,\n): Promise<boolean> {\n const hashMatches = await verifySpecHash(signed, verifier);\n if (!hashMatches) return false;\n\n const signatureValid = await verifier.verify(signed.spec_hash, signed.signature);\n if (!signatureValid) return false;\n\n if (signed.spec.renderer_min > RENDERER_VERSION) return false;\n\n const schemaErrors = validateSpec(signed.spec);\n return schemaErrors.length === 0;\n}\n\nasync function verifySpecHash(\n signed: SignedSpec,\n verifier: SignatureVerifier,\n): Promise<boolean> {\n const computedHash = await verifier.computeHash(signed.spec);\n return computedHash === signed.spec_hash;\n}\n\nasync function fetchRemoteSpec(\n supabase: SupabaseClient,\n platform: string,\n): Promise<SignedSpec | null> {\n try {\n const { data, error } = await supabase\n .from(\"ui_active\")\n .select(\"spec_id, ui_specs(*)\")\n .eq(\"platform\", platform)\n .single();\n\n if (error || !data) return null;\n\n return mapRowToSignedSpec(data);\n } catch {\n return null;\n }\n}\n\nfunction mapRowToSignedSpec(data: unknown): SignedSpec {\n const row = data as {\n spec_id: string;\n ui_specs: {\n component_tree: unknown;\n spec_version: number;\n renderer_min: number;\n spec_hash: string;\n signature: string;\n };\n };\n\n return {\n spec: {\n spec_version: row.ui_specs.spec_version,\n renderer_min: row.ui_specs.renderer_min,\n root: row.ui_specs.component_tree as Spec[\"root\"],\n },\n signature: row.ui_specs.signature,\n signed_at: \"\",\n spec_hash: row.ui_specs.spec_hash,\n };\n}\n\nasync function loadActiveSpec(\n storage: SpecStorage,\n): Promise<SignedSpec | null> {\n try {\n return await storage.loadActive();\n } catch {\n return null;\n }\n}\n","import type { Spec, SignedSpec } from \"./spec-types.js\";\nimport type { SpecStorage, SignatureVerifier } from \"./spec-loader.js\";\nimport type { DataSourceCache } from \"./data-source.js\";\n\n/**\n * Generic key-value storage interface.\n * AsyncStorage (RN), localStorage (web), or any compatible backend.\n */\nexport interface KVStorage {\n getItem(key: string): Promise<string | null> | string | null;\n setItem(key: string, value: string): Promise<void> | void;\n removeItem(key: string): Promise<void> | void;\n}\n\n/**\n * Creates a SpecStorage backed by any KV store.\n * Stores the active signed spec as JSON under a single key.\n */\nexport function createSpecStorage(kv: KVStorage, prefix = \"factoredui\"): SpecStorage {\n const key = `${prefix}:active-spec`;\n\n return {\n async loadActive(): Promise<SignedSpec | null> {\n const raw = await kv.getItem(key);\n if (!raw) return null;\n return JSON.parse(raw) as SignedSpec;\n },\n\n async saveActive(signed: SignedSpec): Promise<void> {\n await kv.setItem(key, JSON.stringify(signed));\n },\n };\n}\n\n/**\n * Creates a DataSourceCache backed by any KV store.\n * Caches resolved source data for offline rendering.\n */\nexport function createDataSourceCache(kv: KVStorage, prefix = \"factoredui\"): DataSourceCache {\n const keyPrefix = `${prefix}:source:`;\n\n return {\n async load(sourceKey: string): Promise<unknown | null> {\n const raw = await kv.getItem(keyPrefix + sourceKey);\n if (!raw) return null;\n return JSON.parse(raw);\n },\n\n async save(sourceKey: string, data: unknown): Promise<void> {\n await kv.setItem(keyPrefix + sourceKey, JSON.stringify(data));\n },\n };\n}\n\n/**\n * Dev-only signature verifier. Always passes.\n * Replace with Ed25519 verification before OTA spec delivery.\n */\nexport const devSignatureVerifier: SignatureVerifier = {\n async verify(_specHash: string, _signature: string): Promise<boolean> {\n return true;\n },\n\n async computeHash(spec: Spec): Promise<string> {\n const json = JSON.stringify(spec);\n let hash = 0;\n for (let i = 0; i < json.length; i++) {\n const char = json.charCodeAt(i);\n hash = ((hash << 5) - hash + char) | 0;\n }\n return `dev:${hash.toString(16)}`;\n },\n};\n","import type { Spec } from \"./spec-types.js\";\nimport type { SignatureVerifier } from \"./spec-loader.js\";\n\n/**\n * Creates an Ed25519 signature verifier for client-side spec validation.\n * Public key is embedded in the APK/IPA at build time.\n *\n * Uses Web Crypto API (Ed25519 supported in Node 20+, Chrome 113+, Deno).\n */\nexport function createEd25519Verifier(publicKeyBase64: string): SignatureVerifier {\n let cachedKey: CryptoKey | null = null;\n\n async function importPublicKey(): Promise<CryptoKey> {\n if (cachedKey) return cachedKey;\n\n const keyBuffer = base64ToBytes(publicKeyBase64);\n cachedKey = await crypto.subtle.importKey(\n \"raw\",\n keyBuffer,\n { name: \"Ed25519\" },\n false,\n [\"verify\"],\n );\n return cachedKey;\n }\n\n return {\n async verify(specHash: string, signature: string): Promise<boolean> {\n const key = await importPublicKey();\n const signatureBuffer = base64ToBytes(signature);\n const hashBytes = new TextEncoder().encode(specHash);\n\n return crypto.subtle.verify(\"Ed25519\", key, signatureBuffer, hashBytes);\n },\n\n async computeHash(spec: Spec): Promise<string> {\n return computeSpecHash(spec);\n },\n };\n}\n\n/**\n * Ed25519 spec signer for server-side spec publishing.\n * Signs spec_hash + monotonic version + renderer_min + timestamp.\n */\nexport interface SpecSigner {\n signSpec(spec: Spec): Promise<{ spec_hash: string; signature: string; signed_at: string }>;\n}\n\nexport function createEd25519Signer(privateKeyBase64: string): SpecSigner {\n let cachedKey: CryptoKey | null = null;\n\n async function importPrivateKey(): Promise<CryptoKey> {\n if (cachedKey) return cachedKey;\n\n const keyBuffer = base64ToBytes(privateKeyBase64);\n cachedKey = await crypto.subtle.importKey(\n \"pkcs8\",\n keyBuffer,\n { name: \"Ed25519\" },\n false,\n [\"sign\"],\n );\n return cachedKey;\n }\n\n return {\n async signSpec(spec: Spec) {\n const specHash = await computeSpecHash(spec);\n const key = await importPrivateKey();\n const hashBytes = new TextEncoder().encode(specHash);\n const signatureBytes = await crypto.subtle.sign(\"Ed25519\", key, hashBytes);\n const signature = bytesToBase64(new Uint8Array(signatureBytes));\n const signedAt = new Date().toISOString();\n\n return { spec_hash: specHash, signature, signed_at: signedAt };\n },\n };\n}\n\n/**\n * Generates an Ed25519 keypair for initial setup.\n * Returns base64-encoded public and private keys.\n */\nexport async function generateEd25519Keypair(): Promise<{\n publicKey: string;\n privateKey: string;\n}> {\n const keypair = await crypto.subtle.generateKey(\"Ed25519\", true, [\"sign\", \"verify\"]);\n\n const publicKeyBytes = await crypto.subtle.exportKey(\"raw\", keypair.publicKey);\n const privateKeyBytes = await crypto.subtle.exportKey(\"pkcs8\", keypair.privateKey);\n\n return {\n publicKey: bytesToBase64(new Uint8Array(publicKeyBytes)),\n privateKey: bytesToBase64(new Uint8Array(privateKeyBytes)),\n };\n}\n\nasync function computeSpecHash(spec: Spec): Promise<string> {\n const json = JSON.stringify(spec);\n const bytes = new TextEncoder().encode(json);\n const hashBuffer = await crypto.subtle.digest(\"SHA-256\", bytes);\n return bytesToHex(new Uint8Array(hashBuffer));\n}\n\nfunction base64ToBytes(base64: string): Uint8Array<ArrayBuffer> {\n const binary = atob(base64);\n const buffer = new ArrayBuffer(binary.length);\n const bytes = new Uint8Array(buffer);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return bytes;\n}\n\nfunction bytesToBase64(bytes: Uint8Array): string {\n let binary = \"\";\n for (let i = 0; i < bytes.length; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return btoa(binary);\n}\n\nfunction bytesToHex(bytes: Uint8Array): string {\n const hexChars: string[] = [];\n for (let i = 0; i < bytes.length; i++) {\n hexChars.push(bytes[i].toString(16).padStart(2, \"0\"));\n }\n return hexChars.join(\"\");\n}\n"],"mappings":"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","names":["resolveUserId"]}
|
|
1
|
+
{"version":3,"sources":["../src/capture/session.ts","../src/capture/writer.ts","../src/capture/path.ts","../src/capture/behavioral.ts","../src/capture/web-adapter.ts","../src/capture/index.ts","../src/factors/query.ts","../src/factors/snapshots.ts","../src/factors/data-sources.ts","../src/sdui/spec-types.ts","../src/factors/dashboard-spec.ts","../src/factors/clustering.ts","../src/experiment/targeting.ts","../src/experiment/flags.ts","../src/experiment/lifecycle.ts","../src/experiment/results.ts","../src/experiment/governance.ts","../src/experiment/governance-check.ts","../src/experiment/dashboard.ts","../src/experiment/governance-log.ts","../src/sdui/spec-validator.ts","../src/sdui/data-source.ts","../src/sdui/binding.ts","../src/sdui/action-dispatch.ts","../src/sdui/spec-loader.ts","../src/sdui/default-storage.ts","../src/sdui/ed25519.ts"],"sourcesContent":["import type { SupabaseClient } from \"@supabase/supabase-js\";\nimport type { Session, Platform } from \"../types.js\";\nimport type { CaptureAdapter } from \"./adapter.js\";\n\nconst DEFAULT_TIMEOUT_MS = 30 * 60 * 1000; // 30 minutes\n\nexport interface SessionManager {\n ensureSession: (userId: string) => Promise<string>;\n endSession: () => Promise<void>;\n getSessionId: () => string | null;\n}\n\nexport function createSessionManager(\n supabase: SupabaseClient,\n adapter: CaptureAdapter,\n platform: Platform,\n timeoutMs: number = DEFAULT_TIMEOUT_MS,\n): SessionManager {\n let currentSessionId: string | null = adapter.loadSessionId();\n let lastActivityAt = Date.now();\n\n function isSessionExpired(): boolean {\n return Date.now() - lastActivityAt > timeoutMs;\n }\n\n async function createSession(userId: string): Promise<string> {\n const metadata = {\n ...adapter.collectSessionMetadata(),\n platform,\n };\n\n const { data, error } = await supabase\n .from(\"sessions\")\n .insert({ user_id: userId, metadata })\n .select(\"id\")\n .single();\n\n if (error) throw new Error(`Failed to create session: ${error.message}`);\n return (data as Session).id;\n }\n\n async function ensureSession(userId: string): Promise<string> {\n lastActivityAt = Date.now();\n\n if (currentSessionId && !isSessionExpired()) {\n return currentSessionId;\n }\n\n currentSessionId = await createSession(userId);\n adapter.storeSessionId(currentSessionId);\n return currentSessionId;\n }\n\n async function endSession(): Promise<void> {\n if (!currentSessionId) return;\n\n await supabase\n .from(\"sessions\")\n .update({ ended_at: new Date().toISOString() })\n .eq(\"id\", currentSessionId);\n\n currentSessionId = null;\n adapter.clearSessionId();\n }\n\n function getSessionId(): string | null {\n return currentSessionId;\n }\n\n return { ensureSession, endSession, getSessionId };\n}\n","import type { SupabaseClient } from \"@supabase/supabase-js\";\nimport type { CaptureEvent } from \"../types.js\";\nimport type { CaptureAdapter } from \"./adapter.js\";\n\nconst DEFAULT_FLUSH_INTERVAL_MS = 2000;\nconst DEFAULT_FLUSH_BATCH_SIZE = 50;\n\nexport interface EventWriter {\n enqueue: (sessionId: string, userId: string, event: CaptureEvent) => void;\n flush: () => Promise<void>;\n startAutoFlush: () => void;\n stopAutoFlush: () => void;\n drainPersistedQueue: () => void;\n}\n\ninterface QueuedEvent {\n user_id: string;\n session_id: string;\n event_type: string;\n component_path: string;\n payload: Record<string, unknown>;\n}\n\nexport function createEventWriter(\n supabase: SupabaseClient,\n flushIntervalMs: number = DEFAULT_FLUSH_INTERVAL_MS,\n flushBatchSize: number = DEFAULT_FLUSH_BATCH_SIZE,\n adapter?: CaptureAdapter,\n): EventWriter {\n let queue: QueuedEvent[] = [];\n let flushTimer: ReturnType<typeof setInterval> | null = null;\n let isFlushing = false;\n\n function enqueue(\n sessionId: string,\n userId: string,\n event: CaptureEvent,\n ): void {\n queue.push({\n user_id: userId,\n session_id: sessionId,\n event_type: event.event_type,\n component_path: event.component_path,\n payload: event.payload,\n });\n\n if (queue.length >= flushBatchSize) {\n flush();\n }\n }\n\n async function flush(): Promise<void> {\n if (isFlushing || queue.length === 0) return;\n\n isFlushing = true;\n const batch = queue.splice(0, flushBatchSize);\n\n try {\n const { error } = await supabase.from(\"events\").insert(batch);\n if (error) {\n queue.unshift(...batch);\n persistQueueToAdapter();\n console.error(\"factoredui: flush failed:\", error.message);\n }\n } catch (err) {\n queue.unshift(...batch);\n persistQueueToAdapter();\n console.error(\"factoredui: flush error:\", err);\n } finally {\n isFlushing = false;\n }\n }\n\n function persistQueueToAdapter(): void {\n if (!adapter?.persistQueue || queue.length === 0) return;\n try {\n adapter.persistQueue(JSON.stringify(queue));\n } catch {\n // Storage full or unavailable — events stay in memory only\n }\n }\n\n function drainPersistedQueue(): void {\n if (!adapter?.loadQueue) return;\n try {\n const serialized = adapter.loadQueue();\n if (!serialized) return;\n\n const persisted = JSON.parse(serialized) as QueuedEvent[];\n if (persisted.length > 0) {\n queue.unshift(...persisted);\n // Clear persisted queue now that events are in memory\n adapter.persistQueue?.(\"\");\n }\n } catch {\n // Corrupt data — discard\n }\n }\n\n function startAutoFlush(): void {\n if (flushTimer) return;\n flushTimer = setInterval(flush, flushIntervalMs);\n }\n\n function stopAutoFlush(): void {\n if (flushTimer) {\n clearInterval(flushTimer);\n flushTimer = null;\n }\n }\n\n return { enqueue, flush, startAutoFlush, stopAutoFlush, drainPersistedQueue };\n}\n","/**\n * Resolves a DOM element to its component path.\n * Traverses upward looking for data-factored attributes:\n * data-factored-flow, data-factored-page, data-factored-component, data-factored-element\n *\n * Returns a path like \"onboarding/review/photo-grid/upload-button\"\n */\n\nconst PATH_TIERS = [\n \"data-factored-flow\",\n \"data-factored-page\",\n \"data-factored-component\",\n \"data-factored-element\",\n] as const;\n\nexport function resolveComponentPath(target: Element): string {\n const segments = collectPathSegments(target);\n return segments.join(\"/\") || \"unknown\";\n}\n\nfunction collectPathSegments(target: Element): string[] {\n const found: Map<string, string> = new Map();\n let current: Element | null = target;\n\n while (current) {\n for (const attr of PATH_TIERS) {\n if (!found.has(attr) && current.hasAttribute(attr)) {\n found.set(attr, current.getAttribute(attr)!);\n }\n }\n current = current.parentElement;\n }\n\n return PATH_TIERS.map((attr) => found.get(attr)).filter(\n (segment): segment is string => segment != null,\n );\n}\n","/**\n * Behavioral detection: pure logic for rage clicks and scroll reversals.\n * Platform-specific DOM bindings are in web-adapter.ts.\n * Dead click detection (MutationObserver) is web-only, lives in web-adapter.ts.\n */\n\nconst RAGE_CLICK_THRESHOLD = 3;\nconst RAGE_CLICK_WINDOW_MS = 500;\nconst SCROLL_REVERSAL_WINDOW_MS = 300;\n\n// --- Rage click detection (pure logic) ---\n\nexport interface RageClickState {\n targetPath: string | null;\n timestamps: number[];\n count: number;\n}\n\nexport function createRageClickState(): RageClickState {\n return { targetPath: null, timestamps: [], count: 0 };\n}\n\nexport function recordClickAndDetectRage(\n state: RageClickState,\n componentPath: string,\n now: number,\n): boolean {\n if (state.targetPath !== componentPath) {\n state.targetPath = componentPath;\n state.timestamps = [now];\n state.count = 1;\n return false;\n }\n\n state.timestamps.push(now);\n state.timestamps = state.timestamps.filter(\n (ts) => now - ts < RAGE_CLICK_WINDOW_MS,\n );\n state.count = state.timestamps.length;\n\n return state.count >= RAGE_CLICK_THRESHOLD;\n}\n\n// --- Scroll reversal detection (pure logic) ---\n\nexport interface ScrollState {\n lastScrollY: number;\n lastDirection: \"up\" | \"down\" | null;\n lastDirectionChangeAt: number;\n}\n\nexport function createScrollState(): ScrollState {\n return { lastScrollY: 0, lastDirection: null, lastDirectionChangeAt: 0 };\n}\n\nexport function detectScrollReversal(\n state: ScrollState,\n scrollY: number,\n now: number,\n): \"up\" | \"down\" | null {\n const direction: \"up\" | \"down\" = scrollY > state.lastScrollY ? \"down\" : \"up\";\n const previousDirection = state.lastDirection;\n\n state.lastScrollY = scrollY;\n\n if (previousDirection === null) {\n state.lastDirection = direction;\n return null;\n }\n\n if (direction !== previousDirection) {\n const timeSinceLastChange = now - state.lastDirectionChangeAt;\n state.lastDirection = direction;\n state.lastDirectionChangeAt = now;\n\n if (timeSinceLastChange < SCROLL_REVERSAL_WINDOW_MS) {\n return direction;\n }\n }\n\n return null;\n}\n","import type { CaptureEvent } from \"../types.js\";\nimport type { CaptureAdapter } from \"./adapter.js\";\nimport { resolveComponentPath } from \"./path.js\";\nimport {\n recordClickAndDetectRage,\n createRageClickState,\n detectScrollReversal,\n createScrollState,\n type RageClickState,\n type ScrollState,\n} from \"./behavioral.js\";\n\nconst THROTTLE_INTERVAL_MS = 100;\nconst DEAD_CLICK_WAIT_MS = 1000;\nconst SESSION_STORAGE_KEY = \"factoredui:session_id\";\nconst QUEUE_STORAGE_KEY = \"factoredui:offline_queue\";\n\n/**\n * Web (DOM) implementation of CaptureAdapter.\n * Attaches document/window listeners for clicks, scroll, input, errors, etc.\n * Uses sessionStorage for session persistence and navigator/window for metadata.\n */\nexport function createWebAdapter(): CaptureAdapter {\n const handlers = new Map<string, EventListener>();\n const rageClickState = createRageClickState();\n const scrollState = createScrollState();\n let emitEvent: ((event: CaptureEvent) => void) | null = null;\n\n function emit(event: CaptureEvent): void {\n emitEvent?.(event);\n }\n\n function addHandler(\n key: string,\n target: EventTarget,\n mapFn: (event: Event) => CaptureEvent | null,\n options?: AddEventListenerOptions,\n ): void {\n const eventName = key.split(\":\")[0];\n const handler = (event: Event) => {\n const mapped = mapFn(event);\n if (mapped) emit(mapped);\n };\n handlers.set(key, handler);\n target.addEventListener(eventName, handler, options);\n }\n\n function addThrottledHandler(\n key: string,\n target: EventTarget,\n mapFn: (event: Event) => CaptureEvent | null,\n options?: AddEventListenerOptions,\n ): void {\n const eventName = key.split(\":\")[0];\n let lastFiredAt = 0;\n const handler = (event: Event) => {\n const now = Date.now();\n if (now - lastFiredAt < THROTTLE_INTERVAL_MS) return;\n lastFiredAt = now;\n const mapped = mapFn(event);\n if (mapped) emit(mapped);\n };\n handlers.set(key, handler);\n target.addEventListener(eventName, handler, options);\n }\n\n function dropHandler(\n key: string,\n target: EventTarget,\n options?: EventListenerOptions,\n ): void {\n const eventName = key.split(\":\")[0];\n const handler = handlers.get(key);\n if (handler) {\n target.removeEventListener(eventName, handler, options);\n handlers.delete(key);\n }\n }\n\n function startListening(onEvent: (event: CaptureEvent) => void): void {\n emitEvent = onEvent;\n\n addHandler(\"click\", document, mapClickEvent, { capture: true });\n addHandler(\"click:rage\", document, (e) => mapRageClick(e, rageClickState), { capture: true });\n addHandler(\"click:dead\", document, (e) => { detectDeadClick(e, emit); return null; }, { capture: true });\n addThrottledHandler(\"scroll\", window, mapScrollEvent);\n addHandler(\"scroll:reversal\", window, () => mapScrollReversal(scrollState));\n addThrottledHandler(\"input\", document, (e) => mapTargetEvent(e, \"input\"), { capture: true });\n addHandler(\"focus\", document, (e) => mapTargetEvent(e, \"focus\"), { capture: true });\n addHandler(\"blur\", document, (e) => mapTargetEvent(e, \"blur\"), { capture: true });\n addHandler(\"submit\", document, mapSubmitEvent, { capture: true });\n addThrottledHandler(\"resize\", window, mapResizeEvent);\n addHandler(\"error\", window, mapErrorEvent);\n addHandler(\"visibilitychange\", document, mapVisibilityEvent);\n }\n\n function stopListening(): void {\n dropHandler(\"click\", document, { capture: true });\n dropHandler(\"click:rage\", document, { capture: true });\n dropHandler(\"click:dead\", document, { capture: true });\n dropHandler(\"scroll\", window);\n dropHandler(\"scroll:reversal\", window);\n dropHandler(\"input\", document, { capture: true });\n dropHandler(\"focus\", document, { capture: true });\n dropHandler(\"blur\", document, { capture: true });\n dropHandler(\"submit\", document, { capture: true });\n dropHandler(\"resize\", window);\n dropHandler(\"error\", window);\n dropHandler(\"visibilitychange\", document);\n emitEvent = null;\n }\n\n function registerUnloadHandler(onUnload: () => void): void {\n if (typeof window === \"undefined\") return;\n window.addEventListener(\"visibilitychange\", () => {\n if (document.visibilityState === \"hidden\") onUnload();\n });\n }\n\n return {\n startListening,\n stopListening,\n collectSessionMetadata,\n storeSessionId,\n loadSessionId,\n clearSessionId,\n registerUnloadHandler,\n persistQueue,\n loadQueue,\n };\n}\n\n// --- Offline queue (leaf functions) ---\n\nfunction persistQueue(serialized: string): void {\n try {\n if (!serialized || serialized === \"\") {\n localStorage.removeItem(QUEUE_STORAGE_KEY);\n } else {\n localStorage.setItem(QUEUE_STORAGE_KEY, serialized);\n }\n } catch {\n // Storage full or restricted\n }\n}\n\nfunction loadQueue(): string | null {\n try {\n return localStorage.getItem(QUEUE_STORAGE_KEY);\n } catch {\n return null;\n }\n}\n\n// --- Session storage (leaf functions, no closure state needed) ---\n\nfunction collectSessionMetadata(): Record<string, unknown> {\n if (typeof window === \"undefined\") return {};\n return {\n user_agent: navigator.userAgent,\n screen_width: screen.width,\n screen_height: screen.height,\n viewport_width: window.innerWidth,\n viewport_height: window.innerHeight,\n language: navigator.language,\n referrer: document.referrer || null,\n url: window.location.href,\n };\n}\n\nfunction storeSessionId(id: string): void {\n try {\n sessionStorage.setItem(SESSION_STORAGE_KEY, id);\n } catch {\n // SSR or restricted storage -- session lives in memory only\n }\n}\n\nfunction loadSessionId(): string | null {\n try {\n return sessionStorage.getItem(SESSION_STORAGE_KEY);\n } catch {\n return null;\n }\n}\n\nfunction clearSessionId(): void {\n try {\n sessionStorage.removeItem(SESSION_STORAGE_KEY);\n } catch {\n // Ignore storage errors\n }\n}\n\n// --- Event mappers (pure leaf functions) ---\n\nfunction mapClickEvent(event: Event): CaptureEvent | null {\n const target = event.target as Element | null;\n if (!target) return null;\n return {\n event_type: \"click\",\n component_path: resolveComponentPath(target),\n payload: {\n x: (event as MouseEvent).clientX,\n y: (event as MouseEvent).clientY,\n target_tag: target.tagName.toLowerCase(),\n },\n };\n}\n\nfunction mapScrollEvent(): CaptureEvent {\n return {\n event_type: \"scroll\",\n component_path: resolveComponentPath(document.documentElement),\n payload: { scroll_x: window.scrollX, scroll_y: window.scrollY },\n };\n}\n\nfunction mapTargetEvent(event: Event, eventType: \"input\" | \"focus\" | \"blur\"): CaptureEvent | null {\n const target = event.target as Element | null;\n if (!target) return null;\n return {\n event_type: eventType,\n component_path: resolveComponentPath(target),\n payload: { target_tag: target.tagName.toLowerCase() },\n };\n}\n\nfunction mapSubmitEvent(event: Event): CaptureEvent | null {\n const target = event.target as Element | null;\n if (!target) return null;\n return {\n event_type: \"submit\",\n component_path: resolveComponentPath(target),\n payload: { form_id: (target as HTMLFormElement).id || null },\n };\n}\n\nfunction mapResizeEvent(): CaptureEvent {\n return {\n event_type: \"resize\",\n component_path: resolveComponentPath(document.documentElement),\n payload: { width: window.innerWidth, height: window.innerHeight },\n };\n}\n\nfunction mapErrorEvent(event: Event): CaptureEvent {\n const errorEvent = event as ErrorEvent;\n return {\n event_type: \"error\",\n component_path: resolveComponentPath(document.documentElement),\n payload: {\n message: errorEvent.message,\n filename: errorEvent.filename,\n lineno: errorEvent.lineno,\n colno: errorEvent.colno,\n },\n };\n}\n\nfunction mapVisibilityEvent(): CaptureEvent {\n return {\n event_type: \"visibility\",\n component_path: resolveComponentPath(document.documentElement),\n payload: { visibility_state: document.visibilityState },\n };\n}\n\n// --- Behavioral mappers (delegate to pure logic in behavioral.ts) ---\n\nfunction mapRageClick(event: Event, state: RageClickState): CaptureEvent | null {\n const target = event.target as Element | null;\n if (!target) return null;\n\n const componentPath = resolveComponentPath(target);\n const isRage = recordClickAndDetectRage(state, componentPath, Date.now());\n\n if (isRage) {\n return {\n event_type: \"rage_click\",\n component_path: componentPath,\n payload: {\n click_count: state.count,\n x: (event as MouseEvent).clientX,\n y: (event as MouseEvent).clientY,\n },\n };\n }\n return null;\n}\n\nfunction detectDeadClick(\n event: Event,\n emit: (e: CaptureEvent) => void,\n): void {\n const target = event.target as Element | null;\n if (!target) return;\n\n const componentPath = resolveComponentPath(target);\n let hasMutation = false;\n const observer = new MutationObserver(() => {\n hasMutation = true;\n observer.disconnect();\n });\n\n observer.observe(document.body, {\n childList: true,\n subtree: true,\n attributes: true,\n characterData: true,\n });\n\n setTimeout(() => {\n observer.disconnect();\n if (!hasMutation) {\n emit({\n event_type: \"dead_click\",\n component_path: componentPath,\n payload: { target_tag: target.tagName.toLowerCase() },\n });\n }\n }, DEAD_CLICK_WAIT_MS);\n}\n\nfunction mapScrollReversal(state: ScrollState): CaptureEvent | null {\n const scrollY = window.scrollY;\n const reversal = detectScrollReversal(state, scrollY, Date.now());\n\n if (reversal) {\n return {\n event_type: \"scroll_reversal\",\n component_path: resolveComponentPath(document.documentElement),\n payload: { scroll_y: scrollY, direction: reversal },\n };\n }\n return null;\n}\n","import type { SupabaseClient } from \"@supabase/supabase-js\";\nimport type { CaptureHandle, Config, CaptureEvent } from \"../types.js\";\nimport { createSessionManager } from \"./session.js\";\nimport { createEventWriter } from \"./writer.js\";\nimport { createWebAdapter } from \"./web-adapter.js\";\n\n/**\n * Orchestrator: initializes capture pipeline.\n * Coordinates adapter, session manager, and batched writer.\n * Defaults to web adapter when no adapter provided.\n */\nexport function initCapture(config: Config): CaptureHandle {\n const adapter = config.adapter ?? createWebAdapter();\n const platform = config.platform ?? \"web\";\n\n const sessionManager = createSessionManager(\n config.supabase,\n adapter,\n platform,\n config.sessionTimeoutMs,\n );\n const writer = createEventWriter(\n config.supabase,\n config.flushIntervalMs,\n config.flushBatchSize,\n );\n\n const enqueueEvent = createEventEnqueuer(\n config.supabase,\n sessionManager,\n writer,\n );\n\n adapter.startListening(enqueueEvent);\n writer.startAutoFlush();\n\n adapter.registerUnloadHandler(() => {\n writer.flush();\n sessionManager.endSession();\n });\n\n return {\n stopCapture: () => {\n adapter.stopListening();\n writer.stopAutoFlush();\n },\n flushEvents: () => writer.flush(),\n getSessionId: () => sessionManager.getSessionId(),\n trackNavigation: (componentPath, action) =>\n enqueueEvent({\n event_type: \"navigation\",\n component_path: componentPath,\n payload: { action },\n }),\n trackImpression: (componentPath) =>\n enqueueEvent({\n event_type: \"impression\",\n component_path: componentPath,\n payload: {},\n }),\n };\n}\n\nfunction createEventEnqueuer(\n supabase: SupabaseClient,\n sessionManager: ReturnType<typeof createSessionManager>,\n writer: ReturnType<typeof createEventWriter>,\n): (event: CaptureEvent) => void {\n let cachedUserId: string | null = null;\n\n return (event: CaptureEvent) => {\n resolveUserId(supabase, cachedUserId).then((userId) => {\n cachedUserId = userId;\n return sessionManager.ensureSession(userId).then((sessionId) => {\n writer.enqueue(sessionId, userId, event);\n });\n }).catch((err) => {\n console.error(\"factoredui: failed to enqueue event:\", err);\n });\n };\n}\n\nasync function resolveUserId(\n supabase: SupabaseClient,\n cachedUserId: string | null,\n): Promise<string> {\n if (cachedUserId) return cachedUserId;\n const { data: { user } } = await supabase.auth.getUser();\n if (!user) throw new Error(\"factoredui: user not authenticated\");\n return user.id;\n}\n","import type { SupabaseClient } from \"@supabase/supabase-js\";\nimport type { Factor, FactorTier } from \"../types.js\";\n\nexport interface ComponentFactorAggregate {\n component_path: string;\n factor_name: string;\n factor_tier: FactorTier;\n user_count: number;\n avg_value: number;\n median_value: number;\n p95_value: number;\n min_value: number;\n max_value: number;\n stddev_value: number | null;\n}\n\nexport async function queryFactors(\n client: SupabaseClient,\n userId: string,\n componentPath: string,\n): Promise<Factor[]> {\n const { data, error } = await client\n .from(\"v_factors_current\")\n .select(\"user_id, component_path, factor_name, factor_tier, value, computed_at\")\n .eq(\"user_id\", userId)\n .eq(\"component_path\", componentPath);\n\n if (error) throw new Error(`queryFactors failed: ${error.message}`);\n return data as Factor[];\n}\n\nexport async function queryComponentFactors(\n client: SupabaseClient,\n componentPath: string,\n): Promise<ComponentFactorAggregate[]> {\n const { data, error } = await client\n .from(\"v_component_factors_agg\")\n .select(\n \"component_path, factor_name, factor_tier, user_count, avg_value, median_value, p95_value, min_value, max_value, stddev_value\",\n )\n .eq(\"component_path\", componentPath);\n\n if (error) throw new Error(`queryComponentFactors failed: ${error.message}`);\n return data as ComponentFactorAggregate[];\n}\n","import type { SupabaseClient } from \"@supabase/supabase-js\";\n\nexport interface FactorSnapshot {\n factor_name: string;\n factor_tier: string;\n value: number;\n snapshot_at: string;\n}\n\nexport interface FactorDelta {\n factor_name: string;\n before: number;\n after: number;\n delta: number;\n}\n\nexport async function queryFactorHistory(\n client: SupabaseClient,\n userId: string,\n componentPath: string,\n factorName: string,\n since: Date,\n): Promise<FactorSnapshot[]> {\n const { data, error } = await client\n .from(\"factor_snapshots\")\n .select(\"factor_name, factor_tier, value, snapshot_at\")\n .eq(\"user_id\", userId)\n .eq(\"component_path\", componentPath)\n .eq(\"factor_name\", factorName)\n .gte(\"snapshot_at\", since.toISOString())\n .order(\"snapshot_at\", { ascending: true });\n\n if (error) throw new Error(`queryFactorHistory failed: ${error.message}`);\n return data as FactorSnapshot[];\n}\n\nexport async function queryFactorDelta(\n client: SupabaseClient,\n userId: string,\n componentPath: string,\n factorName: string,\n before: Date,\n after: Date,\n): Promise<FactorDelta | null> {\n const beforeSnapshot = await findClosestSnapshot(\n client, userId, componentPath, factorName, before,\n );\n const afterSnapshot = await findClosestSnapshot(\n client, userId, componentPath, factorName, after,\n );\n\n if (!beforeSnapshot || !afterSnapshot) return null;\n\n return {\n factor_name: factorName,\n before: beforeSnapshot.value,\n after: afterSnapshot.value,\n delta: afterSnapshot.value - beforeSnapshot.value,\n };\n}\n\nasync function findClosestSnapshot(\n client: SupabaseClient,\n userId: string,\n componentPath: string,\n factorName: string,\n targetDate: Date,\n): Promise<FactorSnapshot | null> {\n const { data, error } = await client\n .from(\"factor_snapshots\")\n .select(\"factor_name, factor_tier, value, snapshot_at\")\n .eq(\"user_id\", userId)\n .eq(\"component_path\", componentPath)\n .eq(\"factor_name\", factorName)\n .lte(\"snapshot_at\", targetDate.toISOString())\n .order(\"snapshot_at\", { ascending: false })\n .limit(1)\n .maybeSingle();\n\n if (error) throw new Error(`findClosestSnapshot failed: ${error.message}`);\n return data as FactorSnapshot | null;\n}\n","import type { SupabaseClient } from \"@supabase/supabase-js\";\nimport type { DataSourceConfig } from \"../sdui/spec-types.js\";\nimport { queryFactors, queryComponentFactors } from \"./query.js\";\nimport { queryFactorHistory } from \"./snapshots.js\";\n\n/**\n * SDUI data source configs for factor views.\n * Each returns a DataSourceConfig that specs reference by name in their registry.\n */\n\nexport function factorSource(\n supabase: SupabaseClient,\n userId: string,\n componentPath: string,\n): DataSourceConfig {\n return {\n fetch: () => queryFactors(supabase, userId, componentPath),\n cache: \"local\",\n };\n}\n\nexport function componentFactorSource(\n supabase: SupabaseClient,\n componentPath: string,\n): DataSourceConfig {\n return {\n fetch: () => queryComponentFactors(supabase, componentPath),\n cache: \"local\",\n };\n}\n\nexport function factorHistorySource(\n supabase: SupabaseClient,\n userId: string,\n componentPath: string,\n factorName: string,\n since: Date,\n): DataSourceConfig {\n return {\n fetch: () => queryFactorHistory(supabase, userId, componentPath, factorName, since),\n cache: \"local\",\n };\n}\n","/**\n * SDUI Spec Types\n *\n * Declarative UI spec format. Pure data, no expressions.\n * Inspired by A2UI's flat structure, constrained for LLM generation.\n *\n * Rules:\n * - No expression language. Values are literals or single-level path refs \"{path.to.value}\".\n * - No state management in the spec. Host provides context.\n * - No data fetching. Spec declares source refs, host resolves them.\n * - No complex conditionals. Single boolean visibility via \"{flag}\" refs.\n * - Actions are named references, never inline code.\n */\n\n// --- Spec envelope ---\n\nexport interface Spec {\n spec_version: number;\n renderer_min: number;\n root: SpecNode;\n}\n\n// --- Node types ---\n\nexport type SpecNodeType =\n | \"column\"\n | \"row\"\n | \"stack\"\n | \"scrollview\"\n | \"grid\"\n | \"text\"\n | \"image\"\n | \"icon\"\n | \"divider\"\n | \"spacer\"\n | \"textinput\"\n | \"button\"\n | \"toggle\"\n | \"select\"\n | \"slider\"\n | \"card\"\n | \"list\"\n | \"tabs\"\n | \"modal\"\n | \"chip\";\n\nexport interface SpecNode {\n id: string;\n type: SpecNodeType;\n props?: Record<string, SpecValue>;\n children?: SpecNode[];\n visible?: string;\n action?: ActionRef;\n}\n\n// --- Values ---\n\n/**\n * A spec value is either a literal, a binding reference, or a nested SpecNode.\n * Binding refs are strings starting with \"{\" and ending with \"}\".\n * Single-level path only: \"{sources.pipeline.name}\" — no expressions, no chaining.\n *\n * SpecNode is included to support props like ListProps.itemTemplate\n * where a prop value is itself a component subtree.\n */\nexport type SpecValue = string | number | boolean | null | SpecNode | SpecValueArray | SpecValueObject;\ninterface SpecValueArray extends Array<SpecValue> {}\ninterface SpecValueObject { [key: string]: SpecValue; }\n\n// --- Actions ---\n\nexport interface ActionRef {\n action: string;\n params?: Record<string, SpecValue>;\n}\n\n// --- List-specific props ---\n\nexport interface ListProps {\n data: string;\n itemTemplate: SpecNode;\n emptyText?: string;\n maxItems?: number;\n}\n\n// --- Layout props ---\n\nexport interface LayoutProps {\n direction?: \"column\" | \"row\";\n gap?: number;\n padding?: number | [number, number, number, number];\n align?: \"start\" | \"center\" | \"end\" | \"stretch\";\n justify?: \"start\" | \"center\" | \"end\" | \"between\" | \"around\";\n flex?: number;\n}\n\n// --- Text props ---\n\nexport interface TextProps {\n value: string;\n variant?: \"heading\" | \"subheading\" | \"body\" | \"caption\" | \"label\";\n align?: \"left\" | \"center\" | \"right\";\n color?: string;\n bold?: boolean;\n numberOfLines?: number;\n}\n\n// --- Button props ---\n\nexport interface ButtonProps {\n label: string;\n variant?: \"primary\" | \"secondary\" | \"outline\" | \"ghost\" | \"destructive\";\n size?: \"sm\" | \"md\" | \"lg\";\n icon?: string;\n disabled?: string;\n}\n\n// --- TextInput props ---\n\nexport interface TextInputProps {\n placeholder?: string;\n multiline?: boolean;\n maxLength?: number;\n submitAction?: ActionRef;\n}\n\n// --- Image props ---\n\nexport interface ImageProps {\n source: string;\n alt: string;\n fit?: \"cover\" | \"contain\" | \"fill\";\n aspectRatio?: number;\n}\n\n// --- Icon props ---\n\nexport interface IconProps {\n name: string;\n size?: number;\n color?: string;\n}\n\n// --- Card props ---\n\nexport interface CardProps {\n variant?: \"elevated\" | \"outlined\" | \"filled\";\n}\n\n// --- Tabs props ---\n\nexport interface TabsProps {\n items: string[];\n selectedIndex?: number;\n}\n\n// --- Grid props ---\n\nexport interface GridProps {\n columns: number;\n gap?: number;\n}\n\n// --- Select props ---\n\nexport interface SelectProps {\n options: Array<{ label: string; value: string }>;\n placeholder?: string;\n selectedValue?: string;\n}\n\n// --- Chip props ---\n\nexport interface ChipProps {\n label: string;\n selected?: boolean;\n variant?: \"filled\" | \"outlined\";\n}\n\n// --- Modal props ---\n\nexport interface ModalProps {\n title?: string;\n dismissible?: boolean;\n}\n\n// --- ScrollView props ---\n\nexport interface ScrollViewProps {\n horizontal?: boolean;\n}\n\n// --- Toggle props ---\n\nexport interface ToggleProps {\n label?: string;\n value?: string;\n}\n\n// --- Slider props ---\n\nexport interface SliderProps {\n min?: number;\n max?: number;\n step?: number;\n value?: string;\n}\n\n// --- Divider props ---\n\nexport interface DividerProps {\n orientation?: \"horizontal\" | \"vertical\";\n}\n\n// --- Spacer props ---\n\nexport interface SpacerProps {\n size?: number;\n flex?: number;\n}\n\n// --- Data source contract (implemented by the host app) ---\n\nexport interface DataSourceConfig {\n fetch: () => Promise<unknown>;\n cache?: \"none\" | \"local\";\n realtime?: boolean;\n maxItems?: number;\n}\n\nexport type DataSourceRegistry = Record<string, DataSourceConfig>;\n\n// --- Action handler contract (implemented by the host app) ---\n\nexport type ActionHandler = (params: Record<string, unknown>) => void | Promise<void>;\nexport type ActionRegistry = Record<string, ActionHandler>;\n\n// --- Component contract (implemented by the host app) ---\n\nexport type ComponentRenderer = (props: Record<string, unknown>, children?: React.ReactNode) => React.ReactNode;\nexport type ComponentRegistry = Record<SpecNodeType, ComponentRenderer>;\n\n// --- Signing ---\n\nexport interface SignedSpec {\n spec: Spec;\n signature: string;\n signed_at: string;\n spec_hash: string;\n}\n\n// --- Renderer version ---\n\nexport const RENDERER_VERSION = 1;\n","import type { Spec, SpecNode, ListProps } from \"../sdui/spec-types.js\";\nimport { RENDERER_VERSION } from \"../sdui/spec-types.js\";\n\n/**\n * Generates an SDUI spec for a factor dashboard.\n * The spec expects a data source named \"factors\" bound to componentFactorSource output.\n * Each factor renders as a card with tier badge, name, and aggregate stats.\n */\n\nexport function buildFactorDashboardSpec(componentPath: string): Spec {\n return {\n spec_version: 1,\n renderer_min: RENDERER_VERSION,\n root: buildRoot(componentPath),\n };\n}\n\nfunction buildRoot(componentPath: string): SpecNode {\n return {\n id: \"root\",\n type: \"column\",\n props: { gap: 16, padding: 16 },\n children: [\n buildHeader(componentPath),\n buildFactorList(),\n ],\n };\n}\n\nfunction buildHeader(componentPath: string): SpecNode {\n return {\n id: \"header\",\n type: \"column\",\n props: { gap: 4 },\n children: [\n {\n id: \"title\",\n type: \"text\",\n props: { value: \"Factor Dashboard\", variant: \"heading\" },\n },\n {\n id: \"subtitle\",\n type: \"text\",\n props: { value: componentPath, variant: \"caption\", color: \"#666\" },\n },\n ],\n };\n}\n\nfunction buildFactorList(): SpecNode {\n const listProps: ListProps = {\n data: \"{sources.factors}\",\n emptyText: \"No factors computed yet\",\n itemTemplate: buildFactorCard(),\n };\n\n return {\n id: \"factor-list\",\n type: \"list\",\n props: { ...listProps },\n };\n}\n\nfunction buildFactorCard(): SpecNode {\n return {\n id: \"factor-card\",\n type: \"card\",\n props: { variant: \"outlined\" },\n children: [\n {\n id: \"card-content\",\n type: \"column\",\n props: { gap: 8, padding: 12 },\n children: [\n buildCardHeader(),\n buildCardStats(),\n ],\n },\n ],\n };\n}\n\nfunction buildCardHeader(): SpecNode {\n return {\n id: \"card-header\",\n type: \"row\",\n props: { justify: \"between\", align: \"center\" },\n children: [\n {\n id: \"factor-name\",\n type: \"text\",\n props: { value: \"{item.factor_name}\", variant: \"subheading\", bold: true },\n },\n {\n id: \"tier-badge\",\n type: \"chip\",\n props: { label: \"{item.factor_tier}\", variant: \"filled\" },\n },\n ],\n };\n}\n\nfunction buildCardStats(): SpecNode {\n return {\n id: \"card-stats\",\n type: \"row\",\n props: { gap: 16 },\n children: [\n buildStatColumn(\"stat-avg\", \"Avg\", \"{item.avg_value}\"),\n buildStatColumn(\"stat-p95\", \"P95\", \"{item.p95_value}\"),\n buildStatColumn(\"stat-users\", \"Users\", \"{item.user_count}\"),\n ],\n };\n}\n\nfunction buildStatColumn(id: string, label: string, valueRef: string): SpecNode {\n return {\n id,\n type: \"column\",\n props: { align: \"center\", gap: 2 },\n children: [\n {\n id: `${id}-label`,\n type: \"text\",\n props: { value: label, variant: \"caption\", color: \"#888\" },\n },\n {\n id: `${id}-value`,\n type: \"text\",\n props: { value: valueRef, variant: \"body\", bold: true },\n },\n ],\n };\n}\n","import type { SupabaseClient } from \"@supabase/supabase-js\";\n\nexport interface UserCluster {\n user_id: string;\n cluster_id: number;\n assigned_at: string;\n}\n\n/**\n * Queries the cluster assignment for a specific user.\n */\nexport async function queryUserCluster(\n client: SupabaseClient,\n userId: string,\n): Promise<UserCluster | null> {\n const { data, error } = await client\n .from(\"user_clusters\")\n .select(\"user_id, cluster_id, assigned_at\")\n .eq(\"user_id\", userId)\n .maybeSingle();\n\n if (error) throw new Error(`queryUserCluster failed: ${error.message}`);\n return data as UserCluster | null;\n}\n\n/**\n * Queries all users in a specific cluster.\n */\nexport async function queryClusterMembers(\n client: SupabaseClient,\n clusterId: number,\n): Promise<UserCluster[]> {\n const { data, error } = await client\n .from(\"user_clusters\")\n .select(\"user_id, cluster_id, assigned_at\")\n .eq(\"cluster_id\", clusterId);\n\n if (error) throw new Error(`queryClusterMembers failed: ${error.message}`);\n return (data ?? []) as UserCluster[];\n}\n\n// --- Pure k-means algorithm (shared with edge function) ---\n\nconst MAX_ITERATIONS = 50;\nconst CONVERGENCE_THRESHOLD = 1e-6;\n\nexport interface KMeansResult {\n labels: number[];\n centroids: number[][];\n iterations: number;\n}\n\n/**\n * K-means clustering with k-means++ initialization.\n * Pure function — no I/O, deterministic given a seed.\n */\nexport function kMeans(\n points: number[][],\n k: number,\n seed?: number,\n): KMeansResult {\n const rng = createSeededRng(seed ?? Date.now());\n const centroids = initializeCentroids(points, k, rng);\n const labels = new Array<number>(points.length).fill(0);\n\n let iteration = 0;\n for (; iteration < MAX_ITERATIONS; iteration++) {\n assignPointsToCentroids(points, centroids, labels);\n const maxShift = updateCentroids(points, centroids, labels, k);\n\n if (maxShift < CONVERGENCE_THRESHOLD) {\n iteration++;\n break;\n }\n }\n\n return { labels, centroids, iterations: iteration };\n}\n\nfunction initializeCentroids(\n points: number[][],\n k: number,\n rng: () => number,\n): number[][] {\n const centroids: number[][] = [];\n const firstIndex = Math.floor(rng() * points.length);\n centroids.push([...points[firstIndex]]);\n\n for (let c = 1; c < k; c++) {\n const distances = points.map(p => nearestCentroidDistance(p, centroids));\n const totalDistance = distances.reduce((sum, d) => sum + d, 0);\n const threshold = rng() * totalDistance;\n\n let cumulative = 0;\n for (let i = 0; i < points.length; i++) {\n cumulative += distances[i];\n if (cumulative >= threshold) {\n centroids.push([...points[i]]);\n break;\n }\n }\n }\n\n return centroids;\n}\n\nfunction nearestCentroidDistance(point: number[], centroids: number[][]): number {\n let minDist = Infinity;\n for (const centroid of centroids) {\n const dist = squaredEuclidean(point, centroid);\n if (dist < minDist) minDist = dist;\n }\n return minDist;\n}\n\nfunction assignPointsToCentroids(\n points: number[][],\n centroids: number[][],\n labels: number[],\n): void {\n for (let i = 0; i < points.length; i++) {\n let minDist = Infinity;\n let bestCluster = 0;\n\n for (let c = 0; c < centroids.length; c++) {\n const dist = squaredEuclidean(points[i], centroids[c]);\n if (dist < minDist) {\n minDist = dist;\n bestCluster = c;\n }\n }\n\n labels[i] = bestCluster;\n }\n}\n\nfunction updateCentroids(\n points: number[][],\n centroids: number[][],\n labels: number[],\n k: number,\n): number {\n const dimensions = points[0].length;\n let maxShift = 0;\n\n for (let c = 0; c < k; c++) {\n const newCentroid = new Array<number>(dimensions).fill(0);\n let count = 0;\n\n for (let i = 0; i < points.length; i++) {\n if (labels[i] !== c) continue;\n count++;\n for (let d = 0; d < dimensions; d++) {\n newCentroid[d] += points[i][d];\n }\n }\n\n if (count === 0) continue;\n\n for (let d = 0; d < dimensions; d++) {\n newCentroid[d] /= count;\n }\n\n const shift = squaredEuclidean(centroids[c], newCentroid);\n if (shift > maxShift) maxShift = shift;\n\n centroids[c] = newCentroid;\n }\n\n return maxShift;\n}\n\nfunction squaredEuclidean(a: number[], b: number[]): number {\n let sum = 0;\n for (let d = 0; d < a.length; d++) {\n const diff = a[d] - b[d];\n sum += diff * diff;\n }\n return sum;\n}\n\n// Mulberry32 PRNG — deterministic for reproducible tests\nfunction createSeededRng(seed: number): () => number {\n let state = seed | 0;\n return () => {\n state = (state + 0x6d2b79f5) | 0;\n let t = Math.imul(state ^ (state >>> 15), 1 | state);\n t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296;\n };\n}\n","import type { Factor } from \"../types.js\";\n\nexport type TargetingOperator = \"gt\" | \"gte\" | \"lt\" | \"lte\" | \"eq\";\n\nexport interface FactorTargetingRule {\n type: \"factor\";\n factor: string;\n operator: TargetingOperator;\n threshold: number;\n}\n\nexport type MetadataField =\n | \"os_name\"\n | \"os_version\"\n | \"manufacturer\"\n | \"model\"\n | \"app_version\"\n | \"app_build\"\n | \"platform\";\n\nexport type MetadataOperator = \"eq\" | \"neq\" | \"contains\" | \"gte\" | \"lte\";\n\nexport interface MetadataTargetingRule {\n type: \"metadata\";\n field: MetadataField;\n operator: MetadataOperator;\n value: string;\n}\n\n/** Legacy format (factor-only) for backward compatibility with existing experiments */\nexport interface LegacyTargetingRule {\n factor: string;\n operator: TargetingOperator;\n threshold: number;\n}\n\nexport type TargetingRule = FactorTargetingRule | MetadataTargetingRule | LegacyTargetingRule;\n\nexport interface DeviceMetadata {\n os_name?: string;\n os_version?: string;\n manufacturer?: string;\n model?: string;\n app_version?: string;\n app_build?: string;\n platform?: string;\n}\n\nexport function evaluateTargeting(\n factors: Factor[],\n rules: TargetingRule[],\n deviceMetadata?: DeviceMetadata,\n): boolean {\n if (rules.length === 0) return true;\n\n const factorsByName = indexFactorsByName(factors);\n return rules.every((rule) => evaluateRule(factorsByName, rule, deviceMetadata));\n}\n\nfunction indexFactorsByName(factors: Factor[]): Map<string, number> {\n const indexed = new Map<string, number>();\n for (const factor of factors) {\n indexed.set(factor.factor_name, factor.value);\n }\n return indexed;\n}\n\nfunction isMetadataRule(rule: TargetingRule): rule is MetadataTargetingRule {\n return \"type\" in rule && rule.type === \"metadata\";\n}\n\nfunction isFactorRule(rule: TargetingRule): rule is FactorTargetingRule | LegacyTargetingRule {\n return !(\"type\" in rule) || rule.type === \"factor\";\n}\n\nfunction evaluateRule(\n factorsByName: Map<string, number>,\n rule: TargetingRule,\n deviceMetadata?: DeviceMetadata,\n): boolean {\n if (isMetadataRule(rule)) {\n return evaluateMetadataRule(rule, deviceMetadata);\n }\n\n if (isFactorRule(rule)) {\n const threshold = \"threshold\" in rule ? rule.threshold : 0;\n const factorName = rule.factor;\n const value = factorsByName.get(factorName);\n if (value === undefined) return false;\n return compareNumeric(value, rule.operator, threshold);\n }\n\n return false;\n}\n\nfunction evaluateMetadataRule(\n rule: MetadataTargetingRule,\n metadata?: DeviceMetadata,\n): boolean {\n if (!metadata) return false;\n\n const fieldValue = metadata[rule.field];\n if (fieldValue === undefined || fieldValue === null) return false;\n\n return compareString(fieldValue, rule.operator, rule.value);\n}\n\nfunction compareNumeric(\n value: number,\n operator: TargetingOperator,\n threshold: number,\n): boolean {\n switch (operator) {\n case \"gt\": return value > threshold;\n case \"gte\": return value >= threshold;\n case \"lt\": return value < threshold;\n case \"lte\": return value <= threshold;\n case \"eq\": return value === threshold;\n }\n}\n\nfunction compareString(\n value: string,\n operator: MetadataOperator,\n target: string,\n): boolean {\n const lower = value.toLowerCase();\n const targetLower = target.toLowerCase();\n switch (operator) {\n case \"eq\": return lower === targetLower;\n case \"neq\": return lower !== targetLower;\n case \"contains\": return lower.includes(targetLower);\n case \"gte\": return lower >= targetLower;\n case \"lte\": return lower <= targetLower;\n }\n}\n","import type { SupabaseClient } from \"@supabase/supabase-js\";\nimport type { ExperimentAssignment, Platform } from \"../types.js\";\nimport { queryFactors } from \"../factors/query.js\";\nimport { evaluateTargeting } from \"./targeting.js\";\nimport type { TargetingRule, DeviceMetadata } from \"./targeting.js\";\n\n/**\n * Flag evaluation: reads experiment assignments for the current user.\n * If not yet assigned to a running experiment, assigns deterministically via hash bucketing.\n * Optional platform parameter filters experiments to those targeting the current platform.\n */\n\nexport async function evaluateFlag(\n supabase: SupabaseClient,\n experimentName: string,\n platform?: Platform,\n deviceMetadata?: DeviceMetadata,\n): Promise<ExperimentAssignment | null> {\n const userId = await resolveUserId(supabase);\n if (!userId) return null;\n\n const existingAssignment = await fetchAssignment(supabase, userId, experimentName);\n if (existingAssignment) {\n await recordExposure(supabase, userId, existingAssignment);\n return existingAssignment;\n }\n\n const newAssignment = await assignToExperiment(supabase, userId, experimentName, platform, deviceMetadata);\n if (newAssignment) {\n await recordExposure(supabase, userId, newAssignment);\n }\n return newAssignment;\n}\n\nasync function resolveUserId(supabase: SupabaseClient): Promise<string | null> {\n const { data: { user } } = await supabase.auth.getUser();\n return user?.id ?? null;\n}\n\ninterface AssignmentJoinRow {\n experiment_id: string;\n variant_key: string;\n experiment_variants: { config: Record<string, unknown> } | null;\n}\n\nasync function fetchAssignment(\n supabase: SupabaseClient,\n userId: string,\n experimentName: string,\n): Promise<ExperimentAssignment | null> {\n const { data, error } = await supabase\n .from(\"experiment_assignments\")\n .select(`\n experiment_id,\n variant_key,\n experiments!inner ( name, status ),\n experiment_variants!inner ( config )\n `)\n .eq(\"user_id\", userId)\n .eq(\"experiments.name\", experimentName)\n .eq(\"experiments.status\", \"running\")\n .maybeSingle();\n\n if (error || !data) return null;\n\n const row = data as unknown as AssignmentJoinRow;\n return {\n experiment_id: row.experiment_id,\n variant_key: row.variant_key,\n config: row.experiment_variants?.config ?? {},\n };\n}\n\nasync function assignToExperiment(\n supabase: SupabaseClient,\n userId: string,\n experimentName: string,\n platform?: Platform,\n deviceMetadata?: DeviceMetadata,\n): Promise<ExperimentAssignment | null> {\n const experiment = await fetchRunningExperiment(supabase, experimentName, platform);\n if (!experiment) return null;\n\n const hasConflict = await hasConflictingAssignment(\n supabase, userId, experiment.component_path, experiment.id,\n );\n if (hasConflict) return null;\n\n const isTargeted = await checkTargeting(supabase, userId, experiment, deviceMetadata);\n if (!isTargeted) return null;\n\n const variants = await fetchExperimentVariants(supabase, experiment.id);\n if (variants.length === 0) return null;\n\n const selectedVariant = selectVariantByHash(userId, experiment.id, variants);\n if (!selectedVariant) return null;\n\n const { error } = await supabase\n .from(\"experiment_assignments\")\n .insert({\n user_id: userId,\n experiment_id: experiment.id,\n variant_key: selectedVariant.variant_key,\n });\n\n if (error) return null;\n\n return {\n experiment_id: experiment.id,\n variant_key: selectedVariant.variant_key,\n config: selectedVariant.config,\n };\n}\n\n/**\n * Checks whether the user is already assigned to another running experiment\n * on the same component_path. Prevents conflicting experiment assignments\n * that would pollute factor data.\n */\nasync function hasConflictingAssignment(\n supabase: SupabaseClient,\n userId: string,\n componentPath: string,\n currentExperimentId: string,\n): Promise<boolean> {\n const { data, error } = await supabase\n .from(\"experiment_assignments\")\n .select(\"experiment_id, experiments!inner ( id, status, component_path )\")\n .eq(\"user_id\", userId)\n .eq(\"experiments.status\", \"running\")\n .eq(\"experiments.component_path\", componentPath)\n .neq(\"experiment_id\", currentExperimentId)\n .limit(1);\n\n if (error) return false;\n return (data?.length ?? 0) > 0;\n}\n\ninterface RunningExperiment {\n id: string;\n name: string;\n component_path: string;\n targeting_rules: TargetingRule[];\n platforms: string[];\n}\n\nasync function fetchRunningExperiment(\n supabase: SupabaseClient,\n experimentName: string,\n platform?: Platform,\n): Promise<RunningExperiment | null> {\n const { data, error } = await supabase\n .from(\"experiments\")\n .select(\"id, name, component_path, targeting_rules, platforms\")\n .eq(\"name\", experimentName)\n .eq(\"status\", \"running\")\n .maybeSingle();\n\n if (error || !data) return null;\n\n const experiment = data as RunningExperiment;\n\n if (platform && experiment.platforms.length > 0 && !experiment.platforms.includes(platform)) {\n return null;\n }\n\n return experiment;\n}\n\nasync function checkTargeting(\n supabase: SupabaseClient,\n userId: string,\n experiment: RunningExperiment,\n deviceMetadata?: DeviceMetadata,\n): Promise<boolean> {\n if (!experiment.targeting_rules || experiment.targeting_rules.length === 0) return true;\n\n const factors = await queryFactors(supabase, userId, experiment.component_path);\n return evaluateTargeting(factors, experiment.targeting_rules, deviceMetadata);\n}\n\ninterface VariantWithTraffic {\n variant_key: string;\n config: Record<string, unknown>;\n traffic_percentage: number;\n}\n\nasync function fetchExperimentVariants(\n supabase: SupabaseClient,\n experimentId: string,\n): Promise<VariantWithTraffic[]> {\n const { data, error } = await supabase\n .from(\"experiment_variants\")\n .select(\"variant_key, config, traffic_percentage\")\n .eq(\"experiment_id\", experimentId)\n .order(\"variant_key\");\n\n if (error || !data) return [];\n return data as VariantWithTraffic[];\n}\n\nfunction selectVariantByHash(\n userId: string,\n experimentId: string,\n variants: VariantWithTraffic[],\n): VariantWithTraffic | null {\n const hashValue = simpleHash(`${userId}:${experimentId}`);\n const bucket = hashValue % 100;\n\n let cumulativeTraffic = 0;\n for (const variant of variants) {\n cumulativeTraffic += variant.traffic_percentage;\n if (bucket < cumulativeTraffic) {\n return variant;\n }\n }\n\n return null;\n}\n\n// DJB2 hash — deterministic, fast, sufficient for traffic bucketing\nfunction simpleHash(input: string): number {\n let hash = 5381;\n for (let i = 0; i < input.length; i++) {\n hash = ((hash << 5) + hash + input.charCodeAt(i)) >>> 0;\n }\n return hash;\n}\n\nasync function recordExposure(\n supabase: SupabaseClient,\n userId: string,\n assignment: ExperimentAssignment,\n): Promise<void> {\n await supabase.from(\"experiment_exposures\").insert({\n user_id: userId,\n experiment_id: assignment.experiment_id,\n variant_key: assignment.variant_key,\n });\n}\n","import type { SupabaseClient } from \"@supabase/supabase-js\";\nimport type { Platform } from \"../types.js\";\nimport type { TargetingRule } from \"./targeting.js\";\n\nexport interface VariantDefinition {\n variant_key: string;\n config: Record<string, unknown>;\n traffic_percentage: number;\n}\n\nexport interface ExperimentDefinition {\n name: string;\n description?: string;\n component_path: string;\n variants: VariantDefinition[];\n targeting_rules?: TargetingRule[];\n platforms?: Platform[];\n}\n\nexport interface CreatedExperiment {\n id: string;\n name: string;\n status: string;\n component_path: string;\n}\n\n/**\n * Creates a new experiment in draft status with its variants.\n * Validates traffic percentages sum to 100 and requires a control variant.\n */\nexport async function createExperiment(\n client: SupabaseClient,\n definition: ExperimentDefinition,\n): Promise<CreatedExperiment> {\n validateDefinition(definition);\n\n const experiment = await insertExperiment(client, definition);\n await insertVariants(client, experiment.id, definition.variants);\n\n return experiment;\n}\n\n/**\n * Transitions an experiment from draft to running.\n * Fails if the experiment is not in draft status.\n */\nexport async function startExperiment(\n client: SupabaseClient,\n experimentId: string,\n): Promise<void> {\n const { data, error } = await client\n .from(\"experiments\")\n .update({ status: \"running\" })\n .eq(\"id\", experimentId)\n .eq(\"status\", \"draft\")\n .select(\"id\");\n\n if (error) throw new Error(`startExperiment failed: ${error.message}`);\n if (!data || data.length === 0) {\n throw new Error(`startExperiment: experiment ${experimentId} not found or not in draft status`);\n }\n}\n\nfunction validateDefinition(definition: ExperimentDefinition): void {\n if (definition.variants.length < 2) {\n throw new Error(\"Experiment requires at least 2 variants\");\n }\n\n const hasControl = definition.variants.some(v => v.variant_key === \"control\");\n if (!hasControl) {\n throw new Error(\"Experiment requires a 'control' variant\");\n }\n\n const totalTraffic = definition.variants.reduce((sum, v) => sum + v.traffic_percentage, 0);\n if (totalTraffic !== 100) {\n throw new Error(`Traffic percentages must sum to 100, got ${totalTraffic}`);\n }\n}\n\nasync function insertExperiment(\n client: SupabaseClient,\n definition: ExperimentDefinition,\n): Promise<CreatedExperiment> {\n const { data, error } = await client\n .from(\"experiments\")\n .insert({\n name: definition.name,\n description: definition.description ?? null,\n component_path: definition.component_path,\n targeting_rules: definition.targeting_rules ?? [],\n platforms: definition.platforms ?? [],\n })\n .select(\"id, name, status, component_path\")\n .single();\n\n if (error) throw new Error(`insertExperiment failed: ${error.message}`);\n return data as CreatedExperiment;\n}\n\nasync function insertVariants(\n client: SupabaseClient,\n experimentId: string,\n variants: VariantDefinition[],\n): Promise<void> {\n const rows = variants.map(v => ({\n experiment_id: experimentId,\n variant_key: v.variant_key,\n config: v.config,\n traffic_percentage: v.traffic_percentage,\n }));\n\n const { error } = await client\n .from(\"experiment_variants\")\n .insert(rows);\n\n if (error) throw new Error(`insertVariants failed: ${error.message}`);\n}\n","import type { SupabaseClient } from \"@supabase/supabase-js\";\nimport type { FactorDelta } from \"../factors/snapshots.js\";\n\nexport interface VariantResult {\n variant_key: string;\n user_count: number;\n factor_deltas: FactorDelta[];\n}\n\nexport async function queryExperimentResults(\n client: SupabaseClient,\n experimentId: string,\n factorNames: string[],\n): Promise<VariantResult[]> {\n const experiment = await fetchExperiment(client, experimentId);\n if (!experiment) return [];\n\n const variantGroups = await fetchAssignmentsByVariant(client, experimentId);\n\n const results: VariantResult[] = [];\n for (const [variantKey, userIds] of variantGroups) {\n const factorDeltas = await computeVariantDeltas(\n client, userIds, experiment.component_path, factorNames, experiment.created_at,\n );\n results.push({\n variant_key: variantKey,\n user_count: userIds.length,\n factor_deltas: factorDeltas,\n });\n }\n\n return results;\n}\n\nasync function fetchExperiment(\n client: SupabaseClient,\n experimentId: string,\n): Promise<{ component_path: string; created_at: string } | null> {\n const { data, error } = await client\n .from(\"experiments\")\n .select(\"component_path, created_at\")\n .eq(\"id\", experimentId)\n .maybeSingle();\n\n if (error || !data) return null;\n return data as { component_path: string; created_at: string };\n}\n\nasync function fetchAssignmentsByVariant(\n client: SupabaseClient,\n experimentId: string,\n): Promise<Map<string, string[]>> {\n const { data, error } = await client\n .from(\"experiment_assignments\")\n .select(\"variant_key, user_id\")\n .eq(\"experiment_id\", experimentId);\n\n if (error || !data) return new Map();\n\n const groups = new Map<string, string[]>();\n for (const row of data) {\n const existing = groups.get(row.variant_key) ?? [];\n existing.push(row.user_id);\n groups.set(row.variant_key, existing);\n }\n return groups;\n}\n\nasync function computeVariantDeltas(\n client: SupabaseClient,\n userIds: string[],\n componentPath: string,\n factorNames: string[],\n experimentCreatedAt: string,\n): Promise<FactorDelta[]> {\n const beforeDate = new Date(experimentCreatedAt);\n const afterDate = new Date();\n\n const { data, error } = await client.rpc(\"bulk_factor_deltas\", {\n p_user_ids: userIds,\n p_component: componentPath,\n p_factor_names: factorNames,\n p_before: beforeDate.toISOString(),\n p_after: afterDate.toISOString(),\n });\n\n if (error) throw new Error(`bulk_factor_deltas failed: ${error.message}`);\n if (!data) return [];\n\n return (data as BulkDeltaRow[]).map(row => ({\n factor_name: row.factor_name,\n before: row.avg_before,\n after: row.avg_after,\n delta: row.avg_delta,\n }));\n}\n\ninterface BulkDeltaRow {\n factor_name: string;\n avg_before: number;\n avg_after: number;\n avg_delta: number;\n}\n","import type { SupabaseClient } from \"@supabase/supabase-js\";\nimport { queryExperimentResults } from \"./results.js\";\nimport type { VariantResult } from \"./results.js\";\nimport type { FactorDelta } from \"../factors/snapshots.js\";\n\nexport type ThresholdOperator = \"gt\" | \"lt\" | \"gte\" | \"lte\" | \"eq\";\n\nexport interface Threshold {\n id: string;\n factor_name: string;\n component_path: string | null;\n operator: ThresholdOperator;\n value: number;\n action: \"alert\" | \"experiment\";\n}\n\nexport interface FactorVerdict {\n factor_name: string;\n best_variant: string;\n best_delta: number;\n control_delta: number;\n is_significant: boolean;\n}\n\nexport type GovernanceAction = \"conclude\" | \"flag_review\" | \"continue\";\n\nexport interface GovernanceVerdict {\n action: GovernanceAction;\n winning_variant: string | null;\n factor_verdicts: FactorVerdict[];\n}\n\n/**\n * Orchestrator: evaluates whether an experiment should be concluded\n * based on factor deltas exceeding governance thresholds.\n */\nexport async function evaluateExperimentThresholds(\n client: SupabaseClient,\n experimentId: string,\n factorNames: string[],\n): Promise<GovernanceVerdict> {\n const componentPath = await fetchExperimentComponentPath(client, experimentId);\n if (!componentPath) return buildEmptyVerdict();\n\n const results = await queryExperimentResults(client, experimentId, factorNames);\n const thresholds = await fetchThresholds(client, factorNames, componentPath);\n\n return computeGovernanceVerdict(results, thresholds);\n}\n\n/**\n * Concludes an experiment: sets status to 'concluded' and records the winner.\n */\nexport async function concludeExperiment(\n client: SupabaseClient,\n experimentId: string,\n winningVariant: string,\n): Promise<void> {\n const { error } = await client\n .from(\"experiments\")\n .update({\n status: \"concluded\",\n concluded_at: new Date().toISOString(),\n winning_variant: winningVariant,\n })\n .eq(\"id\", experimentId)\n .eq(\"status\", \"running\");\n\n if (error) throw new Error(`concludeExperiment failed: ${error.message}`);\n}\n\nasync function fetchExperimentComponentPath(\n client: SupabaseClient,\n experimentId: string,\n): Promise<string | null> {\n const { data, error } = await client\n .from(\"experiments\")\n .select(\"component_path\")\n .eq(\"id\", experimentId)\n .maybeSingle();\n\n if (error || !data) return null;\n return data.component_path as string;\n}\n\nasync function fetchThresholds(\n client: SupabaseClient,\n factorNames: string[],\n componentPath: string,\n): Promise<Threshold[]> {\n const { data, error } = await client\n .from(\"thresholds\")\n .select(\"id, factor_name, component_path, operator, value, action\")\n .in(\"factor_name\", factorNames)\n .or(`component_path.eq.${componentPath},component_path.is.null`);\n\n if (error) throw new Error(`fetchThresholds failed: ${error.message}`);\n return (data ?? []) as Threshold[];\n}\n\n/**\n * Pure logic: compares variant deltas against thresholds to produce a verdict.\n * SQL mirror: factoredui.evaluate_governance() in migration 021 duplicates these rules.\n *\n * Conservative rules:\n * - At least one factor must have a significant delta to conclude\n * - All significant factors must agree on the same winning variant\n * - If any treatment delta is worse than control, flag for review\n * - Otherwise, continue running\n */\nexport function computeGovernanceVerdict(\n results: VariantResult[],\n thresholds: Threshold[],\n): GovernanceVerdict {\n if (results.length < 2 || thresholds.length === 0) return buildEmptyVerdict();\n\n const controlResult = results.find(r => r.variant_key === \"control\");\n if (!controlResult) return buildEmptyVerdict();\n\n const treatmentResults = results.filter(r => r.variant_key !== \"control\");\n const factorVerdicts = buildFactorVerdicts(controlResult, treatmentResults, thresholds);\n\n return deriveVerdict(factorVerdicts);\n}\n\nfunction buildFactorVerdicts(\n controlResult: VariantResult,\n treatmentResults: VariantResult[],\n thresholds: Threshold[],\n): FactorVerdict[] {\n const verdicts: FactorVerdict[] = [];\n\n for (const threshold of thresholds) {\n const controlDelta = findFactorDelta(controlResult.factor_deltas, threshold.factor_name);\n const bestTreatment = findBestTreatment(treatmentResults, threshold);\n\n if (!bestTreatment || controlDelta === null) continue;\n\n const improvement = Math.abs(bestTreatment.delta) - Math.abs(controlDelta);\n const isSignificant = isThresholdExceeded(improvement, threshold.operator, threshold.value);\n\n verdicts.push({\n factor_name: threshold.factor_name,\n best_variant: bestTreatment.variantKey,\n best_delta: bestTreatment.delta,\n control_delta: controlDelta,\n is_significant: isSignificant,\n });\n }\n\n return verdicts;\n}\n\ninterface TreatmentCandidate {\n variantKey: string;\n delta: number;\n}\n\nfunction findBestTreatment(\n treatmentResults: VariantResult[],\n threshold: Threshold,\n): TreatmentCandidate | null {\n let best: TreatmentCandidate | null = null;\n\n for (const result of treatmentResults) {\n const delta = findFactorDelta(result.factor_deltas, threshold.factor_name);\n if (delta === null) continue;\n\n if (!best || Math.abs(delta) > Math.abs(best.delta)) {\n best = { variantKey: result.variant_key, delta };\n }\n }\n\n return best;\n}\n\nfunction findFactorDelta(deltas: FactorDelta[], factorName: string): number | null {\n const match = deltas.find(d => d.factor_name === factorName);\n return match?.delta ?? null;\n}\n\nexport function isThresholdExceeded(\n value: number,\n operator: ThresholdOperator,\n threshold: number,\n): boolean {\n switch (operator) {\n case \"gt\": return value > threshold;\n case \"lt\": return value < threshold;\n case \"gte\": return value >= threshold;\n case \"lte\": return value <= threshold;\n case \"eq\": return value === threshold;\n }\n}\n\nfunction deriveVerdict(factorVerdicts: FactorVerdict[]): GovernanceVerdict {\n if (factorVerdicts.length === 0) return buildEmptyVerdict();\n\n const hasWorseningTreatment = factorVerdicts.some(\n v => Math.abs(v.best_delta) < Math.abs(v.control_delta),\n );\n if (hasWorseningTreatment) {\n return { action: \"flag_review\", winning_variant: null, factor_verdicts: factorVerdicts };\n }\n\n const significantVerdicts = factorVerdicts.filter(v => v.is_significant);\n if (significantVerdicts.length === 0) {\n return { action: \"continue\", winning_variant: null, factor_verdicts: factorVerdicts };\n }\n\n const winningVariants = new Set(significantVerdicts.map(v => v.best_variant));\n if (winningVariants.size !== 1) {\n return { action: \"flag_review\", winning_variant: null, factor_verdicts: factorVerdicts };\n }\n\n const winningVariant = [...winningVariants][0];\n return { action: \"conclude\", winning_variant: winningVariant, factor_verdicts: factorVerdicts };\n}\n\nfunction buildEmptyVerdict(): GovernanceVerdict {\n return { action: \"continue\", winning_variant: null, factor_verdicts: [] };\n}\n","import type { SupabaseClient } from \"@supabase/supabase-js\";\nimport { evaluateExperimentThresholds, concludeExperiment } from \"./governance.js\";\nimport type { GovernanceVerdict } from \"./governance.js\";\n\n/**\n * Logs a governance verdict to the append-only audit log.\n */\nexport async function logGovernanceVerdict(\n client: SupabaseClient,\n experimentId: string,\n verdict: GovernanceVerdict,\n): Promise<void> {\n const { error } = await client\n .from(\"governance_log\")\n .insert({\n experiment_id: experimentId,\n verdict: verdict.action,\n winning_variant: verdict.winning_variant,\n factor_verdicts: verdict.factor_verdicts,\n });\n\n if (error) throw new Error(`logGovernanceVerdict failed: ${error.message}`);\n}\n\n/**\n * Orchestrator: evaluates governance thresholds, logs the verdict,\n * and auto-concludes if there's a clear winner.\n * Mirrors SQL cron evaluate_governance() but callable from TypeScript.\n */\nexport async function runGovernanceCheck(\n client: SupabaseClient,\n experimentId: string,\n factorNames: string[],\n): Promise<GovernanceVerdict> {\n const verdict = await evaluateExperimentThresholds(client, experimentId, factorNames);\n await logGovernanceVerdict(client, experimentId, verdict);\n await concludeIfWinner(client, experimentId, verdict);\n\n return verdict;\n}\n\nasync function concludeIfWinner(\n client: SupabaseClient,\n experimentId: string,\n verdict: GovernanceVerdict,\n): Promise<void> {\n if (verdict.action === \"conclude\" && verdict.winning_variant) {\n await concludeExperiment(client, experimentId, verdict.winning_variant);\n }\n}\n","import type { SupabaseClient } from \"@supabase/supabase-js\";\n\nexport interface ExperimentSummaryRow {\n experiment_id: string;\n name: string;\n component_path: string;\n status: string;\n winning_variant: string | null;\n created_at: string;\n concluded_at: string | null;\n variant_key: string;\n traffic_percentage: number;\n assigned_users: number;\n exposed_users: number;\n}\n\nexport interface ExperimentSummaryFilters {\n status?: string;\n component_path?: string;\n created_after?: string;\n created_before?: string;\n}\n\n/**\n * Queries all experiment summaries from the governor dashboard view.\n * Each row is one variant of one experiment with assignment/exposure counts.\n */\nexport async function queryExperimentSummaries(\n client: SupabaseClient,\n filters?: ExperimentSummaryFilters,\n): Promise<ExperimentSummaryRow[]> {\n let query = client\n .from(\"v_experiment_summary\")\n .select(\"*\");\n\n query = applyFilters(query, filters);\n\n const { data, error } = await query;\n if (error) throw new Error(`queryExperimentSummaries failed: ${error.message}`);\n return (data ?? []) as ExperimentSummaryRow[];\n}\n\n/**\n * Queries a single experiment's summary rows (one per variant).\n */\nexport async function queryExperimentSummary(\n client: SupabaseClient,\n experimentId: string,\n): Promise<ExperimentSummaryRow[]> {\n const { data, error } = await client\n .from(\"v_experiment_summary\")\n .select(\"*\")\n .eq(\"experiment_id\", experimentId);\n\n if (error) throw new Error(`queryExperimentSummary failed: ${error.message}`);\n return (data ?? []) as ExperimentSummaryRow[];\n}\n\ntype SupabaseQuery = ReturnType<ReturnType<SupabaseClient[\"from\"]>[\"select\"]>;\n\nfunction applyFilters(\n query: SupabaseQuery,\n filters?: ExperimentSummaryFilters,\n): SupabaseQuery {\n if (!filters) return query;\n\n if (filters.status) {\n query = query.eq(\"status\", filters.status);\n }\n if (filters.component_path) {\n query = query.eq(\"component_path\", filters.component_path);\n }\n if (filters.created_after) {\n query = query.gte(\"created_at\", filters.created_after);\n }\n if (filters.created_before) {\n query = query.lte(\"created_at\", filters.created_before);\n }\n\n return query;\n}\n","import type { SupabaseClient } from \"@supabase/supabase-js\";\nimport type { GovernanceAction, FactorVerdict } from \"./governance.js\";\n\nexport interface GovernanceLogRow {\n id: string;\n experiment_id: string;\n verdict: GovernanceAction;\n winning_variant: string | null;\n factor_verdicts: FactorVerdict[];\n evaluated_at: string;\n}\n\nconst GOVERNANCE_LOG_COLUMNS =\n \"id, experiment_id, verdict, winning_variant, factor_verdicts, evaluated_at\";\n\n/**\n * Queries all governance evaluations for a single experiment,\n * ordered by most recent first.\n */\nexport async function queryGovernanceLog(\n client: SupabaseClient,\n experimentId: string,\n): Promise<GovernanceLogRow[]> {\n const { data, error } = await client\n .from(\"governance_log\")\n .select(GOVERNANCE_LOG_COLUMNS)\n .eq(\"experiment_id\", experimentId)\n .order(\"evaluated_at\", { ascending: false });\n\n if (error) throw new Error(`queryGovernanceLog failed: ${error.message}`);\n return (data ?? []) as GovernanceLogRow[];\n}\n\n/**\n * Queries the most recent governance evaluations across all experiments.\n * Defaults to 50 rows.\n */\nexport async function queryRecentGovernanceLog(\n client: SupabaseClient,\n limit = 50,\n): Promise<GovernanceLogRow[]> {\n const { data, error } = await client\n .from(\"governance_log\")\n .select(GOVERNANCE_LOG_COLUMNS)\n .order(\"evaluated_at\", { ascending: false })\n .limit(limit);\n\n if (error) throw new Error(`queryRecentGovernanceLog failed: ${error.message}`);\n return (data ?? []) as GovernanceLogRow[];\n}\n\n/**\n * Queries governance evaluations filtered by verdict type\n * (conclude, flag_review, continue).\n */\nexport async function queryGovernanceLogByVerdict(\n client: SupabaseClient,\n verdict: GovernanceAction,\n): Promise<GovernanceLogRow[]> {\n const { data, error } = await client\n .from(\"governance_log\")\n .select(GOVERNANCE_LOG_COLUMNS)\n .eq(\"verdict\", verdict)\n .order(\"evaluated_at\", { ascending: false });\n\n if (error) throw new Error(`queryGovernanceLogByVerdict failed: ${error.message}`);\n return (data ?? []) as GovernanceLogRow[];\n}\n","import type { Spec, SpecNode, SpecNodeType } from \"./spec-types.js\";\nimport { RENDERER_VERSION } from \"./spec-types.js\";\n\n/**\n * Validates an Spec for structural correctness and renderer compatibility.\n * Returns a list of errors. Empty list = valid spec.\n */\n\nconst VALID_TYPES: ReadonlySet<SpecNodeType> = new Set([\n \"column\", \"row\", \"stack\", \"scrollview\", \"grid\",\n \"text\", \"image\", \"icon\", \"divider\", \"spacer\",\n \"textinput\", \"button\", \"toggle\", \"select\", \"slider\",\n \"card\", \"list\", \"tabs\", \"modal\", \"chip\",\n]);\n\nconst MAX_TREE_DEPTH = 20;\n\nexport function validateSpec(spec: Spec): string[] {\n const errors: string[] = [];\n\n validateEnvelope(spec, errors);\n validateNodeTree(spec.root, errors, 0);\n validateUniqueIds(spec.root, errors);\n\n return errors;\n}\n\nfunction validateEnvelope(spec: Spec, errors: string[]): void {\n if (typeof spec.spec_version !== \"number\" || spec.spec_version < 1) {\n errors.push(\"spec_version must be a positive integer\");\n }\n if (typeof spec.renderer_min !== \"number\" || spec.renderer_min < 1) {\n errors.push(\"renderer_min must be a positive integer\");\n }\n if (spec.renderer_min > RENDERER_VERSION) {\n errors.push(\n `spec requires renderer_min ${spec.renderer_min} but installed renderer is ${RENDERER_VERSION}`,\n );\n }\n if (!spec.root) {\n errors.push(\"spec must have a root node\");\n }\n}\n\nfunction validateNodeTree(node: SpecNode, errors: string[], depth: number): void {\n if (depth > MAX_TREE_DEPTH) {\n errors.push(`node \"${node.id}\" exceeds max tree depth of ${MAX_TREE_DEPTH}`);\n return;\n }\n\n validateNodeStructure(node, errors);\n validateBindingRefs(node, errors, depth);\n\n if (node.children) {\n for (const child of node.children) {\n validateNodeTree(child, errors, depth + 1);\n }\n }\n}\n\nfunction validateNodeStructure(node: SpecNode, errors: string[]): void {\n if (!node.id || typeof node.id !== \"string\") {\n errors.push(\"every node must have a string id\");\n }\n if (!VALID_TYPES.has(node.type)) {\n errors.push(`node \"${node.id}\" has unknown type \"${node.type}\"`);\n }\n if (node.action && typeof node.action.action !== \"string\") {\n errors.push(`node \"${node.id}\" has action without a name`);\n }\n}\n\nfunction validateBindingRefs(node: SpecNode, errors: string[], depth: number): void {\n if (node.visible && !isValidBindingRef(node.visible)) {\n errors.push(`node \"${node.id}\" visible must be a binding ref like \"{flag.name}\"`);\n }\n\n if (node.props) {\n for (const [key, value] of Object.entries(node.props)) {\n if (isSpecNode(value)) {\n validateNodeTree(value, errors, depth + 1);\n } else {\n validatePropValue(node.id, key, value, errors);\n }\n }\n }\n}\n\nfunction isSpecNode(value: unknown): value is SpecNode {\n return typeof value === \"object\" && value !== null && \"id\" in value && \"type\" in value;\n}\n\nfunction validatePropValue(\n nodeId: string,\n key: string,\n value: unknown,\n errors: string[],\n): void {\n if (typeof value === \"string\" && value.includes(\"{\") && !isValidBindingRef(value)) {\n errors.push(`node \"${nodeId}\" prop \"${key}\" has malformed binding ref \"${value}\"`);\n }\n}\n\nfunction isValidBindingRef(value: string): boolean {\n if (!value.startsWith(\"{\") || !value.endsWith(\"}\")) return false;\n const path = value.slice(1, -1);\n return /^[a-zA-Z_][a-zA-Z0-9_.]*$/.test(path);\n}\n\nfunction validateUniqueIds(root: SpecNode, errors: string[]): void {\n const ids = new Set<string>();\n collectDuplicateIds(root, ids, errors);\n}\n\nfunction collectDuplicateIds(\n node: SpecNode,\n seen: Set<string>,\n errors: string[],\n): void {\n if (seen.has(node.id)) {\n errors.push(`duplicate node id \"${node.id}\"`);\n }\n seen.add(node.id);\n\n if (node.children) {\n for (const child of node.children) {\n collectDuplicateIds(child, seen, errors);\n }\n }\n\n if (node.props) {\n for (const value of Object.values(node.props)) {\n if (isSpecNode(value)) {\n collectDuplicateIds(value, seen, errors);\n }\n }\n }\n}\n","import type { DataSourceRegistry, DataSourceConfig } from \"./spec-types.js\";\n\n/**\n * Resolves data sources for spec rendering.\n * Each source has a fetch function, optional cache policy, and optional realtime flag.\n * Offline: serves cached data if available, empty object if not.\n */\n\nexport interface ResolvedSources {\n sources: Record<string, unknown>;\n errors: Record<string, string>;\n}\n\nexport interface DataSourceCache {\n load(key: string): Promise<unknown | null>;\n save(key: string, data: unknown): Promise<void>;\n}\n\nexport async function resolveAllSources(\n registry: DataSourceRegistry,\n cache: DataSourceCache,\n): Promise<ResolvedSources> {\n const sourceEntries = Object.entries(registry);\n const results = await Promise.allSettled(\n sourceEntries.map(([name, config]) => resolveSource(name, config, cache)),\n );\n\n return assembleResults(sourceEntries, results);\n}\n\nasync function resolveSource(\n name: string,\n config: DataSourceConfig,\n cache: DataSourceCache,\n): Promise<{ name: string; data: unknown }> {\n const cached = config.cache === \"local\" ? await cache.load(name) : null;\n\n try {\n const fresh = await config.fetch();\n const data = applyMaxItems(fresh, config.maxItems);\n\n if (config.cache === \"local\") {\n await cache.save(name, data);\n }\n\n return { name, data };\n } catch {\n if (cached != null) {\n return { name, data: cached };\n }\n throw new Error(`source \"${name}\" fetch failed and no cache available`);\n }\n}\n\nfunction applyMaxItems(data: unknown, maxItems?: number): unknown {\n if (!maxItems || !Array.isArray(data)) return data;\n return data.slice(0, maxItems);\n}\n\nfunction assembleResults(\n entries: [string, DataSourceConfig][],\n results: PromiseSettledResult<{ name: string; data: unknown }>[],\n): ResolvedSources {\n const sources: Record<string, unknown> = {};\n const errors: Record<string, string> = {};\n\n for (let i = 0; i < entries.length; i++) {\n const [name] = entries[i];\n const result = results[i];\n\n if (result.status === \"fulfilled\") {\n sources[name] = result.value.data;\n } else {\n errors[name] = result.reason?.message ?? \"unknown error\";\n sources[name] = null;\n }\n }\n\n return { sources, errors };\n}\n","/**\n * Binding resolution: resolves \"{path.to.value}\" references against a data context.\n * Pure functions. No side effects. No expressions — single-level path lookup only.\n */\n\nconst BINDING_PATTERN = /^\\{([a-zA-Z_][a-zA-Z0-9_.]*)\\}$/;\nconst INLINE_BINDING_PATTERN = /\\{([a-zA-Z_][a-zA-Z0-9_.]*)\\}/g;\n\nexport function isBindingRef(value: string): boolean {\n return BINDING_PATTERN.test(value);\n}\n\nexport function resolveBinding(ref: string, context: Record<string, unknown>): unknown {\n const match = ref.match(BINDING_PATTERN);\n if (!match) return ref;\n return resolvePath(match[1], context);\n}\n\nexport function resolveTextWithBindings(\n text: string,\n context: Record<string, unknown>,\n): string {\n return text.replace(INLINE_BINDING_PATTERN, (_, path: string) => {\n const value = resolvePath(path, context);\n return value != null ? String(value) : \"\";\n });\n}\n\nexport function resolveProps(\n props: Record<string, unknown>,\n context: Record<string, unknown>,\n): Record<string, unknown> {\n const resolved: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(props)) {\n resolved[key] = resolveValue(value, context);\n }\n return resolved;\n}\n\nfunction resolveValue(value: unknown, context: Record<string, unknown>): unknown {\n if (typeof value === \"string\" && value.includes(\"{\")) {\n if (isBindingRef(value)) return resolveBinding(value, context);\n return resolveTextWithBindings(value, context);\n }\n if (Array.isArray(value)) return value.map((v) => resolveValue(v, context));\n if (typeof value === \"object\" && value !== null) {\n return resolveProps(value as Record<string, unknown>, context);\n }\n return value;\n}\n\nfunction resolvePath(path: string, context: Record<string, unknown>): unknown {\n const segments = path.split(\".\");\n let current: unknown = context;\n\n for (const segment of segments) {\n if (current == null || typeof current !== \"object\") return undefined;\n current = (current as Record<string, unknown>)[segment];\n }\n\n return current;\n}\n","import type { ActionRef, ActionRegistry } from \"./spec-types.js\";\nimport { resolveProps } from \"./binding.js\";\n\n/**\n * Dispatches named actions from spec nodes.\n * Actions are defined by the host app, not the spec.\n * The spec references actions by name; this module resolves and invokes them.\n */\n\nexport function dispatchAction(\n actionRef: ActionRef,\n registry: ActionRegistry,\n context: Record<string, unknown>,\n): void {\n const handler = registry[actionRef.action];\n if (!handler) {\n console.warn(`factoredui: unknown action \"${actionRef.action}\"`);\n return;\n }\n\n const resolvedParams = actionRef.params\n ? resolveProps(actionRef.params as Record<string, unknown>, context)\n : {};\n\n Promise.resolve(handler(resolvedParams)).catch((err) => {\n console.error(`factoredui: action \"${actionRef.action}\" failed:`, err);\n });\n}\n","import type { SupabaseClient } from \"@supabase/supabase-js\";\nimport type { Spec, SignedSpec } from \"./spec-types.js\";\nimport { RENDERER_VERSION } from \"./spec-types.js\";\nimport { validateSpec } from \"./spec-validator.js\";\n\n/**\n * Spec loading: baseline (bundled) → active (local storage) → remote (Supabase).\n * Signature verification is required. Fail closed on invalid signatures.\n *\n * The host app provides:\n * - baselineSpec: bundled in the APK/IPA at build time\n * - loadActive/saveActive: local storage for the current active spec\n * - verifySignature: Ed25519 verification against embedded public key\n */\n\nexport interface SpecStorage {\n loadActive(): Promise<SignedSpec | null>;\n saveActive(signed: SignedSpec): Promise<void>;\n}\n\nexport interface SignatureVerifier {\n verify(specHash: string, signature: string): Promise<boolean>;\n computeHash(spec: Spec): Promise<string>;\n}\n\nexport interface LoadedSpec {\n spec: Spec;\n source: \"remote\" | \"active\" | \"baseline\";\n}\n\nexport async function loadSpec(\n supabase: SupabaseClient,\n platform: string,\n baseline: Spec,\n storage: SpecStorage,\n verifier: SignatureVerifier,\n): Promise<LoadedSpec> {\n const remote = await fetchRemoteSpec(supabase, platform);\n if (remote) {\n const validated = await validateSignedSpec(remote, verifier);\n if (validated) {\n await storage.saveActive(remote);\n return { spec: remote.spec, source: \"remote\" };\n }\n }\n\n const active = await loadActiveSpec(storage);\n if (active) {\n const validated = await validateSignedSpec(active, verifier);\n if (validated) {\n return { spec: active.spec, source: \"active\" };\n }\n }\n\n return { spec: baseline, source: \"baseline\" };\n}\n\nasync function validateSignedSpec(\n signed: SignedSpec,\n verifier: SignatureVerifier,\n): Promise<boolean> {\n const hashMatches = await verifySpecHash(signed, verifier);\n if (!hashMatches) return false;\n\n const signatureValid = await verifier.verify(signed.spec_hash, signed.signature);\n if (!signatureValid) return false;\n\n if (signed.spec.renderer_min > RENDERER_VERSION) return false;\n\n const schemaErrors = validateSpec(signed.spec);\n return schemaErrors.length === 0;\n}\n\nasync function verifySpecHash(\n signed: SignedSpec,\n verifier: SignatureVerifier,\n): Promise<boolean> {\n const computedHash = await verifier.computeHash(signed.spec);\n return computedHash === signed.spec_hash;\n}\n\nasync function fetchRemoteSpec(\n supabase: SupabaseClient,\n platform: string,\n): Promise<SignedSpec | null> {\n try {\n const { data, error } = await supabase\n .from(\"ui_active\")\n .select(\"spec_id, ui_specs(*)\")\n .eq(\"platform\", platform)\n .single();\n\n if (error || !data) return null;\n\n return mapRowToSignedSpec(data);\n } catch {\n return null;\n }\n}\n\nfunction mapRowToSignedSpec(data: unknown): SignedSpec {\n const row = data as {\n spec_id: string;\n ui_specs: {\n component_tree: unknown;\n spec_version: number;\n renderer_min: number;\n spec_hash: string;\n signature: string;\n };\n };\n\n return {\n spec: {\n spec_version: row.ui_specs.spec_version,\n renderer_min: row.ui_specs.renderer_min,\n root: row.ui_specs.component_tree as Spec[\"root\"],\n },\n signature: row.ui_specs.signature,\n signed_at: \"\",\n spec_hash: row.ui_specs.spec_hash,\n };\n}\n\nasync function loadActiveSpec(\n storage: SpecStorage,\n): Promise<SignedSpec | null> {\n try {\n return await storage.loadActive();\n } catch {\n return null;\n }\n}\n","import type { Spec, SignedSpec } from \"./spec-types.js\";\nimport type { SpecStorage, SignatureVerifier } from \"./spec-loader.js\";\nimport type { DataSourceCache } from \"./data-source.js\";\n\n/**\n * Generic key-value storage interface.\n * AsyncStorage (RN), localStorage (web), or any compatible backend.\n */\nexport interface KVStorage {\n getItem(key: string): Promise<string | null> | string | null;\n setItem(key: string, value: string): Promise<void> | void;\n removeItem(key: string): Promise<void> | void;\n}\n\n/**\n * Creates a SpecStorage backed by any KV store.\n * Stores the active signed spec as JSON under a single key.\n */\nexport function createSpecStorage(kv: KVStorage, prefix = \"factoredui\"): SpecStorage {\n const key = `${prefix}:active-spec`;\n\n return {\n async loadActive(): Promise<SignedSpec | null> {\n const raw = await kv.getItem(key);\n if (!raw) return null;\n return JSON.parse(raw) as SignedSpec;\n },\n\n async saveActive(signed: SignedSpec): Promise<void> {\n await kv.setItem(key, JSON.stringify(signed));\n },\n };\n}\n\n/**\n * Creates a DataSourceCache backed by any KV store.\n * Caches resolved source data for offline rendering.\n */\nexport function createDataSourceCache(kv: KVStorage, prefix = \"factoredui\"): DataSourceCache {\n const keyPrefix = `${prefix}:source:`;\n\n return {\n async load(sourceKey: string): Promise<unknown | null> {\n const raw = await kv.getItem(keyPrefix + sourceKey);\n if (!raw) return null;\n return JSON.parse(raw);\n },\n\n async save(sourceKey: string, data: unknown): Promise<void> {\n await kv.setItem(keyPrefix + sourceKey, JSON.stringify(data));\n },\n };\n}\n\n/**\n * Dev-only signature verifier. Always passes.\n * Replace with Ed25519 verification before OTA spec delivery.\n */\nexport const devSignatureVerifier: SignatureVerifier = {\n async verify(_specHash: string, _signature: string): Promise<boolean> {\n return true;\n },\n\n async computeHash(spec: Spec): Promise<string> {\n const json = JSON.stringify(spec);\n let hash = 0;\n for (let i = 0; i < json.length; i++) {\n const char = json.charCodeAt(i);\n hash = ((hash << 5) - hash + char) | 0;\n }\n return `dev:${hash.toString(16)}`;\n },\n};\n","import type { Spec } from \"./spec-types.js\";\nimport type { SignatureVerifier } from \"./spec-loader.js\";\n\n/**\n * Creates an Ed25519 signature verifier for client-side spec validation.\n * Public key is embedded in the APK/IPA at build time.\n *\n * Uses Web Crypto API (Ed25519 supported in Node 20+, Chrome 113+, Deno).\n */\nexport function createEd25519Verifier(publicKeyBase64: string): SignatureVerifier {\n let cachedKey: CryptoKey | null = null;\n\n async function importPublicKey(): Promise<CryptoKey> {\n if (cachedKey) return cachedKey;\n\n const keyBuffer = base64ToBytes(publicKeyBase64);\n cachedKey = await crypto.subtle.importKey(\n \"raw\",\n keyBuffer,\n { name: \"Ed25519\" },\n false,\n [\"verify\"],\n );\n return cachedKey;\n }\n\n return {\n async verify(specHash: string, signature: string): Promise<boolean> {\n const key = await importPublicKey();\n const signatureBuffer = base64ToBytes(signature);\n const hashBytes = new TextEncoder().encode(specHash);\n\n return crypto.subtle.verify(\"Ed25519\", key, signatureBuffer, hashBytes);\n },\n\n async computeHash(spec: Spec): Promise<string> {\n return computeSpecHash(spec);\n },\n };\n}\n\n/**\n * Ed25519 spec signer for server-side spec publishing.\n * Signs spec_hash + monotonic version + renderer_min + timestamp.\n */\nexport interface SpecSigner {\n signSpec(spec: Spec): Promise<{ spec_hash: string; signature: string; signed_at: string }>;\n}\n\nexport function createEd25519Signer(privateKeyBase64: string): SpecSigner {\n let cachedKey: CryptoKey | null = null;\n\n async function importPrivateKey(): Promise<CryptoKey> {\n if (cachedKey) return cachedKey;\n\n const keyBuffer = base64ToBytes(privateKeyBase64);\n cachedKey = await crypto.subtle.importKey(\n \"pkcs8\",\n keyBuffer,\n { name: \"Ed25519\" },\n false,\n [\"sign\"],\n );\n return cachedKey;\n }\n\n return {\n async signSpec(spec: Spec) {\n const specHash = await computeSpecHash(spec);\n const key = await importPrivateKey();\n const hashBytes = new TextEncoder().encode(specHash);\n const signatureBytes = await crypto.subtle.sign(\"Ed25519\", key, hashBytes);\n const signature = bytesToBase64(new Uint8Array(signatureBytes));\n const signedAt = new Date().toISOString();\n\n return { spec_hash: specHash, signature, signed_at: signedAt };\n },\n };\n}\n\n/**\n * Generates an Ed25519 keypair for initial setup.\n * Returns base64-encoded public and private keys.\n */\nexport async function generateEd25519Keypair(): Promise<{\n publicKey: string;\n privateKey: string;\n}> {\n const keypair = await crypto.subtle.generateKey(\"Ed25519\", true, [\"sign\", \"verify\"]);\n\n const publicKeyBytes = await crypto.subtle.exportKey(\"raw\", keypair.publicKey);\n const privateKeyBytes = await crypto.subtle.exportKey(\"pkcs8\", keypair.privateKey);\n\n return {\n publicKey: bytesToBase64(new Uint8Array(publicKeyBytes)),\n privateKey: bytesToBase64(new Uint8Array(privateKeyBytes)),\n };\n}\n\nasync function computeSpecHash(spec: Spec): Promise<string> {\n const json = JSON.stringify(spec);\n const bytes = new TextEncoder().encode(json);\n const hashBuffer = await crypto.subtle.digest(\"SHA-256\", bytes);\n return bytesToHex(new Uint8Array(hashBuffer));\n}\n\nfunction base64ToBytes(base64: string): Uint8Array<ArrayBuffer> {\n const binary = atob(base64);\n const buffer = new ArrayBuffer(binary.length);\n const bytes = new Uint8Array(buffer);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return bytes;\n}\n\nfunction bytesToBase64(bytes: Uint8Array): string {\n let binary = \"\";\n for (let i = 0; i < bytes.length; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return btoa(binary);\n}\n\nfunction bytesToHex(bytes: Uint8Array): string {\n const hexChars: string[] = [];\n for (let i = 0; i < bytes.length; i++) {\n hexChars.push(bytes[i].toString(16).padStart(2, \"0\"));\n }\n return hexChars.join(\"\");\n}\n"],"mappings":"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","names":["resolveUserId"]}
|