@happyvertical/smrt-app-runtime 0.43.9

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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["/**\n * Safe, private, single-owner application runtime for the `local` profile.\n *\n * This Node-only subpath owns the small amount of operational composition that\n * does not belong in a generated application: user-owned paths, restrictive\n * local secret material, SQLite tuning, owner bootstrap, and an optional\n * embedded job runner. Domain schema preparation remains an explicit startup\n * step supplied by the application migration layer.\n */\n\nimport { execFile } from 'node:child_process';\nimport { createHash, createHmac, randomBytes } from 'node:crypto';\nimport {\n constants,\n type FileHandle,\n link,\n lstat,\n mkdir,\n open,\n readdir,\n realpath,\n rmdir,\n unlink,\n} from 'node:fs/promises';\nimport { homedir, platform } from 'node:os';\nimport { isAbsolute, parse, relative, resolve, sep } from 'node:path';\nimport { promisify } from 'node:util';\nimport { Worker } from 'node:worker_threads';\nimport {\n type ResolvedApplicationRuntime,\n type RuntimeProviderOverrides,\n resolveApplicationRuntime,\n} from '@happyvertical/smrt-config';\nimport { TaskRunner, type TaskRunnerConfig } from '@happyvertical/smrt-jobs';\nimport { Person, ProfileTypeCollection } from '@happyvertical/smrt-profiles';\nimport { withSystemContext } from '@happyvertical/smrt-tenancy';\nimport {\n DEFAULT_ROLE_SLUGS,\n MembershipCollection,\n MembershipStatus,\n RoleCollection,\n SessionCollection,\n SessionService,\n TenantService,\n UserCollection,\n UserStatus,\n} from '@happyvertical/smrt-users';\nimport { type DatabaseInterface, getDatabase } from '@happyvertical/sql';\n\nconst DEFAULT_BIND_HOST = '127.0.0.1';\nconst DEFAULT_BOOTSTRAP_TTL_SECONDS = 10 * 60;\nconst MAX_BOOTSTRAP_TTL_SECONDS = 15 * 60;\nconst DEFAULT_SESSION_TTL_SECONDS = 7 * 24 * 60 * 60;\nconst BOOTSTRAP_TABLE = '_smrt_local_owner_bootstrap';\nconst SECRET_FILE_NAME = 'application.secret';\nconst DATABASE_FILE_NAME = 'application.sqlite';\nconst ROOT_MARKER_PREFIX = '.smrt-local-runtime-';\nconst PREFLIGHT_RETRY_LIMIT = 4;\nconst INITIALIZATION_LOCK_TIMEOUT_MS = 120_000;\nconst INITIALIZATION_LOCK_WORKER = `\n const { parentPort, workerData } = require('node:worker_threads');\n let database;\n let transaction;\n (async () => {\n try {\n const { getDatabase } = await import(workerData.sqlModuleUrl);\n database = await getDatabase({\n type: 'sqlite',\n url: workerData.path,\n secureFile: {\n driver: 'node:sqlite',\n custody: 'trusted-parent',\n root: workerData.custodyRoot,\n },\n transactionQueueTimeout: workerData.timeout,\n });\n if (!database.beginTransaction) {\n throw new Error('Secure SQLite does not expose beginTransaction().');\n }\n await database.query('PRAGMA busy_timeout = ' + workerData.timeout);\n transaction = await database.beginTransaction();\n parentPort.postMessage({ type: 'acquired' });\n } catch (error) {\n try { await database?.close?.(); } catch {}\n parentPort.postMessage({ type: 'error', message: String(error) });\n parentPort.close();\n return;\n }\n parentPort.once('message', async (message) => {\n if (message?.type !== 'release') return;\n let releaseError;\n try { await transaction.rollback(); } catch (error) { releaseError = String(error); }\n try { await database.close?.(); } catch (error) { releaseError ??= String(error); }\n parentPort.postMessage({ type: 'released', error: releaseError });\n parentPort.close();\n });\n })().catch((error) => {\n parentPort.postMessage({ type: 'error', message: String(error) });\n parentPort.close();\n });\n`;\nconst execFileAsync = promisify(execFile);\n\n/** Paths owned by the local user, outside the source tree by default. */\nexport interface LocalRuntimePaths {\n readonly root: string;\n readonly database: string;\n readonly assets: string;\n readonly secrets: string;\n readonly applicationSecret: string;\n}\n\nexport interface ResolveLocalRuntimePathsOptions {\n /** Stable application identifier, e.g. `lolaus`. */\n appId: string;\n /** Explicit user-owned data directory. Defaults to the OS application-data directory. */\n dataDirectory?: string;\n /** Source checkout to protect from accidental data placement. Defaults to cwd. */\n sourceRoot?: string;\n /** Testable default-root and filesystem case-sensitivity override. */\n platform?: NodeJS.Platform;\n /** Testable home-directory override. */\n homeDirectory?: string;\n /** Testable environment override. */\n env?: NodeJS.ProcessEnv;\n}\n\nexport interface LocalApplicationRuntimeOptions\n extends ResolveLocalRuntimePathsOptions {\n /** Actual HTTP bind host. Owner bootstrap refuses non-loopback values. */\n bindHost?: string;\n /**\n * Explicit application migration/schema hook, invoked before identity access.\n * It must be idempotent; runtime code never synthesizes application tables.\n */\n prepareDatabase?: (db: DatabaseInterface) => Promise<void>;\n /** Local profile provider overrides (only validated local combinations survive). */\n providers?: RuntimeProviderOverrides;\n /** Short-lived bootstrap token lifetime. Range: 1..900 seconds. */\n bootstrapTtlSeconds?: number;\n /** Normal authenticated session lifetime in whole seconds. Minimum 1. */\n sessionTtlSeconds?: number;\n /** Explicit opt-in for persisted background work. Default false. */\n backgroundJobs?: boolean;\n /** Explicit opt-in for application-defined paid capabilities. Default false. */\n paidCapabilities?: boolean;\n /** Testable clock. */\n now?: () => Date;\n}\n\nexport interface LocalOwnerBootstrapInvitation {\n /** Plaintext is returned exactly when a new claim is issued; it is never persisted. */\n readonly token: string;\n readonly expiresAt: string;\n}\n\nexport interface LocalRuntimeInitialization {\n readonly runtime: LocalApplicationRuntime;\n readonly bootstrap: LocalOwnerBootstrapInvitation | null;\n readonly diagnostics: LocalRuntimeDiagnostics;\n}\n\nexport interface ClaimLocalOwnerInput {\n token: string;\n name: string;\n email: string;\n tenantName?: string;\n userAgent?: string;\n ipAddress?: string;\n}\n\nexport interface LocalOwnerClaimResult {\n readonly profileId: string;\n readonly userId: string;\n readonly tenantId: string;\n readonly membershipId: string;\n readonly sessionId: string;\n}\n\nexport type LocalBootstrapStatus =\n | 'available'\n | 'expired'\n | 'claimed'\n | 'unavailable';\n\n/** Secret-free, machine-readable local runtime state. */\nexport interface LocalRuntimeDiagnostics {\n readonly schemaVersion: 1;\n readonly runtime: ResolvedApplicationRuntime;\n readonly bind: {\n readonly host: string;\n readonly loopback: true;\n };\n readonly paths: LocalRuntimePaths;\n readonly storage: {\n readonly database: 'sqlite-file';\n readonly assets: 'user-owned-directory';\n readonly secrets: 'mode-0600-local-file';\n };\n readonly bootstrap: {\n readonly status: LocalBootstrapStatus;\n readonly expiresAt: string | null;\n readonly tokenValuesIncluded: false;\n readonly tokenHashesIncluded: false;\n };\n readonly tenancy: {\n readonly mode: 'real-default-tenant';\n readonly ui: 'hidden';\n };\n readonly jobs: {\n readonly topology: 'inline' | 'embedded';\n readonly backgroundEnabled: boolean;\n };\n readonly paidCapabilitiesEnabled: boolean;\n readonly secretValuesIncluded: false;\n}\n\nexport type LocalRuntimeErrorCode =\n | 'bootstrap_claimed'\n | 'bootstrap_expired'\n | 'bootstrap_invalid'\n | 'bootstrap_unavailable'\n | 'capability_disabled'\n | 'invalid_configuration'\n | 'unsafe_public_exposure';\n\n/** Stable, secret-free local-runtime failure. */\nexport class LocalRuntimeError extends Error {\n constructor(\n readonly code: LocalRuntimeErrorCode,\n message: string,\n ) {\n super(message);\n this.name = 'LocalRuntimeError';\n }\n}\n\ninterface BootstrapRow {\n expires_at?: unknown;\n consumed_at?: unknown;\n}\n\ninterface ExistingOwner {\n userId: string;\n tenantId: string;\n}\n\n/**\n * Resolve deterministic user-owned paths and reject source-tree placement.\n */\nexport function resolveLocalRuntimePaths(\n options: ResolveLocalRuntimePathsOptions,\n): LocalRuntimePaths {\n const appId = normalizeAppId(options.appId);\n const runtimePlatform = options.platform ?? platform();\n const runtimeHome = options.homeDirectory ?? homedir();\n const env = options.env ?? process.env;\n const defaultRoot = defaultApplicationDataRoot(\n runtimePlatform,\n runtimeHome,\n env,\n );\n const root = resolve(options.dataDirectory ?? resolve(defaultRoot, appId));\n const sourceRoot = resolve(options.sourceRoot ?? process.cwd());\n\n if (\n sameFilesystemPath(root, runtimeHome, runtimePlatform) ||\n sameFilesystemPath(root, parse(root).root, runtimePlatform) ||\n isInside(sourceRoot, root, runtimePlatform) ||\n isInside(root, sourceRoot, runtimePlatform)\n ) {\n throw new LocalRuntimeError(\n 'invalid_configuration',\n 'Local application data must be a dedicated directory that does not overlap the source tree.',\n );\n }\n\n return Object.freeze({\n root,\n database: resolve(root, DATABASE_FILE_NAME),\n assets: resolve(root, 'assets'),\n secrets: resolve(root, 'secrets'),\n applicationSecret: resolve(root, 'secrets', SECRET_FILE_NAME),\n });\n}\n\n/**\n * Initialize or reopen a local application runtime.\n *\n * A plaintext bootstrap token is returned only when this call creates a new\n * invitation. Existing unexpired invitations remain valid but cannot be read\n * back because only their HMAC is stored.\n */\nexport async function initializeLocalApplicationRuntime(\n options: LocalApplicationRuntimeOptions,\n): Promise<LocalRuntimeInitialization> {\n const bindHost = normalizeLoopbackHost(options.bindHost ?? DEFAULT_BIND_HOST);\n const bootstrapTtlSeconds = validateBootstrapTtl(\n options.bootstrapTtlSeconds ?? DEFAULT_BOOTSTRAP_TTL_SECONDS,\n );\n const sessionTtlSeconds = validateSessionTtl(\n options.sessionTtlSeconds ?? DEFAULT_SESSION_TTL_SECONDS,\n );\n const resolvedRuntime = resolveApplicationRuntime({\n profile: 'local',\n providers: options.providers,\n });\n const paths = resolveLocalRuntimePaths(options);\n const sourceRoot = resolve(options.sourceRoot ?? process.cwd());\n const appId = normalizeAppId(options.appId);\n await preflightLocalApplicationRoot(paths.root, sourceRoot, appId);\n const initializationLock = await acquireInitializationLock(paths.root);\n let db: DatabaseInterface | undefined;\n let initialization: LocalRuntimeInitialization | undefined;\n let initializationFailure: unknown;\n let initializationFailed = false;\n try {\n await preflightLocalApplicationRoot(paths.root, sourceRoot, appId);\n const acquired = await acquireLocalDatabase(paths, sourceRoot, appId);\n db = acquired.db;\n const { canonicalSourceRoot } = acquired;\n await prepareLocalFilesystem(paths, canonicalSourceRoot);\n await tuneLocalSqlite(db);\n await options.prepareDatabase?.(db);\n await ensureBootstrapTable(db);\n\n const runtime = new InitializedLocalApplicationRuntime({\n db,\n paths,\n bindHost,\n resolvedRuntime,\n bootstrapTtlSeconds,\n sessionTtlSeconds,\n backgroundJobs: options.backgroundJobs === true,\n paidCapabilities: options.paidCapabilities === true,\n now: options.now ?? (() => new Date()),\n canonicalSourceRoot,\n });\n const bootstrap = await runtime.ensureBootstrapInvitation();\n initialization = {\n runtime,\n bootstrap,\n diagnostics: await runtime.diagnostics(),\n };\n } catch (error) {\n initializationFailed = true;\n initializationFailure = db\n ? await closeDatabaseAfterFailure(db, error)\n : error;\n db = undefined;\n }\n\n try {\n await initializationLock.release();\n } catch (releaseError) {\n if (initializationFailed) {\n initializationFailure = preservePrimaryFailure(\n initializationFailure,\n releaseError,\n 'initializationLockReleaseError',\n 'Local runtime initialization and initialization-lock release both failed.',\n );\n } else if (db) {\n initializationFailed = true;\n initializationFailure = await closeDatabaseAfterFailure(db, releaseError);\n db = undefined;\n } else {\n initializationFailed = true;\n initializationFailure = releaseError;\n }\n }\n\n if (initializationFailed) throw initializationFailure;\n if (!initialization) {\n throw new Error('Local runtime initialization completed without a result.');\n }\n return initialization;\n}\n\ninterface LocalApplicationRuntimeState {\n db: DatabaseInterface;\n paths: LocalRuntimePaths;\n bindHost: string;\n resolvedRuntime: ResolvedApplicationRuntime;\n bootstrapTtlSeconds: number;\n sessionTtlSeconds: number;\n backgroundJobs: boolean;\n paidCapabilities: boolean;\n now: () => Date;\n canonicalSourceRoot: string;\n}\n\n/** Initialized local runtime used by server startup and onboarding handlers. */\nexport interface LocalApplicationRuntime {\n readonly db: DatabaseInterface;\n readonly paths: LocalRuntimePaths;\n readonly bindHost: string;\n readonly resolvedRuntime: ResolvedApplicationRuntime;\n readonly backgroundJobsEnabled: boolean;\n readonly paidCapabilitiesEnabled: boolean;\n ensureBootstrapInvitation(): Promise<LocalOwnerBootstrapInvitation | null>;\n rotateBootstrapInvitation(): Promise<LocalOwnerBootstrapInvitation>;\n claimOwner(input: ClaimLocalOwnerInput): Promise<LocalOwnerClaimResult>;\n restoreSession(\n sessionId: string,\n ): ReturnType<SessionService['loadSessionContext']>;\n createEmbeddedJobRunner(config?: TaskRunnerConfig): Promise<TaskRunner>;\n diagnostics(): Promise<LocalRuntimeDiagnostics>;\n}\n\nclass InitializedLocalApplicationRuntime implements LocalApplicationRuntime {\n readonly db: DatabaseInterface;\n readonly paths: LocalRuntimePaths;\n readonly bindHost: string;\n readonly resolvedRuntime: ResolvedApplicationRuntime;\n readonly backgroundJobsEnabled: boolean;\n readonly paidCapabilitiesEnabled: boolean;\n private readonly bootstrapTtlSeconds: number;\n private readonly sessionTtlSeconds: number;\n private readonly now: () => Date;\n private readonly canonicalSourceRoot: string;\n\n constructor(state: LocalApplicationRuntimeState) {\n this.db = state.db;\n this.paths = state.paths;\n this.bindHost = state.bindHost;\n this.resolvedRuntime = state.resolvedRuntime;\n this.bootstrapTtlSeconds = state.bootstrapTtlSeconds;\n this.sessionTtlSeconds = state.sessionTtlSeconds;\n this.backgroundJobsEnabled = state.backgroundJobs;\n this.paidCapabilitiesEnabled = state.paidCapabilities;\n this.now = state.now;\n this.canonicalSourceRoot = state.canonicalSourceRoot;\n }\n\n /**\n * Issue the first short-lived owner invitation when none is active.\n * Repeated startup never rotates an unexpired token or duplicates an owner.\n */\n async ensureBootstrapInvitation(): Promise<LocalOwnerBootstrapInvitation | null> {\n if (await findExistingOwner(this.db)) return null;\n const current = await readBootstrapRow(this.db);\n if (current?.consumed_at != null) return null;\n const now = this.now();\n const currentExpiry = parseStoredDate(current?.expires_at);\n if (\n current &&\n current.consumed_at == null &&\n currentExpiry !== null &&\n currentExpiry.getTime() > now.getTime()\n ) {\n return null;\n }\n return this.issueBootstrapInvitation(false);\n }\n\n /** Explicit recovery when an installer lost the one-time plaintext token. */\n async rotateBootstrapInvitation(): Promise<LocalOwnerBootstrapInvitation> {\n if (await findExistingOwner(this.db)) {\n throw new LocalRuntimeError(\n 'bootstrap_claimed',\n 'The local owner has already been claimed.',\n );\n }\n if ((await readBootstrapRow(this.db))?.consumed_at != null) {\n throw new LocalRuntimeError(\n 'bootstrap_claimed',\n 'The local owner bootstrap invitation has already been consumed.',\n );\n }\n const invitation = await this.issueBootstrapInvitation(true);\n if (!invitation) {\n if ((await readBootstrapRow(this.db))?.consumed_at != null) {\n throw new LocalRuntimeError(\n 'bootstrap_claimed',\n 'The local owner bootstrap invitation has already been consumed.',\n );\n }\n throw new LocalRuntimeError(\n 'bootstrap_unavailable',\n 'A local owner bootstrap invitation could not be issued.',\n );\n }\n return invitation;\n }\n\n /**\n * Consume a bootstrap token and atomically create normal identity/RBAC/session\n * records. The token transition and every record write share one transaction.\n */\n async claimOwner(\n input: ClaimLocalOwnerInput,\n ): Promise<LocalOwnerClaimResult> {\n validateOwnerInput(input);\n if (await findExistingOwner(this.db)) {\n throw new LocalRuntimeError(\n 'bootstrap_claimed',\n 'The local owner has already been claimed.',\n );\n }\n if (typeof this.db.transaction !== 'function') {\n throw new LocalRuntimeError(\n 'bootstrap_unavailable',\n 'Owner bootstrap requires a database adapter with transaction support.',\n );\n }\n\n const tokenHash = await this.hashBootstrapToken(input.token);\n const now = this.now();\n const nowIso = now.toISOString();\n return this.db.transaction(async (tx) => {\n const claimed = await tx.query(\n `UPDATE ${BOOTSTRAP_TABLE}\n SET consumed_at = ?\n WHERE slot = 1\n AND token_hash = ?\n AND consumed_at IS NULL\n AND expires_at > ?\n RETURNING expires_at`,\n nowIso,\n tokenHash,\n nowIso,\n );\n if (claimed.rows.length === 0) {\n await throwBootstrapClaimFailure(tx, now);\n }\n\n const concurrentOwner = await findExistingOwner(tx);\n if (concurrentOwner) {\n throw new LocalRuntimeError(\n 'bootstrap_claimed',\n 'The local owner has already been claimed.',\n );\n }\n\n return createLocalOwnerRecords(tx, input, this.sessionTtlSeconds);\n });\n }\n\n /** Restore the normal server-side session created by owner bootstrap. */\n async restoreSession(sessionId: string) {\n const service = new SessionService({ db: this.db });\n await service.initialize();\n return service.loadSessionContext(sessionId);\n }\n\n /**\n * Create an in-process persisted-job runner. Background work is default-off\n * and must be explicitly enabled by runtime configuration.\n */\n async createEmbeddedJobRunner(\n config: TaskRunnerConfig = {},\n ): Promise<TaskRunner> {\n if (!this.backgroundJobsEnabled) {\n throw new LocalRuntimeError(\n 'capability_disabled',\n 'Background jobs are disabled; enable them explicitly for this local application.',\n );\n }\n if (this.resolvedRuntime.providers.jobs.topology !== 'embedded') {\n throw new LocalRuntimeError(\n 'invalid_configuration',\n 'An embedded runner requires the local embedded job topology.',\n );\n }\n const runner = new TaskRunner({\n concurrency: 1,\n retention: false,\n ...config,\n });\n await runner.initialize(this.db);\n return runner;\n }\n\n /** Return a deterministic snapshot that never reads secret file contents. */\n async diagnostics(): Promise<LocalRuntimeDiagnostics> {\n const owner = await findExistingOwner(this.db);\n const bootstrap = await readBootstrapRow(this.db);\n const now = this.now();\n const expiresAt = parseStoredDate(bootstrap?.expires_at);\n let status: LocalBootstrapStatus = 'unavailable';\n if (owner || bootstrap?.consumed_at != null) status = 'claimed';\n else if (expiresAt && expiresAt.getTime() > now.getTime())\n status = 'available';\n else if (expiresAt) status = 'expired';\n\n return Object.freeze({\n schemaVersion: 1,\n runtime: this.resolvedRuntime,\n bind: Object.freeze({ host: this.bindHost, loopback: true as const }),\n paths: this.paths,\n storage: Object.freeze({\n database: 'sqlite-file' as const,\n assets: 'user-owned-directory' as const,\n secrets: 'mode-0600-local-file' as const,\n }),\n bootstrap: Object.freeze({\n status,\n expiresAt: expiresAt?.toISOString() ?? null,\n tokenValuesIncluded: false as const,\n tokenHashesIncluded: false as const,\n }),\n tenancy: Object.freeze({\n mode: 'real-default-tenant' as const,\n ui: 'hidden' as const,\n }),\n jobs: Object.freeze({\n topology: this.resolvedRuntime.providers.jobs.topology as\n | 'inline'\n | 'embedded',\n backgroundEnabled: this.backgroundJobsEnabled,\n }),\n paidCapabilitiesEnabled: this.paidCapabilitiesEnabled,\n secretValuesIncluded: false as const,\n });\n }\n\n private async issueBootstrapInvitation(\n replaceActive: boolean,\n ): Promise<LocalOwnerBootstrapInvitation | null> {\n const token = randomBytes(32).toString('base64url');\n const tokenHash = await this.hashBootstrapToken(token);\n const now = this.now();\n const expiresAt = new Date(now.getTime() + this.bootstrapTtlSeconds * 1000);\n const stored = await this.db.query(\n `INSERT INTO ${BOOTSTRAP_TABLE}\n (slot, token_hash, expires_at, consumed_at, created_at)\n VALUES (1, ?, ?, NULL, ?)\n ON CONFLICT(slot) DO UPDATE SET\n token_hash = excluded.token_hash,\n expires_at = excluded.expires_at,\n consumed_at = NULL,\n created_at = excluded.created_at\n WHERE ${BOOTSTRAP_TABLE}.consumed_at IS NULL\n AND (? = 1 OR ${BOOTSTRAP_TABLE}.expires_at <= ?)\n RETURNING token_hash`,\n tokenHash,\n expiresAt.toISOString(),\n now.toISOString(),\n replaceActive ? 1 : 0,\n now.toISOString(),\n );\n const persistedHash = (\n stored.rows[0] as { token_hash?: unknown } | undefined\n )?.token_hash;\n if (persistedHash !== tokenHash) return null;\n return Object.freeze({ token, expiresAt: expiresAt.toISOString() });\n }\n\n private async hashBootstrapToken(token: string): Promise<string> {\n const secret = await validateApplicationSecret(\n this.paths.applicationSecret,\n this.canonicalSourceRoot,\n );\n return createHmac('sha256', secret.trim()).update(token).digest('hex');\n }\n}\n\nasync function createLocalOwnerRecords(\n db: DatabaseInterface,\n input: ClaimLocalOwnerInput,\n sessionTtlSeconds: number,\n): Promise<LocalOwnerClaimResult> {\n const profileTypes = await ProfileTypeCollection.create({ db });\n const personType = await withSystemContext(() =>\n profileTypes.getOrCreateGlobalBySlug('person', {\n name: 'Person',\n description: 'An individual person',\n }),\n );\n const person = new Person({\n db,\n typeId: requireId(personType.id, 'Person profile type'),\n tenantId: null,\n name: input.name.trim(),\n email: input.email.trim(),\n });\n await person.initialize();\n await person.save();\n\n const users = await UserCollection.create({ db });\n const user = await users.create({\n profileId: requireId(person.id, 'Person'),\n email: input.email.trim(),\n status: UserStatus.ACTIVE,\n lastLoginAt: new Date(),\n });\n await user.save();\n\n const tenantService = new TenantService(\n { db },\n {\n mode: 'required',\n maxTenants: 1,\n defaultName: input.tenantName?.trim() || 'My Workspace',\n },\n );\n await tenantService.initialize();\n const { tenant, membership } = await tenantService.createTenantWithOwnership(\n requireId(user.id, 'User'),\n input.tenantName?.trim() || 'My Workspace',\n { slug: 'default' },\n );\n\n const sessions = await SessionCollection.create({ db });\n const session = await sessions.createSession({\n userId: requireId(user.id, 'User'),\n tenantId: requireId(tenant.id, 'Tenant'),\n ttl: sessionTtlSeconds,\n userAgent: input.userAgent,\n ipAddress: input.ipAddress,\n data: { localOwner: true },\n });\n\n return Object.freeze({\n profileId: requireId(person.id, 'Person'),\n userId: requireId(user.id, 'User'),\n tenantId: requireId(tenant.id, 'Tenant'),\n membershipId: requireId(membership.id, 'Membership'),\n sessionId: requireId(session.id, 'Session'),\n });\n}\n\nasync function findExistingOwner(\n db: DatabaseInterface,\n): Promise<ExistingOwner | null> {\n const roles = await RoleCollection.create({ db });\n const ownerRole = await roles.findSystemRoleBySlug(DEFAULT_ROLE_SLUGS.OWNER);\n if (!ownerRole?.id) return null;\n const memberships = await MembershipCollection.create({ db });\n const ownerMemberships = await memberships.findByRole(ownerRole.id);\n const active = ownerMemberships.find(\n (membership) =>\n membership.status === MembershipStatus.ACTIVE &&\n typeof membership.userId === 'string' &&\n typeof membership.tenantId === 'string',\n );\n return active\n ? { userId: active.userId as string, tenantId: active.tenantId as string }\n : null;\n}\n\nasync function throwBootstrapClaimFailure(\n db: DatabaseInterface,\n now: Date,\n): Promise<never> {\n const row = await readBootstrapRow(db);\n if (!row) {\n throw new LocalRuntimeError(\n 'bootstrap_unavailable',\n 'No local owner bootstrap invitation is available.',\n );\n }\n if (row.consumed_at != null) {\n throw new LocalRuntimeError(\n 'bootstrap_claimed',\n 'The local owner bootstrap invitation has already been consumed.',\n );\n }\n const expiresAt = parseStoredDate(row.expires_at);\n if (!expiresAt || expiresAt.getTime() <= now.getTime()) {\n throw new LocalRuntimeError(\n 'bootstrap_expired',\n 'The local owner bootstrap invitation has expired.',\n );\n }\n throw new LocalRuntimeError(\n 'bootstrap_invalid',\n 'The local owner bootstrap token is invalid.',\n );\n}\n\nasync function readBootstrapRow(\n db: DatabaseInterface,\n): Promise<BootstrapRow | null> {\n const result = await db.query(\n `SELECT expires_at, consumed_at\n FROM ${BOOTSTRAP_TABLE}\n WHERE slot = 1\n LIMIT 1`,\n );\n return (result.rows[0] as BootstrapRow | undefined) ?? null;\n}\n\nasync function ensureBootstrapTable(db: DatabaseInterface): Promise<void> {\n await db.query(\n `CREATE TABLE IF NOT EXISTS ${BOOTSTRAP_TABLE} (\n slot INTEGER PRIMARY KEY CHECK (slot = 1),\n token_hash TEXT NOT NULL,\n expires_at TEXT NOT NULL,\n consumed_at TEXT NULL,\n created_at TEXT NOT NULL\n )`,\n );\n}\n\nasync function tuneLocalSqlite(db: DatabaseInterface): Promise<void> {\n await db.query('PRAGMA foreign_keys = ON');\n await db.query('PRAGMA journal_mode = WAL');\n await db.query('PRAGMA synchronous = FULL');\n await db.query('PRAGMA busy_timeout = 5000');\n}\n\ninterface PreparedLocalRoot {\n createdDirectories: string[];\n pendingMarker: string | null;\n pendingMarkerCreatedByAttempt: boolean;\n finalMarker: string;\n}\n\ninterface LocalInitializationLock {\n release(): Promise<void>;\n}\n\nasync function preflightLocalApplicationRoot(\n root: string,\n sourceRoot: string,\n appId: string,\n): Promise<void> {\n for (let attempt = 0; attempt < PREFLIGHT_RETRY_LIMIT; attempt += 1) {\n try {\n await preflightLocalApplicationRootOnce(root, sourceRoot, appId);\n return;\n } catch (error) {\n if (!isMissingFile(error) && !hasMissingFileCause(error)) throw error;\n if (attempt === PREFLIGHT_RETRY_LIMIT - 1) {\n throw unsafeFilesystemEntry(\n 'Local application data changed repeatedly during read-only preflight.',\n error,\n );\n }\n await new Promise<void>((resolveRetry) => setImmediate(resolveRetry));\n }\n }\n}\n\nasync function preflightLocalApplicationRootOnce(\n root: string,\n sourceRoot: string,\n appId: string,\n): Promise<void> {\n requireNoFollowSupport();\n const canonicalSourceRoot = await realpath(sourceRoot);\n const currentUid = process.getuid?.();\n if (currentUid === undefined) {\n throw unsafeFilesystemEntry(\n 'Local runtime storage requires a numeric current-user identity.',\n );\n }\n if (\n isInside(canonicalSourceRoot, root) ||\n isInside(root, canonicalSourceRoot)\n ) {\n throw unsafeFilesystemEntry(\n 'Local application data must remain outside the canonical source tree.',\n );\n }\n\n let rootExists = true;\n for (const component of absolutePathComponents(root)) {\n let details: Awaited<ReturnType<typeof lstat>>;\n try {\n details = await lstat(component);\n } catch (error) {\n if (!isMissingFile(error)) throw error;\n rootExists = false;\n break;\n }\n if (details.isSymbolicLink() || !details.isDirectory()) {\n throw unsafeFilesystemEntry(\n `Local runtime path component must be a real directory: ${component}`,\n );\n }\n await assertCanonicalEntry(component, canonicalSourceRoot);\n const sharedStickyRoot = details.uid === 0 && (details.mode & 0o1000) !== 0;\n if (\n (details.uid !== currentUid && details.uid !== 0) ||\n ((details.mode & 0o022) !== 0 && !sharedStickyRoot)\n ) {\n throw unsafeFilesystemEntry(\n `Local runtime path ancestry does not have trusted-parent custody: ${component}`,\n );\n }\n await assertNoPermissiveDarwinAcl(component);\n }\n\n if (!rootExists) return;\n const rootDetails = await lstat(root);\n if (rootDetails.uid !== currentUid || (rootDetails.mode & 0o777) !== 0o700) {\n throw unsafeFilesystemEntry(\n `Existing local application data root must already be owned by the current user with mode 0700: ${root}`,\n );\n }\n await preflightDedicatedRoot(root, canonicalSourceRoot, appId);\n}\n\nasync function preflightDedicatedRoot(\n root: string,\n canonicalSourceRoot: string,\n appId: string,\n): Promise<void> {\n const finalMarker = resolve(root, `${ROOT_MARKER_PREFIX}${appId}`);\n const pendingMarker = resolve(root, `${ROOT_MARKER_PREFIX}${appId}.pending`);\n const entries = await readdir(root);\n const finalMarkerName = finalMarker.slice(root.length + 1);\n const pendingMarkerName = pendingMarker.slice(root.length + 1);\n const hasFinalMarker = entries.includes(finalMarkerName);\n const hasPendingMarker = entries.includes(pendingMarkerName);\n\n if (hasFinalMarker) {\n await validateRootMarker(finalMarker, canonicalSourceRoot);\n if (hasPendingMarker) {\n await validateRootMarker(pendingMarker, canonicalSourceRoot);\n }\n return;\n }\n if (hasPendingMarker) {\n await validateRootMarker(pendingMarker, canonicalSourceRoot);\n const permittedInterruptedEntries = new Set([\n pendingMarkerName,\n DATABASE_FILE_NAME,\n `${DATABASE_FILE_NAME}-shm`,\n `${DATABASE_FILE_NAME}-wal`,\n ]);\n if (entries.some((entry) => !permittedInterruptedEntries.has(entry))) {\n throw unsafeFilesystemEntry(\n 'Interrupted local application root contains unexpected artifacts.',\n );\n }\n return;\n }\n if (entries.length > 0) {\n throw unsafeFilesystemEntry(\n 'Existing local application data root is populated but has no valid ownership marker.',\n );\n }\n}\n\nasync function assertNoPermissiveDarwinAcl(path: string): Promise<void> {\n if (platform() !== 'darwin') return;\n let listing: string;\n try {\n const result = await execFileAsync('/bin/ls', ['-lde', '--', path], {\n encoding: 'utf8',\n env: { ...process.env, LC_ALL: 'C' },\n });\n listing = result.stdout;\n } catch (error) {\n throw unsafeFilesystemEntry(\n `Local runtime could not inspect macOS access controls: ${path}`,\n error,\n );\n }\n for (const line of listing.split('\\n')) {\n if (!/^\\s*\\d+:/.test(line)) continue;\n const entry = line.match(/^\\s*\\d+:\\s+.+\\s+(allow|deny)\\s+\\S.*$/);\n if (entry?.[1] !== 'deny') {\n throw unsafeFilesystemEntry(\n `Local runtime path contains a permissive macOS access control list: ${path}`,\n );\n }\n }\n}\n\nasync function acquireLocalDatabase(\n paths: LocalRuntimePaths,\n sourceRoot: string,\n appId: string,\n): Promise<{\n canonicalSourceRoot: string;\n db: DatabaseInterface;\n}> {\n requireNoFollowSupport();\n const canonicalSourceRoot = await realpath(sourceRoot);\n const createdDirectories = await ensureSafeDirectoryTree(\n paths.root,\n canonicalSourceRoot,\n true,\n );\n const prepared = await prepareDedicatedRoot(\n paths.root,\n canonicalSourceRoot,\n appId,\n createdDirectories,\n );\n let db: DatabaseInterface;\n try {\n db = await getDatabase({\n type: 'sqlite',\n url: paths.database,\n secureFile: {\n driver: 'node:sqlite',\n custody: 'trusted-parent',\n root: paths.root,\n },\n });\n } catch (error) {\n if (prepared.pendingMarkerCreatedByAttempt) {\n await removeMarkerIfPresent(prepared.pendingMarker, canonicalSourceRoot);\n await removeCreatedDirectories(createdDirectories);\n }\n throw error;\n }\n\n // Once SQLite acquisition succeeds, the database is an authoritative\n // artifact. Keep the pending marker through every promotion failure so a\n // later startup can resume rather than seeing an unmarked populated root.\n try {\n await publishRootMarker(prepared.finalMarker, canonicalSourceRoot);\n await removeMarkerIfPresent(prepared.pendingMarker, canonicalSourceRoot);\n } catch (error) {\n throw await closeDatabaseAfterFailure(db, error);\n }\n return { canonicalSourceRoot, db };\n}\n\nasync function closeDatabaseAfterFailure(\n db: DatabaseInterface,\n primaryFailure: unknown,\n): Promise<unknown> {\n try {\n await db.close?.();\n } catch (cleanupFailure) {\n return preservePrimaryFailure(\n primaryFailure,\n cleanupFailure,\n 'databaseCleanupError',\n 'Local runtime initialization and database cleanup both failed.',\n );\n }\n return primaryFailure;\n}\n\nfunction preservePrimaryFailure(\n primaryFailure: unknown,\n secondaryFailure: unknown,\n secondaryProperty: string,\n aggregateMessage: string,\n): unknown {\n if (primaryFailure instanceof Error) {\n try {\n Object.defineProperty(primaryFailure, secondaryProperty, {\n value: secondaryFailure,\n configurable: true,\n });\n } catch {\n // A frozen application error must remain primary even when secondary\n // failure context cannot be attached to it.\n }\n return primaryFailure;\n }\n return new AggregateError(\n [primaryFailure, secondaryFailure],\n aggregateMessage,\n );\n}\n\nasync function prepareLocalFilesystem(\n paths: LocalRuntimePaths,\n canonicalSourceRoot: string,\n): Promise<void> {\n await ensureSafeDirectoryTree(paths.assets, canonicalSourceRoot);\n await ensureSafeDirectoryTree(paths.secrets, canonicalSourceRoot);\n await ensureApplicationSecret(paths.applicationSecret, canonicalSourceRoot);\n}\n\nasync function prepareDedicatedRoot(\n path: string,\n canonicalSourceRoot: string,\n appId: string,\n createdDirectories: string[],\n): Promise<PreparedLocalRoot> {\n const finalMarker = resolve(path, `${ROOT_MARKER_PREFIX}${appId}`);\n const pendingMarker = resolve(path, `${ROOT_MARKER_PREFIX}${appId}.pending`);\n const entries = await readdir(path);\n const hasFinalMarker = entries.includes(finalMarker.slice(path.length + 1));\n const hasPendingMarker = entries.includes(\n pendingMarker.slice(path.length + 1),\n );\n\n if (hasFinalMarker) {\n await validateRootMarker(finalMarker, canonicalSourceRoot);\n if (hasPendingMarker) {\n await validateRootMarker(pendingMarker, canonicalSourceRoot);\n }\n return {\n createdDirectories,\n pendingMarker: hasPendingMarker ? pendingMarker : null,\n pendingMarkerCreatedByAttempt: false,\n finalMarker,\n };\n }\n\n if (hasPendingMarker) {\n await validateRootMarker(pendingMarker, canonicalSourceRoot);\n const permittedInterruptedEntries = new Set([\n pendingMarker.slice(path.length + 1),\n DATABASE_FILE_NAME,\n `${DATABASE_FILE_NAME}-shm`,\n `${DATABASE_FILE_NAME}-wal`,\n ]);\n if (entries.some((entry) => !permittedInterruptedEntries.has(entry))) {\n throw unsafeFilesystemEntry(\n 'Interrupted local application root contains unexpected artifacts.',\n );\n }\n return {\n createdDirectories,\n pendingMarker,\n pendingMarkerCreatedByAttempt: false,\n finalMarker,\n };\n }\n\n if (entries.length > 0) {\n throw unsafeFilesystemEntry(\n 'Existing local application data root is populated but has no valid ownership marker.',\n );\n }\n const pendingMarkerCreatedByAttempt = await publishRootMarker(\n pendingMarker,\n canonicalSourceRoot,\n );\n return {\n createdDirectories,\n pendingMarker,\n pendingMarkerCreatedByAttempt,\n finalMarker,\n };\n}\n\nasync function acquireInitializationLock(\n root: string,\n): Promise<LocalInitializationLock> {\n const currentUid = process.getuid?.();\n if (currentUid === undefined) {\n throw unsafeFilesystemEntry(\n 'Local runtime initialization locks require a numeric current-user identity.',\n );\n }\n const canonicalTemporaryRoot = await realpath('/tmp');\n const lockRoot = resolve(canonicalTemporaryRoot, `.smrt-${currentUid}`);\n try {\n await mkdir(lockRoot, { mode: 0o700 });\n } catch (error) {\n if (!isFileAlreadyExists(error)) throw error;\n }\n const lockRootDetails = await lstat(lockRoot);\n if (\n !lockRootDetails.isDirectory() ||\n lockRootDetails.isSymbolicLink() ||\n lockRootDetails.uid !== currentUid ||\n (lockRootDetails.mode & 0o777) !== 0o700\n ) {\n throw unsafeFilesystemEntry(\n `Local runtime lock directory must be current-user-owned with mode 0700: ${lockRoot}`,\n );\n }\n const lockKey = createHash('sha256')\n .update(normalizeFilesystemIdentity(root))\n .digest('hex')\n .slice(0, 32);\n const custodyRoot = resolve(lockRoot, lockKey);\n try {\n await mkdir(custodyRoot, { mode: 0o700 });\n } catch (error) {\n if (!isFileAlreadyExists(error)) throw error;\n }\n const path = resolve(custodyRoot, 'initialization.sqlite');\n return acquireInitializationDatabaseLease(path, custodyRoot);\n}\n\nasync function acquireInitializationDatabaseLease(\n path: string,\n custodyRoot: string,\n): Promise<LocalInitializationLock> {\n const worker = new Worker(INITIALIZATION_LOCK_WORKER, {\n eval: true,\n workerData: {\n path,\n custodyRoot,\n timeout: INITIALIZATION_LOCK_TIMEOUT_MS,\n sqlModuleUrl: import.meta.resolve('@happyvertical/sql'),\n },\n });\n const acquisitionFailure = (cause: unknown) => {\n const failure = new LocalRuntimeError(\n 'invalid_configuration',\n 'Could not acquire the local runtime initialization lease within two minutes.',\n );\n Object.defineProperty(failure, 'cause', { value: cause });\n return failure;\n };\n let workerError: unknown;\n const exited = new Promise<never>((_resolve, reject) => {\n worker.once('error', (error) => {\n workerError = error;\n });\n worker.once('exit', (code) => {\n reject(\n acquisitionFailure(\n workerError ??\n new Error(`Initialization lock worker exited ${code}.`),\n ),\n );\n });\n });\n const acquired = new Promise<void>((resolvePromise, reject) => {\n const onMessage = (message: { type?: string; message?: string }) => {\n if (message.type === 'acquired') {\n worker.off('message', onMessage);\n resolvePromise();\n } else if (message.type === 'error') {\n worker.off('message', onMessage);\n reject(acquisitionFailure(new Error(message.message)));\n }\n };\n worker.on('message', onMessage);\n });\n await Promise.race([acquired, exited]);\n\n let released = false;\n return {\n release: async () => {\n if (released) return;\n released = true;\n const releaseCompleted = new Promise<void>((resolvePromise, reject) => {\n const onMessage = (message: { type?: string; error?: string }) => {\n if (message.type !== 'released') return;\n worker.off('message', onMessage);\n if (message.error) reject(new Error(message.error));\n else resolvePromise();\n };\n worker.on('message', onMessage);\n worker.postMessage({ type: 'release' });\n });\n try {\n await Promise.race([releaseCompleted, exited]);\n } finally {\n await worker.terminate();\n }\n },\n };\n}\n\nasync function ensureSafeDirectoryTree(\n path: string,\n canonicalSourceRoot: string,\n dedicatedRoot = false,\n): Promise<string[]> {\n const components = absolutePathComponents(path);\n const createdDirectories: string[] = [];\n for (const component of components) {\n let created = false;\n try {\n const details = await lstat(component);\n if (details.isSymbolicLink() || !details.isDirectory()) {\n throw unsafeFilesystemEntry(\n `Local runtime path component must be a real directory: ${component}`,\n );\n }\n } catch (error) {\n if (!isMissingFile(error)) throw error;\n try {\n await mkdir(component, { mode: 0o700 });\n created = true;\n createdDirectories.push(component);\n } catch (mkdirError) {\n // A concurrent initializer may have created the component. It is still\n // opened and validated without following links below.\n if (!isFileAlreadyExists(mkdirError)) throw mkdirError;\n }\n }\n\n const directory = await openSafeDirectory(component, canonicalSourceRoot);\n try {\n await assertCanonicalEntry(component, canonicalSourceRoot);\n if (component === path && dedicatedRoot && !created) {\n await assertExistingDedicatedRoot(\n directory,\n component,\n canonicalSourceRoot,\n );\n }\n if (created || (component === path && !dedicatedRoot)) {\n await directory.chmod(0o700);\n }\n } finally {\n await directory.close();\n }\n }\n await validateExistingPathChain(path, canonicalSourceRoot, 'directory');\n return createdDirectories;\n}\n\nasync function assertExistingDedicatedRoot(\n directory: FileHandle,\n path: string,\n canonicalSourceRoot: string,\n): Promise<void> {\n const canonical = await realpath(path);\n if (\n isInside(canonicalSourceRoot, canonical) ||\n isInside(canonical, canonicalSourceRoot)\n ) {\n throw unsafeFilesystemEntry(\n 'Local application data must be a dedicated directory that does not overlap the canonical source tree.',\n );\n }\n\n const details = await directory.stat();\n const currentUid = process.getuid?.();\n if (\n currentUid === undefined ||\n details.uid !== currentUid ||\n (details.mode & 0o777) !== 0o700\n ) {\n throw unsafeFilesystemEntry(\n `Existing local application data root must already be owned by the current user with mode 0700: ${path}`,\n );\n }\n}\n\nasync function publishRootMarker(\n path: string,\n canonicalSourceRoot: string,\n): Promise<boolean> {\n let marker: FileHandle | undefined;\n let created = false;\n try {\n marker = await openSafeFile(\n path,\n constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL,\n 0o600,\n 'Local application root marker',\n canonicalSourceRoot,\n );\n created = true;\n await marker.sync();\n } catch (error) {\n if (!isFileAlreadyExists(error)) throw error;\n } finally {\n await marker?.close();\n }\n await validateRootMarker(path, canonicalSourceRoot);\n await syncDirectory(resolve(path, '..'), canonicalSourceRoot);\n return created;\n}\n\nasync function validateRootMarker(\n path: string,\n canonicalSourceRoot: string,\n): Promise<void> {\n await validateExistingPathChain(path, canonicalSourceRoot, 'file');\n const marker = await openSafeFile(\n path,\n constants.O_RDONLY,\n 0o600,\n 'Local application root marker',\n canonicalSourceRoot,\n );\n try {\n const details = await marker.stat();\n const currentUid = process.getuid?.();\n if (\n currentUid === undefined ||\n details.uid !== currentUid ||\n (details.mode & 0o777) !== 0o600 ||\n details.size !== 0\n ) {\n throw unsafeFilesystemEntry(\n `Local application root marker must be an empty current-user-owned mode-0600 file: ${path}`,\n );\n }\n } finally {\n await marker.close();\n }\n}\n\nasync function removeMarkerIfPresent(\n path: string | null,\n canonicalSourceRoot: string,\n): Promise<void> {\n if (path === null) return;\n try {\n await validateRootMarker(path, canonicalSourceRoot);\n await unlink(path);\n await syncDirectory(resolve(path, '..'), canonicalSourceRoot);\n } catch (error) {\n if (!isMissingFile(error) && !hasMissingFileCause(error)) throw error;\n }\n}\n\nasync function removeCreatedDirectories(paths: string[]): Promise<void> {\n for (const path of paths.toReversed()) {\n try {\n await rmdir(path);\n } catch (error) {\n if (!isMissingFile(error) && !isDirectoryNotEmpty(error)) throw error;\n }\n }\n}\n\nasync function ensureApplicationSecret(\n path: string,\n canonicalSourceRoot: string,\n): Promise<void> {\n const directoryPath = resolve(path, '..');\n const temporaryPath = resolve(\n directoryPath,\n `.${SECRET_FILE_NAME}.tmp-${randomBytes(16).toString('hex')}`,\n );\n let temporary: FileHandle | undefined;\n let failure: unknown;\n try {\n temporary = await openSafeFile(\n temporaryPath,\n constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL,\n 0o600,\n 'Temporary application secret',\n canonicalSourceRoot,\n );\n await temporary.writeFile(\n `${randomBytes(32).toString('base64url')}\\n`,\n 'utf8',\n );\n await temporary.sync();\n await temporary.close();\n temporary = undefined;\n\n try {\n await link(temporaryPath, path);\n } catch (error) {\n if (!isFileAlreadyExists(error)) throw error;\n }\n\n await validateApplicationSecret(path, canonicalSourceRoot);\n await syncDirectory(directoryPath, canonicalSourceRoot);\n } catch (error) {\n failure = error;\n }\n try {\n await temporary?.close();\n } catch (error) {\n failure ??= error;\n }\n try {\n await unlink(temporaryPath);\n } catch (error) {\n if (!isMissingFile(error)) failure ??= error;\n }\n if (failure !== undefined) throw failure;\n await removeStaleSecretTemps(directoryPath);\n}\n\nasync function validateApplicationSecret(\n path: string,\n canonicalSourceRoot: string,\n): Promise<string> {\n await validateExistingPathChain(path, canonicalSourceRoot, 'file');\n const file = await openSafeFile(\n path,\n constants.O_RDONLY,\n 0o600,\n 'Application secret',\n canonicalSourceRoot,\n );\n try {\n const details = await file.stat();\n const currentUid = process.getuid?.();\n const secret = await file.readFile('utf8');\n await validateExistingPathChain(path, canonicalSourceRoot, 'file');\n if (\n currentUid === undefined ||\n details.uid !== currentUid ||\n (details.mode & 0o777) !== 0o600 ||\n details.size !== 44 ||\n !/^[A-Za-z0-9_-]{43}\\n$/.test(secret)\n ) {\n throw unsafeFilesystemEntry(\n 'Application secret must be a complete current-user-owned mode-0600 value in the expected format.',\n );\n }\n return secret;\n } finally {\n await file.close();\n }\n}\n\nasync function syncDirectory(\n path: string,\n canonicalSourceRoot: string,\n): Promise<void> {\n const directory = await openSafeDirectory(path, canonicalSourceRoot);\n try {\n await directory.sync();\n } finally {\n await directory.close();\n }\n}\n\nasync function removeStaleSecretTemps(directoryPath: string): Promise<void> {\n const prefix = `.${SECRET_FILE_NAME}.tmp-`;\n for (const entry of await readdir(directoryPath)) {\n if (!entry.startsWith(prefix)) continue;\n try {\n await unlink(resolve(directoryPath, entry));\n } catch (error) {\n if (!isMissingFile(error)) throw error;\n }\n }\n}\n\nasync function openSafeDirectory(path: string, canonicalSourceRoot: string) {\n let directory: FileHandle | undefined;\n try {\n directory = await open(\n path,\n constants.O_RDONLY | constants.O_DIRECTORY | constants.O_NOFOLLOW,\n );\n await validateOpenHandlePath(\n directory,\n path,\n 'directory',\n canonicalSourceRoot,\n );\n return directory;\n } catch (error) {\n await directory?.close();\n if (error instanceof LocalRuntimeError) throw error;\n throw unsafeFilesystemEntry(\n `Could not safely open local runtime directory: ${path}`,\n error,\n );\n }\n}\n\nasync function openSafeFile(\n path: string,\n flags: number,\n mode: number,\n label: string,\n canonicalSourceRoot: string,\n) {\n let file: FileHandle | undefined;\n try {\n file = await open(path, flags | constants.O_NOFOLLOW, mode);\n await validateOpenHandlePath(file, path, 'file', canonicalSourceRoot);\n return file;\n } catch (error) {\n await file?.close();\n if (error instanceof LocalRuntimeError || isFileAlreadyExists(error)) {\n throw error;\n }\n throw unsafeFilesystemEntry(\n `${label} could not be opened without following symbolic links.`,\n error,\n );\n }\n}\n\nasync function validateOpenHandlePath(\n handle: FileHandle,\n path: string,\n expectedType: 'directory' | 'file',\n canonicalSourceRoot: string,\n): Promise<void> {\n const opened = await handle.stat();\n const current = await lstat(path);\n const expectedDirectory = expectedType === 'directory';\n if (\n current.isSymbolicLink() ||\n (expectedDirectory ? !opened.isDirectory() : !opened.isFile()) ||\n (expectedDirectory ? !current.isDirectory() : !current.isFile()) ||\n opened.dev !== current.dev ||\n opened.ino !== current.ino\n ) {\n throw unsafeFilesystemEntry(\n `Local runtime ${expectedType} changed while it was being opened: ${path}`,\n );\n }\n await validateExistingPathChain(path, canonicalSourceRoot, expectedType);\n const afterValidation = await lstat(path);\n if (\n afterValidation.isSymbolicLink() ||\n opened.dev !== afterValidation.dev ||\n opened.ino !== afterValidation.ino\n ) {\n throw unsafeFilesystemEntry(\n `Local runtime ${expectedType} changed during validation: ${path}`,\n );\n }\n}\n\nasync function validateExistingPathChain(\n path: string,\n canonicalSourceRoot: string,\n leafType: 'directory' | 'file',\n): Promise<void> {\n const components = absolutePathComponents(path);\n for (const [index, component] of components.entries()) {\n const details = await lstat(component);\n const expectedFile = index === components.length - 1 && leafType === 'file';\n if (\n details.isSymbolicLink() ||\n (expectedFile ? !details.isFile() : !details.isDirectory())\n ) {\n throw unsafeFilesystemEntry(\n `Local runtime path contains an unsafe component: ${component}`,\n );\n }\n await assertCanonicalEntry(component, canonicalSourceRoot);\n }\n}\n\nasync function assertCanonicalEntry(\n path: string,\n canonicalSourceRoot: string,\n): Promise<void> {\n const canonical = await realpath(path);\n if (!sameFilesystemPath(canonical, path)) {\n throw unsafeFilesystemEntry(\n `Local runtime path must not be redirected: ${path}`,\n );\n }\n if (isInside(canonicalSourceRoot, canonical)) {\n throw unsafeFilesystemEntry(\n 'Local application data must remain outside the canonical source tree.',\n );\n }\n}\n\nfunction absolutePathComponents(path: string): string[] {\n const absolute = resolve(path);\n const root = parse(absolute).root;\n const parts = absolute.slice(root.length).split(sep).filter(Boolean);\n const components = [root];\n for (const part of parts) {\n components.push(resolve(components.at(-1) as string, part));\n }\n return components;\n}\n\nfunction requireNoFollowSupport(): void {\n if (\n typeof constants.O_NOFOLLOW !== 'number' ||\n constants.O_NOFOLLOW === 0 ||\n typeof constants.O_DIRECTORY !== 'number' ||\n constants.O_DIRECTORY === 0\n ) {\n throw unsafeFilesystemEntry(\n 'This platform cannot safely initialize local storage without no-follow filesystem support.',\n );\n }\n}\n\nfunction sameFilesystemPath(\n left: string,\n right: string,\n runtimePlatform: NodeJS.Platform = platform(),\n): boolean {\n return (\n normalizeFilesystemIdentity(left, runtimePlatform) ===\n normalizeFilesystemIdentity(right, runtimePlatform)\n );\n}\n\nfunction usesCaseInsensitivePathGuards(\n runtimePlatform: NodeJS.Platform,\n): boolean {\n return runtimePlatform === 'win32' || runtimePlatform === 'darwin';\n}\n\nfunction normalizeFilesystemIdentity(\n value: string,\n runtimePlatform: NodeJS.Platform = platform(),\n): string {\n const normalized = resolve(value);\n return usesCaseInsensitivePathGuards(runtimePlatform)\n ? normalized.toLowerCase()\n : normalized;\n}\n\nfunction unsafeFilesystemEntry(message: string, cause?: unknown) {\n const error = new LocalRuntimeError('invalid_configuration', message);\n if (cause !== undefined)\n Object.defineProperty(error, 'cause', { value: cause });\n return error;\n}\n\nfunction validateBootstrapTtl(value: number): number {\n if (\n !Number.isInteger(value) ||\n value < 1 ||\n value > MAX_BOOTSTRAP_TTL_SECONDS\n ) {\n throw new LocalRuntimeError(\n 'invalid_configuration',\n `Owner bootstrap TTL must be an integer from 1 to ${MAX_BOOTSTRAP_TTL_SECONDS} seconds.`,\n );\n }\n return value;\n}\n\nfunction validateSessionTtl(value: number): number {\n if (!Number.isInteger(value) || value < 1) {\n throw new LocalRuntimeError(\n 'invalid_configuration',\n 'Session TTL must be a whole number of seconds greater than or equal to 1.',\n );\n }\n return value;\n}\n\nfunction validateOwnerInput(input: ClaimLocalOwnerInput): void {\n if (!input.token || !input.name.trim() || !input.email.trim()) {\n throw new LocalRuntimeError(\n 'bootstrap_invalid',\n 'Owner bootstrap requires a token, name, and email address.',\n );\n }\n}\n\nfunction normalizeLoopbackHost(value: string): string {\n const host = value\n .trim()\n .toLowerCase()\n .replace(/^\\[|\\]$/g, '');\n if (host === '::1') return host;\n const octets = host.split('.');\n if (\n octets.length === 4 &&\n octets.every((part) => /^\\d{1,3}$/.test(part) && Number(part) <= 255) &&\n Number(octets[0]) === 127\n ) {\n return host;\n }\n throw new LocalRuntimeError(\n 'unsafe_public_exposure',\n 'Owner bootstrap is restricted to a loopback IP literal. Use ::1 or 127.0.0.0/8.',\n );\n}\n\nfunction normalizeAppId(value: string): string {\n const appId = value.trim().toLowerCase();\n if (!/^[a-z0-9][a-z0-9.-]{0,62}$/.test(appId)) {\n throw new LocalRuntimeError(\n 'invalid_configuration',\n 'appId must contain only lowercase letters, digits, dots, or hyphens.',\n );\n }\n return appId;\n}\n\nfunction defaultApplicationDataRoot(\n runtimePlatform: NodeJS.Platform,\n runtimeHome: string,\n env: NodeJS.ProcessEnv,\n): string {\n if (runtimePlatform === 'darwin') {\n return resolve(runtimeHome, 'Library', 'Application Support');\n }\n if (runtimePlatform === 'win32') {\n return resolve(env.LOCALAPPDATA ?? env.APPDATA ?? runtimeHome);\n }\n return resolve(env.XDG_DATA_HOME ?? resolve(runtimeHome, '.local', 'share'));\n}\n\nfunction isInside(\n parent: string,\n child: string,\n runtimePlatform: NodeJS.Platform = platform(),\n): boolean {\n const normalizedParent = normalizeFilesystemIdentity(parent, runtimePlatform);\n const normalizedChild = normalizeFilesystemIdentity(child, runtimePlatform);\n const path = relative(normalizedParent, normalizedChild);\n return path === '' || (!path.startsWith('..') && !isAbsolute(path));\n}\n\nfunction parseStoredDate(value: unknown): Date | null {\n if (!(typeof value === 'string' || value instanceof Date)) return null;\n const date = value instanceof Date ? value : new Date(value);\n return Number.isNaN(date.getTime()) ? null : date;\n}\n\nfunction requireId(value: unknown, label: string): string {\n if (typeof value !== 'string' || value.length === 0) {\n throw new Error(`${label} was not persisted with an id.`);\n }\n return value;\n}\n\nfunction isMissingFile(error: unknown): boolean {\n return (\n typeof error === 'object' &&\n error !== null &&\n 'code' in error &&\n (error as { code?: unknown }).code === 'ENOENT'\n );\n}\n\nfunction hasMissingFileCause(error: unknown): boolean {\n return (\n typeof error === 'object' &&\n error !== null &&\n 'cause' in error &&\n isMissingFile((error as { cause?: unknown }).cause)\n );\n}\n\nfunction isFileAlreadyExists(error: unknown): boolean {\n return (\n typeof error === 'object' &&\n error !== null &&\n 'code' in error &&\n (error as { code?: unknown }).code === 'EEXIST'\n );\n}\n\nfunction isDirectoryNotEmpty(error: unknown): boolean {\n return (\n typeof error === 'object' &&\n error !== null &&\n 'code' in error &&\n (error as { code?: unknown }).code === 'ENOTEMPTY'\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ {
2
+ "version": "1.0.0",
3
+ "timestamp": 0,
4
+ "packageName": "@happyvertical/smrt-app-runtime",
5
+ "packageVersion": "0.43.9",
6
+ "objects": {},
7
+ "moduleType": "smrt",
8
+ "smrtDependencies": [
9
+ "@happyvertical/smrt-core",
10
+ "@happyvertical/smrt-jobs",
11
+ "@happyvertical/smrt-profiles",
12
+ "@happyvertical/smrt-tenancy",
13
+ "@happyvertical/smrt-users"
14
+ ]
15
+ }
@@ -0,0 +1,57 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "sensitiveFieldsExcluded": true,
4
+ "generatedAt": "1970-01-01T00:00:00.000Z",
5
+ "packageName": "@happyvertical/smrt-app-runtime",
6
+ "packageVersion": "0.43.9",
7
+ "sourceManifestPath": "dist/manifest.json",
8
+ "agentDocPath": "AGENTS.md",
9
+ "sourceHashes": {
10
+ "manifest": "de1ce9040fa27703ffcace4bce0c51a76f90c1b26884ac05821de7a18c5f1b7b",
11
+ "packageJson": "3f1af495baaa4d0656b7c6b37a584bf93227165caaf931705ad22023b5f33973",
12
+ "agents": "4a2e736f3fe4b1eaa5e90cbffc29e8af43e68059dc099cc9270d6d707c2a1f7c"
13
+ },
14
+ "exports": [
15
+ "."
16
+ ],
17
+ "dependencies": {
18
+ "@happyvertical/smrt-config": "workspace:*",
19
+ "@happyvertical/smrt-core": "workspace:*",
20
+ "@happyvertical/smrt-jobs": "workspace:*",
21
+ "@happyvertical/smrt-profiles": "workspace:*",
22
+ "@happyvertical/smrt-tenancy": "workspace:*",
23
+ "@happyvertical/smrt-users": "workspace:*",
24
+ "@happyvertical/sql": "catalog:",
25
+ "@happyvertical/smrt-vitest": "workspace:*",
26
+ "@types/node": "24.13.2",
27
+ "typescript": "5.9.3",
28
+ "vite": "8.1.4",
29
+ "vitest": "4.1.10"
30
+ },
31
+ "smrtDependencies": [
32
+ "@happyvertical/smrt-config",
33
+ "@happyvertical/smrt-core",
34
+ "@happyvertical/smrt-jobs",
35
+ "@happyvertical/smrt-profiles",
36
+ "@happyvertical/smrt-tenancy",
37
+ "@happyvertical/smrt-users",
38
+ "@happyvertical/smrt-vitest"
39
+ ],
40
+ "sdkDependencies": [
41
+ "@happyvertical/sql"
42
+ ],
43
+ "tags": [],
44
+ "risks": [],
45
+ "objects": [],
46
+ "surfaces": [],
47
+ "prompts": [],
48
+ "relationshipsV2": {
49
+ "foreignKeyFields": 0,
50
+ "crossPackageRefFields": 0,
51
+ "junctionCollections": 0,
52
+ "hierarchicalObjects": 0,
53
+ "polymorphicAssociations": 0,
54
+ "uuidColumns": 0
55
+ },
56
+ "agentDoc": "# @happyvertical/smrt-app-runtime\n\nApplication infrastructure composition for the validated runtime profiles in\n`@happyvertical/smrt-config`.\n\n## Local profile\n\n- `initializeLocalApplicationRuntime()` owns user data paths, SQLite tuning,\n local application-secret creation, and the single-use owner bootstrap flow.\n- SQLite is acquired through `@happyvertical/sql`'s explicit\n `{ driver: 'node:sqlite', custody: 'trusted-parent' }` boundary after the\n runtime establishes its user-owned mode-0700 data root.\n- Application migrations are explicit through `prepareDatabase`; runtime never\n creates application model tables implicitly.\n- Owner bootstrap creates normal `Person`, `User`, `Tenant`, owner `Role` /\n `Membership`, and `Session` records in one transaction.\n- Bootstrap is loopback-only. Only an HMAC of the short-lived token is stored.\n- Background jobs and application-defined paid capabilities are default-off.\n- The embedded runner reuses `TaskRunner`; it is not a second job contract.\n\n## Invariants\n\n- Never expose application-secret bytes or bootstrap token hashes in diagnostics.\n- Keep local data, assets, database, and secrets outside the source tree.\n- Do not reach into collection/database private fields. Add an upstream public\n API if composition cannot be expressed through exported surfaces.\n- Keep profile selection out of domain models, generated APIs, MCP/WebMCP\n surfaces, effects, approvals, and authorization records.\n\n## Validation\n\n```bash\npnpm --filter @happyvertical/smrt-app-runtime test\npnpm --filter @happyvertical/smrt-app-runtime typecheck\npnpm --filter @happyvertical/smrt-app-runtime build\n```\n"
57
+ }
package/package.json ADDED
@@ -0,0 +1,64 @@
1
+ {
2
+ "name": "@happyvertical/smrt-app-runtime",
3
+ "version": "0.43.9",
4
+ "description": "Safe private local runtime composition for s-m-r-t applications",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist",
16
+ "CLAUDE.md",
17
+ "AGENTS.md"
18
+ ],
19
+ "dependencies": {
20
+ "@happyvertical/sql": "^0.89.4",
21
+ "@happyvertical/smrt-config": "0.43.9",
22
+ "@happyvertical/smrt-jobs": "0.43.9",
23
+ "@happyvertical/smrt-profiles": "0.43.9",
24
+ "@happyvertical/smrt-tenancy": "0.43.9",
25
+ "@happyvertical/smrt-core": "0.43.9",
26
+ "@happyvertical/smrt-users": "0.43.9"
27
+ },
28
+ "devDependencies": {
29
+ "@types/node": "24.13.2",
30
+ "typescript": "5.9.3",
31
+ "vite": "8.1.4",
32
+ "vitest": "4.1.10",
33
+ "@happyvertical/smrt-vitest": "0.43.9"
34
+ },
35
+ "engines": {
36
+ "node": ">=24.18.0"
37
+ },
38
+ "publishConfig": {
39
+ "registry": "https://registry.npmjs.org",
40
+ "access": "public"
41
+ },
42
+ "repository": {
43
+ "type": "git",
44
+ "url": "https://github.com/happyvertical/smrt.git",
45
+ "directory": "packages/app-runtime"
46
+ },
47
+ "keywords": [
48
+ "smrt",
49
+ "runtime",
50
+ "sqlite",
51
+ "sveltekit"
52
+ ],
53
+ "author": "HappyVertical",
54
+ "license": "MIT",
55
+ "scripts": {
56
+ "build": "vite build",
57
+ "build:watch": "vite build --watch",
58
+ "clean": "rm -rf dist",
59
+ "dev": "npm run build:watch",
60
+ "test": "vitest run",
61
+ "test:watch": "vitest",
62
+ "typecheck": "tsc --noEmit"
63
+ }
64
+ }