@happyvertical/smrt-app-runtime 0.53.3 → 0.53.5
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/AGENTS.md +83 -0
- package/README.md +111 -0
- package/dist/application-identity.d.ts +43 -0
- package/dist/application-identity.d.ts.map +1 -0
- package/dist/chunks/src-D7cM0zHW.js +2552 -0
- package/dist/chunks/src-D7cM0zHW.js.map +1 -0
- package/dist/deployed-runtime.d.ts +11 -0
- package/dist/deployed-runtime.d.ts.map +1 -1
- package/dist/direct-membership.d.ts +39 -0
- package/dist/direct-membership.d.ts.map +1 -0
- package/dist/error-code.d.ts +3 -0
- package/dist/error-code.d.ts.map +1 -0
- package/dist/index.d.ts +34 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1831
- package/dist/local-mcp-tokens.d.ts +123 -0
- package/dist/local-mcp-tokens.d.ts.map +1 -0
- package/dist/manifest.json +1 -1
- package/dist/operation-lock.d.ts +28 -0
- package/dist/operation-lock.d.ts.map +1 -0
- package/dist/plain-data.d.ts +27 -0
- package/dist/plain-data.d.ts.map +1 -0
- package/dist/provider-readiness.d.ts +48 -0
- package/dist/provider-readiness.d.ts.map +1 -0
- package/dist/smrt-knowledge.json +9 -6
- package/dist/stale-reclaim.d.ts +33 -0
- package/dist/stale-reclaim.d.ts.map +1 -0
- package/dist/state-root.d.ts +53 -0
- package/dist/state-root.d.ts.map +1 -0
- package/dist/sveltekit/handlers.d.ts +83 -0
- package/dist/sveltekit/handlers.d.ts.map +1 -0
- package/dist/sveltekit/index.d.ts +20 -0
- package/dist/sveltekit/index.d.ts.map +1 -0
- package/dist/sveltekit/owner-setup.d.ts +109 -0
- package/dist/sveltekit/owner-setup.d.ts.map +1 -0
- package/dist/sveltekit/runtime.d.ts +363 -0
- package/dist/sveltekit/runtime.d.ts.map +1 -0
- package/dist/sveltekit/tenancy.d.ts +59 -0
- package/dist/sveltekit/tenancy.d.ts.map +1 -0
- package/dist/sveltekit.d.ts +2 -0
- package/dist/sveltekit.d.ts.map +1 -0
- package/dist/sveltekit.js +807 -0
- package/dist/sveltekit.js.map +1 -0
- package/dist/writer-lease.d.ts +36 -0
- package/dist/writer-lease.d.ts.map +1 -0
- package/package.json +23 -9
- package/dist/index.js.map +0 -1
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server half of the local owner-setup page (`src/routes/setup/+page.server.ts`).
|
|
3
|
+
*
|
|
4
|
+
* Owner bootstrap is local-profile only, loopback-only, and single-use. The
|
|
5
|
+
* runtime stores only an HMAC of the short-lived token; this module never
|
|
6
|
+
* stores, logs, or returns claim errors, and it re-checks loopback custody on
|
|
7
|
+
* every request instead of trusting the bind host alone.
|
|
8
|
+
*/
|
|
9
|
+
import type { Cookies } from '@sveltejs/kit';
|
|
10
|
+
import { type ActionFailure } from '@sveltejs/kit';
|
|
11
|
+
import type { LocalOwnerClaimResult } from '../index.js';
|
|
12
|
+
import type { SmrtSvelteKitRuntime } from './runtime.js';
|
|
13
|
+
/** Data returned by the setup page `load`. */
|
|
14
|
+
export interface OwnerSetupPageData {
|
|
15
|
+
/** False when setup is claimed, disabled (deployed), or not loopback. */
|
|
16
|
+
readonly available: boolean;
|
|
17
|
+
/** One-time token from `?token=` (empty unless available). */
|
|
18
|
+
readonly token: string;
|
|
19
|
+
}
|
|
20
|
+
/** Stable failure codes returned by the setup action. */
|
|
21
|
+
export type OwnerSetupErrorCode =
|
|
22
|
+
/** Not the local profile (HTTP 404). */
|
|
23
|
+
'setup_disabled'
|
|
24
|
+
/** Request is not from a loopback client on a loopback host (HTTP 403). */
|
|
25
|
+
| 'setup_unavailable'
|
|
26
|
+
/** Missing token, blank name, or email without `@` (HTTP 400). */
|
|
27
|
+
| 'setup_invalid_input'
|
|
28
|
+
/** Token wrong, expired, or already used; owner already claimed (HTTP 400). */
|
|
29
|
+
| 'setup_invalid';
|
|
30
|
+
/** `form` data returned with `fail(status, …)`. */
|
|
31
|
+
export interface OwnerSetupFailure {
|
|
32
|
+
readonly code: OwnerSetupErrorCode;
|
|
33
|
+
/** Fixed, secret-free message; never claim error text. */
|
|
34
|
+
readonly message: string;
|
|
35
|
+
}
|
|
36
|
+
/** Form field names posted to the setup action. */
|
|
37
|
+
export declare const OWNER_SETUP_FIELDS: Readonly<{
|
|
38
|
+
readonly token: "token";
|
|
39
|
+
readonly name: "name";
|
|
40
|
+
readonly email: "email";
|
|
41
|
+
readonly tenantName: "tenantName";
|
|
42
|
+
}>;
|
|
43
|
+
export declare const DEFAULT_OWNER_SETUP_MESSAGES: Readonly<Record<OwnerSetupErrorCode, string>>;
|
|
44
|
+
/** The request fields the setup page reads. */
|
|
45
|
+
export interface OwnerSetupEvent {
|
|
46
|
+
readonly url: URL;
|
|
47
|
+
readonly locals: unknown;
|
|
48
|
+
getClientAddress(): string;
|
|
49
|
+
}
|
|
50
|
+
export interface OwnerSetupActionEvent extends OwnerSetupEvent {
|
|
51
|
+
readonly request: Request;
|
|
52
|
+
readonly cookies: Pick<Cookies, 'set'>;
|
|
53
|
+
}
|
|
54
|
+
export interface OwnerSetupPageOptions {
|
|
55
|
+
/** Where a signed-in visitor or a successful claim is sent. Default `/`. */
|
|
56
|
+
readonly redirectTo?: string;
|
|
57
|
+
/** Replace fixed failure messages (for example app-specific recovery steps). */
|
|
58
|
+
readonly messages?: Partial<Record<OwnerSetupErrorCode, string>>;
|
|
59
|
+
/** Override where the signed-in user comes from. Defaults to `locals.user`. */
|
|
60
|
+
readonly resolveUser?: (event: OwnerSetupEvent) => unknown;
|
|
61
|
+
/**
|
|
62
|
+
* Set false to keep the `smrt app` onboarding hand-off files after a claim.
|
|
63
|
+
* By default the runtime removes `onboarding.json` and
|
|
64
|
+
* `onboarding-launch.html` from the private state root once the claim has
|
|
65
|
+
* committed, so `pnpm app:open` stops offering the spent invitation.
|
|
66
|
+
*/
|
|
67
|
+
readonly removeOnboardingHandoff?: boolean;
|
|
68
|
+
/**
|
|
69
|
+
* Best-effort extra cleanup after a successful claim (the hand-off files are
|
|
70
|
+
* already removed by default). Errors are ignored: the owner and session are
|
|
71
|
+
* already authoritative and a stale token now fails closed.
|
|
72
|
+
*/
|
|
73
|
+
readonly onOwnerClaimed?: (result: LocalOwnerClaimResult, event: OwnerSetupActionEvent) => void | Promise<void>;
|
|
74
|
+
}
|
|
75
|
+
export interface OwnerSetupPage {
|
|
76
|
+
readonly load: (event: OwnerSetupEvent) => Promise<OwnerSetupPageData>;
|
|
77
|
+
readonly actions: {
|
|
78
|
+
readonly default: (event: OwnerSetupActionEvent) => Promise<ActionFailure<OwnerSetupFailure>>;
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Mount as `src/routes/setup/+page.server.ts`:
|
|
83
|
+
*
|
|
84
|
+
* ```ts
|
|
85
|
+
* import { createOwnerSetupPage } from '@happyvertical/smrt-app-runtime/sveltekit';
|
|
86
|
+
* import { runtime } from '../../hooks.server';
|
|
87
|
+
*
|
|
88
|
+
* export const { load, actions } = createOwnerSetupPage(runtime);
|
|
89
|
+
* ```
|
|
90
|
+
*
|
|
91
|
+
* The form posts to the `default` action with fields `token` (hidden),
|
|
92
|
+
* `name`, `email`, and optional `tenantName`. Success sets the session cookie
|
|
93
|
+
* and redirects 303; failures return `fail(status, { code, message })`.
|
|
94
|
+
*/
|
|
95
|
+
export declare function createOwnerSetupPage(runtime: Pick<SmrtSvelteKitRuntime, 'resolvedRuntime' | 'localRuntime' | 'sessionCookie'> & Partial<Pick<SmrtSvelteKitRuntime, 'applicationStateRoot'>>, options?: OwnerSetupPageOptions): OwnerSetupPage;
|
|
96
|
+
/**
|
|
97
|
+
* True only when both the peer address and the addressed host are loopback.
|
|
98
|
+
* The host check rejects tunnels and DNS-rebinding hosts that forward to a
|
|
99
|
+
* loopback listener; a throwing `getClientAddress` is treated as remote.
|
|
100
|
+
*/
|
|
101
|
+
export declare function isLoopbackRequest(event: {
|
|
102
|
+
readonly url: URL;
|
|
103
|
+
getClientAddress(): string;
|
|
104
|
+
}): boolean;
|
|
105
|
+
/** Loopback IP literal: `127.0.0.0/8`, `::1`, or IPv4-mapped `127/8`. */
|
|
106
|
+
export declare function isLoopbackAddress(value: string | null | undefined): boolean;
|
|
107
|
+
/** Loopback host name as SvelteKit reports it in `url.hostname`. */
|
|
108
|
+
export declare function isLoopbackHostname(hostname: string): boolean;
|
|
109
|
+
//# sourceMappingURL=owner-setup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"owner-setup.d.ts","sourceRoot":"","sources":["../../src/sveltekit/owner-setup.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SvelteKit server composition for the validated runtime profiles.
|
|
3
|
+
*
|
|
4
|
+
* Request foundation, in order:
|
|
5
|
+
*
|
|
6
|
+
* 0. Wait for the fail-closed runtime startup gate (`init`).
|
|
7
|
+
* 1. Resolve a URL tenant candidate into `locals.selectedTenant*`. This is
|
|
8
|
+
* selection only and never enters AsyncLocalStorage tenant context.
|
|
9
|
+
* 2. Load the signed session. Its tenant is accepted only for a verified
|
|
10
|
+
* active direct or legitimately inherited membership
|
|
11
|
+
* ({@link isSessionTenantAuthorized}, the deployed runtime's rule);
|
|
12
|
+
* otherwise the request is unauthenticated. An accepted session enters the
|
|
13
|
+
* tenant context and permission set for downstream code, inside the
|
|
14
|
+
* request RLS transaction when the profile selects `database-rls`.
|
|
15
|
+
* 3. Publish the authorized context on `locals.tenantContext` only when it
|
|
16
|
+
* matches the verified session tenant.
|
|
17
|
+
*
|
|
18
|
+
* This ordering prevents a spoofed header or hostname from becoming query
|
|
19
|
+
* authority. Membership-gated tenant switching belongs in an explicit action
|
|
20
|
+
* using `switchSessionTenant()` from `@happyvertical/smrt-users/sveltekit`.
|
|
21
|
+
*/
|
|
22
|
+
import { type ResolvedApplicationRuntime } from '@happyvertical/smrt-config';
|
|
23
|
+
import { type SmrtClassOptions, type SmrtCollection, type SmrtObject } from '@happyvertical/smrt-core';
|
|
24
|
+
import { type MinimalTenantContext } from '@happyvertical/smrt-tenancy';
|
|
25
|
+
import type { SessionHandlerOptions, SessionLocals } from '@happyvertical/smrt-users/sveltekit';
|
|
26
|
+
import { type DatabaseInterface } from '@happyvertical/sql';
|
|
27
|
+
import type { Handle, ServerInit } from '@sveltejs/kit';
|
|
28
|
+
import { type DeployedApplicationRuntime, initializeDeployedApplicationRuntime } from '../deployed-runtime.js';
|
|
29
|
+
import { type TenantBindingMode } from '../direct-membership.js';
|
|
30
|
+
import { initializeLocalApplicationRuntime, type LocalApplicationRuntime, type LocalMcpTokenPrincipal, type LocalOwnerBootstrapInvitation } from '../index.js';
|
|
31
|
+
import { type RuntimeDiagnostics } from '../runtime-diagnostics.js';
|
|
32
|
+
import { type WriterLease } from '../writer-lease.js';
|
|
33
|
+
import { type TenantSelector } from './tenancy.js';
|
|
34
|
+
/** `App.Locals` fields populated by the SMRT runtime `handle`. */
|
|
35
|
+
export interface SmrtRuntimeLocals extends SessionLocals {
|
|
36
|
+
/**
|
|
37
|
+
* URL-selected tenant candidate. Never use this as authorization; the
|
|
38
|
+
* session-authorized tenant remains `tenantId` from {@link SessionLocals}.
|
|
39
|
+
*/
|
|
40
|
+
selectedTenantId: string | null;
|
|
41
|
+
selectedTenantSlug: string | null;
|
|
42
|
+
/** Full context for the authorized session tenant, when present. */
|
|
43
|
+
tenantContext?: MinimalTenantContext;
|
|
44
|
+
}
|
|
45
|
+
/** Provider component whose readiness a deployed web process must prove. */
|
|
46
|
+
export type ProviderReadinessComponent = 'authentication' | 'assets' | 'secrets';
|
|
47
|
+
/**
|
|
48
|
+
* Build a provider-owned readiness probe. The probe must check the real
|
|
49
|
+
* backing service and must never return or log credentials.
|
|
50
|
+
*/
|
|
51
|
+
export type ProviderReadinessFactory = (component: ProviderReadinessComponent, context: {
|
|
52
|
+
readonly profile: string;
|
|
53
|
+
readonly provider: string;
|
|
54
|
+
}) => () => Promise<void>;
|
|
55
|
+
/** Context handed to an application-owned writer lease. */
|
|
56
|
+
export interface WriterLeaseContext {
|
|
57
|
+
readonly appId: string;
|
|
58
|
+
readonly dataDirectory: string | undefined;
|
|
59
|
+
readonly sourceRoot: string;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Held for the life of the local web process; released on failed startup.
|
|
63
|
+
* The root entry's `acquireWriterLease()` returns one.
|
|
64
|
+
*/
|
|
65
|
+
export type { WriterLease } from '../writer-lease.js';
|
|
66
|
+
/** Inputs to the public diagnostics projection that only the app can supply. */
|
|
67
|
+
export interface ApplicationRuntimeDiagnosticsOptions {
|
|
68
|
+
readonly toolNames: readonly string[];
|
|
69
|
+
readonly observedAt: Date;
|
|
70
|
+
/** Application-owned schema verification seam; runtime liveness is not proof. */
|
|
71
|
+
readonly schemaStatus?: 'not-ready' | 'ready' | 'unknown';
|
|
72
|
+
/** Application-owned migration tracker seam; database liveness is not proof. */
|
|
73
|
+
readonly migrationStatus?: 'current' | 'failed' | 'pending' | 'unknown';
|
|
74
|
+
/** Bounded worker seam supplied by the deployment's lease/heartbeat adapter. */
|
|
75
|
+
readonly workerHeartbeatAt?: Date | string | null;
|
|
76
|
+
/** Stable code/timestamp pairs only; raw errors never cross this seam. */
|
|
77
|
+
readonly recentErrors?: readonly {
|
|
78
|
+
readonly code?: unknown;
|
|
79
|
+
readonly at?: unknown;
|
|
80
|
+
}[];
|
|
81
|
+
}
|
|
82
|
+
/** Liveness body served by the mounted health route. */
|
|
83
|
+
export interface RuntimeHealthBody {
|
|
84
|
+
readonly schemaVersion: 1;
|
|
85
|
+
readonly status: 'ready';
|
|
86
|
+
readonly profile: ResolvedApplicationRuntime['profile'];
|
|
87
|
+
/** Local profile only: canonical application ID. */
|
|
88
|
+
readonly application?: string;
|
|
89
|
+
/** Local profile only: managed process instance (`SMRT_PROCESS_INSTANCE`). */
|
|
90
|
+
readonly instance?: string | null;
|
|
91
|
+
/** Local profile only: {@link runtimeConfigurationFingerprint}. */
|
|
92
|
+
readonly configuration?: string;
|
|
93
|
+
}
|
|
94
|
+
/** Session-handler options the application may tune. */
|
|
95
|
+
export type SmrtRuntimeSessionOptions = Omit<SessionHandlerOptions, 'enterTenantContext'>;
|
|
96
|
+
/** App-specific options for {@link createSmrtSvelteKitRuntime}. */
|
|
97
|
+
export interface SmrtSvelteKitRuntimeOptions {
|
|
98
|
+
/**
|
|
99
|
+
* Explicit application ID. Defaults to `SMRT_APP_ID` (strictly validated)
|
|
100
|
+
* or the encoded `package.json` name under `sourceRoot`.
|
|
101
|
+
*/
|
|
102
|
+
readonly appId?: string;
|
|
103
|
+
/** Application source checkout. Defaults to `process.cwd()`. */
|
|
104
|
+
readonly sourceRoot?: string;
|
|
105
|
+
/** Local data root. Defaults to `SMRT_DATA_DIR`, then the OS data directory. */
|
|
106
|
+
readonly dataDirectory?: string;
|
|
107
|
+
/** Environment to read. Defaults to `process.env`. */
|
|
108
|
+
readonly env?: NodeJS.ProcessEnv;
|
|
109
|
+
/**
|
|
110
|
+
* Resolved runtime profile. Defaults to `smrt.config` `runtime` when
|
|
111
|
+
* present, otherwise the `local` profile; a present value that is not a
|
|
112
|
+
* runtime block (`null`, `false`, `0`, `''`) fails closed.
|
|
113
|
+
*/
|
|
114
|
+
readonly runtime?: ResolvedApplicationRuntime | (() => ResolvedApplicationRuntime | Promise<ResolvedApplicationRuntime>);
|
|
115
|
+
/**
|
|
116
|
+
* Explicit, idempotent application migration hook, run during `init`.
|
|
117
|
+
* The runtime never synthesizes application tables itself.
|
|
118
|
+
*/
|
|
119
|
+
readonly prepareDatabase?: (db: DatabaseInterface) => Promise<void>;
|
|
120
|
+
/**
|
|
121
|
+
* Local HTTP bind host. Defaults to `HOST`, or `127.0.0.1` when
|
|
122
|
+
* `NODE_ENV=development`. Local production startup without one fails.
|
|
123
|
+
*/
|
|
124
|
+
readonly bindHost?: string;
|
|
125
|
+
/** Opt in to persisted local background jobs. Default `SMRT_BACKGROUND_JOBS === 'true'`. */
|
|
126
|
+
readonly backgroundJobs?: boolean;
|
|
127
|
+
/** Opt in to application-defined paid capabilities. Default false. */
|
|
128
|
+
readonly paidCapabilities?: boolean;
|
|
129
|
+
/** Owner-bootstrap token lifetime (1..900 seconds). */
|
|
130
|
+
readonly bootstrapTtlSeconds?: number;
|
|
131
|
+
/** Session lifetime for the owner-bootstrap session cookie. Default 7 days. */
|
|
132
|
+
readonly sessionTtlSeconds?: number;
|
|
133
|
+
/**
|
|
134
|
+
* Local single-writer lease held for the web process, released when local
|
|
135
|
+
* startup fails. Defaults to the state-root writer lease shared with
|
|
136
|
+
* `smrt app` operations ({@link defaultWriterLease}: `writer.lease` under
|
|
137
|
+
* `prepareApplicationStateRoot()`, presenting `SMRT_OPERATION_INSTANCE`).
|
|
138
|
+
* Pass a factory to replace it, or `false` to hold no lease. Deployed
|
|
139
|
+
* profiles never take it.
|
|
140
|
+
*/
|
|
141
|
+
readonly acquireWriterLease?: ((context: WriterLeaseContext) => WriterLease) | false;
|
|
142
|
+
/**
|
|
143
|
+
* Deployed provider readiness probes. Required by `self-hosted` and `cloud`;
|
|
144
|
+
* deployed startup fails closed without them.
|
|
145
|
+
*/
|
|
146
|
+
readonly providerReadiness?: ProviderReadinessFactory;
|
|
147
|
+
/** Replace the default subdomain tenant selector. Selection only. */
|
|
148
|
+
readonly selectTenant?: TenantSelector;
|
|
149
|
+
/** Base domain for the default selector. Defaults to `TENANT_BASE_DOMAIN`. */
|
|
150
|
+
readonly tenantBaseDomain?: string;
|
|
151
|
+
/** Session handler tuning. `enterTenantContext` is always `true`. */
|
|
152
|
+
readonly session?: SmrtRuntimeSessionOptions;
|
|
153
|
+
/** Per-class overrides layered over the runtime database config. */
|
|
154
|
+
readonly classOverrides?: Readonly<Record<string, Partial<SmrtClassOptions>>>;
|
|
155
|
+
/** Call `enableTenancy()` if it is not already enabled. Default true. */
|
|
156
|
+
readonly enableTenancy?: boolean;
|
|
157
|
+
/**
|
|
158
|
+
* Receives an owner-bootstrap invitation that this process's startup newly
|
|
159
|
+
* issued (the plaintext is returned exactly once; only its HMAC is stored).
|
|
160
|
+
* Use it to show a loopback `/setup?token=` URL. Errors are ignored so a
|
|
161
|
+
* failing presenter never blocks startup. Default: not presented.
|
|
162
|
+
*/
|
|
163
|
+
readonly onBootstrapInvitation?: (invitation: LocalOwnerBootstrapInvitation, context: {
|
|
164
|
+
readonly bindHost: string;
|
|
165
|
+
}) => void;
|
|
166
|
+
/** Testable clock for the local runtime. */
|
|
167
|
+
readonly now?: () => Date;
|
|
168
|
+
}
|
|
169
|
+
/** Cookie attributes for a session established outside the session handler. */
|
|
170
|
+
export interface SmrtRuntimeSessionCookie {
|
|
171
|
+
readonly name: string;
|
|
172
|
+
readonly path: string;
|
|
173
|
+
readonly domain?: string;
|
|
174
|
+
readonly sameSite: 'strict' | 'lax' | 'none';
|
|
175
|
+
/** `undefined` means "secure when the request is HTTPS". */
|
|
176
|
+
readonly secure?: boolean;
|
|
177
|
+
readonly maxAgeSeconds: number;
|
|
178
|
+
}
|
|
179
|
+
export type { TenantBindingMode } from '../direct-membership.js';
|
|
180
|
+
/** The composed runtime; `handle` and `init` are bound and destructurable. */
|
|
181
|
+
/** A principal a route authenticated itself, for {@link SmrtSvelteKitRuntime.runAsPrincipal}. */
|
|
182
|
+
export interface SmrtRuntimeBoundPrincipal {
|
|
183
|
+
readonly id: string;
|
|
184
|
+
readonly tenantId?: string | null;
|
|
185
|
+
/** Granted scopes that cap the live permission set (e.g. token scopes). */
|
|
186
|
+
readonly scopes?: readonly string[];
|
|
187
|
+
/**
|
|
188
|
+
* How tenant authority may be established, set by the authenticating
|
|
189
|
+
* adapter (never request input). `direct` (local owner tokens, the default
|
|
190
|
+
* hosted resolver) needs an active direct membership in exactly
|
|
191
|
+
* `tenantId`. `direct-or-inherited` (the default; hosted application-owned
|
|
192
|
+
* mappings) applies the session step's rule: that direct row, or with no
|
|
193
|
+
* direct row, authority inherited from an active inheritable ancestor.
|
|
194
|
+
*/
|
|
195
|
+
readonly tenantBinding?: TenantBindingMode;
|
|
196
|
+
}
|
|
197
|
+
/** A verified hosted access-token identity (see `McpVerifiedIdentity`). */
|
|
198
|
+
export interface SmrtRuntimeMcpIdentity {
|
|
199
|
+
/** Exact issuer the token was verified against. */
|
|
200
|
+
readonly issuer: string;
|
|
201
|
+
/** Verified `sub` claim. */
|
|
202
|
+
readonly subject: string;
|
|
203
|
+
}
|
|
204
|
+
/** The current account and tenant a hosted MCP identity maps to. */
|
|
205
|
+
export interface SmrtRuntimeMcpPrincipalMapping {
|
|
206
|
+
readonly id: string;
|
|
207
|
+
readonly tenantId: string;
|
|
208
|
+
readonly kind: 'human';
|
|
209
|
+
/** The default resolver maps only direct memberships. */
|
|
210
|
+
readonly tenantBinding: 'direct';
|
|
211
|
+
}
|
|
212
|
+
/** `T` with every nested array and object field readonly. */
|
|
213
|
+
export type SmrtRuntimeDeepReadonly<T> = T extends readonly (infer U)[] ? readonly SmrtRuntimeDeepReadonly<U>[] : T extends object ? {
|
|
214
|
+
readonly [K in keyof T]: SmrtRuntimeDeepReadonly<T[K]>;
|
|
215
|
+
} : T;
|
|
216
|
+
/**
|
|
217
|
+
* The frozen principal `runAsPrincipal` hands its callback: a deep, frozen
|
|
218
|
+
* snapshot of the caller's principal taken before any await, with the
|
|
219
|
+
* effective `tenantBinding` and effective (frozen) `scopes`.
|
|
220
|
+
*/
|
|
221
|
+
export type SmrtRuntimeBoundPrincipalSnapshot<P> = SmrtRuntimeDeepReadonly<Omit<P, 'scopes' | 'tenantBinding'>> & {
|
|
222
|
+
readonly scopes: readonly string[];
|
|
223
|
+
readonly tenantBinding: TenantBindingMode;
|
|
224
|
+
};
|
|
225
|
+
export interface SmrtSvelteKitRuntime {
|
|
226
|
+
/** `hooks.server.ts` `handle`. */
|
|
227
|
+
readonly handle: Handle;
|
|
228
|
+
/** `hooks.server.ts` `init`: the fail-closed startup gate. */
|
|
229
|
+
readonly init: ServerInit;
|
|
230
|
+
/** Session cookie attributes shared with owner setup. */
|
|
231
|
+
readonly sessionCookie: SmrtRuntimeSessionCookie;
|
|
232
|
+
/** Resolve the runtime profile (memoized; retried after failure). */
|
|
233
|
+
resolvedRuntime(): Promise<ResolvedApplicationRuntime>;
|
|
234
|
+
/** Await profile-specific startup (same promise as `init`). */
|
|
235
|
+
ready(): Promise<void>;
|
|
236
|
+
/** Canonical application ID. */
|
|
237
|
+
applicationId(): string;
|
|
238
|
+
/**
|
|
239
|
+
* Private state root shared with the `smrt app` operator commands (writer
|
|
240
|
+
* lease, operation lock, onboarding hand-off files). Resolves the path only;
|
|
241
|
+
* it does not create it.
|
|
242
|
+
*/
|
|
243
|
+
applicationStateRoot(): string;
|
|
244
|
+
/** Secret-free configuration fingerprint. Requires a resolved runtime. */
|
|
245
|
+
configurationFingerprint(): string;
|
|
246
|
+
/**
|
|
247
|
+
* Database for SMRT collections. Requires a resolved runtime. Inside a
|
|
248
|
+
* request running in the RLS transaction (`database-rls` isolation, or
|
|
249
|
+
* `session.postgresRls`) this is the transaction-bound request database;
|
|
250
|
+
* otherwise the base configuration. Call it per request and never retain
|
|
251
|
+
* the result (or collections built from it) beyond that request.
|
|
252
|
+
*/
|
|
253
|
+
databaseConfig(): SmrtClassOptions['db'];
|
|
254
|
+
/**
|
|
255
|
+
* Collection options for a class: {@link databaseConfig} plus
|
|
256
|
+
* `classOverrides`. A class whose override sets `db` keeps that database.
|
|
257
|
+
* Same per-request rule as {@link databaseConfig}.
|
|
258
|
+
*/
|
|
259
|
+
classOptions(className: string): SmrtClassOptions;
|
|
260
|
+
/**
|
|
261
|
+
* The registered collection for a class, built from {@link classOptions}
|
|
262
|
+
* evaluated on this call: inside an RLS request it is bound to the request
|
|
263
|
+
* transaction. Generated API routes resolve collections through it. Call it
|
|
264
|
+
* per request and never retain the result beyond that request.
|
|
265
|
+
*/
|
|
266
|
+
getCollection<T extends SmrtObject = SmrtObject>(className: string): Promise<SmrtCollection<T>>;
|
|
267
|
+
/**
|
|
268
|
+
* Run `fn` as a principal the route verified itself (for example a bearer
|
|
269
|
+
* token mapped by an MCP route), replacing the cookie session's permission
|
|
270
|
+
* context for that call. The principal's permissions are resolved live from
|
|
271
|
+
* its membership in `tenantId` and, when `scopes` is given, capped to it;
|
|
272
|
+
* under the RLS transaction rule of {@link databaseConfig} a fresh
|
|
273
|
+
* transaction publishes that user, tenant and permission set, and
|
|
274
|
+
* `databaseConfig()`/`classOptions()` return it inside `fn`. Rejects (before
|
|
275
|
+
* `fn` runs) without a user id, a tenant, or a membership its
|
|
276
|
+
* `tenantBinding` accepts: `direct` needs an active direct membership in
|
|
277
|
+
* exactly that tenant; `direct-or-inherited` (default) also accepts
|
|
278
|
+
* authority inherited from an active inheritable ancestor when no direct
|
|
279
|
+
* row exists. A suspended or pending direct row is always authoritative.
|
|
280
|
+
*
|
|
281
|
+
* `principal` is read once, before any await: `fn` receives a frozen copy
|
|
282
|
+
* of that snapshot (its effective `tenantBinding`, and `scopes` replaced by
|
|
283
|
+
* the effective, frozen permission set: live permissions capped by the
|
|
284
|
+
* given scopes), never the caller's object. Callers
|
|
285
|
+
* that authorize in code (rather than through database policy, as under
|
|
286
|
+
* `application` isolation) must authorize with these effective scopes so a
|
|
287
|
+
* revoked permission takes effect even while a token still carries it.
|
|
288
|
+
*/
|
|
289
|
+
runAsPrincipal<T, P extends SmrtRuntimeBoundPrincipal = SmrtRuntimeBoundPrincipal>(principal: P, fn: (bound: SmrtRuntimeBoundPrincipalSnapshot<P>) => Promise<T>): Promise<T>;
|
|
290
|
+
/**
|
|
291
|
+
* Verify an owner-minted local MCP token (`smrt app token`). Resolves the
|
|
292
|
+
* token's owner principal with its scopes capped to the owner's live
|
|
293
|
+
* permissions, or `null` for anything else: a malformed, unknown, revoked
|
|
294
|
+
* or expired token, an inactive owner or membership, or any non-`local`
|
|
295
|
+
* profile. Pass the runtime as `createHostedMcpResourceAuth({ runtime })`
|
|
296
|
+
* so `/mcp` accepts these tokens in the local profile.
|
|
297
|
+
*/
|
|
298
|
+
verifyLocalMcpToken(token: string): Promise<LocalMcpTokenPrincipal | null>;
|
|
299
|
+
/**
|
|
300
|
+
* Default membership-backed hosted MCP principal mapping: the verified
|
|
301
|
+
* issuer/subject must be linked (`oidc_identities`) to exactly one active
|
|
302
|
+
* user with exactly one active direct tenant membership. Anything else
|
|
303
|
+
* (unlinked, ambiguous, inactive, several tenants, the `local` profile)
|
|
304
|
+
* resolves `null`, which denies the request. Token claims never select the
|
|
305
|
+
* tenant. Applications with multi-tenant users pass their own
|
|
306
|
+
* `resolvePrincipal`, which takes precedence.
|
|
307
|
+
*/
|
|
308
|
+
resolveMcpPrincipal(identity: SmrtRuntimeMcpIdentity): Promise<SmrtRuntimeMcpPrincipalMapping | null>;
|
|
309
|
+
/** The local runtime. Rejects outside the `local` profile. */
|
|
310
|
+
localRuntime(): Promise<LocalApplicationRuntime>;
|
|
311
|
+
/** The deployed runtime. Rejects in the `local` profile. */
|
|
312
|
+
deployedRuntime(): Promise<DeployedApplicationRuntime>;
|
|
313
|
+
/** Liveness body for the health route (awaits startup). */
|
|
314
|
+
health(): Promise<RuntimeHealthBody>;
|
|
315
|
+
/**
|
|
316
|
+
* Read private runtime state and project it onto the public allowlist.
|
|
317
|
+
* Call only after the route has authenticated and authorized its caller.
|
|
318
|
+
*/
|
|
319
|
+
readDiagnostics(options: ApplicationRuntimeDiagnosticsOptions): Promise<RuntimeDiagnostics>;
|
|
320
|
+
}
|
|
321
|
+
/** @internal Test and composition seams; not part of the public entry. */
|
|
322
|
+
export interface SmrtSvelteKitRuntimeSeams {
|
|
323
|
+
readonly initializeLocal?: typeof initializeLocalApplicationRuntime;
|
|
324
|
+
readonly initializeDeployed?: typeof initializeDeployedApplicationRuntime;
|
|
325
|
+
readonly loadRuntime?: () => Promise<ResolvedApplicationRuntime>;
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Compose runtime startup, tenant selection, the signed session, and
|
|
329
|
+
* authorized-tenant locals into a SvelteKit `{ handle, init }` pair.
|
|
330
|
+
*
|
|
331
|
+
* @example
|
|
332
|
+
* ```ts
|
|
333
|
+
* // src/hooks.server.ts
|
|
334
|
+
* import { createSmrtSvelteKitRuntime } from '@happyvertical/smrt-app-runtime/sveltekit';
|
|
335
|
+
*
|
|
336
|
+
* export const runtime = createSmrtSvelteKitRuntime();
|
|
337
|
+
* export const { handle, init } = runtime;
|
|
338
|
+
* ```
|
|
339
|
+
*/
|
|
340
|
+
export declare function createSmrtSvelteKitRuntime(options?: SmrtSvelteKitRuntimeOptions): SmrtSvelteKitRuntime;
|
|
341
|
+
/** @internal */
|
|
342
|
+
export declare function composeSmrtSvelteKitRuntime(options: SmrtSvelteKitRuntimeOptions, seams: SmrtSvelteKitRuntimeSeams): SmrtSvelteKitRuntime;
|
|
343
|
+
/**
|
|
344
|
+
* The default local writer lease: the state-root `writer.lease` shared with
|
|
345
|
+
* `smrt app` operations, presenting the managed operation instance
|
|
346
|
+
* (`SMRT_OPERATION_INSTANCE`) that `smrt app start` passes to its writer.
|
|
347
|
+
*/
|
|
348
|
+
export declare function defaultWriterLease(context: WriterLeaseContext, env?: NodeJS.ProcessEnv): WriterLease;
|
|
349
|
+
/**
|
|
350
|
+
* Step 3: publish the authorized tenant context only when this runtime's
|
|
351
|
+
* session step verified the session tenant and it matches the active
|
|
352
|
+
* AsyncLocalStorage context. Locals populated by any other session layer are
|
|
353
|
+
* never published.
|
|
354
|
+
*/
|
|
355
|
+
export declare const authorizedTenantLocalsHandle: Handle;
|
|
356
|
+
/**
|
|
357
|
+
* Run handles in order. Unlike `sequence()` from `@sveltejs/kit/hooks`, this
|
|
358
|
+
* needs no SvelteKit request store, so the composed handle is usable (and
|
|
359
|
+
* testable) outside the Kit server runtime. The runtime's own handles never
|
|
360
|
+
* pass resolve options; any options a handle passes are forwarded unchanged.
|
|
361
|
+
*/
|
|
362
|
+
export declare function composeHandles(...handles: readonly Handle[]): Handle;
|
|
363
|
+
//# sourceMappingURL=runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/sveltekit/runtime.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tenant *selection* for SvelteKit requests.
|
|
3
|
+
*
|
|
4
|
+
* Selection and authorization are deliberately separate:
|
|
5
|
+
*
|
|
6
|
+
* - a selector maps a trusted URL shape (by default the leading subdomain) to
|
|
7
|
+
* an active tenant record and publishes it as `locals.selectedTenant*`;
|
|
8
|
+
* - the signed session (`createSessionHandler({ enterTenantContext: true })`)
|
|
9
|
+
* authorizes the signed-in user's membership and establishes the request
|
|
10
|
+
* tenant context.
|
|
11
|
+
*
|
|
12
|
+
* A selected tenant is useful for login and membership-gated switch flows, but
|
|
13
|
+
* it never becomes ambient query authority by itself. The default selector
|
|
14
|
+
* ignores client-provided tenant headers.
|
|
15
|
+
*/
|
|
16
|
+
import type { SmrtClassOptions } from '@happyvertical/smrt-core';
|
|
17
|
+
/** The request fields a tenant selector may read. */
|
|
18
|
+
export interface TenantSelectionEvent {
|
|
19
|
+
readonly url: URL;
|
|
20
|
+
readonly request: {
|
|
21
|
+
readonly headers: Headers;
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
/** URL-derived tenant candidate. Never authorization. */
|
|
25
|
+
export interface TenantSelection {
|
|
26
|
+
/** Database ID for an active tenant, or null when none resolves. */
|
|
27
|
+
readonly tenantId: string | null;
|
|
28
|
+
/** URL-derived slug. Informational until membership authorizes a switch. */
|
|
29
|
+
readonly tenantSlug: string | null;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Replaceable selection extension point. Implementations must preserve the
|
|
33
|
+
* rule that selection alone never establishes authorization context.
|
|
34
|
+
*/
|
|
35
|
+
export type TenantSelector = (event: TenantSelectionEvent) => TenantSelection | Promise<TenantSelection>;
|
|
36
|
+
/**
|
|
37
|
+
* Pure URL parser used by the default selector.
|
|
38
|
+
*
|
|
39
|
+
* Set `TENANT_BASE_DOMAIN` (or pass `baseDomain`) in production so
|
|
40
|
+
* multi-label public suffixes are never guessed. Without it, the fallback is
|
|
41
|
+
* intended only for local domains such as `acme.demo.local`.
|
|
42
|
+
*/
|
|
43
|
+
export declare function selectTenantSlug(url: URL, baseDomain?: string | undefined): string | null;
|
|
44
|
+
export interface SubdomainTenantSelectorOptions {
|
|
45
|
+
/** Explicit public base domain. Defaults to `TENANT_BASE_DOMAIN`. */
|
|
46
|
+
readonly baseDomain?: string;
|
|
47
|
+
/** Collection options for the `Tenant` lookup. */
|
|
48
|
+
readonly classOptions: () => SmrtClassOptions;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Default selector: the leading subdomain names an ACTIVE tenant.
|
|
52
|
+
*
|
|
53
|
+
* A missing `tenants` table (a fresh project before its first migration)
|
|
54
|
+
* yields no selection; the runtime never creates that table.
|
|
55
|
+
*/
|
|
56
|
+
export declare function createSubdomainTenantSelector(options: SubdomainTenantSelectorOptions): TenantSelector;
|
|
57
|
+
/** Coerce an application selector's result into the published shape. */
|
|
58
|
+
export declare function normalizeTenantSelection(selection: TenantSelection | null | undefined): TenantSelection;
|
|
59
|
+
//# sourceMappingURL=tenancy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tenancy.d.ts","sourceRoot":"","sources":["../../src/sveltekit/tenancy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAGjE,qDAAqD;AACrD,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;IAClB,QAAQ,CAAC,OAAO,EAAE;QAAE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;CACjD;AAED,yDAAyD;AACzD,MAAM,WAAW,eAAe;IAC9B,oEAAoE;IACpE,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,4EAA4E;IAC5E,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CACpC;AAED;;;GAGG;AACH,MAAM,MAAM,cAAc,GAAG,CAC3B,KAAK,EAAE,oBAAoB,KACxB,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;AAShD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,GAAG,EACR,UAAU,GAAE,MAAM,GAAG,SAA0C,GAC9D,MAAM,GAAG,IAAI,CA4Bf;AAYD,MAAM,WAAW,8BAA8B;IAC7C,qEAAqE;IACrE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,kDAAkD;IAClD,QAAQ,CAAC,YAAY,EAAE,MAAM,gBAAgB,CAAC;CAC/C;AAED;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,8BAA8B,GACtC,cAAc,CAgBhB;AAED,wEAAwE;AACxE,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,eAAe,GAAG,IAAI,GAAG,SAAS,GAC5C,eAAe,CAUjB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sveltekit.d.ts","sourceRoot":"","sources":["../src/sveltekit.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC"}
|