@happyvertical/smrt-app-runtime 0.60.9 → 0.60.10

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/index.d.ts CHANGED
@@ -186,7 +186,7 @@ export interface LocalRuntimeDiagnostics {
186
186
  readonly paidCapabilitiesEnabled: boolean;
187
187
  readonly secretValuesIncluded: false;
188
188
  }
189
- export type LocalRuntimeErrorCode = 'bootstrap_claimed' | 'bootstrap_expired' | 'bootstrap_invalid' | 'bootstrap_unavailable' | 'capability_disabled' | 'invalid_configuration' | 'invalid_scope' | 'migration_failed' | 'owner_tenant_conflict' | 'owner_unavailable' | 'unsafe_public_exposure';
189
+ export type LocalRuntimeErrorCode = 'bootstrap_claimed' | 'bootstrap_expired' | 'bootstrap_invalid' | 'bootstrap_unavailable' | 'capability_disabled' | 'invalid_configuration' | 'invalid_scope' | 'migration_failed' | 'owner_tenant_conflict' | 'owner_identity_conflict' | 'owner_unavailable' | 'unsafe_public_exposure';
190
190
  /**
191
191
  * Fixed, secret-free surface for a failed application migration.
192
192
  *
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- import { A as reclaimStaleRecord, C as findInstalledPackage, D as processExists, E as lockOwnerPid, F as LOCAL_MCP_TOKEN_PRINCIPAL, G as initializeDeployedApplicationRuntime, I as LOCAL_MCP_TOKEN_TABLE, K as isSessionTenantAuthorized, L as MAX_LOCAL_MCP_TOKEN_TTL_SECONDS, M as runtimeConfigurationFingerprint, N as DEFAULT_LOCAL_MCP_TOKEN_TTL_SECONDS, O as withOperationLock, P as LOCAL_MCP_TOKEN_PREFIX, R as isLocalMcpTokenPrincipal, S as createProviderReadinessProbe, T as isStaleOperationLock, U as DeployedRuntimeCleanupError, W as DeployedRuntimeError, _ as MAX_RUNTIME_DIAGNOSTIC_TOOLS, a as openLocalMcpTokenStore, b as projectRuntimeDiagnostics, c as validateApplicationId, d as readActiveWriterLease, f as ONBOARDING_HANDOFF_FILES, g as MAX_RUNTIME_DIAGNOSTIC_ERRORS, h as resolveApplicationStateRoot, i as initializeLocalApplicationRuntime, j as resolveApplicationId, k as RECLAIM_MUTEX_FILE, l as validateLocalDatabaseStorage, m as removeOnboardingHandoff, n as MIGRATION_FAILED_MESSAGE, o as prepareLocalDatabaseStorage, p as prepareApplicationStateRoot, r as encodeApplicationId, s as resolveLocalRuntimePaths, t as LocalRuntimeError, u as acquireWriterLease, v as RUNTIME_DIAGNOSTICS_SCHEMA_VERSION, w as resolveReadinessModule, x as PROVIDER_READINESS_SETTINGS, y as RUNTIME_WORKER_FRESHNESS_SECONDS } from "./chunks/src-DP7SxcSY.js";
1
+ import { A as reclaimStaleRecord, C as findInstalledPackage, D as processExists, E as lockOwnerPid, F as LOCAL_MCP_TOKEN_PRINCIPAL, G as initializeDeployedApplicationRuntime, I as LOCAL_MCP_TOKEN_TABLE, K as isSessionTenantAuthorized, L as MAX_LOCAL_MCP_TOKEN_TTL_SECONDS, M as runtimeConfigurationFingerprint, N as DEFAULT_LOCAL_MCP_TOKEN_TTL_SECONDS, O as withOperationLock, P as LOCAL_MCP_TOKEN_PREFIX, R as isLocalMcpTokenPrincipal, S as createProviderReadinessProbe, T as isStaleOperationLock, U as DeployedRuntimeCleanupError, W as DeployedRuntimeError, _ as MAX_RUNTIME_DIAGNOSTIC_TOOLS, a as openLocalMcpTokenStore, b as projectRuntimeDiagnostics, c as validateApplicationId, d as readActiveWriterLease, f as ONBOARDING_HANDOFF_FILES, g as MAX_RUNTIME_DIAGNOSTIC_ERRORS, h as resolveApplicationStateRoot, i as initializeLocalApplicationRuntime, j as resolveApplicationId, k as RECLAIM_MUTEX_FILE, l as validateLocalDatabaseStorage, m as removeOnboardingHandoff, n as MIGRATION_FAILED_MESSAGE, o as prepareLocalDatabaseStorage, p as prepareApplicationStateRoot, r as encodeApplicationId, s as resolveLocalRuntimePaths, t as LocalRuntimeError, u as acquireWriterLease, v as RUNTIME_DIAGNOSTICS_SCHEMA_VERSION, w as resolveReadinessModule, x as PROVIDER_READINESS_SETTINGS, y as RUNTIME_WORKER_FRESHNESS_SECONDS } from "./chunks/src-DOepXMDO.js";
2
2
  export { DEFAULT_LOCAL_MCP_TOKEN_TTL_SECONDS, DeployedRuntimeCleanupError, DeployedRuntimeError, LOCAL_MCP_TOKEN_PREFIX, LOCAL_MCP_TOKEN_PRINCIPAL, LOCAL_MCP_TOKEN_TABLE, LocalRuntimeError, MAX_LOCAL_MCP_TOKEN_TTL_SECONDS, MAX_RUNTIME_DIAGNOSTIC_ERRORS, MAX_RUNTIME_DIAGNOSTIC_TOOLS, MIGRATION_FAILED_MESSAGE, ONBOARDING_HANDOFF_FILES, PROVIDER_READINESS_SETTINGS, RECLAIM_MUTEX_FILE, RUNTIME_DIAGNOSTICS_SCHEMA_VERSION, RUNTIME_WORKER_FRESHNESS_SECONDS, acquireWriterLease, createProviderReadinessProbe, encodeApplicationId, findInstalledPackage, initializeDeployedApplicationRuntime, initializeLocalApplicationRuntime, isLocalMcpTokenPrincipal, isSessionTenantAuthorized, isStaleOperationLock, lockOwnerPid, openLocalMcpTokenStore, prepareApplicationStateRoot, prepareLocalDatabaseStorage, processExists, projectRuntimeDiagnostics, readActiveWriterLease, reclaimStaleRecord, removeOnboardingHandoff, resolveApplicationId, resolveApplicationStateRoot, resolveLocalRuntimePaths, resolveReadinessModule, runtimeConfigurationFingerprint, validateApplicationId, validateLocalDatabaseStorage, withOperationLock };
@@ -0,0 +1,10 @@
1
+ /** Derive public identifiers from the existing private installation seed. */
2
+ export declare function deriveLocalInstallationIdentity(applicationSecret: string): {
3
+ deviceId: string;
4
+ tenantId: string;
5
+ ownerId: string;
6
+ profileId: string;
7
+ membershipId: string;
8
+ };
9
+ export type LocalInstallationIdentity = ReturnType<typeof deriveLocalInstallationIdentity>;
10
+ //# sourceMappingURL=local-installation-identity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-installation-identity.d.ts","sourceRoot":"","sources":["../src/local-installation-identity.ts"],"names":[],"mappings":"AAaA,6EAA6E;AAC7E,wBAAgB,+BAA+B,CAAC,iBAAiB,EAAE,MAAM;;;;;;EASxE;AAED,MAAM,MAAM,yBAAyB,GAAG,UAAU,CAChD,OAAO,+BAA+B,CACvC,CAAC"}
@@ -2,7 +2,7 @@
2
2
  "version": "1.0.0",
3
3
  "timestamp": 0,
4
4
  "packageName": "@happyvertical/smrt-app-runtime",
5
- "packageVersion": "0.60.9",
5
+ "packageVersion": "0.60.10",
6
6
  "objects": {},
7
7
  "moduleType": "smrt",
8
8
  "smrtDependencies": [
@@ -3,13 +3,13 @@
3
3
  "sensitiveFieldsExcluded": true,
4
4
  "generatedAt": "1970-01-01T00:00:00.000Z",
5
5
  "packageName": "@happyvertical/smrt-app-runtime",
6
- "packageVersion": "0.60.9",
6
+ "packageVersion": "0.60.10",
7
7
  "sourceManifestPath": "dist/manifest.json",
8
8
  "agentDocPath": "AGENTS.md",
9
9
  "sourceHashes": {
10
- "manifest": "25cfef69426cbfbc4334f62df02a2b272bfde02fe409b2726567f8e18bdbd535",
11
- "packageJson": "b94d5b2d4ee89c47fe87ea32615b58e453dd351f06434f9fe11e4ba1be310d75",
12
- "agents": "4650832b5cfbae9cb4d4b92b222d1830b2fcab57320dc322a6df6ff6649d5af8"
10
+ "manifest": "624c8da817857513705640c675c5b89d02021d9119d31a3816a93ba516c39639",
11
+ "packageJson": "bc743f619da6dd2bedc305b5479070a5bed2062cc4b2414d3663a8da7abce143",
12
+ "agents": "0ab0d61d25ac331f6d0a61b34adb6524d1d35885c0f5b2069979e0e8a99b2351"
13
13
  },
14
14
  "exports": [
15
15
  ".",
@@ -67,5 +67,5 @@
67
67
  "polymorphicAssociations": 0,
68
68
  "uuidColumns": 0
69
69
  },
70
- "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- `validateApplicationId()` is the canonical strict validator for explicit app\n IDs. `encodeApplicationId()` derives a length-bounded, collision-resistant\n ID from package names; generated operational surfaces must share these APIs.\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- The initialization lease lives beside the data root\n (`<parent>/.smrt-lease-<key>/initialization.sqlite`, #3877), then the legacy\n `/tmp/.smrt-<uid>/<key>` lease, which older releases take alone: secure when\n its ancestry is trusted, else lock-only (owner check on unmapped ancestors\n relaxed, nothing written; skipped only if its directory cannot be created\n and no lock file exists). It is required (secure) when the parent cannot hold\n a lease. Legacy candidates, deduplicated and in this order: the in-namespace\n uid, then that uid mapped through `/proc/self/uid_map` (identity when absent;\n unparseable/non-covering fails closed); ownership checks still use the\n in-namespace uid. The beside-data lease taken first keeps that order\n deadlock-free. Only the in-namespace candidate (when it differs) is skipped\n if its root is an existing real directory owned by another uid. Acquire in that order; never make the\n lease location configurable per process — every process sharing a data root\n must derive the same lease.\n- Application migrations are explicit through `prepareDatabase`; runtime never\n creates application model tables implicitly. A rejected `prepareDatabase` is\n normalized into `LocalRuntimeError` with the stable `migration_failed` code\n and the fixed recovery message `MIGRATION_FAILED_MESSAGE` (\"run pnpm\n app:setup and inspect the private migration logs\"). The caller's error text\n is never surfaced — it is retained only as a non-enumerable `cause` for\n private logs — and the same application root stays retryable.\n- Standalone migration commands must call `prepareLocalDatabaseStorage()`\n before opening SQLite so custody is established without creating schema or\n bootstrap records.\n- Read-only/copy/import operator commands must call\n `validateLocalDatabaseStorage()` before opening SQLite; it verifies the\n app-bound marker, source separation, real path chain, ownership, and mode\n without creating or repairing storage.\n- Owner bootstrap creates normal `Person`, `User`, `Tenant`, owner `Role` /\n `Membership`, and `Session` records in one transaction. `ownerTenant`\n selects the tenant slug (default `default`); because `Tenant` upserts on\n slug, the claim must look the slug up first and fail closed\n (`owner_tenant_conflict`) rather than save over it. `adoptExisting` adopts\n only an active root tenant with zero memberships (#3032).\n- Bootstrap is loopback-only. Only an HMAC of the short-lived token is stored.\n A token that cannot claim fails a read-only preflight before role/catalog\n seeding (#3323); the claim transaction's conditional UPDATE stays the\n authority for single use, expiry, and concurrency.\n- Local MCP tokens (`mcpTokens`, `openLocalMcpTokenStore`, `smrt app token`):\n owner-bound, scoped, expiring (default 30 d, max 365 d), revocable. Only a\n domain-separated HMAC (application secret) is stored, in the runtime-owned\n `_smrt_local_mcp_tokens` system table (created like the bootstrap table;\n never application schema). Issue refuses scopes the owner lacks; verify\n returns token scopes ∩ live permissions and `null` for anything else.\n- Bearer binding is explicit (`tenantBinding`, set by the auth adapter;\n `direct-membership.ts`): `direct` (local tokens, default hosted resolver)\n needs an active direct membership in exactly the tenant; the default\n `direct-or-inherited` (hosted app mappings) applies\n `isSessionTenantAuthorized`'s rule. The direct row, when present, is pinned\n into `PermissionResolver`, so inheritance never substitutes for it.\n `verify()` principals (and their `scopes` arrays) are frozen;\n `runAsPrincipal` takes a validated, deep-frozen, null-prototype copy of\n the principal before any await (`plain-data.ts`: own data only; poison\n keys `__proto__`/`constructor`/`prototype`, accessors, inherited or\n non-plain data, sparse arrays and functions rejected), authorizes from it,\n and hands `fn` that snapshot. Token `issue()` input is read the same way.\n They carry\n `tenantBinding: 'direct'` and the\n `LOCAL_MCP_TOKEN_PRINCIPAL` brand; `runAsPrincipal` rejects a copy that\n widens the binding, so the two public APIs compose safely.\n Never log or return the token outside `issue()`. The operator store opens an\n uncached connection and takes no writer lease (revocation is per request).\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## Deployed profiles\n\n- `initializeDeployedApplicationRuntime()` composes only `self-hosted` and\n `cloud`; it rejects local initialization and provider/binding mismatches.\n- Provider bindings own credentials, vendor clients, and readiness checks.\n Runtime diagnostics contain selectors and status only.\n- The database binding must expose a provider-owned `close` callback before\n `connect` can run. The runtime owns that cleanup boundary and runs the\n application's explicit, idempotent `prepareDatabase` hook.\n- A failed startup cleanup throws `DeployedRuntimeCleanupError`; callers retain\n and retry its idempotent `retryCleanup()` boundary until it succeeds.\n- Public authentication, asset storage, and secret bindings are mandatory and\n readiness-checked before startup succeeds.\n- `createTaskWorker()` and `createScheduleWorker()` initialize the normal jobs\n package runners against the shared PostgreSQL database. They are intended for\n separate processes; the web process does not start them automatically. A\n task worker polls `default` plus `SCHEDULED_JOB_QUEUE` (`agents`, where\n `ScheduleRunner` enqueues) unless `queues` is passed (#3141). The\n worker process must import the app's compiled registration\n (`.smrt/runtime/register.js`, #3117) first; runners resolve `objectType`\n through the registry and never load application source themselves.\n- `close()` drains in-flight readiness/session/worker initialization and\n serialized runner start/stop operations, stops every runner returned by the\n runtime, and then closes PostgreSQL. Returned runners must not be restarted\n after runtime shutdown begins.\n- A tracked operation may await a re-entrant `close()` request without\n deadlocking; external `close()` callers still await complete cleanup.\n- `health()` is process liveness. `readiness()` probes database/auth/assets/\n secrets; it does not claim that an external worker fleet is running.\n- Database-provider readiness is additive; a PostgreSQL-specific server-version\n probe always gates startup and live readiness.\n- Cloud must keep required tenant context and must never introduce a root or\n unscoped tenant fallback. RLS remains an explicit deployment/migration choice.\n\n## SvelteKit entry (`./sveltekit`)\n\n- Server-only subpath; `@sveltejs/kit` is an optional peer and is externalized\n in `vite.config.ts` (kit recognizes `redirect`/`fail` by class identity).\n Consumer apps use core's `smrt()` preset to bundle the Kit-facing entry into\n their SSR output and dedupe Kit; `./sveltekit-runtime` and the root stay external\n to preserve native dependency loading. The implementation subpath is for\n build composition; apps keep importing `./sveltekit`.\n Package-build externalization alone does not preserve class identity through adapter-node's final production bundle.\n The root entry must never import kit or Svelte.\n- Without a `runtime` option the profile comes from smrt-config's\n `resolveEffectiveApplicationRuntime(await loadConfig())`, the same rule as\n `smrt app` (#3446): no block → `local`; `null`/`false`/`0`/`''` fail closed.\n- `createSmrtSvelteKitRuntime()` order is fixed: readiness gate → URL tenant\n selection (`locals.selectedTenant*`, never tenant context, headers ignored) →\n verified session (tenant context entered only when\n `isSessionTenantAuthorized()` accepts it, else unauthenticated; never via\n `createSessionHandler`, which re-runs `resolve` on downstream errors) →\n publish `locals.tenantContext` only for that verified tenant.\n- `database-rls` isolation forces `postgresRls: true`, including on\n `skipPaths` (anonymous principal). `resolve` runs at most once;\n session-layer failure before it is a 500 with cleared locals.\n- In an RLS request `classOptions()`/`databaseConfig()` return the\n transaction-bound request db (class `db` overrides win). Anything that\n outlives a request (session service, tenant selector) must use the base\n config, never these.\n- The local writer lease defaults to `defaultWriterLease()` (root\n `acquireWriterLease` over `prepareApplicationStateRoot`, presenting\n `SMRT_OPERATION_INSTANCE`); `acquireWriterLease` replaces it, `false` opts\n out, deployed profiles never take it. Provider readiness stays injected:\n apps pass `createProviderReadinessProbe`; deployed startup fails closed\n without `providerReadiness`.\n- `getCollection()` builds from `classOptions()` on every call (RLS request db\n inside a request); each generated route's embedded prelude imports the\n app's `smrt.ts` and reaches it through core's\n `createGeneratedCollectionAccess()` (a legacy accessor export wins,\n deprecated for one release).\n- Owner setup removes the `smrt app` onboarding hand-off files by default,\n immediately after the claim commits (before cookie serialization or hooks);\n `onOwnerClaimed` is for additional cleanup and\n `removeOnboardingHandoff: false` is the explicit opt-out.\n- `createSessionLayoutLoad()` adds `session.user` (`{ id, email, name? }`\n copied from `locals.user`, else `null`). `createSignOutHandler(runtime)` is\n the `POST` handler for `src/routes/sign-out/+server.ts`: 405 for other\n methods, 403 unless `Sec-Fetch-Site: same-origin` or `Origin` equals the\n request origin, then `destroySessionCookie` with the runtime's cookie\n name/path/domain (cookie cleared even if the session row is gone); 204, or\n 303 to `/` when the request accepts HTML.\n- Owner setup re-checks loopback peer and loopback URL host per request and\n returns only fixed `{ code, message }` failures.\n- `verifyLocalMcpToken` (local only) and `resolveMcpPrincipal` (hosted only:\n issuer/subject → `oidc_identities` → exactly one active user with exactly\n one active direct membership, else `null`) are the runtime's MCP credential\n bindings; pass the runtime as `mountMcpAppRoute({ runtime })` (or\n `createHostedMcpResourceAuth({ runtime })`).\n Token claims never select a tenant.\n- `resolveApplicationId()` / `runtimeConfigurationFingerprint()` must stay\n byte-compatible with process managers (golden vectors in tests).\n\n## Operator state (root entry)\n\n- One owner for the state shared by the web process and `smrt app`\n (`@happyvertical/smrt-cli/app` re-exports these): `resolveApplicationStateRoot`\n / `prepareApplicationStateRoot` (private app-bound mode-0700 root and\n marker), `withOperationLock` (`operation.lock`), `acquireWriterLease` /\n `readActiveWriterLease` (`writer.lease`), `reclaimStaleRecord`, and\n `createProviderReadinessProbe` (`SMRT_*_READINESS_MODULE`, resolved from the\n app root with Node's own ESM rules). File names, record formats, and\n messages are a cross-process contract; never change them unilaterally.\n- Tests that hook `node:fs` interleavings must live in this package: from a\n consumer the package is an externalized dependency a mock cannot reach.\n\n## Public runtime diagnostics\n\n- `projectRuntimeDiagnostics()` is the only public diagnostic projection. It\n constructs the schema-version-1 allowlist and never serializes the private\n local or deployed diagnostics objects.\n- The allowlist is limited to active profile/coarse health, schema and\n migration readiness, six fixed capability statuses, a sorted/capped public\n tool inventory plus digest, explicit operational topology differences,\n coarse worker heartbeat state, and eight stable code/timestamp errors.\n- Callers supply an explicit clock and worker-heartbeat seam. A missing\n heartbeat is `unknown`; web-process liveness never proves worker liveness.\n- Error ingestion maps unknown codes to `runtime_error`, truncates timestamps\n to the minute, and ignores messages, stacks, logs, records, and nested state.\n- Authentication and diagnostics-read authorization belong before every call\n to the projector or its runtime probes.\n\n## Invariants\n\n- Never expose application-secret bytes or bootstrap token hashes in diagnostics.\n- Never include migration or provider error text in a local or deployed startup\n error message; migration driver text is a likely credential carrier.\n- Never include provider error text, URLs, tokens, or credentials in deployed\n errors, diagnostics, health, or readiness payloads.\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\nBuild first: `sveltekit-production.test.ts` copies the published `dist` entry\nand exercises the final adapter-node HTTP handler in a separate process.\n\n```bash\npnpm --filter @happyvertical/smrt-app-runtime build\npnpm --filter @happyvertical/smrt-app-runtime test\npnpm --filter @happyvertical/smrt-app-runtime typecheck\n```\n"
70
+ "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- `validateApplicationId()` is the canonical strict validator for explicit app\n IDs. `encodeApplicationId()` derives a length-bounded, collision-resistant\n ID from package names; generated operational surfaces must share these APIs.\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- The initialization lease lives beside the data root\n (`<parent>/.smrt-lease-<key>/initialization.sqlite`, #3877), then the legacy\n `/tmp/.smrt-<uid>/<key>` lease, which older releases take alone: secure when\n its ancestry is trusted, else lock-only (owner check on unmapped ancestors\n relaxed, nothing written; skipped only if its directory cannot be created\n and no lock file exists). It is required (secure) when the parent cannot hold\n a lease. Legacy candidates, deduplicated and in this order: the in-namespace\n uid, then that uid mapped through `/proc/self/uid_map` (identity when absent;\n unparseable/non-covering fails closed); ownership checks still use the\n in-namespace uid. The beside-data lease taken first keeps that order\n deadlock-free. Only the in-namespace candidate (when it differs) is skipped\n if its root is an existing real directory owned by another uid. Acquire in that order; never make the\n lease location configurable per process — every process sharing a data root\n must derive the same lease.\n- Application migrations are explicit through `prepareDatabase`; runtime never\n creates application model tables implicitly. A rejected `prepareDatabase` is\n normalized into `LocalRuntimeError` with the stable `migration_failed` code\n and the fixed recovery message `MIGRATION_FAILED_MESSAGE` (\"run pnpm\n app:setup and inspect the private migration logs\"). The caller's error text\n is never surfaced — it is retained only as a non-enumerable `cause` for\n private logs — and the same application root stays retryable.\n- Standalone migration commands must call `prepareLocalDatabaseStorage()`\n before opening SQLite so custody is established without creating schema or\n bootstrap records.\n- Read-only/copy/import operator commands must call\n `validateLocalDatabaseStorage()` before opening SQLite; it verifies the\n app-bound marker, source separation, real path chain, ownership, and mode\n without creating or repairing storage.\n- Owner bootstrap creates normal `Person`, `User`, `Tenant`, owner `Role` /\n `Membership`, and `Session` records in one transaction. `ownerTenant`\n selects the tenant slug (default `default`); because `Tenant` upserts on\n slug, the claim must look the slug up first and fail closed\n (`owner_tenant_conflict`) rather than save over it. `adoptExisting` adopts\n only an active root tenant with zero memberships (#3032). Fresh tenant\n creation uses `TenantService` with the local ownership policy and a trusted\n reserved identity. Default tenant and owner graph IDs derive from the\n protected per-install application secret. Preserve that file when restoring\n the same installation.\n- Bootstrap is loopback-only. Only an HMAC of the short-lived token is stored.\n A token that cannot claim fails a read-only preflight before role/catalog\n seeding (#3323); the claim transaction's conditional UPDATE stays the\n authority for single use, expiry, and concurrency.\n- Local MCP tokens (`mcpTokens`, `openLocalMcpTokenStore`, `smrt app token`):\n owner-bound, scoped, expiring (default 30 d, max 365 d), revocable. Only a\n domain-separated HMAC (application secret) is stored, in the runtime-owned\n `_smrt_local_mcp_tokens` system table (created like the bootstrap table;\n never application schema). Issue refuses scopes the owner lacks; verify\n returns token scopes ∩ live permissions and `null` for anything else.\n- Bearer binding is explicit (`tenantBinding`, set by the auth adapter;\n `direct-membership.ts`): `direct` (local tokens, default hosted resolver)\n needs an active direct membership in exactly the tenant; the default\n `direct-or-inherited` (hosted app mappings) applies\n `isSessionTenantAuthorized`'s rule. The direct row, when present, is pinned\n into `PermissionResolver`, so inheritance never substitutes for it.\n `verify()` principals (and their `scopes` arrays) are frozen;\n `runAsPrincipal` takes a validated, deep-frozen, null-prototype copy of\n the principal before any await (`plain-data.ts`: own data only; poison\n keys `__proto__`/`constructor`/`prototype`, accessors, inherited or\n non-plain data, sparse arrays and functions rejected), authorizes from it,\n and hands `fn` that snapshot. Token `issue()` input is read the same way.\n They carry\n `tenantBinding: 'direct'` and the\n `LOCAL_MCP_TOKEN_PRINCIPAL` brand; `runAsPrincipal` rejects a copy that\n widens the binding, so the two public APIs compose safely.\n Never log or return the token outside `issue()`. The operator store opens an\n uncached connection and takes no writer lease (revocation is per request).\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## Deployed profiles\n\n- `initializeDeployedApplicationRuntime()` composes only `self-hosted` and\n `cloud`; it rejects local initialization and provider/binding mismatches.\n- Provider bindings own credentials, vendor clients, and readiness checks.\n Runtime diagnostics contain selectors and status only.\n- The database binding must expose a provider-owned `close` callback before\n `connect` can run. The runtime owns that cleanup boundary and runs the\n application's explicit, idempotent `prepareDatabase` hook.\n- A failed startup cleanup throws `DeployedRuntimeCleanupError`; callers retain\n and retry its idempotent `retryCleanup()` boundary until it succeeds.\n- Public authentication, asset storage, and secret bindings are mandatory and\n readiness-checked before startup succeeds.\n- `createTaskWorker()` and `createScheduleWorker()` initialize the normal jobs\n package runners against the shared PostgreSQL database. They are intended for\n separate processes; the web process does not start them automatically. A\n task worker polls `default` plus `SCHEDULED_JOB_QUEUE` (`agents`, where\n `ScheduleRunner` enqueues) unless `queues` is passed (#3141). The\n worker process must import the app's compiled registration\n (`.smrt/runtime/register.js`, #3117) first; runners resolve `objectType`\n through the registry and never load application source themselves.\n- `close()` drains in-flight readiness/session/worker initialization and\n serialized runner start/stop operations, stops every runner returned by the\n runtime, and then closes PostgreSQL. Returned runners must not be restarted\n after runtime shutdown begins.\n- A tracked operation may await a re-entrant `close()` request without\n deadlocking; external `close()` callers still await complete cleanup.\n- `health()` is process liveness. `readiness()` probes database/auth/assets/\n secrets; it does not claim that an external worker fleet is running.\n- Database-provider readiness is additive; a PostgreSQL-specific server-version\n probe always gates startup and live readiness.\n- Cloud must keep required tenant context and must never introduce a root or\n unscoped tenant fallback. RLS remains an explicit deployment/migration choice.\n\n## SvelteKit entry (`./sveltekit`)\n\n- Server-only subpath; `@sveltejs/kit` is an optional peer and is externalized\n in `vite.config.ts` (kit recognizes `redirect`/`fail` by class identity).\n Consumer apps use core's `smrt()` preset to bundle the Kit-facing entry into\n their SSR output and dedupe Kit; `./sveltekit-runtime` and the root stay external\n to preserve native dependency loading. The implementation subpath is for\n build composition; apps keep importing `./sveltekit`.\n Package-build externalization alone does not preserve class identity through adapter-node's final production bundle.\n The root entry must never import kit or Svelte.\n- Without a `runtime` option the profile comes from smrt-config's\n `resolveEffectiveApplicationRuntime(await loadConfig())`, the same rule as\n `smrt app` (#3446): no block → `local`; `null`/`false`/`0`/`''` fail closed.\n- `createSmrtSvelteKitRuntime()` order is fixed: readiness gate → URL tenant\n selection (`locals.selectedTenant*`, never tenant context, headers ignored) →\n verified session (tenant context entered only when\n `isSessionTenantAuthorized()` accepts it, else unauthenticated; never via\n `createSessionHandler`, which re-runs `resolve` on downstream errors) →\n publish `locals.tenantContext` only for that verified tenant.\n- `database-rls` isolation forces `postgresRls: true`, including on\n `skipPaths` (anonymous principal). `resolve` runs at most once;\n session-layer failure before it is a 500 with cleared locals.\n- In an RLS request `classOptions()`/`databaseConfig()` return the\n transaction-bound request db (class `db` overrides win). Anything that\n outlives a request (session service, tenant selector) must use the base\n config, never these.\n- The local writer lease defaults to `defaultWriterLease()` (root\n `acquireWriterLease` over `prepareApplicationStateRoot`, presenting\n `SMRT_OPERATION_INSTANCE`); `acquireWriterLease` replaces it, `false` opts\n out, deployed profiles never take it. Provider readiness stays injected:\n apps pass `createProviderReadinessProbe`; deployed startup fails closed\n without `providerReadiness`.\n- `getCollection()` builds from `classOptions()` on every call (RLS request db\n inside a request); each generated route's embedded prelude imports the\n app's `smrt.ts` and reaches it through core's\n `createGeneratedCollectionAccess()` (a legacy accessor export wins,\n deprecated for one release).\n- Owner setup removes the `smrt app` onboarding hand-off files by default,\n immediately after the claim commits (before cookie serialization or hooks);\n `onOwnerClaimed` is for additional cleanup and\n `removeOnboardingHandoff: false` is the explicit opt-out.\n- `createSessionLayoutLoad()` adds `session.user` (`{ id, email, name? }`\n copied from `locals.user`, else `null`). `createSignOutHandler(runtime)` is\n the `POST` handler for `src/routes/sign-out/+server.ts`: 405 for other\n methods, 403 unless `Sec-Fetch-Site: same-origin` or `Origin` equals the\n request origin, then `destroySessionCookie` with the runtime's cookie\n name/path/domain (cookie cleared even if the session row is gone); 204, or\n 303 to `/` when the request accepts HTML.\n- Owner setup re-checks loopback peer and loopback URL host per request and\n returns only fixed `{ code, message }` failures.\n- `verifyLocalMcpToken` (local only) and `resolveMcpPrincipal` (hosted only:\n issuer/subject → `oidc_identities` → exactly one active user with exactly\n one active direct membership, else `null`) are the runtime's MCP credential\n bindings; pass the runtime as `mountMcpAppRoute({ runtime })` (or\n `createHostedMcpResourceAuth({ runtime })`).\n Token claims never select a tenant.\n- `resolveApplicationId()` / `runtimeConfigurationFingerprint()` must stay\n byte-compatible with process managers (golden vectors in tests).\n\n## Operator state (root entry)\n\n- One owner for the state shared by the web process and `smrt app`\n (`@happyvertical/smrt-cli/app` re-exports these): `resolveApplicationStateRoot`\n / `prepareApplicationStateRoot` (private app-bound mode-0700 root and\n marker), `withOperationLock` (`operation.lock`), `acquireWriterLease` /\n `readActiveWriterLease` (`writer.lease`), `reclaimStaleRecord`, and\n `createProviderReadinessProbe` (`SMRT_*_READINESS_MODULE`, resolved from the\n app root with Node's own ESM rules). File names, record formats, and\n messages are a cross-process contract; never change them unilaterally.\n- Tests that hook `node:fs` interleavings must live in this package: from a\n consumer the package is an externalized dependency a mock cannot reach.\n\n## Public runtime diagnostics\n\n- `projectRuntimeDiagnostics()` is the only public diagnostic projection. It\n constructs the schema-version-1 allowlist and never serializes the private\n local or deployed diagnostics objects.\n- The allowlist is limited to active profile/coarse health, schema and\n migration readiness, six fixed capability statuses, a sorted/capped public\n tool inventory plus digest, explicit operational topology differences,\n coarse worker heartbeat state, and eight stable code/timestamp errors.\n- Callers supply an explicit clock and worker-heartbeat seam. A missing\n heartbeat is `unknown`; web-process liveness never proves worker liveness.\n- Error ingestion maps unknown codes to `runtime_error`, truncates timestamps\n to the minute, and ignores messages, stacks, logs, records, and nested state.\n- Authentication and diagnostics-read authorization belong before every call\n to the projector or its runtime probes.\n\n## Invariants\n\n- Never expose application-secret bytes or bootstrap token hashes in diagnostics.\n- Never include migration or provider error text in a local or deployed startup\n error message; migration driver text is a likely credential carrier.\n- Never include provider error text, URLs, tokens, or credentials in deployed\n errors, diagnostics, health, or readiness payloads.\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\nBuild first: `sveltekit-production.test.ts` copies the published `dist` entry\nand exercises the final adapter-node HTTP handler in a separate process.\n\n```bash\npnpm --filter @happyvertical/smrt-app-runtime build\npnpm --filter @happyvertical/smrt-app-runtime test\npnpm --filter @happyvertical/smrt-app-runtime typecheck\n```\n"
71
71
  }
@@ -0,0 +1,52 @@
1
+ ---
2
+ type: "Component"
3
+ title: "@happyvertical/smrt-app-runtime"
4
+ description: "Validated local, self-hosted, and cloud runtime composition for s-m-r-t applications"
5
+ status: "stable"
6
+ generated:
7
+ by: "smrt/scripts/generate-knowledge-okf.ts"
8
+ at: "2026-11-05T20:27:03Z"
9
+ audience: "internal"
10
+ evidence_level: "manifest-described"
11
+ source_revision: "sha256:e9f48d984a2e263720842aabe4ede9b0e377e1bcef19208b4788f72f8b4d8889"
12
+ sources:
13
+ - id: "manifest"
14
+ resource: "https://github.com/happyvertical/smrt/blob/main/packages/app-runtime/package.json"
15
+ title: "@happyvertical/smrt-app-runtime package manifest"
16
+ - id: "agents"
17
+ resource: "https://github.com/happyvertical/smrt/blob/main/packages/app-runtime/AGENTS.md"
18
+ title: "@happyvertical/smrt-app-runtime packages/app-runtime/AGENTS.md"
19
+ ---
20
+
21
+ # @happyvertical/smrt-app-runtime
22
+
23
+ ## Package
24
+
25
+ - Directory: `packages/app-runtime`
26
+ - Private: no
27
+ - Object source: `domain-artifact`
28
+ - Evidence level: `manifest-described`
29
+
30
+ ## Documentation
31
+
32
+ - `packages/app-runtime/AGENTS.md`
33
+
34
+ ## Framework dependencies
35
+
36
+ - [smrt-config](/components/smrt-config.md)
37
+ - [smrt-core](/components/smrt-core.md)
38
+ - [smrt-jobs](/components/smrt-jobs.md)
39
+ - [smrt-profiles](/components/smrt-profiles.md)
40
+ - [smrt-tenancy](/components/smrt-tenancy.md)
41
+ - [smrt-users](/components/smrt-users.md)
42
+ - [smrt-vitest](/components/smrt-vitest.md)
43
+
44
+ ## SDK dependencies
45
+
46
+ - `@happyvertical/sql`
47
+
48
+ ## Exports
49
+
50
+ - `.`
51
+ - `./sveltekit`
52
+ - `./sveltekit-runtime`
@@ -1 +1 @@
1
- {"version":3,"file":"owner-setup.d.ts","sourceRoot":"","sources":["../../src/sveltekit/owner-setup.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"owner-setup.d.ts","sourceRoot":"","sources":["../../src/sveltekit/owner-setup.ts"],"names":[],"mappings":"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"}
@@ -1,11 +1,11 @@
1
- import { B as deepFrozenPlainCopy, G as initializeDeployedApplicationRuntime, H as resolveBoundMembershipPermissions, K as isSessionTenantAuthorized, M as runtimeConfigurationFingerprint, R as isLocalMcpTokenPrincipal, V as ownValue, b as projectRuntimeDiagnostics, c as validateApplicationId, h as resolveApplicationStateRoot, i as initializeLocalApplicationRuntime, j as resolveApplicationId, p as prepareApplicationStateRoot, s as resolveLocalRuntimePaths, u as acquireWriterLease, z as PlainDataError } from "./chunks/src-DP7SxcSY.js";
1
+ import { B as deepFrozenPlainCopy, G as initializeDeployedApplicationRuntime, H as resolveBoundMembershipPermissions, K as isSessionTenantAuthorized, M as runtimeConfigurationFingerprint, R as isLocalMcpTokenPrincipal, V as ownValue, b as projectRuntimeDiagnostics, c as validateApplicationId, h as resolveApplicationStateRoot, i as initializeLocalApplicationRuntime, j as resolveApplicationId, p as prepareApplicationStateRoot, s as resolveLocalRuntimePaths, u as acquireWriterLease, z as PlainDataError } from "./chunks/src-DOepXMDO.js";
2
2
  import { n as normalizeTenantSelection, t as createSubdomainTenantSelector } from "./chunks/tenancy-BzdIxH2M.js";
3
3
  import { loadConfig, resolveEffectiveApplicationRuntime } from "@happyvertical/smrt-config";
4
+ import { ObjectRegistry } from "@happyvertical/smrt-core";
4
5
  import { OidcIdentityCollection } from "@happyvertical/smrt-profiles";
5
6
  import { enableTenancy, getCurrentTenant, isTenancyEnabled, withSystemContext } from "@happyvertical/smrt-tenancy";
6
7
  import { MembershipCollection, PermissionResolver, SessionService, UserCollection, UserStatus, getCurrentSessionPermissionContext, getRequestScopedDatabase, withPrincipalPermissionContext, withSessionPermissionContext } from "@happyvertical/smrt-users";
7
8
  import { getDatabase } from "@happyvertical/sql";
8
- import { ObjectRegistry } from "@happyvertical/smrt-core";
9
9
  //#region src/sveltekit/runtime.ts
10
10
  var DEFAULT_SESSION_TTL_SECONDS = 10080 * 60;
11
11
  function createSmrtSvelteKitRuntime(options = {}) {
package/dist/sveltekit.js CHANGED
@@ -179,7 +179,7 @@ function createOwnerSetupPage(runtime, options = {}) {
179
179
  ipAddress: event.getClientAddress()
180
180
  });
181
181
  } catch (error) {
182
- if (error instanceof LocalRuntimeError && error.code === "owner_tenant_conflict") return failure(409, "setup_conflict");
182
+ if (error instanceof LocalRuntimeError && (error.code === "owner_tenant_conflict" || error.code === "owner_identity_conflict")) return failure(409, "setup_conflict");
183
183
  return failure(400, "setup_invalid");
184
184
  }
185
185
  if (options.removeOnboardingHandoff !== false && runtime.applicationStateRoot) try {
@@ -1 +1 @@
1
- {"version":3,"file":"sveltekit.js","names":["name"],"sources":["../src/sveltekit/handlers.ts","../src/sveltekit/owner-setup.ts","../src/sveltekit/sign-out.ts"],"sourcesContent":["/**\n * Mountable runtime routes: liveness health, authorized diagnostics, and the\n * server-owned session summary for the root layout.\n */\n\nimport {\n getRequestScopedDatabase,\n RoleCollection,\n} from '@happyvertical/smrt-users';\nimport { json, type RequestHandler } from '@sveltejs/kit';\nimport type { RuntimeDiagnostics } from '../runtime-diagnostics.js';\nimport type {\n ApplicationRuntimeDiagnosticsOptions,\n SmrtSvelteKitRuntime,\n} from './runtime.js';\n\n/** Explicit permission that grants diagnostics read without the owner role. */\nexport const RUNTIME_DIAGNOSTICS_READ_PERMISSION = 'runtime_diagnostics.read';\n\n/**\n * Mount as `src/routes/api/_runtime/health/+server.ts`:\n * `export const GET = createRuntimeHealthHandler(runtime);`\n *\n * Local responses add the application ID, managed process instance, and the\n * secret-free configuration fingerprint that process managers compare.\n * Deployed responses expose only schema version, status, and profile.\n */\nexport function createRuntimeHealthHandler(\n runtime: Pick<SmrtSvelteKitRuntime, 'health'>,\n): RequestHandler {\n return async () => json(await runtime.health());\n}\n\n/** The locals the diagnostics route authorizes against. */\nexport interface DiagnosticsPrincipalLocals {\n readonly user?: { readonly id?: unknown } | null;\n readonly membership?: {\n readonly userId?: unknown;\n readonly tenantId?: unknown;\n readonly roleId?: unknown;\n isActive?: () => boolean;\n } | null;\n readonly permissions?: readonly string[];\n readonly tenantId?: unknown;\n readonly sessionId?: unknown;\n}\n\ntype DiagnosticsInputValue<T> = T | (() => T);\n\nexport interface RuntimeDiagnosticsHandlerOptions {\n /** Supplies default diagnostics reading and owner-role lookup. */\n readonly runtime?: Pick<\n SmrtSvelteKitRuntime,\n 'readDiagnostics' | 'classOptions'\n >;\n /** Replace the runtime projection (must already be the public allowlist). */\n readonly readDiagnostics?: () => Promise<RuntimeDiagnostics>;\n /** Replace the owner-role lookup. Thrown errors deny. */\n readonly resolveRoleSlug?: (roleId: string) => Promise<string | null>;\n /** Override where the principal comes from. Defaults to `event.locals`. */\n readonly resolveLocals?: (event: {\n readonly locals: unknown;\n }) => DiagnosticsPrincipalLocals;\n /** Public tool inventory (sorted/capped by the projector). */\n readonly toolNames?: DiagnosticsInputValue<readonly string[]>;\n readonly schemaStatus?: DiagnosticsInputValue<\n ApplicationRuntimeDiagnosticsOptions['schemaStatus']\n >;\n readonly migrationStatus?: DiagnosticsInputValue<\n ApplicationRuntimeDiagnosticsOptions['migrationStatus']\n >;\n readonly workerHeartbeatAt?: () => Date | string | null | undefined;\n readonly recentErrors?: () => ApplicationRuntimeDiagnosticsOptions['recentErrors'];\n /** Testable clock. */\n readonly now?: () => Date;\n}\n\nfunction resolveInputValue<T>(\n value: DiagnosticsInputValue<T> | undefined,\n): T | undefined {\n return typeof value === 'function' ? (value as () => T)() : value;\n}\n\n/**\n * Mount as `src/routes/api/_runtime/diagnostics/+server.ts`:\n * `export const GET = createRuntimeDiagnosticsHandler({ runtime });`\n *\n * Authentication and authorization always complete before the private runtime\n * is read. Authorized callers hold `runtime_diagnostics.read` or the `owner`\n * role of their active, session-matching membership. Every failure is a\n * stable `{ schemaVersion: 1, error: { code } }` body.\n */\nexport function createRuntimeDiagnosticsHandler(\n options: RuntimeDiagnosticsHandlerOptions,\n): RequestHandler {\n const runtime = options.runtime;\n const readDiagnostics =\n options.readDiagnostics ??\n (runtime\n ? () =>\n runtime.readDiagnostics({\n toolNames: resolveInputValue(options.toolNames) ?? [],\n observedAt: options.now?.() ?? new Date(),\n schemaStatus: resolveInputValue(options.schemaStatus) ?? 'unknown',\n migrationStatus:\n resolveInputValue(options.migrationStatus) ?? 'unknown',\n workerHeartbeatAt: options.workerHeartbeatAt?.() ?? null,\n recentErrors: options.recentErrors?.() ?? [],\n })\n : undefined);\n const resolveRoleSlug =\n options.resolveRoleSlug ??\n (runtime\n ? async (roleId: string) => {\n const config = runtime.classOptions('Role');\n const requestDb = getRequestScopedDatabase();\n const roles = await RoleCollection.create(\n requestDb\n ? { ...config, db: requestDb as typeof config.db }\n : config,\n );\n return (await roles.findById(roleId))?.slug ?? null;\n }\n : undefined);\n if (!readDiagnostics || !resolveRoleSlug) {\n throw new TypeError(\n 'createRuntimeDiagnosticsHandler requires `runtime`, or both `readDiagnostics` and `resolveRoleSlug`.',\n );\n }\n const resolveLocals =\n options.resolveLocals ??\n ((event: { readonly locals: unknown }) =>\n event.locals as DiagnosticsPrincipalLocals);\n\n return async (event) => {\n const locals = resolveLocals(event);\n const principal = authenticatedPrincipal(locals);\n if (!principal) return stableError(401, 'authentication_required');\n\n let authorized =\n locals.permissions?.includes(RUNTIME_DIAGNOSTICS_READ_PERMISSION) ===\n true;\n if (!authorized) {\n try {\n authorized = (await resolveRoleSlug(principal.roleId)) === 'owner';\n } catch {\n authorized = false;\n }\n }\n if (!authorized) return stableError(403, 'authorization_denied');\n\n try {\n return json(await readDiagnostics());\n } catch {\n return stableError(503, 'diagnostics_unavailable');\n }\n };\n}\n\nfunction authenticatedPrincipal(\n locals: DiagnosticsPrincipalLocals | null | undefined,\n): { roleId: string } | null {\n const userId = locals?.user?.id;\n const tenantId = locals?.tenantId;\n const sessionId = locals?.sessionId;\n const membership = locals?.membership;\n if (\n typeof userId !== 'string' ||\n !userId ||\n typeof tenantId !== 'string' ||\n !tenantId ||\n typeof sessionId !== 'string' ||\n !sessionId ||\n !membership ||\n membership.userId !== userId ||\n membership.tenantId !== tenantId ||\n typeof membership.roleId !== 'string' ||\n !membership.roleId\n ) {\n return null;\n }\n try {\n if (membership.isActive?.() !== true) return null;\n } catch {\n return null;\n }\n return { roleId: membership.roleId };\n}\n\nfunction stableError(status: number, code: string): Response {\n return json({ schemaVersion: 1, error: { code } }, { status });\n}\n\n/** Server-owned session summary for the root layout. */\nexport interface SessionLayoutData {\n readonly session: {\n readonly authenticated: boolean;\n /** Tenant authorized by the active session. */\n readonly activeTenantId: string | null;\n /** URL-selected tenant candidate; display only, never authorization. */\n readonly selectedTenantSlug: string | null;\n /** Display identity of the signed-in user (id, email, name only). */\n readonly user: SessionLayoutUser | null;\n };\n}\n\n/**\n * The only user fields the layout data ever carries. `name` appears only when\n * `locals.user` carries one (the `User` model itself has no name; it lives on\n * the linked profile), so consumers fall back to `email`.\n */\nexport interface SessionLayoutUser {\n readonly id: string;\n readonly email: string;\n readonly name?: string;\n}\n\nfunction layoutUser(user: unknown): SessionLayoutUser | null {\n if (!user || typeof user !== 'object') return null;\n const { id, email, name } = user as Record<string, unknown>;\n if (typeof id !== 'string' || typeof email !== 'string') return null;\n return {\n id,\n email,\n ...(typeof name === 'string' && name ? { name } : {}),\n };\n}\n\n/**\n * Mount as `src/routes/+layout.server.ts`:\n * `export const load = createSessionLayoutLoad();`\n */\nexport function createSessionLayoutLoad(): (event: {\n readonly locals: unknown;\n}) => SessionLayoutData {\n return ({ locals }) => {\n const value = locals as {\n user?: unknown;\n tenantId?: string | null;\n selectedTenantSlug?: string | null;\n };\n return {\n session: {\n authenticated: Boolean(value.user),\n activeTenantId: value.tenantId ?? null,\n selectedTenantSlug: value.selectedTenantSlug ?? null,\n user: layoutUser(value.user),\n },\n };\n };\n}\n","/**\n * Server half of the local owner-setup page (`src/routes/setup/+page.server.ts`).\n *\n * Owner bootstrap is local-profile only, loopback-only, and single-use. The\n * runtime stores only an HMAC of the short-lived token; this module never\n * stores, logs, or returns claim errors, and it re-checks loopback custody on\n * every request instead of trusting the bind host alone.\n */\n\nimport {\n type LocalOwnerClaimResult,\n LocalRuntimeError,\n removeOnboardingHandoff,\n} from '@happyvertical/smrt-app-runtime';\nimport type { Cookies } from '@sveltejs/kit';\nimport { type ActionFailure, fail, redirect } from '@sveltejs/kit';\nimport type { SmrtSvelteKitRuntime } from './runtime.js';\n\n/** Data returned by the setup page `load`. */\nexport interface OwnerSetupPageData {\n /** False when setup is claimed, disabled (deployed), or not loopback. */\n readonly available: boolean;\n /** One-time token from `?token=` (empty unless available). */\n readonly token: string;\n /**\n * State of the setup link, so the page can explain a dead link instead of\n * offering a form that cannot succeed. `ready`: a token is present and the\n * invitation has not expired (the token itself is verified on submit);\n * `missing`: no `?token=`; `expired`: the invitation lapsed; `unavailable`:\n * claimed, disabled, or not a loopback request.\n */\n readonly link: OwnerSetupLinkState;\n}\n\nexport type OwnerSetupLinkState =\n | 'ready'\n | 'missing'\n | 'expired'\n | 'unavailable';\n\n/** Stable failure codes returned by the setup action. */\nexport type OwnerSetupErrorCode =\n /** Not the local profile (HTTP 404). */\n | 'setup_disabled'\n /** Request is not from a loopback client on a loopback host (HTTP 403). */\n | 'setup_unavailable'\n /** Missing token, blank name, or email without `@` (HTTP 400). */\n | 'setup_invalid_input'\n /** Token wrong, expired, or already used; owner already claimed (HTTP 400). */\n | 'setup_invalid'\n /** The bootstrap tenant slug already exists (HTTP 409). */\n | 'setup_conflict';\n\n/** `form` data returned with `fail(status, …)`. */\nexport interface OwnerSetupFailure {\n readonly code: OwnerSetupErrorCode;\n /** Fixed, secret-free message; never claim error text. */\n readonly message: string;\n}\n\n/** Form field names posted to the setup action. */\nexport const OWNER_SETUP_FIELDS = Object.freeze({\n token: 'token',\n name: 'name',\n email: 'email',\n password: 'password',\n tenantName: 'tenantName',\n} as const);\n\nexport const DEFAULT_OWNER_SETUP_MESSAGES: Readonly<\n Record<OwnerSetupErrorCode, string>\n> = Object.freeze({\n setup_disabled: 'Local owner setup is disabled.',\n setup_unavailable: 'Local owner setup is available only from this device.',\n setup_invalid_input: 'Name, email, and a valid setup token are required.',\n setup_invalid:\n 'The setup invitation is invalid, expired, or already used. Run pnpm app:stop, pnpm app:recover, pnpm app:start, then pnpm app:open.',\n setup_conflict:\n 'A workspace with the configured owner tenant slug already exists. Configure ownerTenant with another slug or adoptExisting.',\n});\n\n/** The request fields the setup page reads. */\nexport interface OwnerSetupEvent {\n readonly url: URL;\n readonly locals: unknown;\n getClientAddress(): string;\n}\n\nexport interface OwnerSetupActionEvent extends OwnerSetupEvent {\n readonly request: Request;\n readonly cookies: Pick<Cookies, 'set'>;\n}\n\nexport interface OwnerSetupPageOptions {\n /** Require an initial owner password. Default false for existing bootstrap consumers. */\n readonly requirePassword?: boolean;\n /** Where a signed-in visitor or a successful claim is sent. Default `/`. */\n readonly redirectTo?: string;\n /** Replace fixed failure messages (for example app-specific recovery steps). */\n readonly messages?: Partial<Record<OwnerSetupErrorCode, string>>;\n /** Override where the signed-in user comes from. Defaults to `locals.user`. */\n readonly resolveUser?: (event: OwnerSetupEvent) => unknown;\n /**\n * Set false to keep the `smrt app` onboarding hand-off files after a claim.\n * By default the runtime removes `onboarding.json` and\n * `onboarding-launch.html` from the private state root once the claim has\n * committed, so `pnpm app:open` stops offering the spent invitation.\n */\n readonly removeOnboardingHandoff?: boolean;\n /**\n * Best-effort extra cleanup after a successful claim (the hand-off files are\n * already removed by default). Errors are ignored: the owner and session are\n * already authoritative and a stale token now fails closed.\n */\n readonly onOwnerClaimed?: (\n result: LocalOwnerClaimResult,\n event: OwnerSetupActionEvent,\n ) => void | Promise<void>;\n}\n\nexport interface OwnerSetupPage {\n readonly load: (event: OwnerSetupEvent) => Promise<OwnerSetupPageData>;\n readonly actions: {\n readonly default: (\n event: OwnerSetupActionEvent,\n ) => Promise<ActionFailure<OwnerSetupFailure>>;\n };\n}\n\n/**\n * Mount as `src/routes/setup/+page.server.ts`:\n *\n * ```ts\n * import { createOwnerSetupPage } from '@happyvertical/smrt-app-runtime/sveltekit';\n * import { runtime } from '../../hooks.server';\n *\n * export const { load, actions } = createOwnerSetupPage(runtime);\n * ```\n *\n * The form posts to the `default` action with fields `token` (hidden),\n * `name`, `email`, and optional `password` and `tenantName`. Set\n * `requirePassword: true` for password-based applications. Success sets the session cookie\n * and redirects 303; failures return `fail(status, { code, message })`.\n */\nexport function createOwnerSetupPage(\n runtime: Pick<\n SmrtSvelteKitRuntime,\n 'resolvedRuntime' | 'localRuntime' | 'sessionCookie'\n > &\n Partial<Pick<SmrtSvelteKitRuntime, 'applicationStateRoot'>>,\n options: OwnerSetupPageOptions = {},\n): OwnerSetupPage {\n const redirectTo = options.redirectTo ?? '/';\n const messages = { ...DEFAULT_OWNER_SETUP_MESSAGES, ...options.messages };\n const failure = (status: number, code: OwnerSetupErrorCode) =>\n fail(status, { code, message: messages[code] } as OwnerSetupFailure);\n const resolveUser =\n options.resolveUser ??\n ((event: OwnerSetupEvent) => (event.locals as { user?: unknown }).user);\n\n const load = async (event: OwnerSetupEvent): Promise<OwnerSetupPageData> => {\n if (resolveUser(event)) redirect(303, redirectTo);\n const resolved = await runtime.resolvedRuntime();\n if (resolved.profile !== 'local' || !isLoopbackRequest(event)) {\n return { available: false, token: '', link: 'unavailable' };\n }\n const local = await runtime.localRuntime();\n const diagnostics = await local.diagnostics();\n const status = diagnostics.bootstrap.status;\n if (status === 'claimed') {\n return { available: false, token: '', link: 'unavailable' };\n }\n const token = event.url.searchParams.get(OWNER_SETUP_FIELDS.token) || '';\n if (status === 'expired')\n return { available: true, token: '', link: 'expired' };\n if (!token) return { available: true, token: '', link: 'missing' };\n return { available: true, token, link: 'ready' };\n };\n\n const claim = async (\n event: OwnerSetupActionEvent,\n ): Promise<ActionFailure<OwnerSetupFailure>> => {\n const resolved = await runtime.resolvedRuntime();\n if (resolved.profile !== 'local') return failure(404, 'setup_disabled');\n if (!isLoopbackRequest(event)) return failure(403, 'setup_unavailable');\n\n let form: FormData;\n try {\n form = await event.request.formData();\n } catch {\n return failure(400, 'setup_invalid_input');\n }\n const field = (name: string) => {\n const value = form.get(name);\n return typeof value === 'string' ? value : '';\n };\n const token = field(OWNER_SETUP_FIELDS.token);\n const name = field(OWNER_SETUP_FIELDS.name);\n const email = field(OWNER_SETUP_FIELDS.email);\n const password = field(OWNER_SETUP_FIELDS.password);\n const tenantName = field(OWNER_SETUP_FIELDS.tenantName).trim();\n if (\n !token ||\n !name.trim() ||\n !email.includes('@') ||\n (options.requirePassword && !password)\n ) {\n return failure(400, 'setup_invalid_input');\n }\n\n const local = await runtime.localRuntime();\n let result: LocalOwnerClaimResult;\n try {\n result = await local.claimOwner({\n token,\n name,\n email,\n password,\n ...(tenantName ? { tenantName } : {}),\n userAgent: event.request.headers.get('user-agent') || undefined,\n ipAddress: event.getClientAddress(),\n });\n } catch (error) {\n if (\n error instanceof LocalRuntimeError &&\n error.code === 'owner_tenant_conflict'\n ) {\n return failure(409, 'setup_conflict');\n }\n return failure(400, 'setup_invalid');\n }\n\n // claimOwner resolved, so the claim transaction has committed. Clean up\n // before cookie serialization, which can throw on a malformed config.\n if (\n options.removeOnboardingHandoff !== false &&\n runtime.applicationStateRoot\n ) {\n try {\n removeOnboardingHandoff(runtime.applicationStateRoot());\n } catch {\n // Best effort: the spent token already fails closed.\n }\n }\n const cookie = runtime.sessionCookie;\n event.cookies.set(cookie.name, result.sessionId, {\n path: cookie.path,\n ...(cookie.domain ? { domain: cookie.domain } : {}),\n httpOnly: true,\n secure: cookie.secure ?? event.url.protocol === 'https:',\n sameSite: cookie.sameSite,\n maxAge: cookie.maxAgeSeconds,\n });\n try {\n await options.onOwnerClaimed?.(result, event);\n } catch {\n // Best effort only; see OwnerSetupPageOptions.onOwnerClaimed.\n }\n redirect(303, redirectTo);\n };\n\n return Object.freeze({\n load,\n actions: Object.freeze({ default: claim }),\n });\n}\n\n/**\n * True only when both the peer address and the addressed host are loopback.\n * The host check rejects tunnels and DNS-rebinding hosts that forward to a\n * loopback listener; a throwing `getClientAddress` is treated as remote.\n */\nexport function isLoopbackRequest(event: {\n readonly url: URL;\n getClientAddress(): string;\n}): boolean {\n let address: string;\n try {\n address = event.getClientAddress();\n } catch {\n return false;\n }\n return isLoopbackAddress(address) && isLoopbackHostname(event.url.hostname);\n}\n\n/** Loopback IP literal: `127.0.0.0/8`, `::1`, or IPv4-mapped `127/8`. */\nexport function isLoopbackAddress(value: string | null | undefined): boolean {\n if (typeof value !== 'string') return false;\n let host = value\n .trim()\n .toLowerCase()\n .replace(/^\\[|\\]$/g, '');\n if (host === '::1' || host === '0:0:0:0:0:0:0:1') return true;\n if (host.startsWith('::ffff:')) host = host.slice('::ffff:'.length);\n const octets = host.split('.');\n return (\n octets.length === 4 &&\n octets.every((part) => /^\\d{1,3}$/.test(part) && Number(part) <= 255) &&\n Number(octets[0]) === 127\n );\n}\n\n/** Loopback host name as SvelteKit reports it in `url.hostname`. */\nexport function isLoopbackHostname(hostname: string): boolean {\n const host = hostname.trim().toLowerCase().replace(/\\.$/, '');\n return host === 'localhost' || isLoopbackAddress(host);\n}\n","/**\n * Sign-out route handler: destroys the current session and clears its cookie\n * with the same cookie attributes the owner-setup action used to set it.\n */\n\nimport { destroySessionCookie } from '@happyvertical/smrt-users/sveltekit';\nimport { type RequestHandler, redirect } from '@sveltejs/kit';\nimport type { SmrtSvelteKitRuntime } from './runtime.js';\n\n/** True when the browser says the request came from this origin. */\nfunction isSameOriginRequest(request: Request, url: URL): boolean {\n const site = request.headers.get('sec-fetch-site');\n if (site !== null) return site === 'same-origin';\n const origin = request.headers.get('origin');\n return origin !== null && origin === url.origin;\n}\n\n/**\n * Mount as `src/routes/sign-out/+server.ts`:\n * `export const POST = createSignOutHandler(runtime);`\n *\n * `POST` only (other methods answer 405) and same-origin only (403 otherwise).\n * The session row is destroyed best-effort and the cookie is cleared even when\n * the row is already gone. Answers 204, or a 303 to `/` when the request\n * accepts HTML so a no-JS form post lands on the home page.\n */\nexport function createSignOutHandler(\n runtime: Pick<SmrtSvelteKitRuntime, 'sessionCookie' | 'classOptions'>,\n): RequestHandler {\n return async (event) => {\n if (event.request.method !== 'POST') {\n return new Response('Method not allowed', {\n status: 405,\n headers: { allow: 'POST' },\n });\n }\n if (!isSameOriginRequest(event.request, event.url)) {\n return new Response('Forbidden', { status: 403 });\n }\n const cookie = runtime.sessionCookie;\n await destroySessionCookie(\n event as unknown as Parameters<typeof destroySessionCookie>[0],\n {\n ...runtime.classOptions('Session'),\n cookieName: cookie.name,\n cookiePath: cookie.path,\n ...(cookie.domain ? { cookieDomain: cookie.domain } : {}),\n },\n );\n // `delete` omits the Secure flag the setup action used; re-issue the\n // expiry with the same attributes so browsers match and drop the cookie.\n event.cookies.set(cookie.name, '', {\n path: cookie.path,\n ...(cookie.domain ? { domain: cookie.domain } : {}),\n httpOnly: true,\n secure: cookie.secure ?? event.url.protocol === 'https:',\n sameSite: cookie.sameSite,\n maxAge: 0,\n });\n if (event.request.headers.get('accept')?.includes('text/html')) {\n redirect(303, '/');\n }\n return new Response(null, { status: 204 });\n };\n}\n"],"mappings":";;;;;;;AAiBO,IAAM,sCAAsC;AAU5C,SAAS,2BACd,SACgB;CAChB,OAAO,YAAY,KAAK,MAAM,QAAQ,OAAO,CAAC;AAChD;AA8CA,SAAS,kBACP,OACe;CACf,OAAO,OAAO,UAAU,aAAc,MAAkB,IAAI;AAC9D;AAWO,SAAS,gCACd,SACgB;CAChB,MAAM,UAAU,QAAQ;CACxB,MAAM,kBACJ,QAAQ,oBACP,gBAEK,QAAQ,gBAAgB;EACtB,WAAW,kBAAkB,QAAQ,SAAS,KAAK,CAAC;EACpD,YAAY,QAAQ,MAAM,qBAAK,IAAI,KAAK;EACxC,cAAc,kBAAkB,QAAQ,YAAY,KAAK;EACzD,iBACE,kBAAkB,QAAQ,eAAe,KAAK;EAChD,mBAAmB,QAAQ,oBAAoB,KAAK;EACpD,cAAc,QAAQ,eAAe,KAAK,CAAC;CAC7C,CAAC,IACH,KAAA;CACN,MAAM,kBACJ,QAAQ,oBACP,UACG,OAAO,WAAmB;EACxB,MAAM,SAAS,QAAQ,aAAa,MAAM;EAC1C,MAAM,YAAY,yBAAyB;EAM3C,QAAQ,OAAM,MALM,eAAe,OACjC,YACI;GAAE,GAAG;GAAQ,IAAI;EAA8B,IAC/C,MACN,EAAA,CACoB,SAAS,MAAM,EAAA,EAAI,QAAQ;CACjD,IACA,KAAA;CACN,IAAI,CAAC,mBAAmB,CAAC,iBACvB,MAAM,IAAI,UACR,sGACF;CAEF,MAAM,gBACJ,QAAQ,mBACN,UACA,MAAM;CAEV,OAAO,OAAO,UAAU;EACtB,MAAM,SAAS,cAAc,KAAK;EAClC,MAAM,YAAY,uBAAuB,MAAM;EAC/C,IAAI,CAAC,WAAW,OAAO,YAAY,KAAK,yBAAyB;EAEjE,IAAI,aACF,OAAO,aAAa,SAAS,mCAAmC,MAChE;EACF,IAAI,CAAC,YACH,IAAI;GACF,aAAc,MAAM,gBAAgB,UAAU,MAAM,MAAO;EAC7D,QAAQ;GACN,aAAa;EACf;EAEF,IAAI,CAAC,YAAY,OAAO,YAAY,KAAK,sBAAsB;EAE/D,IAAI;GACF,OAAO,KAAK,MAAM,gBAAgB,CAAC;EACrC,QAAQ;GACN,OAAO,YAAY,KAAK,yBAAyB;EACnD;CACF;AACF;AAEA,SAAS,uBACP,QAC2B;CAC3B,MAAM,SAAS,QAAQ,MAAM;CAC7B,MAAM,WAAW,QAAQ;CACzB,MAAM,YAAY,QAAQ;CAC1B,MAAM,aAAa,QAAQ;CAC3B,IACE,OAAO,WAAW,YAClB,CAAC,UACD,OAAO,aAAa,YACpB,CAAC,YACD,OAAO,cAAc,YACrB,CAAC,aACD,CAAC,cACD,WAAW,WAAW,UACtB,WAAW,aAAa,YACxB,OAAO,WAAW,WAAW,YAC7B,CAAC,WAAW,QAEZ,OAAO;CAET,IAAI;EACF,IAAI,WAAW,WAAW,MAAM,MAAM,OAAO;CAC/C,QAAQ;EACN,OAAO;CACT;CACA,OAAO,EAAE,QAAQ,WAAW,OAAO;AACrC;AAEA,SAAS,YAAY,QAAgB,MAAwB;CAC3D,OAAO,KAAK;EAAE,eAAe;EAAG,OAAO,EAAE,KAAK;CAAE,GAAG,EAAE,OAAO,CAAC;AAC/D;AA0BA,SAAS,WAAW,MAAyC;CAC3D,IAAI,CAAC,QAAQ,OAAO,SAAS,UAAU,OAAO;CAC9C,MAAM,EAAE,IAAI,OAAO,SAAS;CAC5B,IAAI,OAAO,OAAO,YAAY,OAAO,UAAU,UAAU,OAAO;CAChE,OAAO;EACL;EACA;EACA,GAAI,OAAO,SAAS,YAAY,OAAO,EAAE,KAAK,IAAI,CAAC;CACrD;AACF;AAMO,SAAS,0BAEQ;CACtB,QAAQ,EAAE,aAAa;EACrB,MAAM,QAAQ;EAKd,OAAO,EACL,SAAS;GACP,eAAe,QAAQ,MAAM,IAAI;GACjC,gBAAgB,MAAM,YAAY;GAClC,oBAAoB,MAAM,sBAAsB;GAChD,MAAM,WAAW,MAAM,IAAI;EAC7B,EACF;CACF;AACF;;;AC7LO,IAAM,qBAAqB,OAAO,OAAO;CAC9C,OAAO;CACP,MAAM;CACN,OAAO;CACP,UAAU;CACV,YAAY;AACd,CAAU;AAEH,IAAM,+BAET,OAAO,OAAO;CAChB,gBAAgB;CAChB,mBAAmB;CACnB,qBAAqB;CACrB,eACE;CACF,gBACE;AACJ,CAAC;AAiEM,SAAS,qBACd,SAKA,UAAiC,CAAC,GAClB;CAChB,MAAM,aAAa,QAAQ,cAAc;CACzC,MAAM,WAAW;EAAE,GAAG;EAA8B,GAAG,QAAQ;CAAS;CACxE,MAAM,WAAW,QAAgB,SAC/B,KAAK,QAAQ;EAAE;EAAM,SAAS,SAAS;CAAM,CAAsB;CACrE,MAAM,cACJ,QAAQ,iBACN,UAA4B,MAAM,OAA8B;CAEpE,MAAM,OAAO,OAAO,UAAwD;EAC1E,IAAI,YAAY,KAAK,GAAG,SAAS,KAAK,UAAU;EAEhD,KAAI,MADmB,QAAQ,gBAAgB,EAAA,CAClC,YAAY,WAAW,CAAC,kBAAkB,KAAK,GAC1D,OAAO;GAAE,WAAW;GAAO,OAAO;GAAI,MAAM;EAAc;EAI5D,MAAM,UAAS,OADW,MADN,QAAQ,aAAa,EAAA,CACT,YAAY,EAAA,CACjB,UAAU;EACrC,IAAI,WAAW,WACb,OAAO;GAAE,WAAW;GAAO,OAAO;GAAI,MAAM;EAAc;EAE5D,MAAM,QAAQ,MAAM,IAAI,aAAa,IAAI,mBAAmB,KAAK,KAAK;EACtE,IAAI,WAAW,WACb,OAAO;GAAE,WAAW;GAAM,OAAO;GAAI,MAAM;EAAU;EACvD,IAAI,CAAC,OAAO,OAAO;GAAE,WAAW;GAAM,OAAO;GAAI,MAAM;EAAU;EACjE,OAAO;GAAE,WAAW;GAAM;GAAO,MAAM;EAAQ;CACjD;CAEA,MAAM,QAAQ,OACZ,UAC8C;EAE9C,KAAI,MADmB,QAAQ,gBAAgB,EAAA,CAClC,YAAY,SAAS,OAAO,QAAQ,KAAK,gBAAgB;EACtE,IAAI,CAAC,kBAAkB,KAAK,GAAG,OAAO,QAAQ,KAAK,mBAAmB;EAEtE,IAAI;EACJ,IAAI;GACF,OAAO,MAAM,MAAM,QAAQ,SAAS;EACtC,QAAQ;GACN,OAAO,QAAQ,KAAK,qBAAqB;EAC3C;EACA,MAAM,SAASA,UAAiB;GAC9B,MAAM,QAAQ,KAAK,IAAIA,KAAI;GAC3B,OAAO,OAAO,UAAU,WAAW,QAAQ;EAC7C;EACA,MAAM,QAAQ,MAAM,mBAAmB,KAAK;EAC5C,MAAM,OAAO,MAAM,mBAAmB,IAAI;EAC1C,MAAM,QAAQ,MAAM,mBAAmB,KAAK;EAC5C,MAAM,WAAW,MAAM,mBAAmB,QAAQ;EAClD,MAAM,aAAa,MAAM,mBAAmB,UAAU,CAAA,CAAE,KAAK;EAC7D,IACE,CAAC,SACD,CAAC,KAAK,KAAK,KACX,CAAC,MAAM,SAAS,GAAG,KAClB,QAAQ,mBAAmB,CAAC,UAE7B,OAAO,QAAQ,KAAK,qBAAqB;EAG3C,MAAM,QAAQ,MAAM,QAAQ,aAAa;EACzC,IAAI;EACJ,IAAI;GACF,SAAS,MAAM,MAAM,WAAW;IAC9B;IACA;IACA;IACA;IACA,GAAI,aAAa,EAAE,WAAW,IAAI,CAAC;IACnC,WAAW,MAAM,QAAQ,QAAQ,IAAI,YAAY,KAAK,KAAA;IACtD,WAAW,MAAM,iBAAiB;GACpC,CAAC;EACH,SAAS,OAAO;GACd,IACE,iBAAiB,qBACjB,MAAM,SAAS,yBAEf,OAAO,QAAQ,KAAK,gBAAgB;GAEtC,OAAO,QAAQ,KAAK,eAAe;EACrC;EAIA,IACE,QAAQ,4BAA4B,SACpC,QAAQ,sBAER,IAAI;GACF,wBAAwB,QAAQ,qBAAqB,CAAC;EACxD,QAAQ,CAER;EAEF,MAAM,SAAS,QAAQ;EACvB,MAAM,QAAQ,IAAI,OAAO,MAAM,OAAO,WAAW;GAC/C,MAAM,OAAO;GACb,GAAI,OAAO,SAAS,EAAE,QAAQ,OAAO,OAAO,IAAI,CAAC;GACjD,UAAU;GACV,QAAQ,OAAO,UAAU,MAAM,IAAI,aAAa;GAChD,UAAU,OAAO;GACjB,QAAQ,OAAO;EACjB,CAAC;EACD,IAAI;GACF,MAAM,QAAQ,iBAAiB,QAAQ,KAAK;EAC9C,QAAQ,CAER;EACA,SAAS,KAAK,UAAU;CAC1B;CAEA,OAAO,OAAO,OAAO;EACnB;EACA,SAAS,OAAO,OAAO,EAAE,SAAS,MAAM,CAAC;CAC3C,CAAC;AACH;AAOO,SAAS,kBAAkB,OAGtB;CACV,IAAI;CACJ,IAAI;EACF,UAAU,MAAM,iBAAiB;CACnC,QAAQ;EACN,OAAO;CACT;CACA,OAAO,kBAAkB,OAAO,KAAK,mBAAmB,MAAM,IAAI,QAAQ;AAC5E;AAGO,SAAS,kBAAkB,OAA2C;CAC3E,IAAI,OAAO,UAAU,UAAU,OAAO;CACtC,IAAI,OAAO,MACR,KAAK,CAAA,CACL,YAAY,CAAA,CACZ,QAAQ,YAAY,EAAE;CACzB,IAAI,SAAS,SAAS,SAAS,mBAAmB,OAAO;CACzD,IAAI,KAAK,WAAW,SAAS,GAAG,OAAO,KAAK,MAAM,CAAgB;CAClE,MAAM,SAAS,KAAK,MAAM,GAAG;CAC7B,OACE,OAAO,WAAW,KAClB,OAAO,OAAO,SAAS,YAAY,KAAK,IAAI,KAAK,OAAO,IAAI,KAAK,GAAG,KACpE,OAAO,OAAO,EAAE,MAAM;AAE1B;AAGO,SAAS,mBAAmB,UAA2B;CAC5D,MAAM,OAAO,SAAS,KAAK,CAAA,CAAE,YAAY,CAAA,CAAE,QAAQ,OAAO,EAAE;CAC5D,OAAO,SAAS,eAAe,kBAAkB,IAAI;AACvD;;;ACxSA,SAAS,oBAAoB,SAAkB,KAAmB;CAChE,MAAM,OAAO,QAAQ,QAAQ,IAAI,gBAAgB;CACjD,IAAI,SAAS,MAAM,OAAO,SAAS;CACnC,MAAM,SAAS,QAAQ,QAAQ,IAAI,QAAQ;CAC3C,OAAO,WAAW,QAAQ,WAAW,IAAI;AAC3C;AAWO,SAAS,qBACd,SACgB;CAChB,OAAO,OAAO,UAAU;EACtB,IAAI,MAAM,QAAQ,WAAW,QAC3B,OAAO,IAAI,SAAS,sBAAsB;GACxC,QAAQ;GACR,SAAS,EAAE,OAAO,OAAO;EAC3B,CAAC;EAEH,IAAI,CAAC,oBAAoB,MAAM,SAAS,MAAM,GAAG,GAC/C,OAAO,IAAI,SAAS,aAAa,EAAE,QAAQ,IAAI,CAAC;EAElD,MAAM,SAAS,QAAQ;EACvB,MAAM,qBACJ,OACA;GACE,GAAG,QAAQ,aAAa,SAAS;GACjC,YAAY,OAAO;GACnB,YAAY,OAAO;GACnB,GAAI,OAAO,SAAS,EAAE,cAAc,OAAO,OAAO,IAAI,CAAC;EACzD,CACF;EAGA,MAAM,QAAQ,IAAI,OAAO,MAAM,IAAI;GACjC,MAAM,OAAO;GACb,GAAI,OAAO,SAAS,EAAE,QAAQ,OAAO,OAAO,IAAI,CAAC;GACjD,UAAU;GACV,QAAQ,OAAO,UAAU,MAAM,IAAI,aAAa;GAChD,UAAU,OAAO;GACjB,QAAQ;EACV,CAAC;EACD,IAAI,MAAM,QAAQ,QAAQ,IAAI,QAAQ,CAAA,EAAG,SAAS,WAAW,GAC3D,SAAS,KAAK,GAAG;EAEnB,OAAO,IAAI,SAAS,MAAM,EAAE,QAAQ,IAAI,CAAC;CAC3C;AACF"}
1
+ {"version":3,"file":"sveltekit.js","names":["name"],"sources":["../src/sveltekit/handlers.ts","../src/sveltekit/owner-setup.ts","../src/sveltekit/sign-out.ts"],"sourcesContent":["/**\n * Mountable runtime routes: liveness health, authorized diagnostics, and the\n * server-owned session summary for the root layout.\n */\n\nimport {\n getRequestScopedDatabase,\n RoleCollection,\n} from '@happyvertical/smrt-users';\nimport { json, type RequestHandler } from '@sveltejs/kit';\nimport type { RuntimeDiagnostics } from '../runtime-diagnostics.js';\nimport type {\n ApplicationRuntimeDiagnosticsOptions,\n SmrtSvelteKitRuntime,\n} from './runtime.js';\n\n/** Explicit permission that grants diagnostics read without the owner role. */\nexport const RUNTIME_DIAGNOSTICS_READ_PERMISSION = 'runtime_diagnostics.read';\n\n/**\n * Mount as `src/routes/api/_runtime/health/+server.ts`:\n * `export const GET = createRuntimeHealthHandler(runtime);`\n *\n * Local responses add the application ID, managed process instance, and the\n * secret-free configuration fingerprint that process managers compare.\n * Deployed responses expose only schema version, status, and profile.\n */\nexport function createRuntimeHealthHandler(\n runtime: Pick<SmrtSvelteKitRuntime, 'health'>,\n): RequestHandler {\n return async () => json(await runtime.health());\n}\n\n/** The locals the diagnostics route authorizes against. */\nexport interface DiagnosticsPrincipalLocals {\n readonly user?: { readonly id?: unknown } | null;\n readonly membership?: {\n readonly userId?: unknown;\n readonly tenantId?: unknown;\n readonly roleId?: unknown;\n isActive?: () => boolean;\n } | null;\n readonly permissions?: readonly string[];\n readonly tenantId?: unknown;\n readonly sessionId?: unknown;\n}\n\ntype DiagnosticsInputValue<T> = T | (() => T);\n\nexport interface RuntimeDiagnosticsHandlerOptions {\n /** Supplies default diagnostics reading and owner-role lookup. */\n readonly runtime?: Pick<\n SmrtSvelteKitRuntime,\n 'readDiagnostics' | 'classOptions'\n >;\n /** Replace the runtime projection (must already be the public allowlist). */\n readonly readDiagnostics?: () => Promise<RuntimeDiagnostics>;\n /** Replace the owner-role lookup. Thrown errors deny. */\n readonly resolveRoleSlug?: (roleId: string) => Promise<string | null>;\n /** Override where the principal comes from. Defaults to `event.locals`. */\n readonly resolveLocals?: (event: {\n readonly locals: unknown;\n }) => DiagnosticsPrincipalLocals;\n /** Public tool inventory (sorted/capped by the projector). */\n readonly toolNames?: DiagnosticsInputValue<readonly string[]>;\n readonly schemaStatus?: DiagnosticsInputValue<\n ApplicationRuntimeDiagnosticsOptions['schemaStatus']\n >;\n readonly migrationStatus?: DiagnosticsInputValue<\n ApplicationRuntimeDiagnosticsOptions['migrationStatus']\n >;\n readonly workerHeartbeatAt?: () => Date | string | null | undefined;\n readonly recentErrors?: () => ApplicationRuntimeDiagnosticsOptions['recentErrors'];\n /** Testable clock. */\n readonly now?: () => Date;\n}\n\nfunction resolveInputValue<T>(\n value: DiagnosticsInputValue<T> | undefined,\n): T | undefined {\n return typeof value === 'function' ? (value as () => T)() : value;\n}\n\n/**\n * Mount as `src/routes/api/_runtime/diagnostics/+server.ts`:\n * `export const GET = createRuntimeDiagnosticsHandler({ runtime });`\n *\n * Authentication and authorization always complete before the private runtime\n * is read. Authorized callers hold `runtime_diagnostics.read` or the `owner`\n * role of their active, session-matching membership. Every failure is a\n * stable `{ schemaVersion: 1, error: { code } }` body.\n */\nexport function createRuntimeDiagnosticsHandler(\n options: RuntimeDiagnosticsHandlerOptions,\n): RequestHandler {\n const runtime = options.runtime;\n const readDiagnostics =\n options.readDiagnostics ??\n (runtime\n ? () =>\n runtime.readDiagnostics({\n toolNames: resolveInputValue(options.toolNames) ?? [],\n observedAt: options.now?.() ?? new Date(),\n schemaStatus: resolveInputValue(options.schemaStatus) ?? 'unknown',\n migrationStatus:\n resolveInputValue(options.migrationStatus) ?? 'unknown',\n workerHeartbeatAt: options.workerHeartbeatAt?.() ?? null,\n recentErrors: options.recentErrors?.() ?? [],\n })\n : undefined);\n const resolveRoleSlug =\n options.resolveRoleSlug ??\n (runtime\n ? async (roleId: string) => {\n const config = runtime.classOptions('Role');\n const requestDb = getRequestScopedDatabase();\n const roles = await RoleCollection.create(\n requestDb\n ? { ...config, db: requestDb as typeof config.db }\n : config,\n );\n return (await roles.findById(roleId))?.slug ?? null;\n }\n : undefined);\n if (!readDiagnostics || !resolveRoleSlug) {\n throw new TypeError(\n 'createRuntimeDiagnosticsHandler requires `runtime`, or both `readDiagnostics` and `resolveRoleSlug`.',\n );\n }\n const resolveLocals =\n options.resolveLocals ??\n ((event: { readonly locals: unknown }) =>\n event.locals as DiagnosticsPrincipalLocals);\n\n return async (event) => {\n const locals = resolveLocals(event);\n const principal = authenticatedPrincipal(locals);\n if (!principal) return stableError(401, 'authentication_required');\n\n let authorized =\n locals.permissions?.includes(RUNTIME_DIAGNOSTICS_READ_PERMISSION) ===\n true;\n if (!authorized) {\n try {\n authorized = (await resolveRoleSlug(principal.roleId)) === 'owner';\n } catch {\n authorized = false;\n }\n }\n if (!authorized) return stableError(403, 'authorization_denied');\n\n try {\n return json(await readDiagnostics());\n } catch {\n return stableError(503, 'diagnostics_unavailable');\n }\n };\n}\n\nfunction authenticatedPrincipal(\n locals: DiagnosticsPrincipalLocals | null | undefined,\n): { roleId: string } | null {\n const userId = locals?.user?.id;\n const tenantId = locals?.tenantId;\n const sessionId = locals?.sessionId;\n const membership = locals?.membership;\n if (\n typeof userId !== 'string' ||\n !userId ||\n typeof tenantId !== 'string' ||\n !tenantId ||\n typeof sessionId !== 'string' ||\n !sessionId ||\n !membership ||\n membership.userId !== userId ||\n membership.tenantId !== tenantId ||\n typeof membership.roleId !== 'string' ||\n !membership.roleId\n ) {\n return null;\n }\n try {\n if (membership.isActive?.() !== true) return null;\n } catch {\n return null;\n }\n return { roleId: membership.roleId };\n}\n\nfunction stableError(status: number, code: string): Response {\n return json({ schemaVersion: 1, error: { code } }, { status });\n}\n\n/** Server-owned session summary for the root layout. */\nexport interface SessionLayoutData {\n readonly session: {\n readonly authenticated: boolean;\n /** Tenant authorized by the active session. */\n readonly activeTenantId: string | null;\n /** URL-selected tenant candidate; display only, never authorization. */\n readonly selectedTenantSlug: string | null;\n /** Display identity of the signed-in user (id, email, name only). */\n readonly user: SessionLayoutUser | null;\n };\n}\n\n/**\n * The only user fields the layout data ever carries. `name` appears only when\n * `locals.user` carries one (the `User` model itself has no name; it lives on\n * the linked profile), so consumers fall back to `email`.\n */\nexport interface SessionLayoutUser {\n readonly id: string;\n readonly email: string;\n readonly name?: string;\n}\n\nfunction layoutUser(user: unknown): SessionLayoutUser | null {\n if (!user || typeof user !== 'object') return null;\n const { id, email, name } = user as Record<string, unknown>;\n if (typeof id !== 'string' || typeof email !== 'string') return null;\n return {\n id,\n email,\n ...(typeof name === 'string' && name ? { name } : {}),\n };\n}\n\n/**\n * Mount as `src/routes/+layout.server.ts`:\n * `export const load = createSessionLayoutLoad();`\n */\nexport function createSessionLayoutLoad(): (event: {\n readonly locals: unknown;\n}) => SessionLayoutData {\n return ({ locals }) => {\n const value = locals as {\n user?: unknown;\n tenantId?: string | null;\n selectedTenantSlug?: string | null;\n };\n return {\n session: {\n authenticated: Boolean(value.user),\n activeTenantId: value.tenantId ?? null,\n selectedTenantSlug: value.selectedTenantSlug ?? null,\n user: layoutUser(value.user),\n },\n };\n };\n}\n","/**\n * Server half of the local owner-setup page (`src/routes/setup/+page.server.ts`).\n *\n * Owner bootstrap is local-profile only, loopback-only, and single-use. The\n * runtime stores only an HMAC of the short-lived token; this module never\n * stores, logs, or returns claim errors, and it re-checks loopback custody on\n * every request instead of trusting the bind host alone.\n */\n\nimport {\n type LocalOwnerClaimResult,\n LocalRuntimeError,\n removeOnboardingHandoff,\n} from '@happyvertical/smrt-app-runtime';\nimport type { Cookies } from '@sveltejs/kit';\nimport { type ActionFailure, fail, redirect } from '@sveltejs/kit';\nimport type { SmrtSvelteKitRuntime } from './runtime.js';\n\n/** Data returned by the setup page `load`. */\nexport interface OwnerSetupPageData {\n /** False when setup is claimed, disabled (deployed), or not loopback. */\n readonly available: boolean;\n /** One-time token from `?token=` (empty unless available). */\n readonly token: string;\n /**\n * State of the setup link, so the page can explain a dead link instead of\n * offering a form that cannot succeed. `ready`: a token is present and the\n * invitation has not expired (the token itself is verified on submit);\n * `missing`: no `?token=`; `expired`: the invitation lapsed; `unavailable`:\n * claimed, disabled, or not a loopback request.\n */\n readonly link: OwnerSetupLinkState;\n}\n\nexport type OwnerSetupLinkState =\n | 'ready'\n | 'missing'\n | 'expired'\n | 'unavailable';\n\n/** Stable failure codes returned by the setup action. */\nexport type OwnerSetupErrorCode =\n /** Not the local profile (HTTP 404). */\n | 'setup_disabled'\n /** Request is not from a loopback client on a loopback host (HTTP 403). */\n | 'setup_unavailable'\n /** Missing token, blank name, or email without `@` (HTTP 400). */\n | 'setup_invalid_input'\n /** Token wrong, expired, or already used; owner already claimed (HTTP 400). */\n | 'setup_invalid'\n /** The bootstrap tenant slug already exists (HTTP 409). */\n | 'setup_conflict';\n\n/** `form` data returned with `fail(status, …)`. */\nexport interface OwnerSetupFailure {\n readonly code: OwnerSetupErrorCode;\n /** Fixed, secret-free message; never claim error text. */\n readonly message: string;\n}\n\n/** Form field names posted to the setup action. */\nexport const OWNER_SETUP_FIELDS = Object.freeze({\n token: 'token',\n name: 'name',\n email: 'email',\n password: 'password',\n tenantName: 'tenantName',\n} as const);\n\nexport const DEFAULT_OWNER_SETUP_MESSAGES: Readonly<\n Record<OwnerSetupErrorCode, string>\n> = Object.freeze({\n setup_disabled: 'Local owner setup is disabled.',\n setup_unavailable: 'Local owner setup is available only from this device.',\n setup_invalid_input: 'Name, email, and a valid setup token are required.',\n setup_invalid:\n 'The setup invitation is invalid, expired, or already used. Run pnpm app:stop, pnpm app:recover, pnpm app:start, then pnpm app:open.',\n setup_conflict:\n 'A workspace with the configured owner tenant slug already exists. Configure ownerTenant with another slug or adoptExisting.',\n});\n\n/** The request fields the setup page reads. */\nexport interface OwnerSetupEvent {\n readonly url: URL;\n readonly locals: unknown;\n getClientAddress(): string;\n}\n\nexport interface OwnerSetupActionEvent extends OwnerSetupEvent {\n readonly request: Request;\n readonly cookies: Pick<Cookies, 'set'>;\n}\n\nexport interface OwnerSetupPageOptions {\n /** Require an initial owner password. Default false for existing bootstrap consumers. */\n readonly requirePassword?: boolean;\n /** Where a signed-in visitor or a successful claim is sent. Default `/`. */\n readonly redirectTo?: string;\n /** Replace fixed failure messages (for example app-specific recovery steps). */\n readonly messages?: Partial<Record<OwnerSetupErrorCode, string>>;\n /** Override where the signed-in user comes from. Defaults to `locals.user`. */\n readonly resolveUser?: (event: OwnerSetupEvent) => unknown;\n /**\n * Set false to keep the `smrt app` onboarding hand-off files after a claim.\n * By default the runtime removes `onboarding.json` and\n * `onboarding-launch.html` from the private state root once the claim has\n * committed, so `pnpm app:open` stops offering the spent invitation.\n */\n readonly removeOnboardingHandoff?: boolean;\n /**\n * Best-effort extra cleanup after a successful claim (the hand-off files are\n * already removed by default). Errors are ignored: the owner and session are\n * already authoritative and a stale token now fails closed.\n */\n readonly onOwnerClaimed?: (\n result: LocalOwnerClaimResult,\n event: OwnerSetupActionEvent,\n ) => void | Promise<void>;\n}\n\nexport interface OwnerSetupPage {\n readonly load: (event: OwnerSetupEvent) => Promise<OwnerSetupPageData>;\n readonly actions: {\n readonly default: (\n event: OwnerSetupActionEvent,\n ) => Promise<ActionFailure<OwnerSetupFailure>>;\n };\n}\n\n/**\n * Mount as `src/routes/setup/+page.server.ts`:\n *\n * ```ts\n * import { createOwnerSetupPage } from '@happyvertical/smrt-app-runtime/sveltekit';\n * import { runtime } from '../../hooks.server';\n *\n * export const { load, actions } = createOwnerSetupPage(runtime);\n * ```\n *\n * The form posts to the `default` action with fields `token` (hidden),\n * `name`, `email`, and optional `password` and `tenantName`. Set\n * `requirePassword: true` for password-based applications. Success sets the session cookie\n * and redirects 303; failures return `fail(status, { code, message })`.\n */\nexport function createOwnerSetupPage(\n runtime: Pick<\n SmrtSvelteKitRuntime,\n 'resolvedRuntime' | 'localRuntime' | 'sessionCookie'\n > &\n Partial<Pick<SmrtSvelteKitRuntime, 'applicationStateRoot'>>,\n options: OwnerSetupPageOptions = {},\n): OwnerSetupPage {\n const redirectTo = options.redirectTo ?? '/';\n const messages = { ...DEFAULT_OWNER_SETUP_MESSAGES, ...options.messages };\n const failure = (status: number, code: OwnerSetupErrorCode) =>\n fail(status, { code, message: messages[code] } as OwnerSetupFailure);\n const resolveUser =\n options.resolveUser ??\n ((event: OwnerSetupEvent) => (event.locals as { user?: unknown }).user);\n\n const load = async (event: OwnerSetupEvent): Promise<OwnerSetupPageData> => {\n if (resolveUser(event)) redirect(303, redirectTo);\n const resolved = await runtime.resolvedRuntime();\n if (resolved.profile !== 'local' || !isLoopbackRequest(event)) {\n return { available: false, token: '', link: 'unavailable' };\n }\n const local = await runtime.localRuntime();\n const diagnostics = await local.diagnostics();\n const status = diagnostics.bootstrap.status;\n if (status === 'claimed') {\n return { available: false, token: '', link: 'unavailable' };\n }\n const token = event.url.searchParams.get(OWNER_SETUP_FIELDS.token) || '';\n if (status === 'expired')\n return { available: true, token: '', link: 'expired' };\n if (!token) return { available: true, token: '', link: 'missing' };\n return { available: true, token, link: 'ready' };\n };\n\n const claim = async (\n event: OwnerSetupActionEvent,\n ): Promise<ActionFailure<OwnerSetupFailure>> => {\n const resolved = await runtime.resolvedRuntime();\n if (resolved.profile !== 'local') return failure(404, 'setup_disabled');\n if (!isLoopbackRequest(event)) return failure(403, 'setup_unavailable');\n\n let form: FormData;\n try {\n form = await event.request.formData();\n } catch {\n return failure(400, 'setup_invalid_input');\n }\n const field = (name: string) => {\n const value = form.get(name);\n return typeof value === 'string' ? value : '';\n };\n const token = field(OWNER_SETUP_FIELDS.token);\n const name = field(OWNER_SETUP_FIELDS.name);\n const email = field(OWNER_SETUP_FIELDS.email);\n const password = field(OWNER_SETUP_FIELDS.password);\n const tenantName = field(OWNER_SETUP_FIELDS.tenantName).trim();\n if (\n !token ||\n !name.trim() ||\n !email.includes('@') ||\n (options.requirePassword && !password)\n ) {\n return failure(400, 'setup_invalid_input');\n }\n\n const local = await runtime.localRuntime();\n let result: LocalOwnerClaimResult;\n try {\n result = await local.claimOwner({\n token,\n name,\n email,\n password,\n ...(tenantName ? { tenantName } : {}),\n userAgent: event.request.headers.get('user-agent') || undefined,\n ipAddress: event.getClientAddress(),\n });\n } catch (error) {\n if (\n error instanceof LocalRuntimeError &&\n (error.code === 'owner_tenant_conflict' ||\n error.code === 'owner_identity_conflict')\n ) {\n return failure(409, 'setup_conflict');\n }\n return failure(400, 'setup_invalid');\n }\n\n // claimOwner resolved, so the claim transaction has committed. Clean up\n // before cookie serialization, which can throw on a malformed config.\n if (\n options.removeOnboardingHandoff !== false &&\n runtime.applicationStateRoot\n ) {\n try {\n removeOnboardingHandoff(runtime.applicationStateRoot());\n } catch {\n // Best effort: the spent token already fails closed.\n }\n }\n const cookie = runtime.sessionCookie;\n event.cookies.set(cookie.name, result.sessionId, {\n path: cookie.path,\n ...(cookie.domain ? { domain: cookie.domain } : {}),\n httpOnly: true,\n secure: cookie.secure ?? event.url.protocol === 'https:',\n sameSite: cookie.sameSite,\n maxAge: cookie.maxAgeSeconds,\n });\n try {\n await options.onOwnerClaimed?.(result, event);\n } catch {\n // Best effort only; see OwnerSetupPageOptions.onOwnerClaimed.\n }\n redirect(303, redirectTo);\n };\n\n return Object.freeze({\n load,\n actions: Object.freeze({ default: claim }),\n });\n}\n\n/**\n * True only when both the peer address and the addressed host are loopback.\n * The host check rejects tunnels and DNS-rebinding hosts that forward to a\n * loopback listener; a throwing `getClientAddress` is treated as remote.\n */\nexport function isLoopbackRequest(event: {\n readonly url: URL;\n getClientAddress(): string;\n}): boolean {\n let address: string;\n try {\n address = event.getClientAddress();\n } catch {\n return false;\n }\n return isLoopbackAddress(address) && isLoopbackHostname(event.url.hostname);\n}\n\n/** Loopback IP literal: `127.0.0.0/8`, `::1`, or IPv4-mapped `127/8`. */\nexport function isLoopbackAddress(value: string | null | undefined): boolean {\n if (typeof value !== 'string') return false;\n let host = value\n .trim()\n .toLowerCase()\n .replace(/^\\[|\\]$/g, '');\n if (host === '::1' || host === '0:0:0:0:0:0:0:1') return true;\n if (host.startsWith('::ffff:')) host = host.slice('::ffff:'.length);\n const octets = host.split('.');\n return (\n octets.length === 4 &&\n octets.every((part) => /^\\d{1,3}$/.test(part) && Number(part) <= 255) &&\n Number(octets[0]) === 127\n );\n}\n\n/** Loopback host name as SvelteKit reports it in `url.hostname`. */\nexport function isLoopbackHostname(hostname: string): boolean {\n const host = hostname.trim().toLowerCase().replace(/\\.$/, '');\n return host === 'localhost' || isLoopbackAddress(host);\n}\n","/**\n * Sign-out route handler: destroys the current session and clears its cookie\n * with the same cookie attributes the owner-setup action used to set it.\n */\n\nimport { destroySessionCookie } from '@happyvertical/smrt-users/sveltekit';\nimport { type RequestHandler, redirect } from '@sveltejs/kit';\nimport type { SmrtSvelteKitRuntime } from './runtime.js';\n\n/** True when the browser says the request came from this origin. */\nfunction isSameOriginRequest(request: Request, url: URL): boolean {\n const site = request.headers.get('sec-fetch-site');\n if (site !== null) return site === 'same-origin';\n const origin = request.headers.get('origin');\n return origin !== null && origin === url.origin;\n}\n\n/**\n * Mount as `src/routes/sign-out/+server.ts`:\n * `export const POST = createSignOutHandler(runtime);`\n *\n * `POST` only (other methods answer 405) and same-origin only (403 otherwise).\n * The session row is destroyed best-effort and the cookie is cleared even when\n * the row is already gone. Answers 204, or a 303 to `/` when the request\n * accepts HTML so a no-JS form post lands on the home page.\n */\nexport function createSignOutHandler(\n runtime: Pick<SmrtSvelteKitRuntime, 'sessionCookie' | 'classOptions'>,\n): RequestHandler {\n return async (event) => {\n if (event.request.method !== 'POST') {\n return new Response('Method not allowed', {\n status: 405,\n headers: { allow: 'POST' },\n });\n }\n if (!isSameOriginRequest(event.request, event.url)) {\n return new Response('Forbidden', { status: 403 });\n }\n const cookie = runtime.sessionCookie;\n await destroySessionCookie(\n event as unknown as Parameters<typeof destroySessionCookie>[0],\n {\n ...runtime.classOptions('Session'),\n cookieName: cookie.name,\n cookiePath: cookie.path,\n ...(cookie.domain ? { cookieDomain: cookie.domain } : {}),\n },\n );\n // `delete` omits the Secure flag the setup action used; re-issue the\n // expiry with the same attributes so browsers match and drop the cookie.\n event.cookies.set(cookie.name, '', {\n path: cookie.path,\n ...(cookie.domain ? { domain: cookie.domain } : {}),\n httpOnly: true,\n secure: cookie.secure ?? event.url.protocol === 'https:',\n sameSite: cookie.sameSite,\n maxAge: 0,\n });\n if (event.request.headers.get('accept')?.includes('text/html')) {\n redirect(303, '/');\n }\n return new Response(null, { status: 204 });\n };\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@happyvertical/smrt-app-runtime",
3
- "version": "0.60.9",
3
+ "version": "0.60.10",
4
4
  "description": "Validated local, self-hosted, and cloud runtime composition for s-m-r-t applications",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -33,16 +33,16 @@
33
33
  }
34
34
  },
35
35
  "dependencies": {
36
- "@happyvertical/smrt-config": "0.60.9",
37
- "@happyvertical/smrt-core": "0.60.9",
38
- "@happyvertical/smrt-jobs": "0.60.9",
39
- "@happyvertical/smrt-profiles": "0.60.9",
40
- "@happyvertical/smrt-tenancy": "0.60.9",
41
- "@happyvertical/smrt-users": "0.60.9",
42
- "@happyvertical/sql": "^0.111.3"
36
+ "@happyvertical/smrt-config": "0.60.10",
37
+ "@happyvertical/smrt-core": "0.60.10",
38
+ "@happyvertical/smrt-jobs": "0.60.10",
39
+ "@happyvertical/smrt-profiles": "0.60.10",
40
+ "@happyvertical/smrt-tenancy": "0.60.10",
41
+ "@happyvertical/smrt-users": "0.60.10",
42
+ "@happyvertical/sql": "^0.111.5"
43
43
  },
44
44
  "devDependencies": {
45
- "@happyvertical/smrt-vitest": "0.60.9",
45
+ "@happyvertical/smrt-vitest": "0.60.10",
46
46
  "@sveltejs/kit": "2.70.3",
47
47
  "@types/node": "24.13.6",
48
48
  "tsx": "^4.23.13",