import { configureDevelopmentRuntimeBridge, createFeltDB } from '@feltdb/core'; configureDevelopmentRuntimeBridge({ sessionId: import.meta.env.VITE_FELTDB_DEV_SESSION_ID, workspaceId: import.meta.env.VITE_FELTDB_WORKSPACE_ID, namespace: import.meta.env.VITE_FELTDB_NAMESPACE, runtime: import.meta.env.VITE_FELTDB_RUNTIME, authorityUrl: import.meta.env.VITE_FELTDB_AUTHORITY_URL, bridgeUrl: import.meta.env.VITE_FELTDB_DEV_BRIDGE_URL, applicationUrl: import.meta.env.VITE_FELTDB_APPLICATION_URL, }); export const managedRuntime = Boolean(import.meta.env.VITE_FELTDB_MANAGED_URL); export const db = createFeltDB(managedRuntime ? { namespace: import.meta.env.VITE_FELTDB_MANAGED_NAMESPACE || 'feltdb-starter', server: { url: import.meta.env.VITE_FELTDB_MANAGED_URL, applicationId: import.meta.env.VITE_FELTDB_MANAGED_APPLICATION_ID, environment: import.meta.env.VITE_FELTDB_MANAGED_ENVIRONMENT || 'production', }, } : { namespace: import.meta.env.VITE_FELTDB_NAMESPACE || 'feltdb-starter', browser: true }); export interface User { id: string; email: string; name: string; created_at: string } export interface Organization { id: string; name: string; created_at: string } export interface Membership { id: string; user: string; organization: string; role: 'owner' | 'member' | 'viewer'; created_at: string } export interface Session { id: string; user: string; expires_at: string; created_at: string } export interface Project { id: string; organization: string; name: string; description: string; owner_id: string; created_at: string; updated_at: string } export interface Invitation { id: string; organization: string; user: string; email: string; role: string; status: string; created_at: string; updated_at: string } export interface AuditEvent { id: string; organization: string; user: string; action: string; resource_type: string; resource_id: string; details: string; created_at: string } export interface Team { id: string; organization: string; name: string; description: string; owner: string; created_at: string; updated_at: string } export interface TeamMembership { id: string; organization: string; team: string; user: string; role: string; created_at: string; updated_at: string } export const users = db.collection('User'); export const organizations = db.collection('Organization'); export const memberships = db.collection('Membership'); export const sessions = db.collection('Session'); export const projects = db.collection('Project'); export const invitations = db.collection('Invitation'); export const auditEvents = db.collection('AuditEvent'); export const teams = db.collection('Team'); export const teamMemberships = db.collection('TeamMembership'); const makeId = (prefix: string) => `${prefix}_${crypto.randomUUID()}`; export async function createAccount(input: { name: string; email: string; organization: string }) { const email = input.email.trim().toLowerCase(); if ((await users.find({ email })).length) throw new Error('An account already exists for that email.'); const now = new Date().toISOString(); const user: User = { id: makeId('user'), email, name: input.name.trim(), created_at: now }; const organization: Organization = { id: makeId('org'), name: input.organization.trim(), created_at: now }; const membership: Membership = { id: makeId('membership'), user: user.id, organization: organization.id, role: 'owner', created_at: now }; const session: Session = { id: makeId('session'), user: user.id, created_at: now, expires_at: new Date(Date.now() + 86_400_000).toISOString() }; const event: AuditEvent = { id: makeId('event'), organization: organization.id, user: user.id, action: 'account.created', resource_type: 'User', resource_id: user.id, details: 'Initial organization and owner membership created', created_at: now }; await db.transaction(async transaction => { transaction.collection('User').insert(user, user.id, { requireAbsent: true }); transaction.collection('Organization').insert(organization, organization.id, { requireAbsent: true }); transaction.collection('Membership').insert(membership, membership.id, { requireAbsent: true }); transaction.collection('Session').insert(session, session.id, { requireAbsent: true }); transaction.collection('AuditEvent').insert(event, event.id, { requireAbsent: true }); }, { transactionId: makeId('signup') }); return session; } export async function createSession(emailInput: string) { const user = (await users.find({ email: emailInput.trim().toLowerCase() }))[0]; if (!user) throw new Error('Account not found.'); const now = new Date().toISOString(); const session: Session = { id: makeId('session'), user: user.id, created_at: now, expires_at: new Date(Date.now() + 86_400_000).toISOString() }; await sessions.insert(session, session.id); return session; } export async function createProject(input: { organization: string; owner: string; name: string }) { const now = new Date().toISOString(); const project: Project = { id: makeId('project'), organization: input.organization, owner_id: input.owner, name: input.name.trim(), description: '', created_at: now, updated_at: now }; const event: AuditEvent = { id: makeId('event'), organization: input.organization, user: input.owner, action: 'project.created', resource_type: 'Project', resource_id: project.id, details: project.name, created_at: now }; await db.transaction(async transaction => { transaction.collection('Project').insert(project, project.id, { requireAbsent: true }); transaction.collection('AuditEvent').insert(event, event.id, { requireAbsent: true }); }); } export async function recordAgentActivity(input: { organization: string; user: string; assistant: string; subject: string }) { const event: AuditEvent = { id: makeId('event'), organization: input.organization, user: input.user, action: 'agent.summary', resource_type: 'AgentExecution', resource_id: input.subject, details: `${input.assistant} summarized authorized application state`, created_at: new Date().toISOString() }; await auditEvents.insert(event, event.id); return event; }